2
2

jianli.html 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070
  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. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  8. <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  9. <style>
  10. :root {
  11. --primary: #4361ee;
  12. --primary-dark: #3a0ca3;
  13. --secondary: #4cc9f0;
  14. --success: #2ecc71;
  15. --warning: #f39c12;
  16. --danger: #e74c3c;
  17. --light: #f8f9fa;
  18. --dark: #212529;
  19. --gray: #6c757d;
  20. --light-gray: #e9ecef;
  21. --border: #dee2e6;
  22. --shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  23. --transition: all 0.3s ease;
  24. --radius: 10px;
  25. }
  26. * {
  27. margin: 0;
  28. padding: 0;
  29. box-sizing: border-box;
  30. font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
  31. }
  32. body {
  33. background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
  34. color: var(--dark);
  35. line-height: 1.6;
  36. min-height: 100vh;
  37. }
  38. .container {
  39. max-width: 1400px;
  40. margin: 0 auto;
  41. padding: 20px;
  42. }
  43. /* 顶部导航栏 */
  44. header {
  45. background: white;
  46. box-shadow: var(--shadow);
  47. border-radius: var(--radius);
  48. margin-bottom: 25px;
  49. position: sticky;
  50. top: 10px;
  51. z-index: 100;
  52. }
  53. .navbar {
  54. display: flex;
  55. justify-content: space-between;
  56. align-items: center;
  57. padding: 15px 30px;
  58. }
  59. .logo {
  60. display: flex;
  61. align-items: center;
  62. gap: 15px;
  63. font-size: 1.8rem;
  64. font-weight: 700;
  65. color: var(--primary);
  66. }
  67. .logo i {
  68. color: var(--primary-dark);
  69. }
  70. .nav-links {
  71. display: flex;
  72. gap: 20px;
  73. }
  74. .nav-link {
  75. padding: 10px 20px;
  76. border-radius: 30px;
  77. font-weight: 600;
  78. cursor: pointer;
  79. transition: var(--transition);
  80. display: flex;
  81. align-items: center;
  82. gap: 8px;
  83. }
  84. .nav-link:hover {
  85. background: var(--light);
  86. }
  87. .nav-link.active {
  88. background: var(--primary);
  89. color: white;
  90. }
  91. .system-info {
  92. display: flex;
  93. gap: 20px;
  94. align-items: center;
  95. }
  96. .resume-count {
  97. background: var(--light);
  98. padding: 8px 15px;
  99. border-radius: 30px;
  100. font-weight: 600;
  101. }
  102. .btn {
  103. background: var(--primary);
  104. color: white;
  105. border: none;
  106. padding: 10px 20px;
  107. border-radius: 30px;
  108. cursor: pointer;
  109. font-weight: 600;
  110. transition: var(--transition);
  111. display: inline-flex;
  112. align-items: center;
  113. gap: 8px;
  114. }
  115. .btn:hover {
  116. background: var(--primary-dark);
  117. transform: translateY(-2px);
  118. box-shadow: 0 4px 8px rgba(67, 97, 238, 0.3);
  119. }
  120. .btn-success {
  121. background: var(--success);
  122. }
  123. .btn-success:hover {
  124. background: #27ae60;
  125. box-shadow: 0 4px 8px rgba(46, 204, 113, 0.3);
  126. }
  127. .btn-warning {
  128. background: var(--warning);
  129. }
  130. .btn-warning:hover {
  131. background: #e67e22;
  132. box-shadow: 0 4px 8px rgba(243, 156, 18, 0.3);
  133. }
  134. .btn-light {
  135. background: var(--light);
  136. color: var(--dark);
  137. }
  138. .btn-light:hover {
  139. background: #e2e6ea;
  140. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  141. }
  142. /* 页面容器 */
  143. .page-container {
  144. display: none;
  145. animation: fadeIn 0.5s ease;
  146. }
  147. .page-container.active {
  148. display: block;
  149. }
  150. @keyframes fadeIn {
  151. from { opacity: 0; transform: translateY(10px); }
  152. to { opacity: 1; transform: translateY(0); }
  153. }
  154. /* 面板样式 */
  155. .panel {
  156. background: white;
  157. border-radius: var(--radius);
  158. box-shadow: var(--shadow);
  159. padding: 25px;
  160. margin-bottom: 25px;
  161. }
  162. .panel-header {
  163. display: flex;
  164. justify-content: space-between;
  165. align-items: center;
  166. margin-bottom: 20px;
  167. padding-bottom: 15px;
  168. border-bottom: 1px solid var(--light-gray);
  169. }
  170. .panel-title {
  171. font-size: 1.5rem;
  172. font-weight: 700;
  173. color: var(--primary-dark);
  174. display: flex;
  175. align-items: center;
  176. gap: 10px;
  177. }
  178. /* 简历列表页 */
  179. .filters-bar {
  180. display: flex;
  181. gap: 15px;
  182. flex-wrap: wrap;
  183. margin-bottom: 20px;
  184. padding: 15px;
  185. background: white;
  186. border-radius: var(--radius);
  187. box-shadow: var(--shadow);
  188. }
  189. .filter-group {
  190. display: flex;
  191. flex-direction: column;
  192. min-width: 200px;
  193. }
  194. .filter-label {
  195. font-weight: 600;
  196. margin-bottom: 8px;
  197. color: var(--gray);
  198. font-size: 0.9rem;
  199. }
  200. .filter-control {
  201. padding: 10px 15px;
  202. border: 1px solid var(--border);
  203. border-radius: 8px;
  204. font-size: 1rem;
  205. }
  206. .candidate-grid {
  207. display: grid;
  208. grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  209. gap: 20px;
  210. }
  211. .candidate-card {
  212. background: white;
  213. border-radius: var(--radius);
  214. overflow: hidden;
  215. box-shadow: var(--shadow);
  216. transition: var(--transition);
  217. border: 1px solid var(--border);
  218. position: relative;
  219. }
  220. .candidate-card:hover {
  221. transform: translateY(-5px);
  222. box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
  223. }
  224. .candidate-header {
  225. background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  226. color: white;
  227. padding: 20px;
  228. position: relative;
  229. }
  230. .candidate-status {
  231. position: absolute;
  232. top: 15px;
  233. right: 15px;
  234. background: rgba(255, 255, 255, 0.2);
  235. padding: 5px 15px;
  236. border-radius: 20px;
  237. font-size: 0.85rem;
  238. font-weight: 600;
  239. }
  240. .status-passed {
  241. background: rgba(46, 204, 113, 0.3);
  242. }
  243. .status-pending {
  244. background: rgba(243, 156, 18, 0.3);
  245. }
  246. .candidate-avatar {
  247. width: 80px;
  248. height: 80px;
  249. border-radius: 50%;
  250. background: white;
  251. display: flex;
  252. align-items: center;
  253. justify-content: center;
  254. font-size: 2rem;
  255. color: var(--primary);
  256. margin-bottom: 15px;
  257. border: 3px solid rgba(255, 255, 255, 0.5);
  258. }
  259. .candidate-name {
  260. font-size: 1.5rem;
  261. margin-bottom: 5px;
  262. }
  263. .candidate-title {
  264. opacity: 0.9;
  265. font-size: 1rem;
  266. margin-bottom: 10px;
  267. }
  268. .candidate-score {
  269. display: inline-block;
  270. background: rgba(255, 255, 255, 0.2);
  271. padding: 5px 15px;
  272. border-radius: 20px;
  273. font-weight: 700;
  274. font-size: 1.1rem;
  275. }
  276. .candidate-body {
  277. padding: 20px;
  278. }
  279. .candidate-info {
  280. margin-bottom: 15px;
  281. }
  282. .info-item {
  283. display: flex;
  284. margin-bottom: 10px;
  285. font-size: 0.95rem;
  286. }
  287. .info-label {
  288. width: 100px;
  289. font-weight: 600;
  290. color: var(--gray);
  291. }
  292. .skills {
  293. display: flex;
  294. flex-wrap: wrap;
  295. gap: 8px;
  296. margin-top: 10px;
  297. }
  298. .skill {
  299. background: var(--light);
  300. padding: 5px 12px;
  301. border-radius: 20px;
  302. font-size: 0.85rem;
  303. }
  304. .card-actions {
  305. display: flex;
  306. justify-content: space-between;
  307. padding: 15px 20px;
  308. border-top: 1px solid var(--light-gray);
  309. }
  310. /* 筛选配置页 */
  311. .config-grid {
  312. display: grid;
  313. grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  314. gap: 25px;
  315. }
  316. .config-section {
  317. background: var(--light);
  318. border-radius: var(--radius);
  319. padding: 20px;
  320. }
  321. .config-title {
  322. font-size: 1.2rem;
  323. margin-bottom: 15px;
  324. color: var(--primary-dark);
  325. display: flex;
  326. align-items: center;
  327. gap: 10px;
  328. }
  329. .criteria-list {
  330. list-style: none;
  331. }
  332. .criteria-item {
  333. padding: 12px 0;
  334. border-bottom: 1px solid var(--border);
  335. display: flex;
  336. justify-content: space-between;
  337. align-items: center;
  338. }
  339. .criteria-name {
  340. font-weight: 500;
  341. }
  342. .criteria-controls {
  343. display: flex;
  344. align-items: center;
  345. gap: 10px;
  346. }
  347. .slider-container {
  348. padding: 10px 0;
  349. }
  350. .slider-label {
  351. display: flex;
  352. justify-content: space-between;
  353. margin-bottom: 5px;
  354. }
  355. .slider-value {
  356. font-weight: 700;
  357. color: var(--primary);
  358. }
  359. input[type="range"] {
  360. width: 100%;
  361. height: 8px;
  362. border-radius: 5px;
  363. background: var(--light-gray);
  364. outline: none;
  365. }
  366. /* 简历详情页 */
  367. .resume-detail-container {
  368. display: grid;
  369. grid-template-columns: 300px 1fr;
  370. gap: 30px;
  371. }
  372. .resume-sidebar {
  373. background: white;
  374. border-radius: var(--radius);
  375. box-shadow: var(--shadow);
  376. padding: 25px;
  377. position: sticky;
  378. top: 100px;
  379. align-self: start;
  380. }
  381. .candidate-basic {
  382. text-align: center;
  383. padding-bottom: 20px;
  384. margin-bottom: 20px;
  385. border-bottom: 1px solid var(--light-gray);
  386. }
  387. .detail-avatar {
  388. width: 120px;
  389. height: 120px;
  390. border-radius: 50%;
  391. background: var(--light);
  392. display: flex;
  393. align-items: center;
  394. justify-content: center;
  395. font-size: 3rem;
  396. color: var(--primary);
  397. margin: 0 auto 15px;
  398. border: 5px solid var(--light-gray);
  399. }
  400. .detail-name {
  401. font-size: 1.8rem;
  402. margin-bottom: 5px;
  403. }
  404. .detail-title {
  405. font-size: 1.2rem;
  406. color: var(--gray);
  407. margin-bottom: 15px;
  408. }
  409. .detail-score {
  410. display: inline-block;
  411. background: var(--primary);
  412. color: white;
  413. padding: 8px 25px;
  414. border-radius: 30px;
  415. font-weight: 700;
  416. font-size: 1.3rem;
  417. margin-bottom: 15px;
  418. }
  419. .contact-info {
  420. margin: 20px 0;
  421. }
  422. .contact-item {
  423. display: flex;
  424. gap: 10px;
  425. margin-bottom: 15px;
  426. align-items: center;
  427. }
  428. .resume-content {
  429. background: white;
  430. border-radius: var(--radius);
  431. box-shadow: var(--shadow);
  432. padding: 30px;
  433. position: relative;
  434. }
  435. .back-button {
  436. position: absolute;
  437. top: 25px;
  438. right: 25px;
  439. }
  440. .section-title {
  441. font-size: 1.4rem;
  442. color: var(--primary-dark);
  443. margin: 30px 0 20px;
  444. padding-bottom: 10px;
  445. border-bottom: 2px solid var(--light-gray);
  446. display: flex;
  447. align-items: center;
  448. gap: 10px;
  449. }
  450. .section-content {
  451. line-height: 1.8;
  452. }
  453. .timeline-item {
  454. margin-bottom: 25px;
  455. padding-left: 20px;
  456. border-left: 2px solid var(--primary);
  457. position: relative;
  458. }
  459. .timeline-item:before {
  460. content: '';
  461. position: absolute;
  462. left: -8px;
  463. top: 5px;
  464. width: 14px;
  465. height: 14px;
  466. border-radius: 50%;
  467. background: var(--primary);
  468. }
  469. .timeline-period {
  470. font-weight: 600;
  471. color: var(--primary);
  472. margin-bottom: 5px;
  473. }
  474. .timeline-title {
  475. font-weight: 700;
  476. margin-bottom: 5px;
  477. }
  478. .skill-bars {
  479. margin-top: 20px;
  480. }
  481. .skill-bar {
  482. margin-bottom: 15px;
  483. }
  484. .skill-info {
  485. display: flex;
  486. justify-content: space-between;
  487. margin-bottom: 5px;
  488. }
  489. .skill-progress {
  490. height: 10px;
  491. background: var(--light-gray);
  492. border-radius: 5px;
  493. overflow: hidden;
  494. }
  495. .skill-progress-inner {
  496. height: 100%;
  497. background: var(--primary);
  498. border-radius: 5px;
  499. }
  500. /* 数据看板页 */
  501. .dashboard-grid {
  502. display: grid;
  503. grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  504. gap: 20px;
  505. }
  506. .metric-card {
  507. background: white;
  508. border-radius: var(--radius);
  509. padding: 25px;
  510. box-shadow: var(--shadow);
  511. display: flex;
  512. flex-direction: column;
  513. align-items: center;
  514. text-align: center;
  515. }
  516. .metric-icon {
  517. width: 70px;
  518. height: 70px;
  519. border-radius: 50%;
  520. background: rgba(67, 97, 238, 0.1);
  521. display: flex;
  522. align-items: center;
  523. justify-content: center;
  524. font-size: 1.8rem;
  525. color: var(--primary);
  526. margin-bottom: 15px;
  527. }
  528. .metric-value {
  529. font-size: 2.5rem;
  530. font-weight: 700;
  531. margin: 10px 0;
  532. color: var(--primary);
  533. }
  534. .metric-label {
  535. color: var(--gray);
  536. font-size: 1.1rem;
  537. }
  538. .metric-change {
  539. margin-top: 10px;
  540. font-weight: 600;
  541. color: var(--success);
  542. }
  543. .chart-container {
  544. background: white;
  545. border-radius: var(--radius);
  546. padding: 25px;
  547. box-shadow: var(--shadow);
  548. margin-top: 25px;
  549. height: 400px;
  550. }
  551. .chart-header {
  552. display: flex;
  553. justify-content: space-between;
  554. align-items: center;
  555. margin-bottom: 20px;
  556. }
  557. .chart-title {
  558. font-size: 1.3rem;
  559. font-weight: 700;
  560. color: var(--dark);
  561. }
  562. /* 响应式设计 */
  563. @media (max-width: 992px) {
  564. .resume-detail-container {
  565. grid-template-columns: 1fr;
  566. }
  567. .resume-sidebar {
  568. position: static;
  569. }
  570. }
  571. @media (max-width: 768px) {
  572. .navbar {
  573. flex-direction: column;
  574. gap: 15px;
  575. }
  576. .nav-links {
  577. width: 100%;
  578. justify-content: center;
  579. flex-wrap: wrap;
  580. }
  581. .system-info {
  582. width: 100%;
  583. justify-content: center;
  584. }
  585. .filters-bar {
  586. flex-direction: column;
  587. }
  588. .card-actions {
  589. flex-direction: column;
  590. gap: 10px;
  591. }
  592. .card-actions .btn {
  593. width: 100%;
  594. }
  595. }
  596. </style>
  597. </head>
  598. <body>
  599. <div class="container">
  600. <!-- 顶部导航栏 -->
  601. <header>
  602. <div class="navbar">
  603. <div class="logo">
  604. <i class="fas fa-file-alt"></i>
  605. <span>智能简历筛选系统</span>
  606. </div>
  607. <div class="nav-links">
  608. <div class="nav-link active" data-page="resume-list">
  609. <i class="fas fa-list"></i>
  610. <span>简历列表</span>
  611. </div>
  612. <div class="nav-link" data-page="filter-config">
  613. <i class="fas fa-sliders-h"></i>
  614. <span>筛选配置</span>
  615. </div>
  616. <div class="nav-link" data-page="dashboard">
  617. <i class="fas fa-chart-bar"></i>
  618. <span>数据看板</span>
  619. </div>
  620. </div>
  621. <div class="system-info">
  622. <div class="resume-count">
  623. <i class="fas fa-file"></i>
  624. <span>简历总数: <span id="total-resumes">24</span></span>
  625. </div>
  626. <button class="btn btn-success" id="filter-action">
  627. <i class="fas fa-filter"></i>
  628. <span>一键筛选 (<span id="passed-resumes">16</span>通过)</span>
  629. </button>
  630. </div>
  631. </div>
  632. </header>
  633. <!-- 简历列表页 -->
  634. <div class="page-container active" id="resume-list-page">
  635. <div class="panel">
  636. <div class="panel-header">
  637. <h2 class="panel-title">
  638. <i class="fas fa-users"></i>
  639. <span>候选人列表</span>
  640. </h2>
  641. <div class="filters-bar">
  642. <div class="filter-group">
  643. <label class="filter-label">职位类型</label>
  644. <select class="filter-control" id="position-filter">
  645. <option value="">所有职位</option>
  646. <option>前端开发</option>
  647. <option>后端开发</option>
  648. <option>UI/UX设计</option>
  649. <option>数据分析</option>
  650. <option>产品经理</option>
  651. <option>测试工程师</option>
  652. </select>
  653. </div>
  654. <div class="filter-group">
  655. <label class="filter-label">工作经验</label>
  656. <select class="filter-control" id="experience-filter">
  657. <option value="0">不限经验</option>
  658. <option value="1">1年以下</option>
  659. <option value="3">1-3年</option>
  660. <option value="5">3-5年</option>
  661. <option value="10">5年以上</option>
  662. </select>
  663. </div>
  664. <div class="filter-group">
  665. <label class="filter-label">学历要求</label>
  666. <select class="filter-control" id="education-filter">
  667. <option value="">不限学历</option>
  668. <option>大专</option>
  669. <option>本科</option>
  670. <option>硕士</option>
  671. <option>博士</option>
  672. </select>
  673. </div>
  674. <div class="filter-group">
  675. <label class="filter-label">最低评分</label>
  676. <input type="number" class="filter-control" min="0" max="100" value="70" id="min-score">
  677. </div>
  678. <button class="btn" id="apply-filters">
  679. <i class="fas fa-search"></i>
  680. <span>应用筛选</span>
  681. </button>
  682. </div>
  683. </div>
  684. <div class="candidate-grid" id="candidate-container">
  685. <!-- 候选人卡片将通过JS动态生成 -->
  686. </div>
  687. </div>
  688. </div>
  689. <!-- 筛选配置页 -->
  690. <div class="page-container" id="filter-config-page">
  691. <div class="panel">
  692. <div class="panel-header">
  693. <h2 class="panel-title">
  694. <i class="fas fa-cog"></i>
  695. <span>筛选配置</span>
  696. </h2>
  697. <button class="btn" id="save-config">
  698. <i class="fas fa-save"></i>
  699. <span>保存配置</span>
  700. </button>
  701. </div>
  702. <div class="config-grid">
  703. <div class="config-section">
  704. <h3 class="config-title">
  705. <i class="fas fa-graduation-cap"></i>
  706. <span>学历要求</span>
  707. </h3>
  708. <ul class="criteria-list">
  709. <li class="criteria-item">
  710. <span class="criteria-name">大专</span>
  711. <div class="criteria-controls">
  712. <input type="checkbox" checked data-type="education" data-value="大专">
  713. </div>
  714. </li>
  715. <li class="criteria-item">
  716. <span class="criteria-name">本科</span>
  717. <div class="criteria-controls">
  718. <input type="checkbox" checked data-type="education" data-value="本科">
  719. </div>
  720. </li>
  721. <li class="criteria-item">
  722. <span class="criteria-name">硕士</span>
  723. <div class="criteria-controls">
  724. <input type="checkbox" checked data-type="education" data-value="硕士">
  725. </div>
  726. </li>
  727. <li class="criteria-item">
  728. <span class="criteria-name">博士</span>
  729. <div class="criteria-controls">
  730. <input type="checkbox" checked data-type="education" data-value="博士">
  731. </div>
  732. </li>
  733. </ul>
  734. </div>
  735. <div class="config-section">
  736. <h3 class="config-title">
  737. <i class="fas fa-briefcase"></i>
  738. <span>工作经验</span>
  739. </h3>
  740. <div class="slider-container">
  741. <div class="slider-label">
  742. <span>最低年限</span>
  743. <span class="slider-value" id="exp-value">3年</span>
  744. </div>
  745. <input type="range" min="0" max="10" value="3" id="exp-slider">
  746. </div>
  747. </div>
  748. <div class="config-section">
  749. <h3 class="config-title">
  750. <i class="fas fa-money-bill-wave"></i>
  751. <span>薪资范围</span>
  752. </h3>
  753. <div class="slider-container">
  754. <div class="slider-label">
  755. <span>最高薪资</span>
  756. <span class="slider-value" id="salary-value">20K</span>
  757. </div>
  758. <input type="range" min="5" max="50" value="20" step="5" id="salary-slider">
  759. </div>
  760. </div>
  761. <div class="config-section">
  762. <h3 class="config-title">
  763. <i class="fas fa-star"></i>
  764. <span>评分设置</span>
  765. </h3>
  766. <div class="slider-container">
  767. <div class="slider-label">
  768. <span>通过阈值</span>
  769. <span class="slider-value" id="score-value">70分</span>
  770. </div>
  771. <input type="range" min="50" max="100" value="70" id="score-slider">
  772. </div>
  773. </div>
  774. <div class="config-section">
  775. <h3 class="config-title">
  776. <i class="fas fa-code"></i>
  777. <span>技能要求</span>
  778. </h3>
  779. <ul class="criteria-list">
  780. <li class="criteria-item">
  781. <span class="criteria-name">JavaScript</span>
  782. <div class="criteria-controls">
  783. <input type="checkbox" checked data-type="skill" data-value="JavaScript">
  784. </div>
  785. </li>
  786. <li class="criteria-item">
  787. <span class="criteria-name">React</span>
  788. <div class="criteria-controls">
  789. <input type="checkbox" checked data-type="skill" data-value="React">
  790. </div>
  791. </li>
  792. <li class="criteria-item">
  793. <span class="criteria-name">Node.js</span>
  794. <div class="criteria-controls">
  795. <input type="checkbox" data-type="skill" data-value="Node.js">
  796. </div>
  797. </li>
  798. <li class="criteria-item">
  799. <span class="criteria-name">Python</span>
  800. <div class="criteria-controls">
  801. <input type="checkbox" data-type="skill" data-value="Python">
  802. </div>
  803. </li>
  804. <li class="criteria-item">
  805. <span class="criteria-name">SQL</span>
  806. <div class="criteria-controls">
  807. <input type="checkbox" data-type="skill" data-value="SQL">
  808. </div>
  809. </li>
  810. <li class="criteria-item">
  811. <span class="criteria-name">AWS</span>
  812. <div class="criteria-controls">
  813. <input type="checkbox" data-type="skill" data-value="AWS">
  814. </div>
  815. </li>
  816. <li class="criteria-item">
  817. <span class="criteria-name">Docker</span>
  818. <div class="criteria-controls">
  819. <input type="checkbox" data-type="skill" data-value="Docker">
  820. </div>
  821. </li>
  822. <li class="criteria-item">
  823. <span class="criteria-name">Git</span>
  824. <div class="criteria-controls">
  825. <input type="checkbox" checked data-type="skill" data-value="Git">
  826. </div>
  827. </li>
  828. </ul>
  829. </div>
  830. </div>
  831. </div>
  832. </div>
  833. <!-- 简历详情页 -->
  834. <div class="page-container" id="resume-detail-page">
  835. <div class="resume-detail-container">
  836. <div class="resume-sidebar">
  837. <div class="candidate-basic">
  838. <div class="detail-avatar">
  839. <i class="fas fa-user"></i>
  840. </div>
  841. <h2 class="detail-name" id="detail-name">张明</h2>
  842. <div class="detail-title" id="detail-title">高级前端开发工程师</div>
  843. <div class="detail-score" id="detail-score">86分</div>
  844. <div class="candidate-status" id="detail-status">已通过</div>
  845. </div>
  846. <div class="contact-info" id="contact-info">
  847. <div class="contact-item">
  848. <i class="fas fa-envelope"></i>
  849. <span>zhangming@example.com</span>
  850. </div>
  851. <div class="contact-item">
  852. <i class="fas fa-phone"></i>
  853. <span>13800138000</span>
  854. </div>
  855. <div class="contact-item">
  856. <i class="fas fa-map-marker-alt"></i>
  857. <span>北京市海淀区</span>
  858. </div>
  859. </div>
  860. <div class="skills">
  861. <h3 class="section-title">
  862. <i class="fas fa-code"></i>
  863. <span>技能专长</span>
  864. </h3>
  865. <div class="skill-bars" id="skill-bars">
  866. <!-- 技能条将通过JS动态生成 -->
  867. </div>
  868. </div>
  869. </div>
  870. <div class="resume-content">
  871. <button class="btn btn-light back-button" id="back-to-list">
  872. <i class="fas fa-arrow-left"></i>
  873. <span>返回列表</span>
  874. </button>
  875. <h2 class="section-title">
  876. <i class="fas fa-user"></i>
  877. <span>个人简介</span>
  878. </h2>
  879. <div class="section-content" id="personal-profile">
  880. <!-- 个人简介内容将通过JS动态生成 -->
  881. </div>
  882. <h2 class="section-title">
  883. <i class="fas fa-briefcase"></i>
  884. <span>工作经历</span>
  885. </h2>
  886. <div class="section-content" id="work-experience">
  887. <!-- 工作经历内容将通过JS动态生成 -->
  888. </div>
  889. <h2 class="section-title">
  890. <i class="fas fa-graduation-cap"></i>
  891. <span>教育背景</span>
  892. </h2>
  893. <div class="section-content" id="education-background">
  894. <!-- 教育背景内容将通过JS动态生成 -->
  895. </div>
  896. <h2 class="section-title">
  897. <i class="fas fa-medal"></i>
  898. <span>项目经验</span>
  899. </h2>
  900. <div class="section-content" id="project-experience">
  901. <!-- 项目经验内容将通过JS动态生成 -->
  902. </div>
  903. </div>
  904. </div>
  905. </div>
  906. <!-- 数据看板页 -->
  907. <div class="page-container" id="dashboard-page">
  908. <div class="dashboard-grid">
  909. <div class="metric-card">
  910. <div class="metric-icon">
  911. <i class="fas fa-file"></i>
  912. </div>
  913. <div class="metric-value" id="total-resumes-dash">24</div>
  914. <div class="metric-label">简历总数</div>
  915. </div>
  916. <div class="metric-card">
  917. <div class="metric-icon">
  918. <i class="fas fa-check-circle"></i>
  919. </div>
  920. <div class="metric-value" id="passed-resumes-dash">16</div>
  921. <div class="metric-label">通过筛选</div>
  922. <div class="metric-change">+2 较昨日</div>
  923. </div>
  924. <div class="metric-card">
  925. <div class="metric-icon">
  926. <i class="fas fa-percentage"></i>
  927. </div>
  928. <div class="metric-value">66.7%</div>
  929. <div class="metric-label">筛选通过率</div>
  930. <div class="metric-change">+3.5% 较上周</div>
  931. </div>
  932. <div class="metric-card">
  933. <div class="metric-icon">
  934. <i class="fas fa-star"></i>
  935. </div>
  936. <div class="metric-value">78.4</div>
  937. <div class="metric-label">平均评分</div>
  938. <div class="metric-change">+1.2 较上月</div>
  939. </div>
  940. </div>
  941. <div class="chart-container">
  942. <div class="chart-header">
  943. <div class="chart-title">简历评分分布</div>
  944. <div class="filter-control">
  945. <select id="score-chart-range">
  946. <option>最近7天</option>
  947. <option>最近30天</option>
  948. <option>全部时间</option>
  949. </select>
  950. </div>
  951. </div>
  952. <canvas id="score-distribution-chart"></canvas>
  953. </div>
  954. <div class="chart-container">
  955. <div class="chart-header">
  956. <div class="chart-title">岗位类型分布</div>
  957. </div>
  958. <canvas id="position-distribution-chart"></canvas>
  959. </div>
  960. </div>
  961. </div>
  962. <script>
  963. // 简历数据 - 增加更多示例
  964. const resumes = [
  965. {
  966. id: 1,
  967. name: "张明",
  968. title: "高级前端开发工程师",
  969. education: "本科",
  970. experience: 5,
  971. salary: 25,
  972. score: 86,
  973. skills: ["JavaScript", "HTML", "CSS", "React", "Vue", "TypeScript", "Webpack"],
  974. status: "passed",
  975. location: "北京",
  976. email: "zhangming@example.com",
  977. phone: "13800138000",
  978. profile: "5年前端开发经验,专注于构建高性能、用户友好的Web应用程序。精通现代JavaScript框架和响应式设计,对前端工程化和性能优化有深入研究。具有良好的团队协作能力和沟通技巧,能够高效地解决复杂问题并交付高质量产品。",
  979. workExperience: [
  980. {
  981. period: "2020年6月 - 至今",
  982. company: "科技有限公司",
  983. position: "高级前端工程师",
  984. responsibilities: [
  985. "负责公司核心产品的前端架构设计和实现",
  986. "优化应用性能,提升页面加载速度40%",
  987. "设计和实现组件库,提高团队开发效率",
  988. "指导初级开发人员,组织技术分享会"
  989. ]
  990. },
  991. {
  992. period: "2018年3月 - 2020年5月",
  993. company: "网络科技有限公司",
  994. position: "前端开发工程师",
  995. responsibilities: [
  996. "参与电商平台的前端开发",
  997. "实现响应式设计,优化移动端体验",
  998. "与后端团队协作开发API接口",
  999. "参与代码审查和团队技术决策"
  1000. ]
  1001. }
  1002. ],
  1003. education: [
  1004. {
  1005. period: "2014年9月 - 2018年6月",
  1006. school: "北京大学",
  1007. major: "计算机科学与技术",
  1008. degree: "本科"
  1009. }
  1010. ],
  1011. projects: [
  1012. {
  1013. name: "企业级管理系统重构",
  1014. description: "将遗留系统从AngularJS迁移到React + TypeScript",
  1015. responsibilities: [
  1016. "设计并实现组件库,统一UI风格",
  1017. "优化构建流程,减少构建时间50%",
  1018. "实现自动化测试,覆盖率从30%提升到85%"
  1019. ]
  1020. },
  1021. {
  1022. name: "移动电商平台",
  1023. description: "使用Vue.js开发高性能移动端应用",
  1024. responsibilities: [
  1025. "实现服务端渲染(SSR)提升首屏加载速度",
  1026. "集成支付系统和物流跟踪功能",
  1027. "优化SEO,提升自然搜索流量30%"
  1028. ]
  1029. }
  1030. ],
  1031. skillLevels: [
  1032. { name: "JavaScript", level: 95 },
  1033. { name: "React", level: 90 },
  1034. { name: "Vue.js", level: 85 },
  1035. { name: "HTML/CSS", level: 92 },
  1036. { name: "TypeScript", level: 88 },
  1037. { name: "Webpack", level: 80 }
  1038. ]
  1039. },
  1040. {
  1041. id: 2,
  1042. name: "李华",
  1043. title: "Java后端工程师",
  1044. education: "硕士",
  1045. experience: 6,
  1046. salary: 28,
  1047. score: 92,
  1048. skills: ["Java", "Spring", "MySQL", "Redis", "Linux", "Docker"],
  1049. status: "passed",
  1050. location: "上海",
  1051. email: "lihua@example.com",
  1052. phone: "13900139000",
  1053. profile: "6年Java后端开发经验,精通Spring生态和微服务架构。熟悉高并发、分布式系统设计,有丰富的性能调优经验。主导过多个大型企业级应用的后端架构设计和实现,对系统安全和稳定性有深刻理解。",
  1054. workExperience: [
  1055. {
  1056. period: "2019年7月 - 至今",
  1057. company: "信息技术有限公司",
  1058. position: "高级Java工程师",
  1059. responsibilities: [
  1060. "设计和实现微服务架构",
  1061. "优化数据库查询性能,减少响应时间60%",
  1062. "实现分布式缓存系统",
  1063. "负责系统安全设计和实现"
  1064. ]
  1065. },
  1066. {
  1067. period: "2017年2月 - 2019年6月",
  1068. company: "软件科技有限公司",
  1069. position: "Java开发工程师",
  1070. responsibilities: [
  1071. "参与企业ERP系统开发",
  1072. "设计和实现RESTful API",
  1073. "优化SQL查询,提高系统性能",
  1074. "参与系统架构设计"
  1075. ]
  1076. }
  1077. ],
  1078. education: [
  1079. {
  1080. period: "2013年9月 - 2017年6月",
  1081. school: "清华大学",
  1082. major: "软件工程",
  1083. degree: "硕士"
  1084. }
  1085. ],
  1086. projects: [
  1087. {
  1088. name: "电商平台后端系统",
  1089. description: "高并发电商平台后端架构设计和实现",
  1090. responsibilities: [
  1091. "设计微服务架构",
  1092. "实现分布式事务处理",
  1093. "优化数据库性能"
  1094. ]
  1095. },
  1096. {
  1097. name: "支付系统",
  1098. description: "企业级支付系统开发",
  1099. responsibilities: [
  1100. "设计支付流程",
  1101. "实现与第三方支付平台对接",
  1102. "确保系统安全性和稳定性"
  1103. ]
  1104. }
  1105. ],
  1106. skillLevels: [
  1107. { name: "Java", level: 98 },
  1108. { name: "Spring", level: 95 },
  1109. { name: "MySQL", level: 90 },
  1110. { name: "Redis", level: 88 },
  1111. { name: "Docker", level: 85 },
  1112. { name: "Linux", level: 80 }
  1113. ]
  1114. },
  1115. {
  1116. id: 3,
  1117. name: "王芳",
  1118. title: "全栈工程师",
  1119. education: "本科",
  1120. experience: 4,
  1121. salary: 22,
  1122. score: 78,
  1123. skills: ["JavaScript", "Node.js", "Express", "MongoDB", "React"],
  1124. status: "passed",
  1125. location: "深圳",
  1126. email: "wangfang@example.com",
  1127. phone: "13700137000",
  1128. profile: "4年全栈开发经验,熟悉JavaScript全栈技术。能够独立完成从前端到后端的完整开发流程。对Web性能优化和用户体验有深入研究,擅长快速学习和应用新技术。",
  1129. workExperience: [
  1130. {
  1131. period: "2019年1月 - 至今",
  1132. company: "互联网科技有限公司",
  1133. position: "全栈工程师",
  1134. responsibilities: [
  1135. "负责Web应用全栈开发",
  1136. "设计和实现RESTful API",
  1137. "优化前端性能",
  1138. "参与数据库设计和优化"
  1139. ]
  1140. }
  1141. ],
  1142. education: [
  1143. {
  1144. period: "2015年9月 - 2019年6月",
  1145. school: "浙江大学",
  1146. major: "计算机科学与技术",
  1147. degree: "本科"
  1148. }
  1149. ],
  1150. projects: [
  1151. {
  1152. name: "内容管理系统",
  1153. description: "基于MERN技术栈的内容管理系统",
  1154. responsibilities: [
  1155. "全栈开发",
  1156. "实现用户权限管理",
  1157. "优化编辑器体验"
  1158. ]
  1159. }
  1160. ],
  1161. skillLevels: [
  1162. { name: "JavaScript", level: 90 },
  1163. { name: "Node.js", level: 85 },
  1164. { name: "React", level: 80 },
  1165. { name: "MongoDB", level: 75 },
  1166. { name: "Express", level: 70 }
  1167. ]
  1168. },
  1169. {
  1170. id: 4,
  1171. name: "刘伟",
  1172. title: "Python数据分析师",
  1173. education: "硕士",
  1174. experience: 3,
  1175. salary: 18,
  1176. score: 72,
  1177. skills: ["Python", "Pandas", "NumPy", "Matplotlib", "SQL"],
  1178. status: "passed",
  1179. location: "广州",
  1180. email: "liuwei@example.com",
  1181. phone: "13600136000",
  1182. profile: "3年数据分析经验,精通Python数据分析工具链。擅长数据清洗、分析和可视化,能够从海量数据中提取有价值的信息。有丰富的商业分析和预测建模经验。",
  1183. workExperience: [
  1184. {
  1185. period: "2020年5月 - 至今",
  1186. company: "数据科技有限公司",
  1187. position: "数据分析师",
  1188. responsibilities: [
  1189. "数据清洗和分析",
  1190. "构建预测模型",
  1191. "生成数据报告",
  1192. "可视化数据展示"
  1193. ]
  1194. }
  1195. ],
  1196. education: [
  1197. {
  1198. period: "2017年9月 - 2020年6月",
  1199. school: "中山大学",
  1200. major: "数据科学",
  1201. degree: "硕士"
  1202. }
  1203. ],
  1204. projects: [
  1205. {
  1206. name: "销售预测系统",
  1207. description: "基于历史数据的销售预测模型",
  1208. responsibilities: [
  1209. "数据收集和清洗",
  1210. "特征工程",
  1211. "模型训练和评估"
  1212. ]
  1213. }
  1214. ],
  1215. skillLevels: [
  1216. { name: "Python", level: 90 },
  1217. { name: "Pandas", level: 85 },
  1218. { name: "NumPy", level: 80 },
  1219. { name: "Matplotlib", level: 75 },
  1220. { name: "SQL", level: 70 }
  1221. ]
  1222. },
  1223. {
  1224. id: 5,
  1225. name: "陈静",
  1226. title: "UI/UX设计师",
  1227. education: "本科",
  1228. experience: 4,
  1229. salary: 20,
  1230. score: 65,
  1231. skills: ["Figma", "Sketch", "Photoshop", "Illustrator", "UI设计"],
  1232. status: "pending",
  1233. location: "杭州",
  1234. email: "chenjing@example.com",
  1235. phone: "13500135000",
  1236. profile: "4年UI/UX设计经验,擅长移动端和Web端界面设计。对用户体验有深刻理解,能够将复杂需求转化为直观易用的界面。熟悉设计系统和组件化设计方法。",
  1237. workExperience: [
  1238. {
  1239. period: "2019年3月 - 至今",
  1240. company: "设计工作室",
  1241. position: "UI设计师",
  1242. responsibilities: [
  1243. "移动应用界面设计",
  1244. "设计规范制定",
  1245. "用户研究",
  1246. "原型设计"
  1247. ]
  1248. }
  1249. ],
  1250. education: [
  1251. {
  1252. period: "2015年9月 - 2019年6月",
  1253. school: "中国美术学院",
  1254. major: "视觉传达设计",
  1255. degree: "本科"
  1256. }
  1257. ],
  1258. projects: [
  1259. {
  1260. name: "电商App设计",
  1261. description: "从0到1设计电商App",
  1262. responsibilities: [
  1263. "用户调研",
  1264. "信息架构设计",
  1265. "界面设计",
  1266. "设计规范制定"
  1267. ]
  1268. }
  1269. ],
  1270. skillLevels: [
  1271. { name: "Figma", level: 95 },
  1272. { name: "Sketch", level: 90 },
  1273. { name: "Photoshop", level: 85 },
  1274. { name: "Illustrator", level: 80 },
  1275. { name: "UI设计", level: 90 }
  1276. ]
  1277. },
  1278. {
  1279. id: 6,
  1280. name: "杨阳",
  1281. title: "DevOps工程师",
  1282. education: "本科",
  1283. experience: 7,
  1284. salary: 32,
  1285. score: 88,
  1286. skills: ["Docker", "Kubernetes", "AWS", "Jenkins", "Linux"],
  1287. status: "passed",
  1288. location: "成都",
  1289. email: "yangyang@example.com",
  1290. phone: "13400134000",
  1291. profile: "7年DevOps经验,精通云原生技术和自动化部署。熟悉CI/CD流程优化,能够构建高可用、可扩展的基础设施。对系统监控和性能调优有丰富经验。",
  1292. workExperience: [
  1293. {
  1294. period: "2018年8月 - 至今",
  1295. company: "云计算有限公司",
  1296. position: "DevOps工程师",
  1297. responsibilities: [
  1298. "设计和维护CI/CD流程",
  1299. "容器化应用部署",
  1300. "云基础设施管理",
  1301. "系统监控和告警"
  1302. ]
  1303. }
  1304. ],
  1305. education: [
  1306. {
  1307. period: "2011年9月 - 2015年6月",
  1308. school: "电子科技大学",
  1309. major: "计算机科学与技术",
  1310. degree: "本科"
  1311. }
  1312. ],
  1313. projects: [
  1314. {
  1315. name: "微服务架构部署",
  1316. description: "将单体应用迁移到微服务架构",
  1317. responsibilities: [
  1318. "容器化部署",
  1319. "服务网格配置",
  1320. "自动化扩缩容"
  1321. ]
  1322. }
  1323. ],
  1324. skillLevels: [
  1325. { name: "Docker", level: 95 },
  1326. { name: "Kubernetes", level: 90 },
  1327. { name: "AWS", level: 85 },
  1328. { name: "Jenkins", level: 80 },
  1329. { name: "Linux", level: 90 }
  1330. ]
  1331. },
  1332. {
  1333. id: 7,
  1334. name: "赵琳",
  1335. title: "移动开发工程师",
  1336. education: "硕士",
  1337. experience: 3,
  1338. salary: 21,
  1339. score: 75,
  1340. skills: ["Swift", "Kotlin", "React Native", "Flutter", "iOS"],
  1341. status: "pending",
  1342. location: "南京",
  1343. email: "zhaolin@example.com",
  1344. phone: "13300133000",
  1345. profile: "3年移动开发经验,熟悉iOS和Android原生开发以及跨平台框架。对移动端性能优化和用户体验有深入研究。能够快速学习和应用新技术。",
  1346. workExperience: [
  1347. {
  1348. period: "2020年2月 - 至今",
  1349. company: "移动科技有限公司",
  1350. position: "移动开发工程师",
  1351. responsibilities: [
  1352. "iOS原生应用开发",
  1353. "Android原生应用开发",
  1354. "跨平台应用开发",
  1355. "性能优化"
  1356. ]
  1357. }
  1358. ],
  1359. education: [
  1360. {
  1361. period: "2017年9月 - 2020年6月",
  1362. school: "东南大学",
  1363. major: "软件工程",
  1364. degree: "硕士"
  1365. }
  1366. ],
  1367. projects: [
  1368. {
  1369. name: "社交App开发",
  1370. description: "基于React Native的跨平台社交应用",
  1371. responsibilities: [
  1372. "核心功能开发",
  1373. "性能优化",
  1374. "与后端API对接"
  1375. ]
  1376. }
  1377. ],
  1378. skillLevels: [
  1379. { name: "Swift", level: 85 },
  1380. { name: "Kotlin", level: 80 },
  1381. { name: "React Native", level: 75 },
  1382. { name: "Flutter", level: 70 },
  1383. { name: "iOS", level: 85 }
  1384. ]
  1385. },
  1386. {
  1387. id: 8,
  1388. name: "周涛",
  1389. title: "大数据工程师",
  1390. education: "博士",
  1391. experience: 8,
  1392. salary: 38,
  1393. score: 90,
  1394. skills: ["Hadoop", "Spark", "Hive", "Scala", "Python"],
  1395. status: "passed",
  1396. location: "武汉",
  1397. email: "zhoutao@example.com",
  1398. phone: "13200132000",
  1399. profile: "8年大数据领域经验,精通Hadoop生态和Spark计算框架。擅长海量数据处理和分析,有丰富的分布式系统优化经验。能够设计和实现高效的数据处理流程。",
  1400. workExperience: [
  1401. {
  1402. period: "2017年5月 - 至今",
  1403. company: "大数据科技有限公司",
  1404. position: "大数据工程师",
  1405. responsibilities: [
  1406. "大数据平台架构设计",
  1407. "数据处理流程优化",
  1408. "实时计算系统开发",
  1409. "团队技术指导"
  1410. ]
  1411. }
  1412. ],
  1413. education: [
  1414. {
  1415. period: "2012年9月 - 2017年6月",
  1416. school: "华中科技大学",
  1417. major: "计算机科学与技术",
  1418. degree: "博士"
  1419. }
  1420. ],
  1421. projects: [
  1422. {
  1423. name: "实时数据分析平台",
  1424. description: "基于Spark Streaming的实时数据处理平台",
  1425. responsibilities: [
  1426. "架构设计",
  1427. "性能优化",
  1428. "数据管道开发"
  1429. ]
  1430. }
  1431. ],
  1432. skillLevels: [
  1433. { name: "Hadoop", level: 95 },
  1434. { name: "Spark", level: 90 },
  1435. { name: "Hive", level: 85 },
  1436. { name: "Scala", level: 80 },
  1437. { name: "Python", level: 75 }
  1438. ]
  1439. },
  1440. {
  1441. id: 9,
  1442. name: "吴强",
  1443. title: "测试工程师",
  1444. education: "本科",
  1445. experience: 5,
  1446. salary: 18,
  1447. score: 68,
  1448. skills: ["自动化测试", "Selenium", "JMeter", "Postman", "JIRA"],
  1449. status: "pending",
  1450. location: "西安",
  1451. email: "wuqiang@example.com",
  1452. phone: "13100131000",
  1453. profile: "5年软件测试经验,精通自动化测试和性能测试。熟悉敏捷开发流程,能够设计和实施全面的测试策略。对质量保证和缺陷管理有丰富经验。",
  1454. workExperience: [
  1455. {
  1456. period: "2018年4月 - 至今",
  1457. company: "软件测试有限公司",
  1458. position: "测试工程师",
  1459. responsibilities: [
  1460. "自动化测试脚本开发",
  1461. "性能测试",
  1462. "测试用例设计",
  1463. "缺陷跟踪和管理"
  1464. ]
  1465. }
  1466. ],
  1467. education: [
  1468. {
  1469. period: "2014年9月 - 2018年6月",
  1470. school: "西安电子科技大学",
  1471. major: "软件工程",
  1472. degree: "本科"
  1473. }
  1474. ],
  1475. projects: [
  1476. {
  1477. name: "电商平台测试",
  1478. description: "全流程测试电商平台",
  1479. responsibilities: [
  1480. "功能测试",
  1481. "性能测试",
  1482. "安全测试",
  1483. "测试报告生成"
  1484. ]
  1485. }
  1486. ],
  1487. skillLevels: [
  1488. { name: "自动化测试", level: 85 },
  1489. { name: "Selenium", level: 80 },
  1490. { name: "JMeter", level: 75 },
  1491. { name: "Postman", level: 70 },
  1492. { name: "JIRA", level: 65 }
  1493. ]
  1494. },
  1495. {
  1496. id: 10,
  1497. name: "郑雪",
  1498. title: "产品经理",
  1499. education: "硕士",
  1500. experience: 6,
  1501. salary: 25,
  1502. score: 82,
  1503. skills: ["产品规划", "用户研究", "Axure", "数据分析", "项目管理"],
  1504. status: "passed",
  1505. location: "重庆",
  1506. email: "zhengxue@example.com",
  1507. phone: "13000130000",
  1508. profile: "6年产品管理经验,熟悉从0到1的产品开发全流程。擅长用户需求分析和产品设计,能够协调跨部门团队推动产品落地。对数据驱动决策有深刻理解。",
  1509. workExperience: [
  1510. {
  1511. period: "2019年1月 - 至今",
  1512. company: "互联网产品有限公司",
  1513. position: "产品经理",
  1514. responsibilities: [
  1515. "产品路线图规划",
  1516. "用户需求分析",
  1517. "产品原型设计",
  1518. "跨部门协调"
  1519. ]
  1520. }
  1521. ],
  1522. education: [
  1523. {
  1524. period: "2016年9月 - 2019年6月",
  1525. school: "重庆大学",
  1526. major: "工商管理",
  1527. degree: "硕士"
  1528. }
  1529. ],
  1530. projects: [
  1531. {
  1532. name: "企业SaaS产品",
  1533. description: "从0到1设计并推出企业级SaaS产品",
  1534. responsibilities: [
  1535. "市场调研",
  1536. "产品功能设计",
  1537. "用户体验优化",
  1538. "产品上线推广"
  1539. ]
  1540. }
  1541. ],
  1542. skillLevels: [
  1543. { name: "产品规划", level: 90 },
  1544. { name: "用户研究", level: 85 },
  1545. { name: "Axure", level: 80 },
  1546. { name: "数据分析", level: 75 },
  1547. { name: "项目管理", level: 70 }
  1548. ]
  1549. }
  1550. ];
  1551. // 当前查看的简历ID
  1552. let currentViewingResumeId = null;
  1553. // 初始化应用
  1554. document.addEventListener('DOMContentLoaded', function() {
  1555. renderCandidates(resumes);
  1556. setupEventListeners();
  1557. updateResumeCounts();
  1558. initSliders();
  1559. initCharts();
  1560. });
  1561. // 渲染候选人列表
  1562. function renderCandidates(candidates) {
  1563. const container = document.getElementById('candidate-container');
  1564. if (candidates.length === 0) {
  1565. container.innerHTML = `<div class="no-results">没有找到匹配的候选人,请调整筛选条件</div>`;
  1566. return;
  1567. }
  1568. let html = '';
  1569. candidates.forEach(candidate => {
  1570. const statusClass = candidate.status === "passed" ? "status-passed" : "status-pending";
  1571. const statusText = candidate.status === "passed" ? "已通过" : "待审核";
  1572. html += `
  1573. <div class="candidate-card" data-id="${candidate.id}">
  1574. <div class="candidate-header">
  1575. <div class="candidate-status ${statusClass}">${statusText}</div>
  1576. <div class="candidate-avatar">
  1577. <i class="fas fa-user"></i>
  1578. </div>
  1579. <div class="candidate-name">${candidate.name}</div>
  1580. <div class="candidate-title">${candidate.title}</div>
  1581. <div class="candidate-score">${candidate.score}分</div>
  1582. </div>
  1583. <div class="candidate-body">
  1584. <div class="candidate-info">
  1585. <div class="info-item">
  1586. <span class="info-label">学历:</span>
  1587. <span>${candidate.education}</span>
  1588. </div>
  1589. <div class="info-item">
  1590. <span class="info-label">经验:</span>
  1591. <span>${candidate.experience}年</span>
  1592. </div>
  1593. <div class="info-item">
  1594. <span class="info-label">期望薪资:</span>
  1595. <span>${candidate.salary}K/月</span>
  1596. </div>
  1597. <div class="info-item">
  1598. <span class="info-label">所在地:</span>
  1599. <span>${candidate.location}</span>
  1600. </div>
  1601. </div>
  1602. <div class="candidate-skills">
  1603. <div class="info-label">技能:</div>
  1604. <div class="skills">
  1605. ${candidate.skills.map(skill => `<div class="skill">${skill}</div>`).join('')}
  1606. </div>
  1607. </div>
  1608. </div>
  1609. <div class="card-actions">
  1610. <button class="btn btn-warning view-detail">
  1611. <i class="fas fa-eye"></i> 查看详情
  1612. </button>
  1613. <button class="btn ${candidate.status === "passed" ? "btn-success" : ""} toggle-status">
  1614. <i class="fas ${candidate.status === "passed" ? "fa-check" : "fa-hourglass-half"}"></i>
  1615. ${candidate.status === "passed" ? "已通过" : "标记通过"}
  1616. </button>
  1617. </div>
  1618. </div>
  1619. `;
  1620. });
  1621. container.innerHTML = html;
  1622. // 添加查看详情事件
  1623. document.querySelectorAll('.view-detail').forEach(button => {
  1624. button.addEventListener('click', function() {
  1625. const card = this.closest('.candidate-card');
  1626. const candidateId = parseInt(card.dataset.id);
  1627. viewResumeDetail(candidateId);
  1628. });
  1629. });
  1630. // 添加标记通过事件
  1631. document.querySelectorAll('.toggle-status').forEach(button => {
  1632. button.addEventListener('click', function() {
  1633. const card = this.closest('.candidate-card');
  1634. const candidateId = parseInt(card.dataset.id);
  1635. toggleCandidateStatus(candidateId);
  1636. });
  1637. });
  1638. }
  1639. // 设置事件监听器
  1640. function setupEventListeners() {
  1641. // 导航切换
  1642. document.querySelectorAll('.nav-link').forEach(link => {
  1643. link.addEventListener('click', function() {
  1644. if (this.dataset.page === 'resume-detail') return;
  1645. document.querySelectorAll('.nav-link').forEach(el => {
  1646. el.classList.remove('active');
  1647. });
  1648. this.classList.add('active');
  1649. const pageId = this.dataset.page + '-page';
  1650. document.querySelectorAll('.page-container').forEach(page => {
  1651. page.classList.remove('active');
  1652. });
  1653. document.getElementById(pageId).classList.add('active');
  1654. });
  1655. });
  1656. // 一键筛选按钮
  1657. document.getElementById('filter-action').addEventListener('click', function() {
  1658. const minScore = parseInt(document.getElementById('min-score').value);
  1659. filterCandidates(minScore);
  1660. });
  1661. // 应用筛选按钮
  1662. document.getElementById('apply-filters').addEventListener('click', applyFilters);
  1663. // 返回列表按钮
  1664. document.getElementById('back-to-list').addEventListener('click', backToList);
  1665. // 保存配置按钮
  1666. document.getElementById('save-config').addEventListener('click', saveConfig);
  1667. }
  1668. // 初始化滑块控件
  1669. function initSliders() {
  1670. const expSlider = document.getElementById('exp-slider');
  1671. const expValue = document.getElementById('exp-value');
  1672. const salarySlider = document.getElementById('salary-slider');
  1673. const salaryValue = document.getElementById('salary-value');
  1674. const scoreSlider = document.getElementById('score-slider');
  1675. const scoreValue = document.getElementById('score-value');
  1676. expSlider.addEventListener('input', () => {
  1677. expValue.textContent = expSlider.value + '年';
  1678. });
  1679. salarySlider.addEventListener('input', () => {
  1680. salaryValue.textContent = salarySlider.value + 'K';
  1681. });
  1682. scoreSlider.addEventListener('input', () => {
  1683. scoreValue.textContent = scoreSlider.value + '分';
  1684. document.getElementById('min-score').value = scoreSlider.value;
  1685. });
  1686. }
  1687. // 初始化图表
  1688. function initCharts() {
  1689. // 评分分布图
  1690. const scoreCtx = document.getElementById('score-distribution-chart').getContext('2d');
  1691. new Chart(scoreCtx, {
  1692. type: 'bar',
  1693. data: {
  1694. labels: ['50-59', '60-69', '70-79', '80-89', '90-100'],
  1695. datasets: [{
  1696. label: '人数',
  1697. data: [2, 5, 8, 6, 3],
  1698. backgroundColor: '#4361ee'
  1699. }]
  1700. },
  1701. options: {
  1702. responsive: true,
  1703. scales: {
  1704. y: {
  1705. beginAtZero: true
  1706. }
  1707. }
  1708. }
  1709. });
  1710. // 岗位类型分布图
  1711. const positionCtx = document.getElementById('position-distribution-chart').getContext('2d');
  1712. new Chart(positionCtx, {
  1713. type: 'doughnut',
  1714. data: {
  1715. labels: ['前端开发', '后端开发', 'UI/UX设计', '数据分析', '产品经理', '测试工程师'],
  1716. datasets: [{
  1717. data: [3, 2, 1, 1, 1, 1],
  1718. backgroundColor: [
  1719. '#4361ee',
  1720. '#4cc9f0',
  1721. '#3a0ca3',
  1722. '#7209b7',
  1723. '#f72585',
  1724. '#4895ef'
  1725. ]
  1726. }]
  1727. },
  1728. options: {
  1729. responsive: true,
  1730. plugins: {
  1731. legend: {
  1732. position: 'right'
  1733. }
  1734. }
  1735. }
  1736. });
  1737. }
  1738. // 筛选候选人
  1739. function filterCandidates(minScore) {
  1740. const filtered = resumes.filter(candidate => candidate.score >= minScore);
  1741. renderCandidates(filtered);
  1742. // 更新通过人数
  1743. const passedCount = filtered.filter(c => c.status === "passed").length;
  1744. document.getElementById('passed-resumes').textContent = passedCount;
  1745. document.getElementById('passed-resumes-dash').textContent = passedCount;
  1746. }
  1747. // 应用筛选条件
  1748. function applyFilters() {
  1749. const position = document.getElementById('position-filter').value;
  1750. const experience = parseInt(document.getElementById('experience-filter').value);
  1751. const education = document.getElementById('education-filter').value;
  1752. const minScore = parseInt(document.getElementById('min-score').value);
  1753. const filtered = resumes.filter(candidate => {
  1754. // 职位筛选
  1755. if (position && !candidate.title.includes(position)) {
  1756. return false;
  1757. }
  1758. // 经验筛选
  1759. if (experience > 0 && candidate.experience < experience) {
  1760. return false;
  1761. }
  1762. // 学历筛选
  1763. if (education && candidate.education !== education) {
  1764. return false;
  1765. }
  1766. // 评分筛选
  1767. if (candidate.score < minScore) {
  1768. return false;
  1769. }
  1770. return true;
  1771. });
  1772. renderCandidates(filtered);
  1773. }
  1774. // 查看简历详情
  1775. function viewResumeDetail(candidateId) {
  1776. const candidate = resumes.find(c => c.id === candidateId);
  1777. if (!candidate) return;
  1778. currentViewingResumeId = candidateId;
  1779. // 更新基本信息
  1780. document.getElementById('detail-name').textContent = candidate.name;
  1781. document.getElementById('detail-title').textContent = candidate.title;
  1782. document.getElementById('detail-score').textContent = candidate.score + '分';
  1783. const statusElement = document.getElementById('detail-status');
  1784. statusElement.textContent = candidate.status === "passed" ? "已通过" : "待审核";
  1785. statusElement.className = `candidate-status status-${candidate.status}`;
  1786. // 更新联系方式
  1787. const contactInfo = document.getElementById('contact-info');
  1788. contactInfo.innerHTML = `
  1789. <div class="contact-item">
  1790. <i class="fas fa-envelope"></i>
  1791. <span>${candidate.email}</span>
  1792. </div>
  1793. <div class="contact-item">
  1794. <i class="fas fa-phone"></i>
  1795. <span>${candidate.phone}</span>
  1796. </div>
  1797. <div class="contact-item">
  1798. <i class="fas fa-map-marker-alt"></i>
  1799. <span>${candidate.location}</span>
  1800. </div>
  1801. `;
  1802. // 更新技能条
  1803. const skillBars = document.getElementById('skill-bars');
  1804. skillBars.innerHTML = candidate.skillLevels.map(skill => `
  1805. <div class="skill-bar">
  1806. <div class="skill-info">
  1807. <span>${skill.name}</span>
  1808. <span>${skill.level}%</span>
  1809. </div>
  1810. <div class="skill-progress">
  1811. <div class="skill-progress-inner" style="width: ${skill.level}%"></div>
  1812. </div>
  1813. </div>
  1814. `).join('');
  1815. // 更新个人简介
  1816. document.getElementById('personal-profile').innerHTML = `
  1817. <p>${candidate.profile}</p>
  1818. `;
  1819. // 更新工作经历
  1820. const workExperience = document.getElementById('work-experience');
  1821. workExperience.innerHTML = candidate.workExperience.map(exp => `
  1822. <div class="timeline-item">
  1823. <div class="timeline-period">${exp.period}</div>
  1824. <div class="timeline-title">${exp.position} - ${exp.company}</div>
  1825. <ul>
  1826. ${exp.responsibilities.map(resp => `<li>${resp}</li>`).join('')}
  1827. </ul>
  1828. </div>
  1829. `).join('');
  1830. // 更新教育背景
  1831. const educationBackground = document.getElementById('education-background');
  1832. educationBackground.innerHTML = candidate.education.map(edu => `
  1833. <div class="timeline-item">
  1834. <div class="timeline-period">${edu.period}</div>
  1835. <div class="timeline-title">${edu.major} ${edu.degree}</div>
  1836. <div>${edu.school}</div>
  1837. </div>
  1838. `).join('');
  1839. // 更新项目经验
  1840. const projectExperience = document.getElementById('project-experience');
  1841. projectExperience.innerHTML = candidate.projects.map(project => `
  1842. <div class="timeline-item">
  1843. <div class="timeline-title">${project.name}</div>
  1844. <p>${project.description}</p>
  1845. <ul>
  1846. ${project.responsibilities.map(resp => `<li>${resp}</li>`).join('')}
  1847. </ul>
  1848. </div>
  1849. `).join('');
  1850. // 切换到详情页
  1851. document.querySelectorAll('.page-container').forEach(page => {
  1852. page.classList.remove('active');
  1853. });
  1854. document.getElementById('resume-detail-page').classList.add('active');
  1855. }
  1856. // 返回列表
  1857. function backToList() {
  1858. document.querySelectorAll('.page-container').forEach(page => {
  1859. page.classList.remove('active');
  1860. });
  1861. document.getElementById('resume-list-page').classList.add('active');
  1862. // 确保列表页的导航按钮高亮
  1863. document.querySelectorAll('.nav-link').forEach(link => {
  1864. link.classList.remove('active');
  1865. });
  1866. document.querySelector('[data-page="resume-list"]').classList.add('active');
  1867. }
  1868. // 切换候选人状态
  1869. function toggleCandidateStatus(candidateId) {
  1870. const candidate = resumes.find(c => c.id === candidateId);
  1871. if (!candidate) return;
  1872. candidate.status = candidate.status === "passed" ? "pending" : "passed";
  1873. renderCandidates(resumes);
  1874. updateResumeCounts();
  1875. // 如果当前正在查看这个候选人的详情,更新详情页状态
  1876. if (currentViewingResumeId === candidateId) {
  1877. const statusElement = document.getElementById('detail-status');
  1878. statusElement.textContent = candidate.status === "passed" ? "已通过" : "待审核";
  1879. statusElement.className = `candidate-status status-${candidate.status}`;
  1880. }
  1881. }
  1882. // 更新简历数量统计
  1883. function updateResumeCounts() {
  1884. const total = resumes.length;
  1885. const passed = resumes.filter(c => c.status === "passed").length;
  1886. document.getElementById('total-resumes').textContent = total;
  1887. document.getElementById('passed-resumes').textContent = passed;
  1888. document.getElementById('total-resumes-dash').textContent = total;
  1889. document.getElementById('passed-resumes-dash').textContent = passed;
  1890. }
  1891. // 保存配置
  1892. function saveConfig() {
  1893. alert('筛选配置已保存');
  1894. // 在实际应用中,这里会将配置保存到本地存储或后端
  1895. }
  1896. </script>
  1897. </body>
  1898. </html>