Sidebar.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. <template>
  2. <aside class="sidebar">
  3. <!-- Logo -->
  4. <div class="sidebar-header">
  5. <div class="logo">
  6. <div class="logo-icon">🧠</div>
  7. <div>
  8. <div class="logo-text">领存智贸</div>
  9. <div class="logo-subtitle">AI原生外贸CRM</div>
  10. </div>
  11. </div>
  12. </div>
  13. <!-- Navigation -->
  14. <nav class="nav-menu">
  15. <!-- AI核心 -->
  16. <div class="nav-section">
  17. <div class="nav-section-title">AI 核心</div>
  18. <!-- <router-link to="/" class="nav-item" :class="{ active: $route.path === '/' }">
  19. <i class="fas fa-brain nav-icon"></i>
  20. <span class="nav-text">企业大脑</span>
  21. </router-link> -->
  22. <router-link to="/prospect" class="nav-item" :class="{ active: $route.path === '/prospect' }">
  23. <i class="fas fa-crosshairs nav-icon"></i>
  24. <span class="nav-text">自动寻客</span>
  25. <span class="nav-badge">新</span>
  26. </router-link>
  27. <router-link to="/marketing" class="nav-item" :class="{ active: $route.path === '/marketing' }">
  28. <i class="fas fa-paper-plane nav-icon"></i>
  29. <span class="nav-text">自动营销</span>
  30. </router-link>
  31. <router-link to="/strategy" class="nav-item" :class="{ active: $route.path === '/strategy' }">
  32. <i class="fas fa-lightbulb nav-icon"></i>
  33. <span class="nav-text">AI策略中心</span>
  34. </router-link>
  35. </div>
  36. <!-- 客户管理 -->
  37. <div class="nav-section">
  38. <div class="nav-section-title">客户管理</div>
  39. <router-link to="/customers" class="nav-item" :class="{ active: $route.path === '/customers' }">
  40. <i class="fas fa-users nav-icon"></i>
  41. <span class="nav-text">客户池</span>
  42. <span class="nav-badge">847</span>
  43. </router-link>
  44. <!-- <router-link to="/opportunities" class="nav-item" :class="{ active: $route.path === '/opportunities' }">
  45. <i class="fas fa-briefcase nav-icon"></i>
  46. <span class="nav-text">商机管理</span>
  47. </router-link>
  48. <router-link to="/orders" class="nav-item" :class="{ active: $route.path === '/orders' }">
  49. <i class="fas fa-box nav-icon"></i>
  50. <span class="nav-text">订单跟进</span>
  51. </router-link> -->
  52. </div>
  53. <!-- 数据洞察 -->
  54. <!-- <div class="nav-section">
  55. <div class="nav-section-title">数据洞察</div>
  56. <router-link to="/analysis" class="nav-item" :class="{ active: $route.path === '/analysis' }">
  57. <i class="fas fa-chart-line nav-icon"></i>
  58. <span class="nav-text">经营分析</span>
  59. </router-link>
  60. <router-link to="/market" class="nav-item" :class="{ active: $route.path === '/market' }">
  61. <i class="fas fa-globe nav-icon"></i>
  62. <span class="nav-text">市场情报</span>
  63. </router-link>
  64. <router-link to="/risk" class="nav-item" :class="{ active: $route.path === '/risk' }">
  65. <i class="fas fa-shield-alt nav-icon"></i>
  66. <span class="nav-text">风险风控</span>
  67. <span class="nav-badge" style="background: var(--warning);">3</span>
  68. </router-link>
  69. </div> -->
  70. <!-- 系统设置 -->
  71. <div class="nav-section">
  72. <div class="nav-section-title">系统</div>
  73. <router-link to="/knowledge" class="nav-item" :class="{ active: $route.path === '/knowledge' }">
  74. <i class="fas fa-book nav-icon"></i>
  75. <span class="nav-text">知识库</span>
  76. </router-link>
  77. <router-link to="/settings" class="nav-item" :class="{ active: $route.path === '/settings' }">
  78. <i class="fas fa-cog nav-icon"></i>
  79. <span class="nav-text">设置</span>
  80. </router-link>
  81. </div>
  82. </nav>
  83. <!-- User Profile -->
  84. <div class="sidebar-footer">
  85. <div class="user-card" @click="toggleUserMenu">
  86. <div class="user-avatar-wrapper">
  87. <div class="user-avatar">张</div>
  88. <div class="online-indicator"></div>
  89. </div>
  90. <div class="user-info">
  91. <div class="user-name">张经理</div>
  92. <div class="user-status">
  93. <span class="status-dot"></span>
  94. 在线
  95. </div>
  96. </div>
  97. <i class="fas fa-chevron-up user-arrow" :class="{ rotated: showUserMenu }"></i>
  98. </div>
  99. <!-- User Dropdown Menu -->
  100. <transition name="dropdown">
  101. <div v-if="showUserMenu" class="user-menu">
  102. <div class="menu-header">
  103. <div class="menu-avatar">张</div>
  104. <div class="menu-user-info">
  105. <div class="menu-user-name">张经理</div>
  106. <div class="menu-user-email">zhang@company.com</div>
  107. </div>
  108. </div>
  109. <div class="menu-divider"></div>
  110. <div class="menu-items">
  111. <router-link to="/settings" class="menu-item" @click="showUserMenu = false">
  112. <div class="menu-item-icon" style="background: rgba(99, 102, 241, 0.2); color: var(--primary);">
  113. <i class="fas fa-user"></i>
  114. </div>
  115. <div class="menu-item-content">
  116. <span class="menu-item-title">个人资料</span>
  117. <span class="menu-item-desc">编辑头像、姓名等信息</span>
  118. </div>
  119. </router-link>
  120. </div>
  121. <div class="menu-divider"></div>
  122. <div class="menu-items">
  123. <div class="menu-item" @click="toggleTheme">
  124. <div class="menu-item-icon" style="background: rgba(245, 158, 11, 0.2); color: var(--warning);">
  125. <i :class="isDarkMode ? 'fas fa-sun' : 'fas fa-moon'"></i>
  126. </div>
  127. <div class="menu-item-content">
  128. <span class="menu-item-title">修改密码</span>
  129. </div>
  130. </div>
  131. <div class="menu-item" @click="showHelpModal = true">
  132. <div class="menu-item-icon" style="background: rgba(6, 182, 212, 0.2); color: var(--info);">
  133. <i class="fas fa-question-circle"></i>
  134. </div>
  135. <div class="menu-item-content">
  136. <span class="menu-item-title">登录历史</span>
  137. </div>
  138. </div>
  139. </div>
  140. <div class="menu-divider"></div>
  141. <div class="menu-footer">
  142. <div class="menu-item danger" @click="handleLogout">
  143. <div class="menu-item-icon" style="background: rgba(239, 68, 68, 0.2); color: var(--danger);">
  144. <i class="fas fa-sign-out-alt"></i>
  145. </div>
  146. <div class="menu-item-content">
  147. <span class="menu-item-title">退出登录</span>
  148. </div>
  149. </div>
  150. </div>
  151. </div>
  152. </transition>
  153. </div>
  154. <!-- Help Modal -->
  155. <div v-if="showHelpModal" class="modal-overlay" @click.self="showHelpModal = false">
  156. <div class="modal">
  157. <div class="modal-header">
  158. <div class="modal-title"><i class="fas fa-question-circle"></i> 帮助中心</div>
  159. <button class="modal-close" @click="showHelpModal = false">
  160. <i class="fas fa-times"></i>
  161. </button>
  162. </div>
  163. <div class="modal-body">
  164. <div class="help-section">
  165. <h4>🚀 快速入门</h4>
  166. <div class="help-list">
  167. <div class="help-item">
  168. <i class="fas fa-brain"></i>
  169. <span>企业大脑 - 与AI对话,快速执行任务</span>
  170. </div>
  171. <div class="help-item">
  172. <i class="fas fa-crosshairs"></i>
  173. <span>自动寻客 - AI全网挖掘高匹配潜客</span>
  174. </div>
  175. <div class="help-item">
  176. <i class="fas fa-paper-plane"></i>
  177. <span>自动营销 - 多渠道自动化客户触达</span>
  178. </div>
  179. </div>
  180. </div>
  181. <div class="help-section">
  182. <h4>📞 联系支持</h4>
  183. <div class="contact-cards">
  184. <div class="contact-card">
  185. <i class="fas fa-envelope"></i>
  186. <div>
  187. <div class="contact-label">邮箱</div>
  188. <div class="contact-value">support@lingcunai.com</div>
  189. </div>
  190. </div>
  191. <div class="contact-card">
  192. <i class="fab fa-weixin"></i>
  193. <div>
  194. <div class="contact-label">微信</div>
  195. <div class="contact-value">领存智贸</div>
  196. </div>
  197. </div>
  198. </div>
  199. </div>
  200. </div>
  201. <div class="modal-footer">
  202. <button class="btn btn-secondary" @click="showHelpModal = false">关闭</button>
  203. <button class="btn btn-primary">
  204. <i class="fas fa-book"></i> 查看完整文档
  205. </button>
  206. </div>
  207. </div>
  208. </div>
  209. <!-- Click outside to close menu -->
  210. <div v-if="showUserMenu" class="menu-backdrop" @click="showUserMenu = false"></div>
  211. </aside>
  212. </template>
  213. <script setup>
  214. import { ref } from 'vue'
  215. import { useRoute, useRouter } from 'vue-router'
  216. const route = useRoute()
  217. const router = useRouter()
  218. const showUserMenu = ref(false)
  219. const showHelpModal = ref(false)
  220. const isDarkMode = ref(true)
  221. const toggleUserMenu = () => {
  222. showUserMenu.value = !showUserMenu.value
  223. }
  224. const goToSettings = (section) => {
  225. showUserMenu.value = false
  226. router.push('/settings')
  227. }
  228. const toggleTheme = () => {
  229. isDarkMode.value = !isDarkMode.value
  230. showUserMenu.value = false
  231. }
  232. const handleLogout = () => {
  233. showUserMenu.value = false
  234. // Handle logout
  235. console.log('Logout')
  236. }
  237. </script>
  238. <style scoped>
  239. .sidebar {
  240. width: 260px;
  241. background: var(--bg-card);
  242. border-right: 1px solid var(--border);
  243. display: flex;
  244. flex-direction: column;
  245. position: fixed;
  246. top: 0;
  247. left: 0;
  248. bottom: 0;
  249. z-index: 100;
  250. }
  251. .sidebar-header {
  252. padding: 20px;
  253. border-bottom: 1px solid var(--border);
  254. }
  255. .logo {
  256. display: flex;
  257. align-items: center;
  258. gap: 12px;
  259. }
  260. .logo-icon {
  261. width: 40px;
  262. height: 40px;
  263. background: var(--gradient-1);
  264. border-radius: 10px;
  265. display: flex;
  266. align-items: center;
  267. justify-content: center;
  268. font-size: 20px;
  269. }
  270. .logo-text {
  271. font-size: 18px;
  272. font-weight: 700;
  273. color: var(--text-primary);
  274. }
  275. .logo-subtitle {
  276. font-size: 11px;
  277. color: var(--text-secondary);
  278. }
  279. /* Navigation Menu */
  280. .nav-menu {
  281. flex: 1;
  282. overflow-y: auto;
  283. padding: 16px 12px;
  284. }
  285. .nav-section {
  286. margin-bottom: 20px;
  287. }
  288. .nav-section-title {
  289. font-size: 11px;
  290. font-weight: 600;
  291. color: var(--text-muted);
  292. text-transform: uppercase;
  293. letter-spacing: 0.5px;
  294. padding: 0 12px;
  295. margin-bottom: 8px;
  296. }
  297. .nav-item {
  298. display: flex;
  299. align-items: center;
  300. gap: 12px;
  301. padding: 10px 12px;
  302. border-radius: 8px;
  303. cursor: pointer;
  304. transition: all 0.2s;
  305. margin-bottom: 4px;
  306. color: var(--text-secondary);
  307. text-decoration: none;
  308. }
  309. .nav-item:hover {
  310. background: var(--bg-hover);
  311. color: var(--text-primary);
  312. }
  313. .nav-item.active {
  314. background: rgba(99, 102, 241, 0.2);
  315. color: var(--primary);
  316. }
  317. .nav-icon {
  318. width: 20px;
  319. font-size: 16px;
  320. }
  321. .nav-text {
  322. flex: 1;
  323. font-size: 13px;
  324. }
  325. .nav-badge {
  326. background: var(--danger);
  327. color: white;
  328. font-size: 10px;
  329. padding: 2px 6px;
  330. border-radius: 10px;
  331. font-weight: 600;
  332. }
  333. /* User Card */
  334. .sidebar-footer {
  335. padding: 12px;
  336. border-top: 1px solid var(--border);
  337. position: relative;
  338. }
  339. .user-card {
  340. display: flex;
  341. align-items: center;
  342. gap: 12px;
  343. padding: 12px;
  344. background: var(--bg-hover);
  345. border-radius: 12px;
  346. cursor: pointer;
  347. transition: all 0.2s;
  348. }
  349. .user-card:hover {
  350. background: var(--border);
  351. }
  352. .user-avatar-wrapper {
  353. position: relative;
  354. }
  355. .user-avatar {
  356. width: 40px;
  357. height: 40px;
  358. background: var(--gradient-1);
  359. border-radius: 50%;
  360. display: flex;
  361. align-items: center;
  362. justify-content: center;
  363. font-size: 16px;
  364. font-weight: 600;
  365. color: white;
  366. }
  367. .online-indicator {
  368. position: absolute;
  369. bottom: 0;
  370. right: 0;
  371. width: 12px;
  372. height: 12px;
  373. background: var(--success);
  374. border: 2px solid var(--bg-card);
  375. border-radius: 50%;
  376. }
  377. .user-info {
  378. flex: 1;
  379. }
  380. .user-name {
  381. font-size: 14px;
  382. font-weight: 600;
  383. }
  384. .user-status {
  385. display: flex;
  386. align-items: center;
  387. gap: 6px;
  388. font-size: 12px;
  389. color: var(--text-secondary);
  390. }
  391. .status-dot {
  392. width: 6px;
  393. height: 6px;
  394. background: var(--success);
  395. border-radius: 50%;
  396. }
  397. .user-arrow {
  398. color: var(--text-muted);
  399. font-size: 12px;
  400. transition: transform 0.2s;
  401. }
  402. .user-arrow.rotated {
  403. transform: rotate(180deg);
  404. }
  405. /* User Menu Dropdown */
  406. .menu-backdrop {
  407. position: fixed;
  408. top: 0;
  409. left: 0;
  410. right: 0;
  411. bottom: 0;
  412. z-index: 98;
  413. }
  414. .user-menu {
  415. position: absolute;
  416. bottom: 100%;
  417. left: 12px;
  418. right: 12px;
  419. margin-bottom: 8px;
  420. background: var(--bg-card);
  421. border: 1px solid var(--border);
  422. border-radius: 12px;
  423. box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3);
  424. z-index: 99;
  425. overflow: hidden;
  426. }
  427. .dropdown-enter-active,
  428. .dropdown-leave-active {
  429. transition: all 0.2s ease;
  430. }
  431. .dropdown-enter-from,
  432. .dropdown-leave-to {
  433. opacity: 0;
  434. transform: translateY(10px);
  435. }
  436. .menu-header {
  437. display: flex;
  438. align-items: center;
  439. gap: 12px;
  440. padding: 16px;
  441. background: var(--bg-hover);
  442. }
  443. .menu-avatar {
  444. width: 44px;
  445. height: 44px;
  446. background: var(--gradient-1);
  447. border-radius: 50%;
  448. display: flex;
  449. align-items: center;
  450. justify-content: center;
  451. font-size: 18px;
  452. font-weight: 600;
  453. color: white;
  454. }
  455. .menu-user-info {
  456. flex: 1;
  457. }
  458. .menu-user-name {
  459. font-size: 14px;
  460. font-weight: 600;
  461. }
  462. .menu-user-email {
  463. font-size: 12px;
  464. color: var(--text-secondary);
  465. }
  466. .menu-divider {
  467. height: 1px;
  468. background: var(--border);
  469. margin: 4px 0;
  470. }
  471. .menu-items {
  472. padding: 8px;
  473. }
  474. .menu-item {
  475. display: flex;
  476. align-items: center;
  477. gap: 12px;
  478. padding: 10px;
  479. border-radius: 8px;
  480. cursor: pointer;
  481. transition: background 0.2s;
  482. text-decoration: none;
  483. color: inherit;
  484. }
  485. .menu-item:hover {
  486. background: var(--bg-hover);
  487. }
  488. .menu-item.danger:hover {
  489. background: rgba(239, 68, 68, 0.1);
  490. }
  491. .menu-item.danger .menu-item-title {
  492. color: var(--danger);
  493. }
  494. .menu-item-icon {
  495. width: 36px;
  496. height: 36px;
  497. border-radius: 8px;
  498. display: flex;
  499. align-items: center;
  500. justify-content: center;
  501. font-size: 14px;
  502. }
  503. .menu-item-content {
  504. flex: 1;
  505. }
  506. .menu-item-title {
  507. display: block;
  508. font-size: 13px;
  509. font-weight: 500;
  510. }
  511. .menu-item-desc {
  512. display: block;
  513. font-size: 11px;
  514. color: var(--text-secondary);
  515. margin-top: 2px;
  516. }
  517. .menu-footer {
  518. padding: 8px;
  519. padding-top: 0;
  520. }
  521. /* Modal */
  522. .modal-overlay {
  523. position: fixed;
  524. top: 0;
  525. left: 0;
  526. right: 0;
  527. bottom: 0;
  528. background: rgba(0, 0, 0, 0.7);
  529. display: flex;
  530. align-items: center;
  531. justify-content: center;
  532. z-index: 1000;
  533. padding: 20px;
  534. }
  535. .modal {
  536. background: var(--bg-card);
  537. border-radius: 16px;
  538. width: 100%;
  539. max-width: 500px;
  540. overflow: hidden;
  541. }
  542. .modal-header {
  543. display: flex;
  544. justify-content: space-between;
  545. align-items: center;
  546. padding: 20px;
  547. border-bottom: 1px solid var(--border);
  548. }
  549. .modal-title {
  550. font-size: 16px;
  551. font-weight: 600;
  552. display: flex;
  553. align-items: center;
  554. gap: 10px;
  555. }
  556. .modal-title i {
  557. color: var(--primary);
  558. }
  559. .modal-close {
  560. width: 32px;
  561. height: 32px;
  562. background: var(--bg-hover);
  563. border: none;
  564. border-radius: 8px;
  565. color: var(--text-secondary);
  566. cursor: pointer;
  567. display: flex;
  568. align-items: center;
  569. justify-content: center;
  570. }
  571. .modal-close:hover {
  572. background: var(--border);
  573. color: var(--text-primary);
  574. }
  575. .modal-body {
  576. padding: 20px;
  577. }
  578. .modal-footer {
  579. display: flex;
  580. justify-content: flex-end;
  581. gap: 12px;
  582. padding: 20px;
  583. border-top: 1px solid var(--border);
  584. }
  585. /* Help Section */
  586. .help-section {
  587. margin-bottom: 20px;
  588. }
  589. .help-section:last-child {
  590. margin-bottom: 0;
  591. }
  592. .help-section h4 {
  593. font-size: 14px;
  594. font-weight: 600;
  595. margin-bottom: 12px;
  596. }
  597. .help-list {
  598. display: flex;
  599. flex-direction: column;
  600. gap: 8px;
  601. }
  602. .help-item {
  603. display: flex;
  604. align-items: center;
  605. gap: 10px;
  606. padding: 12px;
  607. background: var(--bg-hover);
  608. border-radius: 8px;
  609. font-size: 13px;
  610. }
  611. .help-item i {
  612. color: var(--primary);
  613. width: 20px;
  614. }
  615. .contact-cards {
  616. display: grid;
  617. grid-template-columns: repeat(2, 1fr);
  618. gap: 12px;
  619. }
  620. .contact-card {
  621. display: flex;
  622. align-items: center;
  623. gap: 12px;
  624. padding: 14px;
  625. background: var(--bg-hover);
  626. border-radius: 10px;
  627. }
  628. .contact-card i {
  629. font-size: 20px;
  630. color: var(--primary);
  631. }
  632. .contact-label {
  633. font-size: 11px;
  634. color: var(--text-muted);
  635. }
  636. .contact-value {
  637. font-size: 13px;
  638. font-weight: 500;
  639. }
  640. </style>