index.vue 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. <template>
  2. <div class="drive-page">
  3. <Header />
  4. <main class="drive-main">
  5. <section class="drive-hero">
  6. <div class="drive-hero__copy">
  7. <p class="drive-hero__eyebrow">DASHBOARD PORTAL</p>
  8. <p class="drive-hero__title">驾驶舱门户</p>
  9. <p class="drive-hero__desc">选择一个驾驶舱,快速进入对应业务看板。</p>
  10. </div>
  11. <div class="drive-hero__visual">
  12. <el-image :src="banner" class="drive-hero__image" />
  13. </div>
  14. </section>
  15. <section class="drive-tabs px-10">
  16. <button type="button" class="drive-tab drive-tab--active">
  17. 全部驾驶舱
  18. </button>
  19. <button type="button" class="drive-tab">经营管理</button>
  20. <button type="button" class="drive-tab">生产运营</button>
  21. <button type="button" class="drive-tab">财务管理</button>
  22. <button type="button" class="drive-tab">供应链管理</button>
  23. <button type="button" class="drive-tab">市场营销</button>
  24. <button type="button" class="drive-tab">QHSE</button>
  25. </section>
  26. <section class="drive-grid md:px-20">
  27. <button
  28. v-for="card in driveCards"
  29. :key="card.title"
  30. type="button"
  31. class="drive-card overflow-hidden"
  32. :style="{
  33. '--bg-image': `url(${card.pcBg})`,
  34. '--mobile-bg-image': `url(${card.mobileBg})`,
  35. }"
  36. @click="openDrive(card)"
  37. ></button>
  38. </section>
  39. </main>
  40. <div class="mt-[500px] md:mt-[300px]">
  41. <Footer />
  42. </div>
  43. </div>
  44. </template>
  45. <script setup lang="ts">
  46. import Header from "@components/home/header.vue";
  47. import Footer from "@components/home/Footer.vue";
  48. import { Icon } from "@iconify/vue";
  49. import { getMCSsoToken } from "@/api/user";
  50. import { useUserStore } from "@/stores/useUserStore";
  51. import { getAccessToken } from "@/utils/auth";
  52. import banner from "@/assets/images/drivebannere.png";
  53. import drivePc1 from "@/assets/images/dr1.png"; // 经营驾驶舱pc端背景图
  54. import drivePc2 from "@/assets/images/生产pc.png"; // 生产驾驶舱pc端背景图
  55. import drivePc3 from "@/assets/images/财务pc.png"; // 财务驾驶舱pc端背景图
  56. import drivePc4 from "@/assets/images/供应链pc.png"; // 供应链驾驶舱pc端背景图
  57. import drivePc5 from "@/assets/images/市场pc.png"; // 市场驾驶舱pc端背景图
  58. import drivePc6 from "@/assets/images/qhsepc.png"; // QHSE驾驶舱pc端背景图
  59. import driveMobile1 from "@/assets/images/mobile.png"; // 经营驾驶舱移动端背景图
  60. import driveMobile2 from "@/assets/images/生产驾驶舱.png"; // 生产驾驶舱移动端背景图
  61. import driveMobile3 from "@/assets/images/财务驾驶舱.png"; // 财务驾驶舱移动端背景图
  62. import driveMobile4 from "@/assets/images/供应链驾驶舱.png"; // 供应链驾驶舱移动端背景图
  63. import driveMobile5 from "@/assets/images/市场驾驶舱.png"; // 市场驾驶舱移动端背景图
  64. import driveMobile6 from "@/assets/images/QHSE驾驶舱.png"; // QHSE驾驶舱移动端背景图
  65. const userStore = useUserStore();
  66. type DriveCard = {
  67. title: string;
  68. description: string;
  69. url: string;
  70. bgColor: string;
  71. pcBg: string;
  72. mobileBg: string;
  73. };
  74. const driveCards: DriveCard[] = [
  75. {
  76. title: "经营驾驶舱",
  77. description: "查看经营分析、经营指标与执行情况。",
  78. url: "https://report.deepoil.cc/webroot/decision/v10/entry/access/9fb42908-894a-4373-a6be-ce046a42851d?preview=true&page_number=1",
  79. bgColor: "#3876e0",
  80. pcBg: drivePc1,
  81. mobileBg: driveMobile1,
  82. },
  83. {
  84. title: "生产驾驶舱",
  85. description: "查看生产运营态势、核心指标与执行情况。",
  86. url: "https://report.deepoil.cc/webroot/decision/v10/entry/access/dbc9cf73-81ce-43f1-9923-45cdfa5d5d3a?preview=true&page_number=1",
  87. bgColor: "#0f766e",
  88. pcBg: drivePc2,
  89. mobileBg: driveMobile2,
  90. },
  91. {
  92. title: "财务驾驶舱",
  93. description: "查看财务分析、预算执行与经营数据表现。",
  94. url: "https://report.deepoil.cc/webroot/decision/v10/entry/access/e836fb5b-092c-4d64-a324-3beeb4fac0cc?preview=true&page_number=1",
  95. bgColor: "#ca8a04",
  96. pcBg: drivePc3,
  97. mobileBg: driveMobile3,
  98. },
  99. {
  100. title: "供应链驾驶舱",
  101. description: "查看供应链分析、物料需求与执行。",
  102. url: "#",
  103. bgColor: "#7c3aed",
  104. pcBg: drivePc4,
  105. mobileBg: driveMobile4,
  106. },
  107. {
  108. title: "市场驾驶舱",
  109. description: "查看市场分析、销售数据与执行情况。",
  110. url: "#",
  111. bgColor: "#16a34a",
  112. pcBg: drivePc5,
  113. mobileBg: driveMobile5,
  114. },
  115. {
  116. title: "QHSE驾驶舱",
  117. description: "查看安全、健康、环境与质量数据。",
  118. url: "#",
  119. bgColor: "#dc2626",
  120. pcBg: drivePc6,
  121. mobileBg: driveMobile6,
  122. },
  123. ];
  124. const openDrive = async (option: DriveCard) => {
  125. if (userStore.getUser.username && getAccessToken()) {
  126. const res = await getMCSsoToken();
  127. if (res) {
  128. window.open(`${option.url}&ssoToken=${res}`, "_blank");
  129. }
  130. }
  131. };
  132. </script>
  133. <style scoped>
  134. .drive-page {
  135. min-height: 100vh;
  136. background:
  137. radial-gradient(circle at 50% 0%, rgba(30, 74, 255, 0.18), transparent 28%),
  138. radial-gradient(
  139. circle at 82% 18%,
  140. rgba(151, 66, 255, 0.16),
  141. transparent 18%
  142. ),
  143. linear-gradient(180deg, #000613 0%, #000613 100%);
  144. }
  145. .drive-main {
  146. max-width: 100vw;
  147. margin: 0 auto;
  148. padding-top: 50px;
  149. }
  150. .drive-hero {
  151. position: relative;
  152. min-height: 340px;
  153. overflow: hidden;
  154. background:
  155. linear-gradient(180deg, rgba(2, 8, 25, 0.55), rgba(2, 8, 25, 0.86)), #000613;
  156. box-shadow:
  157. 0 24px 60px rgba(0, 0, 0, 0.42),
  158. inset 0 1px 0 rgba(255, 255, 255, 0.04);
  159. }
  160. .drive-hero::before {
  161. content: "";
  162. position: absolute;
  163. inset: 0;
  164. background: linear-gradient(
  165. 90deg,
  166. rgba(0, 6, 19, 0.8) 0%,
  167. rgba(0, 6, 19, 0.24) 40%,
  168. rgba(0, 6, 19, 0.08) 100%
  169. );
  170. z-index: 1;
  171. }
  172. .drive-hero__copy {
  173. position: absolute;
  174. z-index: 2;
  175. left: 56px;
  176. top: 54px;
  177. max-width: 560px;
  178. }
  179. .drive-hero__eyebrow {
  180. margin: 0 0 16px;
  181. color: #6d77ff;
  182. font-size: 14px;
  183. font-weight: 700;
  184. letter-spacing: 0.22em;
  185. }
  186. .drive-hero__title {
  187. margin: 0;
  188. color: #f5f8ff;
  189. font-size: clamp(20px, 5vw, 50px);
  190. font-weight: 900;
  191. line-height: 1.08;
  192. text-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
  193. }
  194. .drive-hero__desc {
  195. margin: 20px 0 0;
  196. color: #5c6dc8;
  197. font-size: 18px;
  198. line-height: 1.8;
  199. }
  200. .drive-hero__visual {
  201. position: absolute;
  202. inset: 0;
  203. }
  204. .drive-hero__image {
  205. width: 100%;
  206. height: 100%;
  207. }
  208. .drive-hero__image :deep(img) {
  209. width: 100%;
  210. height: 100%;
  211. object-fit: cover;
  212. filter: saturate(1.1) contrast(1.05);
  213. }
  214. .drive-tabs {
  215. display: grid;
  216. grid-template-columns: repeat(7, minmax(0, 1fr));
  217. gap: 0;
  218. margin: 0 auto;
  219. padding: 12px 18px;
  220. width: 90%;
  221. border: 1px solid rgba(79, 110, 208, 0.16);
  222. border-radius: 10px;
  223. background: #070e24;
  224. box-shadow: 0 16px 34px rgba(0, 0, 0, 0.2);
  225. }
  226. .drive-tab {
  227. height: 58px;
  228. border: 0;
  229. border-right: 1px solid rgba(255, 255, 255, 0.06);
  230. background: transparent;
  231. color: rgba(220, 229, 255, 0.78);
  232. font-size: 18px;
  233. font-weight: 700;
  234. cursor: pointer;
  235. }
  236. .drive-tab:last-child {
  237. border-right: 0;
  238. }
  239. .drive-tab--active {
  240. color: #fff;
  241. position: relative;
  242. }
  243. .drive-tab--active::after {
  244. content: "";
  245. position: absolute;
  246. left: 50%;
  247. bottom: -12px;
  248. width: 72px;
  249. height: 4px;
  250. border-radius: 999px;
  251. transform: translateX(-50%);
  252. background: linear-gradient(90deg, #8f65ff 0%, #4d82ff 100%);
  253. box-shadow: 0 0 18px rgba(97, 111, 255, 0.85);
  254. }
  255. .drive-grid {
  256. display: grid;
  257. grid-template-columns: repeat(2, minmax(0, 1fr));
  258. gap: 22px;
  259. margin-top: 30px;
  260. }
  261. .drive-card {
  262. position: relative;
  263. display: flex;
  264. align-items: center;
  265. justify-content: center;
  266. width: 100%;
  267. height: 184px;
  268. /* 使用 CSS 变量动态绑定背景图 */
  269. background-image: var(--bg-image);
  270. background-size: contain;
  271. background-position: center;
  272. background-repeat: no-repeat;
  273. text-align: center;
  274. cursor: pointer;
  275. transition:
  276. transform 0.2s ease,
  277. box-shadow 0.2s ease,
  278. border-color 0.2s ease;
  279. overflow: hidden;
  280. margin-top: -50px;
  281. }
  282. .drive-card:hover {
  283. transform: translateY(-4px);
  284. border-color: rgba(115, 145, 255, 0.42);
  285. box-shadow: 0 28px 54px rgba(0, 0, 0, 0.42);
  286. }
  287. /* 补充缺失的内容样式,确保文字能显示在背景图上 */
  288. .drive-card__content {
  289. position: relative;
  290. z-index: 1;
  291. min-width: 0;
  292. flex: 1;
  293. /* 根据原设计可能需要调整文字颜色或背景遮罩以确保可读性 */
  294. }
  295. .drive-card__title {
  296. margin: 0;
  297. color: #f4f7ff;
  298. font-size: 28px;
  299. font-weight: 700;
  300. text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  301. }
  302. .drive-card__text {
  303. margin: 10px 0 0;
  304. color: rgba(191, 203, 235, 0.82);
  305. font-size: 16px;
  306. line-height: 1.7;
  307. text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  308. }
  309. .drive-card__arrow {
  310. position: relative;
  311. z-index: 1;
  312. color: rgba(210, 220, 248, 0.82);
  313. font-size: 34px;
  314. flex-shrink: 0;
  315. transition:
  316. transform 0.2s ease,
  317. color 0.2s ease;
  318. }
  319. .drive-card:hover .drive-card__arrow {
  320. color: #ffffff;
  321. transform: translate(2px, -2px);
  322. }
  323. @media (max-width: 768px) {
  324. .drive-main {
  325. padding: 50px 0px 56px;
  326. margin-top: 0;
  327. }
  328. .drive-hero {
  329. min-height: 260px;
  330. }
  331. .drive-hero__copy {
  332. left: 20px;
  333. right: 20px;
  334. top: 24px;
  335. }
  336. .drive-tabs {
  337. grid-template-columns: repeat(2, minmax(0, 1fr));
  338. }
  339. .drive-grid {
  340. grid-template-columns: 1fr;
  341. gap: 16px;
  342. padding-left: 0;
  343. }
  344. .drive-card {
  345. min-height: 100px;
  346. height: 100px; /* 修正原代码中 height: 0px 的问题,确保卡片有高度 */
  347. width: 100%; /* 修正原代码中 width: 100vw 可能导致溢出问题,通常用 100% */
  348. padding: 0;
  349. margin-top: 0;
  350. /* 使用 CSS 变量动态绑定移动端背景图 */
  351. background-image: var(--mobile-bg-image);
  352. background-size: contain;
  353. background-position: center center;
  354. }
  355. .drive-card__title {
  356. font-size: 20px;
  357. }
  358. .drive-hero__image :deep(img) {
  359. object-fit: cover;
  360. object-position: 68% center;
  361. }
  362. }
  363. </style>