diff --git a/src/api/modules/course.js b/src/api/modules/course.js index 197ee0e2..4944d29f 100644 --- a/src/api/modules/course.js +++ b/src/api/modules/course.js @@ -4,7 +4,7 @@ * **/ import ajax from '@/utils/xajax.js' - +import ajax2 from '../unionAjax.js'; /** * 保存课程基本信息,新增和更新都是此方式 * @param {Object} data @@ -446,6 +446,14 @@ const saveTip = function() { } + +// ai播放器相关 - 批量AI设置 +const benchAiSet=function(data){ + return ajax.postJson('/xboe/m/course/manage/benchAiSet',data); +} +const listByUser=function(data){ + return ajax2.get('/manageApi/admin/thirdApi/permission/listByUser?permissionType=PAGE'); +} export default { saveBase, submitCourse, @@ -489,6 +497,8 @@ export default { exportCourse, queryCrowd, ids, - saveTip + saveTip, + benchAiSet, + listByUser, } diff --git a/src/assets/images/course/courseAbstract.png b/src/assets/images/course/courseAbstract.png new file mode 100644 index 00000000..180aeaac Binary files /dev/null and b/src/assets/images/course/courseAbstract.png differ diff --git a/src/assets/images/course/courseNew.png b/src/assets/images/course/courseNew.png new file mode 100644 index 00000000..13d81fcd Binary files /dev/null and b/src/assets/images/course/courseNew.png differ diff --git a/src/assets/images/course/generationFailed.png b/src/assets/images/course/generationFailed.png new file mode 100644 index 00000000..5ca255d5 Binary files /dev/null and b/src/assets/images/course/generationFailed.png differ diff --git a/src/assets/images/course/languageIcon.png b/src/assets/images/course/languageIcon.png new file mode 100644 index 00000000..454e67cb Binary files /dev/null and b/src/assets/images/course/languageIcon.png differ diff --git a/src/assets/images/course/noData.png b/src/assets/images/course/noData.png new file mode 100644 index 00000000..822040e7 Binary files /dev/null and b/src/assets/images/course/noData.png differ diff --git a/src/assets/images/course/selectLanguage.png b/src/assets/images/course/selectLanguage.png new file mode 100644 index 00000000..f13efb3a Binary files /dev/null and b/src/assets/images/course/selectLanguage.png differ diff --git a/src/assets/images/course/wengaoTip.png b/src/assets/images/course/wengaoTip.png new file mode 100644 index 00000000..f83ce6fb Binary files /dev/null and b/src/assets/images/course/wengaoTip.png differ diff --git a/src/assets/styles/btn.scss b/src/assets/styles/btn.scss index e6ba1a8e..0cb69515 100644 --- a/src/assets/styles/btn.scss +++ b/src/assets/styles/btn.scss @@ -97,3 +97,29 @@ font-size: 14px; border-radius: 4px; } +// 已下架 +.custom-takeout{ + display: inline-block; + padding: 3px 13px; + border-radius: 20px; + font-size: 12px; + background: rgba(254, 249, 195, 1); + color: rgba(133, 77, 14, 1); + font-size: 12px; + font-weight: 500; + line-height: 17px; + letter-spacing: 0px; +} +// 已上架 +.custom-putaway{ + display: inline-block; + padding: 3px 13px; + border-radius: 20px; + font-size: 12px; + background: rgba(220, 252, 231, 1); + color: rgba(22, 101, 52, 1); + font-size: 12px; + font-weight: 500; + line-height: 17px; + letter-spacing: 0px; +} \ No newline at end of file diff --git a/src/components/Course/aiScript.vue b/src/components/Course/aiScript.vue new file mode 100644 index 00000000..7fd1c883 --- /dev/null +++ b/src/components/Course/aiScript.vue @@ -0,0 +1,439 @@ + + + + + \ No newline at end of file diff --git a/src/components/Course/courseForm.vue b/src/components/Course/courseForm.vue index ff52f144..1e25a79e 100644 --- a/src/components/Course/courseForm.vue +++ b/src/components/Course/courseForm.vue @@ -208,6 +208,43 @@ placeholder="请尽量填写课程简介,用于列表中显示,可以让用户更容易了解课程信息"> + +
+
+ + + + +
+
+
+
+ AI摘要 + + + + +
+
+ AI文稿 + + + + +
+
+
+ AI翻译语种 + + + + + + +
+
+
+
@@ -390,6 +427,44 @@ placeholder="请尽量填写课程简介,用于列表中显示,可以让用户更容易了解课程信息"> + + +
+
+ + + + +
+
+
+
+ AI摘要 + + + + +
+
+ AI文稿 + + + + +
+
+
+ AI翻译语种 + + + + + + +
+
+
+
+
+
+ {{!currentLang ? 'AI翻译' : currentLangLabel}} +
+
    +
  • {{ item.label }}
  • +
+
+
+
|
+
+ 字幕 + + +
+
|
+
{{currentSpeed === 1 ? '倍速' : `${currentSpeed}x`}}
@@ -224,6 +252,7 @@ import volumeBar from "@/components/VideoPlayer/volume-bar.vue"; import progressBar from "@/components/VideoPlayer/progress-bar.vue"; import playerBarrageScreen from "@/components/VideoPlayer/player-barrage-screen.vue"; +import { mapGetters, mapMutations } from 'vuex'; export default { name: "barrage-videoplayer", @@ -301,12 +330,24 @@ export default { fullTimeFormat: "00:00:00", // 视频总长度的文字 barrageTimelineStart: 0, // 弹幕时间轴的起始时间点(手动调整进度条触发更新) isInit:false, // 是否初始化过 + // ai播放器相关 + isSubtitle: true, // 是否开启字幕 + currentLangLabel:'', // 当前字幕语言 }; }, + // ai播放器相关 + computed: { + ...mapGetters(['selectableLang','currentLang','courseInfo']), + isAiTranslate () { + return this.courseInfo?.aiSet == 1 && this.courseInfo?.aiTranslate == 1 && this.selectableLang && this.selectableLang.length > 0; + } + }, created() { - + // ai播放器相关 + this.SET_currentLang(''); }, mounted() { + console.log('---',this.isAiTranslate,this.courseInfo,'courseInfo'); this.videoDom = this.$refs.video; this.videoDom.focus({preventScroll: true}); let speedValue=localStorage.getItem('boe_video_speed'); @@ -317,7 +358,8 @@ export default { } setInterval(() => { - console.log('当前状态:',this.currentProgress,this.isDrag,this.videoDom.currentTime , this.videoDom.duration) + this.SET_duration(this.videoDom.duration); + console.log('当前状态:',localStorage.getItem('videoProgressData'),this.currentProgress,this.isDrag,this.videoDom.currentTime , this.videoDom.duration) // 视频播放时本地记录视频实时播放时长,视频设置了禁止拖动时执行 if(!this.isDrag){ var time = localStorage.getItem('videoProgressData') @@ -372,6 +414,7 @@ export default { //if() //console.log(this.videoDom.readyState,'this.videoDom.readyState'); }, 1000); + // 视频dom监听器,用于控制鼠标的显示 this.videoDom.addEventListener("mousemove", () => { this.isCursorStatic = false; @@ -411,6 +454,13 @@ export default { // }); }, methods: { + // ai播放器相关 + ...mapMutations({ + SET_currentLang: 'video/SET_currentLang', + SET_currentTime: 'video/SET_currentTime', + SET_selectableLang: 'video/SET_selectableLang', + SET_duration: 'video/SET_duration', + }), //当视频由于需要缓冲下一帧而停止,解决一直计时的问题 onWaiting(){ console.log('触发了onWairing'); @@ -624,6 +674,8 @@ export default { }, onAudioTimeUpdate() { const currentTime = this.$refs.video.currentTime; + // ai播放器相关 + this.SET_currentTime(currentTime) this.$emit('onTimeUpdate', currentTime); }, /** @@ -641,9 +693,77 @@ export default { this.$emit('onFullscreen',false);//全屏 } } + }, + /** ai播放器相关 + * 切换字幕 + */ + toggleSubtitle(value) { + if (this.videoDom && this.videoDom.textTracks && this.videoDom.textTracks.length >0) { + if (!value) { + // 关闭字幕 + this.videoDom.textTracks[this.videoDom.textTracks.length - 1].mode = 'hidden'; + } else { + // 打开字幕 + this.videoDom.textTracks[this.videoDom.textTracks.length - 1].mode = 'showing'; + } + } + }, + /** ai播放器相关 + * 切换字幕语言 + */ + changeLang(item = {}) { + this.SET_currentLang(item.srclang); + this.currentLangLabel = item.label; + console.log("changeLang",item); + // 先移除所有字幕轨道 + Array.from(this.videoDom.querySelectorAll('track')).forEach(t => t.remove()); + if(!item.vttContent){ + console.log("字幕内容为空!") + return; + } + if(!item.srcUrl){ + try{ + const blob = new Blob([item.vttContent], { type: 'text/vtt' }); + item.srcUrl = URL.createObjectURL(blob); + }catch(e){ + console.log("字幕格式错误",e) + } + } + const trackEl = document.createElement('track'); + trackEl.kind = 'subtitles'; + trackEl.srclang = item.srclang; + trackEl.label = item.label; + trackEl.src = item.srcUrl; + trackEl.default = true; // 确保字幕默认启用 + // 使用箭头函数保持this上下文 + trackEl.addEventListener('load', () => { + console.log('字幕加载成功!'); + // console.log('#########Track cues:', trackEl.track.cues); + }); + + trackEl.addEventListener('error', () => { + console.error('字幕加载失败!'); + }); + + // 确保视频已加载到可添加轨道的状态 + if (this.videoDom.readyState >= 1) { + this.videoDom.appendChild(trackEl); + this.videoDom.textTracks[this.videoDom.textTracks.length - 1].mode = 'showing'; + } else { + this.videoDom.addEventListener('loadedmetadata', () => { + this.videoDom.appendChild(trackEl); + this.videoDom.textTracks[this.videoDom.textTracks.length - 1].mode = 'showing'; + }, { once: true }); + } + }, + seekToTime(time) { + if (!this.videoDom) return; + this.videoDom.currentTime = time + 0.01; + this.isPlaying = true; + this.videoDom.play(); + }, - } }, watch: { currentVolume: function () { @@ -668,9 +788,37 @@ export default { // } // }, src: function () { - // 当视频地址变更时,重载视频 + // 当视频地址变更时,先重置字幕再重载视频 + this.isPlaying = false; + // 重置字幕相关状态 + this.SET_currentLang(''); + this.currentLangLabel = ''; + + // 移除所有现有字幕轨道元素 + Array.from(this.videoDom.querySelectorAll('track')).forEach(t => t.remove()); + + // 更彻底地清除字幕:重置所有textTracks + Array.from(this.videoDom.textTracks).forEach(track => { + track.mode = 'hidden'; + // 尝试移除所有cues(浏览器支持的话) + if (track.cues) { + while (track.cues.length > 0) { + track.cues.remove(0); + } + } + }); + + // 重载视频 this.videoDom.load(); - this.isPlaying = false + + // 如果有默认语言且支持AI翻译,重新设置字幕 + // if (this.isAiTranslate && this.selectableLang && this.selectableLang.length > 0) { + // // 找到默认语言或第一个可用语言 + // const defaultLang = this.selectableLang.find(lang => lang.srclang === 'zh-CN') || this.selectableLang[0]; + // if (defaultLang) { + // this.changeLang(defaultLang); + // } + // } }, }, }; @@ -907,6 +1055,12 @@ export default { color: #fff; margin-bottom: 0.5rem; } +.box-aiTranslate{ + display: flex; + align-items: center; + justify-content: center; + gap: 0.4rem; +} @media (device-width: 100vw) { .player-controls-btn .player-controls-icon { /* height: 26px; */ @@ -918,4 +1072,22 @@ export default { height: 100px; } } +video::cue { + /* color: #fff; */ + /* background-color: transparent; */ + /* font-size: 0.85em; */ + /* font-family: 'Arial', sans-serif; + -webkit-text-stroke: 4px #000; + text-stroke: 4px #000; */ + + /* text-shadow: + 2px 2px 0 #000, + -2px 2px 0 #000, + 2px -2px 0 #000, + -2px -2px 0 #000, + 0 2px 0 #000, + 2px 0 0 #000, + 0 -2px 0 #000, + -2px 0 0 #000; */ +} diff --git a/src/data/pages.js b/src/data/pages.js index 5ec52049..f5423b4b 100644 --- a/src/data/pages.js +++ b/src/data/pages.js @@ -117,6 +117,8 @@ export const iframes=[ {title:'嵌入测试', path:'/iframe/index',hidden:false,component:'portal/iframe'}, {title:'课件管理', path:'/iframe/course/coursewares',hidden:false,component:'course/Courseware'}, {title:'课程管理', path:'/iframe/course/manages',hidden:false,component:'course/ManageList'}, + {title:'ai摘要', path:'/iframe/course/aiAbstract',hidden:false,component:'course/aiSet/aiAbstract'}, + {title:'ai翻译', path:'/iframe/course/aiTranslate',hidden:false,component:'course/aiSet/aiTranslate'}, {title:'考试试题管理', path:'/iframe/exam/questions',hidden:false,component:'exam/Question'}, {title:'查看答卷', path:'/iframe/exam/viewanswer',hidden:false,component:'exam/viewAnswer'}, {title:'考试试卷管理', path:'/iframe/exam/papers',hidden:false,component:'exam/TestPaper'}, diff --git a/src/store/getters.js b/src/store/getters.js index 999ef0c6..a9956d27 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -28,5 +28,12 @@ const getters = { studyTaskCount:state => state.user.studyTaskCount, praisesUnicom:state =>state.pdf.praisesUnicom, favoritesUnicom:state =>state.pdf.favoritesUnicom, + // ai播放器相关 + selectAllLang:state => state.video.selectAllLang, + selectableLang:state => state.video.selectableLang, + currentLang:state => state.video.currentLang, + currentTime:state => state.video.currentTime, + courseInfo:state => state.video.courseInfo, + duration:state => state.video.duration, } export default getters diff --git a/src/store/index.js b/src/store/index.js index ff0d0868..a44d8dba 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -12,6 +12,7 @@ import resOwner from './modules/resOwner' import majorType from './modules/majorType' import orgDomain from './modules/orgDomain' import pdf from './modules/pdf' +import video from './modules/video' // ai播放器相关 Vue.use(Vuex) @@ -27,7 +28,8 @@ const store = new Vuex.Store({ resOwner, majorType, orgDomain, - pdf + pdf, + video }, getters }) diff --git a/src/store/modules/video.js b/src/store/modules/video.js new file mode 100644 index 00000000..7227e9e7 --- /dev/null +++ b/src/store/modules/video.js @@ -0,0 +1,171 @@ +// ai播放器相关 + +/** + * +selectAllLang: [ + { + key: 'ZH_CN', + srclang: 'zh-CN', + label: '中文', + name: '中文', + }, + { + key: 'EN_US', + srclang: 'en-US', + label: '英语', + name: 'English', + }, + { + key: 'JA_JP', + srclang: 'ja-JP', + label: '日语', + name: '日本語', + }, + { + key: 'KO_KR', + srclang: 'ko-KR', + label: '韩语', + name: '한국어', + }, + { + key: 'FR_FR', + srclang: 'fr-FR', + label: '法语', + name: 'français', + }, + { + key: 'DE_DE', + srclang: 'de-DE', + label: '德语', + name: 'Deutsch', + }, + { + key: 'ES_ES', + srclang: 'es-ES', + label: '西班牙语', + name: 'español', + }, + { + key: 'RU_RU', + srclang: 'ru-RU', + label: '俄语', + name: 'русский', + }, + { + key: 'PT_BR', + srclang: 'pt-BR', + label: '葡萄牙语', + name: 'português', + }, + { + key: 'IT_IT', + srclang: 'it-IT', + label: '意大利语', + name: 'italiano', + }, + { + key: 'AR_SA', + srclang: 'ar-SA', + label: '阿拉伯语', + name: 'العربية', + }, + { + key: 'TH_TH', + srclang: 'th-TH', + label: '泰语', + name: 'ไทย', + }, + { + key: 'VI_VN', + srclang: 'vi-VN', + label: '越南语', + name: 'tiếng Việt', + }, + { + key: 'ID_ID', + srclang: 'id-ID', + label: '印度尼西亚语', + name: 'Bahasa Indonesia', + }, + { + key: 'HI_IN', + srclang: 'hi-IN', + label: '印地语', + name: 'हिन्दी', + } + ], // 全部语言列表 +*/ + +const state = { + selectAllLang: [ + { + key: 'ZH_CN', + srclang: 'zh-CN', + label: '中文', + name: '中文', + }, + { + key: 'EN_US', + srclang: 'en-US', + label: '英语', + name: 'English', + }, + { + key: 'VI_VN', + srclang: 'vi-VN', + label: '越南语', + name: 'tiếng Việt', + }, + { + key: 'ES_ES', + srclang: 'es-ES', + label: '西班牙语', + name: 'español', + }, + ], // 一期语言列表 + selectableLang: [], // 可选语言列表+字幕信息 + currentLang: '', // 当前选中语言 + currentTime: -1, // 当前视频时间 + courseInfo: {}, + duration: 0, // 视频时长 +} + +const mutations = { + SET_currentLang: (state, lang) => { + state.currentLang = lang + }, + SET_selectableLang: (state, list = []) => { + let selectableLang = [] + list.forEach(item => { + let selectItem = state.selectAllLang.find(selectItem => selectItem.srclang === item.language) + if (selectItem) { + selectableLang.push({ + ...item, + ...selectItem, + }) + } + }) + state.selectableLang = selectableLang + }, + SET_currentTime: (state, time) => { + state.currentTime = time + }, + SET_courseInfo: (state, info) => { + state.courseInfo = info + }, + SET_duration: (state, duration) => { + state.duration = duration + }, +} + +const actions = { + +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/src/views/course/ManageList.vue b/src/views/course/ManageList.vue index 1cc7d4b7..7465884d 100644 --- a/src/views/course/ManageList.vue +++ b/src/views/course/ManageList.vue @@ -60,14 +60,17 @@
搜索 - 重置 + 重置
- - - 新建课程 - + + + + 新建课程 + 设置语种 + 开启AI处理 +
@@ -140,6 +143,8 @@ @@ -397,9 +632,38 @@ export default { }, extendRefId:'', extendRefType:'', + // ai播放器相关 + aiPermission: false, + selectedCourses: [], //已选课程 + languageSetting: { // 设置语种弹框 + dlgShow: false, + languageCode: ['zh-CN', 'en-US'] // 默认选中的语种 + }, + aiProcessSetting: { // 开启AI处理弹框 + dlgShow: false, + aiSet: 1, + aiAbstract: 1, + aiDraft: 1, + languageCode: ['zh-CN', 'en-US'] // 默认选中的语种 + }, + aiSetting: { // AI设置弹框 + dlgShow: false, + courseId: '', + aiSet: 1, + aiAbstract: 1, // 1:上架 0:下架 + aiDraft: 1, // 1:上架 0:下架 + aiTranslate: 1, // 1:上架 0:下架 + languageCode: ['zh-CN', 'en-US', 'vi-VN'] // 支持的语种 + }, + aiSetTip: '是否将课程进行AI处理', //提示信息 + aiAbstractTip: '一键提炼课程视频核心要点,助力学员课前高效掌握重点,快速筛选学习资源', // 提示信息 + aiDraftTip: '分段展示视频内容并精准同步时间轴,实现视频进度与文稿双向定位,学习内容触手可及', //提示信息 + aiTranslateTip: '智能转换视频字幕与语音为多语种,支持全球学员按需切换语言,打破学习边界', // 提示信息 }; }, mounted() { + // ai播放器相关 + this.getAiPermission(); this.getAudiences() let chooseFlag=this.$route.query.f; this.extendRefId=this.$route.query.refId; @@ -431,7 +695,6 @@ export default { }, methods: { - getAudiences(){ apiUserbasic.getInAudienceIds().then(res=>{ if (res.status == 200) { @@ -455,7 +718,6 @@ export default { inputOn() { this.$forceUpdate(); }, - // 置顶 setTop(row) { let params = { @@ -892,6 +1154,150 @@ export default { saveNewCatalogZhang() { this.catalogs.addNewZhang = false; }, + + + // ai播放器相关 + getLanguageName(lang){ + return this.selectAllLang.find(item => item.srclang === lang)?.label || ''; + }, + handleSelectionChange(val){ + this.selectedCourses = val; + console.log(val); + }, + // 获取选中课程的AI信息 + getAIInfoByList(list = []) { + let selectNum = 0; // 选中的课程数量 + let aiSetNum = 0; // 已设置AI的课程数量 + let aiSetNoNum = 0; // 未设置AI的课程数量 + list.forEach(item => { + if(item.aiSet === 1){ + aiSetNum++; + }else{ + aiSetNoNum++; + } + }); + return { + selectNum, + aiSetNum, + aiSetNoNum + } + }, + // AI设置 + setAI(row) { + console.log('row', row); + this.aiSetting = { + dlgShow: true, + ...row + }; + }, + changeAIKey(key) { + this.aiSetting[key] = this.aiSetting[key] === 1 ? 0 : 1; + }, + // 确认AI设置 + confirmAISetting() { + const item = deepCopy(this.aiSetting); + item.languageStatus = item.aiSet; + item.languageCode = item.languageCode || []; + if (!item.languageCode.includes('zh-CN')) { + item.languageCode.unshift('zh-CN'); // 默认添加中文 去重 + } + this._benchAiSet([item], (res) => { + this.$message.success('AI设置保存成功'); + this.aiSetting.dlgShow = false; + // 可以选择是否刷新列表数据 + this.searchData(); + }, (res) => { + this.$message.error('AI设置保存失败!'); + }) + }, + setLanguage() { + if (this.selectedCourses.length > 0) { + this.languageSetting = {...{ + dlgShow: true, + languageCode: ['zh-CN', 'en-US'] // 默认选中的语种 + }, ...this.getAIInfoByList(this.selectedCourses)} + } + }, + enableAI() { + // 开启AI处理按钮点击事件 + if (this.selectedCourses.length > 0) { + this.aiProcessSetting = {...{ + dlgShow: true, + aiSet: 1, + aiAbstract: 1, + aiDraft: 1, + languageCode: ['zh-CN', 'en-US'] // 默认选中的语种 + }, ...this.getAIInfoByList(this.selectedCourses)} + } + }, + // 批量设置语种 - 确认 + confirmLanguageSetting() { + const courseList = deepCopy(this.selectedCourses); + let languageCode = deepCopy(this.languageSetting.languageCode || []); + if (!languageCode.includes('zh-CN')) { + languageCode.unshift('zh-CN'); // 默认添加中文 去重 + } + courseList.forEach(item => { + item.languageCode = languageCode; + item.aiTranslate = item.aiSet; + item.languageStatus = item.aiSet; + }) + this._benchAiSet(courseList, (res) => { + this.$message.success('设置语种成功!'); + this.languageSetting.dlgShow = false; + // 可以选择是否刷新列表数据 + this.searchData(); + }, (res) => { + this.$message.error('设置语种失败!'); + }) + }, + + // 批量开启AI处理 - 确认 + confirmAiProcess() { + // 获取AI处理配置 + let { aiSet, aiAbstract, aiDraft, languageCode } = this.aiProcessSetting; + const courseList = deepCopy(this.selectedCourses); + languageCode = languageCode || []; + if (!languageCode.includes('zh-CN')) { + languageCode.unshift('zh-CN'); // 默认添加中文 去重 + } + courseList.forEach(item => { + item.aiSet = aiSet; + item.aiAbstract = aiAbstract; + item.aiDraft = aiDraft; + item.aiTranslate = aiSet; + item.languageStatus = aiSet; + item.languageCode = languageCode; + }) + this._benchAiSet(courseList, (res) => { + this.$message.success('开启AI处理成功!'); + this.aiProcessSetting.dlgShow = false; + // 可以选择是否刷新列表数据 + this.searchData(); + }, (res) => { + this.$message.error('开启AI处理失败!'); + }) + }, + + _benchAiSet(courseList, successCB, failCB) { + apiCourse.benchAiSet({courseList}).then(res => { + if(res.status === 200){ + successCB && successCB(res); + }else{ + failCB && failCB(res); + } + }) + }, + getAiPermission() { + apiCourse.listByUser({}).then(res => { + console.log('res', res); + if(res.code === 200){ + let index = res.data.findIndex(item => item.permissionCode === 'KjbAiSetCode'); + this.aiPermission = index !== -1; + console.log('index', index, this.aiPermission); + } + }) + } } }; @@ -960,4 +1366,22 @@ export default { .el-dialog__body { overflow: hidden; } + + .form-item{ + margin-bottom: 20px; + display: flex; + align-items: center; + gap: 10px; + } +.tips { + color: #f56c6c; + font-size: 12px; + margin: 10px 0; + line-height: 1.5; +} +.languages-list{ + display: flex; + flex-wrap: wrap; + gap: 20px; +} diff --git a/src/views/course/aiSet/aiAbstract.vue b/src/views/course/aiSet/aiAbstract.vue new file mode 100644 index 00000000..2efd2c32 --- /dev/null +++ b/src/views/course/aiSet/aiAbstract.vue @@ -0,0 +1,245 @@ + + + + + diff --git a/src/views/course/aiSet/aiTranslate.vue b/src/views/course/aiSet/aiTranslate.vue new file mode 100644 index 00000000..28f146b6 --- /dev/null +++ b/src/views/course/aiSet/aiTranslate.vue @@ -0,0 +1,388 @@ + + + + + diff --git a/src/views/portal/course/Index.vue b/src/views/portal/course/Index.vue index 9a5dd8ec..0381cf5b 100644 --- a/src/views/portal/course/Index.vue +++ b/src/views/portal/course/Index.vue @@ -203,8 +203,25 @@
开课时间:{{ cinfo.startTime }}
- -
+ +
+ +
+

课程摘要

+
{{ cinfo.summaryContent }}
+
+ + 暂无数据 +
+
+ + 摘要 +
{{ cinfo.teacher }} @@ -214,13 +231,13 @@ {{ formatNum(cinfo.studies) }}人学习
-
+
- {{ toScore(cinfo.score) }}分 + {{ toScore(cinfo.score) }}分
-
未评分
+
未评分
@@ -2655,3 +2672,43 @@ a.custom2 { } } + + diff --git a/src/views/study/coursenew.vue b/src/views/study/coursenew.vue index 3da4fe9c..08329508 100644 --- a/src/views/study/coursenew.vue +++ b/src/views/study/coursenew.vue @@ -373,6 +373,30 @@ >我的笔记
+ +
+ AI文稿 + +
@@ -625,6 +649,11 @@ :score="courseInfo.score" >
+ + +
+ +
@@ -637,6 +666,16 @@ > 内容简介
+ +
+ AI摘要 + +
+ +
+
+ {{ courseInfo.summaryContent || '' }} +
+
@@ -799,7 +847,8 @@
+ +