GameIndex.vue 14 KB

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