index-dataDiy.vue 46 KB

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