AIDevelop.vue 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. <template>
  2. <!-- AI发展历程 -->
  3. <div class="home-container">
  4. <!-- 添加抽屉 -->
  5. <div class="drawer-box">
  6. <el-button
  7. v-if="!drawerVisible"
  8. type="primary"
  9. @click="drawerVisible = true"
  10. @closed="buttonVisible = false"
  11. class="toggle-button"
  12. >
  13. 课程小节
  14. </el-button>
  15. <el-drawer v-model="drawerVisible" direction="ltr" size="20%">
  16. <el-row class="tac">
  17. <el-col :span="12">
  18. <h3 class="mb-2">课程小节</h3>
  19. <el-menu
  20. default-active="1"
  21. class="el-menu-vertical-demo"
  22. @open="handleOpen"
  23. @close="handleClose"
  24. @select="handleSelect"
  25. :default-openeds="['1']"
  26. >
  27. <template v-for="item in menuItems" :key="item.index">
  28. <el-menu-item v-if="!item.children" :index="item.index">{{
  29. item.title
  30. }}</el-menu-item>
  31. <el-sub-menu v-else :index="item.index">
  32. <template #title>
  33. <span>{{ item.title }}</span>
  34. </template>
  35. <el-menu-item-group v-if="item.children">
  36. <template v-for="child in item.children" :key="child.index">
  37. <el-menu-item :index="child.index">{{
  38. child.title
  39. }}</el-menu-item>
  40. </template>
  41. </el-menu-item-group>
  42. </el-sub-menu>
  43. </template>
  44. </el-menu>
  45. </el-col>
  46. </el-row>
  47. </el-drawer>
  48. </div>
  49. <div class="box-1">
  50. <div class="inner-box left-box">
  51. <div class="box-icon" @click="goBack">
  52. <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
  53. {{ boxIconTitle }}
  54. </div>
  55. </div>
  56. <div class="inner-box right-box">
  57. <div class="top-right-box">
  58. <el-input
  59. v-model="SearchInput"
  60. class="search-input"
  61. placeholder="搜索"
  62. >
  63. <template #prefix>
  64. <el-icon class="el-input__icon"><search /></el-icon>
  65. </template>
  66. </el-input>
  67. </div>
  68. </div>
  69. </div>
  70. <div class="box-2">
  71. <!-- 课程标题 autoplay自动播放 @ended="playNextVideo"-->
  72. <div class="small-title">
  73. <span>{{ smallTitle }}</span>
  74. </div>
  75. <video
  76. class="full-box-video"
  77. :src="videoSrc"
  78. controls
  79. @timeupdate="handleTimeUpdate"
  80. ref="videoRef"
  81. >
  82. <source :src="videoSrc" type="video/mp4" />
  83. 您的浏览器不支持视频播放。
  84. </video>
  85. <!-- 添加切换视频 -->
  86. <div class="video-switch">
  87. <!-- 上一个视频 -->
  88. <div class="caret-left" @click="playPreviousVideo">
  89. <el-icon class="caret-left-icon"><CaretLeft /></el-icon>
  90. </div>
  91. <!-- 下一个视频 -->
  92. <div class="caret-right" @click="playNextVideo">
  93. <el-icon class="caret-right-icon"><CaretRight /></el-icon>
  94. </div>
  95. </div>
  96. </div>
  97. <!-- 添加试题弹框 -->
  98. <div
  99. v-show="questionDialogVisible"
  100. class="child-dialog-wrapper"
  101. @click.self="handleCloseQuestionDialog"
  102. >
  103. <div class="child-dialog">
  104. <div class="question-title">
  105. <span class="question-icon">?</span>
  106. {{ currentQuestion.title }}
  107. </div>
  108. <!-- 选项区域 -->
  109. <div v-if="currentQuestion.options && currentQuestion.options.length > 0" class="options-container">
  110. <div
  111. v-for="(option, index) in currentQuestion.options"
  112. :key="index"
  113. class="question-option"
  114. >
  115. <el-radio v-model="selectedOption" :label="index" :value="option" v-cloak="selectedOption = option">
  116. <span>{{ option }}</span>
  117. </el-radio>
  118. </div>
  119. </div>
  120. <div v-else class="no-options">
  121. 暂无选项
  122. </div>
  123. <!-- 底部按钮 -->
  124. <div class="dialog-footer">
  125. <el-button class="child-button cancel" @click="questionDialogVisible = false; showAIDialog = false">取消</el-button>
  126. <el-button class="child-button confirm" @click="handleSubmitAnswer">确定</el-button>
  127. </div>
  128. <!-- 右侧小图标 -->
  129. <div class="ai-icon-container" @click="handleAIClick">
  130. <img src="@/assets/images/xiaozhi.png" alt="AI对话" class="ai-icon" />
  131. <span class="ai-text">AI助手</span>
  132. </div>
  133. </div>
  134. </div>
  135. <!-- AI对话弹框 -->
  136. <div
  137. v-show="showAIDialog"
  138. class="ai-dialog-wrapper"
  139. @click.self="showAIDialog = false"
  140. >
  141. <div class="ai-dialog">
  142. <div class="ai-dialog-header">
  143. <h3>小智智能助手</h3>
  144. <el-button @click="showAIDialog = false" class="close-btn">×</el-button>
  145. </div>
  146. <div class="ai-dialog-content">
  147. <div class="ai-message-history">
  148. <div
  149. v-for="(message, index) in messageHistory"
  150. :key="index"
  151. :class="['message', message.type]"
  152. >
  153. <img
  154. v-if="message.type === 'user'"
  155. src="@/assets/images/user.png"
  156. class="avatar user"
  157. />
  158. <img
  159. v-else
  160. src="@/assets/images/xiaozhi.png"
  161. class="avatar"
  162. />
  163. <div class="message-content">
  164. {{ message.content }}
  165. </div>
  166. </div>
  167. </div>
  168. <el-input
  169. v-model="userMessage"
  170. placeholder="输入问题..."
  171. class="user-input"
  172. @keyup.enter="sendMessage"
  173. >
  174. <template #append class="flex flex-wrap items-center mb-4">
  175. <!-- <el-button @click="sendMessage" class="child-button confirm">发送</el-button>-->
  176. <el-button @click="sendMessage" size="large" round>发送</el-button>
  177. </template>
  178. </el-input>
  179. </div>
  180. </div>
  181. </div>
  182. </div>
  183. </template>
  184. <script setup>
  185. import { ref, onMounted } from 'vue'
  186. import { useRouter } from 'vue-router'
  187. import { ArrowDown, ArrowRightBold, CaretRight,CaretLeft } from '@element-plus/icons-vue'
  188. import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
  189. import { valueEquals } from 'element-plus'
  190. // 引入视频
  191. import video1 from '@/assets/02video/01video.mp4'
  192. import video2 from '@/assets/02video/02video.mp4'
  193. import video3 from '@/assets/02video/03video.mp4'
  194. import video4 from '@/assets/02video/04video.mp4'
  195. import video5 from '@/assets/02video/05video.mp4'
  196. import video6 from '@/assets/02video/06video.mp4'
  197. import video7 from '@/assets/02video/07video.mp4'
  198. import video8 from '@/assets/02video/08video.mp4'
  199. import video9 from '@/assets/02video/09video.mp4'
  200. import video10 from '@/assets/02video/10video.mp4'
  201. import video11 from '@/assets/02video/11video.mp4'
  202. import video12 from '@/assets/02video/12video.mp4'
  203. import video13 from '@/assets/02video/13video.mp4'
  204. import video14 from '@/assets/02video/14video.mp4'
  205. import video15 from '@/assets/02video/15video.mp4'
  206. const router = useRouter() // 获取当前路由对象
  207. // 搜索框
  208. const SearchInput = ref('')
  209. // 添加按钮显示状态
  210. const buttonVisible = ref(false)
  211. // 添加抽屉显示状态
  212. const drawerVisible = ref(false)
  213. // 定义映射
  214. const videoMap = {
  215. '1-1': video1,
  216. '1-2': video2,
  217. '1-3': video3,
  218. '1-4': video4,
  219. '1-5': video5,
  220. '1-6': video6,
  221. '1-7': video7,
  222. '1-8': video8,
  223. '1-9': video9,
  224. '1-10': video10,
  225. '1-11': video11,
  226. '1-12': video12,
  227. '1-13': video13,
  228. '1-14': video14,
  229. '1-15': video15
  230. }
  231. // 定义视频源
  232. const videoSrc = ref(video1)
  233. // 返回上一页
  234. const goBack = () => {
  235. router.go(-1)
  236. }
  237. // 渲染页面标题
  238. const boxIconTitle = ref('')
  239. onMounted(() => {
  240. const title = router.currentRoute.value.query.title
  241. if (title) {
  242. boxIconTitle.value = String(title)
  243. }
  244. })
  245. // 菜单打开和关闭的处理函数
  246. const handleOpen = () => {}
  247. const handleClose = () => {}
  248. // 动态渲染树型结构
  249. const menuItems = ref([
  250. { index: '1-1', title: '课前回顾' },
  251. { index: '1-2', title: '课程引入' },
  252. {
  253. index: '1',
  254. title: '知识讲解',
  255. children: [
  256. { index: '1-3', title: '图灵测试' },
  257. { index: '1-4', title: '课堂提问' },
  258. { index: '1-5', title: '达特茅斯会议' },
  259. { index: '1-6', title: '课堂选择' },
  260. { index: '1-7', title: '聊天机器人' },
  261. { index: '1-8', title: '专家系统' },
  262. { index: '1-9', title: '课堂互动' },
  263. { index: '1-10', title: '互联网快速发展' },
  264. { index: '1-11', title: '黄金时代' },
  265. { index: '1-12', title: '课堂提问' },
  266. { index: '1-13', title: '大模型时代' }
  267. ]
  268. },
  269. { index: '1-14', title: '趣味实操' },
  270. { index: '1-15', title: '课程总结' }
  271. ])
  272. // 当前播放的索引
  273. const currentIndex = ref('1-1')
  274. // 渲染课程标题到视频上方
  275. const smallTitle = ref('课前回顾')
  276. const handleSelect = index => {
  277. const findTitle = items => {
  278. for (const item of items) {
  279. if (item.index === index) {
  280. return item.title
  281. }
  282. if (item.children) {
  283. const result = findTitle(item.children)
  284. if (result) {
  285. return result
  286. }
  287. }
  288. }
  289. return null
  290. }
  291. const title = findTitle(menuItems.value)
  292. if (title) {
  293. smallTitle.value = title
  294. }
  295. // 根据索引切换视频
  296. if (videoMap[index]) {
  297. videoSrc.value = videoMap[index]
  298. currentIndex.value = index
  299. }
  300. // 选中标题后关闭抽屉
  301. drawerVisible.value = false
  302. }
  303. // 展平所有菜单项索引
  304. const flattenMenuItems = () => {
  305. const indices = []
  306. const traverse = items => {
  307. for (const item of items) {
  308. if (!item.children) {
  309. indices.push(item.index)
  310. } else {
  311. traverse(item.children)
  312. }
  313. }
  314. }
  315. traverse(menuItems.value)
  316. return indices
  317. }
  318. // 自动播放下一个视频
  319. const playNextVideo = () => {
  320. const allIndices = flattenMenuItems()
  321. const currentIndexInList = allIndices.indexOf(currentIndex.value)
  322. if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
  323. const nextIndex = allIndices[currentIndexInList + 1]
  324. handleSelect(nextIndex)
  325. }
  326. //重置
  327. pausedIndices = ref([])
  328. userMessage = ref('')
  329. messageHistory = ref([])
  330. }
  331. // 切换视频
  332. // 播放上一个视频
  333. const playPreviousVideo = () => {
  334. const allIndices = flattenMenuItems()
  335. const currentIndexInList = allIndices.indexOf(currentIndex.value)
  336. if (currentIndexInList > 0) {
  337. const previousIndex = allIndices[currentIndexInList - 1]
  338. handleSelect(previousIndex)
  339. }
  340. }
  341. // 视频 ref
  342. const videoRef = ref(null)
  343. // 记录已经暂停过的时间点索引
  344. let pausedIndices = ref([])
  345. // 试题弹框显示状态
  346. const questionDialogVisible = ref(false)
  347. // 当前显示的试题
  348. const currentQuestion = ref({ title: '', options: [] })
  349. // 用户选择的选项
  350. const selectedOption = ref(null)
  351. // AI对话弹出框显示状态
  352. let showAIDialog = ref(false)
  353. // 用户输入的消息
  354. let userMessage = ref('')
  355. // 消息历史记录
  356. let messageHistory = ref([])
  357. // 定义每个视频对应的暂停时间和问题
  358. const videoPauseTimes = {
  359. [video2]: {
  360. pauseTimes: [53],
  361. questions: [
  362. {
  363. title: '视频当中发生了什么事情呢?',
  364. options: [],
  365. aiQuestion: '视频当中发生了什么事情呢',
  366. aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
  367. }
  368. ]
  369. },
  370. [video4]: {
  371. pauseTimes: [2],
  372. questions: [
  373. {
  374. title: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
  375. options: [],
  376. aiQuestion: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
  377. aiAnswer: '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
  378. }
  379. ]
  380. },
  381. [video5]: {
  382. pauseTimes: [48],
  383. questions: [
  384. {
  385. title: '1956年达特茅斯会议上提出人工智能的目标是__________?',
  386. options: [],
  387. aiQuestion: '1956年达特茅斯会议上提出人工智能的目标是什么?',
  388. aiAnswer: '原内容:机器能够像人类一样利用知识去解决问题,需要更改'
  389. }
  390. ]
  391. },
  392. [video6]: {
  393. pauseTimes: [5],
  394. },
  395. [video7]: {
  396. pauseTimes: [64,91],
  397. questions: [
  398. {
  399. title: '如果你是聊天机器人,你会怎么回答用户呢?',
  400. options: [],
  401. aiQuestion: '如果你是聊天机器人,你会怎么回答用户呢?',
  402. aiAnswer: '发生什么事情了呢?'
  403. },
  404. {
  405. title: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
  406. options: [],
  407. aiQuestion: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
  408. aiAnswer: '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
  409. '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
  410. }
  411. ]
  412. },
  413. [video8]: {
  414. pauseTimes: [72],
  415. questions: [
  416. {
  417. title: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
  418. options: [],
  419. aiQuestion: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
  420. aiAnswer: '这题没给答案,你自己去查吧!'
  421. }
  422. ]
  423. },
  424. [video9]: {
  425. pauseTimes: [2],
  426. questions: [
  427. {
  428. title: '在生活中,有哪些正在使用的专家系统呢?',
  429. options: [],
  430. aiQuestion: '在生活中,有哪些正在使用的专家系统呢?',
  431. aiAnswer: '在医疗健康领域有复杂疾病协同决策喝Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
  432. }
  433. ]
  434. },
  435. [video11]: {
  436. pauseTimes: [1,90,176],
  437. questions: [
  438. {
  439. title: '怎么会有爆炸声?泡泡怪在这里吗?',
  440. options: [],
  441. aiQuestion: '怎么会有爆炸声?泡泡怪在这里吗?',
  442. aiAnswer: ''
  443. },
  444. {
  445. title: '同学们喜欢下围棋吗?',
  446. options: [],
  447. aiQuestion: '同学们喜欢下围棋吗?',
  448. aiAnswer: ''
  449. },
  450. {
  451. title: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
  452. options: [],
  453. aiQuestion: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
  454. aiAnswer: '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
  455. }
  456. ]
  457. },
  458. [video12]: {
  459. pauseTimes: [1],
  460. },
  461. [video13]: {
  462. pauseTimes: [61],
  463. questions: [
  464. {
  465. title: '我们一起来感受一下大模型吧!',
  466. options: [],
  467. aiQuestion: '我们一起来感受一下大模型吧!',
  468. aiAnswer: ''
  469. }
  470. ]
  471. }
  472. }
  473. // 处理视频时间更新事件
  474. const handleTimeUpdate = () => {
  475. if (!videoRef.value) return
  476. const currentTime = videoRef.value.currentTime
  477. const currentPauseTimes = videoPauseTimes[videoSrc.value]
  478. if (currentPauseTimes) {
  479. currentPauseTimes.pauseTimes.forEach((time, index) => {
  480. // 检查是否到达时间点且还未暂停过
  481. if (currentTime >= time && !pausedIndices.value.includes(index)) {
  482. videoRef.value.pause()
  483. pausedIndices.value.push(index)
  484. // 显示对应的问题
  485. if (currentPauseTimes.questions[index]) {
  486. currentQuestion.value = currentPauseTimes.questions[index]
  487. questionDialogVisible.value = true
  488. }
  489. }
  490. })
  491. }
  492. }
  493. // 关闭试题弹框
  494. const handleCloseQuestionDialog = () => {
  495. questionDialogVisible.value = false
  496. // 继续播放视频
  497. videoRef.value.play()
  498. }
  499. // 提交答案
  500. const handleSubmitAnswer = () => {
  501. // 这里可以添加答案验证逻辑
  502. console.log('用户选择的答案是:', selectedOption.value)
  503. questionDialogVisible.value = false
  504. // 继续播放视频
  505. videoRef.value.play()
  506. selectedOption.value = null
  507. }
  508. // 发送消息
  509. const sendMessage = async () => {
  510. if (userMessage.value.trim()) {
  511. // 添加用户消息到历史记录
  512. messageHistory.value.push({
  513. type: 'user',
  514. content: userMessage.value
  515. })
  516. // 模拟 AI 回复
  517. const aiResponse = await simulateAIResponse(userMessage.value)
  518. messageHistory.value.push({
  519. type: 'ai',
  520. content: aiResponse
  521. })
  522. // 清空输入框
  523. userMessage.value = ''
  524. }
  525. }
  526. // 处理 AI 助手点击事件
  527. const handleAIClick = () => {
  528. // 清空输入框
  529. messageHistory = ref([])
  530. if (currentQuestion.value.aiQuestion) {
  531. userMessage.value = currentQuestion.value.aiQuestion
  532. sendMessage()
  533. userMessage.value = ''
  534. }
  535. showAIDialog.value = true
  536. }
  537. // 模拟 AI 回复
  538. const simulateAIResponse = (question) => {
  539. return new Promise((resolve) => {
  540. setTimeout(() => {
  541. const currentVideoInfo = videoPauseTimes[videoSrc.value]
  542. if (currentVideoInfo) {
  543. const currentQuestionObj = currentVideoInfo.questions.find(q => q.aiQuestion === question)
  544. if (currentQuestionObj && currentQuestionObj.aiAnswer) {
  545. resolve(currentQuestionObj.aiAnswer)
  546. return
  547. }
  548. }
  549. // 若未匹配到自定义回复,给出默认回复
  550. resolve(`您的问题是:${question},这是 AI 的回复示例。`)
  551. }, 1000)
  552. })
  553. }
  554. // 关闭AI对话弹出框
  555. const handleCloseAIDialog = () => {
  556. showAIDialog.value = false
  557. }
  558. </script>
  559. <style scoped lang="scss">
  560. @use 'sass:math';
  561. // 定义rpx转换函数
  562. @function rpx($px) {
  563. @return math.div($px, 750) * 100vw;
  564. }
  565. // 定义儿童风格的蓝紫色调
  566. $primary-color: rgba(106, 90, 205, 0.52); // 主色调:蓝紫色
  567. $secondary-color: rgba(147, 112, 219, 0.66); // 辅助色:亮蓝紫色
  568. $accent-color: rgb(133, 89, 220); // 强调色:暗蓝紫色
  569. $light-color: #e6e6fa; // 浅色背景:淡紫色
  570. $text-color: #483d8b; // 文本颜色:靛蓝色
  571. .home-container {
  572. position: fixed;
  573. top: 0;
  574. left: 0;
  575. right: 0;
  576. bottom: 0;
  577. background: linear-gradient(to bottom, #001169, #B4A8E1);
  578. display: flex;
  579. flex-direction: column;
  580. gap: rpx(0);
  581. }
  582. .tac ::v-deep(.el-menu) {
  583. background-color: transparent;
  584. border: none;
  585. width: 100%;
  586. }
  587. /* 取消点击后的蓝色字体 el-sub-menu__title*/
  588. .tac ::v-deep(.el-menu-item.is-active),
  589. .tac ::v-deep(.el-sub-menu__title.is-active) {
  590. color: black;
  591. }
  592. // 取消鼠标悬浮颜色
  593. .tac ::v-deep(.el-sub-menu__title) {
  594. width: rpx(130);
  595. height: rpx(20);
  596. margin-bottom: rpx(5);
  597. border-radius: rpx(6);
  598. }
  599. .el-menu ::v-deep(.el-sub-menu__title:hover),
  600. .el-menu ::v-deep(.el-sub-menu__title:focus),
  601. .el-menu ::v-deep(.el-sub-menu__title:active) {
  602. background: linear-gradient(
  603. to bottom,
  604. #fee78a,
  605. #ffce1b
  606. ); /* 设置悬停、聚焦、点击状态下的背景色 */
  607. background-color: transparent;
  608. }
  609. .drawer-box ::v-deep(.el-drawer__header) {
  610. margin-bottom: rpx(0);
  611. }
  612. .mb-2 {
  613. color: black;
  614. margin-top: rpx(1);
  615. }
  616. .el-menu-item {
  617. width: rpx(130);
  618. height: rpx(20);
  619. margin-bottom: rpx(5);
  620. border-radius: rpx(6);
  621. }
  622. .el-menu-item span {
  623. color: black;
  624. font-size: rpx(8);
  625. }
  626. .el-menu ::v-deep(.el-menu-item:hover),
  627. .el-menu ::v-deep(.el-menu-item:focus),
  628. .el-menu ::v-deep(.el-menu-item:active) {
  629. background: linear-gradient(
  630. to bottom,
  631. #fee78a,
  632. #ffce1b
  633. ); /* 设置悬停、聚焦、点击状态下的背景色 */
  634. }
  635. .drawer-box {
  636. position: absolute;
  637. display: flex;
  638. align-items: center;
  639. height: 100%;
  640. }
  641. .drawer-box .toggle-button {
  642. width: rpx(10);
  643. height: rpx(50);
  644. font-size: rpx(7);
  645. background-color: rgba(17, 23, 29, 0.2);
  646. border: none;
  647. position: relative;
  648. writing-mode: vertical-lr; // 文字垂直排列,从左到右
  649. text-orientation: upright; // 文字保持正立
  650. }
  651. .toggle-button:hover {
  652. left: 0;
  653. }
  654. // 抽屉滚动条样式
  655. .drawer-box ::v-deep(.el-drawer.ltr) {
  656. background-color: rgb(255, 255, 255, 0.7);
  657. box-shadow: 0 8px 8px rgba(202, 52, 52, 0.1);
  658. }
  659. .drawer-box ::v-deep(.el-drawer__body)::-webkit-scrollbar {
  660. width: rpx(2);
  661. }
  662. .drawer-box ::v-deep(.el-drawer__body)::-webkit-scrollbar-thumb {
  663. background-color: rgba(0, 0, 0, 0.2);
  664. border-radius: 8px;
  665. }
  666. .drawer-box ::v-deep(.el-drawer__body)::-webkit-scrollbar-track {
  667. background-color: rgba(0, 0, 0, 0.05);
  668. border-radius: 8px;
  669. }
  670. .toggle-button.is-active,
  671. .toggle-button:active,
  672. .toggle-button:focus {
  673. background-color: rgba(165, 209, 247, 0.8);
  674. color: black;
  675. border: none; // 移除点击时的边框
  676. outline: none; // 移除点击时的外边框
  677. }
  678. .box-1 {
  679. width: 100%;
  680. height: rpx(50);
  681. // margin-top: rpx(10);
  682. display: flex;
  683. justify-content: center;
  684. align-items: center;
  685. box-sizing: border-box;
  686. font-size: rpx(15); // 默认字体大小
  687. }
  688. .inner-box {
  689. height: 100%;
  690. display: flex;
  691. justify-content: center;
  692. align-items: center;
  693. font-size: rpx(16); // 默认字体大小
  694. }
  695. .left-box {
  696. position: relative;
  697. justify-content: flex-start;
  698. align-items: flex-start;
  699. flex: 1; // 设置左侧盒子占比为 2
  700. cursor: pointer; // 添加鼠标指针样式
  701. }
  702. .box-icon {
  703. width: 100%;
  704. height: 100%;
  705. flex: 1;
  706. display: flex; // 添加 flex 布局
  707. align-items: center; // 垂直居中
  708. color: white; // 设置图标颜色为白色
  709. padding-left: rpx(15);
  710. font-size: rpx(10); // 设置图标大小,可按需调整
  711. }
  712. .box-icon .left-icon {
  713. margin-left: rpx(10);
  714. margin-right: rpx(5); // 设置图标和文字之间的间距 ;
  715. }
  716. .left-box span {
  717. position: absolute;
  718. font-size: rpx(11); // 默认字体大小
  719. color: white;
  720. }
  721. .right-box {
  722. flex: 1;
  723. position: relative; // 添加相对定位;
  724. }
  725. .top-right-box {
  726. position: absolute; // 添加绝对定位
  727. margin-top: rpx(20); // 调整上边距离
  728. margin-right: rpx(50); // 调整右边距离
  729. width: 100%; // 设置盒子宽度,可按需调整
  730. height: 60px; // 设置盒子高度,可按需调整
  731. display: flex;
  732. justify-content: flex-end;
  733. }
  734. .top-right-box {
  735. ::v-deep(.el-input__wrapper) {
  736. background-color: transparent;
  737. border-radius: rpx(12);
  738. color: white;
  739. }
  740. ::v-deep(.el-input__icon) {
  741. color: white; // 设置输入框图标颜色为白色
  742. }
  743. // 添加占位符样式
  744. ::v-deep(.el-input__inner::placeholder) {
  745. color: white;
  746. }
  747. // 添加输入框文字颜色样式
  748. ::v-deep(.el-input__inner) {
  749. color: white;
  750. }
  751. }
  752. // 搜索框
  753. .search-input {
  754. width: rpx(100);
  755. height: rpx(15);
  756. font-size: rpx(7);
  757. }
  758. .box-2 {
  759. width: 100%;
  760. flex: 1;
  761. box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
  762. box-sizing: border-box;
  763. // padding: rpx(-20) rpx(20); // 添加左右内边距
  764. display: flex; // 确保子元素水平排列
  765. flex-wrap: wrap; // 允许子元素换行;
  766. align-content: center; // 顶部对齐;
  767. cursor: pointer; // 添加鼠标指针样式
  768. video.full-box-video {
  769. width: rpx(550);
  770. height: rpx(250);
  771. margin: 0 auto;
  772. border-radius: rpx(12);
  773. box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
  774. object-fit: cover;
  775. // object-fit: contain;
  776. }
  777. }
  778. .small-title {
  779. width: 100%;
  780. margin-top: rpx(-20);
  781. height: rpx(20);
  782. color: white;
  783. font-size: rpx(10);
  784. justify-content: center; //使子元素水平居中
  785. }
  786. .video-switch {
  787. width: 100%;
  788. // height: rpx(50);
  789. display: flex;
  790. margin-top: rpx(10);
  791. // background-color: saddlebrown;
  792. }
  793. .caret-right,
  794. .caret-left{
  795. width: rpx(20);
  796. height: rpx(20);
  797. margin: auto;
  798. border-radius: rpx(50);
  799. border: 2px solid white;
  800. }
  801. .caret-right-icon,
  802. .caret-left-icon{
  803. font-size: rpx(20);
  804. color: white;
  805. }
  806. // 儿童风格试题弹框样式
  807. .child-dialog {
  808. .el-dialog__header {
  809. display: none; // 隐藏原有的标题栏
  810. }
  811. .el-dialog__body {
  812. padding: rpx(20);
  813. position: relative;
  814. }
  815. .el-dialog__footer {
  816. border-top: none;
  817. padding: rpx(10) rpx(20);
  818. text-align: center;
  819. }
  820. .el-dialog__wrapper {
  821. // 修改半透明背景色
  822. background-color: rgba(0, 0, 0, 0.6);
  823. }
  824. .el-dialog {
  825. border: none;
  826. border-radius: rpx(20);
  827. background: linear-gradient(135deg, $light-color, #d8bfd8); // 柔和的蓝紫色渐变
  828. // 添加边框边晕效果
  829. box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
  830. overflow: hidden;
  831. // 添加装饰元素
  832. &::before {
  833. content: "";
  834. position: absolute;
  835. top: 0;
  836. left: 0;
  837. width: 100%;
  838. height: rpx(10);
  839. background: linear-gradient(90deg, $primary-color, $secondary-color, $accent-color);
  840. }
  841. }
  842. }
  843. // AI对话弹出框样式
  844. .ai-dialog {
  845. .el-dialog__header {
  846. background: linear-gradient(90deg, $primary-color, $secondary-color);
  847. color: white;
  848. padding: rpx(10) rpx(20);
  849. border-radius: rpx(10) rpx(10) 0 0;
  850. .el-dialog__title {
  851. font-size: rpx(12);
  852. }
  853. }
  854. .el-dialog__body {
  855. padding: rpx(15);
  856. background-color: white;
  857. }
  858. .el-dialog__footer {
  859. border-top: none;
  860. padding: rpx(10) rpx(20);
  861. text-align: right;
  862. }
  863. .el-dialog {
  864. border-radius: rpx(10);
  865. // 修改半透明背景色
  866. background-color: rgba(255, 255, 255, 0.95);
  867. // 添加边框边晕效果
  868. box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
  869. }
  870. }
  871. // 问题标题样式
  872. .question-title {
  873. background: linear-gradient(90deg, rgba($primary-color, 0.2), rgba($secondary-color, 0.2));
  874. padding: rpx(15);
  875. border-radius: rpx(12);
  876. margin-bottom: rpx(20);
  877. color: $accent-color;
  878. font-weight: bold;
  879. font-size: rpx(14);
  880. box-shadow: 0 rpx(3) rpx(10) rgba($primary-color, 0.1);
  881. position: relative;
  882. display: flex;
  883. align-items: center;
  884. .question-icon {
  885. background-color: $accent-color;
  886. color: white;
  887. width: rpx(24);
  888. height: rpx(24);
  889. border-radius: 50%;
  890. display: flex;
  891. align-items: center;
  892. justify-content: center;
  893. margin-right: rpx(10);
  894. font-weight: bold;
  895. box-shadow: 0 rpx(2) rpx(5) rgba($accent-color, 0.3);
  896. }
  897. }
  898. // 选项容器样式
  899. .options-container {
  900. margin-bottom: rpx(20);
  901. }
  902. // 问题选项样式
  903. .question-option {
  904. margin: rpx(8) 0;
  905. padding: rpx(10) rpx(15);
  906. border-radius: rpx(12);
  907. border: rpx(1) solid rgba($primary-color, 0.3);
  908. transition: all 0.3s ease;
  909. display: flex;
  910. align-items: center;
  911. background-color: white;
  912. box-shadow: 0 rpx(2) rpx(5) rgba($primary-color, 0.05);
  913. ::v-deep(.el-radio__label) {
  914. color: $text-color;
  915. margin-left: rpx(8);
  916. flex: 1;
  917. text-align: left;
  918. // 增大字体大小
  919. font-size: rpx(12);
  920. }
  921. // 选中时的样式变化
  922. .el-radio__input.is-checked + .el-radio__label {
  923. font-weight: bold;
  924. color: $accent-color;
  925. }
  926. &:hover {
  927. background-color: rgba($primary-color, 0.05);
  928. border-color: rgba($primary-color, 0.5);
  929. transform: translateY(-rpx(1));
  930. }
  931. }
  932. // 暂无选项样式
  933. .no-options {
  934. color: rgba($text-color, 0.7);
  935. text-align: center;
  936. padding: rpx(20);
  937. font-size: rpx(12);
  938. }
  939. // 底部按钮样式
  940. .child-button {
  941. min-width: rpx(80);
  942. height: rpx(30);
  943. border-radius: rpx(15);
  944. font-size: rpx(12);
  945. font-weight: 500;
  946. transition: all 0.3s ease;
  947. box-shadow: 0 rpx(2) rpx(8) rgba(0, 0, 0, 0.1);
  948. &.confirm {
  949. background: linear-gradient(to right, $primary-color, $secondary-color);
  950. border: none;
  951. border-right: 15px;;
  952. color: white;
  953. &:hover {
  954. background: linear-gradient(to right, darken($primary-color, 5%), darken($secondary-color, 5%));
  955. box-shadow: 0 rpx(3) rpx(10) rgba($primary-color, 0.4);
  956. transform: translateY(-rpx(1));
  957. color: white;
  958. }
  959. }
  960. &.cancel {
  961. background: white;
  962. border: rpx(1) solid rgba($primary-color, 0.3);
  963. color: $text-color;
  964. &:hover {
  965. background: rgba($primary-color, 0.05);
  966. border-color: rgba($primary-color, 0.5);
  967. transform: translateY(-rpx(1));
  968. }
  969. }
  970. }
  971. // AI对话图标样式
  972. .ai-icon-container {
  973. position: absolute;
  974. bottom: rpx(20);
  975. right: rpx(20);
  976. display: flex;
  977. flex-direction: column;
  978. align-items: center;
  979. cursor: pointer;
  980. transition: all 0.3s ease;
  981. &:hover {
  982. transform: translateY(-rpx(2));
  983. }
  984. .ai-icon {
  985. width: rpx(30);
  986. height: rpx(30);
  987. margin-bottom: rpx(0);
  988. filter: drop-shadow(0 rpx(2) rpx(4) rgba($primary-color, 0.3));
  989. // 添加过渡动画
  990. transition: transform 0.3s ease;
  991. }
  992. // 悬浮时放大效果
  993. .ai-icon:hover {
  994. transform: scale(1.5);
  995. }
  996. .ai-text {
  997. color: $text-color;
  998. font-size: rpx(8);
  999. background-color: rgba(255, 255, 255, 0.7);
  1000. padding: rpx(2) rpx(5);
  1001. border-radius: rpx(5);
  1002. }
  1003. }
  1004. // AI对话弹出框样式
  1005. .ai-dialog {
  1006. .el-dialog__header {
  1007. background: linear-gradient(90deg, $primary-color, $secondary-color);
  1008. color: white;
  1009. padding: rpx(10) rpx(20);
  1010. border-radius: rpx(10) rpx(10) 0 0;
  1011. .el-dialog__title {
  1012. font-size: rpx(12);
  1013. }
  1014. }
  1015. .el-dialog__body {
  1016. padding: rpx(15);
  1017. background-color: white;
  1018. }
  1019. .el-dialog__footer {
  1020. border-top: none;
  1021. padding: rpx(10) rpx(20);
  1022. text-align: right;
  1023. }
  1024. .el-dialog {
  1025. border-radius: rpx(10);
  1026. box-shadow: 0 rpx(10) rpx(30) rgba(0, 0, 0, 0.15);
  1027. }
  1028. }
  1029. // AI消息样式
  1030. .ai-message {
  1031. display: flex;
  1032. align-items: flex-start;
  1033. margin-bottom: rpx(15);
  1034. .ai-avatar {
  1035. width: rpx(30);
  1036. height: rpx(30);
  1037. border-radius: 50%;
  1038. margin-right: rpx(10);
  1039. background-color: $primary-color;
  1040. padding: rpx(5);
  1041. box-shadow: 0 rpx(2) rpx(5) rgba($primary-color, 0.2);
  1042. }
  1043. .ai-text-content {
  1044. background-color: $light-color;
  1045. padding: rpx(8) rpx(12);
  1046. border-radius: rpx(10);
  1047. font-size: rpx(10);
  1048. color: $text-color;
  1049. max-width: 80%;
  1050. box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
  1051. }
  1052. }
  1053. // 用户输入框样式
  1054. .user-input {
  1055. ::v-deep(.el-input__wrapper) {
  1056. border-radius: rpx(15);
  1057. border-color: rgba($primary-color, 0.3);
  1058. margin-right: 10px;
  1059. &:focus-within {
  1060. box-shadow: 0 0 0 rpx(1) rgba($primary-color, 0.5);
  1061. }
  1062. }
  1063. ::v-deep(.el-input__inner) {
  1064. font-size: rpx(10);
  1065. color: $text-color;
  1066. text-indent: 1em;
  1067. }
  1068. }
  1069. // 自定义试题弹框背景
  1070. .child-dialog-wrapper {
  1071. position: fixed;
  1072. top: 0;
  1073. left: 0;
  1074. right: 0;
  1075. bottom: 0;
  1076. background-color: rgba(0, 0, 0, 0.6); // 半透明背景
  1077. display: flex;
  1078. justify-content: center;
  1079. align-items: center;
  1080. z-index: 1000;
  1081. }
  1082. .child-dialog {
  1083. border: none;
  1084. border-radius: rpx(20);
  1085. background: linear-gradient(135deg, $light-color, #d8bfd8); // 柔和的蓝紫色渐变
  1086. box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
  1087. overflow: hidden;
  1088. padding: rpx(20);
  1089. width: 60%;
  1090. position: relative;
  1091. // 添加装饰元素
  1092. &::before {
  1093. content: "";
  1094. position: absolute;
  1095. top: 0;
  1096. left: 0;
  1097. width: 100%;
  1098. height: rpx(10);
  1099. background: linear-gradient(90deg, $primary-color, $secondary-color, $accent-color);
  1100. }
  1101. }
  1102. // AI对话弹框样式
  1103. .ai-dialog-wrapper {
  1104. position: fixed;
  1105. top: 0;
  1106. left: 0;
  1107. right: 0;
  1108. bottom: 0;
  1109. display: flex;
  1110. justify-content: flex-end;
  1111. align-items: center;
  1112. z-index: 1001;
  1113. pointer-events: none;
  1114. }
  1115. .ai-dialog {
  1116. border: none;
  1117. border-radius: rpx(20);
  1118. background: linear-gradient(135deg, $light-color, #d8bfd8);
  1119. box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
  1120. overflow: hidden;
  1121. padding: rpx(20);
  1122. width: 30%;
  1123. // 增加高度
  1124. height: 80%;
  1125. margin-right: rpx(50);
  1126. pointer-events: auto;
  1127. position: relative;
  1128. display: flex;
  1129. flex-direction: column;
  1130. &::before {
  1131. content: "";
  1132. position: absolute;
  1133. top: 0;
  1134. left: 0;
  1135. width: 100%;
  1136. height: rpx(10);
  1137. background: linear-gradient(90deg, $primary-color, $secondary-color, $accent-color);
  1138. }
  1139. }
  1140. .ai-dialog-header {
  1141. display: flex;
  1142. justify-content: space-between;
  1143. align-items: center;
  1144. margin-bottom: rpx(15);
  1145. h3 {
  1146. color: $text-color;
  1147. font-size: rpx(12);
  1148. }
  1149. .close-btn {
  1150. padding: 0;
  1151. width: rpx(20);
  1152. height: rpx(20);
  1153. font-size: rpx(16);
  1154. line-height: 1;
  1155. }
  1156. }
  1157. .ai-dialog-content {
  1158. flex: 1;
  1159. display: flex;
  1160. flex-direction: column;
  1161. }
  1162. .ai-message-history {
  1163. flex: 1;
  1164. // 当内容超出容器高度时,显示垂直滚动条
  1165. overflow-y: auto;
  1166. margin-bottom: rpx(15);
  1167. // 可以根据实际情况调整最大高度
  1168. max-height: 50vh;
  1169. padding: 5px 10px;
  1170. .message {
  1171. display: flex;
  1172. align-items: flex-start;
  1173. margin-bottom: rpx(10);
  1174. &.user {
  1175. flex-direction: row-reverse;
  1176. }
  1177. .avatar {
  1178. width: rpx(30);
  1179. height: rpx(30);
  1180. border-radius: 50%;
  1181. margin: 0 rpx(10);
  1182. }
  1183. .user{
  1184. width: 15px;
  1185. height: 15px;
  1186. }
  1187. .message-content {
  1188. background-color: $light-color;
  1189. padding: rpx(8) rpx(12);
  1190. border-radius: rpx(10);
  1191. font-size: rpx(10);
  1192. color: $text-color;
  1193. max-width: 80%;
  1194. box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
  1195. }
  1196. }
  1197. // 滚动条整体样式
  1198. &::-webkit-scrollbar {
  1199. width: rpx(4); // 滚动条宽度
  1200. }
  1201. // 滚动条滑块样式
  1202. &::-webkit-scrollbar-thumb {
  1203. background-color: $primary-color; // 滑块颜色
  1204. border-radius: rpx(4); // 滑块圆角
  1205. transition: background-color 0.3s ease; // 颜色过渡效果
  1206. &:hover {
  1207. background-color: darken($primary-color, 10%); // 悬停时滑块颜色加深
  1208. }
  1209. }
  1210. // 滚动条轨道样式
  1211. &::-webkit-scrollbar-track {
  1212. background-color: rgba($primary-color, 0.2); // 轨道颜色
  1213. border-radius: rpx(4); // 轨道圆角
  1214. }
  1215. .message {
  1216. display: flex;
  1217. align-items: flex-start;
  1218. margin-bottom: rpx(10);
  1219. &.user {
  1220. flex-direction: row-reverse;
  1221. }
  1222. .avatar {
  1223. width: rpx(30);
  1224. height: rpx(30);
  1225. border-radius: 50%;
  1226. margin: 0 rpx(10);
  1227. }
  1228. .message-content {
  1229. background-color: $light-color;
  1230. padding: rpx(8) rpx(12);
  1231. border-radius: rpx(10);
  1232. font-size: rpx(10);
  1233. color: $text-color;
  1234. max-width: 80%;
  1235. box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
  1236. }
  1237. }
  1238. }
  1239. // 优化发送按钮样式
  1240. .send-button {
  1241. //background: linear-gradient(90deg, $primary-color, $secondary-color);
  1242. border: none;
  1243. color: white;
  1244. &:hover {
  1245. //background: linear-gradient(90deg, darken($primary-color, 5%), darken($secondary-color, 5%));
  1246. }
  1247. }
  1248. </style>