mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/learning-system-portal.git
synced 2025-12-18 15:26:45 +08:00
ai视频二期功能提交-编辑ai摘要
This commit is contained in:
141
src/api/modules/courseAiVideo.js
Normal file
141
src/api/modules/courseAiVideo.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import ajax from '@/utils/xajax.js'
|
||||
const BASE_URL = process.env.NODE_ENV=='development'?'/aiVideo':'';
|
||||
|
||||
/**
|
||||
* AI摘要-摘要课程详情
|
||||
* @param {Object} data
|
||||
* {
|
||||
courseId: "COURSE_001"//课程id
|
||||
}
|
||||
*/
|
||||
const getCourse = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/aiVideo/getCourse', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI摘要-摘要详情
|
||||
* @param {Object} data
|
||||
* {
|
||||
courseId: "COURSE_001"//课程id
|
||||
}
|
||||
*/
|
||||
const selectVideoSummary = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/videoSummary/selectVideoSummary', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI摘要-更新摘要详情
|
||||
* @param {Object} data
|
||||
* {
|
||||
courseId:课程的id
|
||||
summaryContent: 摘要内容
|
||||
}
|
||||
*/
|
||||
const updateVideoSummary = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/videoSummary/updateVideoSummary', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI摘要-根据视频id查询详情
|
||||
* @param {Object} id 视频id
|
||||
*/
|
||||
const selectById = function(id) {
|
||||
return ajax.postJson(BASE_URL+'/videoSummary/selectById/'+id);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI摘要-下载课程摘要文本
|
||||
* @param {Object} courseId 课程 的id
|
||||
*/
|
||||
const downloadSummaryTxt = function(courseId) {
|
||||
let requestParam ={
|
||||
url: BASE_URL+'/videoSummary/downloadSummaryTxt?courseId='+courseId,
|
||||
timeout: 0, // 下载不设置超时
|
||||
responseType: 'blob', // 表明返回服务器返回的数据类型
|
||||
}
|
||||
return ajax.get(requestParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI摘要-重新生成课程摘要
|
||||
* {
|
||||
courseId: "COURSE_001"//课程id
|
||||
}
|
||||
*/
|
||||
const retrySummaryTxt = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/videoSummary/retrySummaryTxt',data);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI翻译-获取视频语种下拉框
|
||||
* @param {Object} videoId 视频的id
|
||||
*/
|
||||
const getTextDropdown = function(videoId) {
|
||||
return ajax.postJson(BASE_URL+'/subtitle/getTextDropdown',{videoId});
|
||||
}
|
||||
|
||||
/**
|
||||
* AI翻译-获取视频指定语种字幕
|
||||
* @param {object} data
|
||||
{
|
||||
"videoId": "VIDEO_111",
|
||||
"language": "zh-CN"
|
||||
}
|
||||
*/
|
||||
const getTextDetail = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/subtitle/getTextDetail',data);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI翻译-更新字幕
|
||||
* @param {Object} data
|
||||
* {
|
||||
"videoId": "VIDEO_001",
|
||||
"language": "zh-CN",
|
||||
"vttContent": "dddd"
|
||||
}
|
||||
*/
|
||||
const updateText = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/subtitle/updateText',data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AI翻译-下载字幕
|
||||
* @param {Object} params
|
||||
{
|
||||
videoId: 视频的id,
|
||||
language: 语种
|
||||
}
|
||||
*/
|
||||
const downloadText = function(studyId,contentId) {
|
||||
return ajax.get(BASE_URL+'/subtitle/downloadText', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* AI翻译-同步跟更新字幕
|
||||
* @param {Object} data
|
||||
{
|
||||
"videoId": "VIDEO_010",
|
||||
"language": "zh-CN"
|
||||
}
|
||||
* @returns
|
||||
*/
|
||||
const regenerate = function(data) {
|
||||
return ajax.postJson(BASE_URL+'/subtitle/regenerate',data);
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
selectVideoSummary,
|
||||
updateVideoSummary,
|
||||
selectById,
|
||||
retrySummaryTxt,
|
||||
updateText,
|
||||
downloadText,
|
||||
getTextDetail,
|
||||
regenerate,
|
||||
getTextDropdown,
|
||||
downloadSummaryTxt,
|
||||
getCourse,
|
||||
}
|
||||
@@ -463,7 +463,7 @@
|
||||
<el-button type="text" @click="changeAIKey('aiAbstract')">
|
||||
{{ aiSetting.aiAbstract === 1 ? '下架' : '上架' }}
|
||||
</el-button>
|
||||
<el-button v-show="false" type="text" >编辑</el-button>
|
||||
<el-button v-show="isV2" type="text" @click="toAiAbstract">编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -490,7 +490,7 @@
|
||||
<el-button type="text" @click="changeAIKey('aiTranslate')">
|
||||
{{ aiSetting.aiTranslate === 1 ? '下架' : '上架' }}
|
||||
</el-button>
|
||||
<el-button v-show="false" type="text" >编辑</el-button>
|
||||
<el-button v-show="isV2" type="text" @click="toAiTranslate">编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -657,6 +657,7 @@ export default {
|
||||
aiAbstractTip: '一键提炼课程视频核心要点,助力学员课前高效掌握重点,快速筛选学习资源', // 提示信息
|
||||
aiDraftTip: '分段展示视频内容并精准同步时间轴,实现视频进度与文稿双向定位,学习内容触手可及', //提示信息
|
||||
aiTranslateTip: '智能转换视频字幕与语音为多语种,支持全球学员按需切换语言,打破学习边界', // 提示信息
|
||||
isV2: true,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -1297,7 +1298,23 @@ export default {
|
||||
console.log('index', index, this.aiPermission);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
toAiAbstract() {
|
||||
this.$router.push({
|
||||
path: '/iframe/course/aiAbstract',
|
||||
query: {
|
||||
id: this.aiSetting.id
|
||||
}
|
||||
})
|
||||
},
|
||||
toAiTranslate() {
|
||||
this.$router.push({
|
||||
path: '/iframe/course/aiTranslate',
|
||||
query: {
|
||||
id: this.aiSetting.id
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
<template>
|
||||
<div class="aiAbstract">
|
||||
<div class="ai-left">
|
||||
<div class="left-title">{{courseName}}</div>
|
||||
<ul class="ai-list">
|
||||
<li class="ai-item" v-for="(item, index) in videoList" @click="currentVideo = item" :class="{'active': currentVideo.id === item.id}" :key="index">
|
||||
<div class="ai-item-title">{{item.name}}</div>
|
||||
</li>
|
||||
<div class="ai-left" v-if="sections.length > 0">
|
||||
<div class="left-title">{{courseInfo.name}}</div>
|
||||
<ul class="ai-list" >
|
||||
<template v-for="c in chapterList">
|
||||
<li class="ai-item" v-for="(item, index) in c.children" @click="handleSelectVideo(item, index+1)" :class="{'active': currentVideo.id === item.id}" :key="index">
|
||||
<div class="ai-item-title">{{item.chapterName}}-{{'视频' + (index + 1)}}</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ai-right">
|
||||
<div class="right-title">
|
||||
<h3>{{currentVideo.name}}</h3>
|
||||
<h3>{{videoName}}</h3>
|
||||
<div>
|
||||
<el-button type="primary" @click="status = 1">下架本课程AI摘要</el-button>
|
||||
<el-button type="primary" @click="handleSummaryStatus">{{courseInfo.aiAbstract == 1 ? '下架' : '上架'}}本课程AI摘要</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-content">
|
||||
<div class="videoBox">
|
||||
<videoPlayer :src="testUrl" style="height: auto;"> </videoPlayer>
|
||||
<videoPlayer
|
||||
:src="blobUrl"
|
||||
:blobId="blobId"
|
||||
style="height: auto;"> </videoPlayer>
|
||||
<div class="video-content">
|
||||
<h4>视频摘要</h4>
|
||||
<p>
|
||||
{{currentVideo.aiAbstract}}
|
||||
{{videoSummary}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,17 +34,18 @@
|
||||
<div class="opera-title">
|
||||
<h4>课程摘要</h4>
|
||||
<div class="opera-btn">
|
||||
<el-button type="primary" plain round size="mini" @click="status = 2">重新生成</el-button>
|
||||
<el-button type="primary" plain round size="mini" @click="status = 4">编辑</el-button>
|
||||
<el-button plain round size="mini" @click="status = 3">取消</el-button>
|
||||
<el-button v-if="type == 1" type="primary" plain round size="mini" @click="retrySummaryTxt">重新生成</el-button>
|
||||
<el-button v-if="type == 1" type="primary" plain round size="mini" @click="type = 4">编辑</el-button>
|
||||
<el-button v-if="type == 4" plain round size="mini" @click="type = 1">取消</el-button>
|
||||
<el-button v-if="type == 4" type="primary" plain round size="mini" @click="updateSummary">确认</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="opera-content" v-show="status != 4">
|
||||
<span v-show="status == 1">{{ aiAbstract }}</span>
|
||||
<p v-show="status == 2" style="color: rgba(207, 207, 207, 1);text-align: center;margin-top: 48%;">AI 摘要重新生成中,过程可能耗时较长,<br>无需在此等待哦~</p>
|
||||
<img v-show="status == 3" src="@/assets/images/course/generationFailed.png" alt="" width="150" height="159" style="display: flex;margin: 35% auto 0 auto;">
|
||||
<div class="opera-content" v-show="type != 4">
|
||||
<span v-show="type == 1">{{ aiAbstract }}</span>
|
||||
<p v-show="type == 2" style="color: rgba(207, 207, 207, 1);text-align: center;margin-top: 48%;">AI 摘要重新生成中,过程可能耗时较长,<br>无需在此等待哦~</p>
|
||||
<img v-show="type == 3" src="@/assets/images/course/generationFailed.png" alt="" width="150" height="159" style="display: flex;margin: 35% auto 0 auto;">
|
||||
</div>
|
||||
<el-input v-show="status == 4"
|
||||
<el-input v-show="type == 4"
|
||||
type="textarea"
|
||||
placeholder="请输入内容"
|
||||
autosize
|
||||
@@ -52,7 +58,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from "vuex";
|
||||
import videoPlayer from "@/components/VideoPlayer/index.vue";
|
||||
import apiStudy from "@/api/modules/courseStudy.js";
|
||||
import cookies from "vue-cookies";
|
||||
import apiAiVideo from "@/api/modules/courseAiVideo.js";
|
||||
import apiCourse from '@/api/modules/course.js';
|
||||
import { encrypt } from "@/utils/jsencrypt.js";
|
||||
export default {
|
||||
name: 'aiAbstract',
|
||||
// ai播放器相关
|
||||
@@ -61,39 +73,201 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
courseName: '企业经营法则--课程单元',
|
||||
videoList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '1. 开源节流1',
|
||||
aiAbstract: '人工智能(AI)是让计算机模拟人类智能的技术,核心包括机器学习、深度学习等。主要分为弱 AI(专注特定任务)和强 AI(通用智能)两类。应用涵盖医疗诊断、自动驾驶、语音助手等多个领域。它通过数据学习模式,实现预测和适应能力,正在改变生活方式和工作方式。未来发展需平衡创新与伦理考量,确保对人类社会有益。'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '2. 企业经营法则总述',
|
||||
aiAbstract: '本课程将介绍企业经营法则的总述,包括企业经营的基本原理、经营策略、经营模式等。'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '3. 企业经营法则总述',
|
||||
aiAbstract: '本课程将介绍企业经营法则的总述,包括企业经营的基本原理、经营策略、经营模式等。'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '4. 企业经营法则总述',
|
||||
aiAbstract: '本课程将介绍企业经营法则的总述,包括企业经营的基本原理、经营策略、经营模式等。'
|
||||
},
|
||||
],
|
||||
testUrl: 'https://vjs.zencdn.net/v/oceans.mp4',
|
||||
chapterList: [],
|
||||
videoName: '',
|
||||
currentVideo: {},
|
||||
aiAbstract: '人工智能(AI)是让计算机模拟人类智能的技术,核心包括机器学习、深度学习等。主要分为弱 AI(专注特定任务)和强 AI(通用智能)两类。应用涵盖医疗诊断、自动驾驶、语音助手等多个领域。它通过数据学习模式,实现预测和适应能力,正在改变生活方式和工作方式。未来发展需平衡创新与伦理考量,确保对人类社会有益。',
|
||||
status: '1', // 1: 正常 2: 生成中 3: 错误 4: 编辑中
|
||||
aiAbstract: '',
|
||||
type: '1', // 1: 正常 2: 生成中 3: 错误 4: 编辑中
|
||||
courseId: '',
|
||||
courseInfo: {},
|
||||
sections: [],
|
||||
blobId: '',
|
||||
blobUrl: '',
|
||||
videoSummary: '',
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.currentVideo = this.videoList[0];
|
||||
created() {
|
||||
this.courseId = this.$route.query.id;
|
||||
console.log(this.courseId);
|
||||
this.getCourseInfo();
|
||||
this.getCourseSummary();
|
||||
},
|
||||
methods: {}
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
SET_selectableLang: 'video/SET_selectableLang',
|
||||
SET_courseInfo: 'video/SET_courseInfo',
|
||||
}),
|
||||
// 上下架状态
|
||||
handleSummaryStatus() {
|
||||
apiCourse.benchAiSet({courseList:[{id: this.courseId, aiAbstract: this.courseInfo.aiAbstract == 1 ? 0 : 1}]}).then(res => {
|
||||
if(res.status === 200){
|
||||
this.$message.success(this.courseInfo.aiAbstract == 1 ? '下架成功!' : '上架成功!');
|
||||
this.getCourseInfo();
|
||||
}else{
|
||||
this.$message.error(this.courseInfo.aiAbstract == 1 ? '下架失败!' : '上架失败!');
|
||||
}
|
||||
})
|
||||
},
|
||||
// 下载摘要 - 不需要
|
||||
downloadSummary() {
|
||||
apiAiVideo.downloadSummaryTxt(this.courseId)
|
||||
.then((rs) => {
|
||||
console.log('下载',rs);
|
||||
// 1. 创建 Blob 的临时 URL
|
||||
const url = URL.createObjectURL(rs);
|
||||
|
||||
// 2. 创建隐藏的 <a> 标签
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = '课程摘要.txt'; // 设置下载的文件名
|
||||
a.style.display = 'none';
|
||||
|
||||
// 3. 添加到文档中并触发点击
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
// 4. 清理
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url); // 释放 URL 对象
|
||||
}, 100);
|
||||
})
|
||||
},
|
||||
updateSummary() {
|
||||
apiAiVideo.updateVideoSummary({
|
||||
courseId: this.courseId,
|
||||
summaryContent: this.aiAbstract,
|
||||
})
|
||||
.then((rs) => {
|
||||
if (rs.rspCode == '0000') {
|
||||
this.type = '1';
|
||||
this.getCourseSummary();
|
||||
}
|
||||
})
|
||||
},
|
||||
retrySummaryTxt() {
|
||||
this.type = '2';
|
||||
apiAiVideo.retrySummaryTxt({
|
||||
courseId: this.courseId,
|
||||
})
|
||||
.then((rs) => {
|
||||
if (rs.rspCode == '0000') {
|
||||
this.type = '1';
|
||||
this.getCourseSummary();
|
||||
} else {
|
||||
this.type = '3';
|
||||
}
|
||||
})
|
||||
},
|
||||
getVideoSummary(id) {
|
||||
apiAiVideo.selectById(id)
|
||||
.then((rs) => {
|
||||
this.videoSummary = ''
|
||||
if (rs.rspCode == '0000') {
|
||||
this.videoSummary = rs.data.briefSummary || '';
|
||||
} else {
|
||||
this.$message.error('获取视频摘要失败!');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.videoSummary = ''
|
||||
this.$message.error('获取视频摘要失败!');
|
||||
})
|
||||
},
|
||||
getCourseSummary() {
|
||||
apiAiVideo.getCourse({
|
||||
courseId: this.courseId,
|
||||
})
|
||||
.then((rs) => {
|
||||
this.aiAbstract = rs.data.summaryContent || '';
|
||||
})
|
||||
},
|
||||
createPlayUrl(fid, u) {
|
||||
let nowDate = new Date();
|
||||
let ctime = parseInt(nowDate.getTime() / 1000);
|
||||
let beforeUrl = parseInt(nowDate.getTime() / 1000) + "/" + fid;
|
||||
let urlSign = encodeURIComponent(encrypt(beforeUrl));
|
||||
cookies.set("PLAYSIGN_TIME", ctime); //写客户端的cookie保存
|
||||
//以下判断是为了区分本地环境和服务器环境
|
||||
if (process.env.NODE_ENV == "development") {
|
||||
this.blobUrl = process.env.VUE_APP_FILE_BASE_URL + u;
|
||||
} else {
|
||||
this.blobUrl =
|
||||
process.env.VUE_APP_BASE_API +
|
||||
"/xboe/m/course/cware/resource?sign=" +
|
||||
urlSign;
|
||||
}
|
||||
},
|
||||
handleSelectVideo(item, index) {
|
||||
console.log('选择了该视频', item);
|
||||
this.SET_selectableLang(item?.boeaiSubtitleRspList);
|
||||
this.videoName = item.chapterName ? item.chapterName + "-视频" + index : this.courseInfo.name;
|
||||
this.currentVideo = item;
|
||||
let curriculumData = {};
|
||||
if (item.content.startsWith("{")) {
|
||||
curriculumData = JSON.parse(item.content);
|
||||
} else {
|
||||
curriculumData.url = item.content;
|
||||
}
|
||||
this.getVideoSummary(item.id);
|
||||
this.blobId = item.id;
|
||||
this.createPlayUrl(item.contentRefId, curriculumData.url);
|
||||
},
|
||||
getCourseInfo() {
|
||||
apiStudy.studyIndexPost({
|
||||
cid: this.courseId,
|
||||
addView: false,
|
||||
audiences: '',
|
||||
})
|
||||
.then((rs) => {
|
||||
if (rs.status == 200) {
|
||||
this.courseInfo = rs.result.course || {};
|
||||
this.SET_courseInfo(this.courseInfo);
|
||||
const contents = rs.result.contents?.filter(item => item.contentType == 10) || [];
|
||||
this.sections = rs.result.sections || [];
|
||||
if (this.sections.length > 0) {
|
||||
let treeList = [];
|
||||
let hasOne = false;
|
||||
this.sections.forEach(section => {
|
||||
let treeNode = {
|
||||
...section,
|
||||
children: [],
|
||||
};
|
||||
contents.forEach(item => {
|
||||
if (section.id == item.csectionId) {
|
||||
item.chapterName = section.name || '';
|
||||
treeNode.children.push(item);
|
||||
if (!hasOne) {
|
||||
this.handleSelectVideo(item, 1);
|
||||
hasOne = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
treeList.push(treeNode);
|
||||
})
|
||||
this.chapterList = treeList;
|
||||
} else {
|
||||
this.handleSelectVideo(contents[0], 1);
|
||||
}
|
||||
console.log('33333',this.courseInfo, this.courseInfo.name);
|
||||
this.aiAbstract = this.courseInfo.summaryContent
|
||||
if (contents.length == 0) {
|
||||
$this.$message.error("课程内容已删除或课程已不再使用");
|
||||
return;
|
||||
}
|
||||
if (!rs.result.course.enabled) {
|
||||
$this.$message.error(
|
||||
"十分抱歉,此课程已停用,如需使用,请联系管理员。"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -156,6 +330,7 @@ export default {
|
||||
display: flex;
|
||||
padding: 0 28px;
|
||||
height: 76px;
|
||||
min-height: 76px;
|
||||
border-bottom: 1px solid rgba(229, 231, 235, 1);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
<template>
|
||||
<div class="aiTranslate">
|
||||
<div class="ai-left">
|
||||
<div class="left-title">{{courseName}}</div>
|
||||
<ul class="ai-list">
|
||||
<li class="ai-item" v-for="(item, index) in videoList" @click="currentVideo = item" :class="{'active': currentVideo.id === item.id}" :key="index">
|
||||
<div class="ai-item-title">{{item.name}}</div>
|
||||
</li>
|
||||
<div class="ai-left" v-if="sections.length > 0">
|
||||
<div class="left-title">{{courseInfo.name}}</div>
|
||||
<ul class="ai-list" >
|
||||
<template v-for="c in chapterList">
|
||||
<li class="ai-item" v-for="(item, index) in c.children" @click="handleSelectVideo(item, index+1)" :class="{'active': currentVideo.id === item.id}" :key="index">
|
||||
<div class="ai-item-title">{{item.chapterName}}-{{'视频' + (index + 1)}}</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ai-right">
|
||||
<div class="right-title">
|
||||
<h3>{{currentVideo.name}}</h3>
|
||||
<h3>{{videoName}}</h3>
|
||||
<div>
|
||||
<el-button type="primary" @click="status = 1">下架本课程AI翻译</el-button>
|
||||
<el-button type="primary" @click="handleSummaryStatus()">
|
||||
{{ courseInfo.aiTranslate == 1 ? '下架本课程AI翻译' : '上架本课程AI翻译' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-content">
|
||||
<div class="videoBox">
|
||||
<videoPlayer :src="testUrl" style="height: auto;"> </videoPlayer>
|
||||
<videoPlayer
|
||||
:src="blobUrl"
|
||||
:blobId="blobId"
|
||||
style="height: auto;"> </videoPlayer>
|
||||
<div class="video-content">
|
||||
<div class="select-lang">
|
||||
<img src="@/assets/images/course/languageIcon.png" alt="" width="10" height="10">
|
||||
@@ -45,26 +52,26 @@
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button type="primary" @click="status = 2">加载字幕</el-button>
|
||||
<el-button type="primary" @click="type = 2">加载字幕</el-button>
|
||||
</div>
|
||||
<div class="opera-content">
|
||||
<div class="bg-gray" v-show="status != 4">
|
||||
<p v-show="status == 1" v-html="aiTranslate"></p>
|
||||
<p v-show="status == 2" style="color: rgba(207, 207, 207, 1);text-align: center;margin-top: 48%;">AI 翻译重新生成中,过程可能耗时较长,<br>无需在此等待哦~</p>
|
||||
<img v-show="status == 3" src="@/assets/images/course/generationFailed.png" alt="" width="150" height="159" style="display: flex;margin: 35% auto 0 auto;">
|
||||
<img v-show="status == 5" src="@/assets/images/course/selectLanguage.png" alt="" width="112" height="130" style="display: flex;margin: 35% auto 0 auto;">
|
||||
<div class="bg-gray" v-show="type != 4">
|
||||
<p v-show="type == 1" v-html="aiTranslate"></p>
|
||||
<p v-show="type == 2" style="color: rgba(207, 207, 207, 1);text-align: center;margin-top: 48%;">AI 翻译重新生成中,过程可能耗时较长,<br>无需在此等待哦~</p>
|
||||
<img v-show="type == 3" src="@/assets/images/course/generationFailed.png" alt="" width="150" height="159" style="display: flex;margin: 35% auto 0 auto;">
|
||||
<img v-show="type == 5" src="@/assets/images/course/selectLanguage.png" alt="" width="112" height="130" style="display: flex;margin: 35% auto 0 auto;">
|
||||
</div>
|
||||
<el-input v-show="status == 4"
|
||||
<el-input v-show="type == 4"
|
||||
type="textarea"
|
||||
placeholder="请输入内容"
|
||||
autosize
|
||||
v-model="aiTranslate">
|
||||
</el-input>
|
||||
<div class="opera-btn">
|
||||
<el-button v-show="status == 1" type="primary" plain round size="mini" @click="updateDialogVisible = true">重新生成</el-button>
|
||||
<el-button v-show="status == 1" type="primary" plain round size="mini" @click="status = 4">编辑</el-button>
|
||||
<el-button v-show="status == 4" plain round size="mini" @click="status = 1">取消</el-button>
|
||||
<el-button v-show="status == 4" type="primary" plain round size="mini" @click="status = 1">确认</el-button>
|
||||
<el-button v-show="type == 1" type="primary" plain round size="mini" @click="updateDialogVisible = true">重新生成</el-button>
|
||||
<el-button v-show="type == 1" type="primary" plain round size="mini" @click="type = 4">编辑</el-button>
|
||||
<el-button v-show="type == 4" plain round size="mini" @click="type = 1">取消</el-button>
|
||||
<el-button v-show="type == 4" type="primary" plain round size="mini" @click="type = 1">确认</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,7 +116,8 @@
|
||||
|
||||
<script>
|
||||
import videoPlayer from "@/components/VideoPlayer/index.vue";
|
||||
import { mapGetters } from 'vuex';
|
||||
import { mapGetters, mapMutations } from 'vuex';
|
||||
import apiCourse from '@/api/modules/course.js';
|
||||
export default {
|
||||
name: 'aiTranslate',
|
||||
// ai播放器相关
|
||||
@@ -119,28 +127,6 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
courseName: '企业经营法则--课程单元',
|
||||
videoList: [
|
||||
{
|
||||
id: 1,
|
||||
name: '1. 开源节流1',
|
||||
aiTranslate: '人工智能(AI)是让计算机模拟人类智能的技术,核心包括机器学习、深度学习等。主要分为弱 AI(专注特定任务)和强 AI(通用智能)两类。应用涵盖医疗诊断、自动驾驶、语音助手等多个领域。它通过数据学习模式,实现预测和适应能力,正在改变生活方式和工作方式。未来发展需平衡创新与伦理考量,确保对人类社会有益。'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '2. 企业经营法则总述',
|
||||
aiTranslate: '本课程将介绍企业经营法则的总述,包括企业经营的基本原理、经营策略、经营模式等。'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '3. 企业经营法则总述',
|
||||
aiTranslate: '本课程将介绍企业经营法则的总述,包括企业经营的基本原理、经营策略、经营模式等。'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '4. 企业经营法则总述',
|
||||
aiTranslate: '本课程将介绍企业经营法则的总述,包括企业经营的基本原理、经营策略、经营模式等。'
|
||||
},
|
||||
],
|
||||
testUrl: 'https://vjs.zencdn.net/v/oceans.mp4',
|
||||
currentVideo: {},
|
||||
aiTranslate: `
|
||||
@@ -153,7 +139,7 @@ today I want to share with you the topic of
|
||||
00:00:05/00:00:09
|
||||
"The Development History and Future Prospects of Computer Technology -
|
||||
`,
|
||||
status: '1', // 1: 正常 2: 生成中 3: 错误 4: 编辑中 5: 未选择语种
|
||||
type: '1', // 1: 正常 2: 生成中 3: 错误 4: 编辑中 5: 未选择语种
|
||||
selectedLang: [
|
||||
{
|
||||
label: '英文',
|
||||
@@ -184,17 +170,124 @@ today I want to share with you the topic of
|
||||
updateDialogVisible: false,
|
||||
selectDialogVisible: false,
|
||||
selectLang: [],
|
||||
chapterList: [],
|
||||
videoName: '',
|
||||
testUrl: 'https://vjs.zencdn.net/v/oceans.mp4',
|
||||
currentVideo: {},
|
||||
aiAbstract: '',
|
||||
courseId: '',
|
||||
courseInfo: {},
|
||||
sections: [],
|
||||
blobId: '',
|
||||
blobUrl: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['selectAllLang']),
|
||||
},
|
||||
mounted() {
|
||||
this.currentVideo = this.videoList[0];
|
||||
this.courseId = this.$route.query.id;
|
||||
console.log(this.courseId);
|
||||
this.getCourseInfo();
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
SET_selectableLang: 'video/SET_selectableLang',
|
||||
SET_courseInfo: 'video/SET_courseInfo',
|
||||
}),
|
||||
setLanguage(){
|
||||
this.selectDialogVisible = true;
|
||||
},
|
||||
handleSummaryStatus() {
|
||||
apiCourse.benchAiSet({courseList:[{id: this.courseId, aiTranslate: this.courseInfo.aiTranslate == 1 ? 0 : 1}]}).then(res => {
|
||||
if(res.status === 200){
|
||||
this.$message.success(this.courseInfo.aiTranslate == 1 ? '下架成功!' : '上架成功!');
|
||||
this.getCourseInfo();
|
||||
}else{
|
||||
this.$message.error(this.courseInfo.aiTranslate == 1 ? '下架失败!' : '上架失败!');
|
||||
}
|
||||
})
|
||||
},
|
||||
createPlayUrl(fid, u) {
|
||||
let nowDate = new Date();
|
||||
let ctime = parseInt(nowDate.getTime() / 1000);
|
||||
let beforeUrl = parseInt(nowDate.getTime() / 1000) + "/" + fid;
|
||||
let urlSign = encodeURIComponent(encrypt(beforeUrl));
|
||||
cookies.set("PLAYSIGN_TIME", ctime); //写客户端的cookie保存
|
||||
//以下判断是为了区分本地环境和服务器环境
|
||||
if (process.env.NODE_ENV == "development") {
|
||||
this.blobUrl = process.env.VUE_APP_FILE_BASE_URL + u;
|
||||
} else {
|
||||
this.blobUrl =
|
||||
process.env.VUE_APP_BASE_API +
|
||||
"/xboe/m/course/cware/resource?sign=" +
|
||||
urlSign;
|
||||
}
|
||||
},
|
||||
handleSelectVideo(item, index) {
|
||||
this.SET_selectableLang(item?.boeaiSubtitleRspList);
|
||||
this.videoName = item.chapterName ? item.chapterName + "-视频" + index : this.courseInfo.name;
|
||||
this.currentVideo = item;
|
||||
let curriculumData = {};
|
||||
if (item.content.startsWith("{")) {
|
||||
curriculumData = JSON.parse(item.content);
|
||||
} else {
|
||||
curriculumData.url = item.content;
|
||||
}
|
||||
this.blobId = item.id;
|
||||
this.createPlayUrl(item.contentRefId, curriculumData.url);
|
||||
},
|
||||
getCourseInfo() {
|
||||
apiStudy.studyIndexPost({
|
||||
cid: this.courseId,
|
||||
addView: false,
|
||||
audiences: '',
|
||||
})
|
||||
.then((rs) => {
|
||||
if (rs.status == 200) {
|
||||
this.courseInfo = rs.result.course || {};
|
||||
this.SET_courseInfo(this.courseInfo);
|
||||
const contents = rs.result.contents?.filter(item => item.contentType == 10) || [];
|
||||
this.sections = rs.result.sections || [];
|
||||
if (this.sections.length > 0) {
|
||||
let treeList = [];
|
||||
let hasOne = false;
|
||||
this.sections.forEach(section => {
|
||||
let treeNode = {
|
||||
...section,
|
||||
children: [],
|
||||
};
|
||||
contents.forEach(item => {
|
||||
if (section.id == item.csectionId) {
|
||||
item.chapterName = section.name || '';
|
||||
treeNode.children.push(item);
|
||||
if (!hasOne) {
|
||||
this.handleSelectVideo(item, 1);
|
||||
hasOne = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
treeList.push(treeNode);
|
||||
})
|
||||
this.chapterList = treeList;
|
||||
} else {
|
||||
this.handleSelectVideo(contents[0], 1);
|
||||
}
|
||||
console.log('33333',this.courseInfo, this.courseInfo.name);
|
||||
this.aiAbstract = this.courseInfo.summaryContent
|
||||
if (contents.length == 0) {
|
||||
$this.$message.error("课程内容已删除或课程已不再使用");
|
||||
return;
|
||||
}
|
||||
if (!rs.result.course.enabled) {
|
||||
$this.$message.error(
|
||||
"十分抱歉,此课程已停用,如需使用,请联系管理员。"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -144,6 +144,17 @@ module.exports = {
|
||||
'^/manageApi': '/manageApi'
|
||||
}
|
||||
},
|
||||
'/systemapi/aiVideo': {
|
||||
// 目标代理服务器地址
|
||||
// target: 'http://127.0.0.1:9090',
|
||||
target: 'http://10.29.0.168:8088',
|
||||
changeOrigin: true,
|
||||
logLevel: 'debug',
|
||||
secure: false,
|
||||
pathRewrite: {
|
||||
'^/systemapi/aiVideo': ''
|
||||
}
|
||||
},
|
||||
'/systemapi': {
|
||||
// 目标代理服务器地址
|
||||
// target: 'http://127.0.0.1:9090',
|
||||
|
||||
Reference in New Issue
Block a user