page-text-response.scss 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /* 基础变量 */
  2. :root {
  3. --primary-color: #6e48aa;
  4. --primary-light: #9d50bb;
  5. --secondary-color: #4776e6;
  6. --text-primary: #2d3748;
  7. --text-secondary: #718096;
  8. --bg-color: #f8f9fa;
  9. --bg-elevated: #ffffff;
  10. --border-color: #e2e8f0;
  11. --user-bubble: #edf2f7;
  12. --ai-bubble: #ffffff;
  13. --shadow-sm: 0 1px 3px rgba(0,0,0,0.12);
  14. --shadow-md: 0 4px 6px rgba(0,0,0,0.1);
  15. --radius-md: 8px;
  16. --radius-lg: 12px;
  17. }
  18. /* 动画定义 */
  19. @keyframes fadeIn {
  20. from { opacity: 0; transform: translateY(10px); }
  21. to { opacity: 1; transform: translateY(0); }
  22. }
  23. @keyframes pulse {
  24. 0% { transform: scale(1); opacity: 1; }
  25. 50% { transform: scale(1.05); opacity: 0.7; }
  26. 100% { transform: scale(1); opacity: 1; }
  27. }
  28. @keyframes typing {
  29. 0% { opacity: 0.4; transform: translateY(0); }
  30. 50% { opacity: 1; transform: translateY(-3px); }
  31. 100% { opacity: 0.4; transform: translateY(0); }
  32. }
  33. /* 主容器 */
  34. .chat-container {
  35. display: flex;
  36. flex-direction: column;
  37. height: 100vh;
  38. background-color: var(--bg-color);
  39. position: relative;
  40. overflow: hidden;
  41. }
  42. /* 顶部导航栏 */
  43. .chat-header {
  44. background: linear-gradient(135deg, var(--primary-color), var(--primary-light));
  45. color: white;
  46. padding: 0.75rem 1.5rem;
  47. box-shadow: var(--shadow-md);
  48. z-index: 10;
  49. .header-content {
  50. display: flex;
  51. justify-content: space-between;
  52. align-items: center;
  53. max-width: 1200px;
  54. margin: 0 auto;
  55. }
  56. .ai-identity {
  57. display: flex;
  58. align-items: center;
  59. gap: 0.75rem;
  60. h1 {
  61. font-size: 1.25rem;
  62. font-weight: 600;
  63. margin: 0;
  64. }
  65. }
  66. .avatar-pulse {
  67. position: relative;
  68. .avatar {
  69. width: 36px;
  70. height: 36px;
  71. border-radius: 50%;
  72. background-color: white;
  73. color: var(--primary-color);
  74. display: flex;
  75. align-items: center;
  76. justify-content: center;
  77. font-weight: bold;
  78. z-index: 2;
  79. position: relative;
  80. }
  81. .pulse-ring {
  82. position: absolute;
  83. top: -4px;
  84. left: -4px;
  85. right: -4px;
  86. bottom: -4px;
  87. background: rgba(255,255,255,0.3);
  88. border-radius: 50%;
  89. z-index: 1;
  90. opacity: 0;
  91. transition: opacity 0.3s ease;
  92. &.active {
  93. opacity: 1;
  94. animation: pulse 2s infinite;
  95. }
  96. }
  97. }
  98. .status-indicator {
  99. display: flex;
  100. align-items: center;
  101. gap: 0.5rem;
  102. font-size: 0.875rem;
  103. background: rgba(255,255,255,0.15);
  104. padding: 0.25rem 0.75rem;
  105. border-radius: 1rem;
  106. transition: all 0.3s ease;
  107. &.error {
  108. background: rgba(239, 68, 68, 0.2);
  109. color: #fef2f2;
  110. }
  111. &.loading {
  112. .status-light {
  113. animation: pulse 1.5s infinite;
  114. }
  115. }
  116. .status-light {
  117. width: 8px;
  118. height: 8px;
  119. border-radius: 50%;
  120. background: #4ade80;
  121. .error & {
  122. background: #ef4444;
  123. }
  124. .loading & {
  125. background: #fbbf24;
  126. }
  127. }
  128. }
  129. }
  130. /* 消息区域 */
  131. .chat-messages {
  132. flex: 1;
  133. overflow-y: auto;
  134. padding: 1.5rem;
  135. scroll-behavior: smooth;
  136. display: flex;
  137. flex-direction: column;
  138. gap: 0.5rem;
  139. max-width: 1200px;
  140. margin: 0 auto;
  141. width: 100%;
  142. box-sizing: border-box;
  143. .message-wrapper {
  144. &.new-group {
  145. margin-top: 1.25rem;
  146. position: relative;
  147. &::before {
  148. content: '';
  149. position: absolute;
  150. top: -0.75rem;
  151. left: 50%;
  152. transform: translateX(-50%);
  153. width: 60%;
  154. height: 1px;
  155. background: var(--border-color);
  156. opacity: 0.6;
  157. }
  158. }
  159. }
  160. .message {
  161. max-width: 85%;
  162. margin: 0 auto;
  163. animation: fadeIn 0.3s ease-out forwards;
  164. opacity: 0;
  165. &.user {
  166. margin-left: auto;
  167. margin-right: 0;
  168. .message-content {
  169. flex-direction: row-reverse;
  170. }
  171. .message-bubble {
  172. background-color: var(--user-bubble);
  173. border-top-right-radius: 4px;
  174. }
  175. }
  176. &.assistant {
  177. margin-left: 0;
  178. margin-right: auto;
  179. .message-bubble {
  180. background-color: var(--ai-bubble);
  181. border-top-left-radius: 4px;
  182. box-shadow: var(--shadow-sm);
  183. }
  184. }
  185. .message-content {
  186. display: flex;
  187. gap: 0.75rem;
  188. align-items: flex-end;
  189. }
  190. .avatar-container {
  191. .avatar {
  192. width: 32px;
  193. height: 32px;
  194. border-radius: 50%;
  195. background: linear-gradient(135deg, var(--primary-light), var(--secondary-color));
  196. color: white;
  197. display: flex;
  198. align-items: center;
  199. justify-content: center;
  200. font-size: 0.75rem;
  201. font-weight: bold;
  202. flex-shrink: 0;
  203. &.user {
  204. background: var(--text-secondary);
  205. }
  206. }
  207. }
  208. .bubble-container {
  209. display: flex;
  210. flex-direction: column;
  211. gap: 0.25rem;
  212. flex: 1;
  213. min-width: 0;
  214. }
  215. .message-bubble {
  216. padding: 0.75rem 1rem;
  217. border-radius: var(--radius-md);
  218. line-height: 1.5;
  219. word-wrap: break-word;
  220. position: relative;
  221. transition: transform 0.2s ease;
  222. &:hover {
  223. .message-actions {
  224. opacity: 1;
  225. }
  226. }
  227. }
  228. .message-actions {
  229. position: absolute;
  230. right: 0;
  231. top: -24px;
  232. display: flex;
  233. gap: 0.25rem;
  234. background: white;
  235. padding: 0.25rem;
  236. border-radius: var(--radius-md);
  237. box-shadow: var(--shadow-sm);
  238. opacity: 0;
  239. transition: opacity 0.2s ease;
  240. }
  241. .action-button {
  242. width: 24px;
  243. height: 24px;
  244. border-radius: 4px;
  245. display: flex;
  246. align-items: center;
  247. justify-content: center;
  248. background: none;
  249. border: none;
  250. color: var(--text-secondary);
  251. cursor: pointer;
  252. transition: all 0.2s ease;
  253. &:hover {
  254. background: var(--bg-color);
  255. color: var(--primary-color);
  256. }
  257. }
  258. .timestamp {
  259. font-size: 0.75rem;
  260. color: var(--text-secondary);
  261. padding: 0 0.5rem;
  262. }
  263. .typing-indicator {
  264. display: flex;
  265. gap: 0.25rem;
  266. padding: 0.5rem 0;
  267. .dot {
  268. width: 8px;
  269. height: 8px;
  270. border-radius: 50%;
  271. background-color: var(--text-secondary);
  272. opacity: 0.4;
  273. animation: typing 1.4s infinite ease-in-out;
  274. &:nth-child(1) { animation-delay: 0s; }
  275. &:nth-child(2) { animation-delay: 0.2s; }
  276. &:nth-child(3) { animation-delay: 0.4s; }
  277. }
  278. }
  279. }
  280. }
  281. /* 输入区域 */
  282. .chat-input-container {
  283. background: var(--bg-elevated);
  284. border-top: 1px solid var(--border-color);
  285. padding: 1rem;
  286. position: relative;
  287. max-width: 1200px;
  288. margin: 0 auto;
  289. width: 100%;
  290. box-sizing: border-box;
  291. .input-tools {
  292. display: flex;
  293. gap: 0.5rem;
  294. margin-bottom: 0.5rem;
  295. }
  296. .tool-button {
  297. width: 36px;
  298. height: 36px;
  299. border-radius: 50%;
  300. display: flex;
  301. align-items: center;
  302. justify-content: center;
  303. background: none;
  304. border: none;
  305. color: var(--text-secondary);
  306. cursor: pointer;
  307. transition: all 0.2s ease;
  308. &:hover {
  309. background: var(--bg-color);
  310. color: var(--primary-color);
  311. }
  312. }
  313. .input-wrapper {
  314. display: flex;
  315. background: var(--bg-elevated);
  316. border-radius: var(--radius-lg);
  317. border: 1px solid var(--border-color);
  318. transition: all 0.2s ease;
  319. overflow: hidden;
  320. &.focused {
  321. border-color: var(--primary-color);
  322. box-shadow: 0 0 0 1px var(--primary-color);
  323. }
  324. textarea {
  325. flex: 1;
  326. border: none;
  327. padding: 0.75rem 1rem;
  328. resize: none;
  329. max-height: 150px;
  330. min-height: 44px;
  331. font-family: inherit;
  332. line-height: 1.5;
  333. background: transparent;
  334. color: var(--text-primary);
  335. &:focus {
  336. outline: none;
  337. }
  338. &::placeholder {
  339. color: var(--text-secondary);
  340. opacity: 0.6;
  341. }
  342. }
  343. .input-actions {
  344. display: flex;
  345. align-items: flex-end;
  346. padding: 0 0.5rem 0.5rem;
  347. }
  348. .send-button {
  349. width: 36px;
  350. height: 36px;
  351. border-radius: 50%;
  352. display: flex;
  353. align-items: center;
  354. justify-content: center;
  355. background: var(--primary-color);
  356. border: none;
  357. color: white;
  358. cursor: pointer;
  359. transition: all 0.2s ease;
  360. position: relative;
  361. overflow: hidden;
  362. &:disabled {
  363. background: var(--border-color);
  364. cursor: not-allowed;
  365. svg {
  366. opacity: 0.5;
  367. }
  368. }
  369. &:not(:disabled):hover {
  370. background: var(--primary-light);
  371. transform: translateY(-2px);
  372. }
  373. &.loading {
  374. background: var(--border-color);
  375. }
  376. svg {
  377. transition: all 0.2s ease;
  378. &.active {
  379. color: white;
  380. }
  381. }
  382. .spinner {
  383. width: 20px;
  384. height: 20px;
  385. border: 2px solid rgba(255,255,255,0.3);
  386. border-radius: 50%;
  387. border-top-color: white;
  388. animation: spin 1s ease-in-out infinite;
  389. }
  390. }
  391. }
  392. }
  393. /* 历史面板 */
  394. .history-panel {
  395. position: absolute;
  396. top: 0;
  397. right: 0;
  398. bottom: 0;
  399. width: 300px;
  400. background: var(--bg-elevated);
  401. border-left: 1px solid var(--border-color);
  402. z-index: 20;
  403. display: flex;
  404. flex-direction: column;
  405. box-shadow: -4px 0 12px rgba(0,0,0,0.05);
  406. transform: translateX(100%);
  407. animation: slideIn 0.3s ease-out forwards;
  408. .panel-header {
  409. display: flex;
  410. justify-content: space-between;
  411. align-items: center;
  412. padding: 1rem;
  413. border-bottom: 1px solid var(--border-color);
  414. h3 {
  415. margin: 0;
  416. font-size: 1rem;
  417. color: var(--text-primary);
  418. }
  419. .close-button {
  420. width: 32px;
  421. height: 32px;
  422. border-radius: 50%;
  423. display: flex;
  424. align-items: center;
  425. justify-content: center;
  426. background: none;
  427. border: none;
  428. color: var(--text-secondary);
  429. cursor: pointer;
  430. transition: all 0.2s ease;
  431. &:hover {
  432. background: var(--bg-color);
  433. }
  434. }
  435. }
  436. .history-list {
  437. flex: 1;
  438. overflow-y: auto;
  439. padding: 0.5rem;
  440. }
  441. .history-item {
  442. padding: 0.75rem;
  443. border-radius: var(--radius-md);
  444. margin-bottom: 0.5rem;
  445. cursor: pointer;
  446. transition: all 0.2s ease;
  447. &:hover {
  448. background: var(--bg-color);
  449. }
  450. .item-content {
  451. font-size: 0.875rem;
  452. color: var(--text-primary);
  453. white-space: nowrap;
  454. overflow: hidden;
  455. text-overflow: ellipsis;
  456. margin-bottom: 0.25rem;
  457. }
  458. .item-time {
  459. font-size: 0.75rem;
  460. color: var(--text-secondary);
  461. }
  462. }
  463. }
  464. /* 动画定义 */
  465. @keyframes slideIn {
  466. from { transform: translateX(100%); }
  467. to { transform: translateX(0); }
  468. }
  469. @keyframes spin {
  470. to { transform: rotate(360deg); }
  471. }
  472. /* 响应式调整 */
  473. @media (max-width: 768px) {
  474. .chat-messages {
  475. padding: 1rem;
  476. .message {
  477. max-width: 90%;
  478. }
  479. }
  480. .history-panel {
  481. width: 280px;
  482. }
  483. }
  484. .action-button {
  485. font-size: 1.2em;
  486. line-height: 1;
  487. }
  488. .send-button {
  489. font-size: 1.5em;
  490. }