AIDevelop.vue 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460
  1. <template>
  2. <!-- AI发展历程 -->
  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. <el-drawer
  22. v-model="drawerVisible"
  23. direction="ltr"
  24. size="18%"
  25. :with-header="false"
  26. >
  27. <!-- 添加抽屉 -->
  28. <div class="drawer-box">
  29. <el-row class="tac">
  30. <el-col :span="12">
  31. <span class="mb-2">
  32. <img :src="classImages" alt="课程小节图标" />
  33. 课程小节
  34. </span>
  35. <el-menu
  36. :default-active="course.key"
  37. @open="handleOpen"
  38. @close="handleClose"
  39. @select="handleSelect"
  40. :default-openeds="['3','5']"
  41. >
  42. <template v-for="item in menuItems" :key="item.key">
  43. <el-menu-item v-if="!item.children" :index="item.key">{{
  44. item.title
  45. }}</el-menu-item>
  46. <el-sub-menu v-else :index="item.key">
  47. <template #title>
  48. <span>{{ item.title }}</span>
  49. </template>
  50. <el-menu-item-group v-if="item.children">
  51. <template v-for="child in item.children" :key="child.key">
  52. <el-menu-item :index="child.key"
  53. >•{{ child.title }}</el-menu-item
  54. >
  55. </template>
  56. </el-menu-item-group>
  57. </el-sub-menu>
  58. </template>
  59. </el-menu>
  60. </el-col>
  61. </el-row>
  62. </div>
  63. </el-drawer>
  64. <div class="content-box">
  65. <div class="box-1">
  66. <div class="inner-box left-box">
  67. <div class="box-icon" @click="goBack">
  68. <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
  69. {{ boxIconTitle }}
  70. </div>
  71. </div>
  72. <div class="inner-box right-box">
  73. <div class="top-right-box">
  74. <el-autocomplete
  75. v-model="SearchInput"
  76. :fetch-suggestions="querySearch"
  77. placeholder="搜索"
  78. @select="handleSearchSelect"
  79. class="search-input"
  80. value-key="title"
  81. :trigger-on-focus="false"
  82. >
  83. <template #prefix>
  84. <el-icon class="el-input__icon"><search /></el-icon>
  85. </template>
  86. <template #popper-append-to-body>
  87. <el-option
  88. class="scrollbar"
  89. v-for="item in filteredTitles"
  90. :key="item.key"
  91. :label="item.title"
  92. :value="item"
  93. ></el-option>
  94. </template>
  95. </el-autocomplete>
  96. </div>
  97. </div>
  98. </div>
  99. <div class="box-2">
  100. <!-- 课程标题 -->
  101. <div class="small-title">
  102. <span>{{ course.courseName }}</span>
  103. </div>
  104. <el-empty v-if="isDisabled"
  105. image-size="500"
  106. description="您无权查看该课程!"
  107. :image="isDisabledImage"
  108. />
  109. <template v-else>
  110. <!-- 视频组件 -->
  111. <VideoPlayer
  112. v-if="course.courseContentType === 'video'"
  113. :contentType="course.courseContentType"
  114. :videoPath="course.courseVideoPath"
  115. :courseId="course.id || ''"
  116. :typeId="typeId"
  117. :courseConfigList="course.courseConfigList || []"
  118. :allIndices="flattenMenuItems()"
  119. :currentIndex="course.key || ''"
  120. @timeUpdate="handleVideoTimeUpdate"
  121. @videoEnded="handleVideoEnded"
  122. @switchVideo="handleSelect"
  123. @saveProgress="handleSaveProgress"
  124. />
  125. <!-- 图片 -->
  126. <ImageView v-if="course.courseContentType === 'image'" :imagePath="course.courseImagePath" altText="课程图片"></ImageView>
  127. <!-- PPT -->
  128. <PptView v-if="course.courseContentType === 'ppt'" :pptPath="course.pptPath" ref="pptRef"></PptView>
  129. <!--文生文-->
  130. <TextToText class="contentClass" v-if="course.courseContentType === 'aiTextToText'" ref="aiTextToText"></TextToText>
  131. <!--文生图-->
  132. <TextToImage class="contentClass" v-if="course.courseContentType === 'aiTextToImage'" ref="aiTextToImage"></TextToImage>
  133. <!--图生图-->
  134. <ImageToImage class="contentClass" v-if="course.courseContentType === 'aiImageToImage'" ref="aiImageToImage"></ImageToImage>
  135. <!--图生视频-->
  136. <ImageToVideo class="contentClass" v-if="course.courseContentType === 'aiImageToVideo'" ref="aiImageToVideo"></ImageToVideo>
  137. </template>
  138. <!-- 视频切换按钮 - 始终显示 -->
  139. <div class="video-switch">
  140. <div class="caret-left" @click="playPreviousVideo">
  141. <el-button type="warning" round :disabled="flattenMenuItems().indexOf(course.key) === 0">
  142. <img :src="leftImg" alt="Left" />上一节</el-button
  143. >
  144. </div>
  145. <div class="caret-right" @click="playNextVideo">
  146. <el-button type="warning" round :disabled="flattenMenuItems().indexOf(course.key) === flattenMenuItems().length - 1"
  147. >下一节<img :src="rightImg" alt="Right" />
  148. </el-button>
  149. </div>
  150. </div>
  151. </div>
  152. </div>
  153. <!-- 弹框组件 -->
  154. <DialogComponents
  155. :questionDialogVisible="questionDialogVisible"
  156. :currentQuestion="courseConfig"
  157. :gradeId="gradeId"
  158. :typeId="typeId"
  159. :courseId="course.id || ''"
  160. @closeQuestionDialog="closeQuestionDialog"
  161. @submitAnswer="handleSubmitAnswer"
  162. />
  163. </div>
  164. </template>
  165. <script setup>
  166. import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
  167. import { useRoute, useRouter } from 'vue-router'
  168. import { Expand, Fold, Memo } from '@element-plus/icons-vue'
  169. import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
  170. import { ElMessage, ElMessageBox, ElNotification, valueEquals } from 'element-plus'
  171. import isDisabledImage from '@/assets/images/permission/isDisabled.png'
  172. import classImages from '@/assets/icon/class.png'
  173. import { ClassType } from '@/api/class.js'
  174. import { Message } from '@/utils/message/Message.js'
  175. import { saveRecord } from '@/api/personalized/index.js'
  176. // 导入全局状态
  177. import { globalState } from '@/utils/globalState.js'
  178. // 导入图标
  179. import leftImg from '@/assets/icon/backward.png'
  180. import rightImg from '@/assets/icon/f-backward.png'
  181. // 导入新创建的组件
  182. import VideoPlayer from '@/components/videopage/VideoPlayer.vue'
  183. import DialogComponents from '@/components/videopage/DialogComponents.vue'
  184. import PptView from "@/components/PPT/PptView.vue";
  185. import ImageView from '@/components/Image/ImageView.vue'
  186. // AI实验室
  187. import TextToText from "@/components/ai/text/TextToText.vue";
  188. import TextToImage from "@/components/ai/image/TextToImage.vue";
  189. import ImageToImage from "@/components/ai/image/ImageToImage.vue";
  190. import ImageToVideo from "@/components/ai/video/ImageToVideo.vue";
  191. const router = useRouter() // 获取当前路由对象
  192. const route = useRoute()
  193. // 添加按钮显示状态
  194. const buttonVisible = ref(false)
  195. // 添加抽屉显示状态
  196. const drawerVisible = ref(false)
  197. // 渲染页面标题
  198. const boxIconTitle = ref('')
  199. // 课程集合数据
  200. const courseList = ref([])
  201. //当前课程
  202. const course = ref({})
  203. // 菜单数据
  204. const menuItems = ref([])
  205. // 课程集合数据
  206. const videoPathMap = ref({})
  207. // 已观看课程ID列表
  208. const watchedCourseIds = ref([])
  209. // 试题弹框显示状态
  210. const questionDialogVisible = ref(false)
  211. // 当前显示的试题
  212. const courseConfig = ref({})
  213. // 搜索框
  214. const SearchInput = ref('')
  215. // 年级id
  216. const gradeId = ref('')
  217. // 课程大纲id
  218. const typeId = ref('')
  219. // 课程小节id
  220. const courseId = ref('')
  221. // 课程排序
  222. const typeSort = ref('')
  223. // 测试账号禁用视频
  224. const isDisabled = ref(false)
  225. // 保存视频进度接口
  226. const handleSaveProgress = async (progressData) => {
  227. try {
  228. const { progress, gradeId: brpNjId, typeId: brpCtId, courseId: brpCourseId } = progressData
  229. await saveRecord({
  230. brpNjId: brpNjId || globalState.getGradeId(),
  231. brpCtId,
  232. brpCourseId,
  233. brpType: 'course',
  234. brpProgress: progress
  235. })
  236. } catch (error) {
  237. console.error('保存视频进度失败:', error)
  238. }
  239. }
  240. //课程小节字典
  241. const menuDict = ref({
  242. 1: '课前回顾',
  243. 2: '课程引入',
  244. 3: '知识讲解',
  245. 4: '趣味实操',
  246. 5: '课程总结'
  247. })
  248. // 切换抽屉显示状态的函数
  249. const toggleDrawer = () => {
  250. drawerVisible.value = !drawerVisible.value
  251. }
  252. // 返回上一页
  253. const goBack = () => {
  254. router.go(-1)
  255. }
  256. // 菜单打开和关闭的处理函数
  257. const handleOpen = () => {}
  258. const handleClose = () => {}
  259. // 菜单选择的处理函数
  260. const handleSelect = index => {
  261. // 根据索引切换视频
  262. if (videoPathMap.value[index]) {
  263. course.value = videoPathMap.value[index]
  264. courseId.value = course.value.id
  265. // 切换标题后,关闭抽屉
  266. drawerVisible.value = false
  267. } else {
  268. //视频不存在
  269. Message().notifyWarning('视频不存在!', true)
  270. }
  271. //测试账号禁用视频
  272. if (disableMsg(index)) return
  273. }
  274. // 展平所有菜单项索引
  275. const flattenMenuItems = () => {
  276. const indices = []
  277. const traverse = items => {
  278. for (const item of items) {
  279. if (!item.children) {
  280. indices.push(item.key)
  281. } else {
  282. traverse(item.children)
  283. }
  284. }
  285. }
  286. traverse(menuItems.value)
  287. return indices
  288. }
  289. // 播放上一个视频
  290. const playPreviousVideo = () => {
  291. const allIndices = flattenMenuItems()
  292. const currentIndexInList = allIndices.indexOf(course.value.key)
  293. if (currentIndexInList > 0) {
  294. const previousIndex = allIndices[currentIndexInList - 1]
  295. handleSelect(previousIndex)
  296. }
  297. }
  298. // 播放下一个视频
  299. const playNextVideo = () => {
  300. const allIndices = flattenMenuItems()
  301. const currentIndexInList = allIndices.indexOf(course.value.key)
  302. if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
  303. const nextIndex = allIndices[currentIndexInList + 1]
  304. handleSelect(nextIndex)
  305. }
  306. }
  307. // 播放结束
  308. const handleVideoEnded = () => {
  309. console.log("播放结束")
  310. // 记录当前视频ID为已观看
  311. if (
  312. course.value &&
  313. course.value.id &&
  314. !watchedCourseIds.value.includes(course.value.id)
  315. ) {
  316. watchedCourseIds.value.push(course.value.id)
  317. localStorage.setItem(
  318. 'watchedCourseIds',
  319. JSON.stringify(watchedCourseIds.value)
  320. )
  321. }
  322. console.log("================")
  323. // 自动播放下一个
  324. const allIndices = flattenMenuItems()
  325. const currentIndexInList = allIndices.indexOf(course.value.key)
  326. if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
  327. const nextIndex = allIndices[currentIndexInList + 1]
  328. handleSelect(nextIndex)
  329. }
  330. }
  331. // 禁用视频(提示语)
  332. const disableMsg = (index = course.value.key) => {
  333. //配置了课程权限,且视频id不在权限列表中
  334. isDisabled.value = videoPathMap.value[index].dataReadonly
  335. if (isDisabled.value) {
  336. Message().notifyWarning('您的账号并未开放此课程!', true)
  337. return isDisabled.value;
  338. }
  339. return isDisabled.value;
  340. }
  341. // 处理视频时间更新事件
  342. const handleVideoTimeUpdate = ({ currentTime, progressPercentage, courseConfig: config }) => {
  343. if (config) {
  344. questionDialogVisible.value = true
  345. courseConfig.value = config
  346. // 保存试题进度
  347. const saveQuestProgress = async () =>{
  348. try {
  349. // 确保courseId已经设置
  350. if (!courseId.value && typeId.value) {
  351. const courseRes = await ClassType(typeId.value)
  352. if (courseRes.data && courseRes.data.length > 0) {
  353. courseId.value = course.value && course.value.id ? course.value.id : courseRes.data[0].id
  354. }
  355. }
  356. if (config.id) {
  357. // 保存弹窗问题进度
  358. await saveRecord({
  359. brpNjId: gradeId.value,
  360. brpCtId: typeId.value,
  361. brpCourseConfigId: config.id,
  362. brpCourseId: courseId.value,
  363. brpType: 'courseQuest',
  364. brpProgress: progressPercentage
  365. })
  366. } else {
  367. console.error('无法保存试题进度: 试题id不存在')
  368. }
  369. }catch(error){
  370. console.error(`保存试题进度失败:`, error)
  371. }
  372. }
  373. // 调用异步函数
  374. saveQuestProgress()
  375. }
  376. }
  377. // 关闭试题弹框
  378. const closeQuestionDialog = () => {
  379. questionDialogVisible.value = false
  380. }
  381. // 提交答案
  382. const handleSubmitAnswer = ({ selectedOption }) => {
  383. questionDialogVisible.value = false
  384. }
  385. // 搜索
  386. const querySearch = (queryString, cb) => {
  387. const sections = getAllCourseSections()
  388. const results = queryString
  389. ? sections.filter(section =>
  390. section.title.toLowerCase().includes(queryString.toLowerCase())
  391. )
  392. : sections
  393. cb(results)
  394. }
  395. const filteredTitles = computed(() => {
  396. const sections = getAllCourseSections()
  397. if (!SearchInput.value) {
  398. return sections
  399. }
  400. return sections.filter(section =>
  401. section.title.toLowerCase().includes(SearchInput.value.toLowerCase())
  402. )
  403. })
  404. const handleSearchSelect = item => {
  405. handleSelect(item.key)
  406. // 清空输入框
  407. SearchInput.value = ''
  408. }
  409. // 课程小节数据提取
  410. const getAllCourseSections = () => {
  411. let sections = []
  412. const traverse = items => {
  413. items.forEach(item => {
  414. if (item.children) {
  415. traverse(item.children)
  416. } else {
  417. sections.push({ title: item.title, key: item.key })
  418. }
  419. })
  420. }
  421. traverse(menuItems.value)
  422. return sections
  423. }
  424. // 渲染 课程数据结构 以及 视频
  425. onMounted(async () => {
  426. const typeIdParam = router.currentRoute.value.query.typeId
  427. if (typeIdParam) {
  428. typeId.value = typeIdParam
  429. try {
  430. // 取接口课程数据
  431. const res = await ClassType(typeIdParam)
  432. // 对返回的课程数据进行处理,确保ccTime为有效秒数
  433. const processedData = res.data.map(course => {
  434. // 检查并处理courseConfigList
  435. if (course.courseConfigList && Array.isArray(course.courseConfigList)) {
  436. // 过滤掉ccTime为0的配置项
  437. const validConfigList = course.courseConfigList.filter(config =>
  438. config.ccTime !== undefined && config.ccTime !== null && config.ccTime > 0
  439. )
  440. return {
  441. ...course,
  442. courseConfigList: validConfigList
  443. }
  444. }
  445. return course
  446. })
  447. courseList.value = processedData
  448. // 初始化已观看课程ID
  449. const savedWatchedIds = localStorage.getItem('watchedCourseIds')
  450. if (savedWatchedIds) {
  451. watchedCourseIds.value = JSON.parse(savedWatchedIds)
  452. }
  453. //课程数据
  454. let topName = '';
  455. courseList.value.forEach((courseTemp, index) => {
  456. let menuIndex = courseTemp.courseLabel + '-' + (index + 1)
  457. //大节
  458. let menu = {
  459. key: menuIndex,
  460. index: menuIndex,
  461. title: courseTemp.courseName
  462. }
  463. if (topName === courseTemp.courseLabel) {
  464. let topMenu = menuItems.value[menuItems.value.length - 1]
  465. let topMenuChildren = topMenu.children;
  466. if (topMenuChildren) {
  467. topMenuChildren.push(menu)
  468. } else {
  469. menu = {
  470. key: menuIndex,
  471. index: menuIndex,
  472. title: menuDict.value[courseTemp.courseLabel],
  473. children: [
  474. {
  475. key: topMenu.key,
  476. index: topMenu.index,
  477. title: topMenu.title,
  478. },
  479. {
  480. key: menuIndex,
  481. index: menuIndex,
  482. title: courseTemp.courseName
  483. }
  484. ]
  485. }
  486. menuItems.value[menuItems.value.length-1] = menu
  487. }
  488. }else{
  489. menuItems.value.push(menu)
  490. }
  491. topName = courseTemp.courseLabel
  492. courseTemp['key'] = menuIndex
  493. videoPathMap.value[menuIndex] = courseTemp
  494. //确定默认课程
  495. if (index === 0) {
  496. courseId.value = courseTemp.id
  497. if(!disableMsg(menuIndex)){
  498. course.value = courseTemp
  499. }else{
  500. course.value.key = courseTemp.key
  501. course.value.courseName = courseTemp.courseName
  502. }
  503. }
  504. })
  505. } catch (error) {
  506. console.error('获取课程数据失败:', error)
  507. }
  508. }
  509. const title = router.currentRoute.value.query.typeName
  510. if (title) {
  511. boxIconTitle.value = String(title)
  512. }
  513. typeSort.value = router.currentRoute.value.query.typeSort
  514. // 初始化年级ID
  515. gradeId.value = globalState.initGradeId()
  516. })
  517. onBeforeUnmount(() => {
  518. // 组件卸载时的清理
  519. })
  520. </script>
  521. <style scoped lang="scss">
  522. @use 'sass:math';
  523. @use 'sass:color'; // 引入 color 模块
  524. // 定义rpx转换函数
  525. @function rpx($px) {
  526. @return math.div($px, 750) * 100vw;
  527. }
  528. // 定义儿童风格的蓝紫色调
  529. $primary-color: rgba(106, 90, 205, 0.52); // 主色调:蓝紫色
  530. $secondary-color: rgba(147, 112, 219, 0.66); // 辅助色:亮蓝紫色
  531. $accent-color: rgb(133, 89, 220); // 强调色:暗蓝紫色
  532. $light-color: #ffffff; // 浅色背景:淡紫色
  533. $text-color: #483d8b; // 文本颜色:靛蓝色
  534. // 视频切换按钮样式
  535. .video-switch {
  536. width: 100%;
  537. display: flex;
  538. margin-top: rpx(5);
  539. margin-bottom: rpx(15);
  540. justify-content: center;
  541. }
  542. .caret-right,
  543. .caret-left {
  544. width: rpx(50);
  545. margin: 0 rpx(20);
  546. margin: auto;
  547. display: flex;
  548. justify-content: center;
  549. }
  550. .caret-left ::v-deep(.el-button.is-round),
  551. .caret-right ::v-deep(.el-button.is-round) {
  552. width: rpx(50);
  553. height: rpx(15);
  554. color: white;
  555. font-size: rpx(7);
  556. border-radius: none;
  557. border: 1px white solid;
  558. background-color: rgb(255, 255, 255, 0.5);
  559. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  560. }
  561. .caret-right img,
  562. .caret-left img {
  563. width: rpx(12);
  564. }
  565. .default-messages {
  566. margin-top: rpx(-10);
  567. margin-bottom: rpx(5);
  568. }
  569. /* 添加过渡样式 */
  570. .drawer-slide-enter-active,
  571. .drawer-slide-leave-active {
  572. transition: all 0.3s ease;
  573. }
  574. .drawer-slide-enter-from,
  575. .drawer-slide-leave-to {
  576. transform: translateX(-100%);
  577. opacity: 0;
  578. }
  579. .home-container ::v-deep(.el-drawer__body) {
  580. width: rpx(135);
  581. height: 100%;
  582. position: relative;
  583. background: linear-gradient(to bottom, #001169, #8a78d0);
  584. }
  585. .content-box {
  586. flex: 1;
  587. height: 100%;
  588. display: flex;
  589. flex-direction: column; /* 子元素上下排列 */
  590. background: linear-gradient(to bottom, #001169, #8a78d0);
  591. }
  592. .icon-expand {
  593. width: rpx(8);
  594. height: rpx(35);
  595. border-top-right-radius: rpx(5);
  596. border-bottom-right-radius: rpx(5);
  597. z-index: 9999;
  598. position: absolute;
  599. top: 50%;
  600. transform: translateY(-50%);
  601. cursor: pointer; // 添加鼠标指针样式
  602. clip-path: polygon(0 0, 100% 15%, 100% 85%, 0 100%);
  603. display: flex;
  604. justify-content: center;
  605. align-items: center;
  606. transition: all 0.3s ease;
  607. }
  608. .icon-expand .vertical-lines {
  609. color: #8a78d0;
  610. font-size: rpx(10);
  611. }
  612. .home-container {
  613. position: fixed;
  614. top: 0;
  615. left: 0;
  616. right: 0;
  617. bottom: 0;
  618. background: linear-gradient(to bottom, #001169, #b4a8e1);
  619. display: flex;
  620. }
  621. .el-row {
  622. margin: auto;
  623. margin-top: rpx(20);
  624. }
  625. .tac ::v-deep(.el-menu) {
  626. background-color: transparent;
  627. border: none;
  628. width: 100%;
  629. margin-top: rpx(8);
  630. }
  631. /* 取消点击后的蓝色字体 el-sub-menu__title*/
  632. .tac ::v-deep(.el-menu-item.is-active),
  633. .tac ::v-deep(.el-sub-menu__title.is-active) {
  634. color: white;
  635. }
  636. // 取消鼠标悬浮颜色
  637. .tac ::v-deep(.el-sub-menu__title) {
  638. width: rpx(130);
  639. height: rpx(20);
  640. margin-bottom: rpx(5);
  641. border-radius: rpx(6);
  642. // 添加flex布局使标题和图标两端对齐
  643. display: flex;
  644. justify-content: space-between;
  645. align-items: center;
  646. }
  647. .el-menu ::v-deep(.el-sub-menu__title:hover),
  648. .el-menu ::v-deep(.el-sub-menu__title:focus),
  649. .el-menu ::v-deep(.el-sub-menu__title:active) {
  650. background: linear-gradient(to bottom, #fee78a, #ffce1b);
  651. background-color: transparent;
  652. }
  653. // 添加二级标题折叠图标样式
  654. ::v-deep(.el-sub-menu__icon-arrow) {
  655. color: white;
  656. font-size: rpx(10); // 增大图标尺寸
  657. margin-left: auto; // 将图标推到右侧
  658. margin-top: rpx(-5);
  659. display: block;
  660. width: rpx(16); // 确保有明确宽度
  661. }
  662. // 鼠标悬停时的图标样式
  663. .el-menu ::v-deep(.el-sub-menu__title:hover .el-sub-menu__icon-arrow) {
  664. color: black; // 与悬停状态的文字颜色保持一致
  665. }
  666. .el-menu ::v-deep(.el-icon svg) {
  667. font-size: rpx(9);
  668. }
  669. .mb-2 {
  670. color: white;
  671. font-size: rpx(9);
  672. }
  673. .mb-2 img {
  674. width: rpx(10);
  675. height: rpx(10);
  676. vertical-align: middle;
  677. margin-top: rpx(-2);
  678. }
  679. .el-menu-item {
  680. width: rpx(100);
  681. height: rpx(20);
  682. margin-bottom: rpx(5);
  683. border-radius: rpx(6);
  684. color: white;
  685. font-size: rpx(8);
  686. }
  687. .el-menu ::v-deep(.el-sub-menu__title) {
  688. color: white;
  689. width: rpx(100);
  690. height: rpx(20);
  691. margin-bottom: rpx(5);
  692. font-size: rpx(8);
  693. }
  694. .el-menu ::v-deep(.el-sub-menu__title:hover),
  695. .el-menu ::v-deep(.el-sub-menu__title:focus),
  696. .el-menu ::v-deep(.el-sub-menu__title:active) {
  697. background: linear-gradient(to bottom, #fee78a, #ffce1b);
  698. color: black;
  699. }
  700. .el-menu ::v-deep(.el-menu-item:hover),
  701. .el-menu ::v-deep(.el-menu-item:focus),
  702. .el-menu ::v-deep(.el-menu-item:active) {
  703. background: linear-gradient(to bottom, #fee78a, #ffce1b);
  704. color: black;
  705. font-size: rpx(8);
  706. box-shadow: 0 4px 8px rgba(3, 3, 3, 0.3);
  707. }
  708. .el-menu .el-menu-item.is-active {
  709. background: linear-gradient(to bottom, #fee78a, #ffce1b);
  710. color: black;
  711. font-size: rpx(8);
  712. box-shadow: 0 4px 8px rgba(3, 3, 3, 0.3);
  713. }
  714. .drawer-box {
  715. position: absolute;
  716. display: flex;
  717. align-items: center;
  718. height: 100%;
  719. width: 80%;
  720. }
  721. .drawer-box .toggle-button {
  722. width: rpx(10);
  723. height: rpx(50);
  724. font-size: rpx(7);
  725. background-color: rgba(17, 23, 29, 0.2);
  726. border: none;
  727. position: relative;
  728. writing-mode: vertical-lr; // 文字垂直排列,从左到右
  729. text-orientation: upright; // 文字保持正立
  730. }
  731. .toggle-button:hover {
  732. left: 0;
  733. }
  734. .toggle-button.is-active,
  735. .toggle-button:active,
  736. .toggle-button:focus {
  737. background-color: rgba(165, 209, 247, 0.8);
  738. color: white;
  739. border: none; // 移除点击时的边框
  740. outline: none; // 移除点击时的外边框
  741. }
  742. .box-1 {
  743. width: 100%;
  744. // height: rpx(50);
  745. margin-top: rpx(10);
  746. display: flex;
  747. justify-content: center;
  748. align-items: center;
  749. box-sizing: border-box;
  750. font-size: rpx(15); // 默认字体大小
  751. }
  752. .inner-box {
  753. height: 100%;
  754. display: flex;
  755. justify-content: center;
  756. align-items: center;
  757. font-size: rpx(16); // 默认字体大小
  758. }
  759. .left-box {
  760. position: relative;
  761. justify-content: flex-start;
  762. align-items: flex-start;
  763. flex: 1; // 设置左侧盒子占比为 2
  764. cursor: pointer; // 添加鼠标指针样式
  765. }
  766. .box-icon {
  767. width: 100%;
  768. height: 100%;
  769. flex: 1;
  770. display: flex; // 添加 flex 布局
  771. align-items: center; // 垂直居中
  772. color: white; // 设置图标颜色为白色
  773. padding-left: rpx(15);
  774. font-size: rpx(10); // 设置图标大小,可按需调整
  775. }
  776. .box-icon .left-icon {
  777. margin-left: rpx(10);
  778. margin-right: rpx(5); // 设置图标和文字之间的间距 ;
  779. }
  780. .left-box span {
  781. position: absolute;
  782. font-size: rpx(11); // 默认字体大小
  783. color: white;
  784. }
  785. .right-box {
  786. flex: 1;
  787. position: relative; // 添加相对定位;
  788. }
  789. .top-right-box {
  790. position: absolute; // 添加绝对定位
  791. // margin-top: rpx(9); // 调整上边距离
  792. margin-left: rpx(260); // 调整右边距离
  793. width: rpx(100); // 设置盒子宽度,可按需调整
  794. // height: 60px; // 设置盒子高度,可按需调整
  795. margin-right: rpx(20);
  796. display: flex;
  797. justify-content: flex-end;
  798. }
  799. .top-right-box {
  800. ::v-deep(.el-input__wrapper) {
  801. height: rpx(15);
  802. font-size: rpx(6);
  803. background-color: rgb(255, 255, 255, 0.5);
  804. border-radius: rpx(12);
  805. border: white 1px solid;
  806. color: white;
  807. }
  808. ::v-deep(.el-input__icon) {
  809. color: white; // 设置输入框图标颜色为白色
  810. }
  811. // 添加占位符样式
  812. ::v-deep(.el-input__inner::placeholder) {
  813. color: white;
  814. }
  815. // 添加输入框文字颜色样式
  816. ::v-deep(.el-input__inner) {
  817. color: black;
  818. }
  819. }
  820. // 搜索框
  821. .search-input {
  822. width: rpx(100);
  823. height: rpx(15);
  824. font-size: rpx(7);
  825. }
  826. .box-2 {
  827. width: 100%;
  828. flex: 1;
  829. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  830. box-sizing: border-box;
  831. // display: flex; // 确保子元素水平排列
  832. flex-wrap: wrap; // 允许子元素换行;
  833. align-content: center; // 顶部对齐;
  834. cursor: pointer; // 添加鼠标指针样式
  835. }
  836. .small-title {
  837. width: 100%;
  838. // margin-top: rpx(-20);
  839. height: rpx(20);
  840. color: white;
  841. font-size: rpx(10);
  842. justify-content: center; //使子元素水平居中
  843. }
  844. // 图片容器样式
  845. .image-container {
  846. width: 100%;
  847. display: flex;
  848. justify-content: center;
  849. align-items: center;
  850. // padding: rpx(20) 0;
  851. }
  852. // 图片样式
  853. .course-image {
  854. max-width: 70%;
  855. max-height: rpx(400);
  856. object-fit: contain;
  857. border-radius: rpx(12);
  858. box-shadow: 0 rpx(10) rpx(20) rgba(0, 0, 0, 0.1);
  859. }
  860. // 儿童风格试题弹框样式
  861. .child-dialog {
  862. .el-dialog__header {
  863. display: none; // 隐藏原有的标题栏
  864. }
  865. .el-dialog__body {
  866. padding: rpx(20);
  867. position: relative;
  868. }
  869. .el-dialog__footer {
  870. border-top: none;
  871. padding: rpx(10) rpx(20);
  872. text-align: center;
  873. margin-top: auto; // 使底部按钮位于底部
  874. }
  875. .el-dialog__wrapper {
  876. // 修改半透明背景色
  877. background-color: rgba(0, 0, 0, 0.6);
  878. }
  879. .el-dialog {
  880. border: none;
  881. border-radius: rpx(20);
  882. background: linear-gradient(
  883. 135deg,
  884. $light-color,
  885. #d8bfd8
  886. ); // 柔和的蓝紫色渐变
  887. overflow: hidden;
  888. display: flex; // 添加 flex 布局
  889. flex-direction: column; // 设置垂直布局
  890. min-height: 0; // 防止子元素溢出
  891. // 添加装饰元素
  892. &::before {
  893. content: '';
  894. position: absolute;
  895. top: 0;
  896. left: 0;
  897. width: 100%;
  898. height: rpx(10);
  899. background: linear-gradient(90deg, $secondary-color, $accent-color);
  900. }
  901. }
  902. }
  903. // 问题标题样式
  904. .question-title {
  905. padding: rpx(15);
  906. border-radius: rpx(12);
  907. margin-bottom: rpx(20);
  908. color: #483d8b;
  909. font-weight: bold;
  910. font-size: rpx(12);
  911. position: relative;
  912. display: flex;
  913. // align-items: center;
  914. .question-icon {
  915. background-color: $accent-color;
  916. color: white;
  917. width: rpx(24);
  918. height: rpx(24);
  919. border-radius: 50%;
  920. display: flex;
  921. align-items: center;
  922. justify-content: center;
  923. margin-right: rpx(10);
  924. font-weight: bold;
  925. box-shadow: 0 rpx(2) rpx(5) rgba($accent-color, 0.3);
  926. }
  927. }
  928. // 选项容器样式
  929. .options-container {
  930. margin-bottom: rpx(20);
  931. }
  932. // 问题选项样式
  933. .question-option {
  934. margin: rpx(8) 0;
  935. padding: rpx(10) rpx(15);
  936. border-radius: rpx(12);
  937. border: rpx(1) solid rgba($primary-color, 0.3);
  938. transition: all 0.3s ease;
  939. display: flex;
  940. align-items: center;
  941. background-color: white;
  942. box-shadow: 0 rpx(2) rpx(5) rgba($primary-color, 0.05);
  943. ::v-deep(.el-radio__label) {
  944. color: $text-color;
  945. margin-left: rpx(8);
  946. flex: 1;
  947. text-align: left;
  948. // 增大字体大小
  949. font-size: rpx(12);
  950. }
  951. // 选中时的样式变化
  952. .el-radio__input.is-checked + .el-radio__label {
  953. font-weight: bold;
  954. color: $accent-color;
  955. }
  956. &:hover {
  957. background-color: rgba($primary-color, 0.05);
  958. border-color: rgba($primary-color, 0.5);
  959. transform: translateY(-rpx(1));
  960. }
  961. }
  962. // 暂无选项样式
  963. .no-options {
  964. color: rgba($text-color, 0.7);
  965. text-align: center;
  966. padding: rpx(20);
  967. font-size: rpx(12);
  968. }
  969. // 底部按钮样式
  970. .child-button {
  971. min-width: rpx(80);
  972. height: rpx(30);
  973. border-radius: rpx(8);
  974. font-size: rpx(12);
  975. font-weight: 500;
  976. transition: all 0.3s ease;
  977. box-shadow: 0 rpx(2) rpx(8) rgba(0, 0, 0, 0.1);
  978. &.confirm {
  979. background: linear-gradient(to bottom, #ab81ff, #8559dc);
  980. border: none;
  981. border-right: 15px;
  982. color: white;
  983. &:hover {
  984. background: linear-gradient(
  985. to bottom,
  986. color.adjust(#ab81ff, $lightness: -5%),
  987. color.adjust(#8559dc, $lightness: -5%)
  988. );
  989. transform: translateY(-rpx(1));
  990. color: white;
  991. }
  992. }
  993. &.cancel {
  994. background: white;
  995. border: rpx(1) solid rgba($primary-color, 0.3);
  996. color: $text-color;
  997. &:hover {
  998. background: rgba($primary-color, 0.05);
  999. border-color: rgba($primary-color, 0.5);
  1000. transform: translateY(-rpx(1));
  1001. }
  1002. }
  1003. }
  1004. // AI对话图标样式
  1005. .ai-icon-container {
  1006. position: absolute;
  1007. bottom: rpx(20);
  1008. right: rpx(20);
  1009. display: flex;
  1010. flex-direction: column;
  1011. align-items: center;
  1012. cursor: pointer;
  1013. transition: all 0.3s ease;
  1014. &:hover {
  1015. transform: translateY(-rpx(2));
  1016. }
  1017. .ai-icon {
  1018. width: rpx(30);
  1019. height: rpx(30);
  1020. margin-bottom: rpx(0);
  1021. filter: drop-shadow(0 rpx(2) rpx(4) rgba($primary-color, 0.3));
  1022. // 添加过渡动画
  1023. transition: transform 0.3s ease;
  1024. }
  1025. // 悬浮时放大效果
  1026. .ai-icon:hover {
  1027. transform: scale(1.5);
  1028. }
  1029. .ai-text {
  1030. color: $text-color;
  1031. font-size: rpx(8);
  1032. background-color: rgba(255, 255, 255, 0.7);
  1033. padding: rpx(2) rpx(5);
  1034. border-radius: rpx(5);
  1035. }
  1036. }
  1037. // AI消息样式
  1038. .ai-message {
  1039. display: flex;
  1040. align-items: flex-start;
  1041. margin-bottom: rpx(15);
  1042. .ai-avatar {
  1043. width: rpx(30);
  1044. height: rpx(30);
  1045. border-radius: 50%;
  1046. margin-right: rpx(10);
  1047. background-color: $primary-color;
  1048. padding: rpx(5);
  1049. // box-shadow: 0 rpx(2) rpx(5) rgba($primary-color, 0.2);
  1050. }
  1051. .ai-text-content {
  1052. background-color: $light-color;
  1053. padding: rpx(8) rpx(12);
  1054. border-radius: rpx(10);
  1055. font-size: rpx(10);
  1056. color: $text-color;
  1057. max-width: 80%;
  1058. // box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
  1059. }
  1060. }
  1061. // 用户输入框样式
  1062. .user-input {
  1063. ::v-deep(.el-input__wrapper) {
  1064. height: rpx(23);
  1065. border-top-left-radius: rpx(5);
  1066. border-bottom-left-radius: rpx(5);
  1067. border-color: rgba($primary-color, 0.3);
  1068. &:focus-within {
  1069. box-shadow: 0 0 0 rpx(1) rgba($primary-color, 0.5);
  1070. }
  1071. }
  1072. ::v-deep(.el-input__inner) {
  1073. font-size: rpx(10);
  1074. // color: $text-color;
  1075. text-indent: 1em;
  1076. }
  1077. ::v-deep(.el-input-group__append, .el-input-group__prepend) {
  1078. background: linear-gradient(to bottom, #ab81ff, #8559dc);
  1079. border-top-right-radius: rpx(5);
  1080. border-bottom-right-radius: rpx(5);
  1081. color: white;
  1082. font-size: rpx(9);
  1083. }
  1084. }
  1085. /* 定义淡入和缩放动画 */
  1086. .fade-scale-enter-active,
  1087. .fade-scale-leave-active {
  1088. transition: all 0.5s ease;
  1089. }
  1090. .fade-scale-enter-from,
  1091. .fade-scale-leave-to {
  1092. opacity: 0.1;
  1093. transform: scale(0.9);
  1094. }
  1095. // 自定义试题弹框背景
  1096. .child-dialog-wrapper {
  1097. position: fixed;
  1098. top: 0;
  1099. left: 0;
  1100. right: 0;
  1101. bottom: 0;
  1102. background-color: rgba(0, 0, 0, 0.6); // 半透明背景
  1103. display: flex;
  1104. justify-content: center;
  1105. align-items: center;
  1106. z-index: 1000;
  1107. }
  1108. .child-dialog {
  1109. border: none;
  1110. border-radius: rpx(15);
  1111. background: rgb(255, 255, 255, 0.8); // 柔和的蓝紫色渐变
  1112. overflow: hidden;
  1113. padding: rpx(5);
  1114. // width: 40%;
  1115. // height: 60%;
  1116. position: relative;
  1117. }
  1118. // AI对话弹框样式
  1119. .ai-dialog-wrapper {
  1120. position: fixed;
  1121. top: 0;
  1122. left: 0;
  1123. right: 0;
  1124. bottom: 0;
  1125. display: flex;
  1126. justify-content: flex-end;
  1127. align-items: center;
  1128. z-index: 1001;
  1129. pointer-events: none;
  1130. }
  1131. .ai-dialog {
  1132. border: none;
  1133. border-radius: rpx(15);
  1134. background: rgb(255, 255, 255, 0.8);
  1135. overflow: hidden;
  1136. padding: rpx(20);
  1137. width: 30%;
  1138. // 增加高度
  1139. height: 80%;
  1140. margin-right: rpx(50);
  1141. pointer-events: auto;
  1142. position: relative;
  1143. display: flex;
  1144. flex-direction: column;
  1145. &::before {
  1146. content: '';
  1147. position: absolute;
  1148. top: 0;
  1149. left: 0;
  1150. width: 100%;
  1151. height: rpx(10);
  1152. }
  1153. }
  1154. .ai-dialog-header {
  1155. position: relative;
  1156. display: flex;
  1157. justify-content: center;
  1158. align-items: center;
  1159. margin-bottom: rpx(15);
  1160. margin-top: rpx(-10);
  1161. img {
  1162. width: rpx(15);
  1163. }
  1164. h3 {
  1165. color: black;
  1166. font-size: rpx(12);
  1167. }
  1168. .close-btn {
  1169. padding: 0;
  1170. width: rpx(20);
  1171. height: rpx(20);
  1172. font-size: rpx(16);
  1173. line-height: 1;
  1174. position: absolute;
  1175. background-color: transparent;
  1176. border: none;
  1177. margin-left: rpx(200);
  1178. }
  1179. }
  1180. .ai-dialog-content {
  1181. flex: 1;
  1182. display: flex;
  1183. flex-direction: column;
  1184. }
  1185. .ai-message-history {
  1186. flex: 1;
  1187. // 当内容超出容器高度时,显示垂直滚动条
  1188. overflow-y: auto;
  1189. margin-bottom: rpx(15);
  1190. // 可以根据实际情况调整最大高度
  1191. font-size: rpx(5);
  1192. max-height: 50vh;
  1193. // padding: 5px 10px;
  1194. .message {
  1195. display: flex;
  1196. align-items: flex-start;
  1197. margin-bottom: rpx(10);
  1198. &.user {
  1199. flex-direction: row-reverse;
  1200. }
  1201. .avatar {
  1202. width: rpx(30);
  1203. height: rpx(30);
  1204. border-radius: 50%;
  1205. margin: 0 rpx(10);
  1206. }
  1207. .user {
  1208. width: 15px;
  1209. height: 15px;
  1210. }
  1211. .message-content {
  1212. background-color: #ffffff;
  1213. font-size: rpx(5);
  1214. max-width: 80%;
  1215. color: black;
  1216. box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
  1217. }
  1218. }
  1219. // 滚动条整体样式
  1220. &::-webkit-scrollbar {
  1221. width: rpx(4); // 滚动条宽度
  1222. }
  1223. // 滚动条滑块样式
  1224. &::-webkit-scrollbar-thumb {
  1225. background-color: $primary-color; // 滑块颜色
  1226. border-radius: rpx(4); // 滑块圆角
  1227. transition: background-color 0.3s ease; // 颜色过渡效果
  1228. &:hover {
  1229. //background-color: darken($primary-color, 10%); // 悬停时滑块颜色加深
  1230. }
  1231. }
  1232. // 滚动条轨道样式
  1233. &::-webkit-scrollbar-track {
  1234. background-color: rgba($primary-color, 0.2); // 轨道颜色
  1235. border-radius: rpx(4); // 轨道圆角
  1236. }
  1237. .message {
  1238. display: flex;
  1239. align-items: flex-start;
  1240. margin-bottom: rpx(10);
  1241. &.user {
  1242. flex-direction: row-reverse;
  1243. }
  1244. .avatar {
  1245. width: rpx(30);
  1246. height: rpx(30);
  1247. border-radius: 50%;
  1248. margin: 0 rpx(10);
  1249. }
  1250. .message-content {
  1251. background-color: white;
  1252. padding: rpx(8) rpx(12);
  1253. border-radius: rpx(5);
  1254. font-size: rpx(8);
  1255. color: black;
  1256. max-width: 80%;
  1257. box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
  1258. }
  1259. }
  1260. }
  1261. // 优化发送按钮样式
  1262. .send-button {
  1263. //background: linear-gradient(90deg, $primary-color, $secondary-color);
  1264. border: none;
  1265. color: white;
  1266. &:hover {
  1267. //background: linear-gradient(90deg, darken($primary-color, 5%), darken($secondary-color, 5%));
  1268. }
  1269. }
  1270. </style>
  1271. <style lang="scss">
  1272. // 搜索下拉框样式
  1273. @use 'sass:math';
  1274. // 定义rpx转换函数
  1275. @function rpx($px) {
  1276. @return math.div($px, 750) * 100vw;
  1277. }
  1278. /* 消除小三角 */
  1279. .el-popper__arrow {
  1280. display: none;
  1281. }
  1282. .el-popper.is-light,
  1283. .el-dropdown__popper.el-popper {
  1284. background: transparent;
  1285. border: none;
  1286. box-shadow: none;
  1287. }
  1288. .el-dropdown__popper {
  1289. --el-dropdown-menuItem-hover-color: none;
  1290. }
  1291. .el-autocomplete-suggestion .el-scrollbar__wrap {
  1292. margin: 0 auto;
  1293. background-color: rgba(255, 255, 255, 0.7);
  1294. border: 2px solid white;
  1295. border-radius: rpx(5);
  1296. backdrop-filter: blur(rpx(5));
  1297. }
  1298. .el-autocomplete-suggestion li {
  1299. color: black;
  1300. font-size: rpx(7);
  1301. padding: rpx(5) rpx(8); // 调整下拉项内边距
  1302. }
  1303. .el-autocomplete-suggestion li:hover {
  1304. background: linear-gradient(to bottom, #ffefb0, #ffcc00);
  1305. }
  1306. </style>
  1307. <style scoped lang="scss">
  1308. @use 'sass:math';
  1309. // 定义rpx转换函数
  1310. @function rpx($px) {
  1311. @return math.div($px, 750) * 100vw;
  1312. }
  1313. .default-messages {
  1314. margin-top: rpx(-10);
  1315. margin-bottom: rpx(5);
  1316. }
  1317. .contentClass{
  1318. width: 70%;
  1319. height: 80%;
  1320. margin: 0 auto;
  1321. border-radius: rpx(15);
  1322. overflow: hidden;
  1323. }
  1324. </style>