12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914 |
- <template>
- <div class="outer-container" :class="{'mobile': isMobile}">
-
- <!-- 添加加载状态和错误提示 -->
- <div v-if="loading" class="loading-state">
- 加载中...
- </div>
-
- <div v-else-if="error" class="error-state">
- {{ error }}
- </div>
- <div v-else class="report-container">
- <!-- 添加顶部标识栏 -->
- <div class="report-header">
- <div class="header-left">
- <img src="/@/assets/qcLogo.png" class="cc-icon" alt="cc icon">
- AI面试结果检验报告
- </div>
- <div class="header-right">
- <div>报告生成时间:{{ reportTime }}</div>
- <div class="report-id">报告ID:{{ reportId }}</div>
- <!-- 添加导出按钮 -->
- </div>
- </div>
- <!-- 头部信息 -->
- <div class="header">
- <!-- 头像部分 -->
- <div class="header-left">
- <img class="avatar" :src="userInfo.avatar" alt="用户头像">
- </div>
- <!-- 信息部分 -->
- <div class="header-right">
- <!-- 左侧信息 -->
- <div class="left-section">
- <div class="info-row">
- <span class="label">姓名:</span>
- <span class="value">{{ userInfo.name }}</span>
- </div>
- <div class="info-row">
- <span class="label">面试时间:</span>
- <span class="value">{{ userInfo.interviewTime }}</span>
- </div>
- <div class="info-row">
- <span class="label">面试时长:</span>
- <span class="value">{{ userInfo.duration }}</span>
- </div>
- </div>
- <!-- 右侧信息 -->
- <div class="right-section">
- <div class="info-row">
- <span class="label">实名认证:</span>
- <span class="value verified">已核验</span>
- </div>
- <div class="info-row">
- <span class="label">身份证号:</span>
- <span class="value">{{ userInfo.idNumber }}</span>
- </div>
- <div class="info-row">
- <span class="label">手机号码:</span>
- <span class="value">{{ userInfo.phone }}</span>
- </div>
- </div>
- <!-- 印章 -->
- <div class="stamp">
- <img v-if="userInfo.pass < 60" src="/@/assets/notPass.png" alt="不通过印章">
- <img v-else src="/@/assets/pass.png" alt="通过印章">
- </div>
- </div>
- </div>
- <!-- 修改导航选项卡部分 -->
- <div
- class="nav-tabs"
- :class="{ 'fixed': isNavFixed }"
- ref="navTabs"
- >
- <div
- v-for="tab in tabs"
- :key="tab.id"
- class="tab-item"
- :class="{
- 'active': activeTab === tab.id,
- 'link-tab': tab.isLink,
- 'info-tab': tab.isInfo
- }"
- @click="handleTabClick(tab)"
- >
- {{ tab.name }}
- <!-- 添加链接图标 -->
- <i v-if="tab.isLink" class="el-icon-link"></i>
- <!-- 添加信息图标 -->
- <i v-if="tab.isInfo" class="el-icon-info"></i>
- </div>
- </div>
-
- <!-- 修改占位元素 -->
- <div
- class="nav-placeholder"
- v-if="isNavFixed"
- :style="{ height: navHeight + 'px' }"
- ></div>
- <!-- 各个内容区域添加ref标识 -->
- <div ref="comprehensive" class="evaluation-result pdfRef">
- <div class="score-section">
- <div class="score-section-left">
- <div class="score-title">综合评价</div>
- <div class="score-value">
- <span class="number">{{userInfo.pass}}</span>
- <span class="unit">分</span>
- <p class="status-tag" v-if="userInfo.pass < 60">不通过</p>
- <p class="status-tag" style='background:#67C23A;' v-else>通过</p>
- </div>
- <div class="detection-results">
- <span class="detection-item">
- 身份认证
- <span :class="userInfo.idNumber ? 'status-normal' : 'status-warning'">
- {{ userInfo.idNumber ? '无异常' : '有异常' }}
- </span>
- </span>
- <span class="separator">/</span>
- <span class="detection-item">
- 手机号实名认证
- <span :class="userInfo.phone ? 'status-normal' : 'status-warning'">
- {{ userInfo.phone ? '无异常' : '有异常' }}
- </span>
- </span>
- <span class="separator">/</span>
- <span class="detection-item">
- 手部综合检测 <span class="status-normal" :style="userInfo.visual_analysis_done ? '':'color:#f56c6c;'"> {{ userInfo.visual_analysis_done ? '无异常' : '有异常' }}</span>
- </span>
- </div>
- </div>
- <div class="fail-reason">
- <div class="reason-header">
- <!-- <i class="el-icon-warning"></i> -->
- <span>录用建议:{{ hireRecommendation || '正在分析中' }}</span>
- </div>
- <div class="reason-content">
- {{ failReason }}
- </div>
- </div>
- <div class="reason-content redline-section">
- <div class="redline-header">
- <span class="redline-title">红线题检测结果</span>
- <span :class="{
- 'status-normal': redLineQuestions.allCorrect,
- 'status-warning': !redLineQuestions.allCorrect
- }">
- {{ redLineQuestions.allCorrect ? '全部正确' : '存在错误,建议不录用' }}
- </span>
- </div>
- <!-- 添加未通过题目的详细信息 -->
- <div v-if="!redLineQuestions.allCorrect && redLineQuestions.failedQuestions.length > 0"
- class="failed-questions">
- <div class="failed-title">未通过的红线题:</div>
- <div class="failed-list">
- <div v-for="(question, index) in redLineQuestions.failedQuestions"
- :key="'failed-'+index"
- class="failed-item">
- <span class="bullet">•</span>
- <span class="question-text">{{ question.question_text || `问题 ${index + 1}` }}</span>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 能力雷达图 -->
- <div class="radar-chart">
- <v-chart
- ref="radarChart"
- class="radar"
- :option="radarOption"
- autoresize
- />
- </div>
- </div>
- <div ref="ability" class="ability-quality pdfRef">
- <h3 style="font-size: 16px; font-weight: bold;">能力素质 <span style="font-size: 14px; font-weight: normal;">综合得分<span class="score-text">{{ totalScore || '正在分析中' }}</span>{{ totalScore ? '/100 分' : '' }}</span> </h3>
-
- <div class="quality-details">
- <div class="quality-item">
- <div class="quality-left">
- <div class="icon-box">
- <div class="icon advantage-icon">
- <img src="/@/assets/yous.png" alt="优势展现">
- </div>
- <h5>优势展现</h5>
- </div>
- <div class="content">
- <template v-if="qualityDetails.strengths && qualityDetails.strengths.length">
- <p v-for="(strength, index) in qualityDetails.strengths"
- :key="index"
- v-html="formatTextWithBrackets(getChineseAnalysis(strength))">
- </p>
- </template>
- <p v-else>正在分析中</p>
- </div>
- </div>
-
- <div class="quality-right">
- <div class="icon-box">
- <div class="icon suggestion-icon" style="position: relative;">
- <img src="/@/assets/que.png" alt="发展建议">
- <img style="width: 10px; height: 10px; position: absolute; top: 32%; left: 5px;" src="/@/assets/info.png" alt="">
- </div>
- <h5>发展建议</h5>
- </div>
- <div class="content">
- <template v-if="qualityDetails.weaknesses && qualityDetails.weaknesses.length">
- <p v-for="(weakness, index) in qualityDetails.weaknesses"
- :key="index"
- v-html="formatTextWithBrackets2(getChineseAnalysis(weakness))">
- </p>
- </template>
- <p v-else>正在分析中</p>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div>
- <div class="detailed-evaluation">
- <div class="line-info">
- <div class="line-info-left">低</div>
- <div class="line-info-center">中</div>
- <div class="line-info-right">高</div>
- </div>
- <div class="line-chart">
- <div class="line-chart-left"></div>
- <div class="line_left"></div>
- <div class="line_center"></div>
- <div class="line_right"></div>
- </div>
- <div class="ability-scores">
- <div v-for="(item, index) in abilityItems" :key="index" class="ability-item">
- <span class="ability-name">{{ item.tag_name }}</span>
- <div class="bar-chart-container">
- <v-chart
- :option="getBarChartOption(item)"
- :autoresize="true"
- style="width: 100%; height: 30px;"
- />
- </div>
- </div>
- </div>
- </div>
- </div>
- <div ref="cheat" class="detection-section">
- <div class="detection-section-header">
- <div class="section-title">作弊检测</div>
- <div class="status-tag normal">无异常</div>
- </div>
- <div class="detection-section-content">
- <div class="detection-items">
- <div class="item">
- <span class="status normal">无风险</span>
- <span class="separator">/</span>
- <span class="desc">转移、替考:检测无异常</span>
- </div>
- <div class="item">
- <span class="status normal">无风险</span>
- <span class="separator">/</span>
- <span class="desc">读稿:检测无异常</span>
- </div>
- <div class="item">
- <span class="status normal">无风险</span>
- <span class="separator">/</span>
- <span class="desc">录屏/切屏:检测无异常</span>
- </div>
- </div>
- <div class="risk-standards">
- <div class="standards-title">风险等级标准</div>
- <div class="standards-content">
- <div class="standard-item">
- <span class="level">无异常:</span>
- <span class="desc">候选人提供的信息真实/无切屏录屏行为/无互联网查询行为/无互联网传行为</span>
- </div>
- <div class="standard-item">
- <span class="level">低风险:</span>
- <span class="desc">候选人提供信息真实/可切屏录屏行为/可互联网查询行为/无互联网传行为</span>
- </div>
- <div class="standard-item">
- <span class="level">高风险:</span>
- <span class="desc">面试者与候选人为一不同人/可切屏录屏行为/可互联网查询行为/过程存在传输行为</span>
- </div>
- </div>
-
- </div>
- </div>
- </div>
- <div ref="psychology" class="psychology-section">
- <div class="section-title">心理检测</div>
- <!-- -->
- <div class="psychology_box">
- <div class="psychology_body">
- <div class="psychology-desc">
- {{ psychologyData.description }}
- </div>
- <div class="psychology-recommendation">
- <span class="label">录用建议:</span>
- <span class="value">{{ psychologyData.recommendation }}</span>
- </div>
- </div>
- <div class="duv-score">
- <!-- <span class="score" :class="getPsychologyScoreClass">{{ psychologyData.score }}</span>
- <span>分</span> -->
- <span class="risk-level" :class="getPsychologyScoreClass">{{ getPsychologyRiskLevel }}</span>
- </div>
- </div>
- </div>
- <div ref="body" class="body-detection-section">
- <div class="detection-section-header">
- <div class="section-title">肢体检测</div>
- <el-button
- type="primary"
- link
- @click="showBodyVerification = true"
- >
- 查看肢体核验结果
- </el-button>
- </div>
- <!-- 手部检测结果说明 -->
- <div class="detection-results mt-6">
- <div class="grid grid-cols-2 gap-4">
- <!-- 左手检测结果 -->
- <template v-for="(photo, index) in getHandPhotos('left')" :key="'left-'+index">
- <div class="detection-item" style="background-color: #f8f8f8;">
- <span class="position" style="color: #6c6c6c;">{{ getPositionLabel('left', index) }}</span>
- <span class="status" :class="{
- 'status-normal': photo.part_verification?.is_correct_part,
- 'status-error': !photo.part_verification?.is_correct_part
- }">
- {{ photo.part_verification?.is_correct_part ? '动作检测无异常' : '动作检测异常' }}
- </span>
- <span class="description text-gray-500 text-sm">
- {{ photo.part_verification?.is_correct_part ? getDefaultDescription('left', index) : photo.part_verification?.explanation || '检测未通过' }}
- </span>
- </div>
- </template>
- <!-- 右手检测结果 -->
- <template v-for="(photo, index) in getHandPhotos('right')" :key="'right-'+index">
- <div class="detection-item" style="background-color: #f8f8f8;">
- <span class="position" style="color: #6c6c6c;">{{ getPositionLabel('right', index) }}</span>
- <span class="status" :class="{
- 'status-normal': photo.part_verification?.is_correct_part,
- 'status-error': !photo.part_verification?.is_correct_part
- }">
- {{ photo.part_verification?.is_correct_part ? '动作检测无异常' : '动作检测异常' }}
- </span>
- <span class="description text-gray-500 text-sm">
- {{ photo.part_verification?.is_correct_part ? getDefaultDescription('right', index) : photo.part_verification?.explanation || '检测未通过' }}
- </span>
- </div>
- </template>
- </div>
- </div>
- </div>
- <div ref="answers" class="report-footer">
- <!-- 添加问答记录展示区域 -->
- <div class="qa-section">
- <h3 class="section-title">问答记录</h3>
- <div class="qa-content">
- <div class="space-y-4">
- <div v-for="(record, index) in interviewRecords" :key="index" class=" rounded-lg p-4" v-show="record.question_form === 0">
- <!-- 题目标题部分 -->
- <div class="mb-4" v-if="record.question_form === 0">
- <div class="flex items-start space-x-2 w-2/3" >
- <div class="px-2 py-1 rounded text-sm" style="font-size: 14px; font-weight: 600; font-family: 微软雅黑;">第{{ index + 1 }}题:</div>
- <!-- <div class="bg-gray-100 text-gray-800 px-2 py-1 rounded text-sm">{{ getQuestionTypeName(record.question_form || 0) }}</div> -->
- <div class="flex-1">
- <span class="text-gray-800 color-black " style="font-size: 14px;">{{ record.question }}</span>
- </div>
- </div>
- <!-- 视频问答题布局 || record.question_form === 5-->
- <div v-if="record.question_form === 0" class="mt-4">
- <!-- 原有的视频问答题布局 -->
- <div class="flex space-x-4">
- <!-- 右侧答案和评分 -->
- <div class="w-2/3">
- <div class="bg-white p-4 rounded-xl">
- <div class="">
- <div class="flex flex-col space-x-2">
- <div class="px-2 py-1 rounded text-sm" id="candidate-answer" style="font-size: 14px;">候选人回答:</div>
- <div class="flex-1">
- <p class="text-gray-700 mb-0" style="font-size: 14px; line-height: 20px; color: #808080;">{{ getAnswerText(record.answer) }}</p>
- </div>
- </div>
- </div>
-
- <div>
- </div>
- </div>
- </div>
- <!-- 左侧视频播放器 -->
- <div class="w-1/3">
- <div class="video-container">
- <video
- class="w-full h-full object-cover rounded-lg"
- controls
- :src="record.video_url"
- preload="metadata"
- :poster="fallbackImageBase64Ref"
- @loadeddata="handleVideoLoaded"
- @error="handleVideoError"
- >
- 您的浏览器不支持视频播放。
- </video>
- </div>
- </div>
- </div>
-
- <!-- 追问题列表 -->
- <div v-if="record.follow_up_questions && record.follow_up_questions.length > 0"
- class="mt-2 border-gray-200">
- <div v-for="(followUp, fIndex) in record.follow_up_questions.slice(-1)"
- :key="fIndex"
- class="">
- <div class="flex items-start space-x-2">
-
- <div class="flex-1">
-
- <!-- 追问题的视频和答案布局 -->
- <div class="mt-2">
- <div class="flex space-x-4">
- <!-- 右侧答案和评分 -->
- <div class="w-2/3">
- <div class=" p-4 rounded-xl bg-white">
- <div class="">
- <div class="flex items-start space-x-2">
- <div class="bg-purple-100 text-purple-800 px-2 py-1 rounded text-sm" style="font-size: 14px;background-color: #fdd3bd; color:#f7681d;">追问题</div>
- <!-- <div class="bg-green-100 text-green-800 px-2 py-1 rounded text-sm">候选人</div> -->
- <div class="flex-1">
- <span class="font-medium text-gray-800" style="font-size: 14px;">{{ followUp.question }}</span>
- <p class="text-gray-700 mb-0" style="font-size: 14px; line-height: 20px; color: #808080;">{{ followUp.answer }}</p>
- </div>
- </div>
- </div>
-
- <div>
- <!-- <div class="flex items-start space-x-2">
- <div class="bg-yellow-100 text-yellow-800 px-2 py-1 rounded text-sm">AI评分</div>
- <div class="flex-1">
- <p class="text-gray-600 m-0">{{ followUp.analysis }}</p>
- <div class="mt-1 text-blue-500">得分:{{ followUp.score }}</div>
- </div>
- </div> -->
- </div>
- </div>
- </div>
- <!-- 左侧视频播放器 -->
- <div v-if="followUp.video_url" class="w-1/3">
- <div class="video-container">
- <video
- class="w-full h-full object-cover rounded-lg"
- controls
- :src="followUp.video_url"
- preload="metadata"
- :poster="fallbackImageBase64Ref"
- @loadeddata="handleVideoLoaded"
- @error="handleVideoError"
- >
- 您的浏览器不支持视频播放。
- </video>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- ai评分 -->
- <div class="flex flex-col items-start bg-[#f8f8f8] p-4 rounded-lg">
- <div class="flex items-center">
- <div class="text-[14px] text-[#000] mr-2">本题评分:</div>
- <div class="text-[#409EFF] font-medium">{{ record.score }}分</div>
- </div>
- <div class="flex ml-0">
- <div class="text-[14px] text-[#f7681d] mr-2">整体分析:</div>
- <div class="analysis-content flex-1">
- <p class="text-[14px] text-[#666666] m-0 ml-4 analysis-text">
- {{ formatAnalysis(record.analysis) }}
- </p>
- </div>
- </div>
- <div class="flex items-center">
- <div class="text-[14px] text-[#666666] mr-2">考核点:</div>
- <div class="analysis-content flex-1">
- <div class="assessment-points">
- <!-- 从分析文本中提取的考核点 -->
- <template v-for="(point, index) in extractAssessmentPoints(record.analysis)" :key="index">
- <div class="assessment-item">
- <span class="point-name">{{ point.name }}</span>
- <!-- <span class="point-score" :class="getScoreClass(point.score)">{{ point.score }}</span> -->
- </div>
- <!-- 添加分隔符,除了最后一项 -->
- <span v-if="index < extractAssessmentPoints(record.analysis).length - 1" class="separator">/</span>
- </template>
- </div>
- </div>
- <div class="progress-bar" style="margin-left: 20px;width: 180px; font-size: 12px;color: #808080;">
- <el-progress
- :percentage="Number(record.score)"
- :stroke-width="6"
- :format="formats"
- :color="getProgressColor(record.score)"
- class="custom-progress"
- style="font-size: 12px;color: #808080;"
- />
- </div>
- </div>
- </div>
- </div>
-
- </div>
- </div>
- </div>
- <!-- 追问题列表 -->
- <div v-if="followUpQuestions && followUpQuestions.length > 0"
- class="mt-2 border-gray-200">
- <div v-for="(followUp, fIndex) in [followUpQuestions[followUpQuestions.length - 1]]"
- :key="fIndex"
- class="">
- <div class="flex items-start space-x-2 pb-4" >
- <!-- {{ JSON.stringify(followUp.user_text) }} -->
- <div class="px-2 py-1 rounded text-sm" style="font-size: 14px; font-weight: 600; font-family: 微软雅黑;">候选人提问:</div>
- <div class="flex-1">
- <span class="text-gray-800 color-black " style="font-size: 14px;">{{ followUp.user_text }}</span>
- </div>
- </div>
- <div class="bg-white p-4 rounded-xl mb-4">
- <div class="">
- <div class="flex flex-col space-x-2">
- <div class="px-2 py-1 rounded text-sm" id="candidate-answer" style="font-size: 14px;">智能体回答:</div>
- <div class="flex-1">
- <p class="text-gray-700 mb-0" style="font-size: 14px; line-height: 20px; color: #808080;">{{ followUp.ai_reply }}</p>
- </div>
- </div>
- </div>
-
- <div>
- </div>
- </div>
- <!-- <div class="flex-1">
- <span class="text-gray-800 color-black " style="font-size: 14px;">{{ followUp.ai_reply }}</span>
- </div> -->
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 将导出按钮移到这里,添加fixed-btn类 -->
- <el-button
- type="primary"
- circle
- class="export-btn fixed-btn"
- :loading="exporting"
- @click="exportPDF"
- >
- <el-icon><Download /></el-icon>
- </el-button>
- <!-- <el-button
- type="primary"
- size="small"
- @click="exportPDF"
- :loading="exporting"
- class="export-btn fixed-btn"
- >
- <i class="el-icon-download"></i>
- {{ exporting ? '导出中...' : '导出PDF' }}
- </el-button> -->
- </div>
- <!-- 添加个人详细信息弹窗 -->
- <el-dialog
- title="个人详细信息"
- v-model="showInfoDialog"
- width="60%"
- :before-close="handleDialogClose"
- class="info-dialog"
- >
- <div class="info-content">
- <div class="info-section">
- <h4>基本信息</h4>
- <div class="info-grid">
- <div class="info-item">
- <span class="label">姓名:</span>
- <span class="value">{{ userProfile.name }}</span>
- </div>
- <div class="info-item">
- <span class="label">性别:</span>
- <span class="value">{{ userProfile.gender }}</span>
- </div>
- <div class="info-item">
- <span class="label">年龄:</span>
- <span class="value">{{ userProfile.age }}岁</span>
- </div>
- <div class="info-item">
- <span class="label">身份证:</span>
- <span class="value">{{ userProfile.idCard }}</span>
- </div>
- <div class="info-item">
- <span class="label">民族:</span>
- <span class="value">{{ userProfile.ethnicity }}</span>
- </div>
- <div class="info-item">
- <span class="label">政治面貌:</span>
- <span class="value">{{ userProfile.politicalStatus }}</span>
- </div>
- <div class="info-item">
- <span class="label">婚姻状况:</span>
- <span class="value">{{ userProfile.maritalStatus }}</span>
- </div>
- <div class="info-item">
- <span class="label">身高:</span>
- <span class="value">{{ userProfile.height }}</span>
- </div>
- <div class="info-item">
- <span class="label">体重:</span>
- <span class="value">{{ userProfile.weight }}</span>
- </div>
- </div>
- </div>
-
- <div class="info-section">
- <h4>联系方式</h4>
- <div class="info-grid">
- <div class="info-item">
- <span class="label">手机号码:</span>
- <span class="value">{{ userProfile.phone }}</span>
- </div>
- <div class="info-item">
- <span class="label">籍贯:</span>
- <span class="value">{{ userProfile.nativePlace }}</span>
- </div>
- <div class="info-item">
- <span class="label">现居地址:</span>
- <span class="value">{{ userProfile.address }}</span>
- </div>
- </div>
- </div>
- <div class="info-section">
- <h4>教育背景</h4>
- <div class="info-grid">
- <div class="info-item">
- <span class="label">学历:</span>
- <span class="value">{{ userProfile.education }}</span>
- </div>
- <div class="info-item">
- <span class="label">毕业院校:</span>
- <span class="value">{{ userProfile.schoolName }}</span>
- </div>
- <div class="info-item">
- <span class="label">专业:</span>
- <span class="value">{{ userProfile.major }}</span>
- </div>
- <div class="info-item">
- <span class="label">毕业时间:</span>
- <span class="value">{{ userProfile.graduationDate }}</span>
- </div>
- </div>
- </div>
- <div class="info-section">
- <h4>工作信息</h4>
- <div class="info-grid">
- <div class="info-item">
- <span class="label">当前公司:</span>
- <span class="value">{{ userProfile.currentCompany }}</span>
- </div>
- <div class="info-item">
- <span class="label">所在部门:</span>
- <span class="value">{{ userProfile.department }}</span>
- </div>
- <div class="info-item">
- <span class="label">当前职位:</span>
- <span class="value">{{ userProfile.position }}</span>
- </div>
- <div class="info-item">
- <span class="label">工作经验:</span>
- <span class="value">{{ userProfile.experience }}</span>
- </div>
- <div class="info-item">
- <span class="label">期望薪资:</span>
- <span class="value">{{ userProfile.expectedSalary }}</span>
- </div>
- </div>
- </div>
- <div class="info-section">
- <h4>其他信息</h4>
- <div class="info-grid">
- <div class="info-item">
- <span class="label">特长爱好:</span>
- <span class="value">{{ userProfile.specialties }}</span>
- </div>
- </div>
- </div>
- </div>
- </el-dialog>
- <!-- 添加肢体核验结果弹窗 -->
- <el-dialog
- title="肢体核验结果"
- v-model="showBodyVerification"
- width="80%"
- :before-close="handleBodyVerificationClose"
- class="body-verification-dialog"
- >
- <!-- 将原来的手势验证内容移到这里 -->
- <div class="hand-verification">
- <div class="grid grid-cols-2 gap-8">
- <!-- 左手验证结果 -->
- <div>
- <h4 class="text-gray-600 mb-2">左手手势验证</h4>
- <div class="grid grid-cols-3 gap-2">
- <div v-for="(photo, index) in getHandPhotos('left')"
- :key="index"
- class="relative aspect-square rounded-lg overflow-hidden bg-gray-100"
- :class="{'border-2': photo.part_verification,
- 'border-green-500': photo.part_verification?.is_correct_part,
- 'border-red-500': photo.part_verification && !photo.part_verification.is_correct_part}"
- >
- <!-- 使用 el-tooltip 包裹内容 -->
- <el-tooltip
- v-if="photo.part_verification && !photo.part_verification.is_correct_part"
- :content="photo.part_verification.explanation || '未提供失败原因'"
- placement="top"
- effect="dark"
- :show-after="200"
- >
- <div class="w-full h-full">
- <img :src="photo.url"
- :alt="photo.description"
- class="w-full h-full object-cover"
- @error="handleImageError">
-
- <!-- 底部状态显示 -->
- <div class="absolute bottom-0 left-0 right-0 py-1 px-2 text-xs text-center text-white z-10"
- :class="{
- 'bg-green-500 bg-opacity-90': photo.part_verification?.is_correct_part,
- 'bg-red-500 bg-opacity-90': photo.part_verification && !photo.part_verification.is_correct_part
- }">
- {{ photo.part_verification?.is_correct_part ? '通过' : '未通过' }}
- </div>
- </div>
- </el-tooltip>
- <template v-else>
- <img :src="photo.url"
- :alt="photo.description"
- class="w-full h-full object-cover"
- @error="handleImageError">
-
- <!-- 底部状态显示 -->
- <div v-if="photo.part_verification"
- class="absolute bottom-0 left-0 right-0 py-1 px-2 text-xs text-center text-white z-10"
- :class="{
- 'bg-green-500 bg-opacity-90': photo.part_verification.is_correct_part,
- 'bg-red-500 bg-opacity-90': !photo.part_verification.is_correct_part
- }">
- {{ photo.part_verification.is_correct_part ? '通过' : '未通过' }}
- </div>
- </template>
- </div>
- </div>
- </div>
- <!-- 右手验证结果 -->
- <div>
- <h4 class="text-gray-600 mb-2">右手手势验证</h4>
- <div class="grid grid-cols-3 gap-2">
- <div v-for="(photo, index) in getHandPhotos('right')"
- :key="index"
- class="relative aspect-square rounded-lg overflow-hidden bg-gray-100"
- :class="{'border-2': photo.part_verification,
- 'border-green-500': photo.part_verification?.is_correct_part,
- 'border-red-500': photo.part_verification && !photo.part_verification.is_correct_part}"
- >
- <!-- 使用 el-tooltip 包裹内容 -->
- <el-tooltip
- v-if="photo.part_verification && !photo.part_verification.is_correct_part"
- :content="photo.part_verification.explanation || '未提供失败原因'"
- placement="top"
- effect="dark"
- :show-after="200"
- >
- <div class="w-full h-full">
- <img :src="photo.url"
- :alt="photo.description"
- class="w-full h-full object-cover"
- @error="handleImageError">
-
- <!-- 底部状态显示 -->
- <div class="absolute bottom-0 left-0 right-0 py-1 px-2 text-xs text-center text-white z-10"
- :class="{
- 'bg-green-500 bg-opacity-90': photo.part_verification?.is_correct_part,
- 'bg-red-500 bg-opacity-90': photo.part_verification && !photo.part_verification.is_correct_part
- }">
- {{ photo.part_verification?.is_correct_part ? '通过' : '未通过' }}
- </div>
- </div>
- </el-tooltip>
- <template v-else>
- <img :src="photo.url"
- :alt="photo.description"
- class="w-full h-full object-cover"
- @error="handleImageError">
-
- <!-- 底部状态显示 -->
- <div v-if="photo.part_verification"
- class="absolute bottom-0 left-0 right-0 py-1 px-2 text-xs text-center text-white z-10"
- :class="{
- 'bg-green-500 bg-opacity-90': photo.part_verification.is_correct_part,
- 'bg-red-500 bg-opacity-90': !photo.part_verification.is_correct_part
- }">
- {{ photo.part_verification.is_correct_part ? '通过' : '未通过' }}
- </div>
- </template>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- </el-dialog>
- </div>
- </template>
- <script>
- import { use } from 'echarts/core'
- import { CanvasRenderer } from 'echarts/renderers'
- import { RadarChart } from 'echarts/charts'
- import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
- import VChart from 'vue-echarts'
- import { BarChart } from 'echarts/charts'
- import { GridComponent } from 'echarts/components'
- // 引入html2canvas和jspdf
- import html2canvas from 'html2canvas'
- import jsPDF from 'jspdf'
- import { Share, Download, Printer, ArrowUp, User } from '@element-plus/icons-vue'
- import { ElMessage } from 'element-plus'
- use([
- CanvasRenderer,
- RadarChart,
- TitleComponent,
- TooltipComponent,
- LegendComponent,
- BarChart,
- GridComponent
- ])
- export default {
- name: 'JobApplicationReport',
- components: {
- VChart
- },
- data() {
- return {
- userInfo: {
- avatar: '/@/assets/default-avatar.png',
- name: '张某三',
- interviewTime: '2021-06-30 18:00',
- duration: '18分 12秒',
- idNumber: '24893119999999999',
- phone: '14893725981',
- pass: 60,
- visual_analysis_done:false
- },
- totalScore: 52.0,
- abilityItems: [],
- isPassed: false,
- hireRecommendation:'',
- failReason: '候选人答题过程中存在非正常表现和应答,同时,可行性较为不足,候选人表现出来的综合能力也不符合岗位要求的行为和动机表现,在特定学习方面,候选人未能呈现出明显的优势和发展潜质。',
- qualityDetails: {
- strengths: [],
- weaknesses: []
- },
- activeTab: 'comprehensive',
- tabs: [
- { id: 'comprehensive', name: '综合评价' },
- { id: 'ability', name: '能力素质' },
- { id: 'cheat', name: '作弊检测' },
- { id: 'psychology', name: '心理检测' },
- { id: 'body', name: '肢体检测' },
- { id: 'personal-info', name: '个人详细信息', isInfo: true },
- { id: 'answers', name: '问答记录' },
- { id: 'other-answers', name: '其余答题详情', isLink: true }
- ],
- isNavFixed: false,
- navHeight: 0,
- navOffsetTop: 0,
- loading: false,
- error: null,
- // 分析结果中英文对照表
- analysisMap: {
- 'clear_expression': '表达清晰',
- 'logical_thinking': '逻辑思维能力强',
- 'professional_knowledge': '专业知识扎实',
- 'communication_skills': '沟通能力出色',
- 'problem_solving': '问题解决能力强',
- 'team_collaboration': '团队协作意识好',
- 'learning_ability': '学习能力强',
- 'lack_experience': '经验不足',
- 'weak_professional': '专业知识有待提升',
- 'poor_expression': '表达能力需要提高',
- 'weak_logic': '逻辑思维需要加强',
- 'weak_communication': '沟通技巧需要改进',
- 'weak_teamwork': '团队协作意识不足',
- 'weak_learning': '学习能力有待提升'
- },
- psychologyData: {
- score: 35,
- description: '轻微焦虑或负面情绪,仍具备岗位适应力。候选人在某些方面可能存在轻微的心理压力,但总体上仍保持稳定,基本符合岗位要求。',
- recommendation: '可考虑录取'
- },
- redLineQuestions: {
- allCorrect: false,
- failedQuestions: []
- },
- // 修改手势验证数据结构
- handVerificationData: {
- left: [],
- right: []
- },
- // 添加新的数据属性
- reportTime: '2025.5.19',
- reportId: '2489372598',
- isMobile: false,
- showInfoDialog: false,
- userProfile: {
- name: '',
- gender: '',
- age: '',
- education: '',
- phone: '',
- email: '',
- address: '',
- position: '',
- experience: '',
- expectedSalary: '',
- idCard: '',
- height: '',
- weight: '',
- nativePlace: '',
- politicalStatus: '',
- ethnicity: '',
- maritalStatus: '',
- specialties: '',
- schoolName: '',
- major: '',
- graduationDate: '',
- currentCompany: '',
- department: '',
- },
- showBodyVerification: false, // 添加控制弹窗显示的数据
- competencyMap: {
- 'communication_cooperation': '团队协作能力',
- 'learning_ability': '应变能力',
- 'service_awareness': '服务意识',
- 'customer_insight': '客户需求洞察力',
- 'position_matching': '应变能力',
- 'communication_expression': '沟通表达能力'
- },
- // 修改雷达图数据结构
- radarData: {
- indicator: [
- { name: '团队协作能力', value: 50, max: 100 },
- { name: '应变能力', value: 50, max: 100 },
- { name: '服务意识', value: 50, max: 100 },
- { name: '客户需求洞察力', value: 50, max: 100 },
- { name: '应变能力', value: 50, max: 100 },
- { name: '沟通表达能力', value: 50, max: 100 }
- ],
- values: [50, 50, 50, 50, 50, 50] // 初始值设为0
- },
- exporting: false, // 添加导出状态控制
- radarChartInstance: null,
- interviewRecords: [], // 存储问答记录
- followUpQuestions: [], // 存储追问题
- noTableHeight: 0
- }
- },
- async created() {
- await this.fetchApplicationDetail()
- },
- mounted() {
- // 获取导航栏的初始位置和高度
- this.$nextTick(() => {
- const navElement = this.$refs.navTabs
- if (navElement) {
- this.navHeight = navElement.offsetHeight
- this.navOffsetTop = navElement.offsetTop
-
- // 添加滚动监听
- window.addEventListener('scroll', this.handleScroll)
- }
- })
- // 检测设备类型
- this.checkDevice();
- // 监听窗口大小变化
- window.addEventListener('resize', this.checkDevice);
- // 添加获取图表实例的ref
- this.$nextTick(() => {
- // 保存图表实例的引用
- this.radarChartInstance = this.$refs.radarChart
- })
- // 等待组件渲染完成后保存图表实例
- this.$nextTick(() => {
- if (this.$refs.radarChart) {
- this.radarChartInstance = this.$refs.radarChart
- }
- })
- },
- beforeDestroy() {
- // 移除滚动监听
- window.removeEventListener('scroll', this.handleScroll)
- // 移除监听器
- window.removeEventListener('resize', this.checkDevice);
- },
- computed: {
- radarOption() {
- return {
- radar: {
- indicator: this.radarData.indicator,
- center: ['50%', '50%'],
- radius: '65%',
- splitNumber: 4,
- shape: 'circle',
- axisName: {
- color: '#666',
- fontSize: 12,
- formatter: (name) => {
- const index = this.radarData.indicator.findIndex(item => item.name === name);
- const value = this.radarData.values[index];
- // 添加中文释义
- const nameMappings = {
- '团队协作能力': '团队协作',
- '应变能力': '应变能力',
- '服务意识': '服务意识',
- '客户需求洞察力': '需求洞察',
- '沟通表达能力': '沟通表达'
- };
- const displayName = nameMappings[name] || name;
- return `${value}\n${displayName}`;
- }
- },
- nameGap: 15,
- axisLabel: {
- show: false
- },
- splitArea: {
- show: true,
- areaStyle: {
- color: ['#fff']
- }
- },
- splitLine: {
- show: true,
- lineStyle: {
- color: '#E7E9ED',
- type: 'solid',
- width: 1
- }
- },
- axisLine: {
- show: true,
- lineStyle: {
- color: '#E7E9ED',
- width: 1
- }
- }
- },
- series: [{
- type: 'radar',
- symbol: 'none',
- itemStyle: {
- normal: {
- lineStyle: {
- color: '#c1dafc',
- width: 2
- },
- areaStyle: {
- type: 'default',
- color: 'rgba(193, 218, 252, 0.6)',
- shadowBlur: 10,
- shadowColor: 'rgba(193, 218, 252, 0.5)',
- shadowOffsetY: 5
- }
- }
- },
- data: [{
- value: this.radarData.values
- }]
- }]
- }
- },
- // 添加新的计算属性
- getPsychologyScoreClass() {
- const score = this.psychologyData.score;
- if (score <= 20) return 'low-risk';
- if (score <= 55) return 'medium-risk';
- return 'high-risk';
- },
-
- getPsychologyRiskLevel() {
- const score = this.psychologyData.score;
- if (score <= 20) return '低风险';
- if (score <= 55) return '中风险';
- return '高风险';
- }
- },
- methods: {
- async fetchApplicationDetail() {
- try {
- const application_id = this.$route.query.id || this.$route.params.id
- console.log(application_id)
- this.loading = true
- const response = await fetch(
- `${import.meta.env.VITE_API_URL}/api/job/application_detail?tenant_id=${1}&application_id=${application_id}`
- )
- if (!response.ok) {
- throw new Error('获取数据失败')
- }
- const data = await response.json()
-
- if (data.code === 2000) {
- // 添加数据安全检查
- const applicationData = data.data || {}
- this.reportTime = applicationData.application?.update_datetime || ''
- // 更新用户信息
- this.userInfo = {
- avatar: this.getFacePhoto(applicationData.posture_photos) || '/@/assets/default-avatar.png',
- name: applicationData.applicant?.name || '未知',
- interviewTime: applicationData.application?.interview_completion_time || '-',
- duration: applicationData.application?.interview_duration_formatted || '-',
- idNumber: applicationData.applicant?.id_card || '-',
- phone: applicationData.applicant?.phone || '-',
- pass: applicationData.application?.comprehensive_score || 0,
- visual_analysis_done:applicationData.application.analysis_status.visual_analysis_done
- }
- this.reportId = applicationData.application?.report_id || ''
- // 处理手势验证照片数据
- if (applicationData.posture_photos && Array.isArray(applicationData.posture_photos)) {
- // 分类处理左右手照片
- const leftHandPhotos = applicationData.posture_photos.filter(photo =>
- photo?.description?.includes('left_') || photo?.description?.includes('左手')
- ) || []
-
- const rightHandPhotos = applicationData.posture_photos.filter(photo =>
- photo?.description?.includes('right_') || photo?.description?.includes('右手')
- ) || []
- // 更新左手照片数据
- this.handVerificationData.left = leftHandPhotos.map(photo => ({
- url: photo?.photo_url || '/@/assets/default-image.png',
- description: this.getPhotoDescription(photo?.description || ''),
- part_verification: {
- is_correct_part: photo?.part_verification?.is_correct_part ?? true,
- explanation: photo?.part_verification?.explanation || '手势验证通过'
- }
- }))
- // 更新右手照片数据
- this.handVerificationData.right = rightHandPhotos.map(photo => ({
- url: photo?.photo_url || '/@/assets/default-image.png',
- description: this.getPhotoDescription(photo?.description || ''),
- part_verification: {
- is_correct_part: photo?.part_verification?.is_correct_part ?? true,
- explanation: photo?.part_verification?.explanation || '手势验证通过'
- }
- }))
- }
- // 更新其他数据,添加空值检查
- if (applicationData.application) {
- this.totalScore = applicationData.application.comprehensive_score || 0
- this.hireRecommendation = applicationData.application.hire_recommendation || ''
- this.failReason = applicationData.application.hire_reason || ''
- }
- // 更新能力标签得分数据,添加空值检查
- const videoAnalysisData = applicationData.application?.comprehensive_analysis?.video_analysis_data
- if (videoAnalysisData?.competency_scores) {
- this.abilityItems = Object.entries(videoAnalysisData.competency_scores)
- .map(([key, item]) => ({
- tag_name: this.getCompetencyName(key) || item.tag_name || key,
- weighted_score: Math.round(item.weighted_score || 0)
- }))
- } else {
- // 设置默认的能力项
- this.abilityItems = [
- { tag_name: '团队协作能力', weighted_score: 0 },
- { tag_name: '应变能力', weighted_score: 0 },
- { tag_name: '服务意识', weighted_score: 0 },
- { tag_name: '客户需求洞察力', weighted_score: 0 },
- { tag_name: '沟通表达能力', weighted_score: 0 }
- ]
- }
- // 更新优势和劣势数据,添加空值检查
- if (videoAnalysisData) {
- this.qualityDetails = {
- strengths: videoAnalysisData.strengths || [],
- weaknesses: videoAnalysisData.weaknesses || []
- }
- } else {
- this.qualityDetails = {
- strengths: [],
- weaknesses: []
- }
- }
- // 更新红线题数据
- if (applicationData.required_questions_summary) {
- this.redLineQuestions = {
- allCorrect: applicationData.required_questions_summary.all_correct || false,
- failedQuestions: applicationData.required_questions_summary.failed_questions_details || []
- }
- }
- // 获取心理测评分数
- const psychologyScore = applicationData.scoring_summary?.total_score_obtained
- // 更新心理检测组件数据
- this.psychologyData = {
- score: psychologyScore || 0,
- description: this.getPsychologyDescription(psychologyScore),
- recommendation: this.getHireRecommendation(psychologyScore)
- }
- // 更新雷达图数据,添加空值检查
- if (videoAnalysisData?.competency_scores) {
- this.updateRadarData(videoAnalysisData.competency_scores)
- } else {
- // 设置默认的雷达图数据
- this.radarData = {
- indicator: [
- { name: '团队协作能力', max: 100 },
- { name: '应变能力', max: 100 },
- { name: '服务意识', max: 100 },
- { name: '客户需求洞察力', max: 100 },
- { name: '沟通表达能力', max: 100 }
- ],
- values: [0, 0, 0, 0, 0]
- }
- }
- // 更新追问题列表
- this.followUpQuestions = applicationData.follow_up_records.map(item => {
- let parsedUserText = null;
- try {
- // 尝试解析user_text字符串为对象
- parsedUserText = JSON.parse(item.user_text.replace(/'/g, '"'));
- console.log(parsedUserText)
- } catch (error) {
- console.error('Failed to parse user_text:', error);
- }
-
- // 获取text值并去除双引号
- const textValue = parsedUserText?.text || '暂无提问';
- const cleanText = textValue.replace(/^"|"$/g, ''); // 去除开头和结尾的双引号
-
- return {
- ...item,
- user_text: cleanText
- }
- });
- console.log(this.followUpQuestions)
- // 添加获取问答记录的逻辑
- if (data.data?.interview_progress) {
- this.interviewRecords = this.processInterviewRecords(data.data.interview_progress)
- console.log(this.interviewRecords)
- }
-
- }
- } catch (error) {
- console.error('获取应用详情失败:', error)
- this.error = error.message
- } finally {
- this.loading = false
- }
- },
- formats(percentage) {
- console.log(percentage)
- return `${percentage}分`
- },
- format(percentage) {
- return `${percentage}分`
- },
- scrollToSection(tabId) {
- // 如果是答题记录标签,则进行路由跳转
- if (tabId === 'other-answers') {
- // 假设当前路由中有 applicationId 参数
- const applicationId = this.$route.query.id || this.$route.params.id
- const baseUrl = window.location.origin;
- // 使用window.open在新标签页打开
- window.open(`${baseUrl}/#/topic?applicationId=${applicationId}`, '_blank')
- return
- }
- // 其他标签的原有滚动逻辑
- this.activeTab = tabId
- const element = this.$refs[tabId]
- if (element) {
- element.scrollIntoView({ behavior: 'smooth' })
- }
- },
- handleScroll() {
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop
-
- // 更新固定状态
- this.isNavFixed = scrollTop > this.navOffsetTop
- // 更新当前激活的标签
- this.updateActiveTab(scrollTop)
- },
- updateActiveTab(scrollTop) {
- const navHeight = this.navHeight
-
- // 获取所有section的位置
- const sections = this.tabs.map(tab => {
- const element = this.$refs[tab.id]
- return {
- id: tab.id,
- top: element.getBoundingClientRect().top + window.pageYOffset - navHeight - 20
- }
- })
- // 找到当前滚动位置对应的section
- for (let i = sections.length - 1; i >= 0; i--) {
- if (scrollTop >= sections[i].top) {
- this.activeTab = sections[i].id
- break
- }
- }
- },
- // 获取分析结果的中文释义
- getChineseAnalysis(key) {
- return this.analysisMap[key] || key
- },
- // 添加获取心理状态描述的方法
- getPsychologyDescription(score) {
- if (score === undefined) return '未进行心理测评或数据缺失'
-
- if (score <= 20) {
- return '心理状态健康,情绪稳定、认知正常。候选人在心理测评中表现出稳定的情绪状态和健康的心理特质,适合岗位要求。'
- } else if (score <= 35) {
- return '轻微焦虑或负面情绪,仍具备岗位适应力。候选人在某些方面可能存在轻微的心理压力,但总体上仍保持稳定,基本符合岗位要求。'
- } else if (score <= 55) {
- return '存在一定情绪波动或压力反应。候选人在测评中表现出一定程度的心理压力或情绪波动,建议进一步面谈评估。'
- } else if (score <= 70) {
- return '心理压力较大,可能影响工作稳定性。候选人在测评中表现出较明显的心理压力或情绪不稳定性,建议慎重录用或考虑调岗。'
- } else {
- return '可能存在较严重心理或精神问题。候选人在测评中表现出明显的心理或情绪问题,不建议录用。'
- }
- },
- // 添加获取录用建议的方法
- getHireRecommendation(score) {
- if (score === undefined) return '无法给出建议'
-
- if (score <= 20) {
- return '建议优先录取'
- } else if (score <= 35) {
- return '可考虑录取'
- } else if (score <= 55) {
- return '建议进一步面谈评估'
- } else if (score <= 70) {
- return '慎重录用或建议调岗'
- } else {
- return '不建议录用'
- }
- },
- // 添加照片描述转换方法
- getPhotoDescription(description) {
- const descriptionMap = {
- 'left_palm': '左手手心',
- 'left_back': '左手手背',
- 'left_fist': '左手腕拳',
- 'right_palm': '右手手心',
- 'right_back': '右手手背',
- 'right_fist': '右手腕拳',
- // 添加中文描述的映射
- '左手手心': '左手手心',
- '左手手背': '左手手背',
- '左手腕拳': '左手腕拳',
- '右手手心': '右手手心',
- '右手手背': '右手手背',
- '右手腕拳': '右手腕拳'
- }
- return descriptionMap[description] || description
- },
- // 修改获取手部照片的方法
- getHandPhotos(hand) {
- const photos = this.handVerificationData[hand] || []
- return photos.map(photo => ({
- url: photo.url,
- status: 'normal',
- photo_id: 1,
- detections: [],
- description: photo.description,
- photo_index: 1,
- analysis_model: '',
- part_verification: photo.part_verification,
- analysis_timestamp: '',
- overall_assessment: '正常'
- }))
- },
- // 图片错误处理函数保持不变
- handleImageError(event) {
- const imgElement = event.target
- if (imgElement) {
- imgElement.src = '/@/assets/default-image.png'
- }
- },
- checkDevice() {
- this.isMobile = window.innerWidth <= 768;
- },
- async handleTabClick(tab) {
- if (tab.isInfo) {
- // 打开弹窗前获取最新的用户信息
- await this.fetchUserProfile();
- this.showInfoDialog = true;
- } else if (tab.isLink) {
- this.scrollToSection(tab.id);
- } else {
- this.scrollToSection(tab.id);
- }
- },
- handleDialogClose() {
- this.showInfoDialog = false;
- },
- async fetchUserProfile() {
- try {
- const userId = this.$route.query.application_id;
- const tenantId = 1;
-
- const response = await fetch(
- `${import.meta.env.VITE_API_URL}/api/system/wechat/user/profile/get?user_id=${userId}&tenant_id=${tenantId}`
- );
- if (!response.ok) {
- throw new Error('获取用户信息失败');
- }
- const data = await response.json();
-
- if (data.success && data.profile) {
- const basicInfo = data.profile.basic_info;
- const education = data.profile.educations[0] || {};
- const workExp = data.profile.work_experiences[0] || {};
- // 更新用户详细信息
- this.userProfile = {
- name: basicInfo.name || this.userInfo.name,
- gender: basicInfo.gender === 1 ? '男' : '女',
- age: basicInfo.age || '',
- education: this.getEducationLevel(education.degree),
- phone: basicInfo.phone || this.userInfo.phone,
- email: '', // API中没有邮箱字段
- address: basicInfo.current_address || '',
- position: workExp.position || '',
- experience: this.formatWorkExperience(workExp),
- expectedSalary: basicInfo.expected_salary ? `${basicInfo.expected_salary}元/月` : '',
- idCard: basicInfo.id_card || '',
- height: basicInfo.height ? `${basicInfo.height}cm` : '',
- weight: basicInfo.weight ? `${basicInfo.weight}kg` : '',
- nativePlace: basicInfo.native_place || '',
- politicalStatus: basicInfo.political_status || '',
- ethnicity: basicInfo.ethnicity || '',
- maritalStatus: this.getMaritalStatus(basicInfo.marital_status),
- specialties: basicInfo.specialties || '',
- schoolName: education.school_name || '',
- major: education.major || '',
- graduationDate: education.end_date || '',
- currentCompany: workExp.company_name || '',
- department: workExp.department || '',
- }
- }
- } catch (error) {
- console.error('获取用户详细信息失败:', error);
- }
- },
- getEducationLevel(degree) {
- const degrees = {
- 1: '专科',
- 2: '本科',
- 3: '硕士',
- 4: '博士'
- };
- return degrees[degree] || '未知';
- },
- formatWorkExperience(workExp) {
- if (!workExp.start_date) return '无工作经验';
- const start = new Date(workExp.start_date);
- const end = workExp.end_date ? new Date(workExp.end_date) : new Date();
- const years = Math.floor((end - start) / (365 * 24 * 60 * 60 * 1000));
- return `${years}年`;
- },
- getMaritalStatus(status) {
- return status === 0 ? '未婚' : '已婚';
- },
- getPositionLabel(hand, index) {
- // 根据照片的类型来确定位置标签
- const photoType = this.getPhotoType(hand, index);
- const positions = {
- left: {
- palm: '①左手手心',
- back: '②左手手背',
- fist: '③左手腕拳'
- },
- right: {
- palm: '④右手手心',
- back: '⑤右手手背',
- fist: '⑥右手腕拳'
- }
- };
- return positions[hand]?.[photoType] || `${hand === 'left' ? '左' : '右'}手部位${index + 1}`;
- },
- getDefaultDescription(hand, index) {
- // 根据照片的类型来确定描述
- const photoType = this.getPhotoType(hand, index);
- const descriptions = {
- left: {
- palm: '手掌纹理清晰,活动自然',
- back: '手背皮肤正常,关节灵活',
- fist: '腕关节活动度正常'
- },
- right: {
- palm: '手掌纹理清晰,活动自然',
- back: '手背皮肤正常,关节灵活',
- fist: '腕关节活动度正常'
- }
- };
- return descriptions[hand]?.[photoType] || '手部动作正常';
- },
- // 新增方法:根据照片信息确定类型
- getPhotoType(hand, index) {
- const photo = this.handVerificationData[hand]?.[index];
- if (!photo) return null;
- // 从照片描述中提取类型
- const description = photo.description?.toLowerCase() || '';
-
- if (description.includes('palm') || description.includes('手心')) {
- return 'palm';
- } else if (description.includes('back') || description.includes('手背')) {
- return 'back';
- } else if (description.includes('fist') || description.includes('腕拳')) {
- return 'fist';
- }
-
- // 如果无法从描述中确定类型,尝试从验证结果中获取
- if (photo.part_verification?.part_type) {
- return photo.part_verification.part_type;
- }
-
- // 根据索引返回默认类型
- const defaultTypes = ['palm', 'back', 'fist'];
- return defaultTypes[index] || 'unknown';
- },
- // 添加关闭弹窗的方法
- handleBodyVerificationClose() {
- this.showBodyVerification = false
- },
- // 添加新方法:获取能力名称的中文释义
- getCompetencyName(key) {
- const competencyMap = {
- 'communication_cooperation': '团队协作能力',
- 'learning_ability': '应变能力',
- 'service_awareness': '服务意识',
- 'customer_insight': '客户需求洞察力',
- 'position_matching': '岗位匹配度',
- 'communication_expression': '沟通表达能力',
- // 可以根据需要添加更多映射
- }
- return competencyMap[key]
- },
- // 修改更新雷达图数据的方法
- updateRadarData(competencyScores) {
- if (!competencyScores) return
-
- const processedData = Object.entries(competencyScores)
- .map(([key, item]) => ({
- name: this.getCompetencyName(key) || item.tag_name || key,
- score: Math.round(item.weighted_score || 0)
- }))
- .sort((a, b) => b.score - a.score)
- .slice(0, 6)
- this.radarData = {
- indicator: processedData.map(item => ({
- name: item.name,
- max: 100
- })),
- values: processedData.map(item => item.score)
- }
- },
- // 添加检查图表实例的方法
- async ensureChartRendered() {
- let attempts = 0
- const maxAttempts = 5
-
- while (!this.$refs.radarChart?.chart && attempts < maxAttempts) {
- await new Promise(resolve => setTimeout(resolve, 200))
- attempts++
- }
-
- return this.$refs.radarChart?.chart
- },
- getFacePhoto(photos) {
- if (!photos || !Array.isArray(photos)) {
- return null;
- }
- // 定义面部照片的中文和英文关键词
- const faceKeywords = ['face', 'facial', '面部', '人脸', '头像'];
-
- // 查找包含面部关键词的照片
- const facePhoto = photos.find(photo => {
- const description = (photo?.description || '').toLowerCase();
- return faceKeywords.some(keyword => description.includes(keyword));
- });
- // 如果找到面部照片则返回URL,否则返回数组第一张照片的URL
- return facePhoto?.photo_url || photos[0]?.photo_url;
- },
- // 获取题型名称
- getQuestionTypeName(questionForm) {
- const typeMap = {
- 0: '视频问答题',
- 1: '单选题',
- 2: '多选题',
- 3: '图片选择题',
- 4: '问卷题',
- 5: '开放问答题'
- }
- return typeMap[questionForm] || '未知题型'
- },
- // 处理问答记录数据
- processInterviewRecords(records) {
- if (!records || !Array.isArray(records)) return []
-
- // 过滤并处理记录,只保留 question_form 为 0 或 5 的记录
- const mainQuestions = records
- .filter(q => (q.question_form === 0 || q.question_form === 5) && (q.video_answer || q.answer_data))
- .map(q => ({
- question: q.question_text || '未提供问题',
- answer: q.video_answer?.transcript || q.answer_data?.text_answer || '',
- analysis: q.video_answer?.ai_analysis?.comment || '',
- score: q.video_answer?.ai_score ? `${q.video_answer.ai_score}` : '',
- question_form: q.question_form,
- question_id: q.question_id,
- parent_question_id: q.parent_question_id,
- follow_up_questions: [],
- video_url: q.video_answer?.video_url || ''
- }))
- // 处理追问题,仍然只处理 question_form 为 5 的追问
- records
- .filter(q => q.question_form === 5 && q.parent_question_id)
- .forEach(followUp => {
- const parentQuestion = mainQuestions.find(
- q => q.question_id === followUp.parent_question_id
- )
- if (parentQuestion) {
- parentQuestion.follow_up_questions.push({
- question: followUp.question_text || '未提供问题',
- answer: followUp.video_answer?.transcript || '',
- analysis: followUp.video_answer?.ai_analysis?.comment || '',
- score: followUp.video_answer?.ai_score ? `${followUp.video_answer.ai_score}分` : '',
- question_form: followUp.question_form,
- question_id: followUp.question_id,
- parent_question_id: followUp.parent_question_id,
- follow_up_questions: [],
- video_url: followUp.video_answer?.video_url || ''
- })
- }
- })
- return mainQuestions
- },
- getProgressColor(score) {
- if (score >= 80) {
- return [{
- color: '#00b050', // 深绿色起点
- percentage: 0
- }, {
- color: '#6aff05', // 浅绿色终点
- percentage: 100
- }]
- } else {
- return [{
- color: '#f7681d', // 橙色起点
- percentage: 0
- }, {
- color: '#fdd1bb', // 浅橙色终点
- percentage: 100
- }]
- }
- },
- // 添加格式化分析文本的方法
- formatAnalysis(analysis) {
- if (!analysis) return '';
- // 移除开头的换行符,并确保每个评价项之间只有一个换行
- return analysis
- .replace(/^\s+/, '') // 移除开头的空白
- .replace(/【/g, '\n【') // 在评价项前添加换行
- .replace(/^\n/, ''); // 移除第一个换行符
- },
- extractAssessmentPoints(analysis) {
- if (!analysis) return [];
- // 改进的正则表达式,更精确地匹配考核点格式
- const pointsRegex = /【([^】]+)】评价:([^【]+)(?=【|$)/g;
- const points = [];
- let match;
-
- while ((match = pointsRegex.exec(analysis)) !== null) {
- const name = match[1].trim();
- const fullDetail = match[2].trim();
-
- // 提取评分等级,保持原有逻辑
- let score = '';
- if (fullDetail.includes('优秀')) score = '优秀';
- else if (fullDetail.includes('良好')) score = '良好';
- else if (fullDetail.includes('一般')) score = '一般';
- else if (fullDetail.includes('较差')) score = '较差';
- else score = '一般';
-
- // 去掉评分等级,保留详细描述
- const detail = fullDetail.replace(/(优秀|良好|一般|较差),/, '').trim();
-
- points.push({
- name,
- score,
- detail
- });
- }
-
- return points;
- },
- getScoreClass(score) {
- switch (score) {
- case '优秀':
- return 'score-excellent';
- case '良好':
- return 'score-good';
- case '一般':
- return 'score-average';
- case '较差':
- return 'score-poor';
- default:
- return 'score-average';
- }
- },
- // 添加新的计算属性
- getPsychologyScoreClass() {
- const score = this.psychologyData.score;
- if (score <= 20) return 'low-risk';
- if (score <= 55) return 'medium-risk';
- return 'high-risk';
- },
-
- getPsychologyRiskLevel() {
- const score = this.psychologyData.score;
- if (score <= 20) return '低风险';
- if (score <= 55) return '中风险';
- return '高风险';
- },
- async exportPDF() {
- try {
- this.exporting = true
-
- // 获取要导出的内容区域
- const element = document.querySelector('.report-container')
- if (!element) {
- throw new Error('未找到要导出的内容')
- }
- // 设置导出选项
- const options = {
- allowTaint: false,
- useCORS: true,
- scale: 2,
- logging: false,
- backgroundColor: '#ffffff',
- height: element.scrollHeight,
- windowHeight: element.scrollHeight,
- imageTimeout: 0,
- onclone: (doc) => {
- // 添加打印样式
- const style = doc.createElement('style')
- style.innerHTML = `
- @media print {
- body {
- -webkit-print-color-adjust: exact !important;
- print-color-adjust: exact !important;
- }
- .report-container {
- width: 100% !important;
- margin: 0 !important;
- padding: 20px !important;
- display: block !important;
- }
- .report-header {
- display: flex !important;
- justify-content: space-between !important;
- align-items: flex-end !important;
- height: 80px !important;
- margin-bottom: 30px !important;
- }
- :v-deep(.status-tag),
- .status-tag[style*="background"],
- span[class="status-tag"] {
- background: none !important;
- background-color: transparent !important;
- -webkit-print-color-adjust: exact !important;
- print-color-adjust: exact !important;
- color: #000000 !important;
- border: 1px solid #000000 !important;
- }
- /* 确保内联样式不会覆盖我们的设置 */
- span[style*="background"].status-tag {
- background: none !important;
- background-color: transparent !important;
- }
- .header {
- display: flex !important;
- gap: 20px !important;
- }
- .header-right {
- display: flex !important;
- position: relative !important;
- }
- .nav-tabs {
- display: flex !important;
- gap: 32px !important;
- justify-content: flex-start !important;
- align-items: center !important;
- }
- .evaluation-result {
- display: flex !important;
- justify-content: space-between !important;
- align-items: flex-start !important;
- }
- .score-section {
- display: flex !important;
- flex-direction: column !important;
- gap: 24px !important;
- }
- .score-section-left {
- display: flex !important;
- justify-content: flex-start !important;
- align-items: center !important;
- gap: 16px !important;
- }
- .detection-results {
- display: flex !important;
- align-items: center !important;
- gap: 8px !important;
- }
- .ability-quality {
- display: block !important;
- }
- .quality-details {
- display: block !important;
- }
- .quality-item {
- display: flex !important;
- gap: 24px !important;
- }
- .psychology_box {
- display: flex !important;
- flex-direction: row !important;
- gap: 16px !important;
- justify-content: space-between !important;
- align-items: center !important;
- }
- .detection-section-content {
- display: flex !important;
- justify-content: space-between !important;
- gap: 16px !important;
- }
- .fixed-btn {
- display: none !important;
- }
-
- /* 确保所有flex容器在打印时保持flex布局 */
- [class*="flex"] {
- display: flex !important;
- }
-
- /* 确保图表容器保持正确的尺寸 */
- .radar-chart {
- width: 500px !important;
- height: 350px !important;
- }
-
- /* 确保进度条样式正确 */
- .el-progress-bar__outer {
- height: 8px !important;
- background-color: #EBEEF5 !important;
- }
-
- .el-progress-bar__inner {
- transition: none !important;
- }
- :v-deep(.el-progress__text){
- display: none !important;
- }
-
- /* 确保文字样式正确
- .text-[14px] {
- font-size: 14px !important;
- line-height: 16px !important;
- }*/
-
- /* 确保边距和间距正确 */
- .mt-6 { margin-top: 1.5rem !important; }
- .mb-4 { margin-bottom: 1rem !important; }
- .p-4 { padding: 1rem !important; }
-
- /* 确保圆角样式正确 */
- .rounded-lg { border-radius: 0.5rem !important; }
-
- /* 确保背景色正确 */
- .bg-white { background-color: #ffffff !important; }
- .bg-gray-50 { background-color: #F9FAFB !important; }
- }
- `
- doc.head.appendChild(style)
- const allElements = doc.querySelectorAll('*')
- allElements.forEach(el => {
- el.style.visibility = 'visible'
- el.style.opacity = '1'
- })
- }
- }
- // 生成画布
- const canvas = await html2canvas(element, options)
- // 计算PDF尺寸(使用A4比例)
- const imgWidth = 595.28
- const imgHeight = 841.89
- const pageHeight = imgHeight
- const imgData = canvas.toDataURL('image/jpeg', 1.0)
- // 创建PDF
- const pdf = new jsPDF({
- orientation: 'p',
- unit: 'pt',
- format: 'a4',
- compress: true
- })
- // 计算页数
- const pageCount = Math.ceil(canvas.height * imgWidth / canvas.width / pageHeight)
- // 逐页添加内容
- for (let i = 0; i < pageCount; i++) {
- if (i > 0) {
- pdf.addPage()
- }
-
- const position = -i * pageHeight
-
- pdf.addImage(
- imgData,
- 'JPEG',
- 0,
- position,
- imgWidth,
- canvas.height * imgWidth / canvas.width,
- '',
- 'FAST'
- )
- }
- // 保存文件
- pdf.save(`AI面试结果检验报告_${this.userInfo.name || '未知'}_${this.reportId}.pdf`)
- } catch (error) {
- console.error('导出PDF失败:', error)
- ElMessage.error('导出PDF失败,请稍后重试')
- } finally {
- this.exporting = false
- }
- },
- // 添加辅助方法
- getFooterElement(remainingHeight, fillingHeight = 0) {
- const newNode = document.createElement('div')
- newNode.style.background = '#ffffff'
- newNode.style.width = 'calc(100% + 8px)'
- newNode.style.marginLeft = '-4px'
- newNode.style.marginBottom = '0px'
- newNode.classList.add('divRemove')
- newNode.style.height = (remainingHeight + fillingHeight) + 'px'
- return newNode
- },
- isSplit(nodes, index, pageHeight) {
- if (!nodes[index + 1]) return false
-
- if (nodes[index].localName !== 'tr') {
- this.noTableHeight += nodes[index].clientHeight
- }
- if (nodes[index].localName !== 'tr') {
- return nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight &&
- nodes[index + 1] &&
- nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight
- } else {
- return nodes[index].offsetTop + nodes[index].offsetHeight + this.noTableHeight < pageHeight &&
- nodes[index + 1] &&
- nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight + this.noTableHeight > pageHeight
- }
- },
- getBarChartOption(item) {
- const color = item.weighted_score >= 80 ?
- [{
- offset: 0,
- color: '#00b050'
- }, {
- offset: 1,
- color: '#6aff05'
- }] :
- [{
- offset: 0,
- color: '#f7681d'
- }, {
- offset: 1,
- color: '#fdd1bb'
- }];
- return {
- grid: {
- left: 0,
- right: 40,
- top: 0,
- bottom: 0,
- containLabel: false
- },
- xAxis: {
- type: 'value',
- show: false,
- max: 100
- },
- yAxis: {
- type: 'category',
- show: false
- },
- series: [{
- type: 'bar',
- data: [item.weighted_score],
- barWidth: 8,
- label: {
- show: true,
- position: 'right',
- formatter: '{c}分',
- fontSize: 12,
- color: '#808080'
- },
- itemStyle: {
- borderRadius: [0, 4, 4, 0],
- color: {
- type: 'linear',
- x: 0,
- y: 0,
- x2: 1,
- y2: 0,
- colorStops: color
- }
- }
- }]
- };
- },
- formatTextWithBrackets(text) {
- if (!text) return '';
- return text.replace(/【(.*?)】/g, '<span style="color:#81b337; font-weight: 500;">【$1】</span>');
- },
- formatTextWithBrackets2(text) {
- if (!text) return '';
- return text.replace(/【(.*?)】/g, '<span style="color:#fb752f; font-weight: 500;">【$1】</span>');
- },
- // 添加处理答案文本的方法
- getAnswerText(answer) {
- if (!answer) return '暂无回答';
-
- // 如果是字符串,直接返回
- if (typeof answer === 'string') {
- return answer;
- }
- console.log(answer);
- // 如果是数组,尝试获取第一个元素的text
- if (Array.isArray(answer) && answer.length > 0) {
- const firstItem = answer[0];
- if (firstItem && firstItem.text) {
- return firstItem.text;
- }
- }
-
- // 如果是对象,尝试获取text属性
- if (typeof answer === 'object' && answer.text) {
- return answer.text;
- }
-
- // 其他情况返回默认文本
- return '暂无回答';
- },
- }
- }
- </script>
- <style lang="scss" scoped>
- .outer-container {
- position: relative;
- width: 100%;
- height: 100vh;
- overflow-y: auto;
- background: #fff;
- }
- .report-container {
- /* padding: 30px; */
- margin: 0 auto 30px;
- width: 1200px;
- background: #fff;
- .header {
- display: flex;
- gap: 20px;
- background: #fff;
- border-radius: 8px;
- .header-left {
- .avatar {
- width: 150px;
- height: 150px;
- border-radius: 50%;
- object-fit: cover;
- }
- }
- .header-right {
- flex: 1;
- display: flex;
- position: relative;
- background: #f8f8f8;
- padding: 20px;
- border-radius: 8px;
- .left-section,
- .right-section {
- flex: 1;
- .info-row {
- margin-bottom: 12px;
- display: flex;
- align-items: center;
-
- &:last-child {
- margin-bottom: 0;
- }
- .label {
- width: 80px;
- color: #666;
- font-size: 14px;
- }
- .value {
- color: #333;
- font-size: 14px;
- &.verified {
- color: #67C23A;
- }
- }
- }
- }
- .stamp {
- position: absolute;
- right: 20px;
- top: 50%;
- transform: translateY(-50%);
- img {
- width: 150px;
- height: 150px;
- opacity: 0.8;
- }
- }
- }
- }
- .evaluation-result {
- border-radius: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-top: 20px;
- background: #f8f8f8;
- .score-section {
- width: 65%;
- display: flex;
- flex-direction: column;
- gap: 24px;
- padding: 24px;
- background: #f8f8f8;
- border-radius: 4px;
- .score-section-left {
- flex: 1;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- gap: 16px;
- white-space: nowrap; // 添加此行防止换行
-
- .score-title {
- font-size: 16px;
- font-weight: bold;
- color: #333;
- min-width: fit-content; // 添加此行确保标题不会被压缩
- }
- .score-value {
- display: flex;
- align-items: baseline;
- min-width: fit-content; // 添加此行确保分数部分不会被压缩
-
- .number {
- font-size: 14px;
- font-weight: bold;
- color: #F56C6C;
- }
- .unit {
- margin: 0 8px;
- font-size: 14px;
- color: #333;
- }
- .status-tag {
- //padding: 2px 8px;
- font-size: 12px;
- color: #fff;
- background: #F56C6C; // 默认背景色
- border-radius: 2px;
- // 添加打印时的特殊样式
- @media print {
- background: none !important; // 移除打印时的背景色
- color: #F56C6C !important; // 使用对应的文字颜色
- border: 1px solid #F56C6C; // 添加边框来区分
- &[style*="background:#67C23A"] {
- background: none !important;
- color: #67C23A !important;
- border: 1px solid #67C23A;
- }
- }
- }
- }
- .detection-results {
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 14px;
- color: #333;
- min-width: fit-content; // 添加此行确保检测结果不会被压缩
- .detection-item {
- display: flex;
- align-items: center;
- gap: 4px;
- white-space: nowrap; // 添加此行防止换行
-
- .status-normal {
- color: #67C23A;
- }
- .status-warning {
- color: #F56C6C;
- }
- }
- .separator {
- color: #DCDFE6;
- }
- }
- }
- .fail-reason {
- flex: 1;
- text-align: left;
- padding: 16px;
- border-radius: 4px;
- .reason-header {
- display: flex;
- align-items: center;
- gap: 8px;
- margin-bottom: 12px;
- color: #F56C6C;
- font-size: 14px;
- i {
- font-size: 16px;
- }
- }
- .reason-content {
- margin-top: 16px;
- font-size: 14px;
- .label {
- color: #333;
- font-weight: 500;
- }
- .status-normal {
- color: #67C23A;
- }
- .status-warning {
- color: #F56C6C;
- }
- .failed-questions {
- margin-top: 12px;
- padding: 12px;
- background-color: #FEF0F0;
- border-radius: 4px;
- border-left: 4px solid #F56C6C;
- .failed-title {
- color: #F56C6C;
- font-weight: 500;
- margin-bottom: 8px;
- }
- .failed-list {
- text-align: left;
- list-style-type: disc;
- padding-left: 20px;
- color: #606266;
- li {
- margin-bottom: 4px;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
- }
- }
- }
- }
- }
- .radar-chart {
- width: 500px;
- height: 350px;
- /* background: #fff; */
- border-radius: 8px;
- /* border: 1px solid #EBEEF5; */
- padding: 20px;
- /* margin-right: 20px; */
-
- .radar {
- width: 100%;
- height: 100%;
- }
- :deep(.echarts-tooltip) {
- display: none; // 隐藏tooltip
- }
- }
- }
- .ability-quality {
- margin-top: 30px;
- background: #f8f8f8;
- padding: 20px;
- border-radius: 8px;
-
- h3 {
- font-size: 16px;
- color: #333;
- margin: 0;
- padding-bottom: 16px;
- /* border-bottom: 1px solid #eee; */
- .score-text {
- font-size: 14px;
- color: #f56c6c;
- font-weight: normal;
- margin-left: 10px;
- }
- }
- .quality-details {
- margin-top: 20px;
- .quality-item {
- display: flex;
-
- gap: 24px;
-
- .quality-left, .quality-right {
- .icon-box{
- display: flex;
- align-items: center;
- .icon {
- width: 32px;
- height: 32px;
- border-radius: 4px;
- flex-shrink: 0;
- margin-right: 12px;
- }
- h5{
- margin-bottom: 0;
- }
- }
- .content{
- p{
- .bracket-content {
- color: #409EFF;
- font-weight: 500;
- }
- }
- }
-
- flex: 1;
- display: flex;
- align-items: center;
- gap: 12px;
-
- .advantage-icon {
- /* background: #67C23A; */
- }
- .suggestion-icon {
- /* background: #E6A23C; */
- }
- .content {
- flex: 1;
-
- h4 {
- margin: 0 0 12px 0;
- font-size: 14px;
- color: #333;
- }
- p {
- margin: 0;
- font-size: 12px;
- line-height: 1.6;
- color: #666;
- }
- }
- }
- }
- }
- }
- .detailed-evaluation {
- padding: 20px;
- border-radius: 8px;
- margin-top: 30px;
- background: #f8f8f8;
- position: relative;
- .line-info {
- color: #9b9b9b;
- .line-info-left {
- position: absolute;
- left: 36%;
- top: 0;
- }
- .line-info-center {
- position: absolute;
- left: 63%;
- top: 0;
- }
- .line-info-right {
- position: absolute;
- left: 72%;
- top: 0;
- }
- }
- .line-chart {
- .line-chart-left {
- width: 1px;
- height: 91%;
- border-left: 1px solid #e1e1e1;
- position: absolute;
- left: 12%;
- margin-left: 16px;
- }
- .line_left {
- width: 1px;
- height: 90%;
- border-left: 1px dashed #e1e1e1;
- position: absolute;
- left: 59%;
- margin-left: 7px;
- /* top: 0; */
- }
- .line_center {
- width: 1px;
- height: 90%;
- border-left: 1px dashed #e1e1e1;
- position: absolute;
- left: 69%;
- margin-left: -7px;
- }
- .line_right {
- width: 1px;
- height: 90%;
- border-left: 1px dashed #e1e1e1;
- position: absolute;
- left: 76%;
- margin-left: -6px;
- }
- }
- .ability-scores {
- .ability-item {
- display: flex;
- align-items: center;
- margin-bottom: 20px;
- position: relative;
- min-height: 30px;
- .ability-name {
- min-width: 120px;
- margin-right: 20px;
- font-size: 14px;
- color: #333;
- white-space: nowrap;
- display: flex;
- align-items: center;
- height: 30px; // 固定高度以确保垂直居中
- }
- .bar-chart-container {
- flex: 1;
- margin-right: 45px;
- display: flex;
- align-items: center;
- height: 30px; // 固定高度以确保垂直居中
- :deep(.echarts) {
- height: 100% !important;
- }
- }
- }
- }
- }
- .detection-section,
- .psychology-section,
- .body-detection-section {
- .detection-section-header{
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
- }
- margin-top: 20px;
- background: #f8f8f8;
- padding: 20px;
- border-radius: 8px;
- .section-title {
- font-size: 16px;
- font-weight: bold;
- color: #333;
- margin-bottom: 16px;
- }
- .status-tag {
- display: inline-block;
- padding: 2px 8px;
- border-radius: 2px;
- font-size: 12px;
-
- &.normal {
- font-size: 14px;
- /* background: #67C23A; */
- color: #67C23A;
- }
- }
- }
- .detection-section-content{
- display: flex;
- justify-content: space-between;
- gap: 16px;
- .detection-items {
- margin: 16px 0;
- .item {
- margin-bottom: 8px;
- font-size: 14px;
- .status {
- &.normal {
- color: #67C23A;
- }
- }
- .separator {
- margin: 0 8px;
- color: #DCDFE6;
- }
- .desc {
- color: #606266;
- }
- }
- }
- .risk-standards {
- margin-top: 16px;
-
- .standards-title {
- font-size: 14px;
- color: #333;
- margin-bottom: 12px;
- }
- .standard-item {
- margin-bottom: 8px;
- font-size: 14px;
-
- .level {
- color: #333;
- }
-
- .desc {
- color: #606266;
- }
- }
- }
- }
- .psychology-section {
- .psychology_box{
- display: flex;
- flex-direction: row;
- gap: 16px;
- justify-content: space-between;
- align-items: center;
- }
- .duv-score {
- position: relative;
-
- .score {
- font-size: 48px;
- font-weight: bold;
-
- &.low-risk {
- color: #67C23A;
- }
-
- &.medium-risk {
- color: #E6A23C;
- }
-
- &.high-risk {
- color: #F56C6C;
- }
- }
- .risk-level {
- margin-top: 0 !important;
- border-radius: 12px;
- font-size: 12px;
- font-weight: normal;
-
- &.low-risk {
-
- color: #67C23A;
- }
-
- &.medium-risk {
-
- color: #E6A23C;
- }
-
- &.high-risk {
-
- color: #F56C6C;
- }
- }
- }
- .psychology-desc {
- font-size: 14px;
- color: #606266;
- line-height: 1.6;
- }
- .psychology-recommendation {
- margin-top: 16px;
- font-size: 14px;
-
- .label {
- color: #333;
- font-weight: 500;
- }
-
- .value {
- color: #409EFF;
- }
- }
- }
- .body-detection-section {
- .hand-verification {
- .grid {
- @apply gap-4;
- }
-
- .aspect-square {
- @apply relative;
- padding-top: 100%;
-
- img {
- @apply absolute inset-0 w-full h-full object-cover;
- }
- }
- }
- .detection-results {
- .detection-item {
- @apply p-4 bg-gray-50 rounded-lg;
-
- .position {
- @apply font-medium text-gray-700 mr-2;
- }
-
- .status {
- font-weight: 500;
-
- &.status-normal {
- color: #67C23A; // 绿色
- }
-
- &.status-error {
- color: #F56C6C; // 红色
- }
- }
-
- .description {
- @apply block mt-1;
- }
- }
- }
- }
- .nav-tabs {
- position: sticky;
- top: 0;
- display: flex;
- gap: 32px;
- margin: 20px 0;
- padding: 0 20px;
- border: none;
- margin-bottom: 2px;
- /* border-bottom: 1px solid #EBEEF5; */
- background: #fff;
- z-index: 100;
- width: 100%;
- box-sizing: border-box;
- transition: all 0.3s ease;
- &.fixed {
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- }
- .tab-item {
- position: relative;
- padding: 5px 22px;
- font-size: 14px;
- color: #606266;
- cursor: pointer;
- transition: all 0.3s;
- border-radius: 15px;
- &:hover {
- color: #409EFF;
- background: #f2f3f8;
- }
- &.active {
- color: #409EFF;
- font-weight: 500;
- background: #f2f3f8;
- &::after {
- display: none;
- }
- }
- &.link-tab {
- display: flex;
- align-items: center;
- gap: 4px;
-
- i {
- font-size: 12px;
- }
- &:hover {
- color: #409EFF;
- text-decoration: underline;
- }
- }
- &.info-tab {
- display: flex;
- align-items: center;
- gap: 4px;
-
- i {
- font-size: 14px;
- }
- &:hover {
- color: #409EFF;
- }
- }
- }
- }
- // 修改占位元素样式
- .nav-placeholder {
- margin: 20px 0;
- transition: height 0.3s ease;
- }
- }
- .loading-state,
- .error-state {
- text-align: center;
- padding: 20px;
- color: #666;
- }
- .error-state {
- color: #F56C6C;
- }
- .redline-section {
- margin-top: 16px;
- padding: 16px;
- background-color: #FFF6F6;
- border-radius: 4px;
- .redline-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 12px;
- .redline-title {
- color: #F56C6C;
- font-size: 14px;
- font-weight: 500;
- }
- .status-normal {
- color: #67C23A;
- font-size: 14px;
- }
- .status-warning {
- color: #F56C6C;
- font-size: 14px;
- }
- }
- .failed-questions {
- text-align: left !important;
- .failed-title {
- text-align: left;
- color: #606266;
- font-size: 14px;
- margin-bottom: 8px;
- }
- .failed-list {
- text-align: left;
- padding-left: 8px;
-
- .failed-item {
- display: flex;
- align-items: flex-start;
- margin-bottom: 8px;
- color: #606266;
- font-size: 14px;
- line-height: 1.5;
- text-align: left;
- &:last-child {
- margin-bottom: 0;
- }
- .bullet {
- color: #F56C6C;
- margin-right: 8px;
- font-size: 16px;
- line-height: 1;
- }
- .question-text {
- flex: 1;
- }
- }
- }
- }
- }
- .hand-verification {
- .grid {
- @apply gap-4;
- }
-
- .aspect-square {
- @apply relative;
- padding-top: 100%;
-
- img {
- @apply absolute inset-0 w-full h-full object-cover;
- }
- }
- }
- .detection-results {
- .detection-item {
- @apply p-4 rounded-lg;
-
- .position {
- @apply font-medium text-gray-700 mr-2;
- }
-
- .status {
- font-weight: 500;
-
- &.status-normal {
- color: #67C23A; // 绿色
- }
-
- &.status-error {
- color: #F56C6C; // 红色
- }
- }
-
- .description {
- @apply block mt-1;
- }
- }
- }
- // 添加一些额外的样式来处理图片加载失败的情况
- .aspect-square {
- background: #f5f5f5;
-
- img {
- &[src="/@/assets/default-image.png"] {
- object-fit: contain;
- padding: 20%;
- }
- }
- }
- // 添加顶部标识栏样式
- .report-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
- height: 80px;
- padding: 5px 24px;
- background: url("/@/assets/report.png") no-repeat center center;
- background-size: 100% 100%;
- color: #fff;
- position: relative;
- width: 1200px;
- margin: 0 auto;
- margin-bottom: 30px;
- border-radius: 5px;
- .header-left {
- position: absolute;
- left: 0;
- bottom: 0;
- display: flex;
- color: #000;
- padding: 5px 40px;
- background-color: #fff;
- align-items: center;
- font-size: 16px;
- font-weight: 500;
- border-top-right-radius: 60px;
- .cc-icon {
- width: 21px;
- height: 12px;
- margin-right: 8px;
- }
- }
- .header-right {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 100%;
- gap: 24px;
- font-size: 14px;
- opacity: 0.8;
- margin-left: 260px;
- span {
- white-space: nowrap;
- }
- .report-id {
- opacity: 0.8;
- }
- }
- }
- // 添加媒体查询和响应式样式
- @media screen and (max-width: 768px) {
- .outer-container {
- padding: 0;
- }
- .report-header {
- height: auto;
- padding: 12px 16px;
- flex-direction: column;
- align-items: flex-start;
- gap: 8px;
- .header-right {
- flex-direction: column;
- gap: 4px;
- width: 100%;
- }
- }
- .report-container {
- padding: 16px;
- .header {
- flex-direction: column;
- gap: 16px;
- .header-left {
- .avatar {
- width: 100px;
- height: 100px;
- margin: 0 auto;
- display: block;
- }
- }
- .header-right {
- flex-direction: column;
- padding: 16px;
- .left-section,
- .right-section {
- width: 100%;
- }
- .stamp {
- position: static;
- transform: none;
- margin-top: 16px;
- text-align: center;
- img {
- width: 80px;
- height: 80px;
- }
- }
- }
- }
- .nav-tabs {
- gap: 16px;
- padding: 0 12px;
- overflow-x: auto;
- white-space: nowrap;
- -webkit-overflow-scrolling: touch;
- &::-webkit-scrollbar {
- display: none;
- }
- .tab-item {
- padding: 8px 0;
- font-size: 13px;
- }
- }
- .evaluation-result {
- .score-section {
- padding: 16px;
- .score-section-left {
- flex-direction: column;
- align-items: flex-start;
- gap: 12px;
- .detection-results {
- flex-direction: column;
- gap: 8px;
- .separator {
- display: none;
- }
- }
- }
- }
- }
- .ability-quality {
- .quality-details {
- .quality-item {
- flex-direction: column;
- gap: 20px;
- }
- }
- }
- .detailed-evaluation {
-
- .ability-scores {
- .ability-item {
- flex-direction: column;
- gap: 8px;
- margin-bottom: 16px;
- .ability-name {
- width: 100%;
- }
- }
- }
- }
- .detection-section-content {
- flex-direction: column;
- gap: 20px;
- }
- // 手势验证部分响应式处理
- .hand-verification {
- .grid {
- grid-template-columns: 1fr !important;
- gap: 16px;
- h4 {
- margin-top: 16px;
- }
- }
- }
- }
- // 修改心理检测部分在移动端的样式
- .psychology-section {
- .duv-score {
- flex-wrap: wrap;
-
- .score {
- font-size: 20px;
- }
- }
- }
- // 修改红线题部分在移动端的样式
- .redline-section {
- padding: 12px;
- .failed-questions {
- .failed-list {
- .failed-item {
- margin-bottom: 12px;
- }
- }
- }
- }
- }
- // 添加暗黑模式支持1
- /* @media (prefers-color-scheme: dark) {
- .report-container {
- background: #1a1a1a;
- color: #e5e5e5;
- .header-right {
- background: #2a2a2a;
- }
- .nav-tabs {
- background: #1a1a1a;
- border-bottom-color: #333;
- .tab-item {
- color: #e5e5e5;
- &:hover,
- &.active {
- color: #409EFF;
- }
- }
- }
- .evaluation-result,
- .ability-quality,
- .detailed-evaluation,
- .detection-section,
- .psychology-section,
- .body-detection-section {
- background: #2a2a2a;
- }
- .status-normal {
- color: #95d475;
- }
- .status-warning {
- color: #ff7875;
- }
- }
- } */
- .info-dialog {
- :deep(.el-dialog__header) {
- padding: 20px;
- border-bottom: 1px solid #EBEEF5;
- }
- :deep(.el-dialog__body) {
- padding: 24px;
- }
- .info-content {
- .info-section {
- margin-bottom: 24px;
- &:last-child {
- margin-bottom: 0;
- }
- h4 {
- font-size: 16px;
- color: #333;
- margin: 0 0 16px 0;
- padding-left: 10px;
- border-left: 3px solid #409EFF;
- }
- .info-grid {
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- gap: 16px;
- .info-item {
- display: flex;
- align-items: center;
- .label {
- width: 80px;
- color: #666;
- font-size: 14px;
- }
- .value {
- flex: 1;
- color: #333;
- font-size: 14px;
- }
- }
- }
- }
- }
- }
- // 添加移动端适配
- @media screen and (max-width: 768px) {
- .info-dialog {
- :deep(.el-dialog) {
- width: 90% !important;
- margin: 20px auto !important;
- }
- .info-content {
- .info-section {
- .info-grid {
- grid-template-columns: 1fr;
- }
- }
- }
- }
- }
- // 添加弹窗相关样式
- .body-verification-dialog {
- :deep(.el-dialog__header) {
- padding: 20px;
- border-bottom: 1px solid #EBEEF5;
- }
- :deep(.el-dialog__body) {
- padding: 24px;
- }
- // 在弹窗中保持原有的手势验证样式
- .hand-verification {
- .grid {
- @apply gap-4;
- }
-
- .aspect-square {
- @apply relative;
- padding-top: 100%;
-
- img {
- @apply absolute inset-0 w-full h-full object-cover;
- }
- }
- }
- .detection-results {
- .detection-item {
- @apply p-4 bg-gray-50 rounded-lg;
-
- .position {
- @apply font-medium text-gray-700 mr-2;
- }
-
- .status {
- @apply text-green-500;
- }
-
- .description {
- @apply block mt-1;
- }
- }
- }
- }
- // 添加移动端适配
- @media screen and (max-width: 768px) {
- .body-verification-dialog {
- :deep(.el-dialog) {
- width: 95% !important;
- margin: 10px auto !important;
- }
- .hand-verification {
- .grid {
- grid-template-columns: 1fr !important;
- gap: 16px;
- }
- }
- .detection-results {
- .grid {
- grid-template-columns: 1fr !important;
- }
- }
- }
- }
- // 确保在移动端也能正常显示
- @media screen and (max-width: 768px) {
- .radar-chart {
- width: 100%;
- margin-right: 0;
- margin-top: 20px;
- }
- }
- // 修改心理测评部分的样式
- .psychology-section {
- .psychology_box {
- display: flex;
- flex-direction: row;
- gap: 16px;
- justify-content: space-between;
- align-items: center;
- .psychology_body {
- flex: 1;
- }
- .duv-score {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 100px;
- height: 100px;
- background: #fff;
- border-radius: 50%;
- color: #81b337;
- gap: 8px;
- span {
- &:first-child {
- font-size: 14px;
- color: #666;
- }
- &.score {
-
- font-size: 48px;
- font-weight: bold;
- color: #81b337;
- }
- &:last-child {
- margin-top: 20px;
- font-weight: bold;
- font-size: 20px;
- color: #81b337;
- }
- }
- }
- }
- .psychology-desc {
- font-size: 14px;
- color: #606266;
- line-height: 1.6;
- margin-bottom: 16px;
- }
- .psychology-recommendation {
- font-size: 14px;
-
- .label {
- color: #333;
- font-weight: 500;
- }
-
- .value {
- color: #409EFF;
- }
- }
- }
- // 添加移动端适配
- @media screen and (max-width: 768px) {
- .psychology-section {
- .psychology_box {
- flex-direction: column;
-
- .duv-score {
- width: 100%;
- padding: 16px;
- }
- }
- }
- }
- // 修改导出按钮样式
- .export-btn.fixed-btn {
- position: fixed;
- right: 40px;
- bottom: 40px;
- z-index: 999;
- padding: 12px; // 修改为固定的padding值
- width: 40px; // 添加固定宽度
- height: 40px; // 添加固定高度
- border-radius: 50%; // 改为圆形
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
- transition: all 0.3s ease;
- display: flex;
- align-items: center;
- justify-content: center;
-
- // 修改图标样式
- :deep(.el-icon) {
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 16px;
- }
-
- &:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
- }
-
- &:active {
- transform: translateY(0);
- }
- }
- // 移动端适配
- @media screen and (max-width: 768px) {
- .export-btn.fixed-btn {
- right: 20px;
- bottom: 20px;
- width: 36px; // 移动端稍微小一点
- height: 36px;
- padding: 8px;
- }
- }
- // 修改header-right样式以适应新增按钮
- .report-header {
- .header-right {
- display: flex;
- align-items: center;
- gap: 16px;
-
- .export-btn {
- margin-left: auto; // 将按钮推到最右侧
- }
- }
- }
- // 添加移动端适配
- @media screen and (max-width: 768px) {
- .report-header {
- .header-right {
- flex-wrap: wrap;
-
- .export-btn {
- margin-left: 0;
- margin-top: 8px;
- width: 100%;
- }
- }
- }
- }
- // 添加问答记录相关样式
- .qa-section {
- margin-top: 30px;
- padding: 20px;
- background: #f8f8f8;
- border-radius: 8px;
- .section-title {
- font-size: 16px;
- font-weight: bold;
- color: #333;
- margin-bottom: 20px;
- }
- .qa-content {
- .qa-item {
- margin-bottom: 24px;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
- .question-block {
- background: #fff;
- border-radius: 8px;
- padding: 16px;
- margin-bottom: 16px;
- .question-header {
- display: flex;
- gap: 8px;
- margin-bottom: 12px;
- .question-tag {
- padding: 2px 8px;
- background: #e6f7ff;
- color: #1890ff;
- border-radius: 4px;
- font-size: 12px;
- }
- .question-type {
- padding: 2px 8px;
- background: #f5f5f5;
- color: #666;
- border-radius: 4px;
- font-size: 12px;
- }
- }
- h4 {
- font-size: 14px;
- color: #333;
- margin-bottom: 12px;
- }
- }
- .answer-content {
- p {
- color: #666;
- font-size: 14px;
- line-height: 1.6;
- margin-bottom: 8px;
- }
- .score-info {
- color: #1890ff;
- font-size: 14px;
- .analysis {
- color: #666;
- margin-top: 4px;
- }
- }
- }
- .follow-up-questions {
- padding-left: 24px;
- border-left: 2px solid #e8e8e8;
- .follow-up-item {
- background: #fff;
- border-radius: 8px;
- padding: 16px;
- margin-bottom: 12px;
- &:last-child {
- margin-bottom: 0;
- }
- .follow-up-header {
- margin-bottom: 12px;
- .follow-up-tag {
- padding: 2px 8px;
- background: #f6f3ff;
- color: #722ed1;
- border-radius: 4px;
- font-size: 12px;
- }
- }
- h4 {
- font-size: 14px;
- color: #333;
- margin-bottom: 12px;
- }
- }
- }
- }
- }
- .video-container {
- position: relative;
- width: 100%;
- max-width: 126px;
- /* aspect-ratio: 3/4; */
- height: 150px;
- margin: 0 auto;
- background: #000;
- border-radius: 12px;
- overflow: hidden;
- }
- // 移动端适配
- @media screen and (max-width: 768px) {
- .qa-section {
- padding: 16px;
- .qa-content {
- .follow-up-questions {
- padding-left: 16px;
- }
- }
- }
- }
- #candidate-answer{
- margin-left: 15px;
- position: relative;
- padding-left: 12px; // 为竖条留出空间
- &::before {
- content: '';
- position: absolute;
- left: -7px;
- top: 50%;
- transform: translateY(-50%);
- width: 3px;
- height: 16px;
- background: #2a3dae; // 竖条颜色
- border-radius: 2px;
- }
- }
- // 添加媒体查询以处理移动端显示
- @media screen and (max-width: 768px) {
- .score-section-left {
- flex-wrap: wrap; // 在移动端允许换行
- white-space: normal; // 在移动端允许换行
-
- .detection-results {
- width: 100%;
- flex-wrap: wrap;
-
- .detection-item {
- width: 100%;
- justify-content: flex-start;
- }
-
- .separator {
- display: none; // 在移动端隐藏分隔符
- }
- }
- }
- }
- // 添加自定义进度条样式
- :deep(.custom-progress) {
- .el-progress-bar__outer {
- border-radius: 3px;
- overflow: hidden;
- }
-
- .el-progress__text {
- font-size: 12px !important;
- color: #808080 !important;
- margin-left: 5px !important;
- }
-
- .el-progress-bar__inner {
- border-radius: 3px;
- position: relative;
- &::after {
- content: '';
- position: absolute;
- right: 0;
- top: 0;
- height: 100%;
- width: 6px;
- background: inherit;
- filter: brightness(115%);
- border-radius: 0 3px 3px 0;
- }
- }
- }
- // 修改分析文本的样式
- /* .text-[14px] {
- white-space: pre-wrap; // 保留换行和空格
- word-wrap: break-word; // 允许长单词换行
- word-break: break-all; // 在任意字符间换行
- line-height: 1.6; // 增加行高
- padding: 8px 0; // 增加上下内边距
- } */
- .analysis-content {
- .analysis-text {
- white-space: pre-line; // 只保留换行符
- line-height: 1.6;
- margin: 0;
- padding: 0;
- }
- }
- .assessment-points {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- align-items: center;
-
- .assessment-item {
- display: flex;
- align-items: center;
- gap: 4px;
-
- .point-name {
- color: #333;
- font-weight: 500;
- }
- .point-score {
- font-size: 12px;
- padding: 2px 6px;
- border-radius: 4px;
-
- &.score-excellent {
- background-color: #e6f7ff;
- color: #1890ff;
- }
-
- &.score-good {
- background-color: #f6ffed;
- color: #52c41a;
- }
-
- &.score-average {
- background-color: #fff7e6;
- color: #fa8c16;
- }
-
- &.score-poor {
- background-color: #fff1f0;
- color: #f5222d;
- }
- }
- }
- .separator {
- color: #666666;
- margin: 0 4px;
- }
- }
- .bar-chart-container {
- flex: 1;
- margin-right: 45px;
- }
- .ability-scores {
- .ability-item {
- display: flex;
- align-items: center;
- margin-bottom: 20px;
- position: relative;
- min-height: 30px;
- .ability-name {
- min-width: 120px;
- margin-right: 20px;
- font-size: 14px;
- color: #333;
- white-space: nowrap;
- display: flex;
- align-items: center;
- height: 30px; // 固定高度以确保垂直居中
- }
- .bar-chart-container {
- flex: 1;
- margin-right: 45px;
- display: flex;
- align-items: center;
- height: 30px; // 固定高度以确保垂直居中
- :deep(.echarts) {
- height: 100% !important;
- }
- }
- }
- }
- // 修改导出PDF时的样式处理
- .detailed-evaluation {
- .ability-scores {
- .ability-item {
- @media print {
- display: flex !important;
- align-items: center !important;
- min-height: 30px !important;
- .ability-name {
- display: flex !important;
- align-items: center !important;
- height: 30px !important;
- }
- .bar-chart-container {
- display: flex !important;
- align-items: center !important;
- height: 30px !important;
- }
- }
- }
- }
- }
- // 确保在导出时保持样式
- :deep(.custom-progress) {
- @media print {
- .el-progress-bar__outer {
- height: 8px !important;
- }
- .el-progress__text {
- position: absolute !important;
- right: -45px !important;
- top: 50% !important;
- transform: translateY(-50%) !important;
- line-height: 1 !important;
- }
- }
- }
- </style>
|