pcm-agents 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{components-chat-message_33.cjs.entry.js → components-chat-message_34.cjs.entry.js} +5990 -4059
- package/dist/cjs/components-chat-message_34.cjs.entry.js.map +1 -0
- package/dist/cjs/{conversation-utils-B4jUfmtU.js → conversation-utils-DGL5uGhS.js} +4 -4
- package/dist/cjs/{conversation-utils-B4jUfmtU.js.map → conversation-utils-DGL5uGhS.js.map} +1 -1
- package/dist/cjs/{index-Dghp_NL6.js → index-CUDWXBQ4.js} +3 -3
- package/dist/cjs/{index-Dghp_NL6.js.map → index-CUDWXBQ4.js.map} +1 -1
- package/dist/cjs/index-C_qhED9Z.js +6 -6
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/oem-htws-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-jd-modal.cjs.entry.js +2 -2
- package/dist/cjs/oem-jlpp-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-jlzz-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-mnct-modal.cjs.entry.js +1 -1
- package/dist/cjs/oem-qgqjl-modal.cjs.entry.js +3 -3
- package/dist/cjs/pcm-agents.cjs.js +1 -1
- package/dist/cjs/pcm-hr-chat-modal.cjs.entry.js +2 -2
- package/dist/cjs/pcm-jlsx-modal.cjs.entry.js +2 -2
- package/dist/cjs/{oem-mnms-modal.cjs.entry.js → pcm-mnms-modal.cjs.entry.js} +41 -156
- package/dist/cjs/pcm-mnms-modal.cjs.entry.js.map +1 -0
- package/dist/cjs/pcm-mnms-modal.entry.cjs.js.map +1 -0
- package/dist/cjs/{sentry-reporter-CgJowDyu.js → sentry-reporter-DsoYs8_e.js} +3 -3
- package/dist/cjs/{sentry-reporter-CgJowDyu.js.map → sentry-reporter-DsoYs8_e.js.map} +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/components-oem-virtual-chat-modal/components-oem-virtual-chat-modal.css +1111 -0
- package/dist/collection/components/components-oem-virtual-chat-modal/components-oem-virtual-chat-modal.js +2334 -0
- package/dist/collection/components/components-oem-virtual-chat-modal/components-oem-virtual-chat-modal.js.map +1 -0
- package/dist/collection/components/oem-mnms-modal/oem-mnms-modal.js +2 -2
- package/dist/collection/components/oem-mnms-modal/oem-mnms-modal.js.map +1 -1
- package/dist/components/components-chat-message.js +1 -1
- package/dist/components/components-digital-human.js +1 -1
- package/dist/components/components-export-records-modal.js +1 -1
- package/dist/components/components-mobile-input-btn.js +1 -1
- package/dist/components/components-mobile-upload-btn.js +1 -1
- package/dist/components/components-oem-virtual-chat-modal.d.ts +11 -0
- package/dist/components/components-oem-virtual-chat-modal.js +9 -0
- package/dist/components/components-oem-virtual-chat-modal.js.map +1 -0
- package/dist/components/components-position-selector.js +1 -1
- package/dist/components/components-thousand-resume-wrapper.js +1 -1
- package/dist/components/components-upload.js +1 -1
- package/dist/components/components-voice-input-btn.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/oem-htws-modal.js +5 -5
- package/dist/components/oem-jd-modal.js +5 -5
- package/dist/components/oem-jlpp-modal.js +7 -7
- package/dist/components/oem-jlsx-modal.js +5 -5
- package/dist/components/oem-jlzz-modal.js +5 -5
- package/dist/components/oem-mnct-modal.js +7 -7
- package/dist/components/oem-mnms-modal.js +14 -14
- package/dist/components/oem-mnms-modal.js.map +1 -1
- package/dist/components/oem-qgqjl-modal.js +9 -9
- package/dist/components/oem-zygh-modal.js +5 -5
- package/dist/components/{p-BhdGTSLg.js → p-BCFZkcSd.js} +5 -5
- package/dist/components/{p-BhdGTSLg.js.map → p-BCFZkcSd.js.map} +1 -1
- package/dist/components/p-BG83hpwD.js +1910 -0
- package/dist/components/p-BG83hpwD.js.map +1 -0
- package/dist/components/{p-BDEiyYVl.js → p-BQcztM0Y.js} +3 -3
- package/dist/components/{p-BDEiyYVl.js.map → p-BQcztM0Y.js.map} +1 -1
- package/dist/components/{p-DJDJfWq9.js → p-BZPf0rl6.js} +3 -3
- package/dist/components/{p-DJDJfWq9.js.map → p-BZPf0rl6.js.map} +1 -1
- package/dist/components/{p-D4RnNrxx.js → p-BgwHiYHx.js} +3 -3
- package/dist/components/{p-D4RnNrxx.js.map → p-BgwHiYHx.js.map} +1 -1
- package/dist/components/{p-Bg0KKnpU.js → p-BqXnsrve.js} +3 -3
- package/dist/components/{p-Bg0KKnpU.js.map → p-BqXnsrve.js.map} +1 -1
- package/dist/components/{p-C7ubjB1x.js → p-CL_Guy01.js} +3 -3
- package/dist/components/{p-C7ubjB1x.js.map → p-CL_Guy01.js.map} +1 -1
- package/dist/components/{p-C-lvK9NX.js → p-CNFdfFMH.js} +3 -3
- package/dist/components/{p-C-lvK9NX.js.map → p-CNFdfFMH.js.map} +1 -1
- package/dist/components/{p-CzFKth7J.js → p-Cbaqx3Tt.js} +3 -3
- package/dist/components/{p-CzFKth7J.js.map → p-Cbaqx3Tt.js.map} +1 -1
- package/dist/components/{p-oVAdweom.js → p-DFDjQmKS.js} +3 -3
- package/dist/components/{p-oVAdweom.js.map → p-DFDjQmKS.js.map} +1 -1
- package/dist/components/{p-CB7myOe_.js → p-DNi0tT01.js} +3 -3
- package/dist/components/{p-CB7myOe_.js.map → p-DNi0tT01.js.map} +1 -1
- package/dist/components/{p-i4wY2JnB.js → p-Dc3NvH9p.js} +4 -4
- package/dist/components/{p-i4wY2JnB.js.map → p-Dc3NvH9p.js.map} +1 -1
- package/dist/components/{p-CPq5-i_-.js → p-DiLmXw24.js} +4 -4
- package/dist/components/{p-CPq5-i_-.js.map → p-DiLmXw24.js.map} +1 -1
- package/dist/components/{p-CEu-bFot.js → p-VwrhX6KG.js} +3 -3
- package/dist/components/{p-CEu-bFot.js.map → p-VwrhX6KG.js.map} +1 -1
- package/dist/components/pcm-1zhanshi-mnms-modal.js +5 -5
- package/dist/components/pcm-app-chat-modal.js +1 -1
- package/dist/components/pcm-ats-mnms-modal.js +5 -5
- package/dist/components/pcm-card.js +1 -1
- package/dist/components/pcm-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 +6 -6
- 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-msbg-modal.js +5 -5
- package/dist/components/pcm-qgqjl-modal.js +9 -9
- 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-chat-message_33.entry.js → components-chat-message_34.entry.js} +5989 -4059
- package/dist/esm/components-chat-message_34.entry.js.map +1 -0
- package/dist/esm/{conversation-utils-CLO35DHR.js → conversation-utils-DJr3w2Gu.js} +4 -4
- package/dist/esm/{conversation-utils-CLO35DHR.js.map → conversation-utils-DJr3w2Gu.js.map} +1 -1
- package/dist/esm/index-Bq0K-WqZ.js +6 -6
- package/dist/esm/{index-KVnu9w-h.js → index-DcQZ0v3S.js} +4 -4
- package/dist/esm/{index-KVnu9w-h.js.map → index-DcQZ0v3S.js.map} +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/oem-htws-modal.entry.js +1 -1
- package/dist/esm/oem-jd-modal.entry.js +2 -2
- package/dist/esm/oem-jlpp-modal.entry.js +1 -1
- package/dist/esm/oem-jlzz-modal.entry.js +1 -1
- package/dist/esm/oem-mnct-modal.entry.js +1 -1
- package/dist/esm/oem-qgqjl-modal.entry.js +3 -3
- package/dist/esm/pcm-agents.js +1 -1
- package/dist/esm/pcm-hr-chat-modal.entry.js +2 -2
- package/dist/esm/pcm-jlsx-modal.entry.js +2 -2
- package/dist/esm/{oem-mnms-modal.entry.js → pcm-mnms-modal.entry.js} +41 -156
- package/dist/esm/pcm-mnms-modal.entry.js.map +1 -0
- package/dist/esm/{sentry-reporter-B4aHQq-A.js → sentry-reporter-N0y2nHh5.js} +3 -3
- package/dist/esm/{sentry-reporter-B4aHQq-A.js.map → sentry-reporter-N0y2nHh5.js.map} +1 -1
- package/dist/pcm-agents/index.esm.js +1 -1
- package/dist/pcm-agents/{p-eb9b355e.entry.js → p-317ec555.entry.js} +2 -2
- package/dist/pcm-agents/p-3f0d27cf.entry.js +8 -0
- package/dist/pcm-agents/p-3f0d27cf.entry.js.map +1 -0
- package/dist/pcm-agents/{p-aa606968.entry.js → p-57993edb.entry.js} +2 -2
- package/dist/pcm-agents/{p-e2b9a9f2.entry.js → p-7c1e7e5a.entry.js} +2 -2
- package/dist/pcm-agents/{p-Bktjt_YJ.js → p-C3qMuJRQ.js} +2 -2
- package/dist/pcm-agents/{p-Bktjt_YJ.js.map → p-C3qMuJRQ.js.map} +1 -1
- package/dist/pcm-agents/p-Ch9kExOi.js +2 -0
- package/dist/pcm-agents/{p-B4ClCdh9.js.map → p-Ch9kExOi.js.map} +1 -1
- package/dist/pcm-agents/{p-CMfzTNOk.js → p-b8oixHud.js} +2 -2
- package/dist/pcm-agents/{p-CMfzTNOk.js.map → p-b8oixHud.js.map} +1 -1
- package/dist/pcm-agents/{p-4d7511e0.entry.js → p-babf3d55.entry.js} +2 -2
- package/dist/pcm-agents/{p-efb4e819.entry.js → p-c2dc4dcd.entry.js} +2 -2
- package/dist/pcm-agents/p-ca1f514b.entry.js +2 -0
- package/dist/pcm-agents/p-ca1f514b.entry.js.map +1 -0
- package/dist/pcm-agents/{p-8256890d.entry.js → p-cdcdec03.entry.js} +2 -2
- package/dist/pcm-agents/{p-8144f0d4.entry.js → p-e13e3325.entry.js} +2 -2
- package/dist/pcm-agents/{p-dd6362f0.entry.js → p-f666e503.entry.js} +2 -2
- package/dist/pcm-agents/pcm-agents.esm.js +1 -1
- package/dist/pcm-agents/pcm-mnms-modal.entry.esm.js.map +1 -0
- package/dist/types/components/components-oem-virtual-chat-modal/components-oem-virtual-chat-modal.d.ts +290 -0
- package/dist/types/components.d.ts +186 -0
- package/package.json +1 -1
- package/dist/cjs/components-chat-message_33.cjs.entry.js.map +0 -1
- package/dist/cjs/oem-mnms-modal.cjs.entry.js.map +0 -1
- package/dist/cjs/oem-mnms-modal.entry.cjs.js.map +0 -1
- package/dist/esm/components-chat-message_33.entry.js.map +0 -1
- package/dist/esm/oem-mnms-modal.entry.js.map +0 -1
- package/dist/pcm-agents/oem-mnms-modal.entry.esm.js.map +0 -1
- package/dist/pcm-agents/p-7e8bdfa6.entry.js +0 -2
- package/dist/pcm-agents/p-7e8bdfa6.entry.js.map +0 -1
- package/dist/pcm-agents/p-B4ClCdh9.js +0 -2
- package/dist/pcm-agents/p-f6683f29.entry.js +0 -8
- package/dist/pcm-agents/p-f6683f29.entry.js.map +0 -1
- /package/dist/pcm-agents/{p-eb9b355e.entry.js.map → p-317ec555.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-aa606968.entry.js.map → p-57993edb.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-e2b9a9f2.entry.js.map → p-7c1e7e5a.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-4d7511e0.entry.js.map → p-babf3d55.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-efb4e819.entry.js.map → p-c2dc4dcd.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-8256890d.entry.js.map → p-cdcdec03.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-8144f0d4.entry.js.map → p-e13e3325.entry.js.map} +0 -0
- /package/dist/pcm-agents/{p-dd6362f0.entry.js.map → p-f666e503.entry.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["webpackUniversalModuleDefinition","root","factory","module","exports","this","__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","type","document","execCommand","err","ClipboardActionCut","target","selectedText","actions_cut","createFakeElement","value","isRTL","documentElement","getAttribute","fakeElement","createElement","style","fontSize","border","padding","margin","position","yPosition","window","pageYOffset","scrollTop","top","concat","setAttribute","fakeCopyAction","options","container","appendChild","remove","ClipboardActionCopy","arguments","length","undefined","body","HTMLInputElement","includes","actions_copy","_typeof","obj","Symbol","iterator","constructor","prototype","ClipboardActionDefault","_options$action","action","text","Error","nodeType","hasAttribute","actions_default","clipboard_typeof","_classCallCheck","instance","Constructor","TypeError","_defineProperties","props","i","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","protoProps","staticProps","_inherits","subClass","superClass","create","_setPrototypeOf","o","p","setPrototypeOf","__proto__","_createSuper","Derived","hasNativeReflectConstruct","_isNativeReflectConstruct","_createSuperInternal","Super","_getPrototypeOf","result","NewTarget","Reflect","construct","apply","_possibleConstructorReturn","self","call","_assertThisInitialized","ReferenceError","sham","Proxy","Date","toString","e","getPrototypeOf","getAttributeValue","suffix","element","attribute","Clipboard","_Emitter","_super","trigger","_this","resolveOptions","listenClick","defaultAction","defaultTarget","defaultText","_this2","listener","onClick","delegateTarget","currentTarget","emit","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","addEventListener","removeEventListener","delegate","elements","bind","querySelectorAll","Array","map","node","HTMLElement","nodeList","string","String","fn","is","listenNode","listenNodeList","listenSelector","select","nodeName","isReadOnly","setSelectionRange","removeAttribute","selection","range","createRange","selectNodeContents","addRange","E","on","name","ctx","push","once","off","_","data","slice","evtArr","len","evts","liveEvents","TinyEmitter","__webpack_module_cache__","moduleId","getter","__esModule","a","definition","get","prop","hasOwnProperty","markdownCss","componentsChatMessageCss","hostCss","componentsConfirmModalCss","ComponentsConfirmModal","isOpen","modalTitle","okText","cancelText","okType","maskClosable","mask","centered","ok","cancel","closed","afterOpen","afterClose","zIndex","bodyOverflowBeforeOpen","transitionEndHandler","open","close","visibleChanged","newValue","overflow","modal","hostElement","shadowRoot","componentWillLoad","cachedZIndex","configStore","getItem","disconnectedCallback","handleMaskClick","handleCancel","handleOk","render","modalStyle","maskStyle","containerClass","contentClass","okButtonClass","h","class","componentsDigitalHumanCss","componentsDrawerCss","ComponentsDrawer","drawerTitle","width","height","closable","drawer","handleClose","drawerStyle","componentsExportRecordsModalCss","DEFAULT_PAGINATION","page","size","EXPORT_BATCH_STATUS_MAP","color","ComponentsExportRecordsModal","botId","sourceId","loading","pagination","showMessage","messageText","messageType","watchOpen","fetchData","response","sendHttpRequest","url","method","params","bot_id","source_id","success","records","total","error","console","handleDownload","record","downloadUrl","getCosPresignedUrl","cos_key","fileName","file_name","link","href","click","showMessageToast","handleDelete","id","setTimeout","message","handleRefresh","handlePageChange","newPagination","formatDate","dateString","date","toLocaleString","year","month","day","hour","minute","second","renderEmpty","renderTag","status","statusInfo","backgroundColor","renderButton","variant","renderTable","textAlign","created_at","renderPagination","totalPages","Math","ceil","currentPage","disabled","onChange","parseInt","selected","renderMessage","stopPropagation","componentsMessageCss","ComponentsMessage","content","duration","visible","timer","componentDidLoad","clearTimeout","show","el","removeChild","renderIcon","viewBox","fill","qrcode","typeNumber","errorCorrectionLevel","PAD0","PAD1","_typeNumber","_errorCorrectionLevel","QRErrorCorrectionLevel","_modules","_moduleCount","_dataCache","_dataList","makeImpl","test","maskPattern","moduleCount","modules","row","col","setupPositionProbePattern","setupPositionAdjustPattern","setupTimingPattern","setupTypeInfo","setupTypeNumber","createData","mapData","r","c","getBestMaskPattern","minLostPoint","pattern","lostPoint","QRUtil","getLostPoint","pos","getPatternPosition","j","bits","getBCHTypeNumber","mod","floor","getBCHTypeInfo","inc","bitIndex","byteIndex","maskFunc","getMaskFunction","dark","createBytes","buffer","rsBlocks","offset","maxDcCount","maxEcCount","dcdata","ecdata","dcCount","dataCount","ecCount","totalCount","max","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","alt","title","opts","mc","mr","qrSvg","rect","scalable","escapeXml","join","trim","createDataURL","min","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","match","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","async","onOk","onError","componentsMobileInputBtnCss","globalCss","ComponentsMobileInputBtn","rows","maxLength","uploadHeaders","uploadParams","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","Message","info","src","marginTop","navigator","writeText","then","catch","readOnly","componentsMobileUploadBtnCss","ComponentsMobileUploadBtn","multiple","acceptFileSuffixList","maxFileCount","Infinity","maxFileSize","uploadAreaMode","defaultFileList","uploadText","mobileUploadFiles","getIsUploading","clearSelectedFiles","file_list","tags","isArray","is_knowledge_doc","maxSize","maxCount","customAccept","clearValue","filter","it","handleOpenUpload","item","event","componentsPositionSelectorCss","componentsThousandResumeWrapperCss","ComponentsThousandResumeWrapper","token","conversationId","optimizationType","customInputs","defaultQuery","icon","fullscreen","isShowHeader","isNeedClose","modalClosed","conversationStart","streamComplete","interviewComplete","someErrorEvent","tokenInvalid","isLoading","internalConversationId","activeTab","tokenInvalidListener","removeErrorListener","handleTokenChange","newToken","authStore","getToken","setToken","handleIsOpenChange","verifyApiKey","startChatStream","setItem","ErrorEventBus","addErrorListener","errorDetail","requestData","response_mode","conversation_id","query","inputs","optimization_type","tempConversationId","sendSSERequest","onMessage","message_id","emitError","onComplete","handleRetry","handleTabChange","tab","overlayClass","tabItems","label","iframeUrl","frameborder","active","componentsUploadCss","ComponentsUpload","mobileUploadAble","uploadFailed","uploadChange","selectedFiles","file","state","FileUploadState","Success","some","Uploading","clearSelectedFile","handleUploadClick","fileInput","uploadFile","uploadFileToBackend","file_size","SentryReporter","captureError","component","Failed","handleFileChange","input","files","from","currentFileCount","remainingSlots","validFiles","invalidFiles","split","pop","toLowerCase","supportedFormats","maxSizeText","formatFileSize","newFileItems","uploadResult","targetIndex","emitUploadChange","ext","uploadBtn","detail","textDecoration","marginLeft","itemIndex","componentsVoiceInputBtnCss","ComponentsVoiceInputBtn","maxRecordingTime","locale","voiceRecognized","voiceStatusChange","_status","_recordingTimeLeft","_audioRecorder","_audioStream","_audioChunks","_audioMimeType","_recordingStartTime","_recordingTimer","_releaseRecordingResources","_getText","zhText","enText","_setStatus","_emitError","_handleClick","_stopRecording","mediaDevices","getUserMedia","MediaRecorder","audio","stream","_startRecording","supportedMimeType","getSupportedAudioMimeType","mimeType","ondataavailable","onerror","onstop","_stopMediaStream","_processAudioRecording","start","setInterval","elapsedTime","_clearRecordingTimer","stop","audioBlob","Blob","extension","_getFileExtension","audioFile","File","fileInfo","transcriptionText","convertAudioToText","clearInterval","getTracks","track","isRecording","isConverting","recording","converting","cx","cy","oemJlsxModalCss","oemZyghModalCss","OemZyghModal","showWorkspaceHistory","uploadSuccess","planningComplete","sendSmsCodeRequest","filePreviewMode","isUploading","uploadedFileInfo","showChatModal","isSubmitting","selectedPlanType","targetPosition","industryName","jobPosition","timePeriod","phoneNumber","verificationCode","isSendingCode","countdown","isVerifyingCode","pcmUploadRef","countdownTimer","handlePlanTypeChange","handlePhoneNumberChange","handleVerificationCodeChange","startCountdown","handleSendCode","phoneRegex","mobile","codeType","handleStartPlanning","file_url","verifySmsCode","handlePlanningComplete","getPlanTypeIcon","isSelected","baseUrl","iconMap","disableResumeUpload","Boolean","placeholder","onInput","rel","phone","industry_name","target_position","time_period","interviewMode","onInterviewComplete","pcm1zhanshiMnmsModalCss","ZhanshiMnmsModal","waitingTime","digitalId","openingIndex","enableVirtualHuman","showEndInterviewButton","playbackRate","recordingError","selectedFile","jobDescription","virtualChatModalRef","setComponentActive","resetState","ref","job_info","ai_interview_type","pcmAppChatModalCss","pcmAtsMnmsModalCss","AtsMnmsModal","interview_type","pcmButtonCss","PcmButton","shape","textColor","borderColor","borderRadius","block","borderStyle","classes","customStyle","keys","pcmCardCss","PcmCard","cardTitle","description","iconUrl","author","authorAvatarUrl","showChatTag","customChatTag","useButtonText","botData","watchBotIdHandler","fetchBotData","desc","iconFromBot","logo","authorName","author_name","authorAvatar","author_avatar","hasChatTag","flag","usersCount","use_count","starsCount","follow_count","usageCount","view_count","log","userIconUrl","pcmHtwsModalCss","HtwsModal","showInputHistory","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","stroke","onUploadChange","pcmHyzjModalCss","HyzjModal","alert","hideFileUpload","pcmJdModalCss","PcmJdModal","showSaveJdButton","saveJdButtonText","strings","step","jobName","isVoiceInputActive","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","handleVoiceRecognized","cursorPosition","selectionStart","beforeCursor","afterCursor","spacer","requestAnimationFrame","newPosition","handleVoiceStatusChange","handleVoiceInputError","handleNextStep","alerts","enterJobName","handlePositionAnalysis","handlePrevStep","input_info","workflow_code","outputs","jsonText","markdownJsonMatch","parsedOutput","JSON","parse","tagGroup","initialSelectedTags","shuffled","group","allTags","defaultTags","optionalTags","random","dimensionName","handleTagClick","category","currentTags","newTags","t","handleAITagClick","tag","handleSubmitStructured","salaryRange","find","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","onVoiceRecognized","onVoiceStatusChange","onSomeErrorEvent","inputGuideTitle","inputGuide","jobTitle","responsibilities","qualifications","location","aiDisclaimer","beianLabel","beianNumber","loadingConversation","pcmJlppModalCss","JlppModal","mobileJdInputAble","resume_content","handleJobDescriptionChange","handleStartAnalysis","hideJdInput","hideResumeUpload","hasFileAndJob","pcmJlzzModalCss","pcmMnctModalCss","MnctModal","questionNumber","canOutputAnalysis","handleQuestionNumberChange","handleAnalysisToggle","checked","uploadResume","enterJobDescription","jobDescriptionLabel","jobDescriptionPlaceholder","resumeUploadLabel","questionNumberLabel","questionUnit","analysisToggleLabel","toggleOn","toggleOff","startAnalysis","question_number","can_outputAnalysis","pcmMnmsModalCss","MnmsModal","skipResumeUpload","showCopyButton","showFeedbackButtons","pcmMnmsZpModalCss","MnmsZpModal","pcmMsbgModalCss","MsbgModal","file_urls","file_names","pcmQgqjlModalCss","pcmVirtualChatModalCss","pcmZskChatModalCss","pcmZyghModalCss","ZyghModal","hasFileAndType","pcmZyghV2ModalCss","ZyghV2Modal"],"sources":["node_modules/.pnpm/clipboard@2.0.11/node_modules/clipboard/dist/clipboard.js","src/global/markdown.css?tag=components-chat-message&encapsulation=shadow","src/components/components-chat-message/components-chat-message.css?tag=components-chat-message&encapsulation=shadow","src/global/host.css?tag=components-chat-message&encapsulation=shadow","src/components/components-confirm-modal/components-confirm-modal.css?tag=components-confirm-modal&encapsulation=shadow","src/global/host.css?tag=components-confirm-modal&encapsulation=shadow","src/components/components-confirm-modal/components-confirm-modal.tsx","src/components/components-digital-human/components-digital-human.css?tag=components-digital-human&encapsulation=shadow","src/global/host.css?tag=components-digital-human&encapsulation=shadow","src/components/components-drawer/components-drawer.css?tag=components-drawer&encapsulation=shadow","src/global/host.css?tag=components-drawer&encapsulation=shadow","src/components/components-drawer/components-drawer.tsx","src/components/components-export-records-modal/components-export-records-modal.css?tag=components-export-records-modal&encapsulation=shadow","src/components/components-export-records-modal/components-export-records-modal.tsx","src/components/components-message/components-message.css?tag=components-message&encapsulation=shadow","src/global/host.css?tag=components-message&encapsulation=shadow","src/components/components-message/components-message.tsx","node_modules/.pnpm/qrcode-generator@2.0.4/node_modules/qrcode-generator/dist/qrcode.js","src/components/components-mobile-input-btn/uploadNumberSDK.ts","src/components/components-mobile-input-btn/components-mobile-input-btn.css?tag=components-mobile-input-btn&encapsulation=shadow","src/global/global.css?tag=components-mobile-input-btn&encapsulation=shadow","src/global/host.css?tag=components-mobile-input-btn&encapsulation=shadow","src/components/components-mobile-input-btn/components-mobile-input-btn.tsx","src/components/components-mobile-upload-btn/uploadNumberSDK.ts","src/components/components-mobile-upload-btn/components-mobile-upload-btn.css?tag=components-mobile-upload-btn&encapsulation=shadow","src/global/global.css?tag=components-mobile-upload-btn&encapsulation=shadow","src/global/host.css?tag=components-mobile-upload-btn&encapsulation=shadow","src/components/components-mobile-upload-btn/components-mobile-upload-btn.tsx","src/components/components-position-selector/components-position-selector.css?tag=components-position-selector&encapsulation=shadow","src/global/global.css?tag=components-position-selector&encapsulation=shadow","src/components/components-thousand-resume-wrapper/components-thousand-resume-wrapper.css?tag=components-thousand-resume-wrapper&encapsulation=shadow","src/global/global.css?tag=components-thousand-resume-wrapper&encapsulation=shadow","src/global/host.css?tag=components-thousand-resume-wrapper&encapsulation=shadow","src/components/components-thousand-resume-wrapper/components-thousand-resume-wrapper.tsx","src/components/components-upload/components-upload.css?tag=components-upload&encapsulation=shadow","src/global/global.css?tag=components-upload&encapsulation=shadow","src/global/host.css?tag=components-upload&encapsulation=shadow","src/components/components-upload/components-upload.tsx","src/components/components-voice-input-btn/components-voice-input-btn.css?tag=components-voice-input-btn&encapsulation=shadow","src/components/components-voice-input-btn/components-voice-input-btn.tsx","src/global/global.css?tag=oem-jlsx-modal&encapsulation=shadow","src/components/oem-jlsx-modal/oem-jlsx-modal.css?tag=oem-jlsx-modal&encapsulation=shadow","src/global/markdown.css?tag=oem-jlsx-modal&encapsulation=shadow","src/global/host.css?tag=oem-jlsx-modal&encapsulation=shadow","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","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/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-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","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-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":["/*!\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: 'components-confirm-modal',\r\n styleUrls: ['components-confirm-modal.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsConfirmModal {\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 min-width: 0;\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.drawer-header-actions {\r\n display: flex;\r\n align-items: center;\r\n flex: 0 0 auto;\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: 'components-drawer',\r\n styleUrls: ['components-drawer.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsDrawer {\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 <div class=\"drawer-header-actions\">\r\n <slot name=\"header-actions\"></slot>\r\n </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: flex-start;\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: 'components-export-records-modal',\r\n styleUrl: 'components-export-records-modal.css',\r\n shadow: true,\r\n})\r\nexport class ComponentsExportRecordsModal {\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}",".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: 'components-message',\r\n styleUrls: ['components-message.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsMessage {\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} ","//---------------------------------------------------------------------\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: 5vh auto auto 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: 'components-mobile-input-btn',\r\n styleUrls: ['components-mobile-input-btn.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsMobileInputBtn {\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;",".upload-area {\r\n max-height: 300px;\r\n overflow-y: auto;\r\n}\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.upload-placeholder {\r\n width: 100%;\r\n cursor: pointer;\r\n}\r\n\r\n.upload-placeholder img {\r\n display: block;\r\n margin: 0 auto;\r\n}\r\n\r\n.upload-placeholder p {\r\n text-align: center;\r\n}\r\n\r\n.upload-text {\r\n margin: 8px 0;\r\n}\r\n\r\n.upload-hint {\r\n font-size: 12px;\r\n color: #999999;\r\n}\r\n\r\n.file-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 8px 0;\r\n}\r\n\r\n.file-item-content {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n}\r\n\r\n.file-name {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.remove-file {\r\n border: 0;\r\n background: transparent;\r\n cursor: pointer;\r\n font-size: 18px;\r\n}\r\n\r\n.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: 5vh auto auto 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, Method } from \"@stencil/core\";\r\nimport { FileUploadResponse, 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: 'components-mobile-upload-btn',\r\n styleUrls: ['components-mobile-upload-btn.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsMobileUploadBtn {\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, unknown>;\r\n /**\r\n * 上传请求参数\r\n */\r\n @Prop() uploadParams?: Record<string, unknown>;\r\n /**\r\n * 是否使用上传区域样式\r\n */\r\n @Prop() uploadAreaMode: boolean = false;\r\n /**\r\n * 是否禁用上传\r\n */\r\n @Prop() disabled: boolean = false;\r\n /**\r\n * 默认文件列表\r\n */\r\n @Prop() defaultFileList: FileUploadResponse[] = [];\r\n /**\r\n * 上传区域提示文本\r\n */\r\n @Prop() uploadText: string = '点击上传简历';\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: FileUploadResponse[] = [];\r\n @State() mobileUploadFiles: FileUploadResponse[] = [];\r\n @State() expireTime: string = ''; // 过期时间\r\n\r\n @Event() ok: EventEmitter<FileUploadResponse[]>;\r\n\r\n componentWillLoad(): void {\r\n this.value = [...this.defaultFileList];\r\n }\r\n\r\n @Method()\r\n async getIsUploading(): Promise<boolean> {\r\n return this.startMobileUploadLoading;\r\n }\r\n\r\n @Method()\r\n async clearSelectedFiles(): Promise<void> {\r\n this.value = [];\r\n }\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: string): Promise<void> => {\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.mobileUploadFiles = 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 tags = Array.isArray(params.tags) ? params.tags as string[] : undefined;\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,\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 (clearValue: boolean = true) => {\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 if (clearValue) {\r\n this.mobileUploadFiles = [];\r\n }\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.mobileUploadFiles = this.mobileUploadFiles.filter(it => it.cos_key !== cos_key);\r\n this.value = this.value.filter(it => it.cos_key !== cos_key);\r\n this.ok.emit(this.value);\r\n }\r\n }\r\n\r\n\r\n private handleOpenUpload = (): void => {\r\n if (this.disabled) return;\r\n if (this.maxFileCount <= this.value.length) {\r\n Message.info('文件数量已达到上限!');\r\n return;\r\n }\r\n this.mobileUploadFiles = [];\r\n this.open = true;\r\n this.handleStartMobileUpload();\r\n }\r\n\r\n render() {\r\n return (\r\n <div>\r\n {this.uploadAreaMode ? <div class=\"upload-area-mode\">\r\n <div class=\"upload-area\">\r\n {this.value.map((item, index) => <div class=\"file-item\" key={item.cos_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 {!this.disabled && <button class=\"remove-file\" onClick={(event) => {\r\n event.stopPropagation();\r\n this.handleDelete(item.cos_key);\r\n }}>×</button>}\r\n </div>)}\r\n </div>\r\n {!this.disabled && this.value.length < this.maxFileCount && <div class=\"upload-actions\">\r\n <div class=\"upload-placeholder\" onClick={this.handleOpenUpload}>\r\n <img src=\"https://pub.pincaimao.com/static/web/images/home/i_upload.png\" />\r\n <p class=\"upload-text\">{this.uploadText}</p>\r\n {!!this.acceptFileSuffixList.length && <p class=\"upload-hint\">支持 {this.acceptFileSuffixList.join('、')} 格式。</p>}\r\n </div>\r\n </div>}\r\n </div> : <div class=\"mobile-upload\">\r\n <div class=\"btn btn-link\" onClick={this.handleOpenUpload}>扫码上传</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.mobileUploadFiles.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.mobileUploadFiles.length > this.maxFileCount) {\r\n Message.info(`最多只能选择${this.maxFileCount}个文件,请删除多余文件!`);\r\n return;\r\n }\r\n this.value = this.multiple\r\n ? [...this.value, ...this.mobileUploadFiles]\r\n : this.mobileUploadFiles.slice(0, 1);\r\n this.ok.emit(this.value);\r\n this.cancelMobileUpload(false);\r\n }}>完成</div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n )\r\n }\r\n}",":host {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.position-selector-container {\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n height: 100%;\r\n background: #fff;\r\n}\r\n\r\n/* 搜索栏样式 */\r\n.search-bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n padding: 16px;\r\n border-bottom: 1px solid #f0f0f0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.search-input-wrapper {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n min-width: 200px;\r\n max-width: 500px;\r\n}\r\n\r\n.search-icon {\r\n position: absolute;\r\n left: 12px;\r\n color: #bfbfbf;\r\n pointer-events: none;\r\n}\r\n\r\n.search-input {\r\n width: 100%;\r\n height: 36px;\r\n padding: 4px 36px 4px 36px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n color: rgba(0, 0, 0, 0.85);\r\n background-color: #fff;\r\n background-image: none;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.search-input:hover {\r\n border-color: #40a9ff;\r\n}\r\n\r\n.search-input:focus {\r\n border-color: #40a9ff;\r\n box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);\r\n}\r\n\r\n.search-input::placeholder {\r\n color: #bfbfbf;\r\n}\r\n\r\n.clear-button {\r\n position: absolute;\r\n right: 12px;\r\n background: none;\r\n border: none;\r\n padding: 4px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #bfbfbf;\r\n transition: color 0.3s;\r\n}\r\n\r\n.clear-button:hover {\r\n color: #8c8c8c;\r\n}\r\n\r\n.search-button {\r\n padding: 4px 15px;\r\n height: 36px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n border-radius: 6px;\r\n color: #fff;\r\n background-color: #1890ff;\r\n border: 1px solid #1890ff;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n outline: none;\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n}\r\n\r\n.search-button:hover {\r\n background-color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.search-button:active {\r\n background-color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n/* 加载状态 */\r\n.loading-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 40px;\r\n gap: 16px;\r\n color: #8c8c8c;\r\n}\r\n\r\n.loading-spinner {\r\n width: 32px;\r\n height: 32px;\r\n border: 3px solid #f0f0f0;\r\n border-top-color: #1890ff;\r\n border-radius: 50%;\r\n animation: spin 0.8s linear infinite;\r\n}\r\n\r\n@keyframes spin {\r\n to { transform: rotate(360deg); }\r\n}\r\n\r\n/* 空状态 */\r\n.empty-container {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 60px 20px;\r\n gap: 16px;\r\n}\r\n\r\n.empty-icon {\r\n opacity: 0.5;\r\n}\r\n\r\n.empty-text {\r\n margin: 0;\r\n color: #8c8c8c;\r\n font-size: 14px;\r\n}\r\n\r\n/* 职位列表 */\r\n.position-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n min-height: 0;\r\n}\r\n\r\n.table-container {\r\n width: 100%;\r\n overflow-x: auto;\r\n}\r\n\r\n.position-table {\r\n width: 100%;\r\n border-collapse: collapse;\r\n font-size: 14px;\r\n}\r\n\r\n.position-table thead {\r\n background-color: #fafafa;\r\n position: sticky;\r\n top: 0;\r\n z-index: 1;\r\n}\r\n\r\n.position-table th {\r\n padding: 12px 16px;\r\n text-align: left;\r\n font-weight: 500;\r\n color: rgba(0, 0, 0, 0.85);\r\n border-bottom: 1px solid #f0f0f0;\r\n white-space: nowrap;\r\n}\r\n\r\n.position-table td {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid #f0f0f0;\r\n color: rgba(0, 0, 0, 0.65);\r\n}\r\n\r\n.position-table tbody tr {\r\n transition: background-color 0.3s;\r\n}\r\n\r\n.position-table tbody tr:hover {\r\n background-color: #fafafa;\r\n}\r\n\r\n.position-table tbody tr.selected-row {\r\n background-color: #e6f7ff;\r\n}\r\n\r\n/* 列宽设置 */\r\n.checkbox-column {\r\n width: 50px;\r\n text-align: center;\r\n}\r\n\r\n.title-column {\r\n min-width: 150px;\r\n max-width: 200px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.company-column {\r\n min-width: 120px;\r\n max-width: 180px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.location-column {\r\n min-width: 100px;\r\n max-width: 150px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.requirements-column {\r\n min-width: 200px;\r\n max-width: 300px;\r\n}\r\n\r\n.requirements-text {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n display: -webkit-box;\r\n -webkit-line-clamp: 2;\r\n -webkit-box-orient: vertical;\r\n white-space: normal;\r\n word-break: break-word;\r\n line-height: 1.5;\r\n}\r\n\r\n.salary-column {\r\n min-width: 100px;\r\n white-space: nowrap;\r\n}\r\n\r\n.action-column {\r\n width: 100px;\r\n text-align: center;\r\n}\r\n\r\n/* 复选框样式 */\r\n.position-checkbox {\r\n width: 16px;\r\n height: 16px;\r\n cursor: pointer;\r\n accent-color: #1890ff;\r\n}\r\n\r\n/* 选择按钮 */\r\n.select-button {\r\n padding: 4px 15px;\r\n height: 28px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n border-radius: 6px;\r\n color: #fff;\r\n background-color: #1890ff;\r\n border: 1px solid #1890ff;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.select-button:hover {\r\n background-color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.select-button:active {\r\n background-color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n/* 移动端适配 */\r\n@media screen and (max-width: 768px) {\r\n .search-bar {\r\n padding: 12px;\r\n gap: 8px;\r\n }\r\n\r\n .search-input-wrapper {\r\n min-width: auto;\r\n max-width: none;\r\n }\r\n\r\n .search-input {\r\n height: 40px;\r\n font-size: 16px;\r\n }\r\n\r\n .search-button {\r\n height: 40px;\r\n padding: 4px 12px;\r\n }\r\n\r\n .table-container {\r\n overflow-x: auto;\r\n -webkit-overflow-scrolling: touch;\r\n }\r\n\r\n .position-table {\r\n font-size: 12px;\r\n }\r\n\r\n .position-table th,\r\n .position-table td {\r\n padding: 8px 12px;\r\n }\r\n\r\n .title-column,\r\n .company-column,\r\n .location-column {\r\n min-width: 100px;\r\n }\r\n\r\n .select-button {\r\n padding: 4px 12px;\r\n height: 32px;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n/* 分页器样式 */\r\n.pagination-container {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 16px;\r\n padding: 16px;\r\n border-top: 1px solid #f0f0f0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.pagination-button {\r\n padding: 4px 15px;\r\n height: 32px;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n border-radius: 6px;\r\n color: rgba(0, 0, 0, 0.85);\r\n background-color: #fff;\r\n border: 1px solid #d9d9d9;\r\n cursor: pointer;\r\n transition: all 0.3s;\r\n outline: none;\r\n}\r\n\r\n.pagination-button:hover:not(:disabled) {\r\n color: #40a9ff;\r\n border-color: #40a9ff;\r\n}\r\n\r\n.pagination-button:active:not(:disabled) {\r\n color: #096dd9;\r\n border-color: #096dd9;\r\n}\r\n\r\n.pagination-button:disabled {\r\n color: rgba(0, 0, 0, 0.25);\r\n background-color: #f5f5f5;\r\n border-color: #d9d9d9;\r\n cursor: not-allowed;\r\n}\r\n\r\n.pagination-info {\r\n font-size: 14px;\r\n color: rgba(0, 0, 0, 0.65);\r\n}\r\n\r\n/* 滚动条样式 */\r\n.position-list::-webkit-scrollbar {\r\n width: 8px;\r\n height: 8px;\r\n}\r\n\r\n.position-list::-webkit-scrollbar-track {\r\n background: #f1f1f1;\r\n}\r\n\r\n.position-list::-webkit-scrollbar-thumb {\r\n background: #888;\r\n border-radius: 4px;\r\n}\r\n\r\n.position-list::-webkit-scrollbar-thumb:hover {\r\n background: #555;\r\n}\r\n","/* 模态框基础样式 */\r\n.modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n z-index: 1000;\r\n overflow-y: auto;\r\n}\r\n\r\n/* 全屏模式下的overlay样式 - 改为基于父组件 */\r\n.fullscreen-overlay {\r\n padding: 0;\r\n background-color: rgba(0, 0, 0, 0.7);\r\n /* 改为基于父组件的全屏 */\r\n position: absolute;\r\n width: 100%;\r\n height: 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: 5vh auto auto 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","/* 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: flex-start;\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: 5vh auto auto 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 '../../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 { 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: 'components-thousand-resume-wrapper',\r\n styleUrls: ['components-thousand-resume-wrapper.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsThousandResumeWrapper {\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: 5vh auto auto 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: 'components-upload',\r\n styleUrls: ['components-upload.css', '../../global/global.css', '../../global/host.css'],\r\n shadow: true,\r\n})\r\nexport class ComponentsUpload {\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 && <components-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 {\n display: inline-flex;\n}\n\n.voice-input-button {\n width: 32px;\n height: 32px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n margin: 0;\n border: 1px solid #d9d9d9;\n border-radius: 6px;\n background: #fff;\n color: #666;\n cursor: pointer;\n transition: background-color 0.2s, color 0.2s, border-color 0.2s;\n}\n\n.voice-input-button:hover:not(:disabled) {\n background-color: #f0f0f0;\n border-color: #bfbfbf;\n}\n\n.voice-input-button:focus-visible {\n outline: 2px solid rgba(46, 110, 223, 0.35);\n outline-offset: 2px;\n}\n\n.voice-input-button:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.voice-input-button.recording {\n background-color: rgba(255, 0, 0, 0.1);\n border-color: rgba(255, 59, 48, 0.45);\n color: #ff3b30;\n animation: pulse 1.5s infinite;\n}\n\n.voice-input-button.converting {\n background-color: rgba(0, 122, 255, 0.1);\n border-color: rgba(0, 122, 255, 0.35);\n color: #007aff;\n}\n\n.converting-icon {\n animation: spin 1.5s linear infinite;\n}\n\n@keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0.65;\n }\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n","import { Component, Event, EventEmitter, h, Prop, State } from '@stencil/core';\nimport { convertAudioToText, getSupportedAudioMimeType, uploadFileToBackend } from '../../utils/utils';\nimport { ErrorEventDetail } from '../../utils/error-event';\n\nexport type VoiceInputStatus = 'idle' | 'recording' | 'converting';\n\n/**\n * 通用语音输入按钮\n * 负责录音、上传音频并将语音转换为文字\n */\n@Component({\n tag: 'components-voice-input-btn',\n styleUrls: ['components-voice-input-btn.css'],\n shadow: true,\n})\nexport class ComponentsVoiceInputBtn {\n /**\n * 是否禁用语音输入\n */\n @Prop() disabled: boolean = false;\n\n /**\n * 最大录音时长,单位为秒\n */\n @Prop() maxRecordingTime: number = 60;\n\n /**\n * 组件语言\n */\n @Prop() locale: 'zh' | 'en' = 'zh';\n\n /**\n * 语音识别完成事件,返回识别后的文字\n */\n @Event() voiceRecognized: EventEmitter<string>;\n\n /**\n * 语音输入状态变化事件\n */\n @Event() voiceStatusChange: EventEmitter<VoiceInputStatus>;\n\n /**\n * 语音输入错误事件\n */\n @Event() someErrorEvent: EventEmitter<ErrorEventDetail>;\n\n @State() private _status: VoiceInputStatus = 'idle';\n @State() private _recordingTimeLeft: number = 60;\n\n private _audioRecorder: MediaRecorder | null = null;\n private _audioStream: MediaStream | null = null;\n private _audioChunks: BlobPart[] = [];\n private _audioMimeType: string = '';\n private _recordingStartTime: number = 0;\n private _recordingTimer: ReturnType<typeof setInterval> | null = null;\n\n disconnectedCallback(): void {\n this._releaseRecordingResources();\n }\n\n private _getText(zhText: string, enText: string): string {\n return this.locale === 'en' ? enText : zhText;\n }\n\n private _setStatus(status: VoiceInputStatus): void {\n this._status = status;\n this.voiceStatusChange.emit(status);\n }\n\n private _emitError(error: unknown, message: string): void {\n console.error(message, error);\n this.someErrorEvent.emit({ error, message });\n }\n\n private _handleClick = (): void => {\n if (this.disabled || this._status === 'converting') {\n return;\n }\n\n if (this._status === 'recording') {\n this._stopRecording();\n return;\n }\n\n if (!navigator.mediaDevices?.getUserMedia || !window.MediaRecorder) {\n this._emitError(new Error('MediaRecorder API is unavailable'), this._getText('当前浏览器不支持语音输入', 'Voice input is not supported by this browser'));\n return;\n }\n\n navigator.mediaDevices\n .getUserMedia({ audio: true })\n .then((stream: MediaStream) => this._startRecording(stream))\n .catch((error: unknown) => {\n this._emitError(error, this._getText('无法访问麦克风,请检查麦克风权限', 'Unable to access the microphone. Please check microphone permissions'));\n });\n };\n\n private _startRecording(stream: MediaStream): void {\n this._audioStream = stream;\n\n try {\n const supportedMimeType = getSupportedAudioMimeType();\n this._audioRecorder = supportedMimeType\n ? new MediaRecorder(stream, { mimeType: supportedMimeType })\n : new MediaRecorder(stream);\n this._audioMimeType = this._audioRecorder.mimeType || supportedMimeType || 'audio/webm';\n } catch (error) {\n this._releaseRecordingResources();\n this._emitError(error, this._getText('无法启动录音,请检查麦克风设备', 'Unable to start recording. Please check the microphone'));\n return;\n }\n\n this._audioChunks = [];\n this._recordingStartTime = Date.now();\n this._recordingTimeLeft = this.maxRecordingTime;\n\n this._audioRecorder.ondataavailable = (event: BlobEvent): void => {\n if (event.data.size > 0) {\n this._audioChunks.push(event.data);\n }\n };\n\n this._audioRecorder.onerror = (event: Event): void => {\n this._emitError(event, this._getText('录音失败,请重试', 'Recording failed. Please try again'));\n this._releaseRecordingResources();\n this._setStatus('idle');\n };\n\n this._audioRecorder.onstop = (): void => {\n this._stopMediaStream();\n void this._processAudioRecording();\n };\n\n try {\n this._audioRecorder.start(100);\n this._setStatus('recording');\n this._recordingTimer = setInterval((): void => {\n const elapsedTime = Math.floor((Date.now() - this._recordingStartTime) / 1000);\n this._recordingTimeLeft = Math.max(0, this.maxRecordingTime - elapsedTime);\n if (this._recordingTimeLeft <= 0) {\n this._stopRecording();\n }\n }, 1000);\n } catch (error) {\n this._releaseRecordingResources();\n this._setStatus('idle');\n this._emitError(error, this._getText('开始录音失败,请重试', 'Failed to start recording. Please try again'));\n }\n }\n\n private _stopRecording(): void {\n if (!this._audioRecorder || this._audioRecorder.state === 'inactive') {\n return;\n }\n\n this._clearRecordingTimer();\n this._audioRecorder.stop();\n }\n\n private async _processAudioRecording(): Promise<void> {\n if (this._audioChunks.length === 0) {\n this._setStatus('idle');\n this._emitError(new Error('Recorded audio is empty'), this._getText('未录制到语音内容,请重试', 'No audio was recorded. Please try again'));\n return;\n }\n\n this._setStatus('converting');\n\n try {\n const audioBlob = new Blob(this._audioChunks, { type: this._audioMimeType });\n if (audioBlob.size === 0) {\n throw new Error('Recorded audio is empty');\n }\n\n const extension = this._getFileExtension(this._audioMimeType);\n const audioFile = new File([audioBlob], `audio_input.${extension}`, { type: this._audioMimeType });\n const fileInfo = await uploadFileToBackend(audioFile, {}, { tags: ['audio'] });\n const transcriptionText = await convertAudioToText(fileInfo.cos_key);\n\n if (!transcriptionText) {\n throw new Error('No transcription text returned');\n }\n\n this.voiceRecognized.emit(transcriptionText);\n } catch (error) {\n this._emitError(error, this._getText('语音识别失败,请重试', 'Speech recognition failed. Please try again'));\n } finally {\n this._audioChunks = [];\n this._audioRecorder = null;\n this._setStatus('idle');\n }\n }\n\n private _getFileExtension(mimeType: string): string {\n if (mimeType.includes('mp4')) return 'm4a';\n if (mimeType.includes('ogg')) return 'ogg';\n return 'webm';\n }\n\n private _clearRecordingTimer(): void {\n if (this._recordingTimer) {\n clearInterval(this._recordingTimer);\n this._recordingTimer = null;\n }\n }\n\n private _stopMediaStream(): void {\n this._audioStream?.getTracks().forEach((track: MediaStreamTrack): void => track.stop());\n this._audioStream = null;\n }\n\n private _releaseRecordingResources(): void {\n this._clearRecordingTimer();\n\n if (this._audioRecorder) {\n this._audioRecorder.ondataavailable = null;\n this._audioRecorder.onerror = null;\n this._audioRecorder.onstop = null;\n if (this._audioRecorder.state !== 'inactive') {\n this._audioRecorder.stop();\n }\n }\n\n this._stopMediaStream();\n this._audioRecorder = null;\n this._audioChunks = [];\n }\n\n render() {\n const isRecording = this._status === 'recording';\n const isConverting = this._status === 'converting';\n const title = isRecording\n ? this._getText(`点击停止录音(剩余${this._recordingTimeLeft}秒)`, `Stop recording (${this._recordingTimeLeft}s remaining)`)\n : isConverting\n ? this._getText('正在识别语音...', 'Recognizing speech...')\n : this._getText('语音输入', 'Voice input');\n\n return (\n <button\n type=\"button\"\n class={{\n 'voice-input-button': true,\n 'recording': isRecording,\n 'converting': isConverting,\n }}\n title={title}\n aria-label={title}\n aria-pressed={isRecording ? 'true' : 'false'}\n disabled={this.disabled || isConverting}\n onClick={this._handleClick}\n >\n {isConverting ? (\n <svg class=\"converting-icon\" viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z\" />\n </svg>\n ) : (\n <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z\" />\n <path d=\"M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z\" />\n {isRecording && <circle cx=\"12\" cy=\"11\" r=\"4\" fill=\"red\" />}\n </svg>\n )}\n </button>\n );\n }\n}\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: 5vh auto auto 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: 12px;\r\n}\r\n\r\n/* 刷新按钮样式 */\r\n.refresh-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n padding: 0;\r\n background: white;\r\n border: 1px solid #d9d9d9;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n}\r\n\r\n.refresh-btn:hover:not(:disabled) {\r\n border-color: #40a9ff;\r\n color: #40a9ff;\r\n background: #f6f8ff;\r\n}\r\n\r\n.refresh-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.refresh-btn svg {\r\n transition: transform 0.3s ease;\r\n}\r\n\r\n\r\n.refresh-btn svg.rotating {\r\n animation: rotate 1s linear infinite;\r\n}\r\n\r\n@keyframes rotate {\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.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\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@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.label-with-button {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 8px;\r\n}\r\n\r\n.button-group {\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n}\r\n\r\n.position-selector-button {\r\n padding: 4px 12px;\r\n background: #1890ff;\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n font-size: 13px;\r\n cursor: pointer;\r\n transition: all 0.3s ease;\r\n white-space: nowrap;\r\n height: 28px;\r\n line-height: 20px;\r\n}\r\n\r\n.position-selector-button:hover {\r\n background: #40a9ff;\r\n}\r\n\r\n.position-selector-button:active {\r\n background: #096dd9;\r\n}\r\n\r\n/* 职位选择器弹窗样式 */\r\n.position-selector-modal-overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 3000;\r\n padding: 20px;\r\n}\r\n\r\n.position-selector-modal {\r\n background: white;\r\n border-radius: 8px;\r\n width: 90%;\r\n max-width: 900px;\r\n height: 80vh;\r\n max-height: 600px;\r\n display: flex;\r\n flex-direction: column;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n animation: modalFadeIn 0.3s ease;\r\n}\r\n\r\n@keyframes modalFadeIn {\r\n from {\r\n opacity: 0;\r\n transform: scale(0.95) translateY(-20px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: scale(1) translateY(0);\r\n }\r\n}\r\n\r\n.position-selector-modal-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 16px 24px;\r\n border-bottom: 1px solid #f0f0f0;\r\n flex-shrink: 0;\r\n}\r\n\r\n.position-selector-modal-header h3 {\r\n margin: 0;\r\n font-size: 16px;\r\n font-weight: 500;\r\n color: rgba(0, 0, 0, 0.85);\r\n}\r\n\r\n.position-selector-close-btn {\r\n background: none;\r\n border: none;\r\n font-size: 24px;\r\n line-height: 1;\r\n cursor: pointer;\r\n color: rgba(0, 0, 0, 0.45);\r\n padding: 0;\r\n width: 32px;\r\n height: 32px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: 4px;\r\n transition: all 0.3s;\r\n}\r\n\r\n.position-selector-close-btn:hover {\r\n background-color: rgba(0, 0, 0, 0.06);\r\n color: rgba(0, 0, 0, 0.85);\r\n}\r\n\r\n.position-selector-modal-body {\r\n flex: 1;\r\n overflow: hidden;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n/* 移动端适配 */\r\n@media screen and (max-width: 768px) {\r\n .position-selector-modal {\r\n width: 100%;\r\n height: 90vh;\r\n max-height: none;\r\n border-radius: 8px 8px 0 0;\r\n margin-top: auto;\r\n }\r\n\r\n .position-selector-modal-overlay {\r\n padding: 0;\r\n align-items: flex-end;\r\n }\r\n}\r\n\r\n/* 上传禁用遮罩样式 */\r\n.upload-disabled-wrapper {\r\n position: relative;\r\n cursor: not-allowed;\r\n}\r\n\r\n.upload-disabled-wrapper::before {\r\n content: '';\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-color: rgba(255, 255, 255, 0.7);\r\n z-index: 0;\r\n cursor: not-allowed;\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.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.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@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\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}","/* 模态框基础样式 */\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: 5vh auto auto 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 <components-mobile-upload-btn\r\n maxFileSize={15 * 1024 * 1024}\r\n multiple={false}\r\n uploadAreaMode={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 onOk={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: 5vh auto auto 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: 5vh auto auto 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: 60vh;\r\n min-height: 400px;\r\n max-height: 900px;\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: flex-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: 5vh auto auto 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} ","/* 输入模式切换 */\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: 5vh auto auto 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 @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?.length) {\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 <components-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 </components-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 <components-upload\r\n ref={el => this.pcmUploadRef = el}\r\n maxFileSize={25 * 1024 * 1024}\r\n multiple={true}\r\n maxFileCount={5}\r\n mobileUploadAble={this.mobileUploadAble}\r\n uploadText=\"点击上传合同\"\r\n acceptFileSuffixList={[\".pdf\", \".doc\", \".docx\", \".jpg\", \".jpeg\", \".png\"]}\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;\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.mobileUploadAble && (\r\n <components-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?.length) ||\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?.map?.((item) => item.cos_key)?.join(\",\") : undefined,\r\n file_name: this.uploadedFileInfo?.map?.((item) => item.file_name)?.join(\",\"),\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: 5vh auto auto 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 this.someErrorEvent.emit({\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 this.someErrorEvent.emit({\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 <components-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 </components-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.voice-textarea-wrapper {\r\n position: relative;\r\n}\r\n\r\n.voice-textarea-wrapper textarea {\r\n padding-bottom: 52px;\r\n}\r\n\r\n.voice-input-entry {\r\n position: absolute;\r\n right: 12px;\r\n bottom: 32px;\r\n z-index: 1;\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: 5vh auto auto 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() isVoiceInputActive: 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 if (this.isVoiceInputActive) return;\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 handleVoiceRecognized = (event: CustomEvent<string>): void => {\r\n const textarea = this.hostElement.shadowRoot?.querySelector('#free-input-text') as HTMLTextAreaElement | null;\r\n const cursorPosition = textarea?.selectionStart ?? this.freeInputText.length;\r\n const beforeCursor = this.freeInputText.substring(0, cursorPosition);\r\n const afterCursor = this.freeInputText.substring(cursorPosition);\r\n const spacer = beforeCursor.length > 0 && !/\\s$/.test(beforeCursor) ? ' ' : '';\r\n\r\n this.freeInputText = `${beforeCursor}${spacer}${event.detail}${afterCursor}`;\r\n\r\n requestAnimationFrame((): void => {\r\n if (!textarea) return;\r\n const newPosition = cursorPosition + spacer.length + event.detail.length;\r\n textarea.focus();\r\n textarea.setSelectionRange(newPosition, newPosition);\r\n });\r\n };\r\n\r\n private handleVoiceStatusChange = (event: CustomEvent<'idle' | 'recording' | 'converting'>): void => {\r\n this.isVoiceInputActive = event.detail !== 'idle';\r\n };\r\n\r\n private handleVoiceInputError = (event: CustomEvent<ErrorEventDetail>): void => {\r\n this.someErrorEvent.emit(event.detail);\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 this.someErrorEvent.emit({\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 this.someErrorEvent.emit({\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 this.someErrorEvent.emit({\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.isVoiceInputActive = false;\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 <components-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 </components-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 || this.isVoiceInputActive}\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 <div class=\"voice-textarea-wrapper\">\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 disabled={this.isVoiceInputActive}\r\n ></textarea>\r\n <div class=\"voice-input-entry\">\r\n <components-voice-input-btn\r\n locale={this.locale === 'en' ? 'en' : 'zh'}\r\n disabled={this.isSubmitting}\r\n onVoiceRecognized={this.handleVoiceRecognized}\r\n onVoiceStatusChange={this.handleVoiceStatusChange}\r\n onSomeErrorEvent={this.handleVoiceInputError}\r\n ></components-voice-input-btn>\r\n </div>\r\n </div>\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 || this.isVoiceInputActive}\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: 5vh auto auto 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 <components-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 </components-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 <components-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 <components-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",".resume-type-container {\r\n display: flex;\r\n flex-direction: row;\r\n flex-wrap: nowrap;\r\n justify-content: space-evenly;\r\n gap: 0;\r\n margin-bottom: 16px;\r\n border-bottom: 2px solid #f0f0f0;\r\n padding-left: 0;\r\n overflow-x: auto;\r\n overflow-y: hidden;\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 white-space: nowrap;\r\n flex-shrink: 0;\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: 5vh auto auto 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}","/* 历史会话相关样式已移至 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: 5vh auto auto 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 <components-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 <components-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 </components-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: 5vh auto auto 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 * 是否跳过简历上传步骤,默认false\r\n */\r\n @Prop() skipResumeUpload: boolean = false;\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.skipResumeUpload) && 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)) || !!this.skipResumeUpload;\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 <components-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 <components-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: 5vh auto auto 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 <components-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 <components-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} ",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: 5vh auto auto 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 this.someErrorEvent.emit({\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 this.someErrorEvent.emit({\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 <components-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 </components-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: 5vh auto auto 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}",":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: flex-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: 5vh auto auto 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: 60vh;\r\n min-height: 400px;\r\n max-height: 900px;\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.document-download-actions {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n margin-right: 8px;\r\n}\r\n\r\n.document-download-button {\r\n padding: 4px 8px;\r\n color: #1890ff;\r\n font-size: 14px;\r\n line-height: 20px;\r\n background: transparent;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n}\r\n\r\n.document-download-button:hover {\r\n background-color: #e6f7ff;\r\n}\r\n\r\n.document-download-button:focus-visible {\r\n outline: 2px solid #1890ff;\r\n outline-offset: 2px;\r\n}\r\n\r\n.document-download-qr-code {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n padding: 8px 0;\r\n}\r\n\r\n.document-download-qr-code img {\r\n width: 200px;\r\n height: 200px;\r\n}\r\n\r\n.document-download-qr-code p {\r\n margin: 16px 0 0;\r\n color: #666;\r\n font-size: 14px;\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: flex-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: 5vh auto auto 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 <components-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 </components-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 <components-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: 5vh auto auto 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 <components-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 </components-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 <components-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":[]}
|