GameIndex.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. <template>
  2. <!-- 游戏页面 -->
  3. <div class="home-container">
  4. <!-- 展开收起侧边栏 -->
  5. <div class="sidebar-container">
  6. <div class="sidebar-layout">
  7. <div
  8. class="icon-expand"
  9. :style="{
  10. backgroundColor: drawerVisible ? '#44449c' : '#7F70C840',
  11. left: drawerVisible ? '18%' : '0'
  12. }"
  13. @click="toggleDrawer"
  14. >
  15. <span
  16. class="vertical-lines"
  17. :style="{
  18. color: drawerVisible ? '#8a78d0' : 'white'
  19. }"
  20. >||</span
  21. >
  22. </div>
  23. </div>
  24. <transition name="drawer-slide">
  25. <div class="main-content" v-if="drawerVisible">
  26. <!-- 菜单栏 -->
  27. <div class="drawer-box">
  28. <el-row class="tac">
  29. <el-col :span="12">
  30. <span class="mb-2">
  31. <img :src="teachingImg" alt="游戏" />
  32. 游戏列表
  33. </span>
  34. <el-menu
  35. default-active="1"
  36. :class="{ 'el-menu-vertical-demo': true }"
  37. >
  38. <el-menu-item
  39. v-for="(title, index) in gameTitles"
  40. :key="index + 1"
  41. :index="(index + 1).toString()"
  42. @click="goToGame(gameData[index])"
  43. >
  44. {{ title }}
  45. </el-menu-item>
  46. </el-menu>
  47. </el-col>
  48. </el-row>
  49. </div>
  50. </div>
  51. </transition>
  52. </div>
  53. <div class="content-box">
  54. <div class="box-1">
  55. <div class="inner-box left-box">
  56. <div class="box-icon" @click="goBack">
  57. <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
  58. {{ pageTitle }}
  59. </div>
  60. <!-- 下拉菜单已移除 -->
  61. </div>
  62. <div class="inner-box right-box">
  63. <div class="top-right-box">
  64. <el-autocomplete
  65. v-model="SearchInput"
  66. :fetch-suggestions="querySearch"
  67. placeholder="搜索游戏"
  68. @select="handleSearchSelect"
  69. class="search-input"
  70. value-key="typeName"
  71. :trigger-on-focus="false"
  72. :key="searchKey"
  73. >
  74. <template #prefix>
  75. <el-icon class="el-input__icon"><search /></el-icon>
  76. </template>
  77. <!-- 下拉项模板 -->
  78. <template #default="{ item }">
  79. <div class="scrollbar">
  80. <!-- 序号和标题 -->
  81. {{ item.gameSort }} {{ item.typeName }}
  82. </div>
  83. </template>
  84. </el-autocomplete>
  85. </div>
  86. </div>
  87. </div>
  88. <div class="box-2">
  89. <div
  90. class="small-box"
  91. v-for="(game, index) in gameData"
  92. :key="index"
  93. @click="goToGame(game)"
  94. >
  95. <div
  96. class="nested-box"
  97. :style="{
  98. backgroundImage: `url(${game.gameImage})`,
  99. backgroundSize: 'cover'
  100. }"
  101. ></div>
  102. <div class="additional-text">
  103. {{ game.gameSort }} {{ game.typeName }}
  104. </div>
  105. </div>
  106. </div>
  107. </div>
  108. </div>
  109. </template>
  110. <script setup>
  111. import { ref, onMounted, computed } from 'vue'
  112. // Element Plus 组件引入
  113. import { ArrowDown, Search, ArrowLeftBold } from '@element-plus/icons-vue'
  114. import { useRouter } from 'vue-router'
  115. import teachingImg from '@/assets/icon/teaching.png'
  116. // 引入游戏列表接口
  117. import { GameList } from '@/api/game/game.js'
  118. // 获取当前路由对象
  119. const router = useRouter()
  120. // 页面标题
  121. const pageTitle = ref('返回虚拟实验室')
  122. // 抽屉显示状态
  123. const drawerVisible = ref(true)
  124. // 游戏数据
  125. const gameData = ref([])
  126. // 获取游戏列表
  127. onMounted(() => {
  128. GameList().then(res => {
  129. // 根据接口返回的数据结构
  130. if (res && res.data) {
  131. console.log(res);
  132. // 处理返回的数据
  133. gameData.value = res.data.list.map(item => {
  134. let sortNum = item.sort || 0;
  135. sortNum = sortNum > 9 ? sortNum : "0" + sortNum;
  136. return {
  137. id: item.id,
  138. typeName: item.name,
  139. gameImage: item.mapBackground,
  140. gameSort: sortNum
  141. };
  142. })
  143. // 重新渲染搜索组件
  144. searchKey.value = Date.now()
  145. }
  146. }).catch(error => {
  147. console.error('获取游戏列表失败:', error)
  148. })
  149. })
  150. // 切换抽屉显示状态的函数
  151. const toggleDrawer = () => {
  152. drawerVisible.value = !drawerVisible.value
  153. }
  154. // 游戏标题数组
  155. const gameTitles = computed(() => {
  156. return gameData.value.map(item => {
  157. return `${item.gameSort} ${item.typeName}`;
  158. });
  159. })
  160. // 搜索框
  161. const SearchInput = ref('')
  162. // 用于强制重新渲染搜索组件的key
  163. const searchKey = ref(Date.now())
  164. // 搜索建议查询方法
  165. const querySearch = (queryString, cb) => {
  166. const results = queryString
  167. ? gameData.value.filter(item => {
  168. // 游戏标题和序号查询
  169. return item.typeName.toLowerCase().includes(queryString.toLowerCase()) ||
  170. item.gameSort.includes(queryString)
  171. })
  172. : gameData.value
  173. cb(results)
  174. }
  175. // 搜索选择处理方法
  176. const handleSearchSelect = item => {
  177. goToGame(item)
  178. // 清空输入框
  179. SearchInput.value = ''
  180. }
  181. // 返回上一页
  182. const goBack = () => {
  183. router.go(-1)
  184. }
  185. // 跳转到游戏页面
  186. const goToGame = game => {
  187. router.push({
  188. path: '/mapGame',
  189. query: { gameId: game.id, gameName: game.typeName }
  190. })
  191. }
  192. </script>
  193. <style scoped lang="scss">
  194. @use 'sass:math';
  195. // 定义rpx转换函数
  196. @function rpx($px) {
  197. @return math.div($px, 750) * 100vw;
  198. }
  199. /* 过渡样式 */
  200. .drawer-slide-enter-active,
  201. .drawer-slide-leave-active {
  202. transition: all 0.3s ease;
  203. }
  204. .drawer-slide-enter-from,
  205. .drawer-slide-leave-to {
  206. transform: translateX(-100%);
  207. opacity: 0;
  208. transition: all 0.3s ease;
  209. }
  210. .home-container {
  211. position: fixed;
  212. top: 0;
  213. left: 0;
  214. right: 0;
  215. bottom: 0;
  216. display: flex;
  217. flex-direction: row;
  218. background: linear-gradient(
  219. to bottom,
  220. #e2ddfc,
  221. #f1effd
  222. ); /* 设置悬停、聚焦、点击状态下的背景色 */
  223. gap: rpx(0);
  224. }
  225. .sidebar-layout {
  226. display: flex;
  227. flex-direction: row;
  228. align-items: flex-start;
  229. }
  230. .icon-wrapper {
  231. width: 40px; /* 根据实际需要调整宽度 */
  232. flex-shrink: 0;
  233. background-color: saddlebrown;
  234. }
  235. .main-content {
  236. width: rpx(135);
  237. height: 100%;
  238. flex-grow: 1;
  239. background: linear-gradient(to bottom, hsl(230, 100%, 21%), #8a78d0); position: relative;
  240. overflow-y: auto; /* 添加垂直滚动条 */
  241. max-height: 100%; /* 设置最大高度 */
  242. transition: all 0.3s ease;
  243. // 自定义滚动条样式
  244. &::-webkit-scrollbar {
  245. width: rpx(0); // 滚动条宽度
  246. }
  247. &::-webkit-scrollbar-track {
  248. background-color: rgba(255, 255, 255, 0.1); // 滚动条轨道背景色
  249. border-radius: rpx(2); // 滚动条轨道圆角
  250. }
  251. &::-webkit-scrollbar-thumb {
  252. background-color: rgba(255, 255, 255, 0.3); // 滚动条滑块颜色
  253. border-radius: rpx(2); // 滚动条滑块圆角
  254. transition: background-color 0.3s ease; // 滑块颜色过渡效果
  255. }
  256. &::-webkit-scrollbar-thumb:hover {
  257. background-color: rgba(255, 255, 255, 0.5); // 鼠标悬停时的滑块颜色
  258. }
  259. }
  260. .icon-expand {
  261. width: rpx(8);
  262. height: rpx(35);
  263. border-top-right-radius: rpx(5);
  264. border-bottom-right-radius: rpx(5);
  265. z-index: 9999;
  266. position: absolute;
  267. top: 50%;
  268. transform: translateY(-50%);
  269. cursor: pointer; // 鼠标指针样式
  270. // 修改裁剪路径使右侧边缘垂直无缝贴合
  271. clip-path: polygon(0 0, 100% 15%, 100% 90%, 0 100%);
  272. display: flex;
  273. justify-content: center;
  274. align-items: center;
  275. // 统一过渡时间与菜单保持同步
  276. transition: all 0.3s ease;
  277. }
  278. .icon-expand .vertical-lines {
  279. color: #8a78d0;
  280. font-size: rpx(10);
  281. }
  282. .content-box {
  283. flex: 1;
  284. height: 100%;
  285. display: flex;
  286. flex-direction: column; /* 子元素上下排列 */
  287. background: linear-gradient(
  288. to bottom,
  289. #e2ddfc,
  290. #f1effd
  291. ); /* 设置悬停、聚焦、点击状态下的背景色 */
  292. }
  293. .tac .el-menu {
  294. background-color: transparent;
  295. border: none;
  296. width: 100%;
  297. margin-left: rpx(10);
  298. margin-top: rpx(10);
  299. }
  300. .mb-2 {
  301. color: white;
  302. font-size: rpx(9);
  303. margin-left: rpx(10);
  304. white-space: nowrap; /* 防止文字换行 */
  305. }
  306. .mb-2 img {
  307. width: rpx(15);
  308. height: rpx(15);
  309. vertical-align: middle;
  310. margin-top: rpx(-2);
  311. margin-left: 0;
  312. }
  313. .el-menu-item {
  314. width: rpx(115);
  315. // height: rpx(20);
  316. margin-bottom: rpx(5);
  317. border-radius: rpx(6);
  318. color: white;
  319. font-size: rpx(8);
  320. }
  321. .el-menu ::v-deep(.el-menu-item:hover),
  322. .el-menu ::v-deep(.el-menu-item:focus),
  323. .el-menu ::v-deep(.el-menu-item:active) {
  324. background: linear-gradient(
  325. to bottom,
  326. #ffefb0,
  327. #ffcc00
  328. ); /* 设置悬停、聚焦、点击状态下的背景色 */
  329. box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
  330. color: black;
  331. }
  332. .drawer-box {
  333. position: absolute;
  334. display: flex;
  335. // align-items: center;
  336. margin-top: rpx(30);
  337. height: 100%;
  338. width: 100%;
  339. }
  340. .box-1 {
  341. width: 100%;
  342. height: rpx(50);
  343. display: flex;
  344. justify-content: center;
  345. align-items: center;
  346. box-sizing: border-box;
  347. font-size: rpx(16); // 默认字体大小
  348. }
  349. .inner-box {
  350. height: 100%;
  351. display: flex;
  352. justify-content: center;
  353. align-items: center;
  354. font-size: rpx(16); // 默认字体大小
  355. }
  356. .left-box {
  357. position: relative;
  358. justify-content: left;
  359. flex: 1;
  360. display: flex;
  361. align-items: center;
  362. gap: rpx(5); // 间距控制
  363. }
  364. .box-icon {
  365. height: 100%;
  366. display: flex;
  367. align-items: center; // 垂直居中
  368. color: black; // 设置图标颜色为白色
  369. padding-left: rpx(15);
  370. font-size: rpx(10); // 设置图标大小,可按需调整
  371. cursor: pointer; // 鼠标指针样式
  372. z-index: 999;
  373. }
  374. .box-icon .left-icon {
  375. margin-left: rpx(10);
  376. margin-right: rpx(5); // 设置图标和文字之间的间距 ;
  377. }
  378. .dropdown-box {
  379. height: 100%;
  380. display: flex; // flex 布局;
  381. align-items: center; // 垂直居中;
  382. }
  383. .dropdown-box .el-button {
  384. width: rpx(60); // 设置按钮宽度;
  385. height: rpx(15); // 设置按钮高度;
  386. background-color: rgb(255, 255, 255, 0.7);
  387. border: 1px white solid;
  388. box-shadow: 0 4px 8px rgb(0, 0, 0, 0.3);
  389. color: black;
  390. border: none;
  391. margin-left: rpx(10);
  392. border-radius: rpx(12);
  393. font-size: rpx(8); // 设置字体大小;
  394. }
  395. .dropdown-box .el-button:hover,
  396. .dropdown-box .el-button:focus,
  397. .dropdown-box .el-button:active {
  398. border: none; /* 移除悬停、聚焦、点击状态下的边框 */
  399. outline: none; /* 移除悬停、聚焦、点击状态下的轮廓线 el-scrollbar__view el-dropdown__list */
  400. }
  401. .dropdown-menu {
  402. width: rpx(100);
  403. border-radius: rpx(5);
  404. border: 1px white solid;
  405. background-color: rgb(255, 255, 255, 0.5);
  406. backdrop-filter: blur(rpx(5));
  407. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  408. margin-left: rpx(40);
  409. }
  410. .dropdown-menu ::v-deep(.el-dropdown-menu__item) {
  411. font-size: rpx(8);
  412. color: black;
  413. border-radius: rpx(5);
  414. width: rpx(78);
  415. height: rpx(20);
  416. margin-left: rpx(4);
  417. margin-bottom: rpx(8);
  418. }
  419. .dropdown-menu ::v-deep(.el-dropdown-menu__item:hover),
  420. .dropdown-menu ::v-deep(.el-dropdown-menu__item:focus),
  421. .dropdown-menu ::v-deep(.el-dropdown-menu__item:active) {
  422. background: linear-gradient(
  423. to bottom,
  424. #fee78a,
  425. #ffce1b
  426. ); /* 设置悬停、聚焦、点击状态下的背景色 */
  427. }
  428. .right-box {
  429. flex: 1;
  430. position: relative; // 添加相对定位;
  431. // background-color: #fff;
  432. display: flex;
  433. justify-content: right;
  434. align-items: center;
  435. }
  436. .top-right-box {
  437. width: rpx(130);
  438. display: flex;
  439. justify-content: flex;
  440. }
  441. .top-right-box {
  442. ::v-deep(.el-input__wrapper) {
  443. height: rpx(15);
  444. font-size: rpx(6);
  445. background-color: rgb(255, 255, 255, 0.5);
  446. border-radius: rpx(12);
  447. border: white 1px solid;
  448. color: #aaa5c5;
  449. }
  450. ::v-deep(.el-input__icon) {
  451. color: #aaa5c5; // 设置输入框图标颜色为白色
  452. }
  453. // 添加占位符样式
  454. ::v-deep(.el-input__inner::placeholder) {
  455. color: #aaa5c5;
  456. }
  457. // 添加输入框文字颜色样式
  458. ::v-deep(.el-input__inner) {
  459. color: black;
  460. }
  461. ::v-deep(.el-input--prefix){
  462. width: rpx(100);
  463. text-align: right;
  464. }
  465. }
  466. // 搜索
  467. .search-input {
  468. width: rpx(200); // 增加搜索框宽度
  469. height: rpx(30); // 增加搜索框高度
  470. font-size: rpx(9);
  471. border-radius: rpx(8); // 添加圆角
  472. border: 1px solid #dcdfe6; // 添加边框
  473. }
  474. ::v-deep(.el-input__inner) {
  475. color: #333; // 调整文字颜色
  476. }
  477. .box-2 {
  478. width: 100%;
  479. // flex: 1;
  480. box-sizing: border-box;
  481. display: flex; // 确保子元素水平排列
  482. flex-wrap: wrap; // 允许子元素换行;
  483. cursor: pointer; // 添加鼠标指针样式
  484. // margin: rpx(10) 0;
  485. overflow-y: auto;
  486. }
  487. // Chrome、Edge等浏览器的滚动条样式
  488. .box-2::-webkit-scrollbar {
  489. width: rpx(2);
  490. }
  491. .box-2::-webkit-scrollbar-track {
  492. background: transparent; // 设置滚动条轨道背景
  493. border-radius: rpx(3); // 设置滚动条轨道圆角
  494. }
  495. .box-2::-webkit-scrollbar-thumb {
  496. background: linear-gradient(to bottom, hsl(230, 100%, 21%), #8a78d0);
  497. border-radius: rpx(3); // 设置滚动条滑块圆角
  498. }
  499. .box-2::-webkit-scrollbar-thumb:hover {
  500. background: linear-gradient(to bottom, hsl(230, 100%, 21%), #8a78d0);
  501. }
  502. .small-box {
  503. flex: 0 0 calc(33.333% - rpx(10)); // 每个小盒子占三分之一宽度,减去间距
  504. margin-left: rpx(10); // 设置小盒子间距
  505. margin-top: rpx(3); // 设置小盒子间距
  506. display: flex;
  507. flex-direction: column;
  508. justify-content: flex-start;
  509. align-items: center;
  510. color: black;
  511. font-size: rpx(8);
  512. }
  513. .nested-box {
  514. width: rpx(150);
  515. height: rpx(80);
  516. border-radius: rpx(10);
  517. margin-top: rpx(5);
  518. display: flex;
  519. border: 1px solid white; // 添加边框;
  520. justify-content: center;
  521. align-items: center;
  522. }
  523. .nested-box:hover,
  524. .nested-box:active {
  525. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
  526. }
  527. .additional-text {
  528. margin-bottom: rpx(4);
  529. font-size: rpx(8);
  530. }
  531. </style>
  532. <style lang="scss">
  533. /* 消除小三角 */
  534. .el-popper__arrow {
  535. display: none;
  536. }
  537. .el-popper.is-light,
  538. .el-dropdown__popper.el-popper {
  539. background: transparent;
  540. border: none;
  541. box-shadow: none;
  542. }
  543. .el-dropdown__popper {
  544. --el-dropdown-menuItem-hover-color: none;
  545. }
  546. </style>
  547. <style lang='scss'>
  548. // 搜索下拉框样式
  549. @use 'sass:math';
  550. // 定义rpx转换函数
  551. @function rpx($px) {
  552. @return math.div($px, 750) * 100vw;
  553. }
  554. .el-autocomplete-suggestion .el-scrollbar__wrap{
  555. margin: 0 auto;
  556. background-color: rgba(255, 255, 255, 0.7);
  557. border: 2px solid white;
  558. border-radius: rpx(5);
  559. backdrop-filter: blur(rpx(5));
  560. }
  561. .el-autocomplete-suggestion li{
  562. color: black;
  563. font-size: rpx(7);
  564. padding: rpx(5) rpx(8); // 调整下拉项内边距
  565. }
  566. .el-autocomplete-suggestion li:hover{
  567. background: linear-gradient(
  568. to bottom,
  569. #ffefb0,
  570. #ffcc00
  571. );
  572. }
  573. </style>