index-dataDiy.vue 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537
  1. <template>
  2. <div class="jd-app" :class="{ 'expanded': !isSidebarCollapsed }">
  3. <!-- 👑 殿堂级左侧主导航抽屉栏 (折叠/展开动画) -->
  4. <div class="left-sidebar" :class="{ 'collapsed': isSidebarCollapsed }">
  5. <!-- 控制项:展开/收起 -->
  6. <div class="sidebar-item ctrl-item" @click="isSidebarCollapsed = !isSidebarCollapsed">
  7. <div class="item-icon-wrapper">
  8. <svg class="s-icon ctrl-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  9. <path d="M4 6h16M4 12h16M4 18h16" stroke-linecap="round" />
  10. </svg>
  11. </div>
  12. <span class="item-text">{{ isSidebarCollapsed ? '展开' : '收起' }}</span>
  13. </div>
  14. <!-- 菜单项列表 -->
  15. <div class="sidebar-menu-list">
  16. <!-- 首页 (无子菜单) -->
  17. <div class="sidebar-item active">
  18. <div class="item-icon-wrapper">
  19. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  20. <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" stroke-linecap="round" stroke-linejoin="round" />
  21. <polyline points="9 22 9 12 15 12 15 22" stroke-linecap="round" stroke-linejoin="round" />
  22. </svg>
  23. </div>
  24. <span class="item-text">首页</span>
  25. </div>
  26. <!-- 工作台 (无子菜单) -->
  27. <div class="sidebar-item">
  28. <div class="item-icon-wrapper">
  29. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  30. <rect x="2" y="3" width="20" height="14" rx="2" stroke-linecap="round" stroke-linejoin="round" />
  31. <line x1="8" y1="21" x2="16" y2="21" stroke-linecap="round" />
  32. <line x1="12" y1="17" x2="12" y2="21" stroke-linecap="round" />
  33. </svg>
  34. </div>
  35. <span class="item-text">{{ isSidebarCollapsed ? '工作台' : '采购工作台' }}</span>
  36. </div>
  37. <!-- 采购单管理 -->
  38. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.purchase }" @click="toggleMenu('purchase')">
  39. <div class="item-icon-wrapper">
  40. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  41. <path d="M9 11l3 3L22 4" stroke-linecap="round" stroke-linejoin="round" />
  42. <path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" stroke-linecap="round" stroke-linejoin="round" />
  43. </svg>
  44. </div>
  45. <span class="item-text">{{ isSidebarCollapsed ? '采购单' : '采购单管理' }}</span>
  46. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  47. <polyline points="6 9 12 15 18 9" />
  48. </svg>
  49. <!-- 窄栏折叠悬停二级菜单 (通用 absolute 气泡弹出,完美卡合在对应项右侧) -->
  50. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  51. <div class="sub-item">
  52. 我的购物车
  53. <span class="cart-badge">1</span>
  54. </div>
  55. <div class="sub-item">我的采购单</div>
  56. <div class="sub-item">清单选品</div>
  57. <div class="sub-item">我的收藏</div>
  58. </div>
  59. </div>
  60. <!-- 二级子菜单 -->
  61. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.purchase }">
  62. <div class="sub-item">
  63. 我的购物车
  64. <span class="cart-badge">1</span>
  65. </div>
  66. <div class="sub-item">我的采购单</div>
  67. <div class="sub-item">清单选品</div>
  68. <div class="sub-item">我的收藏</div>
  69. </div>
  70. <!-- 非招标采购 -->
  71. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.nonTender }" @click="toggleMenu('nonTender')">
  72. <div class="item-icon-wrapper">
  73. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  74. <rect x="3" y="7" width="18" height="13" rx="2" stroke-linecap="round" stroke-linejoin="round" />
  75. <path d="M20 7h-9M14 3L7 21" stroke-linecap="round" />
  76. </svg>
  77. </div>
  78. <span class="item-text">非招标采购</span>
  79. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  80. <polyline points="6 9 12 15 18 9" />
  81. </svg>
  82. <!-- 折叠悬停二级菜单 -->
  83. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  84. <div class="sub-item">竞价采购</div>
  85. </div>
  86. </div>
  87. <!-- 二级子菜单 -->
  88. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.nonTender }">
  89. <div class="sub-item">竞价采购</div>
  90. </div>
  91. <!-- 订单管理 -->
  92. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.order }" @click="toggleMenu('order')">
  93. <div class="item-icon-wrapper">
  94. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  95. <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke-linecap="round" stroke-linejoin="round" />
  96. <polyline points="14 2 14 8 20 8" stroke-linecap="round" stroke-linejoin="round" />
  97. <line x1="16" y1="13" x2="8" y2="13" stroke-linecap="round" />
  98. <line x1="16" y1="17" x2="8" y2="17" stroke-linecap="round" />
  99. </svg>
  100. </div>
  101. <span class="item-text">{{ isSidebarCollapsed ? '订单' : '订单管理' }}</span>
  102. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  103. <polyline points="6 9 12 15 18 9" />
  104. </svg>
  105. <!-- 折叠悬停二级菜单 -->
  106. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  107. <div class="sub-item">我的订单</div>
  108. <div class="sub-item">订单打印</div>
  109. </div>
  110. </div>
  111. <!-- 二级子菜单 -->
  112. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.order }">
  113. <div class="sub-item">我的订单</div>
  114. <div class="sub-item">订单打印</div>
  115. </div>
  116. <!-- 发票管理 -->
  117. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.invoice }" @click="toggleMenu('invoice')">
  118. <div class="item-icon-wrapper">
  119. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  120. <rect x="2" y="4" width="20" height="16" rx="2" stroke-linecap="round" stroke-linejoin="round" />
  121. <line x1="12" y1="4" x2="12" y2="20" stroke-linecap="round" />
  122. <line x1="2" y1="12" x2="22" y2="12" stroke-linecap="round" />
  123. </svg>
  124. </div>
  125. <span class="item-text">{{ isSidebarCollapsed ? '发票' : '发票管理' }}</span>
  126. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  127. <polyline points="6 9 12 15 18 9" />
  128. </svg>
  129. <!-- 折叠悬停二级菜单 -->
  130. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  131. <div class="sub-item">普票抬头管理</div>
  132. <div class="sub-item">开具发票</div>
  133. </div>
  134. </div>
  135. <!-- 二级子菜单 -->
  136. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.invoice }">
  137. <div class="sub-item">普票抬头管理</div>
  138. <div class="sub-item">开具发票</div>
  139. </div>
  140. <!-- 售后管理 -->
  141. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.afterSale }" @click="toggleMenu('afterSale')">
  142. <div class="item-icon-wrapper">
  143. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  144. <path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67" stroke-linecap="round" stroke-linejoin="round" />
  145. </svg>
  146. </div>
  147. <span class="item-text">{{ isSidebarCollapsed ? '售后' : '售后管理' }}</span>
  148. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  149. <polyline points="6 9 12 15 18 9" />
  150. </svg>
  151. <!-- 折叠悬停二级菜单 -->
  152. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  153. <div class="sub-item">退换货</div>
  154. <div class="sub-item">售后记录</div>
  155. </div>
  156. </div>
  157. <!-- 二级子菜单 -->
  158. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.afterSale }">
  159. <div class="sub-item">退换货</div>
  160. <div class="sub-item">售后记录</div>
  161. </div>
  162. <!-- 财务管理 -->
  163. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.finance }" @click="toggleMenu('finance')">
  164. <div class="item-icon-wrapper">
  165. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  166. <circle cx="12" cy="12" r="10" stroke-linecap="round" stroke-linejoin="round" />
  167. <path d="M12 8V16M8 12h8" stroke-linecap="round" stroke-linejoin="round" />
  168. </svg>
  169. </div>
  170. <span class="item-text">{{ isSidebarCollapsed ? '财务' : '财务管理' }}</span>
  171. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  172. <polyline points="6 9 12 15 18 9" />
  173. </svg>
  174. <!-- 折叠悬停二级菜单 -->
  175. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  176. <div class="sub-item">结算中心</div>
  177. <div class="sub-item">自助认款</div>
  178. <div class="sub-item">合并支付</div>
  179. <div class="sub-item">企业结算</div>
  180. <div class="sub-item">企业金采</div>
  181. <div class="sub-item">金采报销</div>
  182. <div class="sub-item">商家结算</div>
  183. <div class="sub-item">我的余额</div>
  184. </div>
  185. </div>
  186. <!-- 二级子菜单 -->
  187. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.finance }">
  188. <div class="sub-item">结算中心</div>
  189. <div class="sub-item">自助认款</div>
  190. <div class="sub-item">合并支付</div>
  191. <div class="sub-item">企业结算</div>
  192. <div class="sub-item">企业金采</div>
  193. <div class="sub-item">金采报销</div>
  194. <div class="sub-item">商家结算</div>
  195. <div class="sub-item">我的余额</div>
  196. </div>
  197. <!-- 数据中心 -->
  198. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.dataCenter }" @click="toggleMenu('dataCenter')">
  199. <div class="item-icon-wrapper">
  200. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  201. <line x1="18" y1="20" x2="18" y2="10" stroke-linecap="round" stroke-linejoin="round" />
  202. <line x1="12" y1="20" x2="12" y2="4" stroke-linecap="round" stroke-linejoin="round" />
  203. <line x1="6" y1="20" x2="6" y2="14" stroke-linecap="round" stroke-linejoin="round" />
  204. </svg>
  205. </div>
  206. <span class="item-text">{{ isSidebarCollapsed ? '数据' : '数据中心' }}</span>
  207. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  208. <polyline points="6 9 12 15 18 9" />
  209. </svg>
  210. <!-- 折叠悬停二级菜单 -->
  211. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  212. <div class="sub-item">下载中心</div>
  213. <div class="sub-item">数据报表</div>
  214. <div class="sub-item">明细数据报表</div>
  215. </div>
  216. </div>
  217. <!-- 二级子菜单 -->
  218. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.dataCenter }">
  219. <div class="sub-item">下载中心</div>
  220. <div class="sub-item">数据报表</div>
  221. <div class="sub-item">明细数据报表</div>
  222. </div>
  223. <!-- 地址管理 -->
  224. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.address }" @click="toggleMenu('address')">
  225. <div class="item-icon-wrapper">
  226. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  227. <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" stroke-linecap="round" stroke-linejoin="round" />
  228. <circle cx="12" cy="10" r="3" stroke-linecap="round" stroke-linejoin="round" />
  229. </svg>
  230. </div>
  231. <span class="item-text">{{ isSidebarCollapsed ? '地址' : '地址管理' }}</span>
  232. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  233. <polyline points="6 9 12 15 18 9" />
  234. </svg>
  235. <!-- 折叠悬停二级菜单 -->
  236. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  237. <div class="sub-item">我的地址</div>
  238. </div>
  239. </div>
  240. <!-- 二级子菜单 -->
  241. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.address }">
  242. <div class="sub-item">我的地址</div>
  243. </div>
  244. <!-- 账号安全 -->
  245. <div class="sidebar-item has-sub" :class="{ 'sub-open': openMenus.security }" @click="toggleMenu('security')">
  246. <div class="item-icon-wrapper">
  247. <svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  248. <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" stroke-linecap="round" stroke-linejoin="round" />
  249. </svg>
  250. </div>
  251. <span class="item-text">{{ isSidebarCollapsed ? '安全' : '账号安全' }}</span>
  252. <svg class="arrow-icon" v-if="!isSidebarCollapsed" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  253. <polyline points="6 9 12 15 18 9" />
  254. </svg>
  255. <!-- 折叠悬停二级菜单 -->
  256. <div class="sidebar-hover-pop" v-if="isSidebarCollapsed">
  257. <div class="sub-item">账号设置</div>
  258. <div class="sub-item">绑定员工</div>
  259. </div>
  260. </div>
  261. <!-- 二级子菜单 -->
  262. <div class="sidebar-sub-menu" v-if="!isSidebarCollapsed" :class="{ 'show': openMenus.security }">
  263. <div class="sub-item">账号设置</div>
  264. <div class="sub-item">绑定员工</div>
  265. </div>
  266. </div>
  267. </div>
  268. <!-- 👑 殿堂级右侧悬浮挂条 -->
  269. <div class="right-toolbar">
  270. <!-- 采购单 (悬停时呈现为纯大红背景 58x58,图2完美复刻) -->
  271. <div class="toolbar-item selection-item">
  272. <!-- 购物车微型数字红圈角标 -->
  273. <div class="cart-badge">5</div>
  274. <div class="toolbar-icon-wrapper">
  275. <svg class="t-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  276. <circle cx="9" cy="21" r="1" />
  277. <circle cx="20" cy="21" r="1" />
  278. <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6" />
  279. </svg>
  280. </div>
  281. <span class="toolbar-text">采购单</span>
  282. </div>
  283. <!-- 企业消息 (悬停时呈现为纯大红背景 58x58,图3完美复刻) -->
  284. <div class="toolbar-item msg-item">
  285. <div class="toolbar-icon-wrapper">
  286. <svg class="t-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  287. <path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.73 21a2 2 0 0 1-3.46 0" stroke-linecap="round" stroke-linejoin="round" />
  288. </svg>
  289. </div>
  290. <span class="toolbar-text">消息</span>
  291. </div>
  292. <!-- 我的客服 (悬停时呈现为纯大红背景 58x58,并向左滑出精致气泡面板,图4完美复刻) -->
  293. <div class="toolbar-item service-item">
  294. <div class="toolbar-icon-wrapper">
  295. <svg class="t-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  296. <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
  297. <circle cx="12" cy="7" r="4" />
  298. </svg>
  299. </div>
  300. <span class="toolbar-text">客服</span>
  301. <!-- 👑 精致高保真客服浮空对话框 (图4一比一完美复刻) -->
  302. <div class="service-popover">
  303. <div class="pop-title">企业采购在线客服</div>
  304. <div class="pop-action">
  305. <svg class="pop-chat-icon" viewBox="0 0 24 24" fill="currentColor">
  306. <path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 9h12v2H6V9zm8 5H6v-2h8v2zm4-6H6V6h12v2z" />
  307. </svg>
  308. 点击咨询
  309. </div>
  310. </div>
  311. </div>
  312. <!-- 回到顶部 (悬停时呈现为纯大红背景 58x58,图5完美复刻) -->
  313. <div class="toolbar-item back-top-item" @click="scrollToTop">
  314. <div class="toolbar-icon-wrapper" style="margin-bottom: 0 !important; height: 18px">
  315. <svg class="t-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
  316. <polyline points="18 15 12 9 6 15" />
  317. </svg>
  318. </div>
  319. </div>
  320. </div>
  321. <!-- 1. 顶部 Header (Logo, 搜索) -->
  322. <JDHeader :userInfo="userInfo" />
  323. <!-- 2. 核心 Banner 区域 -->
  324. <section class="banner-area w">
  325. <!-- 右侧主内容区域,霸占 1600px 全宽 -->
  326. <div class="banner-layout flex">
  327. <!-- 左侧大列 (导航 + 分类与广告) -->
  328. <div class="main-column flex-1 flex-column">
  329. <!-- 顶部的导航条 (尺寸为1040*48px,采用图2的简洁横向设计) -->
  330. <div class="nav-bar">
  331. <!-- 左滑按钮 -->
  332. <button v-show="showLeftNavBtn" class="nav-scroll-btn left-btn" @click="scrollNav('left')">
  333. <svg viewBox="0 0 24 24" class="scroll-arrow">
  334. <path d="M15 19l-7-7 7-7" stroke="currentColor" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round" />
  335. </svg>
  336. </button>
  337. <div class="nav-bar-scroll-wrapper" ref="navScrollRef" @scroll="checkNavScroll">
  338. <ul class="nav-list">
  339. <template v-for="(item, index) in navItems" :key="index">
  340. <li :class="{ active: index === 0 }" @click="onPath(item.linkUrl)">
  341. {{ item.title }}
  342. </li>
  343. <span class="nav-divider" v-if="Number(index) < navItems.length - 1">|</span>
  344. </template>
  345. </ul>
  346. </div>
  347. <!-- 右滑按钮 -->
  348. <button v-show="showRightNavBtn" class="nav-scroll-btn right-btn" @click="scrollNav('right')">
  349. <svg viewBox="0 0 24 24" class="scroll-arrow">
  350. <path d="M9 5l7 7-7 7" stroke="currentColor" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round" />
  351. </svg>
  352. </button>
  353. </div>
  354. <!-- 下方:分类与广告栏并排 -->
  355. <div class="banner-bottom flex flex-1">
  356. <!-- 左侧分类菜单 (常驻显示,尺寸不变) -->
  357. <aside class="side-category">
  358. <JDCategory />
  359. </aside>
  360. <!-- 右侧广告组合 -->
  361. <div class="ad-group flex-1">
  362. <JDBannerCards />
  363. </div>
  364. </div>
  365. </div>
  366. <!-- 右侧大列:高奢重构两段式布局 (281 * 400px,分为上下两个部分,中间间隔 16px) -->
  367. <div class="user-sidebar">
  368. <JDUserPanel :userInfo="userInfo" />
  369. <div class="purchase-classroom">
  370. <div class="classroom-header">
  371. <span class="classroom-title">采购课堂</span>
  372. <span class="classroom-more">查看全部</span>
  373. </div>
  374. <div class="classroom-content">
  375. <div class="classroom-time">
  376. <span class="c-year">2026年</span>
  377. <span class="c-week">第 21 周</span>
  378. </div>
  379. <div class="classroom-info">
  380. <p class="c-desc">防洪防汛特辑 | 工厂园区篇</p>
  381. </div>
  382. <div class="classroom-cover">
  383. <img src="@/assets/data/classroom_cover.png" alt="课程封面" />
  384. </div>
  385. </div>
  386. </div>
  387. </div>
  388. </div>
  389. </section>
  390. <!-- 3. 下方模块 -->
  391. <JDSceneRed />
  392. <JDProducts />
  393. </div>
  394. </template>
  395. <script setup lang="ts">
  396. import JDHeader from '@/views/home/datacomponents/JDHeader.vue';
  397. import JDCategory from '@/views/home/datacomponents/JDCategory.vue';
  398. import JDBannerCards from '@/views/home/datacomponents/JDBannerCards.vue';
  399. import JDUserPanel from '@/views/home/datacomponents/JDUserPanel.vue';
  400. import JDSceneRed from '@/views/home/datacomponents/JDSceneRed.vue';
  401. import JDProducts from '@/views/home/datacomponents/JDProducts.vue';
  402. import '@/views/home/datacomponents/jd-repro.css';
  403. import { headerCategoryList } from '@/api/home/index-data';
  404. import { getInfo } from '@/api/login';
  405. import { computed } from 'vue';
  406. import { onPath } from '@/utils/siteConfig';
  407. const userInfo = ref<any>({});
  408. getInfo().then((res) => {
  409. if (res.code == 200) {
  410. userInfo.value = res.data;
  411. }
  412. });
  413. const navItems = ref<any>([]);
  414. headerCategoryList({}).then((res) => {
  415. if (res.code == 200) {
  416. document.documentElement.style.setProperty('--hover-data3', res.rows.length > 0 ? res.rows[0].headerThemeColor || '#E7000B' : '#E7000B');
  417. navItems.value = res.rows;
  418. }
  419. });
  420. const isSidebarCollapsed = ref(true);
  421. // 一二级子菜单的高保真展开折叠状态管理 (默认展开图2、图3中所有可展开的项,且地址、账号默认关闭符合图2初始态)
  422. const openMenus = ref({
  423. purchase: true, // 采购单管理,默认展开
  424. nonTender: false, // 非招标采购,默认闭合 (图2为闭合,小箭头向下)
  425. order: true, // 订单管理,默认展开
  426. invoice: true, // 发票管理,默认展开
  427. afterSale: true, // 售后管理,默认展开
  428. finance: true, // 财务管理,默认展开
  429. dataCenter: true, // 数据中心,默认展开
  430. address: false, // 地址管理,图2为闭合,图3为展开
  431. security: false // 账号安全,图2为闭合,图3为展开
  432. });
  433. // 通用子菜单展开/闭合切换处理器,带窄栏时自动展宽逻辑
  434. const toggleMenu = (key) => {
  435. if (isSidebarCollapsed.value) {
  436. isSidebarCollapsed.value = false;
  437. openMenus.value[key] = true;
  438. } else {
  439. openMenus.value[key] = !openMenus.value[key];
  440. }
  441. };
  442. // 完美向后兼容原先对采购单管理展开状态的引用
  443. const isPurchaseMenuOpen = computed(() => openMenus.value.purchase);
  444. const handlePurchaseClick = () => toggleMenu('purchase');
  445. const scrollToTop = () => {
  446. window.scrollTo({ top: 0, behavior: 'smooth' });
  447. };
  448. const isLargeScreen = ref(window.innerWidth >= 1600);
  449. const adHovered = ref(false);
  450. const check = () => {
  451. isLargeScreen.value = window.innerWidth >= 1600;
  452. };
  453. const navScrollRef = ref(null);
  454. const showLeftNavBtn = ref(false);
  455. const showRightNavBtn = ref(false);
  456. const checkNavScroll = () => {
  457. if (!navScrollRef.value) return;
  458. const { scrollLeft, scrollWidth, clientWidth } = navScrollRef.value;
  459. showLeftNavBtn.value = scrollLeft > 5;
  460. showRightNavBtn.value = scrollWidth - clientWidth - scrollLeft > 5;
  461. };
  462. const scrollNav = (direction) => {
  463. if (!navScrollRef.value) return;
  464. const amount = 200;
  465. if (direction === 'left') {
  466. navScrollRef.value.scrollLeft -= amount;
  467. } else {
  468. navScrollRef.value.scrollLeft += amount;
  469. }
  470. setTimeout(checkNavScroll, 300);
  471. };
  472. const showSceneCat = ref(false);
  473. onMounted(() => {
  474. window.addEventListener('resize', check);
  475. window.addEventListener('resize', checkNavScroll);
  476. setTimeout(checkNavScroll, 100);
  477. });
  478. onUnmounted(() => {
  479. window.removeEventListener('resize', check);
  480. window.removeEventListener('resize', checkNavScroll);
  481. });
  482. </script>
  483. <style scoped>
  484. /* ==================== 💎 全局版心控制 (最小 1072px 宽度,最大 1600px 宽度) ==================== */
  485. .w {
  486. width: calc(100% - 180px) !important;
  487. max-width: 1600px !important;
  488. min-width: 1072px !important;
  489. margin-left: auto !important;
  490. margin-right: auto !important;
  491. box-sizing: border-box !important;
  492. }
  493. .jd-app {
  494. width: 100%;
  495. background: #f8f8f8;
  496. min-height: 100vh;
  497. padding-left: 0 !important; /* 彻底不占用右侧适配宽度空间,保持右侧主体版心完全垂直居中 */
  498. box-sizing: border-box;
  499. }
  500. .jd-app.expanded {
  501. padding-left: 0 !important;
  502. }
  503. /* ==================== 👑 左侧主导航抽屉栏样式 ==================== */
  504. .left-sidebar {
  505. position: fixed;
  506. left: 0;
  507. top: 44px; /* 完美贴紧 44px 顶栏下沿,吸顶固定 */
  508. height: calc(100vh - 44px);
  509. width: 150px !important; /* 展开宽度锁定为 150px */
  510. background: #fafafa;
  511. border-right: 1px solid #eaeaea;
  512. box-shadow: 2px 0 12px rgba(0, 0, 0, 0.03);
  513. z-index: 99999;
  514. display: flex;
  515. flex-direction: column;
  516. box-sizing: border-box;
  517. transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  518. padding-top: 10px; /* 顶部保留微小精致间距,让展开顶格展示 */
  519. }
  520. .left-sidebar.collapsed {
  521. width: 54px !important; /* 折叠宽度锁定为 54px */
  522. overflow: visible !important;
  523. }
  524. /* 顶部控制栏 */
  525. .ctrl-item {
  526. border-bottom: 1px solid #eaeaea;
  527. margin-bottom: 8px;
  528. cursor: pointer;
  529. }
  530. .ctrl-item:hover .ctrl-icon {
  531. transform: rotate(90deg);
  532. }
  533. .ctrl-icon {
  534. transition: transform 0.3s ease;
  535. }
  536. /* 通用项 (展开状态下一级菜单) */
  537. .sidebar-item {
  538. height: 40px !important; /* 展开状态下主菜单单项高度设为 40px */
  539. padding: 0 12px !important; /* 缩减 padding 以适配 150px 的精致宽度 */
  540. display: flex;
  541. align-items: center;
  542. color: #333333 !important; /* 一级菜单默认字体颜色为高级深黑 (图2) */
  543. cursor: pointer;
  544. position: relative;
  545. transition: all 0.2s ease;
  546. box-sizing: border-box;
  547. margin: 2px 8px !important; /* 背景高亮内缩,留出精致边距 (一比一图2) */
  548. border-radius: 6px !important; /* 精致圆角高亮,拒绝生硬直角 */
  549. }
  550. .left-sidebar.collapsed .sidebar-item {
  551. height: 52px !important; /* 折叠状态下,为 54px 宽度匹配更紧致的 52px 高度 */
  552. padding: 0 !important;
  553. flex-direction: column !important;
  554. justify-content: center !important;
  555. align-items: center !important;
  556. width: 46px !important; /* 窄栏下宽度稍内缩,以匹配 margin */
  557. margin: 3px 4px !important; /* 折叠下精致间距 */
  558. border-radius: 6px !important;
  559. }
  560. /* 图标容器 (高度统一的淡橘红色) */
  561. .item-icon-wrapper {
  562. display: flex;
  563. align-items: center;
  564. justify-content: center;
  565. width: 20px;
  566. height: 20px;
  567. margin-right: 8px !important; /* 缩短图标与文字间距 */
  568. color: #ef5350 !important; /* 默认一级菜单图标采用高度一致、极其精致的定制红粉色 (图2) */
  569. transition: color 0.2s ease;
  570. }
  571. .left-sidebar.collapsed .item-icon-wrapper {
  572. margin-right: 0 !important;
  573. margin-bottom: 3px !important;
  574. color: #ef5350 !important;
  575. }
  576. .s-icon {
  577. width: 18px;
  578. height: 18px;
  579. }
  580. /* 文字 */
  581. .item-text {
  582. font-size: 14px !important; /* 主菜单文字大小锁定为 14px */
  583. font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif !important; /* 字体锁定为图4 */
  584. color: #333333 !important; /* 主菜单默认字体颜色为图2深黑 */
  585. white-space: nowrap;
  586. opacity: 1;
  587. transition: opacity 0.2s ease;
  588. }
  589. .left-sidebar.collapsed .item-text {
  590. font-size: 12px !important; /* 折叠菜单文字大小锁定为 12px (图2) */
  591. font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif !important; /* 字体锁定为图2 */
  592. color: #000000d1 !important; /* 折叠菜单默认字体颜色为 #000000D1 (图2) */
  593. font-weight: normal !important;
  594. max-width: 38px !important; /* 限制最大宽度,正好使“非招标采购”精准折行成“非招标”和“采购” */
  595. white-space: normal !important; /* 允许换行 (图2) */
  596. text-align: center !important; /* 居中对齐 */
  597. line-height: 1.2 !important; /* 精致窄行高 */
  598. display: block !important;
  599. }
  600. /* 展开状态右侧小箭头 */
  601. .arrow-icon {
  602. position: absolute;
  603. right: 12px;
  604. width: 12px;
  605. height: 12px;
  606. color: #999;
  607. transition: transform 0.3s ease;
  608. }
  609. .sub-open .arrow-icon {
  610. transform: rotate(180deg);
  611. color: #e1251b !important; /* 展开时小箭头高亮亮红 */
  612. }
  613. /* 列表容器 */
  614. .sidebar-menu-list {
  615. flex: 1;
  616. overflow-y: auto;
  617. scrollbar-width: none;
  618. }
  619. .sidebar-menu-list::-webkit-scrollbar {
  620. display: none;
  621. }
  622. /* 折叠窄栏状态下,列表容器允许悬浮窗溢出显示,防截断 */
  623. .left-sidebar.collapsed .sidebar-menu-list {
  624. overflow: visible !important;
  625. }
  626. /* ==================== 👑 窄栏折叠悬停二级菜单 (图2) ==================== */
  627. .sidebar-hover-pop {
  628. position: absolute !important;
  629. left: 54px !important; /* 完美卡合在对应项右侧 54px */
  630. top: 0 !important; /* 精准与当前被悬停的一级项高度平齐 */
  631. width: 140px !important; /* 宽度锁定为 140px */
  632. background: #ffffff !important; /* 纯白底色 (图4) */
  633. border: 1px solid #eaeaea !important; /* 精致灰色细边框 (图4) */
  634. border-radius: 8px !important; /* 优雅圆角 */
  635. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important; /* 高级微弱阴影 */
  636. display: none !important;
  637. flex-direction: column !important;
  638. padding: 6px 0 !important;
  639. z-index: 100000 !important;
  640. box-sizing: border-box !important;
  641. }
  642. /* 窄栏折叠悬停二级弹出面板的左侧透明桥梁热区,消除 4px 悬空空隙,保证鼠标能丝滑移入点击 */
  643. .sidebar-hover-pop::before {
  644. content: '' !important;
  645. position: absolute !important;
  646. left: -16px !important; /* 向左延伸 16px 热区,完美覆盖 4px 间隙 */
  647. top: 0 !important;
  648. width: 16px !important;
  649. height: 100% !important;
  650. background: transparent !important; /* 彻底透明,无形保护 */
  651. cursor: pointer !important;
  652. }
  653. /* 折叠窄栏状态下,强力释放侧边栏、菜单列表与单项的所有溢出裁剪限制,保驾气泡弹窗 */
  654. .left-sidebar.collapsed,
  655. .left-sidebar.collapsed .sidebar-menu-list,
  656. .left-sidebar.collapsed .sidebar-item {
  657. overflow: visible !important;
  658. }
  659. /* 窄栏折叠状态下,hover 项时 100% 毫无悬念地浮现 pop (采用 fixed 定位傲立于最顶层,无视任何父级 transition/裁剪限制) */
  660. /* 窄栏折叠状态下,hover 项时 100% 毫无悬念地以相对绝对定位浮现 pop */
  661. .left-sidebar.collapsed .sidebar-item:hover .sidebar-hover-pop {
  662. display: flex !important;
  663. }
  664. /* 窄栏折叠二级菜单子项样式 */
  665. .left-sidebar.collapsed .sidebar-hover-pop .sub-item {
  666. height: 36px !important; /* 与二级菜单一致的高度 */
  667. padding: 0 14px !important;
  668. display: flex !important;
  669. align-items: center !important;
  670. justify-content: space-between !important; /* 撑开以把红徽章放到最右侧 */
  671. font-size: 14px !important;
  672. color: #666666 !important; /* 二级菜单默认灰色 */
  673. transition: all 0.2s ease !important;
  674. white-space: nowrap !important;
  675. box-sizing: border-box !important;
  676. background: transparent !important;
  677. margin: 1px 6px !important;
  678. border-radius: 4px !important;
  679. }
  680. .left-sidebar.collapsed .sidebar-hover-pop .sub-item:hover {
  681. background: #fff2f2 !important; /* 悬停高亮淡粉背景 */
  682. color: #e1251b !important; /* 悬停高亮字色 */
  683. }
  684. /* 二级菜单红色气泡徽章 */
  685. .left-sidebar.collapsed .sidebar-hover-pop .cart-badge {
  686. background: #e1251b !important;
  687. color: #fff !important;
  688. font-size: 11px !important;
  689. font-weight: bold !important;
  690. height: 16px !important;
  691. min-width: 16px !important;
  692. padding: 0 4px !important;
  693. border-radius: 8px !important;
  694. display: flex !important;
  695. align-items: center !important;
  696. justify-content: center !important;
  697. box-sizing: border-box !important;
  698. }
  699. /* hover 悬停项样式 (一比一图2/图4浅粉高亮,无红粗线条) */
  700. .sidebar-item:hover {
  701. background: #fff2f2 !important;
  702. color: #e1251b !important;
  703. }
  704. .sidebar-item:hover .item-icon-wrapper {
  705. color: #e1251b !important;
  706. }
  707. .sidebar-item:hover .item-text {
  708. color: #e1251b !important;
  709. }
  710. /* 菜单项激活高亮样式(图2选中效果,纯浅粉背景,去掉左侧红粗线) */
  711. .sidebar-item.active {
  712. background: #fff2f2 !important;
  713. color: #e1251b !important;
  714. }
  715. .sidebar-item.active .item-icon-wrapper {
  716. color: #e1251b !important;
  717. }
  718. .sidebar-item.active .item-text {
  719. color: #e1251b !important;
  720. font-weight: bold !important; /* 加粗 */
  721. }
  722. .sidebar-item.active::before {
  723. display: none !important; /* 彻底去除左侧红线,还原图2最完美的高保真侧边 */
  724. }
  725. /* 二级子菜单包裹器 */
  726. .sidebar-sub-menu {
  727. max-height: 0;
  728. overflow: hidden;
  729. background: #fafafa; /* 升级为与展开底色相同的典雅纯净灰白 */
  730. transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  731. box-sizing: border-box;
  732. }
  733. .sidebar-sub-menu.show {
  734. max-height: 400px; /* 大幅扩充 max-height 以支持多子项菜单 (如财务管理) 的顺滑完全展开 */
  735. border-bottom: 1px solid #eaeaea;
  736. }
  737. /* 二级子菜单项样式 (一比一完美锁定图2、图5) */
  738. .sub-item {
  739. height: 36px !important; /* 更加精致紧凑的高度 */
  740. padding-left: 36px !important; /* 缩减缩进,保证在 150px 极窄侧边栏下绝对防折行 */
  741. display: flex;
  742. align-items: center;
  743. font-size: 14px !important; /* 子菜单文字大小锁定为 14px */
  744. font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif !important; /* 字体锁定为图5 */
  745. color: #666666 !important; /* 子菜单默认文字颜色为深灰色 #666666 */
  746. cursor: pointer;
  747. position: relative;
  748. transition: all 0.2s ease;
  749. white-space: nowrap;
  750. box-sizing: border-box;
  751. margin: 1px 8px !important; /* 与一级菜单对齐的内缩设计 */
  752. border-radius: 4px !important; /* 精致圆角 */
  753. }
  754. .sub-item:hover {
  755. color: #e1251b !important;
  756. background: #fff2f2 !important; /* 悬停应用高品质浅粉背景 */
  757. }
  758. /* 购物车数字徽章 */
  759. .cart-badge {
  760. background: #e1251b !important;
  761. color: #fff !important;
  762. font-size: 11px !important;
  763. font-weight: bold !important;
  764. height: 16px !important;
  765. min-width: 16px !important;
  766. padding: 0 4px !important;
  767. border-radius: 8px !important;
  768. display: flex !important;
  769. align-items: center !important;
  770. justify-content: center !important;
  771. margin-left: 8px !important;
  772. box-sizing: border-box !important;
  773. }
  774. /* ==================== 👑 右侧悬浮挂条样式 ==================== */
  775. .right-toolbar {
  776. position: fixed !important;
  777. right: 9px !important; /* 精致美化滚动条通常为 8px 宽,设置 9px 可在滑动条左侧精密保留 1px 的极致工艺缝隙 (图1) */
  778. top: 50% !important;
  779. transform: translateY(-50%) !important;
  780. width: 58px !important; /* 宽度锁定为 58px */
  781. background: #ffffff !important;
  782. border: 1px solid #eaeaea !important; /* 精致全封闭灰色细边框 (图1) */
  783. border-radius: 8px !important; /* 药丸全包圆角 */
  784. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important;
  785. z-index: 99999 !important;
  786. display: flex !important;
  787. flex-direction: column !important;
  788. align-items: center !important;
  789. padding: 0 !important; /* 零内边距以保证 58x58 的项完全贴合 */
  790. box-sizing: border-box !important;
  791. }
  792. .toolbar-item {
  793. width: 100% !important; /* 自适应 100% 宽度,完美填充满 58px(含边框)容器的内部,绝不溢出 */
  794. height: 58px !important; /* 单个按钮的背景高度锁定为 58px */
  795. display: flex !important;
  796. flex-direction: column !important;
  797. align-items: center !important;
  798. justify-content: center !important;
  799. cursor: pointer !important;
  800. position: relative !important;
  801. transition: all 0.2s ease !important;
  802. color: #1a1a1a !important; /* 图2规范高保真 #1A1A1A 深沉黑 */
  803. background: #ffffff !important;
  804. margin-bottom: 0 !important; /* 无缝紧密拼合 */
  805. box-sizing: border-box !important;
  806. }
  807. .toolbar-item:last-child {
  808. margin-bottom: 0 !important;
  809. }
  810. /* 👑 清单选品:普通状态下带有透明红色的淡粉渐变,Hover 悬停高亮为大红背景 (图1、2完美复刻) */
  811. .toolbar-item.selection-item {
  812. background: linear-gradient(180deg, rgba(225, 37, 27, 0.06) 0%, rgba(225, 37, 27, 0) 100%) !important; /* 超精美淡红渐变 */
  813. border-radius: 7px 7px 0 0 !important; /* 顶部圆角贴合外层盒子 */
  814. }
  815. .toolbar-item.selection-item:hover {
  816. background: #e1251b !important; /* 悬停大红背景 */
  817. }
  818. .toolbar-item.selection-item:hover .toolbar-text {
  819. color: #ffffff !important; /* 纯白文字 */
  820. }
  821. .toolbar-icon-wrapper {
  822. display: flex !important;
  823. align-items: center !important;
  824. justify-content: center !important;
  825. width: 24px !important;
  826. height: 24px !important;
  827. margin-bottom: 2px !important;
  828. position: relative !important;
  829. }
  830. .t-icon {
  831. width: 18px !important;
  832. height: 18px !important;
  833. transition:
  834. transform 0.2s ease,
  835. color 0.2s ease !important;
  836. }
  837. .toolbar-text {
  838. font-size: 12px !important; /* 精准死锁图2要求的 12px 大小 */
  839. font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif !important;
  840. font-weight: 500 !important;
  841. transition: color 0.2s ease !important;
  842. color: #1a1a1a !important; /* 精准死锁图2要求的 #1A1A1A 深黑色 */
  843. text-align: center !important;
  844. line-height: 1.25 !important;
  845. }
  846. /* 采购单、消息、客服:Hover 悬停时呈现为 58x58 纯大红背景 */
  847. .toolbar-item.selection-item:hover,
  848. .toolbar-item.msg-item:hover,
  849. .toolbar-item.service-item:hover {
  850. background: #e1251b !important;
  851. color: #ffffff !important;
  852. }
  853. .toolbar-item.selection-item:hover .t-icon,
  854. .toolbar-item.msg-item:hover .t-icon,
  855. .toolbar-item.service-item:hover .t-icon {
  856. color: #ffffff !important;
  857. transform: scale(1.1) !important;
  858. }
  859. .toolbar-item.selection-item:hover .toolbar-text,
  860. .toolbar-item.msg-item:hover .toolbar-text,
  861. .toolbar-item.service-item:hover .toolbar-text {
  862. color: #ffffff !important;
  863. }
  864. /* 👑 购物车微型数字红圈角标 (图2完美复刻) */
  865. .cart-badge {
  866. position: absolute !important;
  867. top: 4px !important;
  868. right: 10px !important; /* 精确定位在购物车图标右上角,图2完美高保真 */
  869. background: #e1251b !important;
  870. color: #ffffff !important;
  871. font-size: 10px !important;
  872. font-weight: bold !important;
  873. min-width: 14px !important;
  874. height: 14px !important;
  875. border-radius: 7px !important; /* 微型完美正圆胶囊 */
  876. display: flex !important;
  877. align-items: center !important;
  878. justify-content: center !important;
  879. padding: 0 4px !important;
  880. border: 1px solid #ffffff !important; /* 精致白边增强立体悬浮感 */
  881. box-shadow: 0 1px 4px rgba(225, 37, 27, 0.35) !important;
  882. z-index: 10 !important;
  883. line-height: 1 !important;
  884. box-sizing: border-box !important;
  885. }
  886. /* 👑 精致高保真客服浮空对话框样式 (图2高端重塑,极大提升商务大气度) */
  887. .service-popover {
  888. position: absolute !important;
  889. right: 68px !important; /* 距右侧有 10px 气浮空隙 */
  890. top: 50% !important;
  891. transform: translateY(-50%) translateX(10px) !important;
  892. width: 168px !important; /* 宽度拓宽到 168px,极其大气清爽 */
  893. background: #ffffff !important;
  894. border: 1px solid #eaeaea !important;
  895. border-radius: 8px !important; /* 更加圆润大气的 8px 圆角 */
  896. box-shadow: 0 6px 24px rgba(0, 0, 0, 0.09) !important; /* 升级为更细腻的高端投影 */
  897. padding: 14px 16px !important; /* 内边距加宽,充满开阔空间感 */
  898. display: flex !important;
  899. flex-direction: column !important;
  900. align-items: center !important;
  901. justify-content: center !important;
  902. z-index: 100000 !important;
  903. pointer-events: auto !important;
  904. opacity: 0 !important;
  905. visibility: hidden !important;
  906. transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
  907. }
  908. /* 悬浮在客服项上时弹出气泡 */
  909. .toolbar-item.service-item:hover .service-popover {
  910. opacity: 1 !important;
  911. visibility: visible !important;
  912. transform: translateY(-50%) translateX(0) !important;
  913. }
  914. /* 旋转45度正方形描边小尖角 */
  915. .service-popover::after {
  916. content: '' !important;
  917. position: absolute !important;
  918. right: -5px !important;
  919. top: 50% !important;
  920. transform: translateY(-50%) rotate(45deg) !important;
  921. width: 8px !important;
  922. height: 8px !important;
  923. background: #ffffff !important;
  924. border-right: 1px solid #eaeaea !important;
  925. border-top: 1px solid #eaeaea !important;
  926. }
  927. .pop-title {
  928. font-size: 13px !important; /* 标题字号升级为大气的 13px */
  929. color: #333333 !important; /* 深灰色更显高级沉稳,绝不受父级 Hover 继承白色的影响 */
  930. font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif !important;
  931. font-weight: 600 !important; /* 加粗展现气场 */
  932. margin-bottom: 8px !important;
  933. white-space: nowrap !important;
  934. line-height: 1.3 !important;
  935. }
  936. .pop-action {
  937. width: 100% !important;
  938. height: 30px !important;
  939. background: rgba(225, 37, 27, 0.05) !important; /* 精致淡红背景 */
  940. border: 1px solid rgba(225, 37, 27, 0.15) !important; /* 精美细圆角边框 */
  941. border-radius: 15px !important; /* 高端胶囊按钮样式 */
  942. display: flex !important;
  943. align-items: center !important;
  944. justify-content: center !important;
  945. gap: 6px !important;
  946. color: #e1251b !important; /* 默认优易红,绝不受父级 Hover 影响 */
  947. font-size: 12px !important;
  948. font-weight: bold !important;
  949. cursor: pointer !important;
  950. transition: all 0.2s ease !important;
  951. box-sizing: border-box !important;
  952. white-space: nowrap !important;
  953. }
  954. /* 按钮 Hover 时高亮变大红 */
  955. .pop-action:hover {
  956. background: #e1251b !important;
  957. color: #ffffff !important;
  958. border-color: #e1251b !important;
  959. }
  960. .pop-action:hover .pop-chat-icon {
  961. fill: #ffffff !important;
  962. }
  963. .pop-chat-icon {
  964. width: 14px !important;
  965. height: 14px !important;
  966. fill: #e1251b !important;
  967. transition: fill 0.2s ease !important;
  968. }
  969. /* 回到顶部项:Hover 悬停时呈 58x58 纯大红背景,底部圆角贴合外层盒子 (图5完美复刻) */
  970. .toolbar-item.back-top-item {
  971. border-top: 1px solid #f0f0f0 !important;
  972. border-radius: 0 0 7px 7px !important; /* 底部圆角贴合外层 */
  973. }
  974. .toolbar-item.back-top-item:hover {
  975. background: #e1251b !important;
  976. }
  977. .toolbar-item.back-top-item:hover .t-icon {
  978. color: #ffffff !important;
  979. transform: translateY(-2px) !important;
  980. }
  981. .banner-area {
  982. margin-top: 10px;
  983. position: relative;
  984. background: #fff;
  985. border-radius: 12px;
  986. z-index: 5;
  987. display: flex;
  988. height: 460px;
  989. transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  990. }
  991. /* 极简式大图广告容器,初始 84px 宽,高度撑满 */
  992. .expand-ad-layer {
  993. position: absolute;
  994. left: -84px;
  995. top: 10px;
  996. width: 84px;
  997. height: calc(100% - 20px);
  998. z-index: 100; /* 未展开时层级一般 */
  999. overflow: hidden;
  1000. border-radius: 12px;
  1001. transition:
  1002. width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
  1003. z-index 0s 0.3s;
  1004. cursor: pointer;
  1005. background: transparent;
  1006. }
  1007. /* 悬停时跃升为 9999 皇帝级图层,完美盖死右侧任何弹窗! */
  1008. .expand-ad-layer:hover {
  1009. width: 790px;
  1010. z-index: 9999;
  1011. border-radius: 12px;
  1012. box-shadow: 6px 10px 30px rgba(0, 0, 0, 0.3);
  1013. transition:
  1014. width 0.3s cubic-bezier(0.4, 0, 0.2, 1),
  1015. z-index 0s 0s;
  1016. }
  1017. /* 一整张原生的大图片,定死 790px 宽 */
  1018. .expand-img-full {
  1019. position: absolute;
  1020. left: 0;
  1021. top: 0;
  1022. width: 790px;
  1023. height: 100%;
  1024. object-fit: cover;
  1025. z-index: 1;
  1026. }
  1027. /* 悬浮在图片最左侧的透明文案区,等同于图片本身 */
  1028. .ad-left-text {
  1029. position: absolute;
  1030. left: 0;
  1031. top: 0;
  1032. width: 84px;
  1033. height: 100%;
  1034. display: flex;
  1035. flex-direction: column;
  1036. align-items: center;
  1037. justify-content: center;
  1038. z-index: 5;
  1039. pointer-events: none;
  1040. background: #047038; /* 用深绿色背景完美遮盖原大图左侧边缘自带的蓝色渐变发光 */
  1041. border-radius: 12px 0 0 12px; /* 保持与容器的左侧圆角一致 */
  1042. }
  1043. .deco-inner-white {
  1044. background: #fff;
  1045. width: 60px;
  1046. border-radius: 30px;
  1047. padding: 20px 0;
  1048. display: flex;
  1049. flex-direction: column;
  1050. align-items: center;
  1051. justify-content: center;
  1052. margin-bottom: 15px;
  1053. }
  1054. .d-txt {
  1055. writing-mode: vertical-lr;
  1056. color: #2cb356;
  1057. font-weight: bold;
  1058. font-size: 16px;
  1059. letter-spacing: 2px;
  1060. }
  1061. .d-num {
  1062. font-size: 26px;
  1063. color: #2cb356;
  1064. font-weight: 900;
  1065. margin: 5px 0;
  1066. }
  1067. .play-btn {
  1068. width: 30px;
  1069. height: 30px;
  1070. background: #e1251b;
  1071. border-radius: 50%;
  1072. display: flex;
  1073. align-items: center;
  1074. justify-content: center;
  1075. }
  1076. .triangle {
  1077. width: 0;
  1078. height: 0;
  1079. border-top: 5px solid transparent;
  1080. border-bottom: 5px solid transparent;
  1081. border-left: 8px solid #fff;
  1082. margin-left: 3px;
  1083. }
  1084. .banner-layout {
  1085. height: 100%;
  1086. width: 100%;
  1087. display: flex;
  1088. gap: 16px !important;
  1089. }
  1090. /* 主体列 */
  1091. .main-column {
  1092. display: flex;
  1093. flex-direction: column;
  1094. overflow: visible;
  1095. min-width: 0;
  1096. }
  1097. /* 导航条样式 (图2高保真 1040*48px 浅灰圆角设计) */
  1098. .nav-bar {
  1099. height: 48px;
  1100. background: #f7f8fc;
  1101. border: 1px solid #f7f8fc;
  1102. border-radius: 8px;
  1103. position: relative;
  1104. box-sizing: border-box;
  1105. width: 100%;
  1106. max-width: none !important; /* 确保能跟底下的模块完美对齐且不被1040宽限制限制死 */
  1107. display: flex;
  1108. align-items: center;
  1109. padding: 0; /* 留出空间给轨道自占 */
  1110. overflow: visible;
  1111. }
  1112. .nav-bar-scroll-wrapper {
  1113. flex: 1;
  1114. overflow-x: auto;
  1115. scroll-behavior: smooth;
  1116. display: flex;
  1117. align-items: center;
  1118. height: 100%;
  1119. padding: 0 12px; /* 恒定紧凑内边距,取消按钮盖字与动态状态类的偶合 */
  1120. box-sizing: border-box;
  1121. }
  1122. .nav-bar-scroll-wrapper::-webkit-scrollbar {
  1123. display: none;
  1124. }
  1125. .nav-bar-scroll-wrapper {
  1126. scrollbar-width: none;
  1127. -ms-overflow-style: none;
  1128. }
  1129. .nav-scroll-btn {
  1130. flex-shrink: 0; /* 强力防挤压变形 */
  1131. width: 28px;
  1132. height: 28px;
  1133. background: rgba(255, 255, 255, 0.95);
  1134. border: 1px solid #e2e8f0;
  1135. border-radius: 50%;
  1136. display: flex;
  1137. align-items: center;
  1138. justify-content: center;
  1139. cursor: pointer;
  1140. box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
  1141. z-index: 10;
  1142. transition: all 0.2s ease;
  1143. padding: 0;
  1144. }
  1145. .nav-scroll-btn:hover {
  1146. background: #ffffff;
  1147. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  1148. }
  1149. .nav-scroll-btn.left-btn {
  1150. margin-left: 8px;
  1151. margin-right: 4px;
  1152. }
  1153. .nav-scroll-btn.right-btn {
  1154. margin-right: 8px;
  1155. margin-left: 4px;
  1156. }
  1157. .scroll-arrow {
  1158. width: 16px;
  1159. height: 16px;
  1160. color: #64748b;
  1161. }
  1162. .nav-list {
  1163. display: flex;
  1164. align-items: center;
  1165. height: 100%;
  1166. margin: 0;
  1167. padding: 0;
  1168. list-style: none;
  1169. white-space: nowrap;
  1170. }
  1171. .nav-list li {
  1172. flex-shrink: 0;
  1173. font-size: 16px;
  1174. font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
  1175. font-weight: bold;
  1176. cursor: pointer;
  1177. white-space: nowrap;
  1178. display: flex;
  1179. align-items: center;
  1180. color: #000000;
  1181. height: 100%;
  1182. transition: color 0.15s ease;
  1183. }
  1184. .nav-list li.active {
  1185. color: #000000;
  1186. font-weight: bold;
  1187. }
  1188. .nav-list li:hover {
  1189. color: var(--hover-data3);
  1190. }
  1191. .nav-divider {
  1192. flex-shrink: 0;
  1193. color: #d3d3d3;
  1194. margin: 0 20px;
  1195. font-size: 14px;
  1196. user-select: none;
  1197. }
  1198. /* 下方分类与广告 */
  1199. .banner-bottom {
  1200. display: flex;
  1201. flex: 1;
  1202. overflow: visible;
  1203. padding: 0 0 10px 0 !important;
  1204. gap: 12px;
  1205. background: transparent;
  1206. position: relative;
  1207. }
  1208. .side-category {
  1209. width: 215px;
  1210. height: 400px;
  1211. background: transparent;
  1212. overflow: visible;
  1213. position: relative;
  1214. z-index: 1000;
  1215. }
  1216. .side-category.is-dropdown {
  1217. position: absolute;
  1218. top: 0;
  1219. bottom: 10px; /* 补偿 banner-bottom 的 10px 底部 padding */
  1220. left: 0; /* padding已去除,归零以完美左对齐 */
  1221. z-index: 9999;
  1222. box-shadow: 4px 8px 24px rgba(0, 0, 0, 0.15);
  1223. }
  1224. .ad-group {
  1225. display: flex;
  1226. flex-direction: column;
  1227. overflow: hidden;
  1228. height: 100%;
  1229. }
  1230. /* 右侧高奢两段式侧边栏 */
  1231. .user-sidebar {
  1232. display: flex;
  1233. flex-direction: column;
  1234. gap: 16px;
  1235. width: 281px;
  1236. flex-shrink: 0;
  1237. box-sizing: border-box;
  1238. }
  1239. /* 采购课堂卡片 */
  1240. .purchase-classroom {
  1241. width: 281px;
  1242. height: 116px;
  1243. background: #f7f8fc;
  1244. border: 1px solid #f7f8fc;
  1245. border-radius: 12px;
  1246. box-sizing: border-box;
  1247. padding: 10px 12px;
  1248. display: flex;
  1249. flex-direction: column;
  1250. justify-content: flex-start;
  1251. overflow: hidden;
  1252. box-shadow: 0 4px 10px rgba(0, 0, 0, 0.02);
  1253. }
  1254. .classroom-header {
  1255. display: flex;
  1256. justify-content: space-between;
  1257. align-items: center;
  1258. margin-bottom: 8px;
  1259. }
  1260. .classroom-title {
  1261. font-size: 14px;
  1262. font-weight: 800;
  1263. color: #1a1a1a;
  1264. }
  1265. .classroom-more {
  1266. font-size: 12px;
  1267. color: #999999;
  1268. cursor: pointer;
  1269. transition: color 0.2s ease;
  1270. }
  1271. .classroom-more:hover {
  1272. color: #e1251b;
  1273. }
  1274. .classroom-content {
  1275. display: flex;
  1276. align-items: center;
  1277. gap: 10px;
  1278. flex: 1;
  1279. background: #ffffff;
  1280. border-radius: 8px;
  1281. padding: 6px 8px;
  1282. box-sizing: border-box;
  1283. cursor: pointer;
  1284. transition: all 0.2s ease;
  1285. }
  1286. .classroom-content:hover {
  1287. transform: translateY(-2px);
  1288. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  1289. }
  1290. .classroom-content:hover .c-desc {
  1291. color: #e1251b;
  1292. }
  1293. .classroom-time {
  1294. background: #fff5f5;
  1295. border: 1px solid #ffe3e3;
  1296. border-radius: 6px;
  1297. padding: 2px 4px;
  1298. display: flex;
  1299. flex-direction: column;
  1300. align-items: center;
  1301. justify-content: center;
  1302. flex-shrink: 0;
  1303. width: 58px;
  1304. box-sizing: border-box;
  1305. }
  1306. .c-year {
  1307. font-size: 10px;
  1308. color: #8c8c8c;
  1309. }
  1310. .c-week {
  1311. font-size: 10px;
  1312. font-weight: 800;
  1313. color: #ff5a5f;
  1314. margin-top: 1px;
  1315. }
  1316. .classroom-info {
  1317. display: flex;
  1318. align-items: center;
  1319. min-width: 0;
  1320. }
  1321. .c-desc {
  1322. font-size: 12px;
  1323. font-weight: bold;
  1324. color: #333333;
  1325. line-height: 1.4;
  1326. margin: 0;
  1327. display: -webkit-box;
  1328. -webkit-line-clamp: 2;
  1329. -webkit-box-orient: vertical;
  1330. overflow: hidden;
  1331. transition: color 0.2s ease;
  1332. }
  1333. .classroom-cover {
  1334. width: 48px;
  1335. height: 48px;
  1336. border-radius: 6px;
  1337. overflow: hidden;
  1338. flex-shrink: 0;
  1339. border: 1px solid #f0f0f0;
  1340. }
  1341. .classroom-cover img {
  1342. width: 100%;
  1343. height: 100%;
  1344. object-fit: cover;
  1345. }
  1346. /* 👑 1. 外层白色大底框卡片:四周锁死黄金 16px 呼吸留白内边距,总高为 432px,内容区高度为完美闭合的 400px */
  1347. .banner-area {
  1348. padding: 16px !important;
  1349. height: 432px !important;
  1350. box-sizing: border-box !important;
  1351. }
  1352. /* 👑 2. 下方内容容器:消除多重边距实现绝对的四角对齐填满,并将左侧分类与右侧广告间隙拉开至 16px */
  1353. .banner-bottom {
  1354. padding: 0 !important;
  1355. gap: 16px !important;
  1356. }
  1357. /* 👑 3. 顶部分类导航:浅灰色圆角背景盒,并向右平移 231px 完美与左侧分类框错开 */
  1358. .nav-bar {
  1359. margin-left: 231px !important;
  1360. width: auto !important; /* 宽度设为自适应,随着主容器收缩 */
  1361. max-width: none !important; /* 彻底去除宽度上限以确保与下方广告右边缘完美齐平 */
  1362. height: 48px !important;
  1363. padding: 0 24px !important;
  1364. background: #f7f8fc !important;
  1365. border: 1px solid #f7f8fc !important;
  1366. border-radius: 8px !important;
  1367. box-sizing: border-box !important;
  1368. margin-bottom: 16px !important; /* 与下方内容拉开 16px 间距,使左侧分类栏使用 -64px margin-top 恰好完美顶部平齐 */
  1369. flex-grow: 1 !important; /* 自动撑满 */
  1370. }
  1371. /* 👑 4. 左侧垂直分类区域:高能向上爬升 64px 与顶栏完美并肩对齐,高度补齐到完美的 400px,宽度锁死不缩小 */
  1372. .side-category {
  1373. margin-top: -64px !important;
  1374. width: 215px !important;
  1375. height: 400px !important;
  1376. position: relative !important;
  1377. z-index: 1000 !important;
  1378. flex-shrink: 0 !important; /* 强制不压缩,保持常驻尺寸 */
  1379. }
  1380. /* 使得左侧垂直分类的4个角承接 12px 的大厂大圆角,和横向导航与整体卡片无缝贴合 */
  1381. .side-category :deep(.cate-list) {
  1382. border-radius: 12px !important;
  1383. }
  1384. /* 👑 5. 右侧两段式侧边栏:宽度强制281px,对齐中间导航条顶部,上下间距 16px,宽度锁死不缩小 */
  1385. .user-sidebar {
  1386. width: 281px !important;
  1387. height: 400px !important;
  1388. margin-top: 0 !important;
  1389. display: flex !important;
  1390. flex-direction: column !important;
  1391. gap: 16px !important;
  1392. margin-right: 0 !important;
  1393. flex-shrink: 0 !important; /* 强制不压缩,保持常驻尺寸 */
  1394. }
  1395. /* ==================== 💎 全局上下滚动条高奢美化 ==================== */
  1396. ::-webkit-scrollbar {
  1397. width: 8px !important; /* 宽度从原生 17px 缩窄到极其精致的 8px */
  1398. height: 8px !important; /* 横向滚动条高度 */
  1399. }
  1400. ::-webkit-scrollbar-track {
  1401. background: rgba(0, 0, 0, 0.01) !important; /* 轨道极浅半透明,完全杜绝原生灰色的大块感 */
  1402. border-radius: 4px !important;
  1403. }
  1404. ::-webkit-scrollbar-thumb {
  1405. background: rgba(0, 0, 0, 0.16) !important; /* 胶囊滑块轻量扁平灰,极具高级拟物呼吸感 */
  1406. border-radius: 4px !important;
  1407. transition: background 0.3s ease !important;
  1408. }
  1409. ::-webkit-scrollbar-thumb:hover {
  1410. background: rgba(0, 0, 0, 0.32) !important; /* Hover 时滑块变深灰色,清晰明朗 */
  1411. }
  1412. /* 👑 各个核心板块之间的 16px 恒定垂直呼吸间距保护 */
  1413. .scene-red-integrated {
  1414. margin-top: 16px !important;
  1415. }
  1416. .products-section {
  1417. margin-top: 16px !important;
  1418. }
  1419. </style>