HomePage.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <template>
  2. <div class="home-container">
  3. <div class="box-1">
  4. <div class="inner-box left-box">
  5. <span>{{ platformTitle }}</span>
  6. <div class="dropdown-box">
  7. <!-- 下拉菜单 -->
  8. <el-dropdown v-model="selectedGrade" @command="handleGradeSelect" popper-class="no-arrow-dropdown">
  9. <el-button type="primary">
  10. {{ selectedGrade }}
  11. <el-icon class="el-icon--right"><ArrowDown /></el-icon>
  12. </el-button>
  13. <template #dropdown>
  14. <el-dropdown-menu class="dropdown-menu">
  15. <el-dropdown-item
  16. v-for="item in classData"
  17. :key="item.id"
  18. :command="item.ctType"
  19. >{{ item.ctType }}</el-dropdown-item
  20. >
  21. </el-dropdown-menu>
  22. </template>
  23. </el-dropdown>
  24. </div>
  25. </div>
  26. <div class="inner-box right-box">
  27. <div class="top-right-box">
  28. <el-button
  29. round
  30. class="top-right-btn"
  31. :class="{ 'is-active': selectedButton === 'AI通识课' }"
  32. @click="selectedButton = 'AI通识课'"
  33. >AI通识课</el-button
  34. >
  35. <el-button
  36. round
  37. class="top-right-btn"
  38. :class="{ 'is-active': selectedButton === 'AI写作课' }"
  39. @click="
  40. ;(selectedButton = 'AI通识课'),
  41. Message().notifyWarning('演示版未开放此功能!!', true)
  42. "
  43. >AI写作课</el-button
  44. >
  45. <el-button
  46. round
  47. class="top-right-btn"
  48. :class="{ 'is-active': selectedButton === 'AI艺术课' }"
  49. @click="
  50. ;(selectedButton = 'AI通识课'),
  51. Message().notifyWarning('演示版未开放此功能!', true)
  52. "
  53. >AI艺术课</el-button
  54. >
  55. <!-- 退出登录 -->
  56. <!-- <div class="logout-box"> -->
  57. <el-button round class="logout-box-btn" @click="LogoutClick()">
  58. <img :src="logoutIcon" alt="Logout" />
  59. 退出登录
  60. </el-button>
  61. <!-- </div> -->
  62. </div>
  63. </div>
  64. </div>
  65. <div class="box-2">
  66. <div
  67. class="left-box-in-box2"
  68. @click="goToAIGeneralCourse('AI智能课')"
  69. :style="{ backgroundImage: `url(${indexImages[0]})` }"
  70. >
  71. <span>智能课</span>
  72. </div>
  73. <div
  74. class="center-box-in-box2"
  75. @click="goToAILab()"
  76. :style="{ backgroundImage: `url(${indexImages[1]})` }"
  77. >
  78. <span>AI实验室</span>
  79. </div>
  80. <div class="right-box-in-box2">
  81. <!-- @click="goToEvaluation" -->
  82. <div
  83. class="top-sub-box"
  84. :style="{ backgroundImage: `url(${indexImages[2]})` }"
  85. @click="goToEvaluation"
  86. >
  87. <span>能力测评</span>
  88. </div>
  89. <div
  90. class="bottom-sub-box"
  91. :style="{ backgroundImage: `url(${indexImages[3]})` }"
  92. @click="goToPersonalized"
  93. >
  94. <span>评估报告</span>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. </template>
  100. <script setup>
  101. import { ref, onMounted, watch } from 'vue'
  102. import { useRouter } from 'vue-router'
  103. import { ClassList } from '@/api/class.js'
  104. import { ArrowDown, ArrowRightBold } from '@element-plus/icons-vue'
  105. import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
  106. // 导入图片
  107. import intelligenceImg from '@/assets/images/intelligence.png'
  108. import roomImg from '@/assets/images/room.png'
  109. import testImg from '@/assets/images/test.png'
  110. import studyImg from '@/assets/images/study.png'
  111. // 退出登录图标
  112. import logoutIcon from '@/assets/icon/logout.png'
  113. import { Message } from '@/utils/message/Message.js'
  114. // 平台标题响应式变量
  115. const platformTitle = ref('人工智能通识课平台')
  116. // 更新平台标题
  117. const updatePlatformTitle = () => {
  118. platformTitle.value = localStorage.getItem('tenantName') || import.meta.env.VITE_APP_DEFAULT_LOGIN_TENANT
  119. }
  120. // 获取当前路由对象
  121. const router = useRouter()
  122. // 退出登录
  123. const LogoutClick = () => {
  124. // 清空 token 和登录状态
  125. localStorage.removeItem('token')
  126. localStorage.removeItem('isLoggedIn')
  127. localStorage.removeItem('maxCourseSections')
  128. router.push({ path: '/login' })
  129. }
  130. // 默认选中 AI 通识课
  131. const selectedButton = ref('AI通识课')
  132. // 添加图片路径
  133. const indexImages = ref([intelligenceImg, roomImg, testImg, studyImg])
  134. // AI初体验
  135. const goToAIGeneralCourse = title => {
  136. router.push({ path: '/ai-general-course', query: { title } })
  137. }
  138. //AI实验室
  139. const goToAILab = () => {
  140. router.push({
  141. path: '/ai-laboratory',
  142. // 跳转页面携带下拉菜单选中项的值
  143. query: { grade: selectedGrade.value }
  144. })
  145. }
  146. // 能力测评
  147. const goToEvaluation = () =>{
  148. router.push({
  149. path:'/evaluation'
  150. })
  151. }
  152. // 评估报告
  153. const goToPersonalized = () =>{
  154. router.push({
  155. path:'/personalized'
  156. })
  157. }
  158. // 下拉菜单选中项
  159. const selectedGrade = ref(localStorage.getItem('selectedGrade') || '')
  160. // 年级ID存储变量
  161. const selectedGradeId = ref(localStorage.getItem('selectedGradeId') || '')
  162. // 获取年级
  163. const classData = ref([])
  164. const fetchCtTypes = async () => {
  165. try {
  166. const response = await ClassList()
  167. if (response.code === 0) {
  168. classData.value = response.data
  169. // 获取到数据,将第一个选项的值作为默认选中值
  170. if (classData.value.length > 0 && !selectedGrade.value) {
  171. selectedGrade.value = classData.value[0].ctType
  172. selectedGradeId.value = classData.value[0].id
  173. localStorage.setItem('selectedGrade', selectedGrade.value)
  174. localStorage.setItem('selectedGradeId', selectedGradeId.value)
  175. }
  176. }
  177. } catch (error) {
  178. console.error('获取 ctType 数据失败:', error)
  179. }
  180. }
  181. // 监听 selectedGrade 变化,保存到 localStorage
  182. watch(selectedGrade, (newValue) => {
  183. if (newValue) {
  184. localStorage.setItem('selectedGrade', newValue)
  185. // 当年级名称变化时,查找对应的ID
  186. const selectedItem = classData.value.find(item => item.ctType === newValue)
  187. if (selectedItem) {
  188. selectedGradeId.value = selectedItem.id
  189. localStorage.setItem('selectedGradeId', selectedGradeId.value)
  190. }
  191. }
  192. })
  193. // 监听 selectedGradeId 变化,保存到 localStorage
  194. watch(selectedGradeId, (newValue) => {
  195. if (newValue) {
  196. localStorage.setItem('selectedGradeId', newValue)
  197. }
  198. })
  199. // 处理下拉菜单选择
  200. const handleGradeSelect = (command) => {
  201. selectedGrade.value = command
  202. // 查找对应的ID
  203. const selectedItem = classData.value.find(item => item.ctType === command)
  204. if (selectedItem) {
  205. selectedGradeId.value = selectedItem.id
  206. }
  207. }
  208. //AI实验室
  209. const notOpen = () => {
  210. Message().notifyWarning(
  211. localStorage.getItem('userName') === 'aiTest'
  212. ? '您的账号并未开放此功能!'
  213. : '演示版未开放此功能!',
  214. true
  215. )
  216. }
  217. onMounted(() => {
  218. fetchCtTypes()
  219. // 初始化平台标题
  220. updatePlatformTitle()
  221. // storage事件监听器,监听其他标签页对localStorage的修改
  222. window.addEventListener('storage', (e) => {
  223. if (e.key === 'tenantName') {
  224. updatePlatformTitle()
  225. }
  226. })
  227. })
  228. // 全局:更新租户名称
  229. window.updateTenantName = (newName) => {
  230. localStorage.setItem('tenantName', newName)
  231. updatePlatformTitle()
  232. }
  233. </script>
  234. <style scoped lang="scss">
  235. @use 'sass:math';
  236. // 定义rpx转换函数
  237. @function rpx($px) {
  238. @return math.div($px, 750) * 100vw;
  239. }
  240. .logout-box {
  241. width: rpx(100);
  242. position: fixed;
  243. }
  244. .logout-box-btn {
  245. width: rpx(65); // 使用 rpx 函数设置按钮宽度
  246. height: rpx(15); // 使用 rpx 函数设置按钮高度
  247. margin: rpx(10) rpx(10) 0 0; // 使用 rpx 函数设置外边距
  248. background-color: transparent;
  249. color: white;
  250. border: none; // 移除默认边框
  251. font-size: rpx(7); // 使用 rpx 函数设置字体大小
  252. outline: none; // 移除默认的外边框
  253. }
  254. .logout-box-btn img {
  255. width: rpx(10);
  256. }
  257. .home-container {
  258. position: fixed;
  259. top: 0;
  260. left: 0;
  261. right: 0;
  262. bottom: 0;
  263. background: linear-gradient(to bottom, #001169, #8a78d0);
  264. display: flex;
  265. flex-direction: column;
  266. gap: rpx(0);
  267. }
  268. .box-1 {
  269. width: 100%;
  270. height: rpx(50);
  271. display: flex;
  272. justify-content: center;
  273. align-items: center;
  274. box-sizing: border-box;
  275. font-size: rpx(16); // 默认字体大小
  276. }
  277. .box-2 {
  278. width: 90%;
  279. margin: auto;
  280. flex: 1;
  281. display: flex;
  282. justify-content: space-between;
  283. align-items: center;
  284. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  285. box-sizing: border-box;
  286. // padding: 0 rpx(20); // 添加左右内边距
  287. cursor: pointer; // 添加鼠标指针样式
  288. }
  289. .box-2 span {
  290. // 添加 padding,使文字距上边和左边留有间距
  291. padding: rpx(10) 0 0 rpx(10);
  292. font-size: rpx(12); // 默认字体大小
  293. color: white;
  294. }
  295. .left-box-in-box2,
  296. .center-box-in-box2 {
  297. background-color: rgba(133, 135, 176, 0.5);
  298. border-radius: rpx(20);
  299. flex: 1; // 让三个盒子平均分配空间
  300. margin: 0 rpx(10); // 添加左右间距
  301. height: 85%; // 高度占满容器
  302. display: flex;
  303. justify-content: flex-start;
  304. align-items: flex-start;
  305. background-origin: border-box; // 确保背景图从边框开始显示
  306. background-clip: padding-box; // 确保背景图不会延伸到边框外
  307. }
  308. .left-box-in-box2:hover,
  309. .left-box-in-box2:active,
  310. .center-box-in-box2:hover,
  311. .center-box-in-box2:active {
  312. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
  313. }
  314. .left-box-in-box2,
  315. .center-box-in-box2,
  316. .top-sub-box,
  317. .bottom-sub-box {
  318. background-repeat: no-repeat;
  319. background-size: 100% 100%;
  320. background-position: center;
  321. }
  322. .right-box-in-box2 {
  323. flex: 1; // 让三个盒子平均分配空间
  324. margin: 0 rpx(10); // 添加左右间距
  325. height: 85%; // 高度占满容器
  326. display: flex;
  327. // 确保两个子盒子上下排列
  328. flex-direction: column;
  329. justify-content: flex-start;
  330. align-items: flex-start;
  331. gap: rpx(10);
  332. }
  333. .top-sub-box,
  334. .bottom-sub-box {
  335. background-color: rgba(133, 135, 176, 0.5);
  336. flex: 1; // 让两个子盒子平均分配空间;
  337. display: flex;
  338. border-radius: rpx(20);
  339. width: 100%; // 宽度占满容器;
  340. }
  341. .top-sub-box:hover,
  342. .top-sub-box:active,
  343. .bottom-sub-box:hover,
  344. .bottom-sub-box:active {
  345. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
  346. }
  347. .inner-box {
  348. height: 100%;
  349. display: flex;
  350. justify-content: center;
  351. align-items: center;
  352. font-size: rpx(16); // 默认字体大小
  353. }
  354. .left-box {
  355. position: relative;
  356. justify-content: space-between;
  357. align-items: flex-start;
  358. flex: 1; // 设置左侧盒子占比为 2
  359. // background-color: #fff;
  360. }
  361. .left-box span {
  362. position: absolute;
  363. margin-top: rpx(20); // 调整上边距离
  364. margin-left: rpx(30);
  365. font-size: rpx(11); // 默认字体大小
  366. color: white;
  367. }
  368. .right-box {
  369. flex: 1;
  370. position: relative; // 添加相对定位;
  371. margin-right: rpx(25);
  372. }
  373. .top-right-box {
  374. position: absolute; // 添加绝对定位
  375. width: 100%; // 设置盒子宽度,可按需调整
  376. height: 60px; // 设置盒子高度,可按需调整
  377. display: flex;
  378. justify-content: flex-end;
  379. cursor: pointer; // 添加鼠标指针样式
  380. }
  381. .top-right-btn {
  382. width: rpx(50); // 使用 rpx 函数设置按钮宽度
  383. height: rpx(15); // 使用 rpx 函数设置按钮高度
  384. margin: rpx(10) rpx(5) 0 0; // 使用 rpx 函数设置外边距
  385. background-color: transparent;
  386. color: white;
  387. border: none; // 移除默认边框
  388. font-size: rpx(8); // 使用 rpx 函数设置字体大小
  389. outline: none; // 移除默认的外边框
  390. }
  391. .top-right-btn.is-active,
  392. .top-right-btn:active,
  393. .top-right-btn:focus {
  394. background-color: rgb(255, 255, 255, 0.7);
  395. border: 1px white solid;
  396. color: black;
  397. outline: none; // 移除点击时的外边框
  398. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
  399. }
  400. .dropdown-box {
  401. flex: 1;
  402. align-items: center; // 垂直居中;
  403. margin-top: rpx(22);
  404. }
  405. .dropdown-box .el-button {
  406. width: rpx(60); // 设置按钮宽度;
  407. height: rpx(15); // 设置按钮高度;
  408. background-color: rgb(255, 255, 255, 0.7);
  409. border: 1px white solid;
  410. box-shadow: 0 4px 8px rgb(0, 0, 0, 0.3);
  411. color: black;
  412. border-radius: rpx(12);
  413. font-size: rpx(8); // 设置字体大小;
  414. }
  415. .dropdown-box .el-button:hover,
  416. .dropdown-box .el-button:focus,
  417. .dropdown-box .el-button:active {
  418. border: none; /* 移除悬停、聚焦、点击状态下的边框 */
  419. outline: none; /* 移除悬停、聚焦、点击状态下的轮廓线 el-scrollbar__view el-dropdown__list */
  420. }
  421. .dropdown-menu {
  422. width: rpx(100);
  423. // height: rpx(60);
  424. border-radius: rpx(5);
  425. border: 1px white solid;
  426. background-color: rgb(255, 255, 255,0.5);
  427. backdrop-filter: blur(rpx(5));
  428. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  429. margin-left: rpx(40);
  430. }
  431. .el-scrollbar__view .el-dropdown__list{
  432. background-color: transparent;
  433. }
  434. .dropdown-menu ::v-deep(.el-dropdown-menu__item) {
  435. font-size: rpx(8);
  436. color: black;
  437. border-radius: rpx(5);
  438. width: rpx(78);
  439. height: rpx(20);
  440. margin-left: rpx(4);
  441. margin-bottom: rpx(8);
  442. }
  443. .dropdown-menu ::v-deep(.el-dropdown-menu__item:hover),
  444. .dropdown-menu ::v-deep(.el-dropdown-menu__item:focus),
  445. .dropdown-menu ::v-deep(.el-dropdown-menu__item:active) {
  446. background: linear-gradient(
  447. to bottom,
  448. #fee78a,
  449. #ffce1b
  450. );
  451. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  452. }
  453. </style>
  454. <style lang="scss">
  455. /* 消除小三角 */
  456. .el-popper__arrow{
  457. display: none;
  458. }
  459. .el-popper.is-light,
  460. .el-dropdown__popper.el-popper{
  461. background: transparent;
  462. border: none;
  463. box-shadow: none;
  464. }
  465. .el-dropdown__popper{
  466. --el-dropdown-menuItem-hover-color: none;
  467. }
  468. </style>