employee-info-panel.component.scss 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526
  1. // ========== 员工信息侧边栏面板样式 ==========
  2. // ⭐ 真正的组件复用:不需要引入样式,组件自带样式
  3. // 只需要调整嵌入模式下的显示
  4. // ⭐ 嵌入模式适配:覆盖 employee-detail-panel 组件的外层样式
  5. .tab-content.workload-tab {
  6. padding: 0;
  7. height: 100%;
  8. // 使用 ::ng-deep 调整嵌入组件的样式
  9. ::ng-deep app-employee-detail-panel {
  10. // 隐藏组件的遮罩层和面板容器(embedMode=true 时应该自动处理)
  11. .employee-detail-overlay {
  12. position: static;
  13. background: transparent;
  14. backdrop-filter: none;
  15. z-index: auto;
  16. padding: 0;
  17. animation: none;
  18. }
  19. .employee-detail-panel {
  20. box-shadow: none;
  21. border-radius: 0;
  22. max-width: 100%;
  23. max-height: none;
  24. animation: none;
  25. // 隐藏嵌入模式下的头部(因为父组件已经有头部了)
  26. .panel-header {
  27. display: none;
  28. }
  29. // 让内容区域填满可用空间
  30. .panel-content {
  31. max-height: none;
  32. padding: 0;
  33. }
  34. }
  35. }
  36. }
  37. // 加载状态样式
  38. .loading-state-workload {
  39. display: flex;
  40. flex-direction: column;
  41. align-items: center;
  42. justify-content: center;
  43. padding: 60px 20px;
  44. color: #8c8c8c;
  45. .spinner {
  46. width: 40px;
  47. height: 40px;
  48. border: 3px solid #f0f0f0;
  49. border-top-color: #1890ff;
  50. border-radius: 50%;
  51. animation: spin 0.8s linear infinite;
  52. margin-bottom: 16px;
  53. }
  54. p {
  55. font-size: 14px;
  56. margin: 0;
  57. }
  58. }
  59. @keyframes spin {
  60. to {
  61. transform: rotate(360deg);
  62. }
  63. }
  64. .employee-info-overlay {
  65. position: fixed;
  66. top: 0;
  67. left: 0;
  68. right: 0;
  69. bottom: 0;
  70. background: rgba(0, 0, 0, 0.5);
  71. z-index: 9999;
  72. display: flex;
  73. justify-content: flex-end;
  74. animation: fadeIn 0.2s ease;
  75. }
  76. .employee-info-panel {
  77. width: 600px;
  78. max-width: 90vw;
  79. height: 100vh;
  80. background: #fff;
  81. box-shadow: -2px 0 12px rgba(0, 0, 0, 0.15);
  82. display: flex;
  83. flex-direction: column;
  84. animation: slideInRight 0.3s ease;
  85. }
  86. // ========== 面板头部 ==========
  87. .panel-header {
  88. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  89. color: white;
  90. padding: 0;
  91. flex-shrink: 0;
  92. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  93. }
  94. .header-top {
  95. display: flex;
  96. align-items: center;
  97. justify-content: space-between;
  98. padding: 20px 24px;
  99. }
  100. .panel-title {
  101. display: flex;
  102. align-items: center;
  103. gap: 12px;
  104. margin: 0;
  105. font-size: 20px;
  106. font-weight: 600;
  107. .employee-avatar-small {
  108. width: 48px;
  109. height: 48px;
  110. border-radius: 50%;
  111. object-fit: cover;
  112. border: 2px solid rgba(255, 255, 255, 0.3);
  113. }
  114. .title-content {
  115. display: flex;
  116. flex-direction: column;
  117. gap: 4px;
  118. .employee-name {
  119. font-size: 18px;
  120. font-weight: 600;
  121. }
  122. .employee-role-badge {
  123. display: inline-block;
  124. padding: 2px 8px;
  125. border-radius: 12px;
  126. font-size: 12px;
  127. font-weight: 500;
  128. background: rgba(255, 255, 255, 0.2);
  129. backdrop-filter: blur(10px);
  130. width: fit-content;
  131. &[data-role="组长"] {
  132. background: rgba(255, 193, 7, 0.3);
  133. }
  134. &[data-role="组员"] {
  135. background: rgba(33, 150, 243, 0.3);
  136. }
  137. &[data-role="客服"] {
  138. background: rgba(76, 175, 80, 0.3);
  139. }
  140. &[data-role="管理员"] {
  141. background: rgba(156, 39, 176, 0.3);
  142. }
  143. }
  144. }
  145. }
  146. .btn-close {
  147. width: 36px;
  148. height: 36px;
  149. border-radius: 50%;
  150. background: rgba(255, 255, 255, 0.1);
  151. border: 1px solid rgba(255, 255, 255, 0.2);
  152. color: white;
  153. cursor: pointer;
  154. display: flex;
  155. align-items: center;
  156. justify-content: center;
  157. transition: all 0.2s;
  158. &:hover {
  159. background: rgba(255, 255, 255, 0.2);
  160. transform: scale(1.05);
  161. }
  162. svg {
  163. width: 20px;
  164. height: 20px;
  165. }
  166. }
  167. // ========== 导航标签页 ==========
  168. .panel-tabs {
  169. display: flex;
  170. gap: 0;
  171. padding: 0 24px;
  172. background: rgba(0, 0, 0, 0.05);
  173. }
  174. .tab-button {
  175. flex: 1;
  176. padding: 12px 16px;
  177. border: none;
  178. background: transparent;
  179. color: rgba(255, 255, 255, 0.7);
  180. font-size: 14px;
  181. font-weight: 500;
  182. cursor: pointer;
  183. display: flex;
  184. align-items: center;
  185. justify-content: center;
  186. gap: 6px;
  187. transition: all 0.3s;
  188. border-bottom: 2px solid transparent;
  189. position: relative;
  190. .tab-icon {
  191. width: 18px;
  192. height: 18px;
  193. }
  194. &:hover {
  195. color: white;
  196. background: rgba(255, 255, 255, 0.05);
  197. }
  198. &.active {
  199. color: white;
  200. border-bottom-color: white;
  201. background: rgba(255, 255, 255, 0.1);
  202. }
  203. }
  204. // ========== 面板内容 ==========
  205. .panel-content {
  206. flex: 1;
  207. overflow-y: auto;
  208. padding: 20px 24px;
  209. background: #f5f7fa;
  210. /* 自定义滚动条 */
  211. &::-webkit-scrollbar {
  212. width: 8px;
  213. }
  214. &::-webkit-scrollbar-track {
  215. background: #f1f1f1;
  216. }
  217. &::-webkit-scrollbar-thumb {
  218. background: #c1c1c1;
  219. border-radius: 4px;
  220. &:hover {
  221. background: #a1a1a1;
  222. }
  223. }
  224. }
  225. .tab-content {
  226. animation: fadeIn 0.3s ease;
  227. }
  228. // ========== 基本信息标签页(查看模式) ==========
  229. .view-mode {
  230. .detail-header {
  231. background: white;
  232. border-radius: 12px;
  233. padding: 24px;
  234. margin-bottom: 16px;
  235. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  236. display: flex;
  237. gap: 20px;
  238. }
  239. .detail-avatar-section {
  240. display: flex;
  241. flex-direction: column;
  242. align-items: center;
  243. gap: 12px;
  244. .detail-avatar {
  245. width: 80px;
  246. height: 80px;
  247. border-radius: 50%;
  248. object-fit: cover;
  249. border: 3px solid #f0f0f0;
  250. }
  251. .detail-badge-container {
  252. display: flex;
  253. flex-direction: column;
  254. gap: 6px;
  255. align-items: center;
  256. .detail-role-badge {
  257. padding: 4px 12px;
  258. border-radius: 12px;
  259. font-size: 12px;
  260. font-weight: 500;
  261. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  262. color: white;
  263. }
  264. .detail-status-badge {
  265. padding: 4px 10px;
  266. border-radius: 10px;
  267. font-size: 11px;
  268. font-weight: 500;
  269. &.active {
  270. background: #e8f5e9;
  271. color: #2e7d32;
  272. }
  273. &.disabled {
  274. background: #ffebee;
  275. color: #c62828;
  276. }
  277. }
  278. }
  279. }
  280. .detail-info-section {
  281. flex: 1;
  282. display: flex;
  283. flex-direction: column;
  284. gap: 8px;
  285. .detail-name-block {
  286. .detail-realname {
  287. margin: 0 0 4px 0;
  288. font-size: 22px;
  289. font-weight: 600;
  290. color: #333;
  291. }
  292. .detail-nickname {
  293. font-size: 13px;
  294. color: #666;
  295. }
  296. }
  297. .detail-position {
  298. display: flex;
  299. align-items: center;
  300. gap: 6px;
  301. font-size: 14px;
  302. color: #555;
  303. svg {
  304. color: #999;
  305. }
  306. }
  307. .detail-meta {
  308. display: flex;
  309. gap: 16px;
  310. margin-top: 8px;
  311. .detail-meta-item {
  312. display: flex;
  313. align-items: center;
  314. gap: 4px;
  315. font-size: 13px;
  316. color: #666;
  317. svg {
  318. color: #999;
  319. }
  320. }
  321. }
  322. }
  323. .detail-section {
  324. background: white;
  325. border-radius: 12px;
  326. padding: 20px;
  327. margin-bottom: 16px;
  328. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  329. .detail-section-title {
  330. display: flex;
  331. align-items: center;
  332. gap: 8px;
  333. font-size: 16px;
  334. font-weight: 600;
  335. color: #333;
  336. margin-bottom: 16px;
  337. padding-bottom: 12px;
  338. border-bottom: 2px solid #f0f0f0;
  339. svg {
  340. color: #667eea;
  341. }
  342. }
  343. .detail-grid {
  344. display: grid;
  345. grid-template-columns: repeat(2, 1fr);
  346. gap: 16px;
  347. .detail-item {
  348. label {
  349. display: block;
  350. font-size: 12px;
  351. color: #999;
  352. margin-bottom: 4px;
  353. }
  354. .detail-value {
  355. font-size: 14px;
  356. color: #333;
  357. font-weight: 500;
  358. .badge {
  359. padding: 4px 10px;
  360. border-radius: 12px;
  361. font-size: 12px;
  362. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  363. color: white;
  364. }
  365. }
  366. }
  367. }
  368. .skill-tags {
  369. display: flex;
  370. flex-wrap: wrap;
  371. gap: 8px;
  372. .skill-tag {
  373. padding: 6px 12px;
  374. border-radius: 16px;
  375. font-size: 13px;
  376. background: #f0f4ff;
  377. color: #667eea;
  378. font-weight: 500;
  379. }
  380. }
  381. .workload-grid {
  382. display: grid;
  383. grid-template-columns: repeat(3, 1fr);
  384. gap: 16px;
  385. .workload-item {
  386. text-align: center;
  387. padding: 16px;
  388. background: #f8f9fa;
  389. border-radius: 8px;
  390. label {
  391. display: block;
  392. font-size: 12px;
  393. color: #999;
  394. margin-bottom: 8px;
  395. }
  396. .workload-value {
  397. font-size: 24px;
  398. font-weight: 700;
  399. color: #667eea;
  400. }
  401. }
  402. }
  403. }
  404. .action-bar {
  405. display: flex;
  406. justify-content: center;
  407. margin-top: 20px;
  408. }
  409. }
  410. // ========== 基本信息标签页(编辑模式) ==========
  411. .edit-mode {
  412. .form-avatar-section {
  413. background: white;
  414. border-radius: 12px;
  415. padding: 20px;
  416. margin-bottom: 16px;
  417. display: flex;
  418. align-items: center;
  419. gap: 16px;
  420. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  421. .form-avatar {
  422. width: 64px;
  423. height: 64px;
  424. border-radius: 50%;
  425. object-fit: cover;
  426. border: 2px solid #f0f0f0;
  427. }
  428. .form-avatar-info {
  429. flex: 1;
  430. .form-avatar-name {
  431. font-size: 18px;
  432. font-weight: 600;
  433. color: #333;
  434. margin-bottom: 4px;
  435. }
  436. .form-avatar-id {
  437. font-size: 13px;
  438. color: #999;
  439. }
  440. }
  441. }
  442. .form-section {
  443. background: white;
  444. border-radius: 12px;
  445. padding: 20px;
  446. margin-bottom: 16px;
  447. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  448. .form-section-title {
  449. display: flex;
  450. align-items: center;
  451. gap: 8px;
  452. font-size: 16px;
  453. font-weight: 600;
  454. color: #333;
  455. margin-bottom: 16px;
  456. padding-bottom: 12px;
  457. border-bottom: 2px solid #f0f0f0;
  458. svg {
  459. color: #667eea;
  460. }
  461. }
  462. .form-group {
  463. margin-bottom: 16px;
  464. &:last-child {
  465. margin-bottom: 0;
  466. }
  467. .form-label {
  468. display: block;
  469. font-size: 13px;
  470. font-weight: 500;
  471. color: #555;
  472. margin-bottom: 8px;
  473. &.required::after {
  474. content: '*';
  475. color: #f44336;
  476. margin-left: 4px;
  477. }
  478. }
  479. .form-input,
  480. .form-select {
  481. width: 100%;
  482. padding: 10px 12px;
  483. border: 1px solid #ddd;
  484. border-radius: 8px;
  485. font-size: 14px;
  486. transition: all 0.2s;
  487. &:focus {
  488. outline: none;
  489. border-color: #667eea;
  490. box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
  491. }
  492. &:disabled {
  493. background: #f5f5f5;
  494. color: #999;
  495. cursor: not-allowed;
  496. }
  497. }
  498. .form-hint {
  499. font-size: 12px;
  500. color: #999;
  501. margin-top: 6px;
  502. }
  503. .status-toggle {
  504. display: flex;
  505. gap: 12px;
  506. .status-option {
  507. flex: 1;
  508. padding: 12px;
  509. border: 2px solid #e0e0e0;
  510. border-radius: 8px;
  511. display: flex;
  512. align-items: center;
  513. gap: 8px;
  514. cursor: pointer;
  515. transition: all 0.2s;
  516. input[type="radio"] {
  517. display: none;
  518. }
  519. .status-dot {
  520. width: 12px;
  521. height: 12px;
  522. border-radius: 50%;
  523. &.active {
  524. background: #4caf50;
  525. }
  526. &.disabled {
  527. background: #f44336;
  528. }
  529. }
  530. &.active {
  531. border-color: #667eea;
  532. background: rgba(102, 126, 234, 0.05);
  533. }
  534. &:hover {
  535. border-color: #999;
  536. }
  537. }
  538. }
  539. }
  540. }
  541. .form-notice {
  542. background: #fff3cd;
  543. border-left: 4px solid #ffc107;
  544. padding: 16px;
  545. border-radius: 8px;
  546. margin-bottom: 16px;
  547. display: flex;
  548. gap: 12px;
  549. svg {
  550. flex-shrink: 0;
  551. color: #ffc107;
  552. margin-top: 2px;
  553. }
  554. .form-notice-title {
  555. font-weight: 600;
  556. color: #856404;
  557. margin-bottom: 4px;
  558. }
  559. .form-notice-text {
  560. font-size: 13px;
  561. color: #856404;
  562. line-height: 1.5;
  563. }
  564. }
  565. .action-bar-horizontal {
  566. display: flex;
  567. gap: 12px;
  568. justify-content: flex-end;
  569. margin-top: 20px;
  570. }
  571. }
  572. // ========== 项目负载标签页 ==========
  573. .workload-tab {
  574. .section {
  575. background: white;
  576. border-radius: 12px;
  577. padding: 20px;
  578. margin-bottom: 16px;
  579. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  580. .section-header {
  581. display: flex;
  582. align-items: center;
  583. gap: 8px;
  584. margin-bottom: 16px;
  585. padding-bottom: 12px;
  586. border-bottom: 2px solid #f0f0f0;
  587. .section-icon {
  588. width: 20px;
  589. height: 20px;
  590. color: #667eea;
  591. }
  592. h4 {
  593. flex: 1;
  594. margin: 0;
  595. font-size: 16px;
  596. font-weight: 600;
  597. color: #333;
  598. }
  599. .btn-view-designer-calendar {
  600. padding: 6px 12px;
  601. border: 1px solid #ddd;
  602. border-radius: 6px;
  603. background: white;
  604. color: #667eea;
  605. font-size: 13px;
  606. cursor: pointer;
  607. transition: all 0.2s;
  608. &:hover {
  609. background: #f0f4ff;
  610. border-color: #667eea;
  611. }
  612. }
  613. }
  614. .workload-info {
  615. .workload-stat {
  616. font-size: 15px;
  617. color: #555;
  618. margin-bottom: 12px;
  619. .stat-label {
  620. font-weight: 500;
  621. }
  622. .stat-value {
  623. font-size: 18px;
  624. font-weight: 700;
  625. &.normal-workload {
  626. color: #4caf50;
  627. }
  628. &.high-workload {
  629. color: #ff9800;
  630. }
  631. }
  632. }
  633. .project-list {
  634. .project-label {
  635. font-size: 13px;
  636. color: #999;
  637. display: block;
  638. margin-bottom: 8px;
  639. }
  640. .project-tags {
  641. display: flex;
  642. flex-wrap: wrap;
  643. gap: 8px;
  644. .project-tag {
  645. padding: 8px 12px;
  646. border-radius: 16px;
  647. font-size: 13px;
  648. background: #f0f4ff;
  649. color: #667eea;
  650. font-weight: 500;
  651. display: flex;
  652. align-items: center;
  653. gap: 4px;
  654. &.clickable {
  655. cursor: pointer;
  656. transition: all 0.2s;
  657. &:hover {
  658. background: #667eea;
  659. color: white;
  660. transform: translateY(-2px);
  661. box-shadow: 0 4px 8px rgba(102, 126, 234, 0.3);
  662. }
  663. .icon-arrow {
  664. width: 14px;
  665. height: 14px;
  666. }
  667. }
  668. &.more {
  669. background: #e0e0e0;
  670. color: #666;
  671. }
  672. }
  673. }
  674. }
  675. }
  676. // 日历样式
  677. .employee-calendar {
  678. .calendar-month-header {
  679. display: flex;
  680. align-items: center;
  681. justify-content: space-between;
  682. margin-bottom: 16px;
  683. .btn-prev-month,
  684. .btn-next-month {
  685. width: 32px;
  686. height: 32px;
  687. border: 1px solid #ddd;
  688. border-radius: 6px;
  689. background: white;
  690. cursor: pointer;
  691. display: flex;
  692. align-items: center;
  693. justify-content: center;
  694. transition: all 0.2s;
  695. svg {
  696. width: 18px;
  697. height: 18px;
  698. color: #666;
  699. }
  700. &:hover {
  701. background: #f5f5f5;
  702. border-color: #999;
  703. }
  704. }
  705. .month-title {
  706. font-size: 16px;
  707. font-weight: 600;
  708. color: #333;
  709. }
  710. }
  711. .calendar-weekdays {
  712. display: grid;
  713. grid-template-columns: repeat(7, 1fr);
  714. gap: 4px;
  715. margin-bottom: 8px;
  716. .weekday {
  717. text-align: center;
  718. font-size: 12px;
  719. font-weight: 600;
  720. color: #999;
  721. padding: 8px 0;
  722. }
  723. }
  724. .calendar-grid {
  725. display: grid;
  726. grid-template-columns: repeat(7, 1fr);
  727. gap: 4px;
  728. .calendar-day {
  729. aspect-ratio: 1;
  730. border: 1px solid #e0e0e0;
  731. border-radius: 6px;
  732. padding: 6px;
  733. display: flex;
  734. flex-direction: column;
  735. align-items: center;
  736. justify-content: center;
  737. font-size: 13px;
  738. color: #333;
  739. transition: all 0.2s;
  740. &.other-month {
  741. color: #bbb;
  742. background: #fafafa;
  743. }
  744. &.today {
  745. background: #fff3e0;
  746. border-color: #ff9800;
  747. font-weight: 600;
  748. .day-number {
  749. color: #ff9800;
  750. }
  751. }
  752. &.has-projects {
  753. background: #f0f4ff;
  754. border-color: #667eea;
  755. }
  756. &.clickable {
  757. cursor: pointer;
  758. &:hover {
  759. transform: scale(1.05);
  760. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  761. }
  762. }
  763. .day-number {
  764. font-weight: 600;
  765. margin-bottom: 2px;
  766. }
  767. .day-badge {
  768. font-size: 10px;
  769. padding: 2px 6px;
  770. border-radius: 8px;
  771. background: #667eea;
  772. color: white;
  773. white-space: nowrap;
  774. &.high-load {
  775. background: #f44336;
  776. }
  777. }
  778. }
  779. }
  780. .calendar-legend {
  781. display: flex;
  782. gap: 16px;
  783. margin-top: 12px;
  784. padding-top: 12px;
  785. border-top: 1px solid #e0e0e0;
  786. .legend-item {
  787. display: flex;
  788. align-items: center;
  789. gap: 6px;
  790. font-size: 12px;
  791. color: #666;
  792. .legend-dot {
  793. width: 12px;
  794. height: 12px;
  795. border-radius: 50%;
  796. &.today-dot {
  797. background: #ff9800;
  798. }
  799. &.project-dot {
  800. background: #667eea;
  801. }
  802. &.high-dot {
  803. background: #f44336;
  804. }
  805. }
  806. }
  807. }
  808. }
  809. // 请假表格
  810. .leave-table {
  811. table {
  812. width: 100%;
  813. border-collapse: collapse;
  814. thead {
  815. background: #f8f9fa;
  816. th {
  817. padding: 12px;
  818. text-align: left;
  819. font-size: 13px;
  820. font-weight: 600;
  821. color: #555;
  822. border-bottom: 2px solid #e0e0e0;
  823. }
  824. }
  825. tbody {
  826. tr {
  827. &.leave-day {
  828. background: #ffebee;
  829. }
  830. &.work-day {
  831. background: white;
  832. }
  833. &:hover {
  834. background: #f5f5f5;
  835. }
  836. td {
  837. padding: 12px;
  838. font-size: 14px;
  839. color: #333;
  840. border-bottom: 1px solid #e0e0e0;
  841. .status-badge {
  842. padding: 4px 10px;
  843. border-radius: 12px;
  844. font-size: 12px;
  845. font-weight: 500;
  846. &.leave {
  847. background: #ffebee;
  848. color: #c62828;
  849. }
  850. &.work {
  851. background: #e8f5e9;
  852. color: #2e7d32;
  853. }
  854. }
  855. }
  856. }
  857. }
  858. }
  859. .no-leave {
  860. text-align: center;
  861. padding: 40px 20px;
  862. color: #999;
  863. .no-data-icon {
  864. width: 48px;
  865. height: 48px;
  866. margin: 0 auto 16px;
  867. opacity: 0.5;
  868. }
  869. p {
  870. margin: 0;
  871. font-size: 14px;
  872. }
  873. }
  874. }
  875. // 说明内容
  876. .explanation-content {
  877. .explanation-text {
  878. font-size: 14px;
  879. color: #555;
  880. line-height: 1.6;
  881. margin: 0;
  882. }
  883. }
  884. // 问卷样式
  885. .survey-content {
  886. .survey-status {
  887. display: flex;
  888. align-items: center;
  889. gap: 8px;
  890. padding: 12px;
  891. background: #e8f5e9;
  892. border-radius: 8px;
  893. margin-bottom: 16px;
  894. svg {
  895. flex-shrink: 0;
  896. }
  897. span {
  898. font-size: 14px;
  899. font-weight: 500;
  900. color: #2e7d32;
  901. }
  902. .survey-time {
  903. margin-left: auto;
  904. font-size: 12px;
  905. color: #666;
  906. font-weight: 400;
  907. }
  908. }
  909. .capability-summary {
  910. h5 {
  911. font-size: 15px;
  912. font-weight: 600;
  913. color: #333;
  914. margin: 0 0 12px 0;
  915. }
  916. .summary-grid {
  917. display: grid;
  918. grid-template-columns: 1fr;
  919. gap: 12px;
  920. margin-bottom: 16px;
  921. .summary-item {
  922. padding: 12px;
  923. background: #f8f9fa;
  924. border-radius: 8px;
  925. font-size: 13px;
  926. .label {
  927. font-weight: 600;
  928. color: #555;
  929. }
  930. .value {
  931. color: #333;
  932. margin-left: 8px;
  933. .limit-hint {
  934. font-size: 12px;
  935. color: #999;
  936. }
  937. }
  938. }
  939. }
  940. .btn-view-full {
  941. width: 100%;
  942. padding: 10px;
  943. border: 1px solid #667eea;
  944. border-radius: 8px;
  945. background: white;
  946. color: #667eea;
  947. font-size: 13px;
  948. display: flex;
  949. align-items: center;
  950. justify-content: center;
  951. gap: 6px;
  952. cursor: pointer;
  953. transition: all 0.2s;
  954. &:hover {
  955. background: #667eea;
  956. color: white;
  957. }
  958. }
  959. }
  960. .survey-answers {
  961. h5 {
  962. font-size: 15px;
  963. font-weight: 600;
  964. color: #333;
  965. margin: 0 0 12px 0;
  966. }
  967. .answer-item {
  968. margin-bottom: 16px;
  969. padding: 12px;
  970. background: #f8f9fa;
  971. border-radius: 8px;
  972. .question-text {
  973. font-size: 14px;
  974. font-weight: 600;
  975. color: #333;
  976. margin-bottom: 8px;
  977. }
  978. .answer-text {
  979. display: flex;
  980. flex-wrap: wrap;
  981. gap: 8px;
  982. .answer-tag {
  983. padding: 4px 10px;
  984. border-radius: 12px;
  985. font-size: 13px;
  986. &.empty {
  987. background: #e0e0e0;
  988. color: #999;
  989. }
  990. &.single {
  991. background: #e3f2fd;
  992. color: #1976d2;
  993. }
  994. &.multiple {
  995. background: #f3e5f5;
  996. color: #7b1fa2;
  997. }
  998. }
  999. .answer-scale {
  1000. width: 100%;
  1001. .scale-bar {
  1002. height: 24px;
  1003. background: #e0e0e0;
  1004. border-radius: 12px;
  1005. overflow: hidden;
  1006. .scale-fill {
  1007. height: 100%;
  1008. background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
  1009. display: flex;
  1010. align-items: center;
  1011. justify-content: center;
  1012. color: white;
  1013. font-size: 12px;
  1014. font-weight: 600;
  1015. transition: width 0.3s;
  1016. }
  1017. }
  1018. }
  1019. }
  1020. }
  1021. .btn-collapse {
  1022. width: 100%;
  1023. padding: 10px;
  1024. border: 1px solid #ddd;
  1025. border-radius: 8px;
  1026. background: white;
  1027. color: #666;
  1028. font-size: 13px;
  1029. display: flex;
  1030. align-items: center;
  1031. justify-content: center;
  1032. gap: 6px;
  1033. cursor: pointer;
  1034. margin-top: 8px;
  1035. transition: all 0.2s;
  1036. &:hover {
  1037. background: #f5f5f5;
  1038. border-color: #999;
  1039. }
  1040. }
  1041. }
  1042. }
  1043. .survey-empty {
  1044. text-align: center;
  1045. padding: 40px 20px;
  1046. color: #999;
  1047. .no-data-icon {
  1048. width: 48px;
  1049. height: 48px;
  1050. margin: 0 auto 16px;
  1051. opacity: 0.5;
  1052. }
  1053. p {
  1054. margin: 0;
  1055. font-size: 14px;
  1056. }
  1057. }
  1058. .btn-refresh-survey {
  1059. padding: 6px 12px;
  1060. border: 1px solid #ddd;
  1061. border-radius: 6px;
  1062. background: white;
  1063. color: #667eea;
  1064. cursor: pointer;
  1065. transition: all 0.2s;
  1066. &:hover:not(:disabled) {
  1067. background: #f0f4ff;
  1068. border-color: #667eea;
  1069. }
  1070. &:disabled {
  1071. opacity: 0.6;
  1072. cursor: not-allowed;
  1073. }
  1074. svg.rotating {
  1075. animation: rotate 1s linear infinite;
  1076. }
  1077. }
  1078. }
  1079. }
  1080. // ========== 通用按钮样式 ==========
  1081. .btn {
  1082. padding: 10px 20px;
  1083. border: none;
  1084. border-radius: 8px;
  1085. font-size: 14px;
  1086. font-weight: 500;
  1087. cursor: pointer;
  1088. transition: all 0.2s;
  1089. display: inline-flex;
  1090. align-items: center;
  1091. gap: 6px;
  1092. svg {
  1093. width: 16px;
  1094. height: 16px;
  1095. }
  1096. &.btn-primary {
  1097. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  1098. color: white;
  1099. &:hover {
  1100. transform: translateY(-2px);
  1101. box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
  1102. }
  1103. }
  1104. &.btn-default {
  1105. background: white;
  1106. border: 1px solid #ddd;
  1107. color: #666;
  1108. &:hover {
  1109. background: #f5f5f5;
  1110. border-color: #999;
  1111. }
  1112. }
  1113. }
  1114. // ========== 模态弹窗样式 ==========
  1115. .calendar-project-modal-overlay {
  1116. position: fixed;
  1117. top: 0;
  1118. left: 0;
  1119. right: 0;
  1120. bottom: 0;
  1121. background: rgba(0, 0, 0, 0.5);
  1122. z-index: 10000;
  1123. display: flex;
  1124. align-items: center;
  1125. justify-content: center;
  1126. animation: fadeIn 0.2s ease;
  1127. }
  1128. .calendar-project-modal {
  1129. background: white;
  1130. border-radius: 16px;
  1131. width: 90%;
  1132. max-width: 500px;
  1133. max-height: 80vh;
  1134. display: flex;
  1135. flex-direction: column;
  1136. box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
  1137. animation: scaleIn 0.3s ease;
  1138. &.large {
  1139. max-width: 800px;
  1140. }
  1141. .modal-header {
  1142. padding: 20px 24px;
  1143. border-bottom: 1px solid #e0e0e0;
  1144. display: flex;
  1145. align-items: center;
  1146. justify-content: space-between;
  1147. h3 {
  1148. margin: 0;
  1149. font-size: 18px;
  1150. font-weight: 600;
  1151. color: #333;
  1152. display: flex;
  1153. align-items: center;
  1154. gap: 8px;
  1155. .header-icon {
  1156. width: 20px;
  1157. height: 20px;
  1158. color: #667eea;
  1159. }
  1160. }
  1161. .btn-close {
  1162. width: 32px;
  1163. height: 32px;
  1164. border-radius: 50%;
  1165. border: 1px solid #ddd;
  1166. background: white;
  1167. cursor: pointer;
  1168. display: flex;
  1169. align-items: center;
  1170. justify-content: center;
  1171. transition: all 0.2s;
  1172. &:hover {
  1173. background: #f5f5f5;
  1174. border-color: #999;
  1175. }
  1176. svg {
  1177. width: 18px;
  1178. height: 18px;
  1179. color: #666;
  1180. }
  1181. }
  1182. }
  1183. .modal-body {
  1184. padding: 20px 24px;
  1185. overflow-y: auto;
  1186. flex: 1;
  1187. .project-count-info {
  1188. font-size: 14px;
  1189. color: #666;
  1190. margin-bottom: 16px;
  1191. strong {
  1192. color: #667eea;
  1193. font-size: 16px;
  1194. }
  1195. }
  1196. .project-list {
  1197. display: flex;
  1198. flex-direction: column;
  1199. gap: 12px;
  1200. .project-item {
  1201. padding: 16px;
  1202. border: 1px solid #e0e0e0;
  1203. border-radius: 12px;
  1204. display: flex;
  1205. align-items: center;
  1206. justify-content: space-between;
  1207. cursor: pointer;
  1208. transition: all 0.2s;
  1209. &:hover {
  1210. background: #f8f9fa;
  1211. border-color: #667eea;
  1212. transform: translateX(4px);
  1213. }
  1214. .project-info {
  1215. display: flex;
  1216. gap: 12px;
  1217. flex: 1;
  1218. .project-icon {
  1219. width: 24px;
  1220. height: 24px;
  1221. color: #667eea;
  1222. flex-shrink: 0;
  1223. }
  1224. .project-details {
  1225. flex: 1;
  1226. .project-name {
  1227. margin: 0 0 4px 0;
  1228. font-size: 15px;
  1229. font-weight: 600;
  1230. color: #333;
  1231. }
  1232. .project-deadline {
  1233. margin: 0;
  1234. font-size: 12px;
  1235. color: #999;
  1236. }
  1237. }
  1238. }
  1239. .arrow-icon {
  1240. width: 20px;
  1241. height: 20px;
  1242. color: #999;
  1243. flex-shrink: 0;
  1244. }
  1245. }
  1246. }
  1247. }
  1248. }
  1249. // ========== 动画 ==========
  1250. @keyframes fadeIn {
  1251. from {
  1252. opacity: 0;
  1253. }
  1254. to {
  1255. opacity: 1;
  1256. }
  1257. }
  1258. @keyframes slideInRight {
  1259. from {
  1260. transform: translateX(100%);
  1261. }
  1262. to {
  1263. transform: translateX(0);
  1264. }
  1265. }
  1266. @keyframes scaleIn {
  1267. from {
  1268. transform: scale(0.9);
  1269. opacity: 0;
  1270. }
  1271. to {
  1272. transform: scale(1);
  1273. opacity: 1;
  1274. }
  1275. }
  1276. @keyframes rotate {
  1277. from {
  1278. transform: rotate(0deg);
  1279. }
  1280. to {
  1281. transform: rotate(360deg);
  1282. }
  1283. }
  1284. // ========== 响应式 ==========
  1285. @media (max-width: 768px) {
  1286. .employee-info-panel {
  1287. width: 100%;
  1288. max-width: 100vw;
  1289. }
  1290. .detail-header {
  1291. flex-direction: column;
  1292. align-items: center;
  1293. text-align: center;
  1294. }
  1295. .detail-grid {
  1296. grid-template-columns: 1fr !important;
  1297. }
  1298. .workload-grid {
  1299. grid-template-columns: 1fr !important;
  1300. }
  1301. .calendar-project-modal {
  1302. width: 95%;
  1303. &.large {
  1304. width: 95%;
  1305. }
  1306. }
  1307. }