pcm-agents 0.6.96 → 0.6.97
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/{conversation-utils-BTAEg4xl.js → conversation-utils-DEyWLr1X.js} +4 -4
- package/dist/cjs/{conversation-utils-BTAEg4xl.js.map → conversation-utils-DEyWLr1X.js.map} +1 -1
- package/dist/cjs/{index-77favCKO.js → index-C_wovzZM.js} +3 -3
- package/dist/cjs/{index-77favCKO.js.map → index-C_wovzZM.js.map} +1 -1
- package/dist/cjs/index.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 +2 -2
- 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 +3 -3
- package/dist/cjs/oem-zygh-modal_31.cjs.entry.js +9 -5
- package/dist/cjs/oem-zygh-modal_31.cjs.entry.js.map +1 -1
- package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js +2 -2
- package/dist/cjs/{sentry-reporter-Bk4sUyeD.js → sentry-reporter-D-zjvMQZ.js} +3 -3
- package/dist/cjs/{sentry-reporter-Bk4sUyeD.js.map → sentry-reporter-D-zjvMQZ.js.map} +1 -1
- package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.css +18 -2
- package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.js +1 -1
- package/dist/collection/components/pcm-app-chat-modal/pcm-app-chat-modal.js.map +1 -1
- package/dist/collection/i18n/pcm-app-chat-modal.i18n.en.json +1 -0
- package/dist/collection/i18n/pcm-app-chat-modal.i18n.zh.json +1 -0
- 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 +6 -6
- 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 +10 -10
- package/dist/components/oem-zygh-modal.js +6 -6
- package/dist/components/{p-C0H4jZIi.js → p-6bkwAKoN.js} +3 -3
- package/dist/components/{p-C0H4jZIi.js.map → p-6bkwAKoN.js.map} +1 -1
- package/dist/components/{p-DjHvQ3lN.js → p-Bqe8RnBv.js} +3 -3
- package/dist/components/{p-DjHvQ3lN.js.map → p-Bqe8RnBv.js.map} +1 -1
- package/dist/components/{p-BG6_220L.js → p-BuuSFiV6.js} +3 -3
- package/dist/components/{p-BG6_220L.js.map → p-BuuSFiV6.js.map} +1 -1
- package/dist/components/{p-DzsyVC1t.js → p-CF5t0Na2.js} +3 -3
- package/dist/components/{p-DzsyVC1t.js.map → p-CF5t0Na2.js.map} +1 -1
- package/dist/components/{p-CD5KK3wz.js → p-CPVPHk5Q.js} +3 -3
- package/dist/components/{p-CD5KK3wz.js.map → p-CPVPHk5Q.js.map} +1 -1
- package/dist/components/{p-Cwl8lxbK.js → p-C_6dc91o.js} +3 -3
- package/dist/components/{p-Cwl8lxbK.js.map → p-C_6dc91o.js.map} +1 -1
- package/dist/components/{p-D464Cbwq.js → p-CeCXTxye.js} +4 -4
- package/dist/components/{p-D464Cbwq.js.map → p-CeCXTxye.js.map} +1 -1
- package/dist/components/{p-CdOggYcY.js → p-CgSFF1H-.js} +3 -3
- package/dist/components/{p-CdOggYcY.js.map → p-CgSFF1H-.js.map} +1 -1
- package/dist/components/{p-BxadQZxO.js → p-D139Ae-m.js} +3 -3
- package/dist/components/{p-BxadQZxO.js.map → p-D139Ae-m.js.map} +1 -1
- package/dist/components/{p-CAgn6yl5.js → p-DB1Xb_SN.js} +3 -3
- package/dist/components/{p-CAgn6yl5.js.map → p-DB1Xb_SN.js.map} +1 -1
- package/dist/components/{p-BrYBIrKw.js → p-ny7Ww0_g.js} +3 -3
- package/dist/components/{p-BrYBIrKw.js.map → p-ny7Ww0_g.js.map} +1 -1
- package/dist/components/{p-BMU_3YY-.js → p-rOAW6Z1w.js} +11 -7
- package/dist/components/p-rOAW6Z1w.js.map +1 -0
- 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 +2 -2
- package/dist/components/pcm-htws-modal.js +8 -8
- package/dist/components/pcm-hyzj-modal.js +5 -5
- package/dist/components/pcm-jd-modal.js +5 -5
- package/dist/components/pcm-jlpp-modal.js +8 -8
- package/dist/components/pcm-jlsx-modal.js +5 -5
- package/dist/components/pcm-jlzz-modal.js +6 -6
- package/dist/components/pcm-mnct-modal.js +7 -7
- 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 +5 -5
- package/dist/components/pcm-qgqjl-modal.js +9 -9
- package/dist/components/pcm-thousand-resume-wrapper.js +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 +2 -2
- package/dist/components/pcm-zygh-modal.js +7 -7
- package/dist/components/pcm-zygh-v2-modal.js +7 -7
- package/dist/esm/components-position-selector.entry.js +1 -1
- package/dist/esm/{conversation-utils-BIr_PfAh.js → conversation-utils-D45d-WT8.js} +4 -4
- package/dist/esm/{conversation-utils-BIr_PfAh.js.map → conversation-utils-D45d-WT8.js.map} +1 -1
- package/dist/esm/{index-Comif8Mg.js → index-B2sU0ath.js} +3 -3
- package/dist/esm/{index-Comif8Mg.js.map → index-B2sU0ath.js.map} +1 -1
- package/dist/esm/index.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 +2 -2
- 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 +3 -3
- package/dist/esm/oem-zygh-modal_31.entry.js +9 -5
- package/dist/esm/oem-zygh-modal_31.entry.js.map +1 -1
- package/dist/esm/pcm-hr-chat-modal.entry.js +2 -2
- package/dist/esm/{sentry-reporter-nfF0-Uk2.js → sentry-reporter-BWPbyZsF.js} +3 -3
- package/dist/esm/{sentry-reporter-nfF0-Uk2.js.map → sentry-reporter-BWPbyZsF.js.map} +1 -1
- package/dist/pcm-agents/i18n/pcm-app-chat-modal.i18n.en.json +1 -0
- package/dist/pcm-agents/i18n/pcm-app-chat-modal.i18n.zh.json +1 -0
- package/dist/pcm-agents/index.esm.js +1 -1
- package/dist/pcm-agents/{p-cc8d9aec.entry.js → p-245d3dba.entry.js} +2 -2
- package/dist/pcm-agents/{p-25fa617a.entry.js → p-3069b708.entry.js} +2 -2
- package/dist/pcm-agents/{p-fa0907cf.entry.js → p-32b990fa.entry.js} +2 -2
- package/dist/pcm-agents/{p-0aa9f384.entry.js → p-50e9b7c8.entry.js} +2 -2
- package/dist/pcm-agents/{p-d9b6a309.entry.js → p-5af061ed.entry.js} +2 -2
- package/dist/pcm-agents/{p-6c2ad070.entry.js → p-5def8872.entry.js} +2 -2
- package/dist/pcm-agents/{p-53fb22c2.entry.js → p-9e352fde.entry.js} +2 -2
- package/dist/pcm-agents/{p-BEWKdGwe.js → p-BOH1gYZj.js} +2 -2
- package/dist/pcm-agents/{p-BEWKdGwe.js.map → p-BOH1gYZj.js.map} +1 -1
- package/dist/pcm-agents/p-Duxw4aNn.js +2 -0
- package/dist/pcm-agents/{p-DdVhVtJm.js.map → p-Duxw4aNn.js.map} +1 -1
- package/dist/pcm-agents/{p-De3vyGBR.js → p-KC5DRaFJ.js} +2 -2
- package/dist/pcm-agents/{p-De3vyGBR.js.map → p-KC5DRaFJ.js.map} +1 -1
- package/dist/pcm-agents/{p-6da308b6.entry.js → p-b7a2f1fb.entry.js} +2 -2
- package/dist/pcm-agents/{p-6a5bc73b.entry.js → p-c194b3b5.entry.js} +2 -2
- package/dist/pcm-agents/{p-5db93e8b.entry.js → p-efe2d769.entry.js} +3 -3
- package/dist/pcm-agents/p-efe2d769.entry.js.map +1 -0
- package/dist/pcm-agents/{p-e71df1c6.entry.js → p-f511c080.entry.js} +2 -2
- package/dist/pcm-agents/pcm-agents.esm.js +1 -1
- package/package.json +1 -1
- package/dist/components/p-BMU_3YY-.js.map +0 -1
- package/dist/pcm-agents/p-5db93e8b.entry.js.map +0 -1
- package/dist/pcm-agents/p-DdVhVtJm.js +0 -2
- /package/dist/pcm-agents/{p-cc8d9aec.entry.js.map → p-245d3dba.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-25fa617a.entry.js.map → p-3069b708.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-fa0907cf.entry.js.map → p-32b990fa.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-0aa9f384.entry.js.map → p-50e9b7c8.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-d9b6a309.entry.js.map → p-5af061ed.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-6c2ad070.entry.js.map → p-5def8872.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-53fb22c2.entry.js.map → p-9e352fde.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-6da308b6.entry.js.map → p-b7a2f1fb.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-6a5bc73b.entry.js.map → p-c194b3b5.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-e71df1c6.entry.js.map → p-f511c080.entry.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["globalCss","oemZyghModalCss","hostCss","OemZyghModal","modalTitle","token","isOpen","modalClosed","icon","zIndex","isShowHeader","isNeedClose","conversationId","defaultQuery","fullscreen","customInputs","showWorkspaceHistory","uploadSuccess","streamComplete","conversationStart","planningComplete","tokenInvalid","someErrorEvent","sendSmsCodeRequest","filePreviewMode","isUploading","uploadedFileInfo","showChatModal","isSubmitting","selectedPlanType","targetPosition","industryName","jobPosition","timePeriod","phoneNumber","verificationCode","isSendingCode","countdown","isVerifyingCode","tokenInvalidListener","removeErrorListener","pcmUploadRef","countdownTimer","handleTokenChange","newToken","authStore","getToken","setToken","handleIsOpenChange","newValue","this","clearInterval","type","verifyApiKey","componentWillLoad","configStore","setItem","emit","ErrorEventBus","addErrorListener","errorDetail","document","addEventListener","disconnectedCallback","removeEventListener","handleClose","handlePlanTypeChange","handlePhoneNumberChange","event","input","target","value","handleVerificationCodeChange","startCountdown","setInterval","handleSendCode","trim","Message","error","phoneRegex","test","mobile","codeType","handleStartPlanning","async","file_url","info","result","verifySmsCode","success","message","getIsUploading","handlePlanningComplete","detail","getPlanTypeIcon","isSelected","baseUrl","iconMap","render","modalStyle","String","containerClass","overlayClass","isLoading","disableResumeUpload","Boolean","h","class","style","src","alt","onClick","placeholder","onInput","e","ref","el","maxFileSize","multiple","mobileUploadAble","acceptFileSuffixList","uploadParams","tags","defaultFileList","cos_key","file_name","file_size","ext","undefined","disabled","onUploadChange","maxLength","length","href","rel","botId","phone","industry_name","target_position","time_period","interviewMode","onInterviewComplete","pcm1zhanshiMnmsModalCss","ZhanshiMnmsModal","maxRecordingTime","waitingTime","digitalId","openingIndex","enableVirtualHuman","showEndInterviewButton","playbackRate","interviewComplete","recordingError","selectedFile","jobDescription","virtualChatModalRef","setComponentActive","resetState","job_info","ai_interview_type","pcmAppChatModalCss","markdownCss","pcmAtsMnmsModalCss","AtsMnmsModal","interview_type","pcmButtonCss","PcmButton","size","loading","shape","backgroundColor","textColor","borderColor","borderRadius","width","block","borderStyle","classes","customStyle","key","Object","keys","filter","join","pcmCardCss","PcmCard","cardTitle","description","iconUrl","author","authorAvatarUrl","showChatTag","customChatTag","useButtonText","botData","watchBotIdHandler","fetchBotData","response","sendHttpRequest","url","method","data","Error","err","console","title","desc","iconFromBot","logo","authorName","author_name","authorAvatar","author_avatar","hasChatTag","flag","usersCount","use_count","starsCount","follow_count","usageCount","view_count","log","userIconUrl","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","selectedText","actions_cut","createFakeElement","isRTL","documentElement","getAttribute","fakeElement","createElement","fontSize","border","padding","margin","position","yPosition","window","pageYOffset","scrollTop","top","concat","setAttribute","fakeCopyAction","options","container","appendChild","remove","ClipboardActionCopy","arguments","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","NewTarget","Reflect","construct","apply","_possibleConstructorReturn","self","call","_assertThisInitialized","ReferenceError","sham","Proxy","Date","toString","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","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","showInputHistory","mobileInputAble","isHistoryDrawerOpen","historyConversations","isLoadingConversations","historyConversationCursorStack","historyConversationPageIndex","hasMoreHistoryConversations","inputMode","freeInputText","_historyConversationPageSize","loadHistoryConversations","lastId","pageIndex","fetchHistoryConversations","nextCursorStack","hasMore","nextCursor","items","handleInputHistoryClick","handleHistoryConversationPageChange","direction","previousPageIndex","previousCursor","nextPageIndex","handleSelectConversation","handleToggleInput","handleFreeInputChange","textarea","handleStartInterview","onClosed","conversation","timeDisplay","message_count","completed","running","viewBox","fill","stroke","uploadText","onOk","rows","pcmHyzjModalCss","HyzjModal","clearSelectedFile","handleFileChange","files","handleUploadClick","fileInput","uploadFile","uploadFileToBackend","SentryReporter","captureError","component","emitError","alert","hideFileUpload","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","getBotId","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","currentLocale","lang","botIdMap","zh","en","renderTagGroup","option","renderAITagGroups","renderLoadingState","aiAnalyzing","pleaseWait","history","noHistory","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","resume_content","handleJobDescriptionChange","handleStartAnalysis","hideJdInput","hideResumeUpload","hasFileAndJob","pcmJlsxModalCss","pcmJlzzModalCss","pcmMessageCss","PcmMessage","content","duration","visible","timer","componentDidLoad","clearTimeout","show","removeChild","renderIcon","pcmMnctModalCss","MnctModal","questionNumber","canOutputAnalysis","handleQuestionNumberChange","handleAnalysisToggle","checked","uploadResume","enterJobDescription","jobDescriptionLabel","jobDescriptionPlaceholder","resumeUploadLabel","questionNumberLabel","min","max","questionUnit","analysisToggleLabel","toggleOn","toggleOff","startAnalysis","question_number","can_outputAnalysis","pcmMnmsModalCss","MnmsModal","showCopyButton","showFeedbackButtons","pcmMnmsZpModalCss","MnmsZpModal","qrcode","typeNumber","errorCorrectionLevel","PAD0","PAD1","_typeNumber","_errorCorrectionLevel","QRErrorCorrectionLevel","_modules","_moduleCount","_dataCache","_dataList","makeImpl","maskPattern","moduleCount","modules","row","col","setupPositionProbePattern","setupPositionAdjustPattern","setupTimingPattern","setupTypeInfo","setupTypeNumber","createData","mapData","c","getBestMaskPattern","minLostPoint","pattern","lostPoint","QRUtil","getLostPoint","pos","getPatternPosition","bits","getBCHTypeNumber","mod","getBCHTypeInfo","inc","bitIndex","byteIndex","maskFunc","getMaskFunction","dark","createBytes","buffer","rsBlocks","offset","maxDcCount","maxEcCount","dcdata","ecdata","dcCount","dataCount","ecCount","totalCount","getBuffer","rsPoly","getErrorCorrectPolynomial","rawPoly","qrPolynomial","getLength","modPoly","modIndex","getAt","totalCodeCount","index","dataList","QRRSBlock","getRSBlocks","qrBitBuffer","put","getMode","getLengthInBits","write","totalDataCount","putBit","addData","mode","newData","qrNumber","qrAlphaNum","qr8BitByte","qrKanji","isDark","getModuleCount","make","createTableTag","cellSize","qrHtml","createSvgTag","opts","mc","mr","qrSvg","rect","scalable","escapeXml","createDataURL","x","y","createImgTag","img","s","escaped","charAt","_createHalfASCII","r1","r2","blocks","blocksLastLineNoMargin","ascii","substring","createASCII","white","black","line","renderTo2dContext","context","fillStyle","fillRect","stringToBytesFuncs","bytes","charCodeAt","stringToBytes","createStringToBytes","unicodeData","numChars","unicodeMap","bin","base64DecodeInputStream","read","b","count","b0","b1","b2","b3","k","fromCharCode","v","unknownChar","QRMode","MODE_NUMBER","MODE_ALPHA_NUM","MODE_8BIT_BYTE","MODE_KANJI","L","M","Q","H","QRMaskPattern","PATTERN000","PATTERN001","PATTERN010","PATTERN011","PATTERN100","PATTERN101","PATTERN110","PATTERN111","PATTERN_POSITION_TABLE","G15","G18","G15_MASK","getBCHDigit","digit","errorCorrectLength","multiply","QRMath","gexp","sameCount","darkCount","ratio","abs","EXP_TABLE","LOG_TABLE","glog","num","shift","_num","RS_BLOCK_TABLE","qrRSBlock","getRsBlockTable","rsBlock","list","_buffer","_length","bufIndex","bit","_mode","_data","strToNum","chatToNum","getCode","_bytes","code","byteArrayOutputStream","writeByte","writeShort","writeBytes","writeString","toByteArray","base64EncodeOutputStream","_buflen","_base64","writeEncoded","encode","flush","padlen","str","_str","_pos","decode","gifImage","_width","_height","setPixel","pixel","out","lzwMinCodeSize","raster","getLZWRaster","bitOutputStream","_out","_bitLength","_bitBuffer","clearCode","endCode","bitLength","table","lzwTable","add","byteOut","bitOut","dataIndex","contains","indexOf","_map","_size","getPixel","gif","base64","toUTF8Array","utf8","charcode","uploadNumberSDK","number","isWorking","onError","pcmMobileInputBtnCss","MobileUploadBtn","uploadHeaders","QR_CODE_VALID_TIME","mobileUrl","setStartMobileUpload","startMobileUploadLoading","qrcodeStatus","expireTime","setStartMobileUploadWrapper","qrcodeUrl","setMobileUrlWrapper","qr","pollingQueryNumberInfo","res","resData","custom_data","handleStartMobileUpload","that","reqData","cfg","fromUserName","fromUserId","upload","update_id","expireDate","now","getHours","padStart","getMinutes","theMobileUrl","PCM_DOMAIN","cancelLoading","cancelMobileUpload","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","pcmThousandResumeWrapperCss","ThousandResumeWrapper","optimizationType","internalConversationId","activeTab","startChatStream","requestData","response_mode","conversation_id","query","optimization_type","tempConversationId","sendSSERequest","onMessage","message_id","onComplete","handleRetry","handleTabChange","tab","tabItems","label","iframeUrl","frameborder","active","pcmUploadCss","PcmUpload","uploadFailed","uploadChange","selectedFiles","file","state","FileUploadState","Success","some","Uploading","clearSelectedFiles","Failed","from","currentFileCount","remainingSlots","validFiles","invalidFiles","split","pop","toLowerCase","supportedFormats","maxSizeText","formatFileSize","newFileItems","uploadResult","targetIndex","emitUploadChange","uploadBtn","textDecoration","marginLeft","itemIndex","pcmVirtualChatModalCss","pcmZskChatModalCss","pcmZyghModalCss","ZyghModal","hasFileAndType","pcmZyghV2ModalCss","ZyghV2Modal"],"sources":["src/global/global.css?tag=oem-zygh-modal&encapsulation=shadow","src/components/oem-zygh-modal/oem-zygh-modal.css?tag=oem-zygh-modal&encapsulation=shadow","src/global/host.css?tag=oem-zygh-modal&encapsulation=shadow","src/components/oem-zygh-modal/oem-zygh-modal.tsx","src/components/pcm-1zhanshi-mnms-modal/pcm-1zhanshi-mnms-modal.css?tag=pcm-1zhanshi-mnms-modal&encapsulation=shadow","src/global/global.css?tag=pcm-1zhanshi-mnms-modal&encapsulation=shadow","src/global/host.css?tag=pcm-1zhanshi-mnms-modal&encapsulation=shadow","src/components/pcm-1zhanshi-mnms-modal/pcm-1zhanshi-mnms-modal.tsx","src/components/pcm-app-chat-modal/pcm-app-chat-modal.css?tag=pcm-app-chat-modal&encapsulation=shadow","src/global/markdown.css?tag=pcm-app-chat-modal&encapsulation=shadow","src/global/host.css?tag=pcm-app-chat-modal&encapsulation=shadow","src/components/pcm-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/qrcode-generator@2.0.4/node_modules/qrcode-generator/dist/qrcode.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-thousand-resume-wrapper/pcm-thousand-resume-wrapper.css?tag=pcm-thousand-resume-wrapper&encapsulation=shadow","src/global/global.css?tag=pcm-thousand-resume-wrapper&encapsulation=shadow","src/global/host.css?tag=pcm-thousand-resume-wrapper&encapsulation=shadow","src/components/pcm-thousand-resume-wrapper/pcm-thousand-resume-wrapper.tsx","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","src/global/global.css?tag=pcm-zygh-v2-modal&encapsulation=shadow","src/components/pcm-zygh-v2-modal/pcm-zygh-v2-modal.css?tag=pcm-zygh-v2-modal&encapsulation=shadow","src/global/host.css?tag=pcm-zygh-v2-modal&encapsulation=shadow","src/components/pcm-zygh-v2-modal/pcm-zygh-v2-modal.tsx"],"sourcesContent":["/* 模态框基础样式 */\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.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n}\r\n\r\n.plan-type-option {\r\n flex: 1;\r\n border: none;\r\n border-right: 1px solid #d9d9d9;\r\n padding: 7px 8px;\r\n cursor: pointer;\r\n display: flex;\r\n flex-direction: row;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n transition: background-color 0.2s, color 0.2s;\r\n background-color: #fff;\r\n}\r\n\r\n.plan-type-option:last-child {\r\n border-right: none;\r\n}\r\n\r\n.plan-type-option:hover {\r\n background-color: #f0f7ff;\r\n}\r\n\r\n.plan-type-option.selected {\r\n background-color: #1890ff;\r\n}\r\n\r\n.plan-type-option.selected .option-icon,\r\n.plan-type-option.selected .option-label {\r\n color: #fff;\r\n}\r\n\r\n.option-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.option-icon img {\r\n height: 18px;\r\n width: auto;\r\n}\r\n\r\n.option-label {\r\n font-size: 13px;\r\n font-weight: 500;\r\n color: #555;\r\n white-space: nowrap;\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.dynamic-form-section {\r\n margin-top: 20px;\r\n margin-bottom: 20px;\r\n}\r\n\r\n.form-fields {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n}\r\n\r\n.form-field {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.form-field label {\r\n font-weight: 600;\r\n color: #333;\r\n font-size: 14px;\r\n}\r\n\r\n.form-input {\r\n padding: 10px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.form-input:hover {\r\n border-color: #40a9ff;\r\n}\r\n\r\n.form-input:focus {\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);\r\n}\r\n\r\n.form-input::placeholder {\r\n color: #bfbfbf;\r\n}\r\n\r\n.form-hint {\r\n font-size: 12px;\r\n color: #8c8c8c;\r\n line-height: 1.5;\r\n margin-top: -8px;\r\n padding: 8px 12px;\r\n background-color: #f5f5f5;\r\n border-radius: 4px;\r\n border-left: 3px solid #1890ff;\r\n}\r\n\r\n/* 手机号输入框样式 */\r\n.phone-input {\r\n width: calc(100% - 16px);\r\n padding: 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n}\r\n\r\n.phone-input:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 验证码容器样式 */\r\n.verification-code-container {\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n}\r\n\r\n.verification-code-input {\r\n flex: 1;\r\n padding: 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-family: inherit;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n transition: border-color 0.3s;\r\n}\r\n\r\n.verification-code-input:focus {\r\n outline: none;\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n/* 发送验证码按钮样式 */\r\n.send-code-button {\r\n padding: 8px 16px;\r\n background: #0D75FB;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n white-space: nowrap;\r\n min-width: 100px;\r\n}\r\n\r\n.send-code-button:hover:not(:disabled) {\r\n background-color: #40a9ff;\r\n}\r\n\r\n.send-code-button:disabled {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: rgba(0, 0, 0, 0.25);\r\n cursor: not-allowed;\r\n}\r\n",":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, verifySmsCode } 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: 'oem-zygh-modal',\r\n styleUrls: ['../../global/global.css', 'oem-zygh-modal.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class OemZyghModal {\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.type则可以指定规划类型,可传入\"转型建议\"、\"晋升路径\"<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() 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 * 接入方需要监听此事件并调用自己的短信接口发送验证码\r\n * 事件参数: { mobile: string, codeType: number }\r\n */\r\n @Event() sendSmsCodeRequest: EventEmitter<{ mobile: string; codeType: number }>;\r\n\r\n /**\r\n * 附件预览模式\r\n * 'drawer': 在右侧抽屉中预览\r\n * 'window': 在新窗口中打开\r\n */\r\n @Prop() filePreviewMode: 'drawer' | 'window' = 'drawer';\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 @State() targetPosition: string = ''; // 晋升目标岗位\r\n @State() industryName: string = ''; // 感兴趣的行业\r\n @State() jobPosition: string = ''; // 感兴趣的职位\r\n @State() timePeriod: string = ''; // 期望转型时间\r\n\r\n // 手机号和验证码相关状态\r\n @State() phoneNumber: string = '';\r\n @State() verificationCode: string = '';\r\n @State() isSendingCode: boolean = false;\r\n @State() countdown: number = 0;\r\n @State() isVerifyingCode: boolean = false;\r\n\r\n // 使用 @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 private countdownTimer: NodeJS.Timeout | 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 @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.showChatModal = false;\r\n this.isSubmitting = false;\r\n this.uploadedFileInfo = null;\r\n // 重置手机号和验证码相关状态\r\n this.phoneNumber = '';\r\n this.verificationCode = '';\r\n this.isSendingCode = false;\r\n this.isVerifyingCode = false;\r\n this.countdown = 0;\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n } 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直接显示聊天模态框\r\n if (this.conversationId) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n\r\n // 初始化时设置 token,但不验证(验证在 @Watch('isOpen') 中处理)\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n 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 if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private handlePlanTypeChange = (type: CareerPlanType) => {\r\n this.selectedPlanType = type;\r\n // 切换类型时重置表单字段\r\n this.targetPosition = '';\r\n this.industryName = '';\r\n this.jobPosition = '';\r\n this.timePeriod = '';\r\n };\r\n\r\n private handlePhoneNumberChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.phoneNumber = input.value;\r\n };\r\n\r\n private handleVerificationCodeChange = (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n this.verificationCode = input.value;\r\n };\r\n\r\n private startCountdown = () => {\r\n this.countdown = 60;\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n }\r\n this.countdownTimer = setInterval(() => {\r\n this.countdown--;\r\n if (this.countdown <= 0) {\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n }\r\n }, 1000);\r\n };\r\n\r\n private handleSendCode = () => {\r\n if (!this.phoneNumber.trim()) {\r\n Message.error('请输入手机号');\r\n return;\r\n }\r\n\r\n // 验证手机号格式\r\n const phoneRegex = /^1[3-9]\\d{9}$/;\r\n if (!phoneRegex.test(this.phoneNumber.trim())) {\r\n Message.error('请输入正确的手机号');\r\n return;\r\n }\r\n\r\n // 设置发送中状态\r\n this.isSendingCode = true;\r\n\r\n // 触发事件,让接入方去调用自己的短信接口\r\n this.sendSmsCodeRequest.emit({\r\n mobile: this.phoneNumber.trim(),\r\n codeType: 8,\r\n });\r\n\r\n // 开始倒计时并重置发送状态\r\n this.startCountdown();\r\n this.isSendingCode = false;\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 // 如果填写了手机号,则需要验证验证码\r\n if (this.phoneNumber.trim()) {\r\n // 验证手机号格式\r\n const phoneRegex = /^1[3-9]\\d{9}$/;\r\n if (!phoneRegex.test(this.phoneNumber.trim())) {\r\n Message.error('请输入正确的手机号');\r\n return;\r\n }\r\n\r\n // 验证验证码是否填写\r\n if (!this.verificationCode.trim()) {\r\n Message.error('请输入验证码');\r\n return;\r\n }\r\n\r\n // 验证验证码是否正确\r\n this.isVerifyingCode = true;\r\n try {\r\n const result = await verifySmsCode(this.phoneNumber.trim(), this.verificationCode.trim(), 0);\r\n if (!result.success) {\r\n Message.error(result.message || '验证码错误');\r\n this.isVerifyingCode = false;\r\n return;\r\n }\r\n } catch (error) {\r\n Message.error('验证码校验失败');\r\n this.isVerifyingCode = false;\r\n return;\r\n }\r\n this.isVerifyingCode = false;\r\n }\r\n\r\n // 判断文件是否正在上传\r\n if (await this.pcmUploadRef?.getIsUploading?.()) {\r\n Message.info('文件上传中,请稍后');\r\n return;\r\n }\r\n this.isSubmitting = true;\r\n this.showChatModal = true;\r\n this.isSubmitting = false;\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 private getPlanTypeIcon = (type: CareerPlanType) => {\r\n const isSelected = this.selectedPlanType === type;\r\n const baseUrl = 'https://pcm-pub-1351162788.cos.ap-guangzhou.myqcloud.com/sdk/image/';\r\n const iconMap = {\r\n '初入职场': 'i_entry_level',\r\n '晋升路径': 'i_promotion',\r\n '转型建议': 'i_transition',\r\n };\r\n return `${baseUrl}${iconMap[type]}${isSelected ? '_actived' : ''}.png`;\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 // 判断是否禁用简历上传区域(有预设file_url时禁用)\r\n const disableResumeUpload = 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时显示 */}\r\n {!this.showChatModal && !this.conversationId && (\r\n <div class=\"input-container\">\r\n {/* 规划类型选择 */}\r\n <div class=\"plan-type-section\">\r\n <label>选择建议类型</label>\r\n <div class=\"plan-type-options\">\r\n <div class={`plan-type-option ${this.selectedPlanType === '初入职场' ? 'selected' : ''}`} onClick={() => this.handlePlanTypeChange('初入职场')}>\r\n <div class=\"option-icon\">\r\n <img src={this.getPlanTypeIcon('初入职场')} alt=\"初入职场\" />\r\n </div>\r\n <div class=\"option-label\">初入职场</div>\r\n </div>\r\n <div class={`plan-type-option ${this.selectedPlanType === '晋升路径' ? 'selected' : ''}`} onClick={() => this.handlePlanTypeChange('晋升路径')}>\r\n <div class=\"option-icon\">\r\n <img src={this.getPlanTypeIcon('晋升路径')} alt=\"晋升路径\" />\r\n </div>\r\n <div class=\"option-label\">晋升路径</div>\r\n </div>\r\n <div class={`plan-type-option ${this.selectedPlanType === '转型建议' ? 'selected' : ''}`} onClick={() => this.handlePlanTypeChange('转型建议')}>\r\n <div class=\"option-icon\">\r\n <img src={this.getPlanTypeIcon('转型建议')} alt=\"转型建议\" />\r\n </div>\r\n <div class=\"option-label\">转型建议</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* 动态表单字段 */}\r\n <div class=\"dynamic-form-section\">\r\n {this.selectedPlanType === '初入职场' && (\r\n <div class=\"form-fields\">\r\n <div class=\"form-field\">\r\n <label>感兴趣的行业</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的行业\"\r\n value={this.industryName}\r\n onInput={e => (this.industryName = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-field\">\r\n <label>感兴趣的职位</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的职位\"\r\n value={this.jobPosition}\r\n onInput={e => (this.jobPosition = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-hint\">为确保职业规划报告的准确性,推荐您至少填写其中一项</div>\r\n </div>\r\n )}\r\n\r\n {this.selectedPlanType === '转型建议' && (\r\n <div class=\"form-fields\">\r\n <div class=\"form-field\">\r\n <label>感兴趣的行业</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的行业\"\r\n value={this.industryName}\r\n onInput={e => (this.industryName = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-field\">\r\n <label>感兴趣的职位</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的职位\"\r\n value={this.jobPosition}\r\n onInput={e => (this.jobPosition = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-hint\">为确保职业规划报告的准确性,推荐您至少填写其中一项</div>\r\n <div class=\"form-field\">\r\n <label>期望转型时间</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您期望的转型时间\"\r\n value={this.timePeriod}\r\n onInput={e => (this.timePeriod = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {this.selectedPlanType === '晋升路径' && (\r\n <div class=\"form-fields\">\r\n <div class=\"form-field\">\r\n <label>晋升目标岗位</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您的晋升目标岗位\"\r\n value={this.targetPosition}\r\n onInput={e => (this.targetPosition = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-hint\">为确保职业规划报告的准确性,建议您填写晋升目标岗位名称</div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* 简历上传区域 */}\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={true}\r\n acceptFileSuffixList={['.txt', '.md', '.pdf', '.docx', '.doc']}\r\n uploadParams={{\r\n tags: ['resume'],\r\n }}\r\n defaultFileList={\r\n this.customInputs?.file_url\r\n ? [\r\n {\r\n cos_key: this.customInputs.file_url,\r\n file_name: this.customInputs?.file_name || '预设简历',\r\n file_size: 0,\r\n ext: '',\r\n },\r\n ]\r\n : undefined\r\n }\r\n disabled={disableResumeUpload}\r\n onUploadChange={e => {\r\n const result: FileUploadResponse[] = e.detail ?? [];\r\n this.uploadedFileInfo = result[0];\r\n this.uploadSuccess.emit(this.uploadedFileInfo);\r\n }}\r\n />\r\n </div>\r\n\r\n {/* 手机号和验证码区域(可选) */}\r\n <div class=\"jd-input-section\">\r\n <label>手机号(选填,填写后结果将通过短信发送)</label>\r\n <input type=\"tel\" class=\"phone-input\" placeholder=\"请输入手机号\" maxLength={11} value={this.phoneNumber} onInput={this.handlePhoneNumberChange} />\r\n </div>\r\n\r\n {/* 验证码输入区域 - 仅在填写了手机号时显示 */}\r\n {this.phoneNumber.trim().length === 11 && (\r\n <div class=\"jd-input-section\">\r\n <label>验证码</label>\r\n <div class=\"verification-code-container\">\r\n <input\r\n type=\"text\"\r\n class=\"verification-code-input\"\r\n placeholder=\"请输入验证码\"\r\n maxLength={6}\r\n value={this.verificationCode}\r\n onInput={this.handleVerificationCodeChange}\r\n />\r\n <button class=\"send-code-button\" disabled={this.isSendingCode || this.countdown > 0 || !this.phoneNumber.trim()} onClick={this.handleSendCode}>\r\n {this.isSendingCode ? '发送中...' : this.countdown > 0 ? `${this.countdown}秒` : '发送验证码'}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <button\r\n class=\"submit-button\"\r\n disabled={(!disableResumeUpload && !this.uploadedFileInfo) || this.isUploading || this.isSubmitting || this.isVerifyingCode}\r\n onClick={this.handleStartPlanning}\r\n >\r\n {this.isUploading ? '上传中...' : this.isVerifyingCode ? '验证中...' : this.isSubmitting ? '处理中...' : '开始规划'}\r\n </button>\r\n\r\n <div class=\"ai-disclaimer\">\r\n <p>所有内容均由AI生成仅供参考</p>\r\n <p class=\"beian-info\">\r\n <span>中央网信办生成式人工智能服务备案号</span>:\r\n <a href=\"https://www.pincaimao.com\" target=\"_blank\" rel=\"noopener noreferrer\">\r\n Hunan-PinCaiMao-202412310003\r\n </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=\"121182005294690304\"\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 phone: this.phoneNumber.trim() || undefined,\r\n // 有值就传递\r\n ...(this.industryName ? { industry_name: this.industryName } : {}),\r\n ...(this.targetPosition || this.jobPosition ? { target_position: this.targetPosition || this.jobPosition } : {}),\r\n ...(this.timePeriod ? { time_period: this.timePeriod } : {}),\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}\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 && 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=\"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 digitalId={this.digitalId}\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 ai_interview_type: this.digitalId || 2,\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 min-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-title-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n}\r\n\r\n.header-title-group > div:first-child {\r\n font-size: 16px;\r\n}\r\n\r\n.header-disclaimer {\r\n font-size: 11px;\r\n color: #999;\r\n line-height: 1;\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 && 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=\"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 digitalId={this.digitalId}\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\nimport { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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 * 是否在上传界面显示历史会话按钮\r\n */\r\n @Prop() showInputHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端输入合同内容\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' = 'drawer';\r\n\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 readonly _historyConversationPageSize: number = 20;\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 private loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations('3022316191018882', 'pcm-htws-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title=\"历史会话\">\r\n 历史会话\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle=\"历史会话\"\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>加载中...</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>暂无历史会话</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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} \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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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 @Prop() showInputHistory: 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' = 'drawer';\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 @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 private readonly _historyConversationPageSize: number = 20;\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 loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations('3022316191018885', 'pcm-hyzj-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title=\"历史会话\">\r\n 历史会话\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle=\"历史会话\"\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>加载中...</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>暂无历史会话</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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","/* 输入模式切换 */\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\nimport { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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 * 是否在上传界面显示历史会话按钮\r\n */\r\n @Prop() showInputHistory: 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' = 'drawer';\r\n\r\n @State() showChatModal: boolean = false;\r\n @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 private readonly _historyConversationPageSize: number = 20;\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 loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations(this.getBotId(), 'pcm-jd-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title={this.strings?.historyConversations}>\r\n {this.strings?.historyConversations}\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle={this.strings?.historyConversations}\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>{this.strings?.history?.loading}</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>{this.strings?.history?.noHistory}</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button\r\n type=\"button\"\r\n class=\"history-pagination-button\"\r\n disabled={this.historyConversationPageIndex === 0}\r\n onClick={() => this.handleHistoryConversationPageChange('prev')}\r\n >\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button\r\n type=\"button\"\r\n class=\"history-pagination-button\"\r\n disabled={!this.hasMoreHistoryConversations}\r\n onClick={() => this.handleHistoryConversationPageChange('next')}\r\n >\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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} \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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\nimport { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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或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 */\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 @Prop() showInputHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历\r\n */\r\n @Prop() mobileUploadAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端输入职位描述\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' = 'drawer';\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 @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 readonly _historyConversationPageSize: number = 20;\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或resume_content)和job_info,直接显示聊天模态框\r\n if (this.conversationId || ((this.customInputs?.file_url || this.customInputs?.resume_content) && 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 private loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations('3022316191018881', 'pcm-jlpp-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\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/resume_content,也没有上传文件,则提示\r\n if (!this.customInputs?.file_url && !this.customInputs?.resume_content && !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 // 判断是否隐藏简历上传区域 - 当有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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title=\"历史会话\">\r\n 历史会话\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle=\"历史会话\"\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>加载中...</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>暂无历史会话</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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","/* 模态框基础样式 */\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.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 gap: 8px;\r\n}\r\n\r\n.refresh-btn {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n padding: 0;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n transition: color 0.2s, border-color 0.2s, background 0.2s;\r\n}\r\n\r\n.refresh-btn:hover {\r\n color: #1890ff;\r\n border-color: #1890ff;\r\n background: #e6f4ff;\r\n}\r\n\r\n.refresh-btn:disabled {\r\n color: #bfbfbf;\r\n border-color: #d9d9d9;\r\n background: #f5f5f5;\r\n cursor: not-allowed;\r\n}\r\n\r\n@keyframes spin {\r\n from { transform: rotate(0deg); }\r\n to { transform: rotate(360deg); }\r\n}\r\n\r\n.refresh-btn .rotating {\r\n animation: spin 0.8s linear infinite;\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-wrapper {\r\n width: 100%;\r\n display: flex;\r\n justify-content: end;\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/* 响应式设计 */\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}\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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} ","/* 历史会话相关样式已移至 global/global.css */\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.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\nimport { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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或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.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 * 是否在上传界面显示历史会话按钮\r\n */\r\n @Prop() showInputHistory: 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' = 'drawer';\r\n\r\n @State() isUploading: boolean = false;\r\n @State() uploadedFileInfo: FileUploadResponse | null = null;\r\n @State() showChatModal: boolean = false;\r\n @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 private pcmUploadRef;\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 private readonly _historyConversationPageSize: number = 20;\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.uploadedFileInfo = null;\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或resume_content)和job_info,直接显示聊天模态框\r\n if (this.conversationId || ((this.customInputs?.file_url || this.customInputs?.resume_content) && 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 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 loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations(this.getBotId(), 'pcm-mnct-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\r\n };\r\n\r\n private handleStartInterview = async () => {\r\n // 既没有预设 file_url/resume_content,也没有上传文件,则提示\r\n if (!this.customInputs?.file_url && !this.customInputs?.resume_content && !this.uploadedFileInfo) {\r\n Message.info(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 Message.info(this.strings.alerts.enterJobDescription);\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 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 // 判断是否隐藏简历上传区域 - 当有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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title={this.strings?.historyConversations}>\r\n {this.strings?.historyConversations}\r\n </button>\r\n )}\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或resume_content时显示 */}\r\n {!hideResumeUpload && (\r\n <div class=\"resume-upload-section\">\r\n <label>{this.strings.resumeUploadLabel}</label>\r\n <pcm-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={15 * 1024 * 1024}\r\n multiple={false}\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 <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.uploadedFileInfo) ||\r\n (!hideJdInput && !this.jobDescription.trim())) ||\r\n this.isUploading || this.isSubmitting}\r\n onClick={this.handleStartInterview}\r\n >\r\n {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 </div>\r\n )}\r\n\r\n {/* 历史会话抽屉 */}\r\n {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle={this.strings?.historyConversations}\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>{this.strings?.history?.loading}</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>{this.strings?.history?.noHistory}</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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} \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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\r\n */\r\n @Prop() mobileJdInputAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历\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 ai_interview_type: this.digitalId || (this.interviewMode === 'video' ? 2 : 1),\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\r\n */\r\n @Prop() mobileJdInputAble: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历\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 ai_interview_type: this.digitalId || (this.interviewMode === 'video' ? 2 : 1),\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//\n// QR Code Generator for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word 'QR Code' is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n\nvar qrcode = function() {\n\n //---------------------------------------------------------------------\n // qrcode\n //---------------------------------------------------------------------\n\n /**\n * qrcode\n * @param typeNumber 1 to 40\n * @param errorCorrectionLevel 'L','M','Q','H'\n */\n var qrcode = function(typeNumber, errorCorrectionLevel) {\n\n var PAD0 = 0xEC;\n var PAD1 = 0x11;\n\n var _typeNumber = typeNumber;\n var _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];\n var _modules = null;\n var _moduleCount = 0;\n var _dataCache = null;\n var _dataList = [];\n\n var _this = {};\n\n var makeImpl = function(test, maskPattern) {\n\n _moduleCount = _typeNumber * 4 + 17;\n _modules = function(moduleCount) {\n var modules = new Array(moduleCount);\n for (var row = 0; row < moduleCount; row += 1) {\n modules[row] = new Array(moduleCount);\n for (var col = 0; col < moduleCount; col += 1) {\n modules[row][col] = null;\n }\n }\n return modules;\n }(_moduleCount);\n\n setupPositionProbePattern(0, 0);\n setupPositionProbePattern(_moduleCount - 7, 0);\n setupPositionProbePattern(0, _moduleCount - 7);\n setupPositionAdjustPattern();\n setupTimingPattern();\n setupTypeInfo(test, maskPattern);\n\n if (_typeNumber >= 7) {\n setupTypeNumber(test);\n }\n\n if (_dataCache == null) {\n _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);\n }\n\n mapData(_dataCache, maskPattern);\n };\n\n var setupPositionProbePattern = function(row, col) {\n\n for (var r = -1; r <= 7; r += 1) {\n\n if (row + r <= -1 || _moduleCount <= row + r) continue;\n\n for (var c = -1; c <= 7; c += 1) {\n\n if (col + c <= -1 || _moduleCount <= col + c) continue;\n\n if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )\n || (0 <= c && c <= 6 && (r == 0 || r == 6) )\n || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n };\n\n var getBestMaskPattern = function() {\n\n var minLostPoint = 0;\n var pattern = 0;\n\n for (var i = 0; i < 8; i += 1) {\n\n makeImpl(true, i);\n\n var lostPoint = QRUtil.getLostPoint(_this);\n\n if (i == 0 || minLostPoint > lostPoint) {\n minLostPoint = lostPoint;\n pattern = i;\n }\n }\n\n return pattern;\n };\n\n var setupTimingPattern = function() {\n\n for (var r = 8; r < _moduleCount - 8; r += 1) {\n if (_modules[r][6] != null) {\n continue;\n }\n _modules[r][6] = (r % 2 == 0);\n }\n\n for (var c = 8; c < _moduleCount - 8; c += 1) {\n if (_modules[6][c] != null) {\n continue;\n }\n _modules[6][c] = (c % 2 == 0);\n }\n };\n\n var setupPositionAdjustPattern = function() {\n\n var pos = QRUtil.getPatternPosition(_typeNumber);\n\n for (var i = 0; i < pos.length; i += 1) {\n\n for (var j = 0; j < pos.length; j += 1) {\n\n var row = pos[i];\n var col = pos[j];\n\n if (_modules[row][col] != null) {\n continue;\n }\n\n for (var r = -2; r <= 2; r += 1) {\n\n for (var c = -2; c <= 2; c += 1) {\n\n if (r == -2 || r == 2 || c == -2 || c == 2\n || (r == 0 && c == 0) ) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n }\n }\n };\n\n var setupTypeNumber = function(test) {\n\n var bits = QRUtil.getBCHTypeNumber(_typeNumber);\n\n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ( (bits >> i) & 1) == 1);\n _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;\n }\n\n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ( (bits >> i) & 1) == 1);\n _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n }\n };\n\n var setupTypeInfo = function(test, maskPattern) {\n\n var data = (_errorCorrectionLevel << 3) | maskPattern;\n var bits = QRUtil.getBCHTypeInfo(data);\n\n // vertical\n for (var i = 0; i < 15; i += 1) {\n\n var mod = (!test && ( (bits >> i) & 1) == 1);\n\n if (i < 6) {\n _modules[i][8] = mod;\n } else if (i < 8) {\n _modules[i + 1][8] = mod;\n } else {\n _modules[_moduleCount - 15 + i][8] = mod;\n }\n }\n\n // horizontal\n for (var i = 0; i < 15; i += 1) {\n\n var mod = (!test && ( (bits >> i) & 1) == 1);\n\n if (i < 8) {\n _modules[8][_moduleCount - i - 1] = mod;\n } else if (i < 9) {\n _modules[8][15 - i - 1 + 1] = mod;\n } else {\n _modules[8][15 - i - 1] = mod;\n }\n }\n\n // fixed module\n _modules[_moduleCount - 8][8] = (!test);\n };\n\n var mapData = function(data, maskPattern) {\n\n var inc = -1;\n var row = _moduleCount - 1;\n var bitIndex = 7;\n var byteIndex = 0;\n var maskFunc = QRUtil.getMaskFunction(maskPattern);\n\n for (var col = _moduleCount - 1; col > 0; col -= 2) {\n\n if (col == 6) col -= 1;\n\n while (true) {\n\n for (var c = 0; c < 2; c += 1) {\n\n if (_modules[row][col - c] == null) {\n\n var dark = false;\n\n if (byteIndex < data.length) {\n dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);\n }\n\n var mask = maskFunc(row, col - c);\n\n if (mask) {\n dark = !dark;\n }\n\n _modules[row][col - c] = dark;\n bitIndex -= 1;\n\n if (bitIndex == -1) {\n byteIndex += 1;\n bitIndex = 7;\n }\n }\n }\n\n row += inc;\n\n if (row < 0 || _moduleCount <= row) {\n row -= inc;\n inc = -inc;\n break;\n }\n }\n }\n };\n\n var createBytes = function(buffer, rsBlocks) {\n\n var offset = 0;\n\n var maxDcCount = 0;\n var maxEcCount = 0;\n\n var dcdata = new Array(rsBlocks.length);\n var ecdata = new Array(rsBlocks.length);\n\n for (var r = 0; r < rsBlocks.length; r += 1) {\n\n var dcCount = rsBlocks[r].dataCount;\n var ecCount = rsBlocks[r].totalCount - dcCount;\n\n maxDcCount = Math.max(maxDcCount, dcCount);\n maxEcCount = Math.max(maxEcCount, ecCount);\n\n dcdata[r] = new Array(dcCount);\n\n for (var i = 0; i < dcdata[r].length; i += 1) {\n dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];\n }\n offset += dcCount;\n\n var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);\n\n var modPoly = rawPoly.mod(rsPoly);\n ecdata[r] = new Array(rsPoly.getLength() - 1);\n for (var i = 0; i < ecdata[r].length; i += 1) {\n var modIndex = i + modPoly.getLength() - ecdata[r].length;\n ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;\n }\n }\n\n var totalCodeCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalCodeCount += rsBlocks[i].totalCount;\n }\n\n var data = new Array(totalCodeCount);\n var index = 0;\n\n for (var i = 0; i < maxDcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < dcdata[r].length) {\n data[index] = dcdata[r][i];\n index += 1;\n }\n }\n }\n\n for (var i = 0; i < maxEcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < ecdata[r].length) {\n data[index] = ecdata[r][i];\n index += 1;\n }\n }\n }\n\n return data;\n };\n\n var createData = function(typeNumber, errorCorrectionLevel, dataList) {\n\n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);\n\n var buffer = qrBitBuffer();\n\n for (var i = 0; i < dataList.length; i += 1) {\n var data = dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n data.write(buffer);\n }\n\n // calc num max data.\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n\n if (buffer.getLengthInBits() > totalDataCount * 8) {\n throw 'code length overflow. ('\n + buffer.getLengthInBits()\n + '>'\n + totalDataCount * 8\n + ')';\n }\n\n // end code\n if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {\n buffer.put(0, 4);\n }\n\n // padding\n while (buffer.getLengthInBits() % 8 != 0) {\n buffer.putBit(false);\n }\n\n // padding\n while (true) {\n\n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD0, 8);\n\n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD1, 8);\n }\n\n return createBytes(buffer, rsBlocks);\n };\n\n _this.addData = function(data, mode) {\n\n mode = mode || 'Byte';\n\n var newData = null;\n\n switch(mode) {\n case 'Numeric' :\n newData = qrNumber(data);\n break;\n case 'Alphanumeric' :\n newData = qrAlphaNum(data);\n break;\n case 'Byte' :\n newData = qr8BitByte(data);\n break;\n case 'Kanji' :\n newData = qrKanji(data);\n break;\n default :\n throw 'mode:' + mode;\n }\n\n _dataList.push(newData);\n _dataCache = null;\n };\n\n _this.isDark = function(row, col) {\n if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {\n throw row + ',' + col;\n }\n return _modules[row][col];\n };\n\n _this.getModuleCount = function() {\n return _moduleCount;\n };\n\n _this.make = function() {\n if (_typeNumber < 1) {\n var typeNumber = 1;\n\n for (; typeNumber < 40; typeNumber++) {\n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);\n var buffer = qrBitBuffer();\n\n for (var i = 0; i < _dataList.length; i++) {\n var data = _dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );\n data.write(buffer);\n }\n\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i++) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n\n if (buffer.getLengthInBits() <= totalDataCount * 8) {\n break;\n }\n }\n\n _typeNumber = typeNumber;\n }\n\n makeImpl(false, getBestMaskPattern() );\n };\n\n _this.createTableTag = function(cellSize, margin) {\n\n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n var qrHtml = '';\n\n qrHtml += '<table style=\"';\n qrHtml += ' border-width: 0px; border-style: none;';\n qrHtml += ' border-collapse: collapse;';\n qrHtml += ' padding: 0px; margin: ' + margin + 'px;';\n qrHtml += '\">';\n qrHtml += '<tbody>';\n\n for (var r = 0; r < _this.getModuleCount(); r += 1) {\n\n qrHtml += '<tr>';\n\n for (var c = 0; c < _this.getModuleCount(); c += 1) {\n qrHtml += '<td style=\"';\n qrHtml += ' border-width: 0px; border-style: none;';\n qrHtml += ' border-collapse: collapse;';\n qrHtml += ' padding: 0px; margin: 0px;';\n qrHtml += ' width: ' + cellSize + 'px;';\n qrHtml += ' height: ' + cellSize + 'px;';\n qrHtml += ' background-color: ';\n qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';\n qrHtml += ';';\n qrHtml += '\"/>';\n }\n\n qrHtml += '</tr>';\n }\n\n qrHtml += '</tbody>';\n qrHtml += '</table>';\n\n return qrHtml;\n };\n\n _this.createSvgTag = function(cellSize, margin, alt, title) {\n\n var opts = {};\n if (typeof arguments[0] == 'object') {\n // Called by options.\n opts = arguments[0];\n // overwrite cellSize and margin.\n cellSize = opts.cellSize;\n margin = opts.margin;\n alt = opts.alt;\n title = opts.title;\n }\n\n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n // Compose alt property surrogate\n alt = (typeof alt === 'string') ? {text: alt} : alt || {};\n alt.text = alt.text || null;\n alt.id = (alt.text) ? alt.id || 'qrcode-description' : null;\n\n // Compose title property surrogate\n title = (typeof title === 'string') ? {text: title} : title || {};\n title.text = title.text || null;\n title.id = (title.text) ? title.id || 'qrcode-title' : null;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var c, mc, r, mr, qrSvg='', rect;\n\n rect = 'l' + cellSize + ',0 0,' + cellSize +\n ' -' + cellSize + ',0 0,-' + cellSize + 'z ';\n\n qrSvg += '<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"';\n qrSvg += !opts.scalable ? ' width=\"' + size + 'px\" height=\"' + size + 'px\"' : '';\n qrSvg += ' viewBox=\"0 0 ' + size + ' ' + size + '\" ';\n qrSvg += ' preserveAspectRatio=\"xMinYMin meet\"';\n qrSvg += (title.text || alt.text) ? ' role=\"img\" aria-labelledby=\"' +\n escapeXml([title.id, alt.id].join(' ').trim() ) + '\"' : '';\n qrSvg += '>';\n qrSvg += (title.text) ? '<title id=\"' + escapeXml(title.id) + '\">' +\n escapeXml(title.text) + '</title>' : '';\n qrSvg += (alt.text) ? '<description id=\"' + escapeXml(alt.id) + '\">' +\n escapeXml(alt.text) + '</description>' : '';\n qrSvg += '<rect width=\"100%\" height=\"100%\" fill=\"white\" cx=\"0\" cy=\"0\"/>';\n qrSvg += '<path d=\"';\n\n for (r = 0; r < _this.getModuleCount(); r += 1) {\n mr = r * cellSize + margin;\n for (c = 0; c < _this.getModuleCount(); c += 1) {\n if (_this.isDark(r, c) ) {\n mc = c*cellSize+margin;\n qrSvg += 'M' + mc + ',' + mr + rect;\n }\n }\n }\n\n qrSvg += '\" stroke=\"transparent\" fill=\"black\"/>';\n qrSvg += '</svg>';\n\n return qrSvg;\n };\n\n _this.createDataURL = function(cellSize, margin) {\n\n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n return createDataURL(size, size, function(x, y) {\n if (min <= x && x < max && min <= y && y < max) {\n var c = Math.floor( (x - min) / cellSize);\n var r = Math.floor( (y - min) / cellSize);\n return _this.isDark(r, c)? 0 : 1;\n } else {\n return 1;\n }\n } );\n };\n\n _this.createImgTag = function(cellSize, margin, alt) {\n\n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined')? cellSize * 4 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n\n var img = '';\n img += '<img';\n img += '\\u0020src=\"';\n img += _this.createDataURL(cellSize, margin);\n img += '\"';\n img += '\\u0020width=\"';\n img += size;\n img += '\"';\n img += '\\u0020height=\"';\n img += size;\n img += '\"';\n if (alt) {\n img += '\\u0020alt=\"';\n img += escapeXml(alt);\n img += '\"';\n }\n img += '/>';\n\n return img;\n };\n\n var escapeXml = function(s) {\n var escaped = '';\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charAt(i);\n switch(c) {\n case '<': escaped += '<'; break;\n case '>': escaped += '>'; break;\n case '&': escaped += '&'; break;\n case '\"': escaped += '"'; break;\n default : escaped += c; break;\n }\n }\n return escaped;\n };\n\n var _createHalfASCII = function(margin) {\n var cellSize = 1;\n margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n var y, x, r1, r2, p;\n\n var blocks = {\n '██': '█',\n '█ ': '▀',\n ' █': '▄',\n ' ': ' '\n };\n\n var blocksLastLineNoMargin = {\n '██': '▀',\n '█ ': '▀',\n ' █': ' ',\n ' ': ' '\n };\n\n var ascii = '';\n for (y = 0; y < size; y += 2) {\n r1 = Math.floor((y - min) / cellSize);\n r2 = Math.floor((y + 1 - min) / cellSize);\n for (x = 0; x < size; x += 1) {\n p = '█';\n\n if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {\n p = ' ';\n }\n\n if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {\n p += ' ';\n }\n else {\n p += '█';\n }\n\n // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];\n }\n\n ascii += '\\n';\n }\n\n if (size % 2 && margin > 0) {\n return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('▀');\n }\n\n return ascii.substring(0, ascii.length-1);\n };\n\n _this.createASCII = function(cellSize, margin) {\n cellSize = cellSize || 1;\n\n if (cellSize < 2) {\n return _createHalfASCII(margin);\n }\n\n cellSize -= 1;\n margin = (typeof margin == 'undefined')? cellSize * 2 : margin;\n\n var size = _this.getModuleCount() * cellSize + margin * 2;\n var min = margin;\n var max = size - margin;\n\n var y, x, r, p;\n\n var white = Array(cellSize+1).join('██');\n var black = Array(cellSize+1).join(' ');\n\n var ascii = '';\n var line = '';\n for (y = 0; y < size; y += 1) {\n r = Math.floor( (y - min) / cellSize);\n line = '';\n for (x = 0; x < size; x += 1) {\n p = 1;\n\n if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {\n p = 0;\n }\n\n // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.\n line += p ? white : black;\n }\n\n for (r = 0; r < cellSize; r += 1) {\n ascii += line + '\\n';\n }\n }\n\n return ascii.substring(0, ascii.length-1);\n };\n\n _this.renderTo2dContext = function(context, cellSize) {\n cellSize = cellSize || 2;\n var length = _this.getModuleCount();\n for (var row = 0; row < length; row++) {\n for (var col = 0; col < length; col++) {\n context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';\n context.fillRect(col * cellSize, row * cellSize, cellSize, cellSize);\n }\n }\n }\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrcode.stringToBytes\n //---------------------------------------------------------------------\n\n qrcode.stringToBytesFuncs = {\n 'default' : function(s) {\n var bytes = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n bytes.push(c & 0xff);\n }\n return bytes;\n }\n };\n\n qrcode.stringToBytes = qrcode.stringToBytesFuncs['default'];\n\n //---------------------------------------------------------------------\n // qrcode.createStringToBytes\n //---------------------------------------------------------------------\n\n /**\n * @param unicodeData base64 string of byte array.\n * [16bit Unicode],[16bit Bytes], ...\n * @param numChars\n */\n qrcode.createStringToBytes = function(unicodeData, numChars) {\n\n // create conversion map.\n\n var unicodeMap = function() {\n\n var bin = base64DecodeInputStream(unicodeData);\n var read = function() {\n var b = bin.read();\n if (b == -1) throw 'eof';\n return b;\n };\n\n var count = 0;\n var unicodeMap = {};\n while (true) {\n var b0 = bin.read();\n if (b0 == -1) break;\n var b1 = read();\n var b2 = read();\n var b3 = read();\n var k = String.fromCharCode( (b0 << 8) | b1);\n var v = (b2 << 8) | b3;\n unicodeMap[k] = v;\n count += 1;\n }\n if (count != numChars) {\n throw count + ' != ' + numChars;\n }\n\n return unicodeMap;\n }();\n\n var unknownChar = '?'.charCodeAt(0);\n\n return function(s) {\n var bytes = [];\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n if (c < 128) {\n bytes.push(c);\n } else {\n var b = unicodeMap[s.charAt(i)];\n if (typeof b == 'number') {\n if ( (b & 0xff) == b) {\n // 1byte\n bytes.push(b);\n } else {\n // 2bytes\n bytes.push(b >>> 8);\n bytes.push(b & 0xff);\n }\n } else {\n bytes.push(unknownChar);\n }\n }\n }\n return bytes;\n };\n };\n\n //---------------------------------------------------------------------\n // QRMode\n //---------------------------------------------------------------------\n\n var QRMode = {\n MODE_NUMBER : 1 << 0,\n MODE_ALPHA_NUM : 1 << 1,\n MODE_8BIT_BYTE : 1 << 2,\n MODE_KANJI : 1 << 3\n };\n\n //---------------------------------------------------------------------\n // QRErrorCorrectionLevel\n //---------------------------------------------------------------------\n\n var QRErrorCorrectionLevel = {\n L : 1,\n M : 0,\n Q : 3,\n H : 2\n };\n\n //---------------------------------------------------------------------\n // QRMaskPattern\n //---------------------------------------------------------------------\n\n var QRMaskPattern = {\n PATTERN000 : 0,\n PATTERN001 : 1,\n PATTERN010 : 2,\n PATTERN011 : 3,\n PATTERN100 : 4,\n PATTERN101 : 5,\n PATTERN110 : 6,\n PATTERN111 : 7\n };\n\n //---------------------------------------------------------------------\n // QRUtil\n //---------------------------------------------------------------------\n\n var QRUtil = function() {\n\n var PATTERN_POSITION_TABLE = [\n [],\n [6, 18],\n [6, 22],\n [6, 26],\n [6, 30],\n [6, 34],\n [6, 22, 38],\n [6, 24, 42],\n [6, 26, 46],\n [6, 28, 50],\n [6, 30, 54],\n [6, 32, 58],\n [6, 34, 62],\n [6, 26, 46, 66],\n [6, 26, 48, 70],\n [6, 26, 50, 74],\n [6, 30, 54, 78],\n [6, 30, 56, 82],\n [6, 30, 58, 86],\n [6, 34, 62, 90],\n [6, 28, 50, 72, 94],\n [6, 26, 50, 74, 98],\n [6, 30, 54, 78, 102],\n [6, 28, 54, 80, 106],\n [6, 32, 58, 84, 110],\n [6, 30, 58, 86, 114],\n [6, 34, 62, 90, 118],\n [6, 26, 50, 74, 98, 122],\n [6, 30, 54, 78, 102, 126],\n [6, 26, 52, 78, 104, 130],\n [6, 30, 56, 82, 108, 134],\n [6, 34, 60, 86, 112, 138],\n [6, 30, 58, 86, 114, 142],\n [6, 34, 62, 90, 118, 146],\n [6, 30, 54, 78, 102, 126, 150],\n [6, 24, 50, 76, 102, 128, 154],\n [6, 28, 54, 80, 106, 132, 158],\n [6, 32, 58, 84, 110, 136, 162],\n [6, 26, 54, 82, 110, 138, 166],\n [6, 30, 58, 86, 114, 142, 170]\n ];\n var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);\n var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);\n var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);\n\n var _this = {};\n\n var getBCHDigit = function(data) {\n var digit = 0;\n while (data != 0) {\n digit += 1;\n data >>>= 1;\n }\n return digit;\n };\n\n _this.getBCHTypeInfo = function(data) {\n var d = data << 10;\n while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {\n d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );\n }\n return ( (data << 10) | d) ^ G15_MASK;\n };\n\n _this.getBCHTypeNumber = function(data) {\n var d = data << 12;\n while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {\n d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );\n }\n return (data << 12) | d;\n };\n\n _this.getPatternPosition = function(typeNumber) {\n return PATTERN_POSITION_TABLE[typeNumber - 1];\n };\n\n _this.getMaskFunction = function(maskPattern) {\n\n switch (maskPattern) {\n\n case QRMaskPattern.PATTERN000 :\n return function(i, j) { return (i + j) % 2 == 0; };\n case QRMaskPattern.PATTERN001 :\n return function(i, j) { return i % 2 == 0; };\n case QRMaskPattern.PATTERN010 :\n return function(i, j) { return j % 3 == 0; };\n case QRMaskPattern.PATTERN011 :\n return function(i, j) { return (i + j) % 3 == 0; };\n case QRMaskPattern.PATTERN100 :\n return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };\n case QRMaskPattern.PATTERN101 :\n return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };\n case QRMaskPattern.PATTERN110 :\n return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };\n case QRMaskPattern.PATTERN111 :\n return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };\n\n default :\n throw 'bad maskPattern:' + maskPattern;\n }\n };\n\n _this.getErrorCorrectPolynomial = function(errorCorrectLength) {\n var a = qrPolynomial([1], 0);\n for (var i = 0; i < errorCorrectLength; i += 1) {\n a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );\n }\n return a;\n };\n\n _this.getLengthInBits = function(mode, type) {\n\n if (1 <= type && type < 10) {\n\n // 1 - 9\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 10;\n case QRMode.MODE_ALPHA_NUM : return 9;\n case QRMode.MODE_8BIT_BYTE : return 8;\n case QRMode.MODE_KANJI : return 8;\n default :\n throw 'mode:' + mode;\n }\n\n } else if (type < 27) {\n\n // 10 - 26\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 12;\n case QRMode.MODE_ALPHA_NUM : return 11;\n case QRMode.MODE_8BIT_BYTE : return 16;\n case QRMode.MODE_KANJI : return 10;\n default :\n throw 'mode:' + mode;\n }\n\n } else if (type < 41) {\n\n // 27 - 40\n\n switch(mode) {\n case QRMode.MODE_NUMBER : return 14;\n case QRMode.MODE_ALPHA_NUM : return 13;\n case QRMode.MODE_8BIT_BYTE : return 16;\n case QRMode.MODE_KANJI : return 12;\n default :\n throw 'mode:' + mode;\n }\n\n } else {\n throw 'type:' + type;\n }\n };\n\n _this.getLostPoint = function(qrcode) {\n\n var moduleCount = qrcode.getModuleCount();\n\n var lostPoint = 0;\n\n // LEVEL1\n\n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount; col += 1) {\n\n var sameCount = 0;\n var dark = qrcode.isDark(row, col);\n\n for (var r = -1; r <= 1; r += 1) {\n\n if (row + r < 0 || moduleCount <= row + r) {\n continue;\n }\n\n for (var c = -1; c <= 1; c += 1) {\n\n if (col + c < 0 || moduleCount <= col + c) {\n continue;\n }\n\n if (r == 0 && c == 0) {\n continue;\n }\n\n if (dark == qrcode.isDark(row + r, col + c) ) {\n sameCount += 1;\n }\n }\n }\n\n if (sameCount > 5) {\n lostPoint += (3 + sameCount - 5);\n }\n }\n };\n\n // LEVEL2\n\n for (var row = 0; row < moduleCount - 1; row += 1) {\n for (var col = 0; col < moduleCount - 1; col += 1) {\n var count = 0;\n if (qrcode.isDark(row, col) ) count += 1;\n if (qrcode.isDark(row + 1, col) ) count += 1;\n if (qrcode.isDark(row, col + 1) ) count += 1;\n if (qrcode.isDark(row + 1, col + 1) ) count += 1;\n if (count == 0 || count == 4) {\n lostPoint += 3;\n }\n }\n }\n\n // LEVEL3\n\n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount - 6; col += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row, col + 1)\n && qrcode.isDark(row, col + 2)\n && qrcode.isDark(row, col + 3)\n && qrcode.isDark(row, col + 4)\n && !qrcode.isDark(row, col + 5)\n && qrcode.isDark(row, col + 6) ) {\n lostPoint += 40;\n }\n }\n }\n\n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount - 6; row += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row + 1, col)\n && qrcode.isDark(row + 2, col)\n && qrcode.isDark(row + 3, col)\n && qrcode.isDark(row + 4, col)\n && !qrcode.isDark(row + 5, col)\n && qrcode.isDark(row + 6, col) ) {\n lostPoint += 40;\n }\n }\n }\n\n // LEVEL4\n\n var darkCount = 0;\n\n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount; row += 1) {\n if (qrcode.isDark(row, col) ) {\n darkCount += 1;\n }\n }\n }\n\n var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n lostPoint += ratio * 10;\n\n return lostPoint;\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // QRMath\n //---------------------------------------------------------------------\n\n var QRMath = function() {\n\n var EXP_TABLE = new Array(256);\n var LOG_TABLE = new Array(256);\n\n // initialize tables\n for (var i = 0; i < 8; i += 1) {\n EXP_TABLE[i] = 1 << i;\n }\n for (var i = 8; i < 256; i += 1) {\n EXP_TABLE[i] = EXP_TABLE[i - 4]\n ^ EXP_TABLE[i - 5]\n ^ EXP_TABLE[i - 6]\n ^ EXP_TABLE[i - 8];\n }\n for (var i = 0; i < 255; i += 1) {\n LOG_TABLE[EXP_TABLE[i] ] = i;\n }\n\n var _this = {};\n\n _this.glog = function(n) {\n\n if (n < 1) {\n throw 'glog(' + n + ')';\n }\n\n return LOG_TABLE[n];\n };\n\n _this.gexp = function(n) {\n\n while (n < 0) {\n n += 255;\n }\n\n while (n >= 256) {\n n -= 255;\n }\n\n return EXP_TABLE[n];\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // qrPolynomial\n //---------------------------------------------------------------------\n\n function qrPolynomial(num, shift) {\n\n if (typeof num.length == 'undefined') {\n throw num.length + '/' + shift;\n }\n\n var _num = function() {\n var offset = 0;\n while (offset < num.length && num[offset] == 0) {\n offset += 1;\n }\n var _num = new Array(num.length - offset + shift);\n for (var i = 0; i < num.length - offset; i += 1) {\n _num[i] = num[i + offset];\n }\n return _num;\n }();\n\n var _this = {};\n\n _this.getAt = function(index) {\n return _num[index];\n };\n\n _this.getLength = function() {\n return _num.length;\n };\n\n _this.multiply = function(e) {\n\n var num = new Array(_this.getLength() + e.getLength() - 1);\n\n for (var i = 0; i < _this.getLength(); i += 1) {\n for (var j = 0; j < e.getLength(); j += 1) {\n num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );\n }\n }\n\n return qrPolynomial(num, 0);\n };\n\n _this.mod = function(e) {\n\n if (_this.getLength() - e.getLength() < 0) {\n return _this;\n }\n\n var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );\n\n var num = new Array(_this.getLength() );\n for (var i = 0; i < _this.getLength(); i += 1) {\n num[i] = _this.getAt(i);\n }\n\n for (var i = 0; i < e.getLength(); i += 1) {\n num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);\n }\n\n // recursive call\n return qrPolynomial(num, 0).mod(e);\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // QRRSBlock\n //---------------------------------------------------------------------\n\n var QRRSBlock = function() {\n\n var RS_BLOCK_TABLE = [\n\n // L\n // M\n // Q\n // H\n\n // 1\n [1, 26, 19],\n [1, 26, 16],\n [1, 26, 13],\n [1, 26, 9],\n\n // 2\n [1, 44, 34],\n [1, 44, 28],\n [1, 44, 22],\n [1, 44, 16],\n\n // 3\n [1, 70, 55],\n [1, 70, 44],\n [2, 35, 17],\n [2, 35, 13],\n\n // 4\n [1, 100, 80],\n [2, 50, 32],\n [2, 50, 24],\n [4, 25, 9],\n\n // 5\n [1, 134, 108],\n [2, 67, 43],\n [2, 33, 15, 2, 34, 16],\n [2, 33, 11, 2, 34, 12],\n\n // 6\n [2, 86, 68],\n [4, 43, 27],\n [4, 43, 19],\n [4, 43, 15],\n\n // 7\n [2, 98, 78],\n [4, 49, 31],\n [2, 32, 14, 4, 33, 15],\n [4, 39, 13, 1, 40, 14],\n\n // 8\n [2, 121, 97],\n [2, 60, 38, 2, 61, 39],\n [4, 40, 18, 2, 41, 19],\n [4, 40, 14, 2, 41, 15],\n\n // 9\n [2, 146, 116],\n [3, 58, 36, 2, 59, 37],\n [4, 36, 16, 4, 37, 17],\n [4, 36, 12, 4, 37, 13],\n\n // 10\n [2, 86, 68, 2, 87, 69],\n [4, 69, 43, 1, 70, 44],\n [6, 43, 19, 2, 44, 20],\n [6, 43, 15, 2, 44, 16],\n\n // 11\n [4, 101, 81],\n [1, 80, 50, 4, 81, 51],\n [4, 50, 22, 4, 51, 23],\n [3, 36, 12, 8, 37, 13],\n\n // 12\n [2, 116, 92, 2, 117, 93],\n [6, 58, 36, 2, 59, 37],\n [4, 46, 20, 6, 47, 21],\n [7, 42, 14, 4, 43, 15],\n\n // 13\n [4, 133, 107],\n [8, 59, 37, 1, 60, 38],\n [8, 44, 20, 4, 45, 21],\n [12, 33, 11, 4, 34, 12],\n\n // 14\n [3, 145, 115, 1, 146, 116],\n [4, 64, 40, 5, 65, 41],\n [11, 36, 16, 5, 37, 17],\n [11, 36, 12, 5, 37, 13],\n\n // 15\n [5, 109, 87, 1, 110, 88],\n [5, 65, 41, 5, 66, 42],\n [5, 54, 24, 7, 55, 25],\n [11, 36, 12, 7, 37, 13],\n\n // 16\n [5, 122, 98, 1, 123, 99],\n [7, 73, 45, 3, 74, 46],\n [15, 43, 19, 2, 44, 20],\n [3, 45, 15, 13, 46, 16],\n\n // 17\n [1, 135, 107, 5, 136, 108],\n [10, 74, 46, 1, 75, 47],\n [1, 50, 22, 15, 51, 23],\n [2, 42, 14, 17, 43, 15],\n\n // 18\n [5, 150, 120, 1, 151, 121],\n [9, 69, 43, 4, 70, 44],\n [17, 50, 22, 1, 51, 23],\n [2, 42, 14, 19, 43, 15],\n\n // 19\n [3, 141, 113, 4, 142, 114],\n [3, 70, 44, 11, 71, 45],\n [17, 47, 21, 4, 48, 22],\n [9, 39, 13, 16, 40, 14],\n\n // 20\n [3, 135, 107, 5, 136, 108],\n [3, 67, 41, 13, 68, 42],\n [15, 54, 24, 5, 55, 25],\n [15, 43, 15, 10, 44, 16],\n\n // 21\n [4, 144, 116, 4, 145, 117],\n [17, 68, 42],\n [17, 50, 22, 6, 51, 23],\n [19, 46, 16, 6, 47, 17],\n\n // 22\n [2, 139, 111, 7, 140, 112],\n [17, 74, 46],\n [7, 54, 24, 16, 55, 25],\n [34, 37, 13],\n\n // 23\n [4, 151, 121, 5, 152, 122],\n [4, 75, 47, 14, 76, 48],\n [11, 54, 24, 14, 55, 25],\n [16, 45, 15, 14, 46, 16],\n\n // 24\n [6, 147, 117, 4, 148, 118],\n [6, 73, 45, 14, 74, 46],\n [11, 54, 24, 16, 55, 25],\n [30, 46, 16, 2, 47, 17],\n\n // 25\n [8, 132, 106, 4, 133, 107],\n [8, 75, 47, 13, 76, 48],\n [7, 54, 24, 22, 55, 25],\n [22, 45, 15, 13, 46, 16],\n\n // 26\n [10, 142, 114, 2, 143, 115],\n [19, 74, 46, 4, 75, 47],\n [28, 50, 22, 6, 51, 23],\n [33, 46, 16, 4, 47, 17],\n\n // 27\n [8, 152, 122, 4, 153, 123],\n [22, 73, 45, 3, 74, 46],\n [8, 53, 23, 26, 54, 24],\n [12, 45, 15, 28, 46, 16],\n\n // 28\n [3, 147, 117, 10, 148, 118],\n [3, 73, 45, 23, 74, 46],\n [4, 54, 24, 31, 55, 25],\n [11, 45, 15, 31, 46, 16],\n\n // 29\n [7, 146, 116, 7, 147, 117],\n [21, 73, 45, 7, 74, 46],\n [1, 53, 23, 37, 54, 24],\n [19, 45, 15, 26, 46, 16],\n\n // 30\n [5, 145, 115, 10, 146, 116],\n [19, 75, 47, 10, 76, 48],\n [15, 54, 24, 25, 55, 25],\n [23, 45, 15, 25, 46, 16],\n\n // 31\n [13, 145, 115, 3, 146, 116],\n [2, 74, 46, 29, 75, 47],\n [42, 54, 24, 1, 55, 25],\n [23, 45, 15, 28, 46, 16],\n\n // 32\n [17, 145, 115],\n [10, 74, 46, 23, 75, 47],\n [10, 54, 24, 35, 55, 25],\n [19, 45, 15, 35, 46, 16],\n\n // 33\n [17, 145, 115, 1, 146, 116],\n [14, 74, 46, 21, 75, 47],\n [29, 54, 24, 19, 55, 25],\n [11, 45, 15, 46, 46, 16],\n\n // 34\n [13, 145, 115, 6, 146, 116],\n [14, 74, 46, 23, 75, 47],\n [44, 54, 24, 7, 55, 25],\n [59, 46, 16, 1, 47, 17],\n\n // 35\n [12, 151, 121, 7, 152, 122],\n [12, 75, 47, 26, 76, 48],\n [39, 54, 24, 14, 55, 25],\n [22, 45, 15, 41, 46, 16],\n\n // 36\n [6, 151, 121, 14, 152, 122],\n [6, 75, 47, 34, 76, 48],\n [46, 54, 24, 10, 55, 25],\n [2, 45, 15, 64, 46, 16],\n\n // 37\n [17, 152, 122, 4, 153, 123],\n [29, 74, 46, 14, 75, 47],\n [49, 54, 24, 10, 55, 25],\n [24, 45, 15, 46, 46, 16],\n\n // 38\n [4, 152, 122, 18, 153, 123],\n [13, 74, 46, 32, 75, 47],\n [48, 54, 24, 14, 55, 25],\n [42, 45, 15, 32, 46, 16],\n\n // 39\n [20, 147, 117, 4, 148, 118],\n [40, 75, 47, 7, 76, 48],\n [43, 54, 24, 22, 55, 25],\n [10, 45, 15, 67, 46, 16],\n\n // 40\n [19, 148, 118, 6, 149, 119],\n [18, 75, 47, 31, 76, 48],\n [34, 54, 24, 34, 55, 25],\n [20, 45, 15, 61, 46, 16]\n ];\n\n var qrRSBlock = function(totalCount, dataCount) {\n var _this = {};\n _this.totalCount = totalCount;\n _this.dataCount = dataCount;\n return _this;\n };\n\n var _this = {};\n\n var getRsBlockTable = function(typeNumber, errorCorrectionLevel) {\n\n switch(errorCorrectionLevel) {\n case QRErrorCorrectionLevel.L :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];\n case QRErrorCorrectionLevel.M :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];\n case QRErrorCorrectionLevel.Q :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];\n case QRErrorCorrectionLevel.H :\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];\n default :\n return undefined;\n }\n };\n\n _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {\n\n var rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);\n\n if (typeof rsBlock == 'undefined') {\n throw 'bad rs block @ typeNumber:' + typeNumber +\n '/errorCorrectionLevel:' + errorCorrectionLevel;\n }\n\n var length = rsBlock.length / 3;\n\n var list = [];\n\n for (var i = 0; i < length; i += 1) {\n\n var count = rsBlock[i * 3 + 0];\n var totalCount = rsBlock[i * 3 + 1];\n var dataCount = rsBlock[i * 3 + 2];\n\n for (var j = 0; j < count; j += 1) {\n list.push(qrRSBlock(totalCount, dataCount) );\n }\n }\n\n return list;\n };\n\n return _this;\n }();\n\n //---------------------------------------------------------------------\n // qrBitBuffer\n //---------------------------------------------------------------------\n\n var qrBitBuffer = function() {\n\n var _buffer = [];\n var _length = 0;\n\n var _this = {};\n\n _this.getBuffer = function() {\n return _buffer;\n };\n\n _this.getAt = function(index) {\n var bufIndex = Math.floor(index / 8);\n return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;\n };\n\n _this.put = function(num, length) {\n for (var i = 0; i < length; i += 1) {\n _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);\n }\n };\n\n _this.getLengthInBits = function() {\n return _length;\n };\n\n _this.putBit = function(bit) {\n\n var bufIndex = Math.floor(_length / 8);\n if (_buffer.length <= bufIndex) {\n _buffer.push(0);\n }\n\n if (bit) {\n _buffer[bufIndex] |= (0x80 >>> (_length % 8) );\n }\n\n _length += 1;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrNumber\n //---------------------------------------------------------------------\n\n var qrNumber = function(data) {\n\n var _mode = QRMode.MODE_NUMBER;\n var _data = data;\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _data.length;\n };\n\n _this.write = function(buffer) {\n\n var data = _data;\n\n var i = 0;\n\n while (i + 2 < data.length) {\n buffer.put(strToNum(data.substring(i, i + 3) ), 10);\n i += 3;\n }\n\n if (i < data.length) {\n if (data.length - i == 1) {\n buffer.put(strToNum(data.substring(i, i + 1) ), 4);\n } else if (data.length - i == 2) {\n buffer.put(strToNum(data.substring(i, i + 2) ), 7);\n }\n }\n };\n\n var strToNum = function(s) {\n var num = 0;\n for (var i = 0; i < s.length; i += 1) {\n num = num * 10 + chatToNum(s.charAt(i) );\n }\n return num;\n };\n\n var chatToNum = function(c) {\n if ('0' <= c && c <= '9') {\n return c.charCodeAt(0) - '0'.charCodeAt(0);\n }\n throw 'illegal char :' + c;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrAlphaNum\n //---------------------------------------------------------------------\n\n var qrAlphaNum = function(data) {\n\n var _mode = QRMode.MODE_ALPHA_NUM;\n var _data = data;\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _data.length;\n };\n\n _this.write = function(buffer) {\n\n var s = _data;\n\n var i = 0;\n\n while (i + 1 < s.length) {\n buffer.put(\n getCode(s.charAt(i) ) * 45 +\n getCode(s.charAt(i + 1) ), 11);\n i += 2;\n }\n\n if (i < s.length) {\n buffer.put(getCode(s.charAt(i) ), 6);\n }\n };\n\n var getCode = function(c) {\n\n if ('0' <= c && c <= '9') {\n return c.charCodeAt(0) - '0'.charCodeAt(0);\n } else if ('A' <= c && c <= 'Z') {\n return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;\n } else {\n switch (c) {\n case ' ' : return 36;\n case '$' : return 37;\n case '%' : return 38;\n case '*' : return 39;\n case '+' : return 40;\n case '-' : return 41;\n case '.' : return 42;\n case '/' : return 43;\n case ':' : return 44;\n default :\n throw 'illegal char :' + c;\n }\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qr8BitByte\n //---------------------------------------------------------------------\n\n var qr8BitByte = function(data) {\n\n var _mode = QRMode.MODE_8BIT_BYTE;\n var _data = data;\n var _bytes = qrcode.stringToBytes(data);\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return _bytes.length;\n };\n\n _this.write = function(buffer) {\n for (var i = 0; i < _bytes.length; i += 1) {\n buffer.put(_bytes[i], 8);\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // qrKanji\n //---------------------------------------------------------------------\n\n var qrKanji = function(data) {\n\n var _mode = QRMode.MODE_KANJI;\n var _data = data;\n\n var stringToBytes = qrcode.stringToBytesFuncs['SJIS'];\n if (!stringToBytes) {\n throw 'sjis not supported.';\n }\n !function(c, code) {\n // self test for sjis support.\n var test = stringToBytes(c);\n if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {\n throw 'sjis not supported.';\n }\n }('\\u53cb', 0x9746);\n\n var _bytes = stringToBytes(data);\n\n var _this = {};\n\n _this.getMode = function() {\n return _mode;\n };\n\n _this.getLength = function(buffer) {\n return ~~(_bytes.length / 2);\n };\n\n _this.write = function(buffer) {\n\n var data = _bytes;\n\n var i = 0;\n\n while (i + 1 < data.length) {\n\n var c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);\n\n if (0x8140 <= c && c <= 0x9FFC) {\n c -= 0x8140;\n } else if (0xE040 <= c && c <= 0xEBBF) {\n c -= 0xC140;\n } else {\n throw 'illegal char at ' + (i + 1) + '/' + c;\n }\n\n c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);\n\n buffer.put(c, 13);\n\n i += 2;\n }\n\n if (i < data.length) {\n throw 'illegal char at ' + (i + 1);\n }\n };\n\n return _this;\n };\n\n //=====================================================================\n // GIF Support etc.\n //\n\n //---------------------------------------------------------------------\n // byteArrayOutputStream\n //---------------------------------------------------------------------\n\n var byteArrayOutputStream = function() {\n\n var _bytes = [];\n\n var _this = {};\n\n _this.writeByte = function(b) {\n _bytes.push(b & 0xff);\n };\n\n _this.writeShort = function(i) {\n _this.writeByte(i);\n _this.writeByte(i >>> 8);\n };\n\n _this.writeBytes = function(b, off, len) {\n off = off || 0;\n len = len || b.length;\n for (var i = 0; i < len; i += 1) {\n _this.writeByte(b[i + off]);\n }\n };\n\n _this.writeString = function(s) {\n for (var i = 0; i < s.length; i += 1) {\n _this.writeByte(s.charCodeAt(i) );\n }\n };\n\n _this.toByteArray = function() {\n return _bytes;\n };\n\n _this.toString = function() {\n var s = '';\n s += '[';\n for (var i = 0; i < _bytes.length; i += 1) {\n if (i > 0) {\n s += ',';\n }\n s += _bytes[i];\n }\n s += ']';\n return s;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // base64EncodeOutputStream\n //---------------------------------------------------------------------\n\n var base64EncodeOutputStream = function() {\n\n var _buffer = 0;\n var _buflen = 0;\n var _length = 0;\n var _base64 = '';\n\n var _this = {};\n\n var writeEncoded = function(b) {\n _base64 += String.fromCharCode(encode(b & 0x3f) );\n };\n\n var encode = function(n) {\n if (n < 0) {\n // error.\n } else if (n < 26) {\n return 0x41 + n;\n } else if (n < 52) {\n return 0x61 + (n - 26);\n } else if (n < 62) {\n return 0x30 + (n - 52);\n } else if (n == 62) {\n return 0x2b;\n } else if (n == 63) {\n return 0x2f;\n }\n throw 'n:' + n;\n };\n\n _this.writeByte = function(n) {\n\n _buffer = (_buffer << 8) | (n & 0xff);\n _buflen += 8;\n _length += 1;\n\n while (_buflen >= 6) {\n writeEncoded(_buffer >>> (_buflen - 6) );\n _buflen -= 6;\n }\n };\n\n _this.flush = function() {\n\n if (_buflen > 0) {\n writeEncoded(_buffer << (6 - _buflen) );\n _buffer = 0;\n _buflen = 0;\n }\n\n if (_length % 3 != 0) {\n // padding\n var padlen = 3 - _length % 3;\n for (var i = 0; i < padlen; i += 1) {\n _base64 += '=';\n }\n }\n };\n\n _this.toString = function() {\n return _base64;\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // base64DecodeInputStream\n //---------------------------------------------------------------------\n\n var base64DecodeInputStream = function(str) {\n\n var _str = str;\n var _pos = 0;\n var _buffer = 0;\n var _buflen = 0;\n\n var _this = {};\n\n _this.read = function() {\n\n while (_buflen < 8) {\n\n if (_pos >= _str.length) {\n if (_buflen == 0) {\n return -1;\n }\n throw 'unexpected end of file./' + _buflen;\n }\n\n var c = _str.charAt(_pos);\n _pos += 1;\n\n if (c == '=') {\n _buflen = 0;\n return -1;\n } else if (c.match(/^\\s$/) ) {\n // ignore if whitespace.\n continue;\n }\n\n _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );\n _buflen += 6;\n }\n\n var n = (_buffer >>> (_buflen - 8) ) & 0xff;\n _buflen -= 8;\n return n;\n };\n\n var decode = function(c) {\n if (0x41 <= c && c <= 0x5a) {\n return c - 0x41;\n } else if (0x61 <= c && c <= 0x7a) {\n return c - 0x61 + 26;\n } else if (0x30 <= c && c <= 0x39) {\n return c - 0x30 + 52;\n } else if (c == 0x2b) {\n return 62;\n } else if (c == 0x2f) {\n return 63;\n } else {\n throw 'c:' + c;\n }\n };\n\n return _this;\n };\n\n //---------------------------------------------------------------------\n // gifImage (B/W)\n //---------------------------------------------------------------------\n\n var gifImage = function(width, height) {\n\n var _width = width;\n var _height = height;\n var _data = new Array(width * height);\n\n var _this = {};\n\n _this.setPixel = function(x, y, pixel) {\n _data[y * _width + x] = pixel;\n };\n\n _this.write = function(out) {\n\n //---------------------------------\n // GIF Signature\n\n out.writeString('GIF87a');\n\n //---------------------------------\n // Screen Descriptor\n\n out.writeShort(_width);\n out.writeShort(_height);\n\n out.writeByte(0x80); // 2bit\n out.writeByte(0);\n out.writeByte(0);\n\n //---------------------------------\n // Global Color Map\n\n // black\n out.writeByte(0x00);\n out.writeByte(0x00);\n out.writeByte(0x00);\n\n // white\n out.writeByte(0xff);\n out.writeByte(0xff);\n out.writeByte(0xff);\n\n //---------------------------------\n // Image Descriptor\n\n out.writeString(',');\n out.writeShort(0);\n out.writeShort(0);\n out.writeShort(_width);\n out.writeShort(_height);\n out.writeByte(0);\n\n //---------------------------------\n // Local Color Map\n\n //---------------------------------\n // Raster Data\n\n var lzwMinCodeSize = 2;\n var raster = getLZWRaster(lzwMinCodeSize);\n\n out.writeByte(lzwMinCodeSize);\n\n var offset = 0;\n\n while (raster.length - offset > 255) {\n out.writeByte(255);\n out.writeBytes(raster, offset, 255);\n offset += 255;\n }\n\n out.writeByte(raster.length - offset);\n out.writeBytes(raster, offset, raster.length - offset);\n out.writeByte(0x00);\n\n //---------------------------------\n // GIF Terminator\n out.writeString(';');\n };\n\n var bitOutputStream = function(out) {\n\n var _out = out;\n var _bitLength = 0;\n var _bitBuffer = 0;\n\n var _this = {};\n\n _this.write = function(data, length) {\n\n if ( (data >>> length) != 0) {\n throw 'length over';\n }\n\n while (_bitLength + length >= 8) {\n _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );\n length -= (8 - _bitLength);\n data >>>= (8 - _bitLength);\n _bitBuffer = 0;\n _bitLength = 0;\n }\n\n _bitBuffer = (data << _bitLength) | _bitBuffer;\n _bitLength = _bitLength + length;\n };\n\n _this.flush = function() {\n if (_bitLength > 0) {\n _out.writeByte(_bitBuffer);\n }\n };\n\n return _this;\n };\n\n var getLZWRaster = function(lzwMinCodeSize) {\n\n var clearCode = 1 << lzwMinCodeSize;\n var endCode = (1 << lzwMinCodeSize) + 1;\n var bitLength = lzwMinCodeSize + 1;\n\n // Setup LZWTable\n var table = lzwTable();\n\n for (var i = 0; i < clearCode; i += 1) {\n table.add(String.fromCharCode(i) );\n }\n table.add(String.fromCharCode(clearCode) );\n table.add(String.fromCharCode(endCode) );\n\n var byteOut = byteArrayOutputStream();\n var bitOut = bitOutputStream(byteOut);\n\n // clear code\n bitOut.write(clearCode, bitLength);\n\n var dataIndex = 0;\n\n var s = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n\n while (dataIndex < _data.length) {\n\n var c = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n\n if (table.contains(s + c) ) {\n\n s = s + c;\n\n } else {\n\n bitOut.write(table.indexOf(s), bitLength);\n\n if (table.size() < 0xfff) {\n\n if (table.size() == (1 << bitLength) ) {\n bitLength += 1;\n }\n\n table.add(s + c);\n }\n\n s = c;\n }\n }\n\n bitOut.write(table.indexOf(s), bitLength);\n\n // end code\n bitOut.write(endCode, bitLength);\n\n bitOut.flush();\n\n return byteOut.toByteArray();\n };\n\n var lzwTable = function() {\n\n var _map = {};\n var _size = 0;\n\n var _this = {};\n\n _this.add = function(key) {\n if (_this.contains(key) ) {\n throw 'dup key:' + key;\n }\n _map[key] = _size;\n _size += 1;\n };\n\n _this.size = function() {\n return _size;\n };\n\n _this.indexOf = function(key) {\n return _map[key];\n };\n\n _this.contains = function(key) {\n return typeof _map[key] != 'undefined';\n };\n\n return _this;\n };\n\n return _this;\n };\n\n var createDataURL = function(width, height, getPixel) {\n var gif = gifImage(width, height);\n for (var y = 0; y < height; y += 1) {\n for (var x = 0; x < width; x += 1) {\n gif.setPixel(x, y, getPixel(x, y) );\n }\n }\n\n var b = byteArrayOutputStream();\n gif.write(b);\n\n var base64 = base64EncodeOutputStream();\n var bytes = b.toByteArray();\n for (var i = 0; i < bytes.length; i += 1) {\n base64.writeByte(bytes[i]);\n }\n base64.flush();\n\n return 'data:image/gif;base64,' + base64;\n };\n\n //---------------------------------------------------------------------\n // returns qrcode function.\n\n return qrcode;\n}();\n\n// multibyte support\n!function() {\n\n qrcode.stringToBytesFuncs['UTF-8'] = function(s) {\n // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array\n function toUTF8Array(str) {\n var utf8 = [];\n for (var i=0; i < str.length; i++) {\n var charcode = str.charCodeAt(i);\n if (charcode < 0x80) utf8.push(charcode);\n else if (charcode < 0x800) {\n utf8.push(0xc0 | (charcode >> 6),\n 0x80 | (charcode & 0x3f));\n }\n else if (charcode < 0xd800 || charcode >= 0xe000) {\n utf8.push(0xe0 | (charcode >> 12),\n 0x80 | ((charcode>>6) & 0x3f),\n 0x80 | (charcode & 0x3f));\n }\n // surrogate pair\n else {\n i++;\n // UTF-16 encodes 0x10000-0x10FFFF by\n // subtracting 0x10000 and splitting the\n // 20 bits of 0x0-0xFFFFF into two halves\n charcode = 0x10000 + (((charcode & 0x3ff)<<10)\n | (str.charCodeAt(i) & 0x3ff));\n utf8.push(0xf0 | (charcode >>18),\n 0x80 | ((charcode>>12) & 0x3f),\n 0x80 | ((charcode>>6) & 0x3f),\n 0x80 | (charcode & 0x3f));\n }\n }\n return utf8;\n }\n return toUTF8Array(s);\n };\n\n}();\n\n(function (factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n }\n}(function () {\n return qrcode;\n}));\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 qrcode from 'qrcode-generator'\r\nimport { 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 qr = qrcode(0, 'M');\r\n qr.addData(e);\r\n qr.make();\r\n this.qrcodeUrl = qr.createDataURL(4, 0);\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 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}","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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 { sendHttpRequest, PCM_DOMAIN } from \"../../utils/utils\";\r\nimport uploadNumberSDK from \"./uploadNumberSDK\";\r\nimport { Message } from \"../../services/message.service\";\r\nimport qrcode from 'qrcode-generator'\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 qr = qrcode(0, 'M');\r\n qr.addData(e);\r\n qr.make();\r\n this.qrcodeUrl = qr.createDataURL(4, 0);\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 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}",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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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 @Prop() showInputHistory: 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' = 'drawer';\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 @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 private readonly _historyConversationPageSize: number = 20;\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 loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations('3022316191018877', 'pcm-msbg-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title=\"历史会话\">\r\n 历史会话\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle=\"历史会话\"\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>加载中...</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>暂无历史会话</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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} \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/* 分步骤区域样式 */\r\n.step-section {\r\n margin-bottom: 20px;\r\n}\r\n\r\n.step-title {\r\n font-size: 14px;\r\n font-weight: 600;\r\n color: #333;\r\n margin-bottom: 12px;\r\n padding-bottom: 8px;\r\n border-bottom: 1px solid #e8e8e8;\r\n}\r\n\r\n/* 优化模式选项 */\r\n.mode-options {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 8px;\r\n}\r\n\r\n.mode-option {\r\n padding: 16px;\r\n border: 2px solid #e2e8f0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.mode-option:hover {\r\n border-color: #94a3b8;\r\n}\r\n\r\n.mode-option.selected {\r\n border-color: #0D75FB;\r\n background-color: #f0f7ff;\r\n}\r\n\r\n.option-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.option-title {\r\n font-weight: 600;\r\n color: #333;\r\n}\r\n\r\n.check-icon {\r\n color: #0D75FB;\r\n font-size: 16px;\r\n}\r\n\r\n.option-desc {\r\n font-size: 14px;\r\n color: #666;\r\n}\r\n\r\n.option-suitable {\r\n font-size: 12px;\r\n color: #999;\r\n}\r\n\r\n/* 输出方式选项 */\r\n.output-options {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n}\r\n\r\n.output-option {\r\n padding: 12px 16px;\r\n border: 2px solid #e2e8f0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.output-option:hover {\r\n border-color: #94a3b8;\r\n}\r\n\r\n.output-option.selected {\r\n border-color: #0D75FB;\r\n background-color: #f0f7ff;\r\n}\r\n\r\n.option-time {\r\n font-size: 12px;\r\n color: #999;\r\n}\r\n\r\n/* JD 提示 */\r\n.jd-hint {\r\n padding: 12px;\r\n background-color: #f6f8fa;\r\n border-radius: 8px;\r\n text-align: center;\r\n}\r\n\r\n.jd-hint p {\r\n font-size: 14px;\r\n color: #666;\r\n margin: 0;\r\n}\r\n\r\n/* 表单提示 */\r\n.form-hint {\r\n font-size: 12px;\r\n color: #fa8c16;\r\n text-align: center;\r\n margin-top: 8px;\r\n}\r\n\r\n.form-hint.warning {\r\n color: #fa8c16;\r\n}\r\n\r\n/* 响应式 */\r\n@media screen and (max-width: 768px) {\r\n .mode-options {\r\n grid-template-columns: 1fr;\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.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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}","/* Loading 状态 */\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: 80px 20px;\r\n background: #fff;\r\n}\r\n\r\n.loading-spinner {\r\n width: 48px;\r\n height: 48px;\r\n border: 4px solid #e8e8e8;\r\n border-top-color: #0D75FB;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\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 font-size: 18px;\r\n font-weight: 500;\r\n color: #333;\r\n margin-top: 24px;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.loading-subtext {\r\n font-size: 14px;\r\n color: #666;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.loading-dots {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.dot {\r\n width: 8px;\r\n height: 8px;\r\n border-radius: 50%;\r\n background-color: #0D75FB;\r\n animation: pulse 1.5s ease-in-out infinite;\r\n}\r\n\r\n.dot.delay-1 {\r\n animation-delay: 0.2s;\r\n}\r\n\r\n.dot.delay-2 {\r\n animation-delay: 0.4s;\r\n}\r\n\r\n@keyframes pulse {\r\n 0%, 100% {\r\n opacity: 0.4;\r\n transform: scale(0.8);\r\n }\r\n 50% {\r\n opacity: 1;\r\n transform: scale(1);\r\n }\r\n}\r\n\r\n/* 错误状态 */\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 padding: 80px 20px;\r\n background: #fff;\r\n}\r\n\r\n.error-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 48px;\r\n height: 48px;\r\n border-radius: 50%;\r\n background-color: #fee2e2;\r\n color: #ef4444;\r\n font-size: 24px;\r\n font-weight: bold;\r\n}\r\n\r\n.error-text {\r\n font-size: 16px;\r\n font-weight: 500;\r\n color: #666;\r\n margin-top: 16px;\r\n margin-bottom: 16px;\r\n}\r\n\r\n.retry-button {\r\n padding: 10px 24px;\r\n background-color: #0D75FB;\r\n color: #fff;\r\n border: none;\r\n border-radius: 6px;\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n}\r\n\r\n.retry-button:hover {\r\n background-color: #0a5fd9;\r\n}\r\n\r\n/* 分析视图 */\r\n.analysis-container {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n padding: 20px;\r\n background: #fff;\r\n}\r\n\r\n.analysis-header {\r\n flex-shrink: 0;\r\n padding-bottom: 16px;\r\n}\r\n\r\n.analysis-title {\r\n font-size: 20px;\r\n font-weight: 600;\r\n color: #333;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.analysis-desc {\r\n font-size: 14px;\r\n color: #666;\r\n margin-bottom: 16px;\r\n}\r\n\r\n/* Tab 样式 */\r\n.tab-container {\r\n display: flex;\r\n gap: 8px;\r\n padding: 4px;\r\n background-color: #f5f5f5;\r\n border-radius: 8px;\r\n}\r\n\r\n.tab-button {\r\n padding: 8px 16px;\r\n background: transparent;\r\n border: none;\r\n border-radius: 6px;\r\n font-size: 14px;\r\n color: #666;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n}\r\n\r\n.tab-button:hover {\r\n color: #333;\r\n}\r\n\r\n.tab-button.active {\r\n background-color: #0D75FB;\r\n color: #fff;\r\n}\r\n\r\n/* iframe 容器 */\r\n.iframe-container {\r\n flex: 1;\r\n width: 100%;\r\n min-height: 400px;\r\n height: 85vh;\r\n overflow: hidden;\r\n padding: 20px;\r\n}\r\n\r\n.iframe-container iframe {\r\n width: 100%;\r\n height: 100%;\r\n border: none;\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: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.fullscreen-overlay {\r\n background: rgba(0, 0, 0, 0.8);\r\n}\r\n\r\n.modal-container {\r\n background: #fff;\r\n border-radius: 12px;\r\n width: 90%;\r\n max-width: 1200px;\r\n height: 90vh;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15);\r\n}\r\n\r\n.fullscreen {\r\n width: 100%;\r\n height: 100%;\r\n max-width: 100%;\r\n border-radius: 0;\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: 16px 20px;\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: 12px;\r\n}\r\n\r\n.header-icon {\r\n width: 32px;\r\n height: 32px;\r\n object-fit: contain;\r\n}\r\n\r\n.close-button {\r\n background: transparent;\r\n border: none;\r\n font-size: 24px;\r\n color: #666;\r\n cursor: pointer;\r\n padding: 4px 8px;\r\n line-height: 1;\r\n}\r\n\r\n.close-button:hover {\r\n color: #333;\r\n}\r\n\r\n/* 响应式 */\r\n@media screen and (max-width: 768px) {\r\n .modal-container {\r\n width: 100%;\r\n height: 100%;\r\n max-width: 100%;\r\n border-radius: 0;\r\n }\r\n\r\n .analysis-title {\r\n font-size: 18px;\r\n }\r\n\r\n .tab-container {\r\n flex-wrap: wrap;\r\n }\r\n\r\n .tab-button {\r\n padding: 6px 12px;\r\n font-size: 12px;\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.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 { PCM_DOMAIN, sendSSERequest } from '../../utils/utils';\r\nimport { ConversationStartEventData, StreamCompleteEventData, InterviewCompleteEventData } 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 { verifyApiKey } from '../../utils/utils';\r\n\r\n/**\r\n * 千岗千简历分析包装组件\r\n * 支持 optimizationType:\r\n * - 0: 直接改写(不使用此组件,使用 pcm-app-chat-modal)\r\n * - 1: 改进建议(发起流式请求后显示改进建议 iframe)\r\n * - 2: 深度分析(发起流式请求后显示包含三个 Tab 的分析视图)\r\n */\r\n\r\n@Component({\r\n tag: 'pcm-thousand-resume-wrapper',\r\n styleUrls: ['pcm-thousand-resume-wrapper.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ThousandResumeWrapper {\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 * 会话ID,传入继续对话,否则创建新会话\r\n */\r\n @Prop({ mutable: true }) conversationId?: string;\r\n\r\n /**\r\n * 机器人ID\r\n */\r\n @Prop() botId: string = '45444431062634496';\r\n\r\n /**\r\n * 优化类型<br>\r\n * 1: 改进建议 - 显示改进建议 iframe<br>\r\n * 2: 深度分析 - 显示包含三个 Tab 的分析视图(深度分析、改进建议、简历内容)\r\n */\r\n @Prop() optimizationType: number = 1;\r\n\r\n /**\r\n * 自定义输入参数\r\n */\r\n @Prop() customInputs: Record<string, any> = {};\r\n\r\n /**\r\n * 默认查询文本\r\n */\r\n @Prop() defaultQuery: string = '生成简历格式数据';\r\n\r\n /**\r\n * 模态框标题\r\n */\r\n @Prop() modalTitle: string = '千岗千简历';\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() fullscreen: boolean = false;\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 * 当点击模态框关闭时触发\r\n */\r\n @Event() modalClosed: EventEmitter<void>;\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() streamComplete: EventEmitter<StreamCompleteEventData>;\r\n\r\n /**\r\n * 当聊天完成时触发\r\n */\r\n @Event() interviewComplete: EventEmitter<InterviewCompleteEventData>;\r\n\r\n /**\r\n * 错误事件\r\n */\r\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\r\n\r\n /**\r\n * SDK密钥验证失败事件\r\n */\r\n @Event() tokenInvalid: EventEmitter<void>;\r\n\r\n @State() isLoading: boolean = true;\r\n @State() internalConversationId?: string;\r\n @State() error: string = '';\r\n @State() activeTab: 'analysis' | 'suggestions' | 'resume' = 'analysis';\r\n\r\n @Element() hostElement: HTMLElement;\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 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.isLoading = true;\r\n this.internalConversationId = undefined;\r\n this.error = '';\r\n this.activeTab = 'analysis';\r\n } else {\r\n await verifyApiKey(this.token);\r\n\r\n if (this.conversationId) {\r\n // 有历史会话ID,直接显示结果\r\n this.internalConversationId = this.conversationId;\r\n this.isLoading = false;\r\n } else {\r\n // 新会话,发起流式请求\r\n await this.startChatStream();\r\n }\r\n }\r\n }\r\n\r\n componentWillLoad() {\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 this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\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 componentDidLoad() {\r\n if (this.isOpen) {\r\n this.handleIsOpenChange(true);\r\n }\r\n }\r\n\r\n disconnectedCallback() {\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\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 startChatStream = async () => {\r\n this.isLoading = true;\r\n this.error = '';\r\n\r\n const requestData = {\r\n bot_id: this.botId,\r\n response_mode: 'streaming',\r\n conversation_id: this.conversationId,\r\n query: this.defaultQuery,\r\n inputs: {\r\n ...this.customInputs,\r\n optimization_type: this.optimizationType,\r\n },\r\n };\r\n\r\n let tempConversationId: string | undefined;\r\n\r\n await sendSSERequest({\r\n url: '/sdk/v1/chat/chat-messages',\r\n method: 'POST',\r\n data: requestData,\r\n onMessage: data => {\r\n // 获取 conversation_id\r\n if (data.conversation_id && !tempConversationId) {\r\n tempConversationId = data.conversation_id;\r\n this.internalConversationId = data.conversation_id;\r\n this.conversationStart.emit({\r\n conversation_id: data.conversation_id,\r\n event: data.event,\r\n message_id: data.message_id,\r\n id: data.id,\r\n });\r\n }\r\n\r\n // 检查任务结束\r\n if (data.event === 'node_finished' && data.data?.title?.includes('聘才猫任务结束')) {\r\n this.isLoading = false;\r\n this.interviewComplete.emit({\r\n conversation_id: this.internalConversationId,\r\n });\r\n }\r\n\r\n // 检查 message_end\r\n if (data.event === 'message_end') {\r\n this.streamComplete.emit({\r\n conversation_id: data.conversation_id || '',\r\n event: data.event,\r\n message_id: data.message_id,\r\n id: data.id,\r\n });\r\n }\r\n\r\n // 检查错误\r\n if (data.event === 'error') {\r\n this.isLoading = false;\r\n this.error = data.data?.message || data.message || '请求失败';\r\n ErrorEventBus.emitError({\r\n error: data.data,\r\n message: this.error,\r\n });\r\n }\r\n },\r\n onError: error => {\r\n console.error('SSE 请求错误:', error);\r\n this.isLoading = false;\r\n this.error = '请求失败,请重试';\r\n ErrorEventBus.emitError({\r\n error: error,\r\n message: this.error,\r\n });\r\n },\r\n onComplete: () => {\r\n this.isLoading = false;\r\n },\r\n });\r\n };\r\n\r\n /**\r\n * 重试按钮点击\r\n */\r\n private handleRetry = () => {\r\n this.startChatStream();\r\n };\r\n\r\n /**\r\n * Tab 切换\r\n */\r\n private handleTabChange = (tab: 'analysis' | 'suggestions' | 'resume') => {\r\n this.activeTab = tab;\r\n };\r\n\r\n render() {\r\n if (!this.isOpen) return null;\r\n\r\n const modalStyle = {\r\n zIndex: String(this.zIndex),\r\n };\r\n\r\n const containerClass = {\r\n 'modal-container': true,\r\n 'fullscreen': this.fullscreen,\r\n };\r\n\r\n const overlayClass = {\r\n 'modal-overlay': true,\r\n 'fullscreen-overlay': this.fullscreen,\r\n };\r\n\r\n const tabItems = [\r\n { key: 'analysis', label: '深度分析' },\r\n { key: 'suggestions', label: '改进建议' },\r\n { key: 'resume', label: '优化版本' },\r\n ];\r\n\r\n const iframeUrl = this.optimizationType === 1\r\n ? `${PCM_DOMAIN}/reportNode/thousandResume?conversationId=${this.internalConversationId}&referrer=sdk&reportType=suggestions&showHeader=1&token=${this.token}`\r\n : `${PCM_DOMAIN}/reportNode/thousandResume?conversationId=${this.internalConversationId}&referrer=sdk&reportType=${this.activeTab}&token=${this.token}`;\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 {/* Loading 状态 */}\r\n {this.isLoading && (\r\n <div class=\"loading-container\">\r\n <div class=\"loading-spinner\"></div>\r\n <p class=\"loading-text\">AI 正在分析您的简历</p>\r\n <p class=\"loading-subtext\">请耐心等待...</p>\r\n <div class=\"loading-dots\">\r\n <span class=\"dot\"></span>\r\n <span class=\"dot delay-1\"></span>\r\n <span class=\"dot delay-2\"></span>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* 错误状态 */}\r\n {!this.isLoading && this.error && (\r\n <div class=\"error-container\">\r\n <span class=\"error-icon\">!</span>\r\n <p class=\"error-text\">{this.error}</p>\r\n <button class=\"retry-button\" onClick={this.handleRetry}>重新分析</button>\r\n </div>\r\n )}\r\n\r\n {/* optimizationType=1: 改进建议 */}\r\n {!this.isLoading && !this.error && this.optimizationType === 1 && this.internalConversationId && (\r\n <div class=\"iframe-container\">\r\n <iframe src={iframeUrl} frameborder=\"0\"></iframe>\r\n </div>\r\n )}\r\n\r\n {/* optimizationType=2: 深度分析 */}\r\n {!this.isLoading && !this.error && this.optimizationType === 2 && this.internalConversationId && (\r\n <div class=\"analysis-container\">\r\n <div class=\"analysis-header\">\r\n <h1 class=\"analysis-title\">深度分析报告</h1>\r\n <p class=\"analysis-desc\">全面诊断 + 改进建议 + 优化版本</p>\r\n <div class=\"tab-container\">\r\n {tabItems.map(item => (\r\n <button\r\n class={{\r\n 'tab-button': true,\r\n 'active': this.activeTab === item.key\r\n }}\r\n onClick={() => this.handleTabChange(item.key as 'analysis' | 'suggestions' | 'resume')}\r\n >\r\n {item.label}\r\n </button>\r\n ))}\r\n </div>\r\n </div>\r\n <div class=\"iframe-container\">\r\n <iframe src={iframeUrl} frameborder=\"0\"></iframe>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 * 是否开启移动端上传\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/* 历史会话按钮 */\r\n.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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\nimport { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\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或customInputs.resume_content时,会隐藏简历上传区域。<br>\r\n * 传入customInputs.file_url(或customInputs.resume_content)和customInputs.type时,会直接开始聊天。<br>\r\n * customInputs.resume_content:可传入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 * 是否在上传界面显示历史会话按钮\r\n */\r\n @Prop() showInputHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历\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' = 'drawer';\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 @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: 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 readonly _historyConversationPageSize: number = 20;\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或resume_content)和type,直接显示聊天模态框\r\n if (this.conversationId || ((this.customInputs?.file_url || this.customInputs?.resume_content) && 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 loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations('3022316191018898', 'pcm-zygh-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\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/resume_content,也没有上传文件,则提示\r\n if (!this.customInputs?.file_url && !this.customInputs?.resume_content && !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 // 判断是否隐藏简历上传区域 - 当有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)和type\r\n const hasFileAndType = Boolean((this.customInputs?.file_url || this.customInputs?.resume_content) && 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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title=\"历史会话\">\r\n 历史会话\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle=\"历史会话\"\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>加载中...</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>暂无历史会话</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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.customInputs?.resume_content && !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} \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.header-history-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 4px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: transparent;\r\n color: #bbb;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-family: inherit;\r\n line-height: 1;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n white-space: nowrap;\r\n}\r\n\r\n.header-history-button svg {\r\n width: 16px;\r\n height: 16px;\r\n display: block;\r\n flex-shrink: 0;\r\n}\r\n\r\n.header-history-button:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n color: #666;\r\n}\r\n\r\n.header-history-button:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\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-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.header-history-entry {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n margin-left: 8px;\r\n padding: 4px 8px;\r\n border: none;\r\n border-radius: 4px;\r\n background: #e6f7ff;\r\n color: #1890ff;\r\n cursor: pointer;\r\n font-size: 12px;\r\n font-family: inherit;\r\n line-height: 1;\r\n white-space: nowrap;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.header-history-entry:hover {\r\n background: #bae7ff;\r\n color: #0958d9;\r\n transform: translateY(-1px);\r\n}\r\n\r\n.header-history-entry:focus-visible {\r\n outline: 2px solid rgba(13, 117, 251, 0.35);\r\n outline-offset: 2px;\r\n}\r\n\r\n.history-pagination {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 12px;\r\n padding: 12px 16px 16px;\r\n border-top: 1px solid #f0f0f0;\r\n}\r\n\r\n.history-pagination-button {\r\n min-width: 72px;\r\n padding: 6px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n background: #fff;\r\n color: #595959;\r\n cursor: pointer;\r\n font-size: 12px;\r\n transition: all 0.2s ease;\r\n}\r\n\r\n.history-pagination-button:hover:not(:disabled) {\r\n border-color: #1890ff;\r\n color: #1890ff;\r\n background: #e6f7ff;\r\n}\r\n\r\n.history-pagination-button:disabled {\r\n border-color: #f0f0f0;\r\n color: #bfbfbf;\r\n background: #fafafa;\r\n cursor: not-allowed;\r\n}\r\n\r\n.history-pagination-info {\r\n flex: 1;\r\n text-align: center;\r\n color: #8c8c8c;\r\n font-size: 12px;\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 border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n overflow: hidden;\r\n}\r\n\r\n.plan-type-option {\r\n flex: 1;\r\n border: none;\r\n border-right: 1px solid #d9d9d9;\r\n padding: 7px 8px;\r\n cursor: pointer;\r\n display: flex;\r\n flex-direction: row;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n transition:\r\n background-color 0.2s,\r\n color 0.2s;\r\n background-color: #fff;\r\n}\r\n\r\n.plan-type-option:last-child {\r\n border-right: none;\r\n}\r\n\r\n.plan-type-option:hover {\r\n background-color: #f0f7ff;\r\n}\r\n\r\n.plan-type-option.selected {\r\n background-color: #1890ff;\r\n}\r\n\r\n.plan-type-option.selected .option-icon,\r\n.plan-type-option.selected .option-label {\r\n color: #fff;\r\n}\r\n\r\n.option-icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.option-icon img {\r\n height: 18px;\r\n width: auto;\r\n}\r\n\r\n.option-label {\r\n font-size: 13px;\r\n font-weight: 500;\r\n color: #555;\r\n white-space: nowrap;\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.dynamic-form-section {\r\n margin-top: 20px;\r\n margin-bottom: 20px;\r\n}\r\n\r\n.form-fields {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n}\r\n\r\n.form-field {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.form-field label {\r\n font-weight: 600;\r\n color: #333;\r\n font-size: 14px;\r\n}\r\n\r\n.form-input {\r\n padding: 10px 12px;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.form-input:hover {\r\n border-color: #40a9ff;\r\n}\r\n\r\n.form-input:focus {\r\n border-color: #1890ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);\r\n}\r\n\r\n.form-input::placeholder {\r\n color: #bfbfbf;\r\n}\r\n\r\n.form-hint {\r\n font-size: 12px;\r\n color: #8c8c8c;\r\n line-height: 1.5;\r\n margin-top: -8px;\r\n padding: 8px 12px;\r\n background-color: #f5f5f5;\r\n border-radius: 4px;\r\n border-left: 3px solid #1890ff;\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\nimport { ConversationItem } from '../../interfaces/chat';\r\nimport { fetchHistoryConversations } from '../../utils/conversation-utils';\r\n\r\n/**\r\n * 职业规划助手\r\n */\r\n\r\nexport type CareerPlanType = '初入职场' | '转型建议' | '晋升路径';\r\n\r\n@Component({\r\n tag: 'pcm-zygh-v2-modal',\r\n styleUrls: ['../../global/global.css', 'pcm-zygh-v2-modal.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ZyghV2Modal {\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.type则可以指定规划类型,可传入\"初入职场\"、\"转型建议\"、\"晋升路径\"<br>\r\n * 传入customInputs.file_url或customInputs.resume_content时,会隐藏简历上传区域。<br>\r\n * 传入customInputs.file_url(或customInputs.resume_content)和customInputs.type时,会直接开始聊天。<br>\r\n * customInputs.resume_content:可传入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 * 是否在上传界面显示历史会话按钮\r\n */\r\n @Prop() showInputHistory: boolean = false;\r\n\r\n /**\r\n * 是否开启移动端上传简历\r\n */\r\n @Prop() mobileUploadAble: 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() 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' = 'drawer';\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 @State() isHistoryDrawerOpen: boolean = false;\r\n @State() historyConversations: ConversationItem[] = [];\r\n @State() isLoadingConversations: boolean = false;\r\n @State() historyConversationCursorStack: string[] = [''];\r\n @State() historyConversationPageIndex: number = 0;\r\n @State() hasMoreHistoryConversations: boolean = false;\r\n @State() targetPosition: string = ''; // 晋升目标岗位\r\n @State() industryName: string = ''; // 感兴趣的行业\r\n @State() jobPosition: string = ''; // 感兴趣的职位\r\n @State() timePeriod: string = ''; // 期望转型时间\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 readonly _historyConversationPageSize: number = 20;\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 @Watch('isOpen')\r\n async handleIsOpenChange(newValue: boolean) {\r\n if (!newValue) {\r\n // 重置状态\r\n this.showChatModal = false;\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或resume_content)和type,直接显示聊天模态框\r\n if (this.conversationId || ((this.customInputs?.file_url || this.customInputs?.resume_content) && this.customInputs?.type)) {\r\n this.showChatModal = true;\r\n }\r\n }\r\n }\r\n\r\n componentWillLoad() {\r\n // 将 zIndex 存入配置缓存\r\n if (this.zIndex) {\r\n configStore.setItem('modal-zIndex', this.zIndex);\r\n }\r\n if (this.token) {\r\n authStore.setToken(this.token);\r\n }\r\n verifyApiKey(this.token);\r\n\r\n // 添加全局token无效事件监听器\r\n this.tokenInvalidListener = () => {\r\n this.tokenInvalid.emit();\r\n };\r\n // 添加全局错误监听\r\n this.removeErrorListener = ErrorEventBus.addErrorListener(errorDetail => {\r\n this.someErrorEvent.emit(errorDetail);\r\n });\r\n document.addEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n }\r\n\r\n disconnectedCallback() {\r\n // 组件销毁时移除事件监听器\r\n document.removeEventListener('pcm-token-invalid', this.tokenInvalidListener);\r\n // 移除错误监听器\r\n if (this.removeErrorListener) {\r\n this.removeErrorListener();\r\n }\r\n }\r\n\r\n private handleClose = () => {\r\n this.modalClosed.emit();\r\n };\r\n\r\n private loadHistoryConversations = async (lastId: string, pageIndex: number): Promise<void> => {\r\n this.isLoadingConversations = true;\r\n const result = await fetchHistoryConversations('121182005294690304', 'pcm-zygh-v2-modal', lastId, this._historyConversationPageSize);\r\n const nextCursorStack = this.historyConversationCursorStack.slice(0, pageIndex + 1);\r\n\r\n if (result.hasMore && result.nextCursor) {\r\n nextCursorStack[pageIndex + 1] = result.nextCursor;\r\n }\r\n\r\n this.historyConversationCursorStack = nextCursorStack;\r\n this.historyConversationPageIndex = pageIndex;\r\n this.historyConversations = result.items;\r\n this.hasMoreHistoryConversations = result.hasMore;\r\n this.isLoadingConversations = false;\r\n };\r\n\r\n private handleInputHistoryClick = async () => {\r\n this.isHistoryDrawerOpen = true;\r\n this.historyConversationCursorStack = [''];\r\n await this.loadHistoryConversations('', 0);\r\n };\r\n\r\n private handleHistoryConversationPageChange = async (direction: 'prev' | 'next'): Promise<void> => {\r\n if (direction === 'prev') {\r\n if (this.historyConversationPageIndex === 0) {\r\n return;\r\n }\r\n\r\n const previousPageIndex = this.historyConversationPageIndex - 1;\r\n const previousCursor = this.historyConversationCursorStack[previousPageIndex] || '';\r\n await this.loadHistoryConversations(previousCursor, previousPageIndex);\r\n return;\r\n }\r\n\r\n if (!this.hasMoreHistoryConversations) {\r\n return;\r\n }\r\n\r\n const nextPageIndex = this.historyConversationPageIndex + 1;\r\n const nextCursor = this.historyConversationCursorStack[nextPageIndex];\r\n if (!nextCursor) {\r\n return;\r\n }\r\n\r\n await this.loadHistoryConversations(nextCursor, nextPageIndex);\r\n };\r\n\r\n private handleSelectConversation = (id: string) => {\r\n this.conversationId = id;\r\n this.isHistoryDrawerOpen = false;\r\n this.showChatModal = true;\r\n };\r\n\r\n private handlePlanTypeChange = (type: CareerPlanType) => {\r\n this.selectedPlanType = type;\r\n // 切换类型时重置表单字段\r\n this.targetPosition = '';\r\n this.industryName = '';\r\n this.jobPosition = '';\r\n this.timePeriod = '';\r\n };\r\n\r\n private handleStartPlanning = async () => {\r\n // 既没有预设 file_url/resume_content,也没有上传文件,则提示\r\n if (!this.customInputs?.file_url && !this.customInputs?.resume_content && !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 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 private getPlanTypeIcon = (type: CareerPlanType) => {\r\n const isSelected = this.selectedPlanType === type;\r\n const baseUrl = 'https://pcm-pub-1351162788.cos.ap-guangzhou.myqcloud.com/sdk/image/';\r\n const iconMap = {\r\n '初入职场': 'i_entry_level',\r\n '晋升路径': 'i_promotion',\r\n '转型建议': 'i_transition',\r\n };\r\n return `${baseUrl}${iconMap[type]}${isSelected ? '_actived' : ''}.png`;\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 // 判断是否隐藏简历上传区域 - 当有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)和type\r\n const hasFileAndType = Boolean((this.customInputs?.file_url || this.customInputs?.resume_content) && 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 {this.showInputHistory && (\r\n <button type=\"button\" class=\"header-history-entry\" onClick={this.handleInputHistoryClick} title=\"历史会话\">\r\n 历史会话\r\n </button>\r\n )}\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 {this.showInputHistory && (\r\n <pcm-drawer\r\n isOpen={this.isHistoryDrawerOpen}\r\n drawerTitle=\"历史会话\"\r\n width=\"400px\"\r\n onClosed={() => { this.isHistoryDrawerOpen = false; }}\r\n >\r\n <div class=\"history-drawer-content\">\r\n <div class=\"conversation-list\">\r\n {this.isLoadingConversations ? (\r\n <div class=\"loading-conversations\">\r\n <div class=\"loading-spinner-small\"></div>\r\n <p>加载中...</p>\r\n </div>\r\n ) : this.historyConversations.length === 0 ? (\r\n <div class=\"empty-conversations\">\r\n <p>暂无历史会话</p>\r\n </div>\r\n ) : (\r\n this.historyConversations.map(conversation => (\r\n <div\r\n key={conversation.id}\r\n class=\"conversation-item\"\r\n onClick={() => this.handleSelectConversation(conversation.id)}\r\n >\r\n <div class=\"conversation-info\">\r\n <div class=\"conversation-title\">{conversation.name}</div>\r\n <div class=\"conversation-meta\">\r\n <span class=\"conversation-time\">{conversation.timeDisplay}</span>\r\n {conversation.message_count > 0 && (\r\n <span class=\"message-count\">{conversation.message_count}条消息</span>\r\n )}\r\n {conversation.status && (\r\n <span class={{\r\n 'conversation-status': true,\r\n 'completed': conversation.status === '结束',\r\n 'running': conversation.status === '进行中',\r\n }}>\r\n {conversation.status}\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n ))\r\n )}\r\n </div>\r\n {!this.isLoadingConversations && (this.historyConversationPageIndex > 0 || this.hasMoreHistoryConversations) && (\r\n <div class=\"history-pagination\">\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={this.historyConversationPageIndex === 0} onClick={() => this.handleHistoryConversationPageChange('prev')}>\r\n 上一页\r\n </button>\r\n <span class=\"history-pagination-info\">第 {this.historyConversationPageIndex + 1} 页</span>\r\n <button type=\"button\" class=\"history-pagination-button\" disabled={!this.hasMoreHistoryConversations} onClick={() => this.handleHistoryConversationPageChange('next')}>\r\n 下一页\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n </pcm-drawer>\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 <div class=\"plan-type-section\">\r\n <label>选择建议类型</label>\r\n <div class=\"plan-type-options\">\r\n <div class={`plan-type-option ${this.selectedPlanType === '初入职场' ? 'selected' : ''}`} onClick={() => this.handlePlanTypeChange('初入职场')}>\r\n <div class=\"option-icon\">\r\n <img src={this.getPlanTypeIcon('初入职场')} alt=\"初入职场\" />\r\n </div>\r\n <div class=\"option-label\">初入职场</div>\r\n </div>\r\n <div class={`plan-type-option ${this.selectedPlanType === '晋升路径' ? 'selected' : ''}`} onClick={() => this.handlePlanTypeChange('晋升路径')}>\r\n <div class=\"option-icon\">\r\n <img src={this.getPlanTypeIcon('晋升路径')} alt=\"晋升路径\" />\r\n </div>\r\n <div class=\"option-label\">晋升路径</div>\r\n </div>\r\n <div class={`plan-type-option ${this.selectedPlanType === '转型建议' ? 'selected' : ''}`} onClick={() => this.handlePlanTypeChange('转型建议')}>\r\n <div class=\"option-icon\">\r\n <img src={this.getPlanTypeIcon('转型建议')} alt=\"转型建议\" />\r\n </div>\r\n <div class=\"option-label\">转型建议</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* 动态表单字段 */}\r\n <div class=\"dynamic-form-section\">\r\n {this.selectedPlanType === '初入职场' && (\r\n <div class=\"form-fields\">\r\n <div class=\"form-field\">\r\n <label>感兴趣的行业</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的行业\"\r\n value={this.industryName}\r\n onInput={e => (this.industryName = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-field\">\r\n <label>感兴趣的职位</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的职位\"\r\n value={this.jobPosition}\r\n onInput={e => (this.jobPosition = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-hint\">为确保职业规划报告的准确性,推荐您至少填写其中一项</div>\r\n </div>\r\n )}\r\n {this.selectedPlanType === '转型建议' && (\r\n <div class=\"form-fields\">\r\n <div class=\"form-field\">\r\n <label>感兴趣的行业</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的行业\"\r\n value={this.industryName}\r\n onInput={e => (this.industryName = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-field\">\r\n <label>感兴趣的职位</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您感兴趣的职位\"\r\n value={this.jobPosition}\r\n onInput={e => (this.jobPosition = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-hint\">为确保职业规划报告的准确性,推荐您至少填写其中一项</div>\r\n <div class=\"form-field\">\r\n <label>期望转型时间</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您期望的转型时间\"\r\n value={this.timePeriod}\r\n onInput={e => (this.timePeriod = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {this.selectedPlanType === '晋升路径' && (\r\n <div class=\"form-fields\">\r\n <div class=\"form-field\">\r\n <label>晋升目标岗位</label>\r\n <input\r\n type=\"text\"\r\n class=\"form-input\"\r\n placeholder=\"请输入您的晋升目标岗位\"\r\n value={this.targetPosition}\r\n onInput={e => (this.targetPosition = (e.target as HTMLInputElement).value)}\r\n />\r\n </div>\r\n <div class=\"form-hint\">为确保职业规划报告的准确性,建议您填写晋升目标岗位名称</div>\r\n </div>\r\n )}\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.customInputs?.resume_content && !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\">\r\n Hunan-PinCaiMao-202412310003\r\n </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=\"121182005294690304\"\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 ...(this.industryName ? { industry_name: this.industryName } : {}),\r\n ...(this.targetPosition || this.jobPosition ? { target_position: this.targetPosition || this.jobPosition } : {}),\r\n ...(this.timePeriod ? { time_period: this.timePeriod } : {}),\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}\r\n"],"mappings":"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","ignoreList":[]}
|