AIC.html 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>智能招聘系统</title>
  7. <!-- 国内CDN引入 -->
  8. <link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
  9. <link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet">
  10. <script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.min.js"></script>
  11. <style>
  12. :root {
  13. --primary: #2563eb;
  14. --secondary: #f59e0b;
  15. --dark: #1e293b;
  16. --light: #f8fafc;
  17. --success: #10b981;
  18. --danger: #ef4444;
  19. --warning: #f97316;
  20. }
  21. * {
  22. margin: 0;
  23. padding: 0;
  24. box-sizing: border-box;
  25. font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
  26. }
  27. body {
  28. background-color: #f1f5f9;
  29. color: var(--dark);
  30. line-height: 1.6;
  31. }
  32. /* 登录页面样式 */
  33. .login-container {
  34. display: flex;
  35. min-height: 100vh;
  36. align-items: center;
  37. justify-content: center;
  38. background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
  39. }
  40. .login-box {
  41. width: 400px;
  42. background: white;
  43. border-radius: 12px;
  44. padding: 40px;
  45. box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
  46. text-align: center;
  47. }
  48. .login-logo {
  49. font-size: 28px;
  50. font-weight: bold;
  51. color: var(--primary);
  52. margin-bottom: 30px;
  53. display: flex;
  54. align-items: center;
  55. justify-content: center;
  56. gap: 10px;
  57. }
  58. .login-tabs {
  59. display: flex;
  60. margin-bottom: 20px;
  61. border-bottom: 1px solid #e2e8f0;
  62. }
  63. .login-tab {
  64. flex: 1;
  65. padding: 12px;
  66. cursor: pointer;
  67. font-weight: 500;
  68. transition: all 0.2s;
  69. }
  70. .login-tab.active {
  71. color: var(--primary);
  72. border-bottom: 2px solid var(--primary);
  73. }
  74. .login-form {
  75. display: none;
  76. }
  77. .login-form.active {
  78. display: block;
  79. }
  80. .form-group {
  81. margin-bottom: 20px;
  82. text-align: left;
  83. }
  84. .form-group label {
  85. display: block;
  86. margin-bottom: 8px;
  87. font-weight: 500;
  88. }
  89. .form-control {
  90. width: 100%;
  91. padding: 12px 16px;
  92. border: 1px solid #e2e8f0;
  93. border-radius: 8px;
  94. font-size: 16px;
  95. transition: all 0.2s;
  96. }
  97. .form-control:focus {
  98. border-color: var(--primary);
  99. box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
  100. outline: none;
  101. }
  102. .btn {
  103. width: 100%;
  104. padding: 12px;
  105. border: none;
  106. border-radius: 8px;
  107. font-size: 16px;
  108. font-weight: 500;
  109. cursor: pointer;
  110. transition: all 0.2s;
  111. }
  112. .btn-primary {
  113. background: var(--primary);
  114. color: white;
  115. }
  116. .btn-primary:hover {
  117. background: #1d4ed8;
  118. }
  119. .login-links {
  120. margin-top: 20px;
  121. display: flex;
  122. justify-content: space-between;
  123. }
  124. .login-link {
  125. color: var(--primary);
  126. font-size: 14px;
  127. cursor: pointer;
  128. }
  129. /* 主界面样式 */
  130. .container {
  131. display: flex;
  132. min-height: 100vh;
  133. padding: 20px;
  134. gap: 20px;
  135. max-width: 1400px;
  136. margin: 0 auto;
  137. display: none;
  138. }
  139. /* 左侧导航 */
  140. .sidebar {
  141. width: 240px;
  142. background: white;
  143. border-radius: 12px;
  144. padding: 20px;
  145. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
  146. display: flex;
  147. flex-direction: column;
  148. }
  149. .logo {
  150. font-size: 20px;
  151. font-weight: bold;
  152. color: var(--primary);
  153. margin-bottom: 30px;
  154. display: flex;
  155. align-items: center;
  156. gap: 10px;
  157. }
  158. .nav-menu {
  159. flex: 1;
  160. display: flex;
  161. flex-direction: column;
  162. gap: 8px;
  163. }
  164. .nav-item {
  165. padding: 12px 16px;
  166. border-radius: 8px;
  167. display: flex;
  168. align-items: center;
  169. gap: 12px;
  170. cursor: pointer;
  171. transition: all 0.2s;
  172. }
  173. .nav-item:hover {
  174. background-color: #f1f5f9;
  175. }
  176. .nav-item.active {
  177. background-color: #eff6ff;
  178. color: var(--primary);
  179. font-weight: 500;
  180. }
  181. .nav-item i {
  182. width: 20px;
  183. text-align: center;
  184. }
  185. /* 主内容区 */
  186. .main-content {
  187. flex: 1;
  188. display: flex;
  189. flex-direction: column;
  190. gap: 20px;
  191. }
  192. /* 顶部信息栏 */
  193. .header {
  194. background: white;
  195. border-radius: 12px;
  196. padding: 18px 24px;
  197. display: flex;
  198. justify-content: space-between;
  199. align-items: center;
  200. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
  201. }
  202. .user-info {
  203. display: flex;
  204. align-items: center;
  205. gap: 12px;
  206. }
  207. .avatar {
  208. width: 40px;
  209. height: 40px;
  210. border-radius: 50%;
  211. background-color: #e0f2fe;
  212. display: flex;
  213. align-items: center;
  214. justify-content: center;
  215. color: var(--primary);
  216. font-weight: bold;
  217. cursor: pointer;
  218. }
  219. .user-dropdown {
  220. position: relative;
  221. }
  222. .dropdown-menu {
  223. position: absolute;
  224. top: 50px;
  225. right: 0;
  226. width: 200px;
  227. background: white;
  228. border-radius: 8px;
  229. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  230. padding: 10px 0;
  231. z-index: 100;
  232. display: none;
  233. }
  234. .dropdown-item {
  235. padding: 10px 16px;
  236. cursor: pointer;
  237. transition: all 0.2s;
  238. }
  239. .dropdown-item:hover {
  240. background: #f1f5f9;
  241. }
  242. .dropdown-divider {
  243. height: 1px;
  244. background: #e2e8f0;
  245. margin: 5px 0;
  246. }
  247. /* 搜索栏 */
  248. .search-bar {
  249. display: flex;
  250. gap: 10px;
  251. }
  252. .search-input {
  253. flex: 1;
  254. padding: 10px 16px;
  255. border: 1px solid #e2e8f0;
  256. border-radius: 8px;
  257. font-size: 14px;
  258. }
  259. .search-btn {
  260. padding: 10px 16px;
  261. background: var(--primary);
  262. color: white;
  263. border: none;
  264. border-radius: 8px;
  265. cursor: pointer;
  266. }
  267. /* 内容区域样式 */
  268. .content-area {
  269. flex: 1;
  270. background: white;
  271. border-radius: 12px;
  272. padding: 24px;
  273. box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
  274. overflow-y: auto;
  275. }
  276. .content-title {
  277. font-size: 20px;
  278. font-weight: 600;
  279. margin-bottom: 24px;
  280. color: var(--primary);
  281. display: flex;
  282. align-items: center;
  283. gap: 10px;
  284. }
  285. /* 工作/简历卡片样式 */
  286. .card-grid {
  287. display: grid;
  288. grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  289. gap: 20px;
  290. margin-top: 20px;
  291. }
  292. .card {
  293. background: white;
  294. border-radius: 8px;
  295. padding: 16px;
  296. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
  297. border: 1px solid #e2e8f0;
  298. transition: all 0.2s;
  299. cursor: pointer;
  300. }
  301. .card:hover {
  302. transform: translateY(-4px);
  303. box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
  304. }
  305. .card-header {
  306. display: flex;
  307. align-items: center;
  308. gap: 12px;
  309. margin-bottom: 12px;
  310. }
  311. .card-avatar {
  312. width: 48px;
  313. height: 48px;
  314. border-radius: 50%;
  315. background-color: #e0f2fe;
  316. display: flex;
  317. align-items: center;
  318. justify-content: center;
  319. color: var(--primary);
  320. font-weight: bold;
  321. }
  322. .card-title {
  323. font-weight: 600;
  324. margin-bottom: 4px;
  325. }
  326. .card-subtitle {
  327. font-size: 14px;
  328. color: #64748b;
  329. }
  330. .card-tags {
  331. display: flex;
  332. flex-wrap: wrap;
  333. gap: 8px;
  334. margin-top: 12px;
  335. }
  336. .card-tag {
  337. background: #f1f5f9;
  338. padding: 4px 10px;
  339. border-radius: 12px;
  340. font-size: 12px;
  341. color: #64748b;
  342. }
  343. .card-footer {
  344. margin-top: 16px;
  345. display: flex;
  346. justify-content: space-between;
  347. align-items: center;
  348. }
  349. .card-match {
  350. background: #dcfce7;
  351. color: #166534;
  352. padding: 4px 10px;
  353. border-radius: 12px;
  354. font-size: 12px;
  355. }
  356. .card-btn {
  357. padding: 6px 12px;
  358. background: var(--primary);
  359. color: white;
  360. border: none;
  361. border-radius: 6px;
  362. font-size: 12px;
  363. cursor: pointer;
  364. }
  365. /* 简历分析表单 */
  366. .resume-form {
  367. max-width: 800px;
  368. margin: 0 auto;
  369. }
  370. .form-section {
  371. margin-bottom: 24px;
  372. padding: 16px;
  373. background: #f8fafc;
  374. border-radius: 8px;
  375. }
  376. .form-section-title {
  377. font-size: 18px;
  378. font-weight: 600;
  379. margin-bottom: 16px;
  380. color: var(--primary);
  381. display: flex;
  382. align-items: center;
  383. gap: 8px;
  384. }
  385. .form-row {
  386. display: flex;
  387. gap: 16px;
  388. margin-bottom: 16px;
  389. }
  390. .form-col {
  391. flex: 1;
  392. }
  393. textarea.form-control {
  394. min-height: 100px;
  395. resize: vertical;
  396. }
  397. .form-actions {
  398. display: flex;
  399. justify-content: flex-end;
  400. gap: 12px;
  401. margin-top: 24px;
  402. }
  403. /* 职业匹配结果 */
  404. .match-result {
  405. margin-top: 24px;
  406. padding: 16px;
  407. background: #f8fafc;
  408. border-radius: 8px;
  409. }
  410. .match-title {
  411. font-size: 18px;
  412. font-weight: 600;
  413. margin-bottom: 16px;
  414. color: var(--primary);
  415. }
  416. .match-item {
  417. display: flex;
  418. justify-content: space-between;
  419. align-items: center;
  420. padding: 12px 0;
  421. border-bottom: 1px solid #e2e8f0;
  422. }
  423. .match-item:last-child {
  424. border-bottom: none;
  425. }
  426. .match-job {
  427. font-weight: 500;
  428. }
  429. .match-score {
  430. font-weight: 600;
  431. color: var(--primary);
  432. }
  433. /* 模态框样式 */
  434. .modal-overlay {
  435. position: fixed;
  436. top: 0;
  437. left: 0;
  438. right: 0;
  439. bottom: 0;
  440. background: rgba(0, 0, 0, 0.5);
  441. display: none;
  442. justify-content: center;
  443. align-items: center;
  444. z-index: 1000;
  445. }
  446. .modal-content {
  447. background: white;
  448. padding: 24px;
  449. border-radius: 12px;
  450. max-width: 600px;
  451. width: 90%;
  452. box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
  453. max-height: 90vh;
  454. overflow-y: auto;
  455. }
  456. .modal-title {
  457. font-size: 18px;
  458. font-weight: 600;
  459. margin-bottom: 16px;
  460. }
  461. .modal-buttons {
  462. display: flex;
  463. gap: 12px;
  464. margin-top: 24px;
  465. }
  466. .modal-btn {
  467. flex: 1;
  468. padding: 10px;
  469. border-radius: 8px;
  470. border: none;
  471. font-weight: 500;
  472. cursor: pointer;
  473. transition: all 0.2s;
  474. }
  475. .modal-btn-cancel {
  476. background: #f1f5f9;
  477. color: var(--dark);
  478. }
  479. .modal-btn-confirm {
  480. background: var(--success);
  481. color: white;
  482. }
  483. .modal-btn:hover {
  484. transform: translateY(-2px);
  485. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  486. }
  487. /* 响应式设计 */
  488. @media (max-width: 768px) {
  489. .login-box {
  490. width: 90%;
  491. padding: 30px 20px;
  492. }
  493. .container {
  494. flex-direction: column;
  495. padding: 10px;
  496. }
  497. .sidebar {
  498. width: 100%;
  499. flex-direction: row;
  500. align-items: center;
  501. }
  502. .logo {
  503. margin-bottom: 0;
  504. margin-right: 30px;
  505. }
  506. .nav-menu {
  507. flex-direction: row;
  508. overflow-x: auto;
  509. padding-bottom: 10px;
  510. }
  511. .card-grid {
  512. grid-template-columns: 1fr;
  513. }
  514. .form-row {
  515. flex-direction: column;
  516. gap: 16px;
  517. }
  518. }
  519. </style>
  520. </head>
  521. <body>
  522. <!-- 登录页面 -->
  523. <div class="login-container" id="loginPage">
  524. <div class="login-box">
  525. <div class="login-logo">
  526. <i class="fas fa-briefcase"></i>
  527. <span>智能招聘系统</span>
  528. </div>
  529. <div class="login-tabs">
  530. <div class="login-tab active" data-tab="candidate">应聘者登录</div>
  531. <div class="login-tab" data-tab="recruiter">招聘者登录</div>
  532. </div>
  533. <!-- 应聘者登录表单 -->
  534. <div class="login-form active" id="candidateLogin">
  535. <div class="form-group">
  536. <label for="candidateUsername">用户名</label>
  537. <input type="text" id="candidateUsername" class="form-control" placeholder="请输入用户名">
  538. </div>
  539. <div class="form-group">
  540. <label for="candidatePassword">密码</label>
  541. <input type="password" id="candidatePassword" class="form-control" placeholder="请输入密码">
  542. </div>
  543. <button class="btn btn-primary" id="candidateLoginBtn">登录</button>
  544. <div class="login-links">
  545. <span class="login-link" id="showRegister">注册账号</span>
  546. <span class="login-link" id="showForgot">忘记密码</span>
  547. </div>
  548. </div>
  549. <!-- 招聘者登录表单 -->
  550. <div class="login-form" id="recruiterLogin">
  551. <div class="form-group">
  552. <label for="recruiterUsername">用户名</label>
  553. <input type="text" id="recruiterUsername" class="form-control" placeholder="请输入用户名">
  554. </div>
  555. <div class="form-group">
  556. <label for="recruiterPassword">密码</label>
  557. <input type="password" id="recruiterPassword" class="form-control" placeholder="请输入密码">
  558. </div>
  559. <button class="btn btn-primary" id="recruiterLoginBtn">登录</button>
  560. <div class="login-links">
  561. <span class="login-link" id="showRegister2">注册账号</span>
  562. <span class="login-link" id="showForgot2">忘记密码</span>
  563. </div>
  564. </div>
  565. </div>
  566. </div>
  567. <!-- 注册页面 -->
  568. <div class="login-container" id="registerPage" style="display: none;">
  569. <div class="login-box">
  570. <div class="login-logo">
  571. <i class="fas fa-user-plus"></i>
  572. <span>注册账号</span>
  573. </div>
  574. <div class="login-tabs">
  575. <div class="login-tab active" data-tab="candidateReg">应聘者注册</div>
  576. <div class="login-tab" data-tab="recruiterReg">招聘者注册</div>
  577. </div>
  578. <!-- 应聘者注册表单 -->
  579. <div class="login-form active" id="candidateRegister">
  580. <div class="form-group">
  581. <label for="regCandidateUsername">用户名</label>
  582. <input type="text" id="regCandidateUsername" class="form-control" placeholder="请输入用户名">
  583. </div>
  584. <div class="form-group">
  585. <label for="regCandidatePassword">密码</label>
  586. <input type="password" id="regCandidatePassword" class="form-control" placeholder="请输入密码">
  587. </div>
  588. <div class="form-group">
  589. <label for="regCandidateConfirm">确认密码</label>
  590. <input type="password" id="regCandidateConfirm" class="form-control" placeholder="请再次输入密码">
  591. </div>
  592. <div class="form-group">
  593. <label for="regCandidateEmail">电子邮箱</label>
  594. <input type="email" id="regCandidateEmail" class="form-control" placeholder="请输入电子邮箱">
  595. </div>
  596. <button class="btn btn-primary" id="candidateRegisterBtn">注册</button>
  597. <div class="login-links">
  598. <span class="login-link" id="backToLogin">返回登录</span>
  599. </div>
  600. </div>
  601. <!-- 招聘者注册表单 -->
  602. <div class="login-form" id="recruiterRegister">
  603. <div class="form-group">
  604. <label for="regRecruiterUsername">用户名</label>
  605. <input type="text" id="regRecruiterUsername" class="form-control" placeholder="请输入用户名">
  606. </div>
  607. <div class="form-group">
  608. <label for="regRecruiterPassword">密码</label>
  609. <input type="password" id="regRecruiterPassword" class="form-control" placeholder="请输入密码">
  610. </div>
  611. <div class="form-group">
  612. <label for="regRecruiterConfirm">确认密码</label>
  613. <input type="password" id="regRecruiterConfirm" class="form-control" placeholder="请再次输入密码">
  614. </div>
  615. <div class="form-group">
  616. <label for="regRecruiterEmail">电子邮箱</label>
  617. <input type="email" id="regRecruiterEmail" class="form-control" placeholder="请输入电子邮箱">
  618. </div>
  619. <div class="form-group">
  620. <label for="regCompany">公司名称</label>
  621. <input type="text" id="regCompany" class="form-control" placeholder="请输入公司名称">
  622. </div>
  623. <button class="btn btn-primary" id="recruiterRegisterBtn">注册</button>
  624. <div class="login-links">
  625. <span class="login-link" id="backToLogin2">返回登录</span>
  626. </div>
  627. </div>
  628. </div>
  629. </div>
  630. <!-- 忘记密码页面 -->
  631. <div class="login-container" id="forgotPage" style="display: none;">
  632. <div class="login-box">
  633. <div class="login-logo">
  634. <i class="fas fa-key"></i>
  635. <span>找回密码</span>
  636. </div>
  637. <div class="form-group">
  638. <label for="forgotEmail">电子邮箱</label>
  639. <input type="email" id="forgotEmail" class="form-control" placeholder="请输入注册时使用的电子邮箱">
  640. </div>
  641. <button class="btn btn-primary" id="forgotBtn">发送重置链接</button>
  642. <div class="login-links">
  643. <span class="login-link" id="backToLogin3">返回登录</span>
  644. </div>
  645. </div>
  646. </div>
  647. <!-- 主界面 - 应聘者 -->
  648. <div class="container" id="candidateContainer">
  649. <!-- 左侧导航 -->
  650. <div class="sidebar">
  651. <div class="logo">
  652. <i class="fas fa-user-tie"></i>
  653. <span>应聘者中心</span>
  654. </div>
  655. <div class="nav-menu">
  656. <div class="nav-item active" id="navCandidateJobs">
  657. <i class="fas fa-briefcase"></i>
  658. <span>工作机会</span>
  659. </div>
  660. <div class="nav-item" id="navCandidateResume">
  661. <i class="fas fa-file-alt"></i>
  662. <span>简历分析</span>
  663. </div>
  664. <div class="nav-item" id="navCandidateInterview">
  665. <i class="fas fa-video"></i>
  666. <span>视频面试</span>
  667. </div>
  668. <div class="nav-item" id="navCandidateRecords">
  669. <i class="fas fa-history"></i>
  670. <span>面试记录</span>
  671. </div>
  672. </div>
  673. </div>
  674. <!-- 主内容区 -->
  675. <div class="main-content">
  676. <!-- 顶部信息栏 -->
  677. <div class="header">
  678. <div class="search-bar">
  679. <input type="text" class="search-input" placeholder="搜索工作职位、公司...">
  680. <button class="search-btn">
  681. <i class="fas fa-search"></i>
  682. </button>
  683. </div>
  684. <div class="user-info">
  685. <div class="user-dropdown">
  686. <div class="avatar" id="userAvatar">张</div>
  687. <div class="dropdown-menu" id="userDropdown">
  688. <div class="dropdown-item">
  689. <i class="fas fa-user"></i> 个人中心
  690. </div>
  691. <div class="dropdown-item">
  692. <i class="fas fa-cog"></i> 系统设置
  693. </div>
  694. <div class="dropdown-divider"></div>
  695. <div class="dropdown-item">
  696. <i class="fas fa-sign-out-alt"></i> 退出登录
  697. </div>
  698. </div>
  699. </div>
  700. <div>
  701. <div style="font-weight: 500;">张伟</div>
  702. <div style="font-size: 12px; color: #64748b;">应聘者</div>
  703. </div>
  704. </div>
  705. </div>
  706. <!-- 工作机会页面 -->
  707. <div class="content-area" id="candidateJobsPage">
  708. <div class="content-title">
  709. <i class="fas fa-briefcase"></i>
  710. <span>推荐工作机会</span>
  711. </div>
  712. <div class="card-grid" id="jobGrid">
  713. <!-- 工作卡片将通过JS动态生成 -->
  714. </div>
  715. </div>
  716. <!-- 简历分析页面 -->
  717. <div class="content-area" id="candidateResumePage" style="display: none;">
  718. <div class="content-title">
  719. <i class="fas fa-file-alt"></i>
  720. <span>我的简历</span>
  721. </div>
  722. <div class="resume-form">
  723. <div class="form-section">
  724. <div class="form-section-title">
  725. <i class="fas fa-user"></i>
  726. <span>基本信息</span>
  727. </div>
  728. <div class="form-row">
  729. <div class="form-col">
  730. <label for="resumeName">姓名</label>
  731. <input type="text" id="resumeName" class="form-control" placeholder="请输入您的姓名">
  732. </div>
  733. <div class="form-col">
  734. <label for="resumeGender">性别</label>
  735. <select id="resumeGender" class="form-control">
  736. <option value="male">男</option>
  737. <option value="female">女</option>
  738. <option value="other">其他</option>
  739. </select>
  740. </div>
  741. </div>
  742. <div class="form-row">
  743. <div class="form-col">
  744. <label for="resumeBirth">出生日期</label>
  745. <input type="date" id="resumeBirth" class="form-control">
  746. </div>
  747. <div class="form-col">
  748. <label for="resumePhone">联系电话</label>
  749. <input type="tel" id="resumePhone" class="form-control" placeholder="请输入联系电话">
  750. </div>
  751. </div>
  752. <div class="form-row">
  753. <div class="form-col">
  754. <label for="resumeEmail">电子邮箱</label>
  755. <input type="email" id="resumeEmail" class="form-control" placeholder="请输入电子邮箱">
  756. </div>
  757. <div class="form-col">
  758. <label for="resumeLocation">居住地</label>
  759. <input type="text" id="resumeLocation" class="form-control" placeholder="请输入居住城市">
  760. </div>
  761. </div>
  762. </div>
  763. <div class="form-section">
  764. <div class="form-section-title">
  765. <i class="fas fa-graduation-cap"></i>
  766. <span>教育背景</span>
  767. </div>
  768. <div class="form-row">
  769. <div class="form-col">
  770. <label for="resumeSchool">学校名称</label>
  771. <input type="text" id="resumeSchool" class="form-control" placeholder="请输入学校名称">
  772. </div>
  773. <div class="form-col">
  774. <label for="resumeDegree">学历</label>
  775. <select id="resumeDegree" class="form-control">
  776. <option value="bachelor">本科</option>
  777. <option value="master">硕士</option>
  778. <option value="phd">博士</option>
  779. <option value="college">大专</option>
  780. </select>
  781. </div>
  782. </div>
  783. <div class="form-row">
  784. <div class="form-col">
  785. <label for="resumeMajor">专业</label>
  786. <input type="text" id="resumeMajor" class="form-control" placeholder="请输入所学专业">
  787. </div>
  788. <div class="form-col">
  789. <label for="resumeGraduation">毕业时间</label>
  790. <input type="date" id="resumeGraduation" class="form-control">
  791. </div>
  792. </div>
  793. </div>
  794. <div class="form-section">
  795. <div class="form-section-title">
  796. <i class="fas fa-briefcase"></i>
  797. <span>工作经历</span>
  798. </div>
  799. <div id="workExperienceContainer">
  800. <!-- 工作经历将通过JS动态添加 -->
  801. </div>
  802. <button class="btn" id="addWorkExperience" style="margin-top: 10px;">
  803. <i class="fas fa-plus"></i> 添加工作经历
  804. </button>
  805. </div>
  806. <div class="form-section">
  807. <div class="form-section-title">
  808. <i class="fas fa-project-diagram"></i>
  809. <span>项目经验</span>
  810. </div>
  811. <div id="projectExperienceContainer">
  812. <!-- 项目经验将通过JS动态添加 -->
  813. </div>
  814. <button class="btn" id="addProjectExperience" style="margin-top: 10px;">
  815. <i class="fas fa-plus"></i> 添加项目经验
  816. </button>
  817. </div>
  818. <div class="form-section">
  819. <div class="form-section-title">
  820. <i class="fas fa-star"></i>
  821. <span>技能专长</span>
  822. </div>
  823. <div class="form-group">
  824. <label for="resumeSkills">技能 (用逗号分隔)</label>
  825. <input type="text" id="resumeSkills" class="form-control" placeholder="例如: JavaScript, Python, 项目管理">
  826. </div>
  827. </div>
  828. <div class="form-section">
  829. <div class="form-section-title">
  830. <i class="fas fa-certificate"></i>
  831. <span>证书资质</span>
  832. </div>
  833. <div id="certificateContainer">
  834. <!-- 证书将通过JS动态添加 -->
  835. </div>
  836. <button class="btn" id="addCertificate" style="margin-top: 10px;">
  837. <i class="fas fa-plus"></i> 添加证书
  838. </button>
  839. </div>
  840. <div class="form-actions">
  841. <button class="btn" id="cancelResume">
  842. 取消
  843. </button>
  844. <button class="btn btn-primary" id="saveResume">
  845. <i class="fas fa-save"></i> 保存简历
  846. </button>
  847. <button class="btn btn-primary" id="analyzeResume">
  848. <i class="fas fa-chart-bar"></i> 分析匹配度
  849. </button>
  850. </div>
  851. </div>
  852. <!-- 职业匹配结果 -->
  853. <div class="match-result" id="matchResult" style="display: none;">
  854. <div class="match-title">
  855. <i class="fas fa-chart-pie"></i>
  856. <span>职业匹配分析</span>
  857. </div>
  858. <div id="matchList">
  859. <!-- 匹配结果将通过JS动态生成 -->
  860. </div>
  861. </div>
  862. </div>
  863. <!-- 视频面试页面 -->
  864. <div class="content-area" id="candidateInterviewPage" style="display: none;">
  865. <div class="content-title">
  866. <i class="fas fa-video"></i>
  867. <span>视频面试</span>
  868. </div>
  869. <div style="text-align: center; padding: 40px;">
  870. <i class="fas fa-video" style="font-size: 60px; color: #e2e8f0; margin-bottom: 20px;"></i>
  871. <h3 style="margin-bottom: 20px;">等待面试邀请</h3>
  872. <p style="color: #64748b; margin-bottom: 30px;">当招聘者发起面试邀请时,您将在此处看到面试信息</p>
  873. </div>
  874. </div>
  875. <!-- 面试记录页面 -->
  876. <div class="content-area" id="candidateRecordsPage" style="display: none;">
  877. <div class="content-title">
  878. <i class="fas fa-history"></i>
  879. <span>面试记录</span>
  880. </div>
  881. <div style="text-align: center; padding: 40px;">
  882. <i class="fas fa-clock" style="font-size: 60px; color: #e2e8f0; margin-bottom: 20px;"></i>
  883. <h3 style="margin-bottom: 20px;">暂无面试记录</h3>
  884. <p style="color: #64748b;">完成面试后,您的面试记录将显示在此处</p>
  885. </div>
  886. </div>
  887. </div>
  888. </div>
  889. <!-- 主界面 - 招聘者 -->
  890. <div class="container" id="recruiterContainer">
  891. <!-- 左侧导航 -->
  892. <div class="sidebar">
  893. <div class="logo">
  894. <i class="fas fa-building"></i>
  895. <span>招聘者中心</span>
  896. </div>
  897. <div class="nav-menu">
  898. <div class="nav-item active" id="navRecruiterCandidates">
  899. <i class="fas fa-users"></i>
  900. <span>候选人</span>
  901. </div>
  902. <div class="nav-item" id="navRecruiterJobs">
  903. <i class="fas fa-briefcase"></i>
  904. <span>职位管理</span>
  905. </div>
  906. <div class="nav-item" id="navRecruiterResume">
  907. <i class="fas fa-file-alt"></i>
  908. <span>简历分析</span>
  909. </div>
  910. <div class="nav-item" id="navRecruiterInterview">
  911. <i class="fas fa-video"></i>
  912. <span>视频面试</span>
  913. </div>
  914. <div class="nav-item" id="navRecruiterRecords">
  915. <i class="fas fa-history"></i>
  916. <span>面试记录</span>
  917. </div>
  918. <div class="nav-item" id="navRecruiterAnalysis">
  919. <i class="fas fa-chart-bar"></i>
  920. <span>数据分析</span>
  921. </div>
  922. </div>
  923. </div>
  924. <!-- 主内容区 -->
  925. <div class="main-content">
  926. <!-- 顶部信息栏 -->
  927. <div class="header">
  928. <div class="search-bar">
  929. <input type="text" class="search-input" placeholder="搜索候选人姓名、技能...">
  930. <button class="search-btn">
  931. <i class="fas fa-search"></i>
  932. </button>
  933. </div>
  934. <div class="user-info">
  935. <div class="user-dropdown">
  936. <div class="avatar" id="recruiterAvatar">李</div>
  937. <div class="dropdown-menu" id="recruiterDropdown">
  938. <div class="dropdown-item">
  939. <i class="fas fa-user"></i> 个人中心
  940. </div>
  941. <div class="dropdown-item">
  942. <i class="fas fa-cog"></i> 系统设置
  943. </div>
  944. <div class="dropdown-divider"></div>
  945. <div class="dropdown-item">
  946. <i class="fas fa-sign-out-alt"></i> 退出登录
  947. </div>
  948. </div>
  949. </div>
  950. <div>
  951. <div style="font-weight: 500;">李明</div>
  952. <div style="font-size: 12px; color: #64748b;">XX公司招聘经理</div>
  953. </div>
  954. </div>
  955. </div>
  956. <!-- 候选人页面 -->
  957. <div class="content-area" id="recruiterCandidatesPage">
  958. <div class="content-title">
  959. <i class="fas fa-users"></i>
  960. <span>候选人列表</span>
  961. </div>
  962. <div class="card-grid" id="candidateGrid">
  963. <!-- 候选人卡片将通过JS动态生成 -->
  964. </div>
  965. </div>
  966. <!-- 职位管理页面 -->
  967. <div class="content-area" id="recruiterJobsPage" style="display: none;">
  968. <div class="content-title">
  969. <i class="fas fa-briefcase"></i>
  970. <span>职位管理</span>
  971. </div>
  972. <div style="text-align: right; margin-bottom: 20px;">
  973. <button class="btn btn-primary" id="addJobBtn">
  974. <i class="fas fa-plus"></i> 发布新职位
  975. </button>
  976. </div>
  977. <div class="card-grid" id="jobManageGrid">
  978. <!-- 职位管理卡片将通过JS动态生成 -->
  979. </div>
  980. </div>
  981. <!-- 简历分析页面 -->
  982. <div class="content-area" id="recruiterResumePage" style="display: none;">
  983. <div class="content-title">
  984. <i class="fas fa-file-alt"></i>
  985. <span>简历分析</span>
  986. </div>
  987. <div style="text-align: center; padding: 40px;">
  988. <i class="fas fa-file-search" style="font-size: 60px; color: #e2e8f0; margin-bottom: 20px;"></i>
  989. <h3 style="margin-bottom: 20px;">选择候选人查看简历</h3>
  990. <p style="color: #64748b;">点击候选人列表中的候选人,查看其完整简历和AI分析报告</p>
  991. </div>
  992. </div>
  993. <!-- 视频面试页面 -->
  994. <div class="content-area" id="recruiterInterviewPage" style="display: none;">
  995. <div class="content-title">
  996. <i class="fas fa-video"></i>
  997. <span>视频面试</span>
  998. </div>
  999. <div style="text-align: center; padding: 40px;">
  1000. <i class="fas fa-video" style="font-size: 60px; color: #e2e8f0; margin-bottom: 20px;"></i>
  1001. <h3 style="margin-bottom: 20px;">发起视频面试</h3>
  1002. <p style="color: #64748b; margin-bottom: 30px;">选择候选人后,您可以发起视频面试邀请</p>
  1003. <button class="btn btn-primary" id="startInterviewBtn" style="display: none;">
  1004. <i class="fas fa-video"></i> 发起面试
  1005. </button>
  1006. </div>
  1007. </div>
  1008. <!-- 面试记录页面 -->
  1009. <div class="content-area" id="recruiterRecordsPage" style="display: none;">
  1010. <div class="content-title">
  1011. <i class="fas fa-history"></i>
  1012. <span>面试记录</span>
  1013. </div>
  1014. <div style="text-align: center; padding: 40px;">
  1015. <i class="fas fa-clock" style="font-size: 60px; color: #e2e8f0; margin-bottom: 20px;"></i>
  1016. <h3 style="margin-bottom: 20px;">暂无面试记录</h3>
  1017. <p style="color: #64748b;">完成面试后,您的面试记录将显示在此处</p>
  1018. </div>
  1019. </div>
  1020. <!-- 数据分析页面 -->
  1021. <div class="content-area" id="recruiterAnalysisPage" style="display: none;">
  1022. <div class="content-title">
  1023. <i class="fas fa-chart-bar"></i>
  1024. <span>数据分析</span>
  1025. </div>
  1026. <div style="text-align: center; padding: 40px;">
  1027. <i class="fas fa-chart-pie" style="font-size: 60px; color: #e2e8f0; margin-bottom: 20px;"></i>
  1028. <h3 style="margin-bottom: 20px;">数据分析面板</h3>
  1029. <p style="color: #64748b;">查看候选人数据、面试表现统计和招聘效果分析</p>
  1030. </div>
  1031. </div>
  1032. </div>
  1033. </div>
  1034. <!-- 发布职位模态框 -->
  1035. <div class="modal-overlay" id="jobModal">
  1036. <div class="modal-content">
  1037. <div class="modal-title">
  1038. <i class="fas fa-briefcase"></i>
  1039. <span>发布新职位</span>
  1040. </div>
  1041. <div class="form-group">
  1042. <label for="jobTitle">职位名称</label>
  1043. <input type="text" id="jobTitle" class="form-control" placeholder="例如: 高级产品经理">
  1044. </div>
  1045. <div class="form-group">
  1046. <label for="jobType">职位类型</label>
  1047. <select id="jobType" class="form-control">
  1048. <option value="fulltime">全职</option>
  1049. <option value="parttime">兼职</option>
  1050. <option value="intern">实习</option>
  1051. </select>
  1052. </div>
  1053. <div class="form-group">
  1054. <label for="jobDepartment">所属部门</label>
  1055. <input type="text" id="jobDepartment" class="form-control" placeholder="例如: 产品部">
  1056. </div>
  1057. <div class="form-group">
  1058. <label for="jobLocation">工作地点</label>
  1059. <input type="text" id="jobLocation" class="form-control" placeholder="例如: 北京">
  1060. </div>
  1061. <div class="form-group">
  1062. <label for="jobSalary">薪资范围</label>
  1063. <input type="text" id="jobSalary" class="form-control" placeholder="例如: 15k-30k">
  1064. </div>
  1065. <div class="form-group">
  1066. <label for="jobDescription">职位描述</label>
  1067. <textarea id="jobDescription" class="form-control" rows="5" placeholder="请输入职位描述和工作内容"></textarea>
  1068. </div>
  1069. <div class="form-group">
  1070. <label for="jobRequirements">任职要求</label>
  1071. <textarea id="jobRequirements" class="form-control" rows="5" placeholder="请输入任职要求和技能要求"></textarea>
  1072. </div>
  1073. <div class="modal-buttons">
  1074. <button class="modal-btn modal-btn-cancel" id="cancelJob">
  1075. 取消
  1076. </button>
  1077. <button class="modal-btn modal-btn-confirm" id="confirmJob">
  1078. 发布职位
  1079. </button>
  1080. </div>
  1081. </div>
  1082. </div>
  1083. <script>
  1084. // 用户类型: candidate(应聘者) 或 recruiter(招聘者)
  1085. let userType = '';
  1086. let currentUser = null;
  1087. // 工作数据
  1088. const jobs = [
  1089. {
  1090. id: 1,
  1091. title: "高级产品经理",
  1092. company: "XX科技公司",
  1093. location: "北京",
  1094. salary: "25k-40k",
  1095. type: "全职",
  1096. experience: "5年以上",
  1097. skills: ["产品规划", "用户增长", "数据分析"],
  1098. description: "负责公司核心产品的规划与设计,主导产品从0到1的开发...",
  1099. posted: "2023-10-10",
  1100. match: 82
  1101. },
  1102. {
  1103. id: 2,
  1104. title: "UI设计师",
  1105. company: "YY设计公司",
  1106. location: "上海",
  1107. salary: "15k-25k",
  1108. type: "全职",
  1109. experience: "3年以上",
  1110. skills: ["界面设计", "用户体验", "Figma"],
  1111. description: "负责公司客户产品的界面设计和用户体验优化...",
  1112. posted: "2023-10-12",
  1113. match: 76
  1114. },
  1115. {
  1116. id: 3,
  1117. title: "前端开发工程师",
  1118. company: "ZZ互联网公司",
  1119. location: "深圳",
  1120. salary: "20k-35k",
  1121. type: "全职",
  1122. experience: "3年以上",
  1123. skills: ["Vue.js", "React", "TypeScript"],
  1124. description: "负责公司核心产品的前端架构设计和开发...",
  1125. posted: "2023-10-15",
  1126. match: 88
  1127. },
  1128. {
  1129. id: 4,
  1130. title: "市场营销经理",
  1131. company: "AA集团",
  1132. location: "广州",
  1133. salary: "18k-30k",
  1134. type: "全职",
  1135. experience: "5年以上",
  1136. skills: ["品牌策划", "数字营销", "市场分析"],
  1137. description: "制定并执行公司年度营销策略,管理营销团队...",
  1138. posted: "2023-10-08",
  1139. match: 79
  1140. }
  1141. ];
  1142. // 候选人数据
  1143. const candidates = [
  1144. {
  1145. id: 1,
  1146. name: "张伟",
  1147. position: "高级产品经理",
  1148. experience: "5年",
  1149. skills: ["产品规划", "用户增长", "数据分析", "Axure", "SQL"],
  1150. location: "北京",
  1151. match: 82,
  1152. resume: "张伟的简历内容..."
  1153. },
  1154. {
  1155. id: 2,
  1156. name: "李娜",
  1157. position: "UI设计师",
  1158. experience: "3年",
  1159. skills: ["界面设计", "用户体验", "交互设计", "Sketch", "Figma"],
  1160. location: "上海",
  1161. match: 76,
  1162. resume: "李娜的简历内容..."
  1163. },
  1164. {
  1165. id: 3,
  1166. name: "王强",
  1167. position: "前端开发工程师",
  1168. experience: "4年",
  1169. skills: ["Vue.js", "React", "TypeScript", "Node.js", "Webpack"],
  1170. location: "深圳",
  1171. match: 88,
  1172. resume: "王强的简历内容..."
  1173. },
  1174. {
  1175. id: 4,
  1176. name: "赵敏",
  1177. position: "市场营销经理",
  1178. experience: "6年",
  1179. skills: ["品牌策划", "数字营销", "市场分析", "SEO", "Google Analytics"],
  1180. location: "广州",
  1181. match: 79,
  1182. resume: "赵敏的简历内容..."
  1183. }
  1184. ];
  1185. // 职位管理数据
  1186. let managedJobs = [
  1187. {
  1188. id: 1,
  1189. title: "高级产品经理",
  1190. department: "产品部",
  1191. type: "全职",
  1192. location: "北京",
  1193. salary: "25k-40k",
  1194. posted: "2023-10-01",
  1195. applicants: 12,
  1196. status: "招聘中"
  1197. },
  1198. {
  1199. id: 2,
  1200. title: "UI设计师",
  1201. department: "设计部",
  1202. type: "全职",
  1203. location: "上海",
  1204. salary: "15k-25k",
  1205. posted: "2023-09-15",
  1206. applicants: 8,
  1207. status: "招聘中"
  1208. }
  1209. ];
  1210. // 初始化页面
  1211. const initPages = () => {
  1212. // 绑定登录/注册切换事件
  1213. document.querySelectorAll('.login-tab').forEach(tab => {
  1214. tab.addEventListener('click', function() {
  1215. const tabId = this.getAttribute('data-tab');
  1216. // 更新标签页状态
  1217. document.querySelectorAll('.login-tab').forEach(t => t.classList.remove('active'));
  1218. this.classList.add('active');
  1219. // 显示对应的表单
  1220. if (tabId.includes('Reg')) {
  1221. // 注册表单
  1222. document.querySelectorAll('.login-form').forEach(form => form.classList.remove('active'));
  1223. document.getElementById(tabId === 'candidateReg' ? 'candidateRegister' : 'recruiterRegister').classList.add('active');
  1224. } else {
  1225. // 登录表单
  1226. document.querySelectorAll('.login-form').forEach(form => form.classList.remove('active'));
  1227. document.getElementById(tabId === 'candidate' ? 'candidateLogin' : 'recruiterLogin').classList.add('active');
  1228. }
  1229. });
  1230. });
  1231. // 绑定显示注册页面事件
  1232. document.getElementById('showRegister').addEventListener('click', showRegisterPage);
  1233. document.getElementById('showRegister2').addEventListener('click', showRegisterPage);
  1234. // 绑定显示忘记密码页面事件
  1235. document.getElementById('showForgot').addEventListener('click', showForgotPage);
  1236. document.getElementById('showForgot2').addEventListener('click', showForgotPage);
  1237. // 绑定返回登录事件
  1238. document.getElementById('backToLogin').addEventListener('click', showLoginPage);
  1239. document.getElementById('backToLogin2').addEventListener('click', showLoginPage);
  1240. document.getElementById('backToLogin3').addEventListener('click', showLoginPage);
  1241. // 绑定登录按钮事件
  1242. document.getElementById('candidateLoginBtn').addEventListener('click', () => login('candidate'));
  1243. document.getElementById('recruiterLoginBtn').addEventListener('click', () => login('recruiter'));
  1244. // 绑定注册按钮事件
  1245. document.getElementById('candidateRegisterBtn').addEventListener('click', () => register('candidate'));
  1246. document.getElementById('recruiterRegisterBtn').addEventListener('click', () => register('recruiter'));
  1247. // 绑定忘记密码按钮事件
  1248. document.getElementById('forgotBtn').addEventListener('click', forgotPassword);
  1249. // 生成工作卡片
  1250. document.getElementById('jobGrid').innerHTML = jobs.map(job => `
  1251. <div class="card" data-id="${job.id}">
  1252. <div class="card-header">
  1253. <div class="card-avatar">${job.company.charAt(0)}</div>
  1254. <div>
  1255. <div class="card-title">${job.title}</div>
  1256. <div class="card-subtitle">${job.company} · ${job.location}</div>
  1257. </div>
  1258. </div>
  1259. <div class="card-tags">
  1260. ${job.skills.slice(0, 3).map(skill => `<span class="card-tag">${skill}</span>`).join('')}
  1261. ${job.skills.length > 3 ? `<span class="card-tag">+${job.skills.length - 3}</span>` : ''}
  1262. </div>
  1263. <div class="card-footer">
  1264. <span class="card-match">匹配度: ${job.match}%</span>
  1265. <button class="card-btn">申请职位</button>
  1266. </div>
  1267. </div>
  1268. `).join('');
  1269. // 生成候选人卡片
  1270. document.getElementById('candidateGrid').innerHTML = candidates.map(candidate => `
  1271. <div class="card" data-id="${candidate.id}">
  1272. <div class="card-header">
  1273. <div class="card-avatar">${candidate.name.charAt(0)}</div>
  1274. <div>
  1275. <div class="card-title">${candidate.name}</div>
  1276. <div class="card-subtitle">${candidate.position} · ${candidate.experience}经验</div>
  1277. </div>
  1278. </div>
  1279. <div class="card-tags">
  1280. ${candidate.skills.slice(0, 3).map(skill => `<span class="card-tag">${skill}</span>`).join('')}
  1281. ${candidate.skills.length > 3 ? `<span class="card-tag">+${candidate.skills.length - 3}</span>` : ''}
  1282. </div>
  1283. <div class="card-footer">
  1284. <span class="card-match">匹配度: ${candidate.match}%</span>
  1285. <button class="card-btn">查看简历</button>
  1286. </div>
  1287. </div>
  1288. `).join('');
  1289. // 生成职位管理卡片
  1290. updateJobManageGrid();
  1291. // 绑定工作卡片点击事件
  1292. document.querySelectorAll('#jobGrid .card').forEach(card => {
  1293. card.addEventListener('click', function() {
  1294. const jobId = parseInt(this.getAttribute('data-id'));
  1295. showJobDetail(jobId);
  1296. });
  1297. });
  1298. // 绑定候选人卡片点击事件
  1299. document.querySelectorAll('#candidateGrid .card').forEach(card => {
  1300. card.addEventListener('click', function() {
  1301. const candidateId = parseInt(this.getAttribute('data-id'));
  1302. showCandidateDetail(candidateId);
  1303. });
  1304. });
  1305. // 绑定职位管理卡片点击事件
  1306. document.querySelectorAll('#jobManageGrid .card').forEach(card => {
  1307. card.addEventListener('click', function() {
  1308. const jobId = parseInt(this.getAttribute('data-id'));
  1309. showJobManageDetail(jobId);
  1310. });
  1311. });
  1312. // 绑定用户头像点击事件
  1313. document.getElementById('userAvatar').addEventListener('click', toggleUserDropdown);
  1314. document.getElementById('recruiterAvatar').addEventListener('click', toggleRecruiterDropdown);
  1315. // 绑定导航菜单点击事件 - 应聘者
  1316. document.getElementById('navCandidateJobs').addEventListener('click', () => switchCandidatePage('jobs'));
  1317. document.getElementById('navCandidateResume').addEventListener('click', () => switchCandidatePage('resume'));
  1318. document.getElementById('navCandidateInterview').addEventListener('click', () => switchCandidatePage('interview'));
  1319. document.getElementById('navCandidateRecords').addEventListener('click', () => switchCandidatePage('records'));
  1320. // 绑定导航菜单点击事件 - 招聘者
  1321. document.getElementById('navRecruiterCandidates').addEventListener('click', () => switchRecruiterPage('candidates'));
  1322. document.getElementById('navRecruiterJobs').addEventListener('click', () => switchRecruiterPage('jobs'));
  1323. document.getElementById('navRecruiterResume').addEventListener('click', () => switchRecruiterPage('resume'));
  1324. document.getElementById('navRecruiterInterview').addEventListener('click', () => switchRecruiterPage('interview'));
  1325. document.getElementById('navRecruiterRecords').addEventListener('click', () => switchRecruiterPage('records'));
  1326. document.getElementById('navRecruiterAnalysis').addEventListener('click', () => switchRecruiterPage('analysis'));
  1327. // 绑定简历表单事件
  1328. document.getElementById('addWorkExperience').addEventListener('click', addWorkExperienceField);
  1329. document.getElementById('addProjectExperience').addEventListener('click', addProjectExperienceField);
  1330. document.getElementById('addCertificate').addEventListener('click', addCertificateField);
  1331. document.getElementById('saveResume').addEventListener('click', saveResume);
  1332. document.getElementById('cancelResume').addEventListener('click', cancelResume);
  1333. document.getElementById('analyzeResume').addEventListener('click', analyzeResume);
  1334. // 绑定职位管理事件
  1335. document.getElementById('addJobBtn').addEventListener('click', showJobModal);
  1336. document.getElementById('cancelJob').addEventListener('click', hideJobModal);
  1337. document.getElementById('confirmJob').addEventListener('click', addNewJob);
  1338. // 绑定退出登录事件
  1339. document.querySelectorAll('.dropdown-item').forEach(item => {
  1340. if (item.textContent.includes('退出登录')) {
  1341. item.addEventListener('click', logout);
  1342. }
  1343. });
  1344. };
  1345. // 更新职位管理网格
  1346. const updateJobManageGrid = () => {
  1347. document.getElementById('jobManageGrid').innerHTML = managedJobs.map(job => `
  1348. <div class="card" data-id="${job.id}">
  1349. <div class="card-header">
  1350. <div class="card-avatar">${job.title.charAt(0)}</div>
  1351. <div>
  1352. <div class="card-title">${job.title}</div>
  1353. <div class="card-subtitle">${job.department} · ${job.location}</div>
  1354. </div>
  1355. </div>
  1356. <div class="card-tags">
  1357. <span class="card-tag">${job.type}</span>
  1358. <span class="card-tag">${job.salary}</span>
  1359. <span class="card-tag">${job.status}</span>
  1360. </div>
  1361. <div class="card-footer">
  1362. <span>${job.applicants}位申请人</span>
  1363. <span>发布于 ${job.posted}</span>
  1364. </div>
  1365. </div>
  1366. `).join('');
  1367. };
  1368. // 显示工作详情
  1369. const showJobDetail = (jobId) => {
  1370. const job = jobs.find(j => j.id === jobId);
  1371. if (!job) return;
  1372. alert(`职位详情: ${job.title}\n公司: ${job.company}\n地点: ${job.location}\n薪资: ${job.salary}\n描述: ${job.description}`);
  1373. };
  1374. // 显示候选人详情
  1375. const showCandidateDetail = (candidateId) => {
  1376. const candidate = candidates.find(c => c.id === candidateId);
  1377. if (!candidate) return;
  1378. alert(`候选人详情: ${candidate.name}\n职位: ${candidate.position}\n经验: ${candidate.experience}\n技能: ${candidate.skills.join(', ')}\n简历: ${candidate.resume}`);
  1379. // 如果是招聘者界面,显示发起面试按钮
  1380. if (userType === 'recruiter') {
  1381. document.getElementById('startInterviewBtn').style.display = 'inline-block';
  1382. }
  1383. };
  1384. // 显示职位管理详情
  1385. const showJobManageDetail = (jobId) => {
  1386. const job = managedJobs.find(j => j.id === jobId);
  1387. if (!job) return;
  1388. alert(`职位管理: ${job.title}\n部门: ${job.department}\n地点: ${job.location}\n薪资: ${job.salary}\n状态: ${job.status}\n申请人: ${job.applicants}`);
  1389. };
  1390. // 切换应聘者页面
  1391. const switchCandidatePage = (page) => {
  1392. // 隐藏所有页面
  1393. document.getElementById('candidateJobsPage').style.display = 'none';
  1394. document.getElementById('candidateResumePage').style.display = 'none';
  1395. document.getElementById('candidateInterviewPage').style.display = 'none';
  1396. document.getElementById('candidateRecordsPage').style.display = 'none';
  1397. // 显示选中的页面
  1398. document.getElementById(`candidate${page.charAt(0).toUpperCase() + page.slice(1)}Page`).style.display = 'block';
  1399. // 更新导航激活状态
  1400. document.querySelectorAll('#candidateContainer .nav-item').forEach(item => {
  1401. item.classList.remove('active');
  1402. });
  1403. document.getElementById(`navCandidate${page.charAt(0).toUpperCase() + page.slice(1)}`).classList.add('active');
  1404. };
  1405. // 切换招聘者页面
  1406. const switchRecruiterPage = (page) => {
  1407. // 隐藏所有页面
  1408. document.getElementById('recruiterCandidatesPage').style.display = 'none';
  1409. document.getElementById('recruiterJobsPage').style.display = 'none';
  1410. document.getElementById('recruiterResumePage').style.display = 'none';
  1411. document.getElementById('recruiterInterviewPage').style.display = 'none';
  1412. document.getElementById('recruiterRecordsPage').style.display = 'none';
  1413. document.getElementById('recruiterAnalysisPage').style.display = 'none';
  1414. // 显示选中的页面
  1415. document.getElementById(`recruiter${page.charAt(0).toUpperCase() + page.slice(1)}Page`).style.display = 'block';
  1416. // 更新导航激活状态
  1417. document.querySelectorAll('#recruiterContainer .nav-item').forEach(item => {
  1418. item.classList.remove('active');
  1419. });
  1420. document.getElementById(`navRecruiter${page.charAt(0).toUpperCase() + page.slice(1)}`).classList.add('active');
  1421. };
  1422. // 显示登录页面
  1423. const showLoginPage = () => {
  1424. document.getElementById('loginPage').style.display = 'flex';
  1425. document.getElementById('registerPage').style.display = 'none';
  1426. document.getElementById('forgotPage').style.display = 'none';
  1427. };
  1428. // 显示注册页面
  1429. const showRegisterPage = () => {
  1430. document.getElementById('loginPage').style.display = 'none';
  1431. document.getElementById('registerPage').style.display = 'flex';
  1432. document.getElementById('forgotPage').style.display = 'none';
  1433. };
  1434. // 显示忘记密码页面
  1435. const showForgotPage = () => {
  1436. document.getElementById('loginPage').style.display = 'none';
  1437. document.getElementById('registerPage').style.display = 'none';
  1438. document.getElementById('forgotPage').style.display = 'flex';
  1439. };
  1440. // 切换用户下拉菜单
  1441. const toggleUserDropdown = () => {
  1442. const dropdown = document.getElementById('userDropdown');
  1443. dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
  1444. };
  1445. const toggleRecruiterDropdown = () => {
  1446. const dropdown = document.getElementById('recruiterDropdown');
  1447. dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
  1448. };
  1449. // 添加工作经历字段
  1450. const addWorkExperienceField = () => {
  1451. const container = document.getElementById('workExperienceContainer');
  1452. const id = Date.now();
  1453. const html = `
  1454. <div class="form-section" id="work-${id}">
  1455. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
  1456. <div class="form-section-title">
  1457. <i class="fas fa-briefcase"></i>
  1458. <span>工作经历</span>
  1459. </div>
  1460. <button class="btn" onclick="removeField('work-${id}')">
  1461. <i class="fas fa-trash"></i> 删除
  1462. </button>
  1463. </div>
  1464. <div class="form-row">
  1465. <div class="form-col">
  1466. <label for="workCompany-${id}">公司名称</label>
  1467. <input type="text" id="workCompany-${id}" class="form-control" placeholder="请输入公司名称">
  1468. </div>
  1469. <div class="form-col">
  1470. <label for="workPosition-${id}">职位</label>
  1471. <input type="text" id="workPosition-${id}" class="form-control" placeholder="请输入职位">
  1472. </div>
  1473. </div>
  1474. <div class="form-row">
  1475. <div class="form-col">
  1476. <label for="workStart-${id}">开始时间</label>
  1477. <input type="date" id="workStart-${id}" class="form-control">
  1478. </div>
  1479. <div class="form-col">
  1480. <label for="workEnd-${id}">结束时间</label>
  1481. <input type="date" id="workEnd-${id}" class="form-control">
  1482. </div>
  1483. </div>
  1484. <div class="form-group">
  1485. <label for="workDescription-${id}">工作内容</label>
  1486. <textarea id="workDescription-${id}" class="form-control" rows="3" placeholder="请输入工作内容和职责"></textarea>
  1487. </div>
  1488. </div>
  1489. `;
  1490. container.insertAdjacentHTML('beforeend', html);
  1491. };
  1492. // 添加项目经验字段
  1493. const addProjectExperienceField = () => {
  1494. const container = document.getElementById('projectExperienceContainer');
  1495. const id = Date.now();
  1496. const html = `
  1497. <div class="form-section" id="project-${id}">
  1498. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
  1499. <div class="form-section-title">
  1500. <i class="fas fa-project-diagram"></i>
  1501. <span>项目经验</span>
  1502. </div>
  1503. <button class="btn" onclick="removeField('project-${id}')">
  1504. <i class="fas fa-trash"></i> 删除
  1505. </button>
  1506. </div>
  1507. <div class="form-row">
  1508. <div class="form-col">
  1509. <label for="projectName-${id}">项目名称</label>
  1510. <input type="text" id="projectName-${id}" class="form-control" placeholder="请输入项目名称">
  1511. </div>
  1512. <div class="form-col">
  1513. <label for="projectRole-${id}">担任角色</label>
  1514. <input type="text" id="projectRole-${id}" class="form-control" placeholder="请输入您在项目中的角色">
  1515. </div>
  1516. </div>
  1517. <div class="form-row">
  1518. <div class="form-col">
  1519. <label for="projectStart-${id}">开始时间</label>
  1520. <input type="date" id="projectStart-${id}" class="form-control">
  1521. </div>
  1522. <div class="form-col">
  1523. <label for="projectEnd-${id}">结束时间</label>
  1524. <input type="date" id="projectEnd-${id}" class="form-control">
  1525. </div>
  1526. </div>
  1527. <div class="form-group">
  1528. <label for="projectDescription-${id}">项目描述</label>
  1529. <textarea id="projectDescription-${id}" class="form-control" rows="3" placeholder="请输入项目描述"></textarea>
  1530. </div>
  1531. <div class="form-group">
  1532. <label for="projectAchievement-${id}">项目成果</label>
  1533. <textarea id="projectAchievement-${id}" class="form-control" rows="3" placeholder="请输入项目成果和收获"></textarea>
  1534. </div>
  1535. </div>
  1536. `;
  1537. container.insertAdjacentHTML('beforeend', html);
  1538. };
  1539. // 添加证书字段
  1540. const addCertificateField = () => {
  1541. const container = document.getElementById('certificateContainer');
  1542. const id = Date.now();
  1543. const html = `
  1544. <div class="form-row" id="certificate-${id}" style="margin-bottom: 16px;">
  1545. <div class="form-col">
  1546. <label for="certificateName-${id}">证书名称</label>
  1547. <input type="text" id="certificateName-${id}" class="form-control" placeholder="请输入证书名称">
  1548. </div>
  1549. <div class="form-col">
  1550. <label for="certificateTime-${id}">获得时间</label>
  1551. <input type="date" id="certificateTime-${id}" class="form-control">
  1552. </div>
  1553. <div class="form-col" style="display: flex; align-items: flex-end;">
  1554. <button class="btn" onclick="removeField('certificate-${id}')" style="height: 42px;">
  1555. <i class="fas fa-trash"></i>
  1556. </button>
  1557. </div>
  1558. </div>
  1559. `;
  1560. container.insertAdjacentHTML('beforeend', html);
  1561. };
  1562. // 删除字段
  1563. const removeField = (id) => {
  1564. document.getElementById(id).remove();
  1565. };
  1566. // 保存简历
  1567. const saveResume = () => {
  1568. alert('简历已保存');
  1569. // 这里可以添加保存简历到服务器的代码
  1570. };
  1571. // 取消编辑简历
  1572. const cancelResume = () => {
  1573. if (confirm('确定要取消编辑吗?所有未保存的更改将丢失。')) {
  1574. // 重置表单
  1575. document.getElementById('resumeForm').reset();
  1576. // 清空动态添加的字段
  1577. document.getElementById('workExperienceContainer').innerHTML = '';
  1578. document.getElementById('projectExperienceContainer').innerHTML = '';
  1579. document.getElementById('certificateContainer').innerHTML = '';
  1580. }
  1581. };
  1582. // 分析简历匹配度
  1583. const analyzeResume = () => {
  1584. // 模拟分析过程
  1585. document.getElementById('matchResult').style.display = 'block';
  1586. // 模拟匹配结果
  1587. const matches = [
  1588. { job: "高级产品经理", score: 85 },
  1589. { job: "产品经理", score: 78 },
  1590. { job: "产品助理", score: 65 },
  1591. { job: "项目经理", score: 72 },
  1592. { job: "用户研究员", score: 60 }
  1593. ];
  1594. document.getElementById('matchList').innerHTML = matches.map(match => `
  1595. <div class="match-item">
  1596. <div class="match-job">${match.job}</div>
  1597. <div class="match-score">${match.score}%</div>
  1598. </div>
  1599. `).join('');
  1600. // 滚动到结果区域
  1601. document.getElementById('matchResult').scrollIntoView({ behavior: 'smooth' });
  1602. };
  1603. // 显示职位发布模态框
  1604. const showJobModal = () => {
  1605. document.getElementById('jobModal').style.display = 'flex';
  1606. };
  1607. // 隐藏职位发布模态框
  1608. const hideJobModal = () => {
  1609. document.getElementById('jobModal').style.display = 'none';
  1610. };
  1611. // 添加新职位
  1612. const addNewJob = () => {
  1613. const title = document.getElementById('jobTitle').value;
  1614. const type = document.getElementById('jobType').value;
  1615. const department = document.getElementById('jobDepartment').value;
  1616. const location = document.getElementById('jobLocation').value;
  1617. const salary = document.getElementById('jobSalary').value;
  1618. const description = document.getElementById('jobDescription').value;
  1619. const requirements = document.getElementById('jobRequirements').value;
  1620. if (!title || !department || !location || !salary) {
  1621. alert('请填写所有必填字段');
  1622. return;
  1623. }
  1624. const now = new Date();
  1625. const newJob = {
  1626. id: managedJobs.length + 1,
  1627. title: title,
  1628. department: department,
  1629. type: type === 'fulltime' ? '全职' : type === 'parttime' ? '兼职' : '实习',
  1630. location: location,
  1631. salary: salary,
  1632. posted: `${now.getFullYear()}-${(now.getMonth()+1).toString().padStart(2, '0')}-${now.getDate().toString().padStart(2, '0')}`,
  1633. applicants: 0,
  1634. status: "招聘中"
  1635. };
  1636. managedJobs.push(newJob);
  1637. updateJobManageGrid();
  1638. hideJobModal();
  1639. // 重置表单
  1640. document.getElementById('jobTitle').value = '';
  1641. document.getElementById('jobDepartment').value = '';
  1642. document.getElementById('jobLocation').value = '';
  1643. document.getElementById('jobSalary').value = '';
  1644. document.getElementById('jobDescription').value = '';
  1645. document.getElementById('jobRequirements').value = '';
  1646. };
  1647. // 登录功能
  1648. const login = (type) => {
  1649. const usernameField = type === 'candidate' ? 'candidateUsername' : 'recruiterUsername';
  1650. const passwordField = type === 'candidate' ? 'candidatePassword' : 'recruiterPassword';
  1651. const username = document.getElementById(usernameField).value;
  1652. const password = document.getElementById(passwordField).value;
  1653. if (!username || !password) {
  1654. alert('请输入用户名和密码');
  1655. return;
  1656. }
  1657. // 模拟登录成功
  1658. userType = type;
  1659. currentUser = {
  1660. username: username,
  1661. type: type,
  1662. name: type === 'candidate' ? '张伟' : '李明',
  1663. company: type === 'recruiter' ? 'XX科技公司' : null
  1664. };
  1665. // 显示主界面
  1666. document.getElementById('loginPage').style.display = 'none';
  1667. if (type === 'candidate') {
  1668. document.getElementById('candidateContainer').style.display = 'flex';
  1669. switchCandidatePage('jobs');
  1670. } else {
  1671. document.getElementById('recruiterContainer').style.display = 'flex';
  1672. switchRecruiterPage('candidates');
  1673. }
  1674. };
  1675. // 注册功能
  1676. const register = (type) => {
  1677. const usernameField = type === 'candidate' ? 'regCandidateUsername' : 'regRecruiterUsername';
  1678. const passwordField = type === 'candidate' ? 'regCandidatePassword' : 'regRecruiterPassword';
  1679. const confirmField = type === 'candidate' ? 'regCandidateConfirm' : 'regRecruiterConfirm';
  1680. const emailField = type === 'candidate' ? 'regCandidateEmail' : 'regRecruiterEmail';
  1681. const username = document.getElementById(usernameField).value;
  1682. const password = document.getElementById(passwordField).value;
  1683. const confirm = document.getElementById(confirmField).value;
  1684. const email = document.getElementById(emailField).value;
  1685. const company = type === 'recruiter' ? document.getElementById('regCompany').value : null;
  1686. if (!username || !password || !confirm || !email) {
  1687. alert('请填写所有必填字段');
  1688. return;
  1689. }
  1690. if (password !== confirm) {
  1691. alert('两次输入的密码不一致');
  1692. return;
  1693. }
  1694. if (type === 'recruiter' && !company) {
  1695. alert('请填写公司名称');
  1696. return;
  1697. }
  1698. // 模拟注册成功
  1699. alert('注册成功!请登录');
  1700. showLoginPage();
  1701. };
  1702. // 忘记密码功能
  1703. const forgotPassword = () => {
  1704. const email = document.getElementById('forgotEmail').value;
  1705. if (!email) {
  1706. alert('请输入电子邮箱');
  1707. return;
  1708. }
  1709. // 模拟发送重置链接
  1710. alert(`重置链接已发送至 ${email},请查收邮件并按照指示操作`);
  1711. showLoginPage();
  1712. };
  1713. // 退出登录
  1714. const logout = () => {
  1715. userType = '';
  1716. currentUser = null;
  1717. // 隐藏所有主界面
  1718. document.getElementById('candidateContainer').style.display = 'none';
  1719. document.getElementById('recruiterContainer').style.display = 'none';
  1720. // 显示登录页面
  1721. showLoginPage();
  1722. };
  1723. // 初始化页面
  1724. initPages();
  1725. </script>
  1726. </body>
  1727. </html>