requirements-confirm-card.scss 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425
  1. @use '../../styles/_ios-theme.scss' as *;
  2. @use 'sass:color';
  3. @use './requirements-confirm-card-alternative.scss' as *;
  4. :host {
  5. display: block;
  6. height: 100%;
  7. position: relative; // 确保子元素定位基准
  8. }
  9. // 新增:文本输入区域独立样式
  10. .text-upload-section {
  11. margin-bottom: 1.5rem;
  12. .upload-item {
  13. background: white;
  14. border: 1px solid #e0e0e0;
  15. border-radius: 8px;
  16. padding: 1rem;
  17. h5 {
  18. margin: 0 0 0.75rem 0;
  19. font-size: 0.9rem;
  20. color: #333;
  21. font-weight: 600;
  22. }
  23. textarea {
  24. width: 100%;
  25. padding: 0.75rem;
  26. border: 1px solid #ddd;
  27. border-radius: 4px;
  28. font-size: 0.85rem;
  29. resize: vertical;
  30. margin-bottom: 0.75rem;
  31. &:focus {
  32. outline: none;
  33. border-color: #007bff;
  34. }
  35. }
  36. .btn-primary {
  37. background: #007bff;
  38. border: none;
  39. border-radius: 4px;
  40. padding: 0.5rem 1rem;
  41. color: white;
  42. font-size: 0.85rem;
  43. cursor: pointer;
  44. &:disabled {
  45. opacity: 0.6;
  46. cursor: not-allowed;
  47. }
  48. }
  49. }
  50. }
  51. // 新增:参考图片和CAD图纸并排布局 - 优化弹窗出现时的布局稳定性
  52. .file-upload-grid {
  53. display: grid;
  54. grid-template-columns: 1fr 1fr;
  55. gap: 1rem;
  56. position: relative;
  57. z-index: 1; // 确保在正常文档流中
  58. margin-bottom: $ios-spacing-lg;
  59. // 移动端响应式
  60. @media (max-width: 768px) {
  61. grid-template-columns: 1fr;
  62. gap: $ios-spacing-sm;
  63. }
  64. // 平板端响应式
  65. @media (min-width: 769px) and (max-width: 1024px) {
  66. gap: $ios-spacing-md;
  67. }
  68. // 当弹窗出现时保持布局稳定
  69. .upload-item {
  70. position: relative;
  71. background: white;
  72. border: 1px solid #e0e0e0;
  73. border-radius: 8px;
  74. padding: 1rem;
  75. transition: transform 0.2s ease, box-shadow 0.2s ease;
  76. &:hover {
  77. transform: translateY(-2px);
  78. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  79. }
  80. // 确保在弹窗出现时不会被遮挡或错位,优化层级管理
  81. &.image-item, &.cad-item {
  82. z-index: 2;
  83. // 当有弹窗显示时,降低交互优先级
  84. &.modal-active {
  85. pointer-events: none;
  86. opacity: 0.8;
  87. }
  88. }
  89. h5 {
  90. margin: 0 0 $ios-spacing-sm 0;
  91. font-size: $ios-font-size-xs;
  92. font-weight: $ios-font-weight-semibold;
  93. color: $ios-text-primary;
  94. }
  95. .file-upload-zone {
  96. border: 2px dashed $ios-border;
  97. border-radius: 8px;
  98. padding: $ios-spacing-lg;
  99. text-align: center;
  100. cursor: pointer;
  101. transition: all 0.2s ease;
  102. &:hover {
  103. border-color: $ios-primary;
  104. background: rgba(0, 122, 255, 0.02);
  105. }
  106. svg {
  107. color: $ios-text-secondary;
  108. margin-bottom: $ios-spacing-sm;
  109. }
  110. p {
  111. margin: 0 0 $ios-spacing-xs 0;
  112. font-size: $ios-font-size-xs;
  113. color: $ios-text-primary;
  114. font-weight: $ios-font-weight-medium;
  115. }
  116. .hint {
  117. font-size: $ios-font-size-xs;
  118. color: $ios-text-secondary;
  119. }
  120. }
  121. }
  122. }
  123. .requirements-confirm-card {
  124. .card-header {
  125. display: flex;
  126. justify-content: space-between;
  127. align-items: center;
  128. margin-bottom: $ios-spacing-md;
  129. h4 {
  130. margin: 0;
  131. font-size: $ios-font-size-sm;
  132. font-weight: $ios-font-weight-semibold;
  133. color: $ios-text-primary;
  134. }
  135. .header-actions {
  136. display: flex;
  137. align-items: center;
  138. gap: $ios-spacing-md;
  139. .btn-ghost {
  140. white-space: nowrap;
  141. }
  142. }
  143. .progress-indicator {
  144. display: flex;
  145. align-items: center;
  146. gap: $ios-spacing-xs;
  147. .progress-bar {
  148. width: 80px;
  149. height: 4px;
  150. background: $ios-border;
  151. border-radius: 2px;
  152. overflow: hidden;
  153. .progress-fill {
  154. height: 100%;
  155. background: linear-gradient(90deg, #007AFF 0%, #34C759 100%);
  156. transition: width 0.3s ease;
  157. }
  158. }
  159. .progress-text {
  160. font-size: $ios-font-size-xs;
  161. color: $ios-text-secondary;
  162. font-weight: $ios-font-weight-medium;
  163. }
  164. }
  165. }
  166. // 滑动条输入框样式
  167. .slider-container {
  168. display: flex;
  169. align-items: center;
  170. gap: $ios-spacing-xs;
  171. input[type="range"] {
  172. flex: 1;
  173. }
  174. .slider-input {
  175. width: 60px;
  176. padding: 4px 8px;
  177. border: 1px solid $ios-border;
  178. border-radius: 4px;
  179. font-size: $ios-font-size-xs;
  180. text-align: center;
  181. background: white;
  182. &:focus {
  183. outline: none;
  184. border-color: $ios-primary;
  185. box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
  186. }
  187. }
  188. .unit-label {
  189. font-size: $ios-font-size-xs;
  190. color: $ios-text-secondary;
  191. min-width: 20px;
  192. }
  193. }
  194. // 进度条样式
  195. .progress-container {
  196. margin-bottom: $ios-spacing-md;
  197. &.progress-updated {
  198. .progress-bar-fill {
  199. animation: progressPulse 0.5s ease;
  200. }
  201. }
  202. .progress-visual {
  203. display: flex;
  204. align-items: center;
  205. gap: $ios-spacing-md;
  206. .linear-progress {
  207. flex: 1;
  208. display: flex;
  209. align-items: center;
  210. gap: $ios-spacing-sm;
  211. .progress-track {
  212. flex: 1;
  213. height: 8px;
  214. background: $ios-background-secondary;
  215. border-radius: 4px;
  216. overflow: hidden;
  217. .progress-bar-fill {
  218. height: 100%;
  219. background: linear-gradient(90deg, #007AFF 0%, #34C759 100%);
  220. border-radius: 4px;
  221. transition: width 0.3s ease;
  222. }
  223. }
  224. .progress-text {
  225. font-size: $ios-font-size-sm;
  226. font-weight: $ios-font-weight-semibold;
  227. color: $ios-text-primary;
  228. min-width: 40px;
  229. }
  230. }
  231. .circular-progress {
  232. position: relative;
  233. width: 120px;
  234. height: 120px;
  235. .progress-circle {
  236. width: 100%;
  237. height: 100%;
  238. transform: rotate(-90deg);
  239. circle {
  240. transition: stroke-dashoffset 0.3s ease;
  241. }
  242. }
  243. .progress-text {
  244. position: absolute;
  245. top: 50%;
  246. left: 50%;
  247. transform: translate(-50%, -50%);
  248. text-align: center;
  249. .progress-percentage {
  250. font-size: $ios-font-size-lg;
  251. font-weight: $ios-font-weight-bold;
  252. color: $ios-text-primary;
  253. }
  254. .progress-label {
  255. font-size: $ios-font-size-xs;
  256. color: $ios-text-secondary;
  257. }
  258. }
  259. }
  260. }
  261. }
  262. // 进度统计样式
  263. .progress-stats {
  264. display: grid;
  265. grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  266. gap: $ios-spacing-sm;
  267. margin-bottom: $ios-spacing-md;
  268. .stat-item {
  269. text-align: center;
  270. padding: $ios-spacing-sm;
  271. background: $ios-background-secondary;
  272. border-radius: 8px;
  273. .stat-number {
  274. font-size: $ios-font-size-lg;
  275. font-weight: $ios-font-weight-bold;
  276. color: $ios-text-primary;
  277. }
  278. .stat-label {
  279. font-size: $ios-font-size-xs;
  280. color: $ios-text-secondary;
  281. margin-top: 2px;
  282. }
  283. }
  284. }
  285. // 标签页导航
  286. .tab-navigation {
  287. display: flex;
  288. background: $ios-background-secondary;
  289. border-radius: 8px;
  290. padding: 2px;
  291. margin-bottom: $ios-spacing-md;
  292. .tab-button {
  293. flex: 1;
  294. display: flex;
  295. align-items: center;
  296. justify-content: center;
  297. gap: $ios-spacing-xs;
  298. padding: $ios-spacing-sm $ios-spacing-xs;
  299. border: none;
  300. background: transparent;
  301. color: $ios-text-secondary;
  302. font-size: $ios-font-size-xs;
  303. font-weight: $ios-font-weight-medium;
  304. border-radius: 6px;
  305. transition: all 0.2s ease;
  306. cursor: pointer;
  307. svg {
  308. width: 14px;
  309. height: 14px;
  310. }
  311. &:hover {
  312. color: $ios-text-primary;
  313. background: rgba(0, 122, 255, 0.1);
  314. }
  315. &.active {
  316. background: white;
  317. color: $ios-primary;
  318. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  319. }
  320. }
  321. }
  322. // 标签页内容
  323. .tab-content {
  324. min-height: 300px;
  325. }
  326. // 素材解析部分
  327. .materials-section {
  328. // 文本输入区域 - 独立一行
  329. .text-upload-section {
  330. margin-bottom: $ios-spacing-lg;
  331. .upload-item.text-item {
  332. h5 {
  333. margin: 0 0 $ios-spacing-sm 0;
  334. font-size: $ios-font-size-xs;
  335. font-weight: $ios-font-weight-semibold;
  336. color: $ios-text-primary;
  337. }
  338. textarea {
  339. width: 100%;
  340. padding: $ios-spacing-sm;
  341. border: 1px solid $ios-border;
  342. border-radius: 6px;
  343. font-size: $ios-font-size-xs;
  344. resize: vertical;
  345. margin-bottom: $ios-spacing-sm;
  346. &:focus {
  347. outline: none;
  348. border-color: $ios-primary;
  349. box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1);
  350. }
  351. }
  352. }
  353. }
  354. // 参考图片和CAD图纸并排布局
  355. .file-upload-grid {
  356. display: grid;
  357. grid-template-columns: 1fr 1fr;
  358. gap: 2%;
  359. margin-bottom: $ios-spacing-lg;
  360. // 移动端响应式 - 改为垂直布局
  361. @media (max-width: 768px) {
  362. grid-template-columns: 1fr;
  363. gap: $ios-spacing-md;
  364. }
  365. .upload-item {
  366. &.image-item, &.cad-item {
  367. h5 {
  368. margin: 0 0 $ios-spacing-sm 0;
  369. font-size: $ios-font-size-xs;
  370. font-weight: $ios-font-weight-semibold;
  371. color: $ios-text-primary;
  372. }
  373. .file-upload-zone {
  374. border: 2px dashed $ios-border;
  375. border-radius: 8px;
  376. padding: $ios-spacing-lg;
  377. text-align: center;
  378. cursor: pointer;
  379. transition: all 0.2s ease;
  380. min-height: 120px;
  381. display: flex;
  382. flex-direction: column;
  383. justify-content: center;
  384. align-items: center;
  385. &:hover {
  386. border-color: $ios-primary;
  387. background: rgba(0, 122, 255, 0.02);
  388. }
  389. svg {
  390. color: $ios-text-secondary;
  391. margin-bottom: $ios-spacing-sm;
  392. }
  393. p {
  394. margin: 0 0 $ios-spacing-xs 0;
  395. font-size: $ios-font-size-xs;
  396. color: $ios-text-primary;
  397. font-weight: $ios-font-weight-medium;
  398. }
  399. .hint {
  400. font-size: $ios-font-size-xs;
  401. color: $ios-text-secondary;
  402. }
  403. }
  404. }
  405. }
  406. }
  407. // 保留原有的upload-grid样式作为备选方案
  408. .upload-grid {
  409. display: grid;
  410. grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  411. gap: $ios-spacing-md;
  412. margin-bottom: $ios-spacing-lg;
  413. .upload-item {
  414. h5 {
  415. margin: 0 0 $ios-spacing-sm 0;
  416. font-size: $ios-font-size-xs;
  417. font-weight: $ios-font-weight-semibold;
  418. color: $ios-text-primary;
  419. }
  420. textarea {
  421. width: 100%;
  422. padding: $ios-spacing-sm;
  423. border: 1px solid $ios-border;
  424. border-radius: 6px;
  425. font-size: $ios-font-size-xs;
  426. resize: vertical;
  427. margin-bottom: $ios-spacing-sm;
  428. &:focus {
  429. outline: none;
  430. border-color: $ios-primary;
  431. box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1);
  432. }
  433. }
  434. .file-upload-zone {
  435. border: 2px dashed $ios-border;
  436. border-radius: 8px;
  437. padding: $ios-spacing-lg;
  438. text-align: center;
  439. cursor: pointer;
  440. transition: all 0.2s ease;
  441. &:hover {
  442. border-color: $ios-primary;
  443. background: rgba(0, 122, 255, 0.02);
  444. }
  445. svg {
  446. color: $ios-text-secondary;
  447. margin-bottom: $ios-spacing-sm;
  448. }
  449. p {
  450. margin: 0 0 $ios-spacing-xs 0;
  451. font-size: $ios-font-size-xs;
  452. color: $ios-text-primary;
  453. font-weight: $ios-font-weight-medium;
  454. }
  455. .hint {
  456. font-size: $ios-font-size-xs;
  457. color: $ios-text-secondary;
  458. }
  459. }
  460. }
  461. }
  462. .materials-list {
  463. position: relative;
  464. z-index: 3; // 确保素材列表在弹窗层级之下但高于其他内容
  465. h5 {
  466. margin: 0 0 $ios-spacing-sm 0;
  467. font-size: $ios-font-size-xs;
  468. font-weight: $ios-font-weight-semibold;
  469. color: $ios-text-primary;
  470. }
  471. .material-cards {
  472. display: grid;
  473. grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  474. gap: $ios-spacing-sm;
  475. // 响应式布局优化
  476. @media (max-width: 768px) {
  477. grid-template-columns: 1fr;
  478. gap: $ios-spacing-xs;
  479. }
  480. @media (min-width: 769px) and (max-width: 1024px) {
  481. grid-template-columns: repeat(2, 1fr);
  482. }
  483. .material-card {
  484. border: 1px solid $ios-border;
  485. border-radius: 6px;
  486. padding: $ios-spacing-sm;
  487. background: white;
  488. position: relative;
  489. transition: transform 0.2s ease, box-shadow 0.2s ease;
  490. // 防止弹窗出现时布局错乱,优化对齐
  491. &:hover {
  492. transform: translateY(-1px);
  493. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  494. z-index: 4; // 悬停时提升层级
  495. }
  496. &.material-text {
  497. border-left: 3px solid #34C759;
  498. }
  499. &.material-image {
  500. border-left: 3px solid #FF9500;
  501. }
  502. &.material-cad {
  503. border-left: 3px solid #007AFF;
  504. }
  505. .material-header {
  506. display: flex;
  507. justify-content: space-between;
  508. align-items: center;
  509. margin-bottom: $ios-spacing-xs;
  510. .material-type {
  511. font-size: $ios-font-size-xs;
  512. font-weight: $ios-font-weight-medium;
  513. color: $ios-text-secondary;
  514. text-transform: uppercase;
  515. }
  516. }
  517. .material-name {
  518. font-size: $ios-font-size-xs;
  519. color: $ios-text-primary;
  520. margin-bottom: $ios-spacing-xs;
  521. font-weight: $ios-font-weight-medium;
  522. }
  523. .parsed-info {
  524. .parsed-tags {
  525. .tag-group {
  526. margin-bottom: $ios-spacing-xs;
  527. .tag-label {
  528. font-size: $ios-font-size-xs;
  529. color: $ios-text-secondary;
  530. margin-right: $ios-spacing-xs;
  531. }
  532. .tag {
  533. display: inline-block;
  534. background: $ios-background-secondary;
  535. color: $ios-text-primary;
  536. padding: 2px 6px;
  537. border-radius: 4px;
  538. font-size: $ios-font-size-xs;
  539. margin-right: 4px;
  540. }
  541. }
  542. }
  543. .analysis-results {
  544. .color-info {
  545. margin-bottom: $ios-spacing-sm;
  546. .color-temp {
  547. font-size: $ios-font-size-xs;
  548. color: $ios-text-secondary;
  549. }
  550. }
  551. .enhanced-analysis {
  552. .analysis-section {
  553. margin-bottom: $ios-spacing-md;
  554. padding: $ios-spacing-sm;
  555. background: rgba(0, 122, 255, 0.02);
  556. border-radius: 6px;
  557. border: 1px solid rgba(0, 122, 255, 0.1);
  558. h6 {
  559. margin: 0 0 $ios-spacing-xs 0;
  560. font-size: $ios-font-size-xs;
  561. font-weight: $ios-font-weight-semibold;
  562. color: $ios-primary;
  563. }
  564. .color-wheel-info {
  565. display: flex;
  566. align-items: center;
  567. gap: $ios-spacing-xs;
  568. margin-bottom: $ios-spacing-xs;
  569. .color-wheel-icon {
  570. display: flex;
  571. align-items: center;
  572. justify-content: center;
  573. width: 24px;
  574. height: 24px;
  575. svg {
  576. color: $ios-primary;
  577. }
  578. }
  579. span {
  580. font-size: $ios-font-size-xs;
  581. color: $ios-text-secondary;
  582. margin-right: $ios-spacing-sm;
  583. }
  584. }
  585. .psychology-info {
  586. display: flex;
  587. gap: $ios-spacing-xs;
  588. flex-wrap: wrap;
  589. .mood-tag, .atmosphere-tag {
  590. display: inline-block;
  591. background: rgba(52, 199, 89, 0.1);
  592. color: #34C759;
  593. padding: 2px 6px;
  594. border-radius: 4px;
  595. font-size: $ios-font-size-xs;
  596. font-weight: $ios-font-weight-medium;
  597. }
  598. .atmosphere-tag {
  599. background: rgba(255, 149, 0, 0.1);
  600. color: #FF9500;
  601. }
  602. }
  603. .form-metrics {
  604. .metric-item {
  605. display: flex;
  606. align-items: center;
  607. gap: $ios-spacing-sm;
  608. margin-bottom: $ios-spacing-xs;
  609. .metric-label {
  610. font-size: $ios-font-size-xs;
  611. color: $ios-text-secondary;
  612. min-width: 60px;
  613. }
  614. .metric-bar {
  615. flex: 1;
  616. height: 4px;
  617. background: $ios-border;
  618. border-radius: 2px;
  619. overflow: hidden;
  620. .metric-fill {
  621. height: 100%;
  622. background: linear-gradient(90deg, #34C759, #007AFF);
  623. transition: width 0.3s ease;
  624. }
  625. }
  626. }
  627. }
  628. .material-info {
  629. display: flex;
  630. gap: $ios-spacing-xs;
  631. flex-wrap: wrap;
  632. .material-tag, .surface-tag {
  633. display: inline-block;
  634. background: rgba(175, 82, 222, 0.1);
  635. color: #AF52DE;
  636. padding: 2px 6px;
  637. border-radius: 4px;
  638. font-size: $ios-font-size-xs;
  639. font-weight: $ios-font-weight-medium;
  640. }
  641. .surface-tag {
  642. background: rgba(255, 45, 85, 0.1);
  643. color: #FF2D55;
  644. }
  645. }
  646. .pattern-info {
  647. display: flex;
  648. gap: $ios-spacing-xs;
  649. flex-wrap: wrap;
  650. .pattern-tag {
  651. display: inline-block;
  652. background: rgba(88, 86, 214, 0.1);
  653. color: #5856D6;
  654. padding: 2px 6px;
  655. border-radius: 4px;
  656. font-size: $ios-font-size-xs;
  657. font-weight: $ios-font-weight-medium;
  658. }
  659. }
  660. .lighting-info {
  661. display: flex;
  662. gap: $ios-spacing-xs;
  663. flex-wrap: wrap;
  664. .mood-tag {
  665. display: inline-block;
  666. background: rgba(255, 204, 0, 0.1);
  667. color: #FFCC00;
  668. padding: 2px 6px;
  669. border-radius: 4px;
  670. font-size: $ios-font-size-xs;
  671. font-weight: $ios-font-weight-medium;
  672. }
  673. .brightness-tag {
  674. display: inline-block;
  675. background: rgba(255, 149, 0, 0.1);
  676. color: #FF9500;
  677. padding: 2px 6px;
  678. border-radius: 4px;
  679. font-size: $ios-font-size-xs;
  680. font-weight: $ios-font-weight-medium;
  681. }
  682. }
  683. }
  684. }
  685. }
  686. }
  687. }
  688. }
  689. }
  690. }
  691. // 需求映射部分
  692. .mapping-section {
  693. .consistency-warning {
  694. display: flex;
  695. align-items: center;
  696. gap: $ios-spacing-xs;
  697. padding: $ios-spacing-sm;
  698. background: rgba(255, 59, 48, 0.1);
  699. border: 1px solid rgba(255, 59, 48, 0.2);
  700. border-radius: 6px;
  701. color: #FF3B30;
  702. font-size: $ios-font-size-xs;
  703. margin-bottom: $ios-spacing-md;
  704. svg {
  705. width: 16px;
  706. height: 16px;
  707. flex-shrink: 0;
  708. }
  709. }
  710. .indicator-grid {
  711. display: grid;
  712. grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  713. gap: $ios-spacing-lg;
  714. .indicator-group {
  715. h5 {
  716. margin: 0 0 $ios-spacing-sm 0;
  717. font-size: $ios-font-size-xs;
  718. font-weight: $ios-font-weight-semibold;
  719. color: $ios-text-primary;
  720. padding-bottom: $ios-spacing-xs;
  721. border-bottom: 1px solid $ios-border;
  722. }
  723. .indicator-item {
  724. margin-bottom: $ios-spacing-md;
  725. label {
  726. display: block;
  727. font-size: $ios-font-size-xs;
  728. color: $ios-text-secondary;
  729. margin-bottom: $ios-spacing-xs;
  730. font-weight: $ios-font-weight-medium;
  731. }
  732. .slider-container {
  733. display: flex;
  734. align-items: center;
  735. gap: $ios-spacing-sm;
  736. input[type="range"] {
  737. flex: 1;
  738. height: 4px;
  739. background: $ios-border;
  740. border-radius: 2px;
  741. outline: none;
  742. -webkit-appearance: none;
  743. appearance: none;
  744. &::-webkit-slider-thumb {
  745. -webkit-appearance: none;
  746. appearance: none;
  747. width: 16px;
  748. height: 16px;
  749. background: #007AFF;
  750. border-radius: 50%;
  751. cursor: pointer;
  752. }
  753. &::-moz-range-thumb {
  754. width: 16px;
  755. height: 16px;
  756. background: #007AFF;
  757. border-radius: 50%;
  758. cursor: pointer;
  759. border: none;
  760. }
  761. }
  762. .slider-value {
  763. font-size: $ios-font-size-xs;
  764. color: $ios-text-primary;
  765. font-weight: $ios-font-weight-medium;
  766. min-width: 40px;
  767. text-align: right;
  768. }
  769. }
  770. // RGB控件样式
  771. .rgb-controls {
  772. display: flex;
  773. flex-direction: column;
  774. gap: $ios-spacing-xs;
  775. .rgb-slider {
  776. display: flex;
  777. align-items: center;
  778. gap: $ios-spacing-xs;
  779. span:first-child {
  780. font-size: $ios-font-size-xs;
  781. font-weight: $ios-font-weight-semibold;
  782. color: $ios-text-secondary;
  783. width: 12px;
  784. }
  785. input[type="range"] {
  786. flex: 1;
  787. height: 4px;
  788. background: $ios-border;
  789. border-radius: 2px;
  790. outline: none;
  791. -webkit-appearance: none;
  792. appearance: none;
  793. &::-webkit-slider-thumb {
  794. -webkit-appearance: none;
  795. appearance: none;
  796. width: 14px;
  797. height: 14px;
  798. background: #007AFF;
  799. border-radius: 50%;
  800. cursor: pointer;
  801. }
  802. }
  803. span:last-child {
  804. font-size: $ios-font-size-xs;
  805. color: $ios-text-primary;
  806. font-weight: $ios-font-weight-medium;
  807. min-width: 30px;
  808. text-align: right;
  809. }
  810. }
  811. .color-preview {
  812. width: 100%;
  813. height: 30px;
  814. border-radius: 6px;
  815. border: 1px solid $ios-border;
  816. margin-top: $ios-spacing-xs;
  817. transition: background-color 0.1s ease; // 减少过渡时间,提高响应速度
  818. // 移除默认背景色,完全依赖Angular绑定
  819. will-change: background-color; // 优化GPU渲染
  820. }
  821. }
  822. }
  823. }
  824. }
  825. // 预设氛围样式
  826. .atmosphere-presets {
  827. display: grid;
  828. grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  829. gap: $ios-spacing-sm;
  830. .preset-card {
  831. display: flex;
  832. align-items: center;
  833. gap: $ios-spacing-sm;
  834. padding: $ios-spacing-sm;
  835. border: 1px solid $ios-border;
  836. border-radius: 8px;
  837. background: white;
  838. cursor: pointer;
  839. transition: all 0.2s ease;
  840. &:hover {
  841. border-color: #007AFF;
  842. background: rgba(0, 122, 255, 0.02);
  843. }
  844. .preset-color {
  845. width: 40px;
  846. height: 40px;
  847. border-radius: 6px;
  848. border: 1px solid $ios-border;
  849. flex-shrink: 0;
  850. }
  851. .preset-info {
  852. flex: 1;
  853. .preset-name {
  854. font-size: $ios-font-size-xs;
  855. font-weight: $ios-font-weight-semibold;
  856. color: $ios-text-primary;
  857. margin-bottom: 2px;
  858. }
  859. .preset-details {
  860. font-size: $ios-font-size-xs;
  861. color: $ios-text-secondary;
  862. margin-bottom: $ios-spacing-xs;
  863. }
  864. .preset-materials {
  865. display: flex;
  866. gap: 4px;
  867. flex-wrap: wrap;
  868. .material-tag {
  869. display: inline-block;
  870. background: $ios-background-secondary;
  871. color: $ios-text-secondary;
  872. padding: 2px 6px;
  873. border-radius: 4px;
  874. font-size: $ios-font-size-xs;
  875. }
  876. }
  877. }
  878. }
  879. }
  880. }
  881. // 进度管理样式
  882. .progress-section {
  883. .progress-overview {
  884. display: flex;
  885. gap: 2rem;
  886. margin-bottom: 2rem;
  887. .progress-stats {
  888. flex: 1;
  889. display: grid;
  890. grid-template-columns: repeat(4, 1fr);
  891. gap: 1rem;
  892. .stat-item {
  893. text-align: center;
  894. padding: 1rem;
  895. background: #f8f9fa;
  896. border-radius: 8px;
  897. .stat-number {
  898. font-size: 2rem;
  899. font-weight: 600;
  900. color: #007AFF;
  901. margin-bottom: 0.5rem;
  902. }
  903. .stat-label {
  904. font-size: 0.875rem;
  905. color: #666;
  906. }
  907. }
  908. }
  909. .progress-chart {
  910. .chart-container {
  911. display: flex;
  912. justify-content: center;
  913. align-items: center;
  914. .progress-circle {
  915. position: relative;
  916. .progress-text {
  917. position: absolute;
  918. top: 50%;
  919. left: 50%;
  920. transform: translate(-50%, -50%);
  921. text-align: center;
  922. .progress-percentage {
  923. font-size: 1.5rem;
  924. font-weight: 600;
  925. color: #34C759;
  926. }
  927. .progress-label {
  928. font-size: 0.75rem;
  929. color: #666;
  930. margin-top: 0.25rem;
  931. }
  932. }
  933. }
  934. }
  935. }
  936. }
  937. .history-section {
  938. margin-bottom: 2rem;
  939. .section-header {
  940. display: flex;
  941. justify-content: space-between;
  942. align-items: center;
  943. margin-bottom: 1rem;
  944. h5 {
  945. margin: 0;
  946. color: #333;
  947. }
  948. .history-controls {
  949. display: flex;
  950. gap: 1rem;
  951. align-items: center;
  952. .history-select {
  953. padding: 0.5rem;
  954. border: 1px solid #ddd;
  955. border-radius: 4px;
  956. background: white;
  957. min-width: 200px;
  958. }
  959. }
  960. }
  961. .history-timeline {
  962. .timeline-item {
  963. display: flex;
  964. align-items: flex-start;
  965. margin-bottom: 1rem;
  966. cursor: pointer;
  967. padding: 0.5rem;
  968. border-radius: 4px;
  969. transition: background-color 0.2s;
  970. &:hover {
  971. background: #f8f9fa;
  972. }
  973. .timeline-marker {
  974. width: 12px;
  975. height: 12px;
  976. border-radius: 50%;
  977. background: #007AFF;
  978. margin-right: 1rem;
  979. margin-top: 0.25rem;
  980. flex-shrink: 0;
  981. }
  982. .timeline-content {
  983. flex: 1;
  984. .timeline-header {
  985. display: flex;
  986. justify-content: space-between;
  987. margin-bottom: 0.25rem;
  988. .timeline-time {
  989. font-weight: 500;
  990. color: #333;
  991. }
  992. .timeline-author {
  993. color: #666;
  994. font-size: 0.875rem;
  995. }
  996. }
  997. .timeline-summary {
  998. color: #666;
  999. font-size: 0.875rem;
  1000. }
  1001. }
  1002. }
  1003. }
  1004. .empty-history {
  1005. text-align: center;
  1006. padding: 2rem;
  1007. color: #666;
  1008. p {
  1009. margin-bottom: 1rem;
  1010. }
  1011. }
  1012. }
  1013. .status-distribution {
  1014. h5 {
  1015. margin-bottom: 1rem;
  1016. color: #333;
  1017. }
  1018. .status-bars {
  1019. .status-bar {
  1020. margin-bottom: 1rem;
  1021. .status-info {
  1022. display: flex;
  1023. justify-content: space-between;
  1024. margin-bottom: 0.5rem;
  1025. .status-name {
  1026. font-weight: 500;
  1027. color: #333;
  1028. }
  1029. .status-count {
  1030. color: #666;
  1031. }
  1032. }
  1033. .status-progress {
  1034. height: 8px;
  1035. background: #e5e5ea;
  1036. border-radius: 4px;
  1037. overflow: hidden;
  1038. .progress-bar {
  1039. height: 100%;
  1040. transition: width 0.3s ease;
  1041. &.confirmed {
  1042. background: #34C759;
  1043. }
  1044. &.pending {
  1045. background: #FF9500;
  1046. }
  1047. &.rejected {
  1048. background: #FF3B30;
  1049. }
  1050. }
  1051. }
  1052. }
  1053. }
  1054. }
  1055. }
  1056. // 协作验证部分
  1057. .collaboration-section {
  1058. .list-header {
  1059. display: flex;
  1060. justify-content: space-between;
  1061. align-items: center;
  1062. margin-bottom: $ios-spacing-md;
  1063. padding-bottom: $ios-spacing-sm;
  1064. border-bottom: 1px solid $ios-border;
  1065. h5 {
  1066. margin: 0;
  1067. font-size: $ios-font-size-sm;
  1068. font-weight: $ios-font-weight-semibold;
  1069. color: $ios-text-primary;
  1070. }
  1071. .list-controls {
  1072. display: flex;
  1073. gap: $ios-spacing-sm;
  1074. }
  1075. }
  1076. .requirements-list {
  1077. .requirement-item {
  1078. border: 1px solid $ios-border;
  1079. border-radius: 8px;
  1080. padding: $ios-spacing-md;
  1081. margin-bottom: $ios-spacing-md;
  1082. background: white;
  1083. transition: all 0.2s ease;
  1084. &.confirmed {
  1085. border-color: #34C759;
  1086. background: rgba(52, 199, 89, 0.02);
  1087. }
  1088. &.rejected {
  1089. border-color: #FF3B30;
  1090. background: rgba(255, 59, 48, 0.02);
  1091. }
  1092. &.pending {
  1093. border-color: #FF9500;
  1094. background: rgba(255, 149, 0, 0.02);
  1095. }
  1096. .requirement-header {
  1097. display: flex;
  1098. justify-content: space-between;
  1099. align-items: flex-start;
  1100. margin-bottom: $ios-spacing-sm;
  1101. .requirement-info {
  1102. flex: 1;
  1103. h6 {
  1104. margin: 0 0 $ios-spacing-xs 0;
  1105. font-size: $ios-font-size-sm;
  1106. font-weight: $ios-font-weight-semibold;
  1107. color: $ios-text-primary;
  1108. }
  1109. p {
  1110. margin: 0 0 $ios-spacing-xs 0;
  1111. font-size: $ios-font-size-xs;
  1112. color: $ios-text-secondary;
  1113. line-height: 1.4;
  1114. }
  1115. .requirement-tags {
  1116. display: flex;
  1117. gap: $ios-spacing-xs;
  1118. flex-wrap: wrap;
  1119. .tag {
  1120. display: inline-block;
  1121. background: $ios-background-secondary;
  1122. color: $ios-text-secondary;
  1123. padding: 2px 6px;
  1124. border-radius: 4px;
  1125. font-size: $ios-font-size-xs;
  1126. }
  1127. }
  1128. }
  1129. .requirement-meta {
  1130. display: flex;
  1131. flex-direction: column;
  1132. gap: $ios-spacing-xs;
  1133. align-items: flex-end;
  1134. .priority-select {
  1135. padding: 4px 8px;
  1136. border: 1px solid $ios-border;
  1137. border-radius: 4px;
  1138. font-size: $ios-font-size-xs;
  1139. background: white;
  1140. &:focus {
  1141. outline: none;
  1142. border-color: #007AFF;
  1143. }
  1144. }
  1145. .status-badge {
  1146. padding: 2px 8px;
  1147. border-radius: 12px;
  1148. font-size: $ios-font-size-xs;
  1149. font-weight: $ios-font-weight-medium;
  1150. &.confirmed {
  1151. background: #34C759;
  1152. color: white;
  1153. }
  1154. &.rejected {
  1155. background: #FF3B30;
  1156. color: white;
  1157. }
  1158. &.pending {
  1159. background: #FF9500;
  1160. color: white;
  1161. }
  1162. }
  1163. }
  1164. }
  1165. .requirement-actions {
  1166. display: flex;
  1167. gap: $ios-spacing-sm;
  1168. align-items: center;
  1169. .unread-indicator {
  1170. display: inline-block;
  1171. width: 6px;
  1172. height: 6px;
  1173. background: #FF3B30;
  1174. border-radius: 50%;
  1175. margin-left: 4px;
  1176. }
  1177. }
  1178. .comments-section {
  1179. margin-top: $ios-spacing-md;
  1180. padding-top: $ios-spacing-md;
  1181. border-top: 1px solid $ios-border;
  1182. .comments-list {
  1183. margin-bottom: $ios-spacing-md;
  1184. .comment-item {
  1185. padding: $ios-spacing-sm;
  1186. border: 1px solid $ios-border;
  1187. border-radius: 6px;
  1188. margin-bottom: $ios-spacing-sm;
  1189. background: $ios-background-secondary;
  1190. &.resolved {
  1191. opacity: 0.6;
  1192. background: rgba(52, 199, 89, 0.05);
  1193. }
  1194. .comment-header {
  1195. display: flex;
  1196. align-items: center;
  1197. gap: $ios-spacing-sm;
  1198. margin-bottom: $ios-spacing-xs;
  1199. .comment-author {
  1200. font-size: $ios-font-size-xs;
  1201. font-weight: $ios-font-weight-semibold;
  1202. color: $ios-text-primary;
  1203. }
  1204. .comment-role {
  1205. font-size: $ios-font-size-xs;
  1206. color: $ios-text-secondary;
  1207. background: white;
  1208. padding: 1px 4px;
  1209. border-radius: 3px;
  1210. }
  1211. .comment-time {
  1212. font-size: $ios-font-size-xs;
  1213. color: $ios-text-tertiary;
  1214. margin-left: auto;
  1215. }
  1216. }
  1217. .comment-content {
  1218. font-size: $ios-font-size-xs;
  1219. color: $ios-text-primary;
  1220. line-height: 1.4;
  1221. }
  1222. }
  1223. }
  1224. .add-comment {
  1225. display: flex;
  1226. gap: $ios-spacing-sm;
  1227. align-items: flex-end;
  1228. textarea {
  1229. flex: 1;
  1230. padding: $ios-spacing-xs;
  1231. border: 1px solid $ios-border;
  1232. border-radius: 6px;
  1233. font-size: $ios-font-size-xs;
  1234. resize: vertical;
  1235. min-height: 60px;
  1236. &:focus {
  1237. outline: none;
  1238. border-color: #007AFF;
  1239. }
  1240. }
  1241. }
  1242. }
  1243. }
  1244. }
  1245. }
  1246. // 进度管理部分
  1247. .progress-section {
  1248. .progress-overview {
  1249. display: grid;
  1250. grid-template-columns: 1fr auto;
  1251. gap: $ios-spacing-lg;
  1252. margin-bottom: $ios-spacing-lg;
  1253. .progress-stats {
  1254. display: flex;
  1255. gap: $ios-spacing-lg;
  1256. .stat-item {
  1257. text-align: center;
  1258. .stat-number {
  1259. font-size: 24px;
  1260. font-weight: $ios-font-weight-bold;
  1261. color: $ios-primary;
  1262. margin-bottom: $ios-spacing-xs;
  1263. }
  1264. .stat-label {
  1265. font-size: $ios-font-size-xs;
  1266. color: $ios-text-secondary;
  1267. }
  1268. }
  1269. }
  1270. .progress-chart {
  1271. .chart-container {
  1272. position: relative;
  1273. .progress-circle {
  1274. position: relative;
  1275. .progress-text-center {
  1276. position: absolute;
  1277. top: 50%;
  1278. left: 50%;
  1279. transform: translate(-50%, -50%);
  1280. text-align: center;
  1281. .progress-percentage {
  1282. font-size: 18px;
  1283. font-weight: $ios-font-weight-bold;
  1284. color: $ios-primary;
  1285. }
  1286. .progress-label {
  1287. font-size: $ios-font-size-xs;
  1288. color: $ios-text-secondary;
  1289. }
  1290. }
  1291. }
  1292. }
  1293. }
  1294. }
  1295. .timeline {
  1296. h5 {
  1297. margin: 0 0 $ios-spacing-sm 0;
  1298. font-size: $ios-font-size-xs;
  1299. font-weight: $ios-font-weight-semibold;
  1300. color: $ios-text-primary;
  1301. }
  1302. .timeline-list {
  1303. .timeline-item {
  1304. display: flex;
  1305. align-items: center;
  1306. gap: $ios-spacing-sm;
  1307. padding: $ios-spacing-sm 0;
  1308. border-bottom: 1px dashed $ios-border;
  1309. &:last-child {
  1310. border-bottom: none;
  1311. }
  1312. .timeline-marker {
  1313. width: 8px;
  1314. height: 8px;
  1315. border-radius: 50%;
  1316. background: $ios-border;
  1317. flex-shrink: 0;
  1318. }
  1319. &.status-confirmed .timeline-marker {
  1320. background: #34C759;
  1321. }
  1322. &.status-rejected .timeline-marker {
  1323. background: #FF3B30;
  1324. }
  1325. &.status-pending .timeline-marker {
  1326. background: #007AFF;
  1327. }
  1328. .timeline-content {
  1329. .timeline-title {
  1330. font-size: $ios-font-size-xs;
  1331. color: $ios-text-primary;
  1332. font-weight: $ios-font-weight-medium;
  1333. }
  1334. .timeline-status {
  1335. font-size: $ios-font-size-xs;
  1336. color: $ios-text-secondary;
  1337. }
  1338. }
  1339. }
  1340. }
  1341. }
  1342. }
  1343. // 通用按钮样式
  1344. .btn-primary, .btn-success, .btn-ghost {
  1345. border: none;
  1346. border-radius: 6px;
  1347. font-size: $ios-font-size-xs;
  1348. font-weight: $ios-font-weight-medium;
  1349. cursor: pointer;
  1350. transition: all 0.2s ease;
  1351. &.btn-sm {
  1352. padding: 6px 12px;
  1353. }
  1354. &.btn-xs {
  1355. padding: 4px 8px;
  1356. }
  1357. &:disabled {
  1358. opacity: 0.5;
  1359. cursor: not-allowed;
  1360. }
  1361. }
  1362. .btn-primary {
  1363. background: $ios-primary;
  1364. color: white;
  1365. &:hover:not(:disabled) {
  1366. background: color.adjust($ios-primary, $lightness: -10%);
  1367. }
  1368. }
  1369. .btn-success {
  1370. background: #34C759;
  1371. color: white;
  1372. &:hover:not(:disabled) {
  1373. background: color.adjust(#34C759, $lightness: -10%);
  1374. }
  1375. }
  1376. .btn-ghost {
  1377. background: transparent;
  1378. color: $ios-text-secondary;
  1379. border: 1px solid $ios-border;
  1380. &:hover:not(:disabled) {
  1381. background: $ios-background-secondary;
  1382. color: $ios-text-primary;
  1383. }
  1384. }
  1385. }
  1386. // 进度动画
  1387. @keyframes progressPulse {
  1388. 0% { opacity: 0.6; }
  1389. 50% { opacity: 1; }
  1390. 100% { opacity: 0.6; }
  1391. }
  1392. // 全局通知样式
  1393. .execution-notification {
  1394. position: fixed;
  1395. top: 20px;
  1396. right: 20px;
  1397. background: #4CAF50;
  1398. color: white;
  1399. padding: 16px 24px;
  1400. border-radius: 8px;
  1401. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  1402. z-index: 1000;
  1403. animation: slideInRight 0.3s ease-out;
  1404. &.error {
  1405. background: #f44336;
  1406. }
  1407. &.warning {
  1408. background: #ff9800;
  1409. }
  1410. }
  1411. @keyframes slideInRight {
  1412. from {
  1413. transform: translateX(100%);
  1414. opacity: 0;
  1415. }
  1416. to {
  1417. transform: translateX(0);
  1418. opacity: 1;
  1419. }
  1420. }
  1421. // 紧凑型流程进度指示器
  1422. .compact-stage-indicators {
  1423. display: flex;
  1424. align-items: center;
  1425. margin: 0 16px;
  1426. .stage-chain {
  1427. display: flex;
  1428. align-items: center;
  1429. gap: 8px;
  1430. }
  1431. .stage-dot {
  1432. width: 28px;
  1433. height: 28px;
  1434. border-radius: 50%;
  1435. display: flex;
  1436. align-items: center;
  1437. justify-content: center;
  1438. font-size: 12px;
  1439. font-weight: 600;
  1440. color: white;
  1441. cursor: pointer;
  1442. transition: all 0.3s ease;
  1443. position: relative;
  1444. .stage-number {
  1445. font-size: 11px;
  1446. font-weight: bold;
  1447. }
  1448. // 已完成状态 - 绿色
  1449. &.stage-completed {
  1450. background: linear-gradient(135deg, #10b981, #059669);
  1451. box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3);
  1452. &:hover {
  1453. transform: scale(1.1);
  1454. box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
  1455. }
  1456. }
  1457. // 进行中状态 - 红色
  1458. &.stage-in-progress {
  1459. background: linear-gradient(135deg, #ef4444, #dc2626);
  1460. box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3);
  1461. animation: pulse-red 2s infinite;
  1462. &:hover {
  1463. transform: scale(1.1);
  1464. box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4);
  1465. }
  1466. }
  1467. // 未进行状态 - 黄色
  1468. &.stage-pending {
  1469. background: linear-gradient(135deg, #f59e0b, #d97706);
  1470. box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);
  1471. &:hover {
  1472. transform: scale(1.1);
  1473. box-shadow: 0 4px 12px rgba(245, 158, 11, 0.4);
  1474. }
  1475. }
  1476. }
  1477. .stage-connector {
  1478. width: 20px;
  1479. height: 3px;
  1480. border-radius: 2px;
  1481. transition: all 0.3s ease;
  1482. &.completed {
  1483. background: linear-gradient(90deg, #10b981, #059669);
  1484. }
  1485. &.pending {
  1486. background: #e5e7eb;
  1487. }
  1488. }
  1489. }
  1490. // 进行中状态的脉冲动画
  1491. @keyframes pulse-red {
  1492. 0%, 100% {
  1493. box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3);
  1494. }
  1495. 50% {
  1496. box-shadow: 0 2px 12px rgba(239, 68, 68, 0.6);
  1497. }
  1498. }
  1499. // 更新header-actions布局
  1500. .header-actions {
  1501. display: flex;
  1502. align-items: center;
  1503. gap: 16px;
  1504. .btn-ghost {
  1505. flex-shrink: 0;
  1506. }
  1507. .compact-stage-indicators {
  1508. flex-shrink: 0;
  1509. }
  1510. .progress-indicator {
  1511. flex-shrink: 0;
  1512. }
  1513. }
  1514. // 保存状态区域
  1515. .save-section {
  1516. margin-top: 24px;
  1517. padding: 16px;
  1518. background: #f8fafc;
  1519. border-radius: 8px;
  1520. border: 1px solid #e2e8f0;
  1521. display: flex;
  1522. justify-content: space-between;
  1523. align-items: center;
  1524. gap: 16px;
  1525. .save-status {
  1526. display: flex;
  1527. align-items: center;
  1528. gap: 8px;
  1529. .save-icon {
  1530. font-size: 16px;
  1531. font-weight: bold;
  1532. &.save-icon-saved {
  1533. color: #10b981;
  1534. }
  1535. &.save-icon-saving {
  1536. color: #3b82f6;
  1537. animation: spin 1s linear infinite;
  1538. }
  1539. &.save-icon-error {
  1540. color: #ef4444;
  1541. }
  1542. &.save-icon-unsaved {
  1543. color: #f59e0b;
  1544. }
  1545. }
  1546. .save-text {
  1547. font-size: 14px;
  1548. color: #64748b;
  1549. }
  1550. }
  1551. .save-actions {
  1552. display: flex;
  1553. align-items: center;
  1554. gap: 16px;
  1555. .btn-secondary {
  1556. padding: 8px 16px;
  1557. background: #3b82f6;
  1558. color: white;
  1559. border: none;
  1560. border-radius: 6px;
  1561. font-size: 14px;
  1562. cursor: pointer;
  1563. transition: all 0.2s ease;
  1564. &:hover:not(:disabled) {
  1565. background: #2563eb;
  1566. transform: translateY(-1px);
  1567. }
  1568. &:disabled {
  1569. background: #94a3b8;
  1570. cursor: not-allowed;
  1571. transform: none;
  1572. }
  1573. .loading-spinner {
  1574. display: inline-block;
  1575. width: 12px;
  1576. height: 12px;
  1577. border: 2px solid transparent;
  1578. border-top: 2px solid currentColor;
  1579. border-radius: 50%;
  1580. animation: spin 1s linear infinite;
  1581. margin-right: 8px;
  1582. }
  1583. }
  1584. .auto-save-toggle {
  1585. .toggle-label {
  1586. display: flex;
  1587. align-items: center;
  1588. gap: 8px;
  1589. cursor: pointer;
  1590. .toggle-input {
  1591. display: none;
  1592. }
  1593. .toggle-slider {
  1594. width: 40px;
  1595. height: 20px;
  1596. background: #cbd5e1;
  1597. border-radius: 10px;
  1598. position: relative;
  1599. transition: all 0.3s ease;
  1600. &::after {
  1601. content: '';
  1602. position: absolute;
  1603. top: 2px;
  1604. left: 2px;
  1605. width: 16px;
  1606. height: 16px;
  1607. background: white;
  1608. border-radius: 50%;
  1609. transition: all 0.3s ease;
  1610. }
  1611. }
  1612. .toggle-input:checked + .toggle-slider {
  1613. background: #10b981;
  1614. &::after {
  1615. transform: translateX(20px);
  1616. }
  1617. }
  1618. .toggle-text {
  1619. font-size: 14px;
  1620. color: #64748b;
  1621. }
  1622. }
  1623. }
  1624. }
  1625. }
  1626. @keyframes spin {
  1627. from {
  1628. transform: rotate(0deg);
  1629. }
  1630. to {
  1631. transform: rotate(360deg);
  1632. }
  1633. }
  1634. // 需求映射测试相关样式
  1635. .test-progress {
  1636. margin-bottom: 32px;
  1637. padding: 20px;
  1638. background: #f8f9fa;
  1639. border-radius: 8px;
  1640. border: 1px solid #e9ecef;
  1641. h3 {
  1642. margin: 0 0 16px 0;
  1643. font-size: 18px;
  1644. color: #495057;
  1645. }
  1646. .steps-container {
  1647. display: grid;
  1648. grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  1649. gap: 16px;
  1650. }
  1651. .step-item {
  1652. display: flex;
  1653. align-items: center;
  1654. padding: 12px;
  1655. background: white;
  1656. border-radius: 6px;
  1657. border: 2px solid #e9ecef;
  1658. transition: all 0.2s ease;
  1659. &.step-pending {
  1660. border-color: #e9ecef;
  1661. .step-icon { color: #6c757d; }
  1662. }
  1663. &.step-in-progress {
  1664. border-color: #ffc107;
  1665. background: #fff8e1;
  1666. .step-icon { color: #ffc107; }
  1667. }
  1668. &.step-completed {
  1669. border-color: #28a745;
  1670. background: #f8fff9;
  1671. .step-icon { color: #28a745; }
  1672. }
  1673. &.step-error {
  1674. border-color: #dc3545;
  1675. background: #fff5f5;
  1676. .step-icon { color: #dc3545; }
  1677. }
  1678. .step-icon {
  1679. font-size: 20px;
  1680. margin-right: 12px;
  1681. }
  1682. .step-info {
  1683. .step-name {
  1684. font-weight: 500;
  1685. font-size: 14px;
  1686. color: #495057;
  1687. }
  1688. .step-status {
  1689. font-size: 12px;
  1690. color: #6c757d;
  1691. margin-top: 2px;
  1692. }
  1693. }
  1694. }
  1695. }
  1696. .upload-section,
  1697. .analysis-section,
  1698. .mapping-section {
  1699. margin-bottom: 32px;
  1700. padding: 24px;
  1701. background: white;
  1702. border-radius: 8px;
  1703. border: 1px solid #e9ecef;
  1704. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  1705. &.disabled {
  1706. opacity: 0.6;
  1707. pointer-events: none;
  1708. }
  1709. h3 {
  1710. margin: 0 0 20px 0;
  1711. font-size: 20px;
  1712. color: #495057;
  1713. border-bottom: 2px solid #e9ecef;
  1714. padding-bottom: 8px;
  1715. }
  1716. }
  1717. .upload-area {
  1718. position: relative;
  1719. min-height: 200px;
  1720. .upload-dropzone {
  1721. display: flex;
  1722. flex-direction: column;
  1723. align-items: center;
  1724. justify-content: center;
  1725. min-height: 200px;
  1726. border: 2px dashed #dee2e6;
  1727. border-radius: 8px;
  1728. background: #f8f9fa;
  1729. cursor: pointer;
  1730. transition: all 0.2s ease;
  1731. position: relative;
  1732. &:hover {
  1733. border-color: #667eea;
  1734. background: #f0f4ff;
  1735. }
  1736. .upload-icon {
  1737. font-size: 48px;
  1738. margin-bottom: 16px;
  1739. opacity: 0.7;
  1740. }
  1741. .upload-text {
  1742. font-size: 18px;
  1743. font-weight: 500;
  1744. color: #495057;
  1745. margin-bottom: 8px;
  1746. }
  1747. .upload-hint {
  1748. font-size: 14px;
  1749. color: #6c757d;
  1750. }
  1751. .file-input {
  1752. position: absolute;
  1753. top: 0;
  1754. left: 0;
  1755. width: 100%;
  1756. height: 100%;
  1757. opacity: 0;
  1758. cursor: pointer;
  1759. }
  1760. }
  1761. .uploaded-files {
  1762. h4 {
  1763. margin: 0 0 16px 0;
  1764. font-size: 16px;
  1765. color: #495057;
  1766. }
  1767. .files-grid {
  1768. display: grid;
  1769. grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  1770. gap: 16px;
  1771. }
  1772. .file-item {
  1773. border: 1px solid #e9ecef;
  1774. border-radius: 6px;
  1775. overflow: hidden;
  1776. background: white;
  1777. .file-preview {
  1778. width: 100%;
  1779. height: 120px;
  1780. object-fit: cover;
  1781. }
  1782. .file-info {
  1783. padding: 8px;
  1784. .file-name {
  1785. font-size: 12px;
  1786. font-weight: 500;
  1787. color: #495057;
  1788. margin-bottom: 4px;
  1789. white-space: nowrap;
  1790. overflow: hidden;
  1791. text-overflow: ellipsis;
  1792. }
  1793. .file-size {
  1794. font-size: 11px;
  1795. color: #6c757d;
  1796. }
  1797. }
  1798. }
  1799. }
  1800. .loading-overlay {
  1801. position: absolute;
  1802. top: 0;
  1803. left: 0;
  1804. right: 0;
  1805. bottom: 0;
  1806. background: rgba(255, 255, 255, 0.9);
  1807. display: flex;
  1808. flex-direction: column;
  1809. align-items: center;
  1810. justify-content: center;
  1811. border-radius: 8px;
  1812. }
  1813. }
  1814. .analysis-loading,
  1815. .mapping-loading {
  1816. display: flex;
  1817. align-items: center;
  1818. padding: 24px;
  1819. background: #f0f4ff;
  1820. border-radius: 6px;
  1821. border: 1px solid #e3f2fd;
  1822. .loading-text {
  1823. margin-left: 16px;
  1824. h4 {
  1825. margin: 0 0 8px 0;
  1826. font-size: 16px;
  1827. color: #495057;
  1828. }
  1829. p {
  1830. margin: 0;
  1831. font-size: 14px;
  1832. color: #6c757d;
  1833. }
  1834. }
  1835. }
  1836. .analysis-error,
  1837. .mapping-error {
  1838. display: flex;
  1839. align-items: center;
  1840. padding: 24px;
  1841. background: #fff5f5;
  1842. border-radius: 6px;
  1843. border: 1px solid #ffebee;
  1844. .error-icon {
  1845. font-size: 24px;
  1846. margin-right: 16px;
  1847. }
  1848. .error-text {
  1849. flex: 1;
  1850. h4 {
  1851. margin: 0 0 8px 0;
  1852. font-size: 16px;
  1853. color: #dc3545;
  1854. }
  1855. p {
  1856. margin: 0 0 12px 0;
  1857. font-size: 14px;
  1858. color: #6c757d;
  1859. }
  1860. .retry-btn {
  1861. background: #dc3545;
  1862. color: white;
  1863. border: none;
  1864. padding: 8px 16px;
  1865. border-radius: 4px;
  1866. cursor: pointer;
  1867. font-size: 14px;
  1868. transition: background 0.2s ease;
  1869. &:hover {
  1870. background: #c82333;
  1871. }
  1872. }
  1873. }
  1874. }
  1875. .analysis-result,
  1876. .mapping-result {
  1877. h4 {
  1878. margin: 0 0 16px 0;
  1879. font-size: 18px;
  1880. color: #28a745;
  1881. display: flex;
  1882. align-items: center;
  1883. }
  1884. .analysis-summary {
  1885. display: grid;
  1886. grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  1887. gap: 16px;
  1888. margin-top: 16px;
  1889. }
  1890. .summary-item {
  1891. display: flex;
  1892. justify-content: space-between;
  1893. padding: 12px;
  1894. background: #f8f9fa;
  1895. border-radius: 4px;
  1896. .label {
  1897. font-weight: 500;
  1898. color: #495057;
  1899. }
  1900. .value {
  1901. color: #6c757d;
  1902. }
  1903. }
  1904. }
  1905. .mapping-section-item {
  1906. margin-bottom: 24px;
  1907. h5 {
  1908. margin: 0 0 16px 0;
  1909. font-size: 16px;
  1910. color: #495057;
  1911. border-bottom: 1px solid #e9ecef;
  1912. padding-bottom: 8px;
  1913. }
  1914. .scene-info {
  1915. .info-row {
  1916. display: flex;
  1917. justify-content: space-between;
  1918. padding: 8px 0;
  1919. border-bottom: 1px solid #f8f9fa;
  1920. .label {
  1921. font-weight: 500;
  1922. color: #495057;
  1923. }
  1924. .value {
  1925. color: #6c757d;
  1926. }
  1927. }
  1928. .atmosphere-preview {
  1929. margin-top: 16px;
  1930. text-align: center;
  1931. .preview-image {
  1932. max-width: 300px;
  1933. max-height: 200px;
  1934. border-radius: 6px;
  1935. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  1936. }
  1937. .preview-label {
  1938. margin-top: 8px;
  1939. font-size: 14px;
  1940. color: #6c757d;
  1941. }
  1942. }
  1943. }
  1944. .params-grid {
  1945. display: grid;
  1946. grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  1947. gap: 20px;
  1948. }
  1949. .param-group {
  1950. background: #f8f9fa;
  1951. padding: 16px;
  1952. border-radius: 6px;
  1953. h6 {
  1954. margin: 0 0 12px 0;
  1955. font-size: 14px;
  1956. font-weight: 600;
  1957. color: #495057;
  1958. }
  1959. .param-item {
  1960. display: flex;
  1961. justify-content: space-between;
  1962. padding: 6px 0;
  1963. border-bottom: 1px solid #e9ecef;
  1964. &:last-child {
  1965. border-bottom: none;
  1966. }
  1967. .label {
  1968. font-size: 13px;
  1969. color: #6c757d;
  1970. }
  1971. .value {
  1972. font-size: 13px;
  1973. font-weight: 500;
  1974. color: #495057;
  1975. }
  1976. }
  1977. }
  1978. }
  1979. .analysis-placeholder,
  1980. .mapping-placeholder {
  1981. display: flex;
  1982. flex-direction: column;
  1983. align-items: center;
  1984. justify-content: center;
  1985. min-height: 150px;
  1986. color: #6c757d;
  1987. .placeholder-icon {
  1988. font-size: 48px;
  1989. margin-bottom: 16px;
  1990. opacity: 0.7;
  1991. }
  1992. .placeholder-text {
  1993. text-align: center;
  1994. h4 {
  1995. margin: 0 0 8px 0;
  1996. font-size: 16px;
  1997. }
  1998. p {
  1999. margin: 0;
  2000. font-size: 14px;
  2001. opacity: 0.8;
  2002. }
  2003. }
  2004. }
  2005. .test-actions {
  2006. margin-top: 24px;
  2007. text-align: center;
  2008. .download-btn {
  2009. display: inline-flex;
  2010. align-items: center;
  2011. gap: 8px;
  2012. background: #667eea;
  2013. color: white;
  2014. border: none;
  2015. padding: 12px 24px;
  2016. border-radius: 6px;
  2017. cursor: pointer;
  2018. font-size: 14px;
  2019. font-weight: 500;
  2020. transition: all 0.2s ease;
  2021. &:hover {
  2022. background: #5a6fd8;
  2023. transform: translateY(-1px);
  2024. }
  2025. svg {
  2026. width: 16px;
  2027. height: 16px;
  2028. }
  2029. }
  2030. }
  2031. .loading-spinner {
  2032. width: 24px;
  2033. height: 24px;
  2034. border: 2px solid #f3f3f3;
  2035. border-top: 2px solid #667eea;
  2036. border-radius: 50%;
  2037. animation: spin 1s linear infinite;
  2038. }
  2039. // 响应式设计
  2040. @media (max-width: 768px) {
  2041. .test-progress {
  2042. padding: 16px;
  2043. .steps-container {
  2044. grid-template-columns: 1fr;
  2045. }
  2046. }
  2047. .upload-section,
  2048. .analysis-section,
  2049. .mapping-section {
  2050. padding: 16px;
  2051. }
  2052. .params-grid {
  2053. grid-template-columns: 1fr;
  2054. }
  2055. .analysis-summary {
  2056. grid-template-columns: 1fr;
  2057. }
  2058. }
  2059. @keyframes pulse {
  2060. 0%, 100% { opacity: 1; }
  2061. 50% { opacity: 0.5; }
  2062. }