Compare commits
118 Commits
master-081
...
player-202
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e46ffb65a | ||
|
|
cbb36b429b | ||
|
|
a1b8c617e4 | ||
|
|
8168c8880d | ||
|
|
7d3ab9b6b6 | ||
|
|
27e76da571 | ||
|
|
82c765edd4 | ||
|
|
39d29c0dad | ||
|
|
311ec096eb | ||
|
|
9379aad28f | ||
|
|
fa1bcaf1c7 | ||
|
|
3ee4afb229 | ||
|
|
82dcfa6348 | ||
|
|
caa9b23766 | ||
|
|
4b4c0943d8 | ||
|
|
b31f02bf23 | ||
|
|
003fece291 | ||
|
|
986a47f22a | ||
|
|
782bcc31e5 | ||
|
|
1a95852912 | ||
|
|
f5d865ccc3 | ||
|
|
65673561d8 | ||
|
|
2cbb379fa6 | ||
|
|
6d4af3aa2d | ||
|
|
5ebee96ce4 | ||
| 408d6a1612 | |||
| b1508ad226 | |||
| a9764bf2f8 | |||
|
|
c3f53515b9 | ||
| 087be5dd38 | |||
|
|
1772c972b9 | ||
|
|
91bafcb5b9 | ||
|
|
8c533c5f3a | ||
|
|
bb17784501 | ||
|
|
69530fe6ad | ||
|
|
b1cd8e2f63 | ||
|
|
7335dd4eba | ||
| 3860087fac | |||
| 046509f70d | |||
| bf0ae91184 | |||
| f61742a0b9 | |||
|
|
c886a80193 | ||
| 05ad90b025 | |||
| f3833a23fa | |||
| d957a8d44b | |||
|
|
89ed79828f | ||
|
|
b926590edc | ||
| 19bc757dc2 | |||
| f3a1036b64 | |||
| 3c1650b751 | |||
| ff2bdb4ae5 | |||
|
|
14fb53ccd3 | ||
|
|
72f9661150 | ||
|
|
7806afc5f7 | ||
| e1af233c5f | |||
| 2738493030 | |||
| 480a4f5564 | |||
|
|
205bf5469f | ||
|
|
30897a1fa5 | ||
|
|
1c59cffd3e | ||
|
|
6e9f93d6c9 | ||
|
|
3ee4a2fd6e | ||
|
|
1b442ef040 | ||
|
|
4693cb0db1 | ||
|
|
92fecbec80 | ||
|
|
be63f5a1aa | ||
|
|
c9899eda6b | ||
|
|
0f52a69beb | ||
|
|
3410afedcf | ||
|
|
33866c0f49 | ||
|
|
c9e51fc21f | ||
|
|
a42668c929 | ||
|
|
01d4bc0536 | ||
|
|
d52e8b389b | ||
|
|
e9a86d0364 | ||
|
|
0e43ca5e82 | ||
|
|
0771460f60 | ||
|
|
1a2829d70a | ||
|
|
68eda7efcc | ||
| 0b0789feda | |||
| 70bb87a17a | |||
| 4e60811542 | |||
|
|
075fdb1913 | ||
|
|
8c7569ae4e | ||
|
|
56f565cbf3 | ||
|
|
c15f52e325 | ||
|
|
98c10e703e | ||
|
|
2078c128c9 | ||
|
|
e8fe7b4fd3 | ||
|
|
029d5b0791 | ||
|
|
12a6ed8fea | ||
|
|
363492866f | ||
|
|
d237dc99ee | ||
|
|
995933ae56 | ||
|
|
dff81df91d | ||
|
|
0864704c4c | ||
|
|
58fc6264fe | ||
|
|
5276813eba | ||
|
|
3485435c9e | ||
|
|
2ee3daedf6 | ||
|
|
5d0d64abbf | ||
|
|
ea97aee4af | ||
|
|
a968062936 | ||
|
|
6d11475456 | ||
|
|
a7396e0a6a | ||
|
|
ac236e8d7c | ||
|
|
f537608e4f | ||
|
|
c7f4a224ff | ||
|
|
a4d088a3ae | ||
|
|
3cd2c5f433 | ||
|
|
8c69fac9be | ||
|
|
4033eb2294 | ||
|
|
ec469db72a | ||
|
|
5e1ea2469b | ||
|
|
2baa5c61a4 | ||
|
|
b627398b7d | ||
|
|
7be5c072d9 | ||
|
|
de14f9f561 |
@@ -1 +0,0 @@
|
|||||||
60ab8a4b97b446b2dcd32889
|
|
||||||
BIN
public/images/qualityBg.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
208
src/api/httpAjax.js
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import qs from 'qs'
|
||||||
|
import {Notification, MessageBox, Message} from 'element-ui'
|
||||||
|
import store from '@/store'
|
||||||
|
import {getToken} from '@/utils/token'
|
||||||
|
import errorCode from '@/utils/errorCode'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*request请求 axios.request(config)
|
||||||
|
*requestJson请求 axios.request(config)
|
||||||
|
*get请求 axios.get(url[, config])
|
||||||
|
*post请求 axios.post(url[, data[, config]])
|
||||||
|
*postJson请求 axios.post(url[, data[, config]])
|
||||||
|
*put请求 axios.put(url[, data[, config]])
|
||||||
|
*putJson请求 axios.put(url[, data[, config]])
|
||||||
|
*patch请求 axios.patch(url[, data[, config]])
|
||||||
|
*patchJson请求 axios.patch(url[, data[, config]])
|
||||||
|
*delete请求 axios.delete(url[, config])
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// const ReLoginUrl=process.env.VUE_APP_LOGIN_URL;
|
||||||
|
const TokenName = 'token';
|
||||||
|
/**axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'**/
|
||||||
|
//只是用于发送json对象数据时使用post,put,patch
|
||||||
|
/**axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'**/
|
||||||
|
//只是用于发送json对象数据时使用post,put,patch
|
||||||
|
//用于普通的发送请求
|
||||||
|
const formRequest = axios.create({
|
||||||
|
//headers:{'Content-Type':'application/x-www-form-urlencoded'},
|
||||||
|
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||||
|
// baseURL: process.env.VUE_APP_CESOURCE_BASE_API,
|
||||||
|
//超时
|
||||||
|
timeout: 10000,
|
||||||
|
})
|
||||||
|
//发送json对象的拦截器
|
||||||
|
formRequest.interceptors.request.use(config => {
|
||||||
|
//是否需要设置 token
|
||||||
|
const isToken = (config.headers || {}).isToken === false
|
||||||
|
let curToken = getToken();
|
||||||
|
//curToken='eyJ0eXBlIjoidG9rZW4iLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC91LmJvZS5jb20iLCJpYXQiOjE2NzIzMTE2MTIsImV4cCI6MTY3MjMxODgxMiwiR2l2ZW5OYW1lIjoiYm9ldSIsInVzZXJJZCI6IjZCMDQ5RkFGLUMzMTQtN0NDRi0wRDI4LTBEMjNGNEM0MjUzMSIsInVJZCI6Ijk2NTM0MjAyNzQ5NzYwNzE2OCIsInBlcm1pc3Npb24iOiIifQ==.a4f41376e994c5fcd3ab537ce17572ef4c633863f87785cf7b6ffa353e2ed51c';
|
||||||
|
if (curToken && !isToken) {
|
||||||
|
config.headers[TokenName] = curToken // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}, error => {
|
||||||
|
console.log(error)
|
||||||
|
Promise.reject(error)
|
||||||
|
});
|
||||||
|
formRequest.interceptors.response.use(res => {
|
||||||
|
//console.log(res);
|
||||||
|
const code = res.data.status || 200;
|
||||||
|
if (code === 200) {
|
||||||
|
return res.data
|
||||||
|
} else {
|
||||||
|
if (code === 401) {
|
||||||
|
// store.dispatch('LogOut').then(() => {
|
||||||
|
// location.href = this.webBaseUrl + ReLoginUrl;
|
||||||
|
// })
|
||||||
|
console.error('', res.data);
|
||||||
|
return Promise.reject(new Error('接口返回未登录'))
|
||||||
|
} else if (code === 403) {
|
||||||
|
var msg = '当前操作没有权限';
|
||||||
|
Message({message: msg, type: 'error'});
|
||||||
|
return Promise.reject(new Error(msg))
|
||||||
|
} else {
|
||||||
|
//Message({message: res.data.message, type: 'error'});
|
||||||
|
//console.log('err' + res.data.error);
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log('err', error)
|
||||||
|
let {message} = error;
|
||||||
|
if (message == "Network Error") {
|
||||||
|
message = "网络异常,请稍后重试";
|
||||||
|
} else if (message.includes("timeout")) {
|
||||||
|
message = "网络异常或接口错误,请求超时";
|
||||||
|
} else if (message.includes("Request failed with status code")) {
|
||||||
|
message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||||
|
}
|
||||||
|
Message({
|
||||||
|
message: message,
|
||||||
|
type: 'error',
|
||||||
|
duration: 5 * 1000
|
||||||
|
})
|
||||||
|
return Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* request请求,可以自定义参数
|
||||||
|
*/
|
||||||
|
const request = formRequest.request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get请求 ,只有url
|
||||||
|
*/
|
||||||
|
const get = function (baseURL, url) {
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'get',
|
||||||
|
headers: {'Content-Type': 'application/json'}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post请求
|
||||||
|
* @param {Object} url
|
||||||
|
* @param {Object} postData
|
||||||
|
*/
|
||||||
|
const post = function (baseURL, url, postData) {
|
||||||
|
// if (postData) {
|
||||||
|
// postData = qs.stringify(postData);
|
||||||
|
// }
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'post',
|
||||||
|
data: postData,
|
||||||
|
headers: {'Content-Type': 'application/json'}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//post请求
|
||||||
|
const postForm = function (baseURL, url, data) {
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url,
|
||||||
|
data,
|
||||||
|
method: 'post',
|
||||||
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// const postJson=jsonRequest.post;
|
||||||
|
|
||||||
|
const postJson = function (baseURL, url, postData) {
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'post',
|
||||||
|
data: postData,
|
||||||
|
headers: {'Content-Type': 'application/json;charset=utf-8'},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出文件请求定义
|
||||||
|
const postJsonToFile = function (baseURL, url, postData) {
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'post',
|
||||||
|
data: postData,
|
||||||
|
headers: {'Content-Type': 'application/json;charset=utf-8'},
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getJsonToFile = function (baseURL, url, postData) {
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'get',
|
||||||
|
data: postData,
|
||||||
|
headers: {'Content-Type': 'application/json;charset=utf-8'},
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* put请求
|
||||||
|
*/
|
||||||
|
const put = function (baseURL, url, data) {
|
||||||
|
if (data) {
|
||||||
|
data = qs.stringify(data);
|
||||||
|
}
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const putJson = function (baseURL, url, data) {
|
||||||
|
return request({
|
||||||
|
baseURL,
|
||||||
|
url: url,
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
headers: {'Content-Type': 'application/json;charset=utf-8'},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
tokenName: TokenName,
|
||||||
|
request,
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
postJson,
|
||||||
|
postJsonToFile,
|
||||||
|
put,
|
||||||
|
putJson,
|
||||||
|
getJsonToFile
|
||||||
|
}
|
||||||
@@ -34,48 +34,9 @@ const userRsSginupCourse = function(data){
|
|||||||
return ajax.postJson(baseURL,'/stu/project/stuCancelEnrollment',data);
|
return ajax.postJson(baseURL,'/stu/project/stuCancelEnrollment',data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取学员指定新员工转正项目的bpm审批状况
|
|
||||||
* {studentId,pid}
|
|
||||||
* add by zhengsongbo on 2025-07-12
|
|
||||||
*/
|
|
||||||
const getStudntProjectInfo = function(pid){
|
|
||||||
return ajax.get(baseURL,`/stu/project/queryStudentInfo?pid=${pid}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BPM项目:立即报名
|
|
||||||
* pid
|
|
||||||
* add by zhengsongbo on 2025-07-13
|
|
||||||
*/
|
|
||||||
const signUpBpmProjectNow = function(pid){
|
|
||||||
return ajax.get(baseURL,`/stu/project/signUpBpmProjectNow?pid=${pid}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BPM项目:重新报名
|
|
||||||
* pid
|
|
||||||
* add by zhengsongbo on 2025-07-13
|
|
||||||
*/
|
|
||||||
const signUpBpmProjectAgain = function(data){
|
|
||||||
return ajax.postJson(baseURL,'/stu/project/signUpBpmProjectAgain',data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 社招新员工
|
|
||||||
* add by zhengsongbo on 2025-07-14
|
|
||||||
*/
|
|
||||||
const getNewSocialHireProject = function(){
|
|
||||||
return ajax.get(baseURL,'/stu/project/getNewSocialHireProject');
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getTaskNum,
|
getTaskNum,
|
||||||
userTaskList,
|
userTaskList,
|
||||||
userDeleteStudy,
|
userDeleteStudy,
|
||||||
userRsSginupCourse,
|
userRsSginupCourse
|
||||||
getStudntProjectInfo,
|
|
||||||
signUpBpmProjectNow,
|
|
||||||
signUpBpmProjectAgain,
|
|
||||||
getNewSocialHireProject
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
import ajax from '@/utils/xajax.js'
|
import ajax from '@/utils/xajax.js'
|
||||||
import request from "../unionAjax";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存课程基本信息,新增和更新都是此方式
|
* 保存课程基本信息,新增和更新都是此方式
|
||||||
@@ -174,7 +173,6 @@ const detail = function(id) {
|
|||||||
const getDictIds = function(pid,type) {
|
const getDictIds = function(pid,type) {
|
||||||
return ajax.get(`/xboe/m/course/manage/getDictIds?pid=${pid}&type=${type}`);
|
return ajax.get(`/xboe/m/course/manage/getDictIds?pid=${pid}&type=${type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新内容的名称
|
* 更新内容的名称
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
@@ -442,6 +440,11 @@ const queryCrowd=function(query){
|
|||||||
const ids=function (data){
|
const ids=function (data){
|
||||||
return ajax.postJson('/xboe/m/course/manage/ids',data);
|
return ajax.postJson('/xboe/m/course/manage/ids',data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ai播放器相关 - 批量AI设置
|
||||||
|
const benchAiSet=function(data){
|
||||||
|
return ajax.postJson('/xboe/m/course/manage/benchAiSet',data);
|
||||||
|
}
|
||||||
export default {
|
export default {
|
||||||
saveBase,
|
saveBase,
|
||||||
submitCourse,
|
submitCourse,
|
||||||
@@ -484,6 +487,7 @@ export default {
|
|||||||
exportCourseAudit,
|
exportCourseAudit,
|
||||||
exportCourse,
|
exportCourse,
|
||||||
queryCrowd,
|
queryCrowd,
|
||||||
ids
|
ids,
|
||||||
|
benchAiSet
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ const findList = function(data) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const saveUpload = function(data) {
|
const saveUpload = function(data) {
|
||||||
return ajax.post('/xboe/m/course/file/upload/save', data);
|
return ajax.post('/xboe/m/course/file/upload/save', data, {
|
||||||
|
timeout: 60000
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
/**课程标签模块的相关处理*/
|
|
||||||
import ajax from '@/utils/xajax.js'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询:标签列表
|
|
||||||
* @param {Object} query
|
|
||||||
*/
|
|
||||||
const portalPageList = function(query) {
|
|
||||||
return ajax.post('/xboe/m/coursetag/page', query);
|
|
||||||
}
|
|
||||||
|
|
||||||
//改变标签的公共属性
|
|
||||||
const changeTagPublic = function (row){
|
|
||||||
// 返回 Promise 的 API 调用
|
|
||||||
return ajax.post('/xboe/m/coursetag/changePublicStatus', {
|
|
||||||
id: row.id,
|
|
||||||
isPublic: row.isPublic
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//改变标签的热点属性
|
|
||||||
const changeTagHot = function (row){
|
|
||||||
// 返回 Promise 的 API 调用
|
|
||||||
return ajax.post('/xboe/m/coursetag/changeHotStatus', {
|
|
||||||
id: row.id,
|
|
||||||
isHot: row.isHot
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询指定id的标签关联的所有课程
|
|
||||||
const showCourseByTag = function (query){
|
|
||||||
return ajax.post('/xboe/m/coursetag/showCourseByTag', query);
|
|
||||||
}
|
|
||||||
|
|
||||||
//解除指定id的课程和某个标签之间的关联关系
|
|
||||||
const unbindCourseTagRelation = function (params){
|
|
||||||
return ajax.post('/xboe/m/coursetag/unbind', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
//编辑课程:标签模糊查询
|
|
||||||
const searchTags = function (params){
|
|
||||||
return ajax.post('/xboe/m/coursetag/searchTags', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
//编辑课程:创建标签(与当前课程关联)
|
|
||||||
const createTag = function (params){
|
|
||||||
return ajax.post('/xboe/m/coursetag/createTag', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取最新前10个热点标签
|
|
||||||
const getHotTagList = function (params){
|
|
||||||
return ajax.post('/xboe/m/coursetag/getHotTagList', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
portalPageList,
|
|
||||||
changeTagPublic,
|
|
||||||
changeTagHot,
|
|
||||||
showCourseByTag,
|
|
||||||
unbindCourseTagRelation,
|
|
||||||
searchTags,
|
|
||||||
createTag,
|
|
||||||
getHotTagList
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import ajax from '@/utils/xajax.js'
|
import ajax from '@/utils/xajax.js'
|
||||||
import http from '../unionAjax'
|
import http from '../unionAjax'
|
||||||
|
import httpAjax from '../httpAjax'
|
||||||
|
|
||||||
const baseURL = process.env.VUE_APP_MANAGER_API_PATH;
|
const baseURL = process.env.VUE_APP_MANAGER_API_PATH;
|
||||||
|
|
||||||
|
|
||||||
@@ -47,6 +49,18 @@ const articlelist=function (type){
|
|||||||
const courselist=function (data){
|
const courselist=function (data){
|
||||||
return ajax.post('/xboe/portal/index/courselist',data);
|
return ajax.post('/xboe/portal/index/courselist',data);
|
||||||
}
|
}
|
||||||
|
// 精品课信息列表
|
||||||
|
const qualitylist=function (data){
|
||||||
|
return httpAjax.post(baseURL,'/quality/home/qualityItem',data);
|
||||||
|
}
|
||||||
|
// 精品课分页查询
|
||||||
|
export const qualityPageList=function (data){
|
||||||
|
return httpAjax.post(baseURL,'/quality/home/qualityPages',data);
|
||||||
|
}
|
||||||
|
// 课程精品课标记时间年份列表
|
||||||
|
export const qualityCourseTimeMark=function (){
|
||||||
|
return httpAjax.post(baseURL,'/quality/manage/qualityYearList',{});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 首页新课程推荐列表
|
* 首页新课程推荐列表
|
||||||
*/
|
*/
|
||||||
@@ -61,5 +75,7 @@ export default {
|
|||||||
articlelist,
|
articlelist,
|
||||||
courselist,
|
courselist,
|
||||||
newCases,
|
newCases,
|
||||||
getRecommendList
|
getRecommendList,
|
||||||
|
qualitylist,
|
||||||
|
qualityPageList
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/assets/images/course/courseAbstract.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
src/assets/images/course/courseBackground.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
src/assets/images/course/courseNew.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
src/assets/images/course/courseTag.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/images/course/courseTitle.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
src/assets/images/course/generationFailed.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
src/assets/images/course/languageIcon.png
Normal file
|
After Width: | Height: | Size: 478 B |
BIN
src/assets/images/course/noData.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
src/assets/images/course/selectLanguage.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
src/assets/images/course/wengaoTip.png
Normal file
|
After Width: | Height: | Size: 504 B |
|
Before Width: | Height: | Size: 437 KiB |
|
Before Width: | Height: | Size: 42 KiB |
@@ -97,3 +97,29 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-radius: 4px;
|
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;
|
||||||
|
}
|
||||||
439
src/components/Course/aiScript.vue
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ai-script">
|
||||||
|
<!-- 搜索和语言选择区域 -->
|
||||||
|
<div v-if="selectableLang && selectableLang.length > 0" class="search-container">
|
||||||
|
<el-input
|
||||||
|
v-model="searchKeyword"
|
||||||
|
placeholder="请输入关键词查找文稿内容"
|
||||||
|
class="search-input"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
@keyup.enter.native="searchContent"
|
||||||
|
@input="handleInputChange"
|
||||||
|
clearable
|
||||||
|
native-type="text"
|
||||||
|
/>
|
||||||
|
<div class="language-selector">
|
||||||
|
<span class="language-label">语言</span>
|
||||||
|
<el-select v-model="selectedLanguage" class="language-select" @change="changeLanguage" placeholder="请选择语言">
|
||||||
|
<el-option v-for="lang in selectableLang" :key="lang.srclang" :label="getSelectLabel(lang)" :value="lang.srclang"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 内容展示区域 -->
|
||||||
|
<div v-if="selectableLang && selectableLang.length > 0" class="content-container">
|
||||||
|
<!-- 动态渲染内容块 -->
|
||||||
|
<div v-for="(item, index) in contentList" :key="index" class="content-item" :class="{'active': currentTime >= item.start && currentTime <= item.end}">
|
||||||
|
<div class="timestamp">
|
||||||
|
<div class="timestamp-text">
|
||||||
|
<i class="el-icon-time"></i>
|
||||||
|
{{ formatTime(item.start) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-card class="content-text" @click.native="scrollToTime(item.start)">
|
||||||
|
<div v-html="item.highlightedContent || item.text"></div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="no-data">
|
||||||
|
<img src="../../assets/images/course/noData.png" alt="">
|
||||||
|
<span >生成中,过程可能耗时较长,<br>无需在此等待哦~</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 视频链接对应的content Id
|
||||||
|
blobId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
isDrag:{
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: 'ai-script',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchKeyword: '',
|
||||||
|
selectedLanguage: 'zh-CN',
|
||||||
|
originalContentList: [],
|
||||||
|
contentList: [], // 用于显示的内容列表
|
||||||
|
isUserScrolling: false, // 用户是否正在滚动
|
||||||
|
userScrollTimeout: null // 滚动超时计时器
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
'currentTime',
|
||||||
|
'selectableLang',
|
||||||
|
'duration'
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
mounted: function() {
|
||||||
|
// 添加滚动事件监听,检测用户手动滚动
|
||||||
|
const container = document.querySelector('.content-container');
|
||||||
|
if (container) {
|
||||||
|
container.addEventListener('scroll', this.handleUserScroll);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy: function() {
|
||||||
|
// 清理事件监听和计时器
|
||||||
|
const container = document.querySelector('.content-container');
|
||||||
|
if (container) {
|
||||||
|
container.removeEventListener('scroll', this.handleUserScroll);
|
||||||
|
}
|
||||||
|
if (this.userScrollTimeout) {
|
||||||
|
clearTimeout(this.userScrollTimeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
// 监听currentTime变化,自动滚动到当前激活项
|
||||||
|
currentTime: function(newTime) {
|
||||||
|
// 只有当用户没有手动滚动时才执行自动滚动
|
||||||
|
if (!this.isUserScrolling) {
|
||||||
|
this.$nextTick(function() {
|
||||||
|
const activeElement = document.querySelector('.content-item.active');
|
||||||
|
if (activeElement) {
|
||||||
|
// 获取内容容器
|
||||||
|
const container = document.querySelector('.content-container');
|
||||||
|
|
||||||
|
// 计算元素是否在可视区域内
|
||||||
|
const containerRect = container.getBoundingClientRect();
|
||||||
|
const elementRect = activeElement.getBoundingClientRect();
|
||||||
|
|
||||||
|
// 如果元素不在可视区域内,则滚动到可视区域
|
||||||
|
if (elementRect.top < containerRect.top || elementRect.bottom > containerRect.bottom) {
|
||||||
|
// 计算元素相对于容器的偏移量,而不是使用scrollIntoView
|
||||||
|
// 这样只会滚动content-container内部,不会影响页面滚动
|
||||||
|
|
||||||
|
// 计算元素相对于容器的位置
|
||||||
|
const elementOffsetTop = activeElement.offsetTop;
|
||||||
|
const containerScrollTop = container.scrollTop;
|
||||||
|
const containerHeight = container.clientHeight;
|
||||||
|
const elementHeight = activeElement.clientHeight;
|
||||||
|
|
||||||
|
// 计算目标滚动位置,使元素居中显示
|
||||||
|
// 考虑容器的内边距和元素本身的高度
|
||||||
|
let targetScrollTop = elementOffsetTop - (containerHeight / 2) + (elementHeight / 2);
|
||||||
|
|
||||||
|
// 确保目标滚动位置不会小于0
|
||||||
|
targetScrollTop = Math.max(0, targetScrollTop);
|
||||||
|
|
||||||
|
// 确保目标滚动位置不会导致元素超出容器底部
|
||||||
|
const maxScrollTop = container.scrollHeight - containerHeight;
|
||||||
|
targetScrollTop = Math.min(targetScrollTop, maxScrollTop);
|
||||||
|
|
||||||
|
// 使用requestAnimationFrame实现平滑滚动
|
||||||
|
const startScrollTop = containerScrollTop;
|
||||||
|
const distance = targetScrollTop - startScrollTop;
|
||||||
|
const duration = 300; // 滚动持续时间,毫秒
|
||||||
|
let startTime = null;
|
||||||
|
|
||||||
|
function animateScroll(currentTime) {
|
||||||
|
if (!startTime) startTime = currentTime;
|
||||||
|
const timeElapsed = currentTime - startTime;
|
||||||
|
container.scrollTo({
|
||||||
|
top: startScrollTop + distance - elementHeight - 120,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (timeElapsed < duration) {
|
||||||
|
requestAnimationFrame(animateScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(animateScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 初始化时根据语言选择显示内容
|
||||||
|
this.changeLanguage(this.selectedLanguage)
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 动态获取选择框的标签
|
||||||
|
getSelectLabel(lang) {
|
||||||
|
if (lang.srclang == 'zh-CN') {
|
||||||
|
return lang.label;
|
||||||
|
}
|
||||||
|
return `${lang.name} (${lang.label})`;
|
||||||
|
},
|
||||||
|
formatTime (time) {
|
||||||
|
// 格式化时间为HH:MM:SS,如01:00:00
|
||||||
|
const hours = Math.floor(time / 3600);
|
||||||
|
const minutes = Math.floor((time % 3600) / 60);
|
||||||
|
const seconds = Math.floor(time % 60);
|
||||||
|
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||||
|
},
|
||||||
|
// 跳转到指定时间点
|
||||||
|
scrollToTime(time) {
|
||||||
|
// console.log('scrollToTime', time , this.blobId, localStorage.getItem('videoProgressData'), this.duration)
|
||||||
|
if(!this.isDrag && this.duration){
|
||||||
|
var t = localStorage.getItem('videoProgressData')
|
||||||
|
var arr = t&&JSON.parse(t) || {}
|
||||||
|
if(arr[this.blobId] < time/this.duration || !arr[this.blobId]){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('跳转到时间点:', time);
|
||||||
|
this.$emit('changeCurrentTime', time);
|
||||||
|
// 设置用户滚动状态,避免自动滚动干扰
|
||||||
|
this.isUserScrolling = true;
|
||||||
|
if (this.userScrollTimeout) {
|
||||||
|
clearTimeout(this.userScrollTimeout);
|
||||||
|
}
|
||||||
|
this.userScrollTimeout = setTimeout(() => {
|
||||||
|
this.isUserScrolling = false;
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
// 处理用户滚动事件
|
||||||
|
handleUserScroll: function() {
|
||||||
|
this.isUserScrolling = true;
|
||||||
|
|
||||||
|
// 清除之前的计时器
|
||||||
|
if (this.userScrollTimeout) {
|
||||||
|
clearTimeout(this.userScrollTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置新的计时器,3秒后恢复自动滚动
|
||||||
|
this.userScrollTimeout = setTimeout(() => {
|
||||||
|
this.isUserScrolling = false;
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
|
||||||
|
searchContent () {
|
||||||
|
// 搜索功能实现
|
||||||
|
if (!this.searchKeyword.trim()) {
|
||||||
|
// 如果搜索关键词为空,显示所有内容
|
||||||
|
this.contentList = this.originalContentList.map(item => ({ ...item }));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyword = this.searchKeyword.trim();
|
||||||
|
// 过滤包含关键词的内容
|
||||||
|
const filteredList = this.originalContentList.filter(item =>
|
||||||
|
item.text.includes(keyword)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (filteredList.length === 0) {
|
||||||
|
// 如果没有搜索到内容,显示提示
|
||||||
|
this.$message({
|
||||||
|
message: '未找到相关内容',
|
||||||
|
type: 'info'
|
||||||
|
});
|
||||||
|
this.contentList = this.originalContentList.map(item => ({ ...item }));
|
||||||
|
} else {
|
||||||
|
// 对搜索到的内容进行关键词高亮处理
|
||||||
|
this.contentList = filteredList.map(item => ({
|
||||||
|
...item,
|
||||||
|
highlightedContent: this.highlightKeyword(item.text, keyword)
|
||||||
|
}));
|
||||||
|
console.log(this.contentList)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
highlightKeyword(content, keyword) {
|
||||||
|
// 对关键词进行转义,防止正则表达式特殊字符的影响
|
||||||
|
const escapedKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
// 使用正则表达式全局匹配关键词并添加高亮标记
|
||||||
|
const regex = new RegExp(`(${escapedKeyword})`, 'gi');
|
||||||
|
return content.replace(regex, '<span style="color: rgba(6, 125, 255, 1); background: rgba(6, 125, 255, 0.1);">$1</span>');
|
||||||
|
},
|
||||||
|
changeLanguage (event) {
|
||||||
|
// this.selectedLanguage = event
|
||||||
|
this.selectableLang.forEach(item => {
|
||||||
|
if (item.srclang === event) {
|
||||||
|
console.log('当前语言:', item)
|
||||||
|
if (!item.originalContentList) {
|
||||||
|
try {
|
||||||
|
item.originalContentList = JSON.parse(item.subtitleData)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('ai文稿格式有问题!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.originalContentList = item.originalContentList || []
|
||||||
|
// 初始化时显示所有内容
|
||||||
|
this.contentList = this.originalContentList.map(item => ({ ...item }));
|
||||||
|
console.log('ai文稿数据:', this.originalContentList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('切换语言:', event)
|
||||||
|
},
|
||||||
|
handleInputChange() {
|
||||||
|
// 当输入框内容变化时,如果为空则重置显示所有内容
|
||||||
|
if (!this.searchKeyword.trim()) {
|
||||||
|
this.contentList = this.originalContentList.map(item => ({ ...item }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ai-script {
|
||||||
|
padding: 15px 0;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 0 20px 15px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input__inner {
|
||||||
|
border-color: #2688FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input__inner:focus {
|
||||||
|
border-color: #1a6fe0;
|
||||||
|
box-shadow: 0 0 0 2px rgba(38, 136, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input__prefix {
|
||||||
|
left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input__icon {
|
||||||
|
color: #2688FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-selector {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-select {
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
max-height: 410px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timestamp {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
padding: 5px 0;
|
||||||
|
.timestamp-text{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 2px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(102, 102, 102, 1);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: rgba(250, 250, 250, 1);
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0.28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
.timestamp-text{
|
||||||
|
color: rgba(6, 125, 255, 1);
|
||||||
|
background: rgba(6, 125, 255, 0.1);
|
||||||
|
}
|
||||||
|
.content-text{
|
||||||
|
border: 1px solid rgba(116, 182, 255, 1);
|
||||||
|
box-shadow: 0px 0px 7px 0px rgba(6, 125, 255, 0.24);
|
||||||
|
background: rgba(250, 250, 250, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-card.is-hover-shadow:focus, .el-card.is-hover-shadow:hover) {
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(38, 136, 255, 0.2);
|
||||||
|
}
|
||||||
|
:deep(.el-input__inner) {
|
||||||
|
border-radius: 4px!important;
|
||||||
|
}
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.search-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.language-selector {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.no-data{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding-top: 60px;
|
||||||
|
color: rgba(0, 0, 0, 0.34);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 21px;
|
||||||
|
letter-spacing: 0.26px;
|
||||||
|
text-align: center;
|
||||||
|
img{
|
||||||
|
width: 96px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<el-input-number v-model="duration" size="mini" :min="1" :max="100"></el-input-number>
|
<el-input-number v-model="duration" size="mini" :min="1" :max="100"></el-input-number>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<el-upload class="upload-demo" :headers="headers" :data="data" drag :action="uploadFileUrl" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload">
|
<el-upload ref="uploadRef" class="upload-demo" :headers="headers" :data="data" drag :action="uploadFileUrl" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload">
|
||||||
<i class="el-icon-upload"></i>
|
<i class="el-icon-upload"></i>
|
||||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
<div class="el-upload__tip" slot="tip">文件大小限制:{{curComType.maxSizeName}},支持的文件类型:{{curComType.fileTypes.join(',')}}</div>
|
<div class="el-upload__tip" slot="tip">文件大小限制:{{curComType.maxSizeName}},支持的文件类型:{{curComType.fileTypes.join(',')}}</div>
|
||||||
@@ -195,6 +195,7 @@
|
|||||||
// this.cware.content.content=result.filePath;
|
// this.cware.content.content=result.filePath;
|
||||||
}else{
|
}else{
|
||||||
this.$message.error(rs.message);
|
this.$message.error(rs.message);
|
||||||
|
this.$refs.uploadRef.clearFiles();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -158,6 +158,43 @@
|
|||||||
placeholder="请尽量填写课程简介,用于列表中显示,可以让用户更容易了解课程信息">
|
placeholder="请尽量填写课程简介,用于列表中显示,可以让用户更容易了解课程信息">
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="AI设置">
|
||||||
|
<div style="margin-top: 7px;">
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;">
|
||||||
|
<el-switch v-model="courseInfo.aiSet" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiSetTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-show="courseInfo.aiSet==1" style="margin-left: -20px;">
|
||||||
|
<div style="display: flex; justify-content: space-between;;align-items: center;gap: 5px;margin: 10px 0;">
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;">
|
||||||
|
<span>AI摘要</span>
|
||||||
|
<el-switch v-model="courseInfo.aiAbstract" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiAbstractTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;">
|
||||||
|
<span>AI文稿</span>
|
||||||
|
<el-switch v-model="courseInfo.aiDraft" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiDraftTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;margin: 10px 0;margin-left: -30px;">
|
||||||
|
<span>AI翻译语种</span>
|
||||||
|
<el-select v-model="courseInfo.languageCode" placeholder="请选择" multiple filterable style="width: 240px;">
|
||||||
|
<el-option v-for="item in selectAllLang" :key="item.key" :label="item.label" :value="item.srclang"> </el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiTranslateTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="14">
|
<el-col :span="14">
|
||||||
<div @click="checkCourse"><weikeContent ref="weikeContent" :reset="weikeReset" :contents="contentInfo.list" :course="courseInfo" min-height="644px"></weikeContent></div>
|
<div @click="checkCourse"><weikeContent ref="weikeContent" :reset="weikeReset" :contents="contentInfo.list" :course="courseInfo" min-height="644px"></weikeContent></div>
|
||||||
@@ -254,9 +291,6 @@
|
|||||||
</el-select> -->
|
</el-select> -->
|
||||||
<choice :teacherValue="teacherValues" @getTeacherList="getTeacherList"></choice>
|
<choice :teacherValue="teacherValues" @getTeacherList="getTeacherList"></choice>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="标签" required>
|
|
||||||
<courseTag :courseId="curCourseId" :sysTypeList="sysTypeList"></courseTag>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="关键字">
|
<el-form-item label="关键字">
|
||||||
<el-input v-model.trim="keywords" maxlength="100" @keyup.enter.native="changeKeywords" placeholder="请输入关键字"></el-input>
|
<el-input v-model.trim="keywords" maxlength="100" @keyup.enter.native="changeKeywords" placeholder="请输入关键字"></el-input>
|
||||||
<el-tag v-for="(tag,index) in tips" size="small" :key="index" closable type="info" @close="closeKeywordsTag(tag,index)">
|
<el-tag v-for="(tag,index) in tips" size="small" :key="index" closable type="info" @close="closeKeywordsTag(tag,index)">
|
||||||
@@ -332,6 +366,44 @@
|
|||||||
placeholder="请尽量填写课程简介,用于列表中显示,可以让用户更容易了解课程信息">
|
placeholder="请尽量填写课程简介,用于列表中显示,可以让用户更容易了解课程信息">
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- ai播放器相关 -->
|
||||||
|
<el-form-item label="AI设置">
|
||||||
|
<div style="margin-top: 7px;">
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;">
|
||||||
|
<el-switch v-model="courseInfo.aiSet" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiSetTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div v-show="courseInfo.aiSet==1" style="margin-left: -20px;">
|
||||||
|
<div style="display: flex;align-items: center;gap: 80px;margin: 20px 0;">
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;">
|
||||||
|
<span>AI摘要</span>
|
||||||
|
<el-switch v-model="courseInfo.aiAbstract" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiAbstractTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;">
|
||||||
|
<span>AI文稿</span>
|
||||||
|
<el-switch v-model="courseInfo.aiDraft" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiDraftTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; align-items: center;gap: 5px;margin: 20px 0;margin-left: -30px;">
|
||||||
|
<span>AI翻译语种</span>
|
||||||
|
<el-select v-model="courseInfo.languageCode" placeholder="请选择" multiple filterable style="flex:1">
|
||||||
|
<el-option v-for="item in selectAllLang" :key="item.key" :label="item.label" :value="item.srclang"> </el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiTranslateTip" placement="top">
|
||||||
|
<i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: pointer;"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
<!-- v-if="!weike.onlyRequired" -->
|
<!-- v-if="!weike.onlyRequired" -->
|
||||||
<!-- <el-form-item label="课程描述">
|
<!-- <el-form-item label="课程描述">
|
||||||
<WxEditor v-model="courseInfo.overview" :minHeight="50"></WxEditor>
|
<WxEditor v-model="courseInfo.overview" :minHeight="50"></WxEditor>
|
||||||
@@ -407,7 +479,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import courseTag from "@/components/Course/courseTag.vue";
|
|
||||||
import choice from '@/components/Course/choice.vue';
|
import choice from '@/components/Course/choice.vue';
|
||||||
import agreement from '@/components/Portal/agreement.vue';
|
import agreement from '@/components/Portal/agreement.vue';
|
||||||
import weikeContent from '@/components/Course/weikeContent.vue';
|
import weikeContent from '@/components/Course/weikeContent.vue';
|
||||||
@@ -432,7 +503,7 @@ import filecloud from '@/components/FileCloud/index.vue';
|
|||||||
import chooseOrg from '@/components/System/chooseOrg.vue';
|
import chooseOrg from '@/components/System/chooseOrg.vue';
|
||||||
export default {
|
export default {
|
||||||
props: {},
|
props: {},
|
||||||
components: { courseTag, weikeContent, catalogCourseware, imageUpload, WxEditor, catalogSort,agreement,filecloud,choice,chooseOrg},
|
components: { weikeContent, catalogCourseware, imageUpload, WxEditor, catalogSort,agreement,filecloud,choice,chooseOrg},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
keywords:'',//关键字的定义
|
keywords:'',//关键字的定义
|
||||||
@@ -539,14 +610,19 @@ export default {
|
|||||||
selectedOrg: {
|
selectedOrg: {
|
||||||
orgId: null,
|
orgId: null,
|
||||||
name: ''
|
name: ''
|
||||||
}
|
},
|
||||||
|
aiSetTip: '是否将课程进行AI处理', //提示信息
|
||||||
|
aiAbstractTip: '一键提炼课程视频核心要点,助力学员课前高效掌握重点,快速筛选学习资源', // 提示信息
|
||||||
|
aiDraftTip: '分段展示视频内容并精准同步时间轴,实现视频进度与文稿双向定位,学习内容触手可及', //提示信息
|
||||||
|
aiTranslateTip: '智能转换视频字幕与语音为多语种,支持全球学员按需切换语言,打破学习边界', // 提示信息
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getSceneData();
|
this.getSceneData();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['resOwnerMap', 'sysTypeMap','userInfo','identity']),
|
// ai播放器相关
|
||||||
|
...mapGetters(['resOwnerMap', 'sysTypeMap','userInfo','identity', 'selectAllLang']),
|
||||||
catalogTree() {
|
catalogTree() {
|
||||||
let treeList = [];
|
let treeList = [];
|
||||||
let $this = this;
|
let $this = this;
|
||||||
@@ -606,7 +682,7 @@ export default {
|
|||||||
this.isPermission = false;
|
this.isPermission = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("--- dicts = ",this.dicts)
|
console.log("--- this.dicts = ",this.dicts)
|
||||||
this.isPermission = this.dicts.includes(orgId);
|
this.isPermission = this.dicts.includes(orgId);
|
||||||
console.log("--- 监听结束 this.isPermission = ",this.isPermission)
|
console.log("--- 监听结束 this.isPermission = ",this.isPermission)
|
||||||
},
|
},
|
||||||
@@ -828,7 +904,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.initAiData();
|
||||||
} else {
|
} else {
|
||||||
//console.log(editData,'editData');
|
//console.log(editData,'editData');
|
||||||
this.weikeReset = editData.id;
|
this.weikeReset = editData.id;
|
||||||
@@ -920,6 +996,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const response = await apiCourse.getDictIds(637, 1); // 确保返回 Promise
|
const response = await apiCourse.getDictIds(637, 1); // 确保返回 Promise
|
||||||
console.log("--- 获取字典信息 2 result= ", response);
|
console.log("--- 获取字典信息 2 result= ", response);
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.dicts = response.result.dicts; // 正确提取 dicts
|
this.dicts = response.result.dicts; // 正确提取 dicts
|
||||||
console.log("--- 获取字典信息 3 = ", this.dicts);
|
console.log("--- 获取字典信息 3 = ", this.dicts);
|
||||||
@@ -928,6 +1005,23 @@ export default {
|
|||||||
console.error("获取字典信息失败:", error);
|
console.error("获取字典信息失败:", error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// ai播放器相关
|
||||||
|
// 初始化ai数据
|
||||||
|
initAiData() {
|
||||||
|
// 如果ai设置为空则给默认值 - 会看成新增状态
|
||||||
|
if(this.courseInfo.aiSet === null || this.courseInfo.aiSet === '' || this.courseInfo.aiSet === undefined){
|
||||||
|
this.courseInfo.isAddAI = 1; //暂时是否是新增
|
||||||
|
this.courseInfo.aiSet = 1;
|
||||||
|
this.courseInfo.aiAbstract = 1;
|
||||||
|
this.courseInfo.aiDraft = 1;
|
||||||
|
this.courseInfo.aiTranslate = 1;
|
||||||
|
this.courseInfo.languageStatus = 1;
|
||||||
|
this.courseInfo.languageCode = ['zh-CN', 'en-US'];
|
||||||
|
} else {
|
||||||
|
// 获取ai设置信息
|
||||||
|
this.courseInfo.isAddAI = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
//获取课程信息
|
//获取课程信息
|
||||||
async getDetail(id) {
|
async getDetail(id) {
|
||||||
this.curCourseId = id;
|
this.curCourseId = id;
|
||||||
@@ -954,6 +1048,8 @@ export default {
|
|||||||
this.dicts = result.dicts; //课程的老师信息
|
this.dicts = result.dicts; //课程的老师信息
|
||||||
console.log("--- 编辑查看 this.isPermission = ",this.isPermission)
|
console.log("--- 编辑查看 this.isPermission = ",this.isPermission)
|
||||||
console.log("--- 编辑查看 this.dicts = ",this.dicts)
|
console.log("--- 编辑查看 this.dicts = ",this.dicts)
|
||||||
|
// ai播放器相关
|
||||||
|
this.initAiData()
|
||||||
if(!this.courseInfo.orgId){
|
if(!this.courseInfo.orgId){
|
||||||
//根据课程创建者获取机构id
|
//根据课程创建者获取机构id
|
||||||
apiUser.getOrgSimpleByUserId(result.course.sysCreateAid).then(ors=>{
|
apiUser.getOrgSimpleByUserId(result.course.sysCreateAid).then(ors=>{
|
||||||
|
|||||||
@@ -48,17 +48,13 @@ export default {
|
|||||||
let name = '';
|
let name = '';
|
||||||
if (this.course && this.course.name && this.course.name !== '') {
|
if (this.course && this.course.name && this.course.name !== '') {
|
||||||
name = this.course.name.replace('color:#FF0000', 'color:#fff');
|
name = this.course.name.replace('color:#FF0000', 'color:#fff');
|
||||||
console.log("name gengxindata1 : ",name)
|
|
||||||
}
|
}
|
||||||
if (this.course && this.course.courseName && this.course.courseName !== '') {
|
if (this.course && this.course.courseName && this.course.courseName !== '') {
|
||||||
name = this.course.courseName.replace('color:#FF0000', 'color:#fff');
|
name = this.course.courseName.replace('color:#FF0000', 'color:#fff');
|
||||||
console.log("name gengxindata2 : ",name)
|
|
||||||
}
|
}
|
||||||
if (this.course && this.course.title && this.course.title !== '') {
|
if (this.course && this.course.title && this.course.title !== '') {
|
||||||
name = this.course.title.replace('color:#FF0000', 'color:#fff');
|
name = this.course.title.replace('color:#FF0000', 'color:#fff');
|
||||||
console.log("name gengxindata3 : ",name)
|
|
||||||
}
|
}
|
||||||
console.log("name gengxindata4 : ",name)
|
|
||||||
return name;
|
return name;
|
||||||
// course.name || course.courseName || course.title
|
// course.name || course.courseName || course.title
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
|
|
||||||
<template>
|
|
||||||
<div class="tag-container">
|
|
||||||
<el-select style="width: 100%;"
|
|
||||||
v-model="selectedTags"
|
|
||||||
multiple
|
|
||||||
filterable
|
|
||||||
value-key="id"
|
|
||||||
remote
|
|
||||||
reserve-keyword
|
|
||||||
:remote-method="debouncedSearch"
|
|
||||||
:loading="loading"
|
|
||||||
:disabled="sysTypeList.length===0"
|
|
||||||
placeholder="按回车键Enter创建标签"
|
|
||||||
@remove-tag="handleTagRemove"
|
|
||||||
@keyup.enter.native="handleEnterKey"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in searchResults"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.tagName"
|
|
||||||
:value="item"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
<!-- 预览 ---
|
|
||||||
<div class="tag-preview">
|
|
||||||
<el-tag
|
|
||||||
v-for="tag in displayTags"
|
|
||||||
:key="tag.id"
|
|
||||||
closable
|
|
||||||
@close="removeTag(tag.id)"
|
|
||||||
>
|
|
||||||
{{ tag.tagName }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { debounce } from 'lodash'
|
|
||||||
import apiCourseTag from '@/api/modules/courseTag.js'
|
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
courseId:{
|
|
||||||
type:String,
|
|
||||||
require:true,
|
|
||||||
},
|
|
||||||
sysTypeList:{
|
|
||||||
type:Array,
|
|
||||||
require:true,
|
|
||||||
default: []
|
|
||||||
},
|
|
||||||
maxTags: {
|
|
||||||
type: Number,
|
|
||||||
default: 10
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selectedTags: [],
|
|
||||||
searchResults: [],
|
|
||||||
loading: false,
|
|
||||||
tagMap: new Map(),
|
|
||||||
inputBuffer: '',
|
|
||||||
params: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['userInfo']),
|
|
||||||
displayTags() {
|
|
||||||
return this.selectedTags.map(tag =>
|
|
||||||
typeof tag === 'object' ? tag : this.tagMap.get(tag)
|
|
||||||
).filter(Boolean)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.debouncedSearch = debounce(this.doSearch, 500)
|
|
||||||
console.log("----------sysTypeList.length---------->"+this.sysTypeList.length)
|
|
||||||
console.log("----------sysTypeList.length---------->"+(this.sysTypeList.length===0))
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async doSearch(query) {
|
|
||||||
if (!query.trim()) {
|
|
||||||
this.searchResults = []
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
const {result:tags} = await apiCourseTag.searchTags({tagName:query})
|
|
||||||
tags.forEach(item => {
|
|
||||||
this.tagMap.set(item.id, item)
|
|
||||||
})
|
|
||||||
this.searchResults = tags
|
|
||||||
} finally {
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleTagRemove(tagId) {
|
|
||||||
this.selectedTags = this.selectedTags.filter(id => id !== tagId)
|
|
||||||
this.$emit('change', this.displayTags)
|
|
||||||
},
|
|
||||||
removeTag(tagId) {
|
|
||||||
this.handleTagRemove(tagId)
|
|
||||||
},
|
|
||||||
|
|
||||||
//按回车键,创建新标签
|
|
||||||
handleEnterKey(event) {
|
|
||||||
const inputVal = event.target.value?.trim()
|
|
||||||
if (!this.searchResults.length && inputVal && this.selectedTags.length < this.maxTags) {
|
|
||||||
this.createNewTag(event.target.value.trim())
|
|
||||||
event.target.value = ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//创建新标签
|
|
||||||
async createNewTag(tagName) {
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
this.params.courseId = this.courseId;
|
|
||||||
this.params.tagName = tagName;
|
|
||||||
// 分类
|
|
||||||
if (this.sysTypeList.length > 0) {
|
|
||||||
this.params.sysType1 = this.sysTypeList[0]; //一级的id
|
|
||||||
}
|
|
||||||
if (this.sysTypeList.length > 1) {
|
|
||||||
this.params.sysType2 = this.sysTypeList[1]; //二级的id
|
|
||||||
}
|
|
||||||
if (this.sysTypeList.length > 2) {
|
|
||||||
this.params.sysType3 = this.sysTypeList[2]; //三级的id
|
|
||||||
}
|
|
||||||
const {result:newTag} = await apiCourseTag.createTag(this.params)
|
|
||||||
this.tagMap.set(newTag.id, newTag)
|
|
||||||
this.selectedTags.push(newTag.tagName)
|
|
||||||
this.$emit('change', this.selectedTags.map(tag => tag.id))
|
|
||||||
} finally {
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.tag-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.tag-preview {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
.el-tag {
|
|
||||||
margin-right: 6px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -558,7 +558,7 @@
|
|||||||
this.$message.error(res.message);
|
this.$message.error(res.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.loadData(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -633,7 +633,6 @@
|
|||||||
this.$message.error(res.message);
|
this.$message.error(res.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.loadData(false);
|
|
||||||
},
|
},
|
||||||
delCommnet(com,idx){
|
delCommnet(com,idx){
|
||||||
if(com.replyList!='' && com.replyList.length>0){
|
if(com.replyList!='' && com.replyList.length>0){
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<!-- <svg-icon v-else style="margin-right: 0;" :style="{'font-size':(size+2)+'px'}" :icon-class="isFavorite?'scactive2':'xihuan'"></svg-icon> -->
|
<!-- <svg-icon v-else style="margin-right: 0;" :style="{'font-size':(size+2)+'px'}" :icon-class="isFavorite?'scactive2':'xihuan'"></svg-icon> -->
|
||||||
<div v-else class="is_favorite" :class="isFavorite?'is_favorite_a':'is_favorite'"></div>
|
<div v-else class="is_favorite" :class="isFavorite?'is_favorite_a':'is_favorite'"></div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span v-if="!courseExclusive" class="interact-bar-value"> {{ data.favorites? data.favorites:0}}</span>
|
<span v-if="!courseExclusive" class="interact-bar-value"> {{ data.favorites? data.favorites:data.hasCollect?number(data.hasCollect):1}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="shares" @click="addShare()" :style="`min-width: ${nodeWidth};`" class="interact-bar-btn" :class="{cursor:!readonly}">
|
<div v-if="shares" @click="addShare()" :style="`min-width: ${nodeWidth};`" class="interact-bar-btn" :class="{cursor:!readonly}">
|
||||||
<el-tooltip effect="light" content="分享" placement="top" :visible-arrow="false" popper-class="text-tooltip">
|
<el-tooltip effect="light" content="分享" placement="top" :visible-arrow="false" popper-class="text-tooltip">
|
||||||
@@ -114,6 +114,8 @@ export default {
|
|||||||
shares:0,
|
shares:0,
|
||||||
praises:0,
|
praises:0,
|
||||||
views:0,
|
views:0,
|
||||||
|
courseId:'',
|
||||||
|
courseName:''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -234,7 +236,7 @@ export default {
|
|||||||
created(){
|
created(){
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if(this.data && this.data.id && !this.readonly){
|
if(this.data && (this.data.id||this.data.courseId) && !this.readonly){
|
||||||
this.checkHas();
|
this.checkHas();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +310,7 @@ export default {
|
|||||||
}
|
}
|
||||||
let msgPageParams=this.pageParams;
|
let msgPageParams=this.pageParams;
|
||||||
if(!msgPageParams){
|
if(!msgPageParams){
|
||||||
msgPageParams=this.data.id;
|
msgPageParams=this.data.id ?this.data.id: this.data.courseId;
|
||||||
}
|
}
|
||||||
let message={
|
let message={
|
||||||
content,
|
content,
|
||||||
@@ -331,9 +333,9 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
checkHas(){
|
checkHas(){
|
||||||
if(this.type>0 && !this.readonly && this.data.id){
|
if(this.type>0 && !this.readonly && (this.data.id||this.data.courseId)){
|
||||||
if(this.favorites){
|
if(this.favorites){
|
||||||
apiFavorites.has(this.type,this.data.id).then(rs=>{
|
apiFavorites.has(this.type,(this.data.id || this.data.courseId)).then(rs=>{
|
||||||
if(rs.status==200 && rs.result){
|
if(rs.status==200 && rs.result){
|
||||||
this.isFavorite=true;
|
this.isFavorite=true;
|
||||||
}else{
|
}else{
|
||||||
@@ -506,9 +508,11 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//需要判断是否已点赞,已点赞的不再加
|
//需要判断是否已点赞,已点赞的不再加
|
||||||
|
console.log(this.data,'---------------');
|
||||||
|
|
||||||
let postData={
|
let postData={
|
||||||
objType:this.type,
|
objType:this.type,
|
||||||
objId:this.data.id,
|
objId:this.data.id ?this.data.id: this.data.courseId,
|
||||||
title:'',
|
title:'',
|
||||||
}
|
}
|
||||||
if(this.loading) {
|
if(this.loading) {
|
||||||
@@ -516,7 +520,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.loading=true;
|
this.loading=true;
|
||||||
if(this.type==1){
|
if(this.type==1){
|
||||||
postData.title=this.data.name;
|
postData.title=this.data.name?this.data.name:this.data.courseName;
|
||||||
}else if(this.type==60){
|
}else if(this.type==60){
|
||||||
postData.title=this.data.content;
|
postData.title=this.data.content;
|
||||||
} else if(this.type==5){
|
} else if(this.type==5){
|
||||||
@@ -525,7 +529,7 @@ export default {
|
|||||||
postData.title=this.data.title;
|
postData.title=this.data.title;
|
||||||
}
|
}
|
||||||
if(this.isFavorite) {// 已经收藏,再次点击取消收藏
|
if(this.isFavorite) {// 已经收藏,再次点击取消收藏
|
||||||
apiFavorites.remove(this.type,this.data.id).then(res=>{
|
apiFavorites.remove(this.type,this.data.id ?this.data.id: this.data.courseId).then(res=>{
|
||||||
this.loading=false;
|
this.loading=false;
|
||||||
if(res.status==200){
|
if(res.status==200){
|
||||||
this.isFavorite=false;
|
this.isFavorite=false;
|
||||||
@@ -554,7 +558,7 @@ export default {
|
|||||||
this.$store.dispatch("unicomFavorites",true)
|
this.$store.dispatch("unicomFavorites",true)
|
||||||
}
|
}
|
||||||
//if(this.type===2||this.type===4){
|
//if(this.type===2||this.type===4){
|
||||||
this.messageSave(this.data.id,this.data.title,this.userInfo.name,this.data.sysCreateBy,this.data.sysCreateAid,'收藏了我发布的');
|
this.messageSave(this.data.id ?this.data.id: this.data.courseId,this.data.title,this.userInfo.name,this.data.sysCreateBy,this.data.sysCreateAid,'收藏了我发布的');
|
||||||
//}
|
//}
|
||||||
this.$message({message:'已加入收藏',type:'success'});
|
this.$message({message:'已加入收藏',type:'success'});
|
||||||
//this.$emit('addFavorite',res.result);//添加收藏,如果是true代表添加成功,false代表已存在
|
//this.$emit('addFavorite',res.result);//添加收藏,如果是true代表添加成功,false代表已存在
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-nav" :style="{color:textColor}" :class="current == 'course' ? activeNav : ''">
|
<div class="top-nav" :style="{color:textColor}" :class="current == 'course' ? activeNav : ''">
|
||||||
<router-link to="/course">课程
|
<a @click="handleChangeCourse">课程
|
||||||
<div :class="current == 'course' ? 'nav-bottbor' : ''"></div>
|
<div :class="current == 'course' ? 'nav-bottbor' : ''"></div>
|
||||||
</router-link>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-nav" :style="{color:textColor}" :class="current == 'case' ? activeNav : ''">
|
<div class="top-nav" :style="{color:textColor}" :class="current == 'case' ? activeNav : ''">
|
||||||
<router-link to="/case">案例
|
<router-link to="/case">案例
|
||||||
@@ -137,30 +137,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- "社招新员工转正培训项目简介"弹框 -->
|
|
||||||
<el-dialog width="733px"
|
|
||||||
:visible.sync="projectDialogVisible"
|
|
||||||
:append-to-body="true"
|
|
||||||
>
|
|
||||||
<div class="el-dialog__header">
|
|
||||||
<span style="font-size: 35px; font-weight: bold; color: white; margin: 60px;line-height: 100px;">项目简介</span>
|
|
||||||
</div>
|
|
||||||
<div style="height: 280px;margin: 0px 40px 0px 40px;">
|
|
||||||
<span v-html="studentInfo.introduction"></span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span style="font-size: 14px; margin: 40px;" v-if="studentInfo.bpmStatus!=0">审批编号:<span style="font-weight: bold;">{{studentInfo.bpmNumber}}</span></span>
|
|
||||||
<br/>
|
|
||||||
<span style="font-size: 14px; margin: 40px;">审批状态:<span style="font-weight: bold; color: #efbf82">{{studentInfo.bpmStatusName}}</span></span>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="signUpNow" v-if="studentInfo.bpmStatus==0">立即报名</el-button>
|
|
||||||
<el-button v-if="studentInfo.bpmStatus==1" disabled>审批中</el-button>
|
|
||||||
<el-button type="primary" @click="signUpAgain" v-if="studentInfo.bpmStatus==3">重新报名</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
<popup></popup><yearMedal></yearMedal>
|
<popup></popup><yearMedal></yearMedal>
|
||||||
</div>
|
</div>
|
||||||
@@ -168,7 +144,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters, mapActions } from 'vuex';
|
import { mapGetters, mapActions } from 'vuex';
|
||||||
import apiMessage from '@/api/system/message.js';
|
import apiMessage from '@/api/system/message.js';
|
||||||
import apiManage from '@/api/manage/manage.js';
|
|
||||||
import popup from '@/components/AlertPopup.vue';
|
import popup from '@/components/AlertPopup.vue';
|
||||||
import yearMedal from '@/components/Popup/China2023.vue';
|
import yearMedal from '@/components/Popup/China2023.vue';
|
||||||
import apiBoeCourse from '@/api/boe/course.js';
|
import apiBoeCourse from '@/api/boe/course.js';
|
||||||
@@ -229,8 +204,6 @@ export default {
|
|||||||
keyword: '',
|
keyword: '',
|
||||||
isTiao: false,
|
isTiao: false,
|
||||||
sex:'',
|
sex:'',
|
||||||
projectDialogVisible: false,
|
|
||||||
studentInfo: {},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -241,22 +214,13 @@ export default {
|
|||||||
//this.loadPopupConfig();
|
//this.loadPopupConfig();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
//BPM项目:立即报名
|
handleChangeCourse() {
|
||||||
signUpNow(){
|
const paths = ["/course","/qualityCourse"]
|
||||||
const pid = this.studentInfo.projectId;
|
// 如果是 课程 和 精品课程, 那么就不再重定向
|
||||||
apiManage.signUpBpmProjectNow(pid).then(res=>{
|
const needReload = paths.findIndex(e=> e === this.$route.path) === -1
|
||||||
this.projectDialogVisible = false;
|
if (needReload) this.$router.push({path: paths[0]})
|
||||||
})
|
|
||||||
},
|
|
||||||
//BPM项目:重新报名
|
|
||||||
signUpAgain(){
|
|
||||||
const pid = this.studentInfo.projectId;
|
|
||||||
const studentId=this.studentInfo.studentId;
|
|
||||||
const data = {"pid":pid,"studentId":studentId};
|
|
||||||
apiManage.signUpBpmProjectAgain(data).then(res=>{
|
|
||||||
this.projectDialogVisible = false;
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setCurIdentity(iden){
|
setCurIdentity(iden){
|
||||||
this.$store.dispatch('SetCurIdentity',iden);
|
this.$store.dispatch('SetCurIdentity',iden);
|
||||||
},
|
},
|
||||||
@@ -297,28 +261,6 @@ export default {
|
|||||||
if (val === "four") {
|
if (val === "four") {
|
||||||
window.open("https://m.qingxuetang.com/x/?appId=qxtcorp306130")
|
window.open("https://m.qingxuetang.com/x/?appId=qxtcorp306130")
|
||||||
// this.$emit('showClass',true)
|
// this.$emit('showClass',true)
|
||||||
} else if(val === "five"){//new社招新员工项目(需BPM审批报名--唯一,如果不唯一,取发布时间最新的)
|
|
||||||
let studentPath = process.env.VUE_APP_STUDENT_PATH;
|
|
||||||
apiManage.getNewSocialHireProject().then(res=>{
|
|
||||||
this.studentInfo = res.data;
|
|
||||||
const bpmStatus = this.studentInfo.bpmStatus;
|
|
||||||
if (bpmStatus == 0){//未报名--则弹窗含“立即报名”
|
|
||||||
this.studentInfo.bpmStatusName="未报名";
|
|
||||||
this.projectDialogVisible=true;
|
|
||||||
|
|
||||||
}else if (bpmStatus == 1){//已报名待审核(审批中)--仅弹窗展示
|
|
||||||
this.studentInfo.bpmStatusName="审批中";
|
|
||||||
this.projectDialogVisible=true;
|
|
||||||
|
|
||||||
}else if (bpmStatus == 2){//bpm报名审核通过,则直接进入项目进行学习
|
|
||||||
let params = encodeURIComponent('projectId=' + this.studentInfo.projectId);
|
|
||||||
this.$router.push('/forward?to=' + studentPath + '/projectdetails¶ms=' + params);
|
|
||||||
}else if(bpmStatus == 3){//已拒绝--则弹窗含“重新报名”
|
|
||||||
this.studentInfo.bpmStatusName="已拒绝(含个人撤回)";
|
|
||||||
this.projectDialogVisible=true;
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
let urlPre = window.location.protocol + "//" + window.location.host;
|
let urlPre = window.location.protocol + "//" + window.location.host;
|
||||||
// process.env.VUE_APP_BOE_WEB_URL
|
// process.env.VUE_APP_BOE_WEB_URL
|
||||||
@@ -328,7 +270,7 @@ export default {
|
|||||||
two: urlPre + "/grow180/login",
|
two: urlPre + "/grow180/login",
|
||||||
three: this.webBaseUrl + "/study/index?study=1",
|
three: this.webBaseUrl + "/study/index?study=1",
|
||||||
// four: 'https://m.qingxuetang.com/x/?appId=qxtcorp306130',
|
// four: 'https://m.qingxuetang.com/x/?appId=qxtcorp306130',
|
||||||
// five: urlPre + "/boe/new-employee/index.html", //old社招新员工 zhengsongbo 注释掉 2025-07-14
|
five: urlPre + "/boe/new-employee/index.html",
|
||||||
six: urlPre + "/web/contributor/index",
|
six: urlPre + "/web/contributor/index",
|
||||||
seven: this.webBaseUrl + '/grateful/index'
|
seven: this.webBaseUrl + '/grateful/index'
|
||||||
};
|
};
|
||||||
@@ -662,27 +604,4 @@ text-align: center;
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
/* 项目简介 弹窗 ---start--- */
|
|
||||||
::v-deep .el-dialog__header {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
::v-deep .el-dialog {
|
|
||||||
border-radius: 3% 3% 1% 1%;
|
|
||||||
}
|
|
||||||
.el-dialog__header {
|
|
||||||
height: 100px;
|
|
||||||
margin: 0 !important;
|
|
||||||
background-image: url('../assets/images/project/title-bg.png');
|
|
||||||
background-size: 100% 100%; /* 完全填充 */
|
|
||||||
display: block; /* 避免行内元素空隙 */
|
|
||||||
}
|
|
||||||
::v-deep .el-dialog__title {
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
::v-deep .el-dialog__body {
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
/* 项目简介 弹窗 ---end--- */
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -119,7 +119,35 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="player-time">{{ currentTimeFormat }} / {{ fullTimeFormat }}</div>
|
<div class="player-time">{{ currentTimeFormat }} / {{ fullTimeFormat }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ai播放器相关 -->
|
||||||
<div class="player-controls-bottom-right">
|
<div class="player-controls-bottom-right">
|
||||||
|
<div v-if="isAiTranslate" class="player-controls-btn box-aiTranslate">
|
||||||
|
<div v-show="isSubtitle" class="player-controls-btn cursor-pointer btn-speed">
|
||||||
|
<span>{{!currentLang ? 'AI翻译' : currentLangLabel}}</span>
|
||||||
|
<div class="speed-control">
|
||||||
|
<ul class="speed-control-list">
|
||||||
|
<li
|
||||||
|
v-for="item in selectableLang"
|
||||||
|
:key="item.srclang"
|
||||||
|
@click="changeLang(item)"
|
||||||
|
:data-value="item.srclang"
|
||||||
|
class="one-line-ellipsis"
|
||||||
|
:title="item.label"
|
||||||
|
:class="{'current': currentLang === item.srclang}"
|
||||||
|
>{{ item.label }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="isSubtitle" style="margin-top: -3px;">|</div>
|
||||||
|
<div class="player-controls-btn" style="display: flex;gap: 0.3rem;align-items: center;">
|
||||||
|
<span>字幕</span>
|
||||||
|
<el-switch
|
||||||
|
@change="toggleSubtitle"
|
||||||
|
v-model="isSubtitle">
|
||||||
|
</el-switch>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: -3px;">|</div>
|
||||||
|
</div>
|
||||||
<div class="player-controls-btn cursor-pointer btn-speed">
|
<div class="player-controls-btn cursor-pointer btn-speed">
|
||||||
<span>{{currentSpeed === 1 ? '倍速' : `${currentSpeed}x`}}</span>
|
<span>{{currentSpeed === 1 ? '倍速' : `${currentSpeed}x`}}</span>
|
||||||
<div class="speed-control">
|
<div class="speed-control">
|
||||||
@@ -224,6 +252,7 @@
|
|||||||
import volumeBar from "@/components/VideoPlayer/volume-bar.vue";
|
import volumeBar from "@/components/VideoPlayer/volume-bar.vue";
|
||||||
import progressBar from "@/components/VideoPlayer/progress-bar.vue";
|
import progressBar from "@/components/VideoPlayer/progress-bar.vue";
|
||||||
import playerBarrageScreen from "@/components/VideoPlayer/player-barrage-screen.vue";
|
import playerBarrageScreen from "@/components/VideoPlayer/player-barrage-screen.vue";
|
||||||
|
import { mapGetters, mapMutations } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "barrage-videoplayer",
|
name: "barrage-videoplayer",
|
||||||
@@ -301,12 +330,24 @@ export default {
|
|||||||
fullTimeFormat: "00:00:00", // 视频总长度的文字
|
fullTimeFormat: "00:00:00", // 视频总长度的文字
|
||||||
barrageTimelineStart: 0, // 弹幕时间轴的起始时间点(手动调整进度条触发更新)
|
barrageTimelineStart: 0, // 弹幕时间轴的起始时间点(手动调整进度条触发更新)
|
||||||
isInit:false, // 是否初始化过
|
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() {
|
created() {
|
||||||
|
// ai播放器相关
|
||||||
|
this.SET_currentLang('');
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
console.log('---',this.isAiTranslate,this.courseInfo,'courseInfo');
|
||||||
this.videoDom = this.$refs.video;
|
this.videoDom = this.$refs.video;
|
||||||
this.videoDom.focus({preventScroll: true});
|
this.videoDom.focus({preventScroll: true});
|
||||||
let speedValue=localStorage.getItem('boe_video_speed');
|
let speedValue=localStorage.getItem('boe_video_speed');
|
||||||
@@ -317,7 +358,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setInterval(() => {
|
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){
|
if(!this.isDrag){
|
||||||
var time = localStorage.getItem('videoProgressData')
|
var time = localStorage.getItem('videoProgressData')
|
||||||
@@ -364,14 +406,15 @@ export default {
|
|||||||
}
|
}
|
||||||
// 根据视频的readyState判断下一帧是否已加载,并控制loading的显示
|
// 根据视频的readyState判断下一帧是否已加载,并控制loading的显示
|
||||||
this.isShowLoading = this.videoDom.readyState < 3;
|
this.isShowLoading = this.videoDom.readyState < 3;
|
||||||
// console.log("当前缓存:"+this.videoDom.readyState)
|
console.log("当前缓存:"+this.videoDom.readyState)
|
||||||
if (this.videoDom.readyState < 3){
|
if (this.videoDom.readyState < 3){
|
||||||
// console.log("详细信息",this.videoDom)
|
console.log("详细信息",this.videoDom)
|
||||||
// console.log("卡了",this.videoDom.readyState)
|
console.log("卡了",this.videoDom.readyState)
|
||||||
}
|
}
|
||||||
//if()
|
//if()
|
||||||
//console.log(this.videoDom.readyState,'this.videoDom.readyState');
|
//console.log(this.videoDom.readyState,'this.videoDom.readyState');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
// 视频dom监听器,用于控制鼠标的显示
|
// 视频dom监听器,用于控制鼠标的显示
|
||||||
this.videoDom.addEventListener("mousemove", () => {
|
this.videoDom.addEventListener("mousemove", () => {
|
||||||
this.isCursorStatic = false;
|
this.isCursorStatic = false;
|
||||||
@@ -411,6 +454,13 @@ export default {
|
|||||||
// });
|
// });
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// ai播放器相关
|
||||||
|
...mapMutations({
|
||||||
|
SET_currentLang: 'video/SET_currentLang',
|
||||||
|
SET_currentTime: 'video/SET_currentTime',
|
||||||
|
SET_selectableLang: 'video/SET_selectableLang',
|
||||||
|
SET_duration: 'video/SET_duration',
|
||||||
|
}),
|
||||||
//当视频由于需要缓冲下一帧而停止,解决一直计时的问题
|
//当视频由于需要缓冲下一帧而停止,解决一直计时的问题
|
||||||
onWaiting(){
|
onWaiting(){
|
||||||
console.log('触发了onWairing');
|
console.log('触发了onWairing');
|
||||||
@@ -624,6 +674,8 @@ export default {
|
|||||||
},
|
},
|
||||||
onAudioTimeUpdate() {
|
onAudioTimeUpdate() {
|
||||||
const currentTime = this.$refs.video.currentTime;
|
const currentTime = this.$refs.video.currentTime;
|
||||||
|
// ai播放器相关
|
||||||
|
this.SET_currentTime(currentTime)
|
||||||
this.$emit('onTimeUpdate', currentTime);
|
this.$emit('onTimeUpdate', currentTime);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -641,9 +693,77 @@ export default {
|
|||||||
this.$emit('onFullscreen',false);//全屏
|
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: {
|
watch: {
|
||||||
currentVolume: function () {
|
currentVolume: function () {
|
||||||
@@ -668,9 +788,37 @@ export default {
|
|||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
src: function () {
|
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.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;
|
color: #fff;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
.box-aiTranslate{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
}
|
||||||
@media (device-width: 100vw) {
|
@media (device-width: 100vw) {
|
||||||
.player-controls-btn .player-controls-icon {
|
.player-controls-btn .player-controls-icon {
|
||||||
/* height: 26px; */
|
/* height: 26px; */
|
||||||
@@ -918,4 +1072,22 @@ export default {
|
|||||||
height: 100px;
|
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; */
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -85,9 +85,10 @@ export default {
|
|||||||
if(current<0) current = 0;
|
if(current<0) current = 0;
|
||||||
var time = localStorage.getItem('videoProgressData');
|
var time = localStorage.getItem('videoProgressData');
|
||||||
var arr = time&&JSON.parse(time) || {}
|
var arr = time&&JSON.parse(time) || {}
|
||||||
console.log('down arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
//console.log('down arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
||||||
// 禁止拖动 true:禁止拖动,false:允许拖动
|
// 禁止拖动
|
||||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||||
|
|
||||||
this.$emit("updateProgress", current);
|
this.$emit("updateProgress", current);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ export default {
|
|||||||
if(current<0) current = 0;
|
if(current<0) current = 0;
|
||||||
var time = localStorage.getItem('videoProgressData');
|
var time = localStorage.getItem('videoProgressData');
|
||||||
var arr = time&&JSON.parse(time) || {}
|
var arr = time&&JSON.parse(time) || {}
|
||||||
console.log('move arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
//console.log('move arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
||||||
// 禁止拖动
|
// 禁止拖动
|
||||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||||
this.$emit("updateProgress", current);
|
this.$emit("updateProgress", current);
|
||||||
@@ -117,12 +118,12 @@ export default {
|
|||||||
if(current<0) current = 0;
|
if(current<0) current = 0;
|
||||||
var time = localStorage.getItem('videoProgressData');
|
var time = localStorage.getItem('videoProgressData');
|
||||||
var arr = time&&JSON.parse(time) || {}
|
var arr = time&&JSON.parse(time) || {}
|
||||||
console.log('up arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
//console.log('up arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
||||||
this.$emit("getMouseDownStatus", false);
|
this.$emit("getMouseDownStatus", false);
|
||||||
// 禁止拖动
|
// 禁止拖动
|
||||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||||
this.$emit("updateProgress", current);
|
this.$emit("updateProgress", current);
|
||||||
this.$emit("getMouseDownStatus", false);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ export const iframes=[
|
|||||||
{title:'嵌入测试', path:'/iframe/index',hidden:false,component:'portal/iframe'},
|
{title:'嵌入测试', path:'/iframe/index',hidden:false,component:'portal/iframe'},
|
||||||
{title:'课件管理', path:'/iframe/course/coursewares',hidden:false,component:'course/Courseware'},
|
{title:'课件管理', path:'/iframe/course/coursewares',hidden:false,component:'course/Courseware'},
|
||||||
{title:'课程管理', path:'/iframe/course/manages',hidden:false,component:'course/ManageList'},
|
{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/questions',hidden:false,component:'exam/Question'},
|
||||||
{title:'查看答卷', path:'/iframe/exam/viewanswer',hidden:false,component:'exam/viewAnswer'},
|
{title:'查看答卷', path:'/iframe/exam/viewanswer',hidden:false,component:'exam/viewAnswer'},
|
||||||
{title:'考试试卷管理', path:'/iframe/exam/papers',hidden:false,component:'exam/TestPaper'},
|
{title:'考试试卷管理', path:'/iframe/exam/papers',hidden:false,component:'exam/TestPaper'},
|
||||||
@@ -128,8 +130,7 @@ export const iframes=[
|
|||||||
{title:'查看受众', path:'/iframe/ugroup/view',hidden:false,component:'manage/AudienceView'},
|
{title:'查看受众', path:'/iframe/ugroup/view',hidden:false,component:'manage/AudienceView'},
|
||||||
{title:'问答管理', path:'/iframe/qa/manages',hidden:false,component:'qa/ManageList'},
|
{title:'问答管理', path:'/iframe/qa/manages',hidden:false,component:'qa/ManageList'},
|
||||||
{title:'待审核课程', path:'/iframe/course/noapproved',hidden:false,component:'examine/NotApproved'},
|
{title:'待审核课程', path:'/iframe/course/noapproved',hidden:false,component:'examine/NotApproved'},
|
||||||
{title:'已审核课程', path:'/iframe/course/reviewed',hidden:false,component:'examine/Reviewed'},
|
{title:'已审核课程', path:'/iframe/course/reviewed',hidden:false,component:'examine/Reviewed'}
|
||||||
{title:'标签管理', path:'/iframe/tag/manages',hidden:false,component:'tag/TagManageList'},
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import Vue from 'vue'
|
|||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
/* Layout */
|
/* Layout */
|
||||||
import Layout from '@/layout/index'
|
import Layout from '@/layout/index'
|
||||||
import LayoutPortal from '@/layout/portal'
|
|
||||||
import Grateful from '@/views/grateful'
|
import Grateful from '@/views/grateful'
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
@@ -362,7 +361,15 @@ export const constantRoutes = [{
|
|||||||
path: '/500',
|
path: '/500',
|
||||||
component: (resolve) => require(['@/views/error/500'], resolve),
|
component: (resolve) => require(['@/views/error/500'], resolve),
|
||||||
hidden: true
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/qualityCourse',
|
||||||
|
hidden: true,
|
||||||
|
component: (resolve) => require(['@/views/portal/course/qualityCourse'], resolve),
|
||||||
|
name: 'qualityCourse',
|
||||||
|
meta: {title: '精品课课程', keepAlive: true, icon: 'dashboard', noCache: true, affix: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
|
|||||||
@@ -29,6 +29,19 @@ router.beforeEach((to, from, next) => {
|
|||||||
// 在免登录白名单,直接进入
|
// 在免登录白名单,直接进入
|
||||||
next()
|
next()
|
||||||
}else{
|
}else{
|
||||||
|
// if (!store.getters.init) {
|
||||||
|
// store.commit('app/SET_INITDATA',true);
|
||||||
|
// let myRouters=routers();
|
||||||
|
// store.dispatch('GenerateRoutes',{routers:myRouters}).then(accessRoutes=>{
|
||||||
|
// console.log('accessRoutes::',accessRoutes)
|
||||||
|
// router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||||
|
// next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// to.meta.keepAlive = true
|
||||||
|
// next();
|
||||||
|
// }
|
||||||
|
// return;
|
||||||
if(getToken()){
|
if(getToken()){
|
||||||
if(to.path === '/login'){
|
if(to.path === '/login'){
|
||||||
// 如果是外部用户,把配置的路由跳转到个人中心
|
// 如果是外部用户,把配置的路由跳转到个人中心
|
||||||
|
|||||||
@@ -28,5 +28,12 @@ const getters = {
|
|||||||
studyTaskCount:state => state.user.studyTaskCount,
|
studyTaskCount:state => state.user.studyTaskCount,
|
||||||
praisesUnicom:state =>state.pdf.praisesUnicom,
|
praisesUnicom:state =>state.pdf.praisesUnicom,
|
||||||
favoritesUnicom:state =>state.pdf.favoritesUnicom,
|
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
|
export default getters
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import resOwner from './modules/resOwner'
|
|||||||
import majorType from './modules/majorType'
|
import majorType from './modules/majorType'
|
||||||
import orgDomain from './modules/orgDomain'
|
import orgDomain from './modules/orgDomain'
|
||||||
import pdf from './modules/pdf'
|
import pdf from './modules/pdf'
|
||||||
|
import video from './modules/video' // ai播放器相关
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
@@ -27,7 +28,8 @@ const store = new Vuex.Store({
|
|||||||
resOwner,
|
resOwner,
|
||||||
majorType,
|
majorType,
|
||||||
orgDomain,
|
orgDomain,
|
||||||
pdf
|
pdf,
|
||||||
|
video
|
||||||
},
|
},
|
||||||
getters
|
getters
|
||||||
})
|
})
|
||||||
|
|||||||
171
src/store/modules/video.js
Normal file
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
@@ -153,9 +153,85 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="xindex-content">
|
<div class="xindex-content">
|
||||||
|
|
||||||
<!-- 推荐课程 -->
|
<!-- 推荐课程 -->
|
||||||
<div class="modules xcontent2">
|
<div class="modules xcontent2">
|
||||||
|
<!-- <div class="xcontent2-main"> -->
|
||||||
|
<!--内容块-->
|
||||||
|
|
||||||
|
<!-- </div> -->
|
||||||
|
<!-- 精品课模块 -->
|
||||||
<div class="xcontent2-main">
|
<div class="xcontent2-main">
|
||||||
|
<div class="modules-title xindex-main" v-if="this.qusisityList.list.length > 0">
|
||||||
|
<!-- <span class="modules-text" style="color: #3D86F4;">精品课</span> -->
|
||||||
|
<span class="quyer-tag" style="margin-left: 0px;">
|
||||||
|
<!-- <img src="../assets/images/tutoring1.pn" alt=""> -->
|
||||||
|
<img class="modules-text" style="height: 28px;" src="../assets/images/course/courseTitle.png" alt="">
|
||||||
|
</span>
|
||||||
|
<span class="more">
|
||||||
|
<router-link to="/qualityCourse">查看更多>></router-link>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-for="(course, eIndex) in exquisiteList"
|
||||||
|
:key="'cc' + eIndex"
|
||||||
|
class="xindex-course courseBg"
|
||||||
|
style="position: relative;margin-top: 20px;"
|
||||||
|
>
|
||||||
|
<div style="position: absolute; right: 25px; bottom: 72px">
|
||||||
|
<interactBar
|
||||||
|
nodeWidth="20px"
|
||||||
|
:courseExclusive="true"
|
||||||
|
:type="1"
|
||||||
|
:data="course"
|
||||||
|
:comments="false"
|
||||||
|
:praises="false"
|
||||||
|
:shares="false"
|
||||||
|
:views="false"
|
||||||
|
>
|
||||||
|
</interactBar>
|
||||||
|
<!-- <svg-icon style="font-size: 32px;margin-top: -5px;" icon-class="collectedCourse"></svg-icon> -->
|
||||||
|
</div>
|
||||||
|
<a @click="toCourseDetail(course)">
|
||||||
|
<div class="xindex-course-image">
|
||||||
|
<course-image :course="course"></course-image>
|
||||||
|
<!-- <span v-if="course.type == 20 || 10" class="course-type"
|
||||||
|
>录播课</span
|
||||||
|
> -->
|
||||||
|
<img v-if="course.type == 20 || 10" src="../assets/images/course/courseTag.png" class="course-type" style="background: none;" alt="">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="width: 80%"
|
||||||
|
:title="course.courseName"
|
||||||
|
class="course-title portal-title-tow two-line-ellipsis"
|
||||||
|
>
|
||||||
|
{{ course.courseName }}
|
||||||
|
</div>
|
||||||
|
<div class="course-author">
|
||||||
|
<div class="course-author-left">
|
||||||
|
{{ course.authorInfo.name }}
|
||||||
|
|
||||||
|
<span class="study-num"
|
||||||
|
>{{ formatNum(course.studyNum) }}人学习</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex">
|
||||||
|
<div v-if="course.courseScore">
|
||||||
|
<span class="course-score-value" style="margin-left: 10px"
|
||||||
|
>{{ toScore(course.courseScore) }}分</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div v-else class="course-score-no">未评分</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!--内容块-->
|
<!--内容块-->
|
||||||
<div class="modules-title xindex-main">
|
<div class="modules-title xindex-main">
|
||||||
<span class="modules-text">推荐课程</span>
|
<span class="modules-text">推荐课程</span>
|
||||||
@@ -1137,6 +1213,9 @@ export default {
|
|||||||
orderType: 2,
|
orderType: 2,
|
||||||
list: [],
|
list: [],
|
||||||
},
|
},
|
||||||
|
qusisityList: {
|
||||||
|
list: [],
|
||||||
|
},
|
||||||
// 推荐课程
|
// 推荐课程
|
||||||
recommendedList:{
|
recommendedList:{
|
||||||
list: [],
|
list: [],
|
||||||
@@ -1164,6 +1243,7 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getCourseData(1);
|
this.getCourseData(1);
|
||||||
|
this.getEsqusiteList();
|
||||||
this.getRecommendList();
|
this.getRecommendList();
|
||||||
this.getPositive()
|
this.getPositive()
|
||||||
this.getCaseData();
|
this.getCaseData();
|
||||||
@@ -1227,6 +1307,10 @@ export default {
|
|||||||
courseComputedTwoList(){
|
courseComputedTwoList(){
|
||||||
return this.courseList.list.slice(3)
|
return this.courseList.list.slice(3)
|
||||||
},
|
},
|
||||||
|
// 精品课展示
|
||||||
|
exquisiteList() {
|
||||||
|
return this.qusisityList.list.slice(0,3)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getPositive() {
|
getPositive() {
|
||||||
@@ -1421,21 +1505,27 @@ export default {
|
|||||||
//二期调整,直接改成一个地址
|
//二期调整,直接改成一个地址
|
||||||
//return this.webBaseUrl + '/course/detail?id=' + item.id;
|
//return this.webBaseUrl + '/course/detail?id=' + item.id;
|
||||||
let $this = this;
|
let $this = this;
|
||||||
|
let cId = "";
|
||||||
|
if (item.id) {
|
||||||
|
cId = item.id;
|
||||||
|
} else {
|
||||||
|
cId = item.courseId;
|
||||||
|
}
|
||||||
if (item.type == 10) {
|
if (item.type == 10) {
|
||||||
//return this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
//return this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
||||||
//console.log("直接进入学习页面");
|
//console.log("直接进入学习页面");
|
||||||
this.$router.push("/course/studyindex?id=" + item.id);
|
this.$router.push("/course/studyindex?id=" + cId);
|
||||||
} else if (item.type == 20) {
|
} else if (item.type == 20) {
|
||||||
apiCourseStudy.hasSignup(item.id).then((rs) => {
|
apiCourseStudy.hasSignup(cId).then((rs) => {
|
||||||
if (rs.status == 200) {
|
if (rs.status == 200) {
|
||||||
//return $this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
//return $this.webBaseUrl + "/course/studyindex?id=" + cId;
|
||||||
this.$router.push("/course/studyindex?id=" + item.id);
|
this.$router.push("/course/studyindex?id=" + cId);
|
||||||
} else {
|
} else {
|
||||||
//return $this.webBaseUrl + "/course/detail?id=" + item.id;
|
//return $this.webBaseUrl + "/course/detail?id=" + cId;
|
||||||
this.$router.push("/course/detail?id=" + item.id);
|
this.$router.push("/course/detail?id=" + cId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//return $this.webBaseUrl + "/course/detail?id=" + item.id;
|
//return $this.webBaseUrl + "/course/detail?id=" + cId;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
orderTypeFilter(val) {
|
orderTypeFilter(val) {
|
||||||
@@ -1472,6 +1562,29 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
//精品课展示
|
||||||
|
getEsqusiteList(){
|
||||||
|
let course = {
|
||||||
|
aid: this.userInfo.aid,
|
||||||
|
}
|
||||||
|
apiIndex.qualitylist(course).then((res) => {
|
||||||
|
let courseIds = [];
|
||||||
|
res.data.result.forEach((item) => {
|
||||||
|
item.authorInfo = {
|
||||||
|
aid: "",
|
||||||
|
name: "",
|
||||||
|
orgInfo: "",
|
||||||
|
avatar: "",
|
||||||
|
code: "",
|
||||||
|
sex: null,
|
||||||
|
};
|
||||||
|
courseIds.push(item.courseId);
|
||||||
|
});
|
||||||
|
this.loadCouserTeacher(res.data.result, courseIds);
|
||||||
|
console.log(res.data.result,'--------------------------');
|
||||||
|
this.qusisityList.list = res.data.result;
|
||||||
|
})
|
||||||
|
},
|
||||||
getCourseData(pageIndex) {
|
getCourseData(pageIndex) {
|
||||||
this.isNext = false;
|
this.isNext = false;
|
||||||
let { orderType, num } = this.courseList;
|
let { orderType, num } = this.courseList;
|
||||||
@@ -1671,7 +1784,7 @@ export default {
|
|||||||
let userIds = [];
|
let userIds = [];
|
||||||
list.forEach((item, index) => {
|
list.forEach((item, index) => {
|
||||||
cres.result.some((courseTeahcer) => {
|
cres.result.some((courseTeahcer) => {
|
||||||
if (courseTeahcer.courseId == item.id) {
|
if (courseTeahcer.courseId == (item.id||item.courseId)) {
|
||||||
if (courseTeahcer.teacherIds) {
|
if (courseTeahcer.teacherIds) {
|
||||||
userIds.push(courseTeahcer.teacherIds[0]);
|
userIds.push(courseTeahcer.teacherIds[0]);
|
||||||
item.authorInfo.aid = courseTeahcer.teacherIds[0];
|
item.authorInfo.aid = courseTeahcer.teacherIds[0];
|
||||||
@@ -2661,6 +2774,7 @@ export default {
|
|||||||
// padding-bottom: 10px;
|
// padding-bottom: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
.course-author-left {
|
.course-author-left {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -3009,4 +3123,17 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.courseBg{
|
||||||
|
// width: 332px;
|
||||||
|
// height: 323px;
|
||||||
|
// background: url("../assets/images/course/courseBackground.png") no-repeat;
|
||||||
|
// background-size: 100% 100%; /* 或 use 'contain' */
|
||||||
|
// background-position: center;
|
||||||
|
// border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(135deg, #e6f7ff, #f0f8ff, #ffffff);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #d9edf7;
|
||||||
|
//overflow: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -289,8 +289,8 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
viewTopic(data) {
|
viewTopic(data) {
|
||||||
window.open(this.webBaseUrl+'/article/detail?id='+data.id , '_blank')
|
// window.open(this.webBaseUrl+'/article/detail?id='+data.id , '_blank')
|
||||||
// this.$router.push({path:'/article/detail',query:{id:data.id}})
|
this.$router.push({path:'/article/detail',query:{id:data.id}})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -697,8 +697,7 @@ export default {
|
|||||||
},
|
},
|
||||||
viewTopic(data) {
|
viewTopic(data) {
|
||||||
if (data.confidentialityLevel == '内部') {
|
if (data.confidentialityLevel == '内部') {
|
||||||
// this.$router.push({ path: '/case/detail', query: { id: data.id } })
|
this.$router.push({ path: '/case/detail', query: { id: data.id } })
|
||||||
window.open(this.webBaseUrl+'/case/detail?id='+data.id , '_blank')
|
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning("非内部密级案例不能查看");
|
this.$message.warning("非内部密级案例不能查看");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -483,8 +483,11 @@ export default {
|
|||||||
} else if (this.form.device2 === true) {
|
} else if (this.form.device2 === true) {
|
||||||
this.form.device = 2;
|
this.form.device = 2;
|
||||||
}
|
}
|
||||||
//时长,秒与分钟的转化
|
// 时长,秒与分钟的转化
|
||||||
//if(this.form.)
|
if (this.form.minute) {
|
||||||
|
this.form.duration = this.form.minute * 60;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { status,message} = await coueseFile.batchUpdate([this.form]);
|
const { status,message} = await coueseFile.batchUpdate([this.form]);
|
||||||
if (status === 200) {
|
if (status === 200) {
|
||||||
@@ -624,12 +627,8 @@ export default {
|
|||||||
// if(item.minute){
|
// if(item.minute){
|
||||||
// item.duration=parseFloat(item.minute)*60;
|
// item.duration=parseFloat(item.minute)*60;
|
||||||
// }
|
// }
|
||||||
// 视频文件才可以设置时长,其他类型直接赋值0
|
// 如果没有给一个默认值30分钟
|
||||||
if (item.fileType === 'mp4' || item.fileType === 'mp3') {
|
item.duration = item.minute ? parseFloat(item.minute) * 60 : 1800;
|
||||||
item.duration = item.minute ? parseFloat(item.minute) * 60 : 0;
|
|
||||||
} else {
|
|
||||||
item.duration = 0;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
coueseFile.batchUpdate(this.fileList).then(rs => {
|
coueseFile.batchUpdate(this.fileList).then(rs => {
|
||||||
|
|||||||
@@ -64,14 +64,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-row :gutter="20" style="margin-top:10px">
|
<el-row :gutter="20" style="margin-top:10px">
|
||||||
<el-col :span="4">
|
<!-- ai播放器相关 -->
|
||||||
|
<el-col :span="24">
|
||||||
<!-- <el-button icon="el-icon-folder" type="primary" size="small">导出</el-button> -->
|
<!-- <el-button icon="el-icon-folder" type="primary" size="small">导出</el-button> -->
|
||||||
<el-button class="Create-coures" type="primary" @click="addNewCourse()" icon="el-icon-plus">新建课程</el-button>
|
<el-button class="Create-coures" type="primary" @click="addNewCourse()" icon="el-icon-plus">新建课程</el-button>
|
||||||
|
<el-button type="primary" @click="setLanguage()" icon="el-icon-connection" :disabled="selectedCourses.length === 0">设置语种</el-button>
|
||||||
|
<el-button type="primary" @click="enableAI()" icon="el-icon-switch-button" :disabled="selectedCourses.length === 0">开启AI处理</el-button>
|
||||||
</el-col >
|
</el-col >
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-right:30px;">
|
<div style="margin-right:30px;">
|
||||||
<el-table style="margin:10px 32px 10px 22px;" :data="pageData" border stripe>
|
<!-- ai播放器相关 -->
|
||||||
|
<el-table style="margin:10px 32px 10px 22px;" :data="pageData" border stripe @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55"></el-table-column>
|
||||||
<el-table-column label="序号" type="index" width="50"></el-table-column>
|
<el-table-column label="序号" type="index" width="50"></el-table-column>
|
||||||
<el-table-column v-if="forChoose" label="选择" width="80">
|
<el-table-column v-if="forChoose" label="选择" width="80">
|
||||||
<template slot-scope="scope" v-if="scope.row.published">
|
<template slot-scope="scope" v-if="scope.row.published">
|
||||||
@@ -136,6 +141,8 @@
|
|||||||
<el-table-column label="操作" width="180px" fixed="right">
|
<el-table-column label="操作" width="180px" fixed="right">
|
||||||
<template slot-scope="scope" class="btn-gl">
|
<template slot-scope="scope" class="btn-gl">
|
||||||
<!-- 20240621 修改scope.row.isPermission = fasle 时不展示操作按钮-->
|
<!-- 20240621 修改scope.row.isPermission = fasle 时不展示操作按钮-->
|
||||||
|
<!-- ai播放器相关 -->
|
||||||
|
<el-button v-if="scope.row.isPermission && scope.row.status != 2" type="text" size="mini" @click="setAI(scope.row)">AI设置</el-button>
|
||||||
<el-button type="text" size="mini" v-if="scope.row.isPermission && scope.row.status == 5 && !scope.row.published" @click="releaseData(scope.row)">发布</el-button>
|
<el-button type="text" size="mini" v-if="scope.row.isPermission && scope.row.status == 5 && !scope.row.published" @click="releaseData(scope.row)">发布</el-button>
|
||||||
<el-button v-if="scope.row.isPermission && pageManage && scope.row.published" @click="showStudent(scope.row)" type="text" size="mini">学员</el-button>
|
<el-button v-if="scope.row.isPermission && pageManage && scope.row.published" @click="showStudent(scope.row)" type="text" size="mini">学员</el-button>
|
||||||
<el-button v-if="scope.row.isPermission && !forChoose && scope.row.published" @click="showManageStudy(scope.row)" type="text" size="mini">管理</el-button>
|
<el-button v-if="scope.row.isPermission && !forChoose && scope.row.published" @click="showManageStudy(scope.row)" type="text" size="mini">管理</el-button>
|
||||||
@@ -287,6 +294,236 @@
|
|||||||
<div>
|
<div>
|
||||||
<course-form ref="courseForm" @submitSuccess="searchData" @close="searchData"></course-form>
|
<course-form ref="courseForm" @submitSuccess="searchData" @close="searchData"></course-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- ai播放器相关 -->
|
||||||
|
<!-- 设置语种弹框 -->
|
||||||
|
<el-dialog
|
||||||
|
title="AI翻译"
|
||||||
|
:visible.sync="languageSetting.dlgShow"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<div style="margin-bottom: 20px;">
|
||||||
|
<div style="margin-bottom: 15px;">请选择课程所支持语种</div>
|
||||||
|
<el-select
|
||||||
|
v-model="languageSetting.languageCode"
|
||||||
|
multiple
|
||||||
|
placeholder="请选择语种"
|
||||||
|
style="width: 100%;"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="lang in selectAllLang"
|
||||||
|
:key="lang.srclang"
|
||||||
|
:label="lang.label"
|
||||||
|
:value="lang.srclang"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div style="color: #ff4d4f; font-size: 12px;">
|
||||||
|
注:仅支持对已开启AI处理的课程进行批量语种设置;所选的课程中有{{languageSetting.aiSetNoNum}}个未开启AI处理的课程,以上配置仅对{{languageSetting.aiSetNum}}个已开启AI处理的课程生效。
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="languageSetting.dlgShow = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmLanguageSetting">确认</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 开启AI处理弹框 -->
|
||||||
|
<el-dialog
|
||||||
|
title="开启AI处理"
|
||||||
|
:visible.sync="aiProcessSetting.dlgShow"
|
||||||
|
width="400px"
|
||||||
|
>
|
||||||
|
<div class="ai-process-dialog">
|
||||||
|
<!-- AI处理状态 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiSetTip" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
AI处理:
|
||||||
|
</span>
|
||||||
|
<span class="status-text">
|
||||||
|
{{ aiProcessSetting.aiSet === 1 ? '开启' : '关闭' }}
|
||||||
|
</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="aiProcessSetting.aiSet"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
></el-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-show="aiProcessSetting.aiSet === 1">
|
||||||
|
<!-- 是否生成AI摘要 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiAbstractTip" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
AI摘要:
|
||||||
|
</span>
|
||||||
|
<span class="status-text">
|
||||||
|
{{ aiProcessSetting.aiAbstract === 1 ? '开启' : '关闭' }}
|
||||||
|
</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="aiProcessSetting.aiAbstract"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 是否生成AI文稿 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiDraftTip" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
AI文稿:
|
||||||
|
</span>
|
||||||
|
<span class="status-text">
|
||||||
|
{{ aiProcessSetting.aiDraft === 1 ? '开启' : '关闭' }}
|
||||||
|
</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="aiProcessSetting.aiDraft"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 课程支持语种选择 -->
|
||||||
|
<div class="form-item" style="flex-flow: column;align-items: baseline;">
|
||||||
|
<span class="form-label">
|
||||||
|
<el-tooltip class="item" effect="dark" :content="aiTranslateTip" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
AI翻译语种:
|
||||||
|
</span>
|
||||||
|
<el-select
|
||||||
|
v-model="aiProcessSetting.languageCode"
|
||||||
|
multiple
|
||||||
|
style="width: 100%;"
|
||||||
|
placeholder="请选择语种"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="lang in selectAllLang"
|
||||||
|
:key="lang.srclang"
|
||||||
|
:label="lang.label"
|
||||||
|
:value="lang.srclang"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 提示信息 -->
|
||||||
|
<div class="tips">
|
||||||
|
<span>注:已跳过{{aiProcessSetting.aiSetNum}}个已开启AI处理的课程,仅更新剩余{{aiProcessSetting.aiSetNoNum}}个</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="aiProcessSetting.dlgShow = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmAiProcess">确认</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- AI设置弹框 -->
|
||||||
|
<el-dialog
|
||||||
|
title="AI设置"
|
||||||
|
:visible.sync="aiSetting.dlgShow"
|
||||||
|
width="500px"
|
||||||
|
>
|
||||||
|
<div class="ai-setting-dialog">
|
||||||
|
|
||||||
|
<!-- AI功能状态 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">
|
||||||
|
<el-tooltip class="item" effect="dark" content="是否将课程进行AI处理" placement="top">
|
||||||
|
<i class="el-icon-question"></i>
|
||||||
|
</el-tooltip>
|
||||||
|
AI功能状态:
|
||||||
|
</span>
|
||||||
|
<span class="status-text">
|
||||||
|
{{ aiSetting.aiSet === 1 ? '已开放' : '未开放' }}
|
||||||
|
</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="aiSetting.aiSet"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
></el-switch>
|
||||||
|
</div>
|
||||||
|
<div v-show="aiSetting.aiSet === 1">
|
||||||
|
<!-- AI摘要状态 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">AI摘要状态:</span>
|
||||||
|
<span :class="aiSetting.aiAbstract === 1 ? 'custom-putaway' : 'custom-takeout'">
|
||||||
|
{{ aiSetting.aiAbstract === 1 ? '已上架' : '已下架' }}
|
||||||
|
</span>
|
||||||
|
<div class="action-buttons">
|
||||||
|
<el-button type="text" @click="changeAIKey('aiAbstract')">
|
||||||
|
{{ aiSetting.aiAbstract === 1 ? '下架' : '上架' }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-show="false" type="text" >编辑</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- AI文稿状态 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">AI文稿状态:</span>
|
||||||
|
<span :class="aiSetting.aiDraft === 1 ? 'custom-putaway' : 'custom-takeout'">
|
||||||
|
{{ aiSetting.aiDraft === 1 ? '已上架' : '已下架' }}
|
||||||
|
</span>
|
||||||
|
<div class="action-buttons">
|
||||||
|
<el-button type="text" @click="changeAIKey('aiDraft')">
|
||||||
|
{{ aiSetting.aiDraft === 1 ? '下架' : '上架' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- AI翻译状态 -->
|
||||||
|
<div class="form-item">
|
||||||
|
<span class="form-label">AI翻译状态:</span>
|
||||||
|
<span :class="aiSetting.aiTranslate === 1 ? 'custom-putaway' : 'custom-takeout'">
|
||||||
|
{{ aiSetting.aiTranslate === 1 ? '已上架' : '已下架' }}
|
||||||
|
</span>
|
||||||
|
<div class="action-buttons">
|
||||||
|
<el-button type="text" @click="changeAIKey('aiTranslate')">
|
||||||
|
{{ aiSetting.aiTranslate === 1 ? '下架' : '上架' }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-show="false" type="text" >编辑</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 支持语种 -->
|
||||||
|
<div class="form-item" style="align-items: flex-start;">
|
||||||
|
<span class="form-label" style="white-space: nowrap;">支持语种:</span>
|
||||||
|
<div class="languages-list" v-show="false">
|
||||||
|
<div v-for="lang in aiSetting.languageCode" :key="lang" class="language-tag">
|
||||||
|
{{ getLanguageName(lang) }}
|
||||||
|
<span class="custom-takeout">已下架</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-select
|
||||||
|
v-model="aiSetting.languageCode"
|
||||||
|
multiple
|
||||||
|
style="width: 100%;"
|
||||||
|
placeholder="请选择语种"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="lang in selectAllLang"
|
||||||
|
:key="lang.srclang"
|
||||||
|
:label="lang.label"
|
||||||
|
:value="lang.srclang"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="aiSetting.dlgShow = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmAISetting">确认</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -299,7 +536,7 @@ import auditCourse2 from '@/components/Course/auditCourse2.vue';
|
|||||||
import adminPage from '@/components/Administration/adminPage.vue';
|
import adminPage from '@/components/Administration/adminPage.vue';
|
||||||
import apiResowner from '../../api/modules/resowner.js';
|
import apiResowner from '../../api/modules/resowner.js';
|
||||||
import apiType from '../../api/modules/type.js'
|
import apiType from '../../api/modules/type.js'
|
||||||
import {courseType} from '../../utils/tools.js';
|
import {courseType, deepCopy} from '../../utils/tools.js';
|
||||||
import apiCourse from '../../api/modules/course.js';
|
import apiCourse from '../../api/modules/course.js';
|
||||||
// import {resOwnerIndexName,sysTypeIndexName} from '@/utils/type.js';
|
// import {resOwnerIndexName,sysTypeIndexName} from '@/utils/type.js';
|
||||||
import { mapGetters,mapActions } from 'vuex';
|
import { mapGetters,mapActions } from 'vuex';
|
||||||
@@ -307,8 +544,9 @@ import apiUserbasic from "@/api/boe/userbasic.js"
|
|||||||
export default {
|
export default {
|
||||||
name: 'manageCourse',
|
name: 'manageCourse',
|
||||||
components: {courseForm, manager, auditCourse1, auditCourse2,adminPage},
|
components: {courseForm, manager, auditCourse1, auditCourse2,adminPage},
|
||||||
|
// ai播放器相关
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['resOwnerMap','sysTypeMap','userInfo']),
|
...mapGetters(['resOwnerMap','sysTypeMap','userInfo', 'selectAllLang']),
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -392,6 +630,32 @@ export default {
|
|||||||
},
|
},
|
||||||
extendRefId:'',
|
extendRefId:'',
|
||||||
extendRefType:'',
|
extendRefType:'',
|
||||||
|
// ai播放器相关
|
||||||
|
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() {
|
mounted() {
|
||||||
@@ -426,6 +690,7 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
getAudiences(){
|
getAudiences(){
|
||||||
apiUserbasic.getInAudienceIds().then(res=>{
|
apiUserbasic.getInAudienceIds().then(res=>{
|
||||||
if (res.status == 200) {
|
if (res.status == 200) {
|
||||||
@@ -449,6 +714,7 @@ export default {
|
|||||||
inputOn() {
|
inputOn() {
|
||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 置顶
|
// 置顶
|
||||||
setTop(row) {
|
setTop(row) {
|
||||||
let params = {
|
let params = {
|
||||||
@@ -885,6 +1151,140 @@ export default {
|
|||||||
saveNewCatalogZhang() {
|
saveNewCatalogZhang() {
|
||||||
this.catalogs.addNewZhang = false;
|
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);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -953,4 +1353,22 @@ export default {
|
|||||||
.el-dialog__body {
|
.el-dialog__body {
|
||||||
overflow: hidden;
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
245
src/views/course/aiSet/aiAbstract.vue
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
<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>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="ai-right">
|
||||||
|
<div class="right-title">
|
||||||
|
<h3>{{currentVideo.name}}</h3>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="status = 1">下架本课程AI摘要</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ai-content">
|
||||||
|
<div class="videoBox">
|
||||||
|
<videoPlayer :src="testUrl" style="height: auto;"> </videoPlayer>
|
||||||
|
<div class="video-content">
|
||||||
|
<h4>视频摘要</h4>
|
||||||
|
<p>
|
||||||
|
{{currentVideo.aiAbstract}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="videoOperation">
|
||||||
|
<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>
|
||||||
|
</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>
|
||||||
|
<el-input v-show="status == 4"
|
||||||
|
type="textarea"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
autosize
|
||||||
|
v-model="aiAbstract">
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import videoPlayer from "@/components/VideoPlayer/index.vue";
|
||||||
|
export default {
|
||||||
|
name: 'aiAbstract',
|
||||||
|
// ai播放器相关
|
||||||
|
components: {
|
||||||
|
videoPlayer
|
||||||
|
},
|
||||||
|
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',
|
||||||
|
currentVideo: {},
|
||||||
|
aiAbstract: '人工智能(AI)是让计算机模拟人类智能的技术,核心包括机器学习、深度学习等。主要分为弱 AI(专注特定任务)和强 AI(通用智能)两类。应用涵盖医疗诊断、自动驾驶、语音助手等多个领域。它通过数据学习模式,实现预测和适应能力,正在改变生活方式和工作方式。未来发展需平衡创新与伦理考量,确保对人类社会有益。',
|
||||||
|
status: '1', // 1: 正常 2: 生成中 3: 错误 4: 编辑中
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.currentVideo = this.videoList[0];
|
||||||
|
},
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.aiAbstract{
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
padding: 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 15px;
|
||||||
|
background: #f4f7fa;
|
||||||
|
.ai-left{
|
||||||
|
padding: 9px 10px;
|
||||||
|
width: 24%;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
.left-title{
|
||||||
|
background: rgba(239, 244, 252, 1);
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(75, 92, 118, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 23px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
}
|
||||||
|
.ai-list{
|
||||||
|
margin: 0;
|
||||||
|
.ai-item{
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(75, 92, 118, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 23px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
padding: 17px 31px;
|
||||||
|
border-bottom: 1px solid rgba(240, 240, 240, 1);
|
||||||
|
text-align: left;
|
||||||
|
&:hover{
|
||||||
|
background: rgba(240, 240, 240, 1);
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color: rgba(64, 158, 255, 1);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ai-right{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
.right-title{
|
||||||
|
display: flex;
|
||||||
|
padding: 0 28px;
|
||||||
|
height: 76px;
|
||||||
|
border-bottom: 1px solid rgba(229, 231, 235, 1);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
h3{
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 26px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ai-content{
|
||||||
|
flex: 1;
|
||||||
|
padding: 24px 30px;
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
|
||||||
|
.videoBox{
|
||||||
|
width: 55%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
.video-content{
|
||||||
|
flex: 1;
|
||||||
|
h4{
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 23px;
|
||||||
|
}
|
||||||
|
p{
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.videoOperation{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
.opera-title{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
h4{
|
||||||
|
margin: 0;
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 23px;
|
||||||
|
}
|
||||||
|
.opera-btn{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.opera-content{
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 7px;
|
||||||
|
background: rgba(249, 250, 251, 1);
|
||||||
|
padding: 15px;
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .el-textarea{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
::v-deep .el-textarea__inner{
|
||||||
|
height: 100%!important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
388
src/views/course/aiSet/aiTranslate.vue
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
<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>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="ai-right">
|
||||||
|
<div class="right-title">
|
||||||
|
<h3>{{currentVideo.name}}</h3>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="status = 1">下架本课程AI翻译</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ai-content">
|
||||||
|
<div class="videoBox">
|
||||||
|
<videoPlayer :src="testUrl" style="height: auto;"> </videoPlayer>
|
||||||
|
<div class="video-content">
|
||||||
|
<div class="select-lang">
|
||||||
|
<img src="@/assets/images/course/languageIcon.png" alt="" width="10" height="10">
|
||||||
|
<span>本课程支持语种:</span>
|
||||||
|
<el-button type="primary" @click="setLanguage()" icon="el-icon-connection">设置语种</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="lang-content">
|
||||||
|
<div class="lang-item" v-for="(item, index) in selectedLang" :key="index">
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
<span :class="item.aiTranslate == 1 ? 'custom-putaway' : 'custom-takeout'">{{ item.aiTranslate == 1 ? '已上架' : '已下架' }}</span>
|
||||||
|
<el-button type="text" @click="item.aiTranslate = item.aiTranslate == 1 ? 0 : 1">{{ item.aiTranslate == 1 ? '下架' : '上架' }}</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="videoOperation">
|
||||||
|
<div class="opera-title">
|
||||||
|
<span>目标语种</span>
|
||||||
|
<el-select v-model="value" placeholder="请选择目标语种" style="flex: 1;">
|
||||||
|
<el-option
|
||||||
|
v-for="item in selectAllLang"
|
||||||
|
:key="item.srclang"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.srclang"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-button type="primary" @click="status = 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>
|
||||||
|
<el-input v-show="status == 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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-dialog
|
||||||
|
title="确认同步更新吗"
|
||||||
|
:visible.sync="updateDialogVisible"
|
||||||
|
width="420px"
|
||||||
|
style="border-radius: 10px;"
|
||||||
|
center>
|
||||||
|
<p style="text-align: center;">系统将根据当前最新中文内容重新生成其他语种的翻译,您此前对翻译的修改将会丢失!</p>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="updateDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button style="margin-left: 60px;" type="primary" @click="updateDialogVisible = false">确认同步更新</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
title="AIf翻译"
|
||||||
|
:visible.sync="selectDialogVisible"
|
||||||
|
width="500px"
|
||||||
|
class="select-dialog">
|
||||||
|
<div class="select-dialog-content">
|
||||||
|
<p>请选择该课程所支持语种</p>
|
||||||
|
<el-select v-model="selectLang" placeholder="请选择目标语种" style="width: 100%;" multiple>
|
||||||
|
<el-option
|
||||||
|
v-for="item in selectAllLang"
|
||||||
|
:key="item.srclang"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.srclang"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="selectDialogVisible = false">取 消</el-button>
|
||||||
|
<el-button style="" type="primary" @click="selectDialogVisible = false">确 认</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import videoPlayer from "@/components/VideoPlayer/index.vue";
|
||||||
|
import { mapGetters } from 'vuex';
|
||||||
|
export default {
|
||||||
|
name: 'aiTranslate',
|
||||||
|
// ai播放器相关
|
||||||
|
components: {
|
||||||
|
videoPlayer
|
||||||
|
},
|
||||||
|
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: `
|
||||||
|
00:00:01/00:00:03
|
||||||
|
Hello everyone in the audience
|
||||||
|
|
||||||
|
00:00:03/00:00:05
|
||||||
|
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: 未选择语种
|
||||||
|
selectedLang: [
|
||||||
|
{
|
||||||
|
label: '英文',
|
||||||
|
srclang: 'en',
|
||||||
|
aiTranslate: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '中文',
|
||||||
|
srclang: 'zh',
|
||||||
|
aiTranslate: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '日文',
|
||||||
|
srclang: 'ja',
|
||||||
|
aiTranslate: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '韩文',
|
||||||
|
srclang: 'ko',
|
||||||
|
aiTranslate: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '法文',
|
||||||
|
srclang: 'fr',
|
||||||
|
aiTranslate: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
updateDialogVisible: false,
|
||||||
|
selectDialogVisible: false,
|
||||||
|
selectLang: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['selectAllLang']),
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.currentVideo = this.videoList[0];
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setLanguage(){
|
||||||
|
this.selectDialogVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.aiTranslate{
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
padding: 10px;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 15px;
|
||||||
|
background: #f4f7fa;
|
||||||
|
.ai-left{
|
||||||
|
padding: 9px 10px;
|
||||||
|
width: 24%;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
.left-title{
|
||||||
|
background: rgba(239, 244, 252, 1);
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(75, 92, 118, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 23px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
}
|
||||||
|
.ai-list{
|
||||||
|
margin: 0;
|
||||||
|
.ai-item{
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
color: rgba(75, 92, 118, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 23px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
padding: 17px 31px;
|
||||||
|
border-bottom: 1px solid rgba(240, 240, 240, 1);
|
||||||
|
text-align: left;
|
||||||
|
&:hover{
|
||||||
|
background: rgba(240, 240, 240, 1);
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color: rgba(64, 158, 255, 1);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ai-right{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
.right-title{
|
||||||
|
display: flex;
|
||||||
|
padding: 0 28px;
|
||||||
|
height: 76px;
|
||||||
|
border-bottom: 1px solid rgba(229, 231, 235, 1);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
h3{
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 26px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ai-content{
|
||||||
|
flex: 1;
|
||||||
|
padding: 24px 30px;
|
||||||
|
display: flex;
|
||||||
|
gap: 30px;
|
||||||
|
|
||||||
|
.videoBox{
|
||||||
|
width: 55%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24px;
|
||||||
|
.video-content{
|
||||||
|
flex: 1;
|
||||||
|
.select-lang{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
color: rgba(107, 114, 128, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 17px;
|
||||||
|
}
|
||||||
|
.lang-content{
|
||||||
|
display: flex;
|
||||||
|
margin-top: 25px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 25px 60px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
.lang-item{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
color: rgba(96, 98, 102, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.videoOperation{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
.opera-title{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
>span{
|
||||||
|
color: rgba(75, 92, 118, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.opera-content{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
.bg-gray{
|
||||||
|
border-radius: 7px;
|
||||||
|
background: rgba(249, 250, 251, 1);
|
||||||
|
height: 100%;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
.opera-btn{
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .el-textarea{
|
||||||
|
height: 100%!important;
|
||||||
|
}
|
||||||
|
::v-deep .el-textarea__inner{
|
||||||
|
height: 100%!important;
|
||||||
|
}
|
||||||
|
::v-deep .el-dialog {
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-dialog{
|
||||||
|
::v-deep .el-dialog__header{
|
||||||
|
border-bottom: 1px solid rgba(229, 231, 235, 1);
|
||||||
|
}
|
||||||
|
.select-dialog-content{
|
||||||
|
p{
|
||||||
|
color: rgba(17, 24, 39, 1);
|
||||||
|
font-family: Noto Sans SC;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
<!-- 当轮播图等于一张时 -->
|
<!-- 当轮播图等于一张时 -->
|
||||||
<swiper :options="swiperOptiontwo">
|
<swiper :options="swiperOptiontwo">
|
||||||
<swiper-slide style="margin: 0 auto" v-for="(item, idx) in resonimg" :key="'a' + idx"
|
<swiper-slide style="margin: 0 auto" v-for="(item, idx) in resonimg" :key="'a' + idx"
|
||||||
class="swiper-slide games pointer">
|
class="swiper-slide games pointer" >
|
||||||
<div class="bannbox" :style="{
|
<div class="bannbox" @click="handleCarouselClick(item)" :style="{
|
||||||
background: `url(${fileBaseUrl + item.image
|
background: `url(${fileBaseUrl + item.image
|
||||||
}) center center no-repeat`,
|
}) center center no-repeat`,
|
||||||
}"></div>
|
}"></div>
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
<div id="container" style="z-index: 99" v-else>
|
<div id="container" style="z-index: 99" v-else>
|
||||||
<swiper :options="swiperOption" ref="mySwiper" v-if="resonimg.length > 1">
|
<swiper :options="swiperOption" ref="mySwiper" v-if="resonimg.length > 1">
|
||||||
<swiper-slide style="margin: 0 auto" v-for="(item, idx) in resonimg" :key="'b' + idx"
|
<swiper-slide style="margin: 0 auto" v-for="(item, idx) in resonimg" :key="'b' + idx"
|
||||||
class="swiper-slide games pointer">
|
class="swiper-slide games pointer" >
|
||||||
<div class="bannbox" :style="{
|
<div class="bannbox" @click="handleCarouselClick(item)" :style="{
|
||||||
background: `url(${fileBaseUrl + item.image
|
background: `url(${fileBaseUrl + item.image
|
||||||
}) center center no-repeat`,
|
}) center center no-repeat`,
|
||||||
}"></div>
|
}"></div>
|
||||||
@@ -220,7 +220,7 @@ export default {
|
|||||||
autoplay: false,
|
autoplay: false,
|
||||||
// noSwiping: true,
|
// noSwiping: true,
|
||||||
},
|
},
|
||||||
resonimg: [],
|
// resonimg: [],
|
||||||
swiperOption: {
|
swiperOption: {
|
||||||
autoplay: {
|
autoplay: {
|
||||||
delay: 2000,
|
delay: 2000,
|
||||||
@@ -249,6 +249,13 @@ export default {
|
|||||||
this.getToolData()
|
this.getToolData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 添加点击轮播图跳转的方法
|
||||||
|
handleCarouselClick(item) {
|
||||||
|
if (item.url) {
|
||||||
|
window.open(item.url, '_blank');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
downTool(toolInfo) {
|
downTool(toolInfo) {
|
||||||
console.log(toolInfo);
|
console.log(toolInfo);
|
||||||
window.open(`/activityApi/xboe/m/boe/tools/url/download?urlStr=${process.env.VUE_APP_BOE_WEB_URL}/upload${toolInfo.filePath}&fileName=${toolInfo.name}`)
|
window.open(`/activityApi/xboe/m/boe/tools/url/download?urlStr=${process.env.VUE_APP_BOE_WEB_URL}/upload${toolInfo.filePath}&fileName=${toolInfo.name}`)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<div class="navTop">
|
<div class="navTop">
|
||||||
<div>
|
<div>
|
||||||
<router-link to="/grateful" class="nav">首页</router-link> >
|
<router-link to="/grateful" class="nav">首页</router-link> >
|
||||||
<span style="cursor: pointer;" class="nav">认证讲师库(2023)</span>
|
<span style="cursor: pointer;" class="nav">认证讲师库</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="position: relative;">
|
<div style="position: relative;">
|
||||||
<el-input class="portal-input" placeholder="请输入课程名称" style="border-radius: 20px !important; "
|
<el-input class="portal-input" placeholder="请输入课程名称" style="border-radius: 20px !important; "
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
60ab8a4b97b446b2dcd32889
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<author :aid="caseDetail.sysCreateAid" :onlyAvatar="true" :avatar="authorInfo.avatar"
|
<author :aid="caseDetail.sysCreateAid" :onlyAvatar="true" :avatar="authorInfo.avatar"
|
||||||
:sex="authorInfo.sex"></author>
|
:sex="authorInfo.sex" :name="authorInfo.name"></author>
|
||||||
<span>案主:{{ authorInfo.name }} ({{ authorInfo.orgInfo }})</span>
|
<span>案主:{{ authorInfo.name }} ({{ authorInfo.orgInfo }})</span>
|
||||||
<!-- <span>案主:{{ authorInfo.name }}</span>
|
<!-- <span>案主:{{ authorInfo.name }}</span>
|
||||||
<span>工号:{{ authorInfo.code }}</span>
|
<span>工号:{{ authorInfo.code }}</span>
|
||||||
@@ -652,7 +652,7 @@ export default {
|
|||||||
},
|
},
|
||||||
getCaseData() {
|
getCaseData() {
|
||||||
// 清空pdf数据
|
// 清空pdf数据
|
||||||
// this.pdfPath = '';
|
this.pdfPath = '';
|
||||||
|
|
||||||
let $this = this;
|
let $this = this;
|
||||||
apiCase.details(this.resolveId, true).then(res => {
|
apiCase.details(this.resolveId, true).then(res => {
|
||||||
|
|||||||
@@ -196,7 +196,7 @@
|
|||||||
<div @click="toCaseDetail(item.id, item.refId)" style="cursor: pointer;">
|
<div @click="toCaseDetail(item.id, item.refId)" style="cursor: pointer;">
|
||||||
<div v-if="isTime" class="case_text">
|
<div v-if="isTime" class="case_text">
|
||||||
<span style="margin-right:28px">阅读了案例</span>
|
<span style="margin-right:28px">阅读了案例</span>
|
||||||
<span>{{ formatDateTime(item.eventTime) }}</span>
|
<span>{{ item.eventTime }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="case-info-title">
|
<div class="case-info-title">
|
||||||
<div class="case-titdiv">
|
<div class="case-titdiv">
|
||||||
@@ -664,12 +664,6 @@ export default {
|
|||||||
return !this.speciData.some(item => item.fielclass);
|
return !this.speciData.some(item => item.fielclass);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formatDateTime(dateArray) {
|
|
||||||
if (!dateArray || dateArray.length !== 6) return '';
|
|
||||||
const [year, month, day, hour, minute, second] = dateArray;
|
|
||||||
const pad = (num) => num.toString().padStart(2, '0');
|
|
||||||
return `${year}-${pad(month)}-${pad(day)} ${pad(hour)}:${pad(minute)}:${pad(second)}`;
|
|
||||||
},
|
|
||||||
beforeRouteLeave (to, from, next) {
|
beforeRouteLeave (to, from, next) {
|
||||||
const isScroll = 'caseDetail,caseCharts,caseExcellent'
|
const isScroll = 'caseDetail,caseCharts,caseExcellent'
|
||||||
if(!isScroll.includes(to.name)){
|
if(!isScroll.includes(to.name)){
|
||||||
@@ -1513,7 +1507,7 @@ export default {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
res.result.list.forEach(item=>{
|
res.result.list.forEach(item=>{
|
||||||
item.viewRankTags = (item.viewRankTags||[]).slice(0,2)||[]
|
item.viewRankTags = item.viewRankTags?.slice(0,2)||[]
|
||||||
})
|
})
|
||||||
this.caseList.list = res.result.list
|
this.caseList.list = res.result.list
|
||||||
this.getCaseUserData(res.result.list);
|
this.getCaseUserData(res.result.list);
|
||||||
@@ -1568,7 +1562,7 @@ export default {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
res.result.list.forEach(item=>{
|
res.result.list.forEach(item=>{
|
||||||
item.viewRankTags = (item.viewRankTags||[]).slice(0,2)||[]
|
item.viewRankTags = item.viewRankTags?.slice(0,2)||[]
|
||||||
})
|
})
|
||||||
this.caseList.list = res.result.list
|
this.caseList.list = res.result.list
|
||||||
this.getCaseUserData(res.result.list);
|
this.getCaseUserData(res.result.list);
|
||||||
@@ -1611,11 +1605,11 @@ export default {
|
|||||||
}
|
}
|
||||||
console.log(res?.result?.list ,'有没有数据1');
|
console.log(res?.result?.list ,'有没有数据1');
|
||||||
res.result.list.forEach(item=>{
|
res.result.list.forEach(item=>{
|
||||||
item.viewRankTags = (item.viewRankTags||[]).slice(0,2)||[]
|
item.viewRankTags = item.viewRankTags?.slice(0,2)||[]
|
||||||
})
|
})
|
||||||
console.log(res?.result?.list ,'有没有数据2');
|
console.log(res?.result?.list ,'有没有数据2');
|
||||||
this.caseList.list = res.result.list
|
this.caseList.list = res.result.list
|
||||||
// this.getCaseUserData(res.result.list);
|
this.getCaseUserData(res.result.list);
|
||||||
// 给所有的赋值
|
// 给所有的赋值
|
||||||
this.caseList.count = res.result.count;
|
this.caseList.count = res.result.count;
|
||||||
this.caseList.showPagCount = res.result.count;
|
this.caseList.showPagCount = res.result.count;
|
||||||
|
|||||||
@@ -284,40 +284,32 @@
|
|||||||
<!-- 内容导航 -->
|
<!-- 内容导航 -->
|
||||||
<div class="topNav" v-if="!newData">
|
<div class="topNav" v-if="!newData">
|
||||||
<div class="search-div nav" style="height: 100px;flex: 1;">
|
<div class="search-div nav" style="height: 100px;flex: 1;">
|
||||||
<div @click="handleTypeAllClick(1)" class="option-item" style="font-weight: bold" :class="{ 'option-active': ctypeTagAll }">
|
<div @click="handleTypeAllClick(1)" class="option-item" :class="{ 'option-active': ctypeTagAll }">
|
||||||
<a>全部</a>
|
<a>全部</a>
|
||||||
<span :class="ctypeTagAll ? 'nav-bottbor' : ''"></span>
|
<span :class="ctypeTagAll ? 'nav-bottbor' : ''"></span>
|
||||||
</div>
|
</div>
|
||||||
<div @click="handleTypeClick(ctypeList[0], ctypeList)" class="option-item" style="font-weight: bold"
|
<div @click="handleTypeClick(ctypeList[0], ctypeList)" class="option-item"
|
||||||
:class="{ 'option-active': ctypeList[0].checked }">
|
:class="{ 'option-active': ctypeList[0].checked }">
|
||||||
<a>录播课</a>
|
<a>录播课</a>
|
||||||
<span :class="ctypeList[0].checked ? 'nav-bottbor' : ''"></span>
|
<span :class="ctypeList[0].checked ? 'nav-bottbor' : ''"></span>
|
||||||
</div>
|
</div>
|
||||||
<div @click="handleTypeClick(ctypeList[1], ctypeList)" class="option-item" style="font-weight: bold"
|
<div @click="handleTypeClick(ctypeList[1], ctypeList)" class="option-item"
|
||||||
:class="{ 'option-active': ctypeList[1].checked }">
|
:class="{ 'option-active': ctypeList[1].checked }">
|
||||||
<a>线下课</a>
|
<a>线下课</a>
|
||||||
<span :class="ctypeList[1].checked ? 'nav-bottbor' : ''"></span>
|
<span :class="ctypeList[1].checked ? 'nav-bottbor' : ''"></span>
|
||||||
</div>
|
</div>
|
||||||
<div @click="handleTypeClick(ctypeList[2], ctypeList)" class="option-item" style="font-weight: bold"
|
<div @click="handleTypeClick(ctypeList[2], ctypeList)" class="option-item"
|
||||||
:class="{ 'option-active': ctypeList[2].checked }">
|
:class="{ 'option-active': ctypeList[2].checked }">
|
||||||
<a>学习项目</a>
|
<a>学习项目</a>
|
||||||
<span :class="ctypeList[2].checked ? 'nav-bottbor' : ''"></span>
|
<span :class="ctypeList[2].checked ? 'nav-bottbor' : ''"></span>
|
||||||
</div>
|
</div>
|
||||||
<a class="option-item">
|
<a class="option-item">
|
||||||
<span @click="uClassClick" class="Uxtext" style="font-weight: bold"> U选小课堂
|
<span @click="uClassClick" class="Uxtext" style=""> U选小课堂
|
||||||
<span class="uxicon">
|
<span class="uxicon">
|
||||||
<svg-icon icon-class="hot" style="font-size:22px"></svg-icon>
|
<svg-icon icon-class="hot" style="font-size:22px"></svg-icon>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<!-- 热点标签 add by zhengsongbo on 2025-08-01 -->
|
|
||||||
<div style="margin-top:10px;flex: 1;">
|
|
||||||
<div class="option-item" style="padding-top: 2px"
|
|
||||||
v-for="tag in hotTagsList" :key="tag.id"
|
|
||||||
@click="handleTagClick(tag, hotTagsList)">
|
|
||||||
<a class="custom" :class="tag.checked ? 'custom2' : ''">{{tag.name}}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="fixd-box" class="upload" style="margin-left: 26px;">
|
<div id="fixd-box" class="upload" style="margin-left: 26px;">
|
||||||
<div v-if="identity == 2 || identity == 3 || identity == 5">
|
<div v-if="identity == 2 || identity == 3 || identity == 5">
|
||||||
@@ -384,8 +376,25 @@
|
|||||||
<div class="couresstartTime">
|
<div class="couresstartTime">
|
||||||
<span v-if="cinfo.type == 30 && cinfo.startTime">开课时间:{{ cinfo.startTime }}</span>
|
<span v-if="cinfo.type == 30 && cinfo.startTime">开课时间:{{ cinfo.startTime }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ai播放器相关 -->
|
||||||
<div class="course-info">
|
<div class="course-info" style="align-items: center;">
|
||||||
|
<el-popover
|
||||||
|
placement="top-start"
|
||||||
|
:width="cinfo.summaryContent && cinfo.summaryContent.length > 200 ? '402' : '253'"
|
||||||
|
trigger="hover"
|
||||||
|
popper-class="course-popover"
|
||||||
|
>
|
||||||
|
<div class="course-popover-content">
|
||||||
|
<h4>课程摘要</h4>
|
||||||
|
<div v-if="cinfo.summaryContent" class="course-popover-content-text" >{{ cinfo.summaryContent }}</div>
|
||||||
|
<div v-else class="course-popover-noContent" >
|
||||||
|
<img src="../../../assets/images/course/noData.png" alt="">
|
||||||
|
<span>暂无数据</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <img slot="reference" src="../../../assets/images/course/courseAbstract.png" alt="摘要" style="width: 94px;height: 44px;margin-left: -10px;"> -->
|
||||||
|
<img v-show="cinfo.aiSet == 1 && cinfo.aiAbstract == 1" slot="reference" src="../../../assets/images/course/courseAbstract.png" alt="摘要" style="width: 94px;height: 44px;margin-left: -10px;">
|
||||||
|
</el-popover>
|
||||||
<div class="course-info-user" style="max-width: 100px;" v-if="cinfo.teacher">
|
<div class="course-info-user" style="max-width: 100px;" v-if="cinfo.teacher">
|
||||||
<el-tooltip :content="cinfo.teacher" placement="bottom" effect="light">
|
<el-tooltip :content="cinfo.teacher" placement="bottom" effect="light">
|
||||||
<span class="course-info-author">{{ cinfo.teacher }}</span>
|
<span class="course-info-author">{{ cinfo.teacher }}</span>
|
||||||
@@ -395,13 +404,13 @@
|
|||||||
<span class="course-info-studys">{{ formatNum(cinfo.studies) }}人学习</span>
|
<span class="course-info-studys">{{ formatNum(cinfo.studies) }}人学习</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="course-info-score">
|
<div class="course-info-score">
|
||||||
<div style="display: flex;">
|
<div style="display: flex; align-items: center;">
|
||||||
<interactBar :type="1" nodeWidth="20px" :data="cinfo" :courseExclusive="true" :comments="false"
|
<interactBar :type="1" nodeWidth="20px" :data="cinfo" :courseExclusive="true" :comments="false"
|
||||||
:praises="false" :shares="false" :views="false"></interactBar>
|
:praises="false" :shares="false" :views="false"></interactBar>
|
||||||
<div v-if="cinfo.score">
|
<div v-if="cinfo.score">
|
||||||
<span class="course-score-value">{{ toScore(cinfo.score) }}分</span>
|
<span class="course-score-value" style="white-space: nowrap;">{{ toScore(cinfo.score) }}分</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="course-score-no">未评分</div>
|
<div v-else class="course-score-no" style="white-space: nowrap;">未评分</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -494,32 +503,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- "新员工项目简介""弹框 -->
|
|
||||||
<el-dialog width="733px" title="项目简介" top="80px"
|
|
||||||
:visible.sync="projectDialogVisible"
|
|
||||||
class="custom-class">
|
|
||||||
<div slot="header" class="el-dialog__header">
|
|
||||||
</div>
|
|
||||||
<div style="height: 300px;margin: 20px 40px 0px 40px;">
|
|
||||||
<span v-html="studentInfo.introduction"></span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span style="margin: 40px; font-size: 14px" v-if="studentInfo.bpmStatus!=0">
|
|
||||||
审批编号:<span style="font-weight: bold;">{{studentInfo.bpmNumber}}</span>
|
|
||||||
</span>
|
|
||||||
<br/>
|
|
||||||
<span style="margin: 40px; font-size: 14px">
|
|
||||||
审批状态:<span v-html="studentInfo.bpmStatusName"></span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="signUpNow" v-if="studentInfo.bpmStatus==0">立即报名</el-button>
|
|
||||||
<el-button v-if="studentInfo.bpmStatus==1" disabled>审批中</el-button>
|
|
||||||
<el-button type="primary" @click="signUpAgain" v-if="studentInfo.bpmStatus==3">重新报名</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -541,14 +524,12 @@ import apiTeacher from "@/api/modules/teacher.js";
|
|||||||
import apiUser from "@/api/system/user.js";
|
import apiUser from "@/api/system/user.js";
|
||||||
import scene from "@/api/modules/scene.js";
|
import scene from "@/api/modules/scene.js";
|
||||||
import apiUserbasic from "@/api/boe/userbasic.js";
|
import apiUserbasic from "@/api/boe/userbasic.js";
|
||||||
import apiManage from '@/api/manage/manage.js';
|
|
||||||
import interactBar from "@/components/Portal/interactBar.vue";
|
import interactBar from "@/components/Portal/interactBar.vue";
|
||||||
import courseImage from "@/components/Course/courseImage.vue";
|
import courseImage from "@/components/Course/courseImage.vue";
|
||||||
import { courseType, getType, toScore, formatDate, formatUserNumber, formatDateByFmt } from "@/utils/tools.js";
|
import { courseType, getType, toScore, formatDate, formatUserNumber, formatDateByFmt } from "@/utils/tools.js";
|
||||||
import { deepClone, param } from "../../../utils";
|
import { deepClone, param } from "../../../utils";
|
||||||
import apiSearchterm from "@/api/modules/searchterm.js";
|
import apiSearchterm from "@/api/modules/searchterm.js";
|
||||||
import apiPlace from "@/api/phase2/place.js"
|
import apiPlace from "@/api/phase2/place.js"
|
||||||
import apiCourseTag from '@/api/modules/courseTag.js'
|
|
||||||
export default {
|
export default {
|
||||||
name: "index",
|
name: "index",
|
||||||
components: {
|
components: {
|
||||||
@@ -583,11 +564,6 @@ export default {
|
|||||||
list.push(item);
|
list.push(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.hotTagsList.forEach(item => {
|
|
||||||
if (item.checked) {
|
|
||||||
list.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.oneList.forEach(one => {
|
this.oneList.forEach(one => {
|
||||||
var twoChildChecked = false;//是否有下级
|
var twoChildChecked = false;//是否有下级
|
||||||
one.children.forEach(two => {
|
one.children.forEach(two => {
|
||||||
@@ -654,25 +630,12 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hotTagsList: [ //热点标签
|
|
||||||
{id:1,name:"数据库", checked: false },
|
|
||||||
{id:2,name:"Python", checked: false },
|
|
||||||
{id:3,name:"Java", checked: false },
|
|
||||||
{id:4,name:"Vue3.0", checked: false },
|
|
||||||
{id:5,name:"大数据", checked: false },
|
|
||||||
{id:6,name:"Bootstrap", checked: false },
|
|
||||||
{id:7,name:"营销学", checked: false },
|
|
||||||
{id:8,name:"芯片", checked: false },
|
|
||||||
{id:9,name:"火箭", checked: false },
|
|
||||||
{id:10,name:"感悟", checked: false }
|
|
||||||
],
|
|
||||||
newData: false,//线上品牌系列隐藏
|
newData: false,//线上品牌系列隐藏
|
||||||
navTitle: [],
|
navTitle: [],
|
||||||
// 设置高亮
|
// 设置高亮
|
||||||
twoId: '',
|
twoId: '',
|
||||||
count: 0,//分页总条条数
|
count: 0,//分页总条条数
|
||||||
showUClass: false,
|
showUClass: false,
|
||||||
projectDialogVisible: false,
|
|
||||||
ctypeList: [
|
ctypeList: [
|
||||||
{ type: 1, id: 20, name: '录播课', checked: false },
|
{ type: 1, id: 20, name: '录播课', checked: false },
|
||||||
{ type: 1, id: 30, name: '线下课', checked: false },
|
{ type: 1, id: 30, name: '线下课', checked: false },
|
||||||
@@ -683,7 +646,7 @@ export default {
|
|||||||
twoList: [], //二级分类{type:12}
|
twoList: [], //二级分类{type:12}
|
||||||
threeList: [],//三级分类{type:13}
|
threeList: [],//三级分类{type:13}
|
||||||
searching: false,//是否正在搜索中
|
searching: false,//是否正在搜索中
|
||||||
studentInfo: {},
|
|
||||||
resonimg: {},
|
resonimg: {},
|
||||||
formatDate,
|
formatDate,
|
||||||
formatNum: formatUserNumber,
|
formatNum: formatUserNumber,
|
||||||
@@ -741,14 +704,6 @@ export default {
|
|||||||
console.log(rs.message);
|
console.log(rs.message);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
//初始化:获取最新前10个热点标签
|
|
||||||
apiCourseTag.getHotTagList(null).then(rs => {
|
|
||||||
if (rs.status == 200) {
|
|
||||||
this.hotTagsList = rs.result;
|
|
||||||
} else {
|
|
||||||
console.log(rs.message);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let screenWidth = window.screen.availWidth;
|
let screenWidth = window.screen.availWidth;
|
||||||
@@ -831,24 +786,6 @@ export default {
|
|||||||
// window.removeEventListener("scroll", this.handleScroll);
|
// window.removeEventListener("scroll", this.handleScroll);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
//BPM项目:立即报名
|
|
||||||
signUpNow(){
|
|
||||||
const pid = this.studentInfo.projectId;
|
|
||||||
apiManage.signUpBpmProjectNow(pid).then(res=>{
|
|
||||||
this.projectDialogVisible = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
//BPM项目:重新报名
|
|
||||||
signUpAgain(){
|
|
||||||
const pid = this.studentInfo.projectId;
|
|
||||||
const studentId=this.studentInfo.studentId;
|
|
||||||
const data = {"pid":pid,"studentId":studentId};
|
|
||||||
apiManage.signUpBpmProjectAgain(data).then(res=>{
|
|
||||||
this.projectDialogVisible = false;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 改变分页
|
// 改变分页
|
||||||
currentChange(val) {
|
currentChange(val) {
|
||||||
this.course.pageIndex = val
|
this.course.pageIndex = val
|
||||||
@@ -979,9 +916,6 @@ export default {
|
|||||||
this.ctypeList.forEach(item => {
|
this.ctypeList.forEach(item => {
|
||||||
item.checked = false;
|
item.checked = false;
|
||||||
});
|
});
|
||||||
this.hotTagsList.forEach(item => {
|
|
||||||
item.checked = false;
|
|
||||||
});
|
|
||||||
this.oneList.forEach(one => {
|
this.oneList.forEach(one => {
|
||||||
one.checked = false;
|
one.checked = false;
|
||||||
one.children.forEach(two => {
|
one.children.forEach(two => {
|
||||||
@@ -1009,11 +943,6 @@ export default {
|
|||||||
|
|
||||||
this.searchData();
|
this.searchData();
|
||||||
},
|
},
|
||||||
//点击标签
|
|
||||||
handleTagClick(item, list) {
|
|
||||||
item.checked = !item.checked;
|
|
||||||
this.searchData();
|
|
||||||
},
|
|
||||||
//三级分类
|
//三级分类
|
||||||
handleOptionClick(item, level, list) {
|
handleOptionClick(item, level, list) {
|
||||||
// 线上品牌展示效果
|
// 线上品牌展示效果
|
||||||
@@ -1304,34 +1233,10 @@ export default {
|
|||||||
let params = encodeURIComponent('courseId=' + courseId);
|
let params = encodeURIComponent('courseId=' + courseId);
|
||||||
this.$router.push('/forward?to=' + manageApi + '/stu/project/redirectDetail¶ms=' + params);
|
this.$router.push('/forward?to=' + manageApi + '/stu/project/redirectDetail¶ms=' + params);
|
||||||
} else if (item.type == 40) { //学习项目
|
} else if (item.type == 40) { //学习项目
|
||||||
if (item.bpmFlag == 1) { //是否是需要BPM审批的项目(新员工转正项目)
|
|
||||||
//检查当前用户是否已经报名该项目(“未报名”、“审批中”和“审核拒绝”--则弹窗!--“立即报名”和“重新报名"调BPM接口)
|
|
||||||
apiManage.getStudntProjectInfo(courseId).then(res=>{
|
|
||||||
this.studentInfo = res.data;
|
|
||||||
const bpmStatus = this.studentInfo.bpmStatus;
|
|
||||||
if (bpmStatus == 0){//未报名--则弹窗含“立即报名”
|
|
||||||
this.projectDialogVisible=true;
|
|
||||||
this.studentInfo.bpmStatusName="<span style='color: #ddc507;font-weight: bold;'>未报名</span>";
|
|
||||||
|
|
||||||
}else if (bpmStatus == 1){//已报名待审核(审批中)--仅弹窗展示
|
|
||||||
this.projectDialogVisible=true;
|
|
||||||
this.studentInfo.bpmStatusName="<span style='color: #ddc507;font-weight: bold;'>审批中</span>";
|
|
||||||
|
|
||||||
}else if (bpmStatus == 2){//bpm报名审核通过,则直接进入项目进行学习
|
|
||||||
let params = encodeURIComponent('projectId=' + courseId);
|
|
||||||
this.$router.push('/forward?to=' + studentPath + '/projectdetails¶ms=' + params);
|
|
||||||
}else if(bpmStatus == 3){//已拒绝--则弹窗含“重新报名”
|
|
||||||
this.projectDialogVisible=true;
|
|
||||||
this.studentInfo.bpmStatusName="<span style='color: red;font-weight: bold;'>已拒绝(含个人撤回)</span>";
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else {
|
|
||||||
let params = encodeURIComponent('projectId=' + courseId);
|
let params = encodeURIComponent('projectId=' + courseId);
|
||||||
this.$router.push('/forward?to=' + studentPath + '/projectdetails¶ms=' + params);
|
this.$router.push('/forward?to=' + studentPath + '/projectdetails¶ms=' + params);
|
||||||
//this.$router.push('/forward?to='+manageApi+'/stu/project/redirectDetail¶ms='+params);
|
//this.$router.push('/forward?to='+manageApi+'/stu/project/redirectDetail¶ms='+params);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (item.type == 10) {
|
if (item.type == 10) {
|
||||||
//return this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
//return this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
||||||
@@ -1419,18 +1324,12 @@ export default {
|
|||||||
},
|
},
|
||||||
getAllChecked() { //获取全部选中的标签
|
getAllChecked() { //获取全部选中的标签
|
||||||
let list = [];
|
let list = [];
|
||||||
//获取选中的课程类型
|
|
||||||
this.ctypeList.forEach(item => {
|
this.ctypeList.forEach(item => {
|
||||||
if (item.checked) {
|
if (item.checked) {
|
||||||
list.push(item);
|
list.push(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//获取选中的热点标签
|
|
||||||
this.hotTagsList.forEach(item => {
|
|
||||||
if (item.checked) {
|
|
||||||
list.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.oneList.forEach(one => {
|
this.oneList.forEach(one => {
|
||||||
one.children.forEach(two => {
|
one.children.forEach(two => {
|
||||||
two.children.forEach(three => {
|
two.children.forEach(three => {
|
||||||
@@ -1535,7 +1434,7 @@ export default {
|
|||||||
item.name = item.name;
|
item.name = item.name;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log(res.result.list,'data')
|
console.log(res.result.list,'data')
|
||||||
this.courseList = res?.result?.list ?? []
|
this.courseList = res?.result?.list ?? []
|
||||||
console.log(this.courseList);
|
console.log(this.courseList);
|
||||||
if (this.newData) {
|
if (this.newData) {
|
||||||
@@ -2539,73 +2438,44 @@ export default {
|
|||||||
|
|
||||||
.option-active {
|
.option-active {
|
||||||
color: #387DF7;
|
color: #387DF7;
|
||||||
}
|
}</style>
|
||||||
/* 项目简介 方法一:外部 CSS 类 */
|
<!-- ai播放器相关 -->
|
||||||
::v-deep.el-dialog {
|
<style lang="scss">
|
||||||
border-radius: 3% 3% 1% 1%;
|
.course-popover{
|
||||||
padding: 0;
|
border-radius: 12px;
|
||||||
}
|
box-shadow: 0px 0px 16px 0px rgba(0, 0, 0, 0.12);
|
||||||
::v-deep.custom-class .el-dialog__header {
|
.course-popover-content{
|
||||||
height: 100px;
|
h4{
|
||||||
margin: 0 !important;
|
margin: 0 0 7px 0;
|
||||||
padding: 0 !important;
|
font-size: 14px;
|
||||||
background-image: url('../../../assets/images/project/title-bg.png');
|
font-weight: 500;
|
||||||
background-size: 100% 100%; /* 完全填充 */
|
line-height: 17px;
|
||||||
display: block; /* 避免行内元素空隙 */
|
letter-spacing: 0.3px;
|
||||||
}
|
color: rgba(0, 0, 0, 1);
|
||||||
::v-deep.custom-class .el-dialog__header .el-dialog__title {
|
}
|
||||||
padding: 0 !important;
|
.course-popover-content-text{
|
||||||
font-size: 35px;
|
font-size: 12px;
|
||||||
font-weight: bold;
|
font-weight: 400;
|
||||||
color: white;
|
|
||||||
margin: 60px;
|
|
||||||
line-height: 100px;
|
|
||||||
}
|
|
||||||
::v-deep.custom-class .el-dialog__body {
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
/* ---end--- */
|
|
||||||
/* ---标签管理 added by zhengsongbo on 2025-08-01--- */
|
|
||||||
.search-div.nav {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
.option-item {
|
|
||||||
margin: 0px 5px;
|
|
||||||
}
|
|
||||||
/* 热点标签:自定义按钮样式 */
|
|
||||||
a.custom {
|
|
||||||
/* 基础样式 */
|
|
||||||
display: inline-block; /* 使内边距生效 */
|
|
||||||
padding: 1px; /* 按钮内边距 */
|
|
||||||
margin: 1px 5px;
|
|
||||||
background-color: #F2F2F2; /* 淡灰色背景 */
|
|
||||||
color: #333; /* 文字颜色 */
|
|
||||||
text-decoration: none; /* 去除下划线 */
|
|
||||||
border-radius: 3px; /* 圆角设计 */
|
|
||||||
font-family: Arial, sans-serif; /* 字体 */
|
|
||||||
font-size: 14px; /* 文字大小 */
|
|
||||||
height: 24px;
|
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
/* 过渡效果,使颜色变化更平滑 */
|
letter-spacing: 0.26px;
|
||||||
transition: background-color 0.2s ease;
|
color: rgba(102, 102, 102, 1);
|
||||||
|
}
|
||||||
|
.course-popover-noContent{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
color: rgba(0, 0, 0, 0.34);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 14px;
|
||||||
|
letter-spacing: 0.26px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
img{
|
||||||
|
width: 96px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 鼠标悬停效果 */
|
|
||||||
a.custom:hover {
|
|
||||||
background-color: #DDEDFF; /* 浅蓝色背景 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 可选:点击时效果 */
|
|
||||||
a.custom:active {
|
|
||||||
background-color: #757575; /* 点击时更深的灰色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 鼠标悬停效果 */
|
|
||||||
a.custom2 {
|
|
||||||
background-color: #DDEDFF; /* 浅蓝色背景 */
|
|
||||||
}
|
|
||||||
/* ---end--- */
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -95,10 +95,7 @@
|
|||||||
<div v-if="coursewareInfo.content.contentType == 52">
|
<div v-if="coursewareInfo.content.contentType == 52">
|
||||||
<div class="hyper-link" v-if="conLink.openType==2">
|
<div class="hyper-link" v-if="conLink.openType==2">
|
||||||
<div class="hyper-link-row">课程内容是外部连接</div>
|
<div class="hyper-link-row">课程内容是外部连接</div>
|
||||||
<!-- <div class="hyper-link-row">{{conLink.url}}</div>-->
|
<div class="hyper-link-row">{{conLink.url}}</div>
|
||||||
<div class="hyper-link-row">
|
|
||||||
<el-button @click="widthOpen(conLink.url)" type="primary" style="margin-left: 15px">点击前往</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="conLink.openType==1">
|
<div v-if="conLink.openType==1">
|
||||||
<iframe :src="conLink.url" style="width: 100%;border:0px;min-height: 473px;border:0px" border="0" frameborder="0"></iframe>
|
<iframe :src="conLink.url" style="width: 100%;border:0px;min-height: 473px;border:0px" border="0" frameborder="0"></iframe>
|
||||||
|
|||||||
2254
src/views/portal/course/qualityCourse.vue
Normal file
@@ -48,8 +48,8 @@
|
|||||||
<div class="qa-info-summary portal-summary-text" :class="qa.images==''? 'two-line-ellipsis':'four-line-ellipsis'" @click="jumpDetail(qa)" v-html="$keywordActiveShow(qa.content,queryKeyWord)">
|
<div class="qa-info-summary portal-summary-text" :class="qa.images==''? 'two-line-ellipsis':'four-line-ellipsis'" @click="jumpDetail(qa)" v-html="$keywordActiveShow(qa.content,queryKeyWord)">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div style="cursor: pointer; text-align: right;cursor: pointer;" v-if="qa.images && qa.images!==''" @click="jumpDetail(qa)">
|
<div style="cursor: pointer; text-align: right;cursor: pointer;" v-if="qa.images!==''" @click="jumpDetail(qa)">
|
||||||
<img style="width: 156px;height: 105px;border-radius: 4px;margin-left: 18px;" :src="fileBaseUrl + qa.images" alt="图片貌似被外星人劫走了">
|
<img style="width: 156px;height: 105px;border-radius: 4px;margin-left: 18px;" :src="fileBaseUrl + qa.images" alt="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -349,7 +349,6 @@ export default {
|
|||||||
this.$message.success('删除成功');
|
this.$message.success('删除成功');
|
||||||
this.queryData.pageIndex = 1;
|
this.queryData.pageIndex = 1;
|
||||||
this.queryMessage(true);
|
this.queryMessage(true);
|
||||||
this.$store.dispatch('refrashMsg');
|
|
||||||
} else {
|
} else {
|
||||||
this.$message.error('删除失败' + res.message);
|
this.$message.error('删除失败' + res.message);
|
||||||
}
|
}
|
||||||
@@ -367,7 +366,6 @@ export default {
|
|||||||
this.$message.success('删除成功');
|
this.$message.success('删除成功');
|
||||||
this.queryData.pageIndex = 1;
|
this.queryData.pageIndex = 1;
|
||||||
this.queryMessage(true);
|
this.queryMessage(true);
|
||||||
this.$store.dispatch('refrashMsg');
|
|
||||||
} else {
|
} else {
|
||||||
this.$message.error('删除失败' + res.message);
|
this.$message.error('删除失败' + res.message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,8 +306,8 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
viewTopic(data) {
|
viewTopic(data) {
|
||||||
window.open(this.webBaseUrl+'/qa/answer?id='+data.id, '_blank');
|
// window.open(this.webBaseUrl+'/qa/answer?id='+data.id, '_blank');
|
||||||
// this.$router.push({path:'/qa/answer',query:{id:data.id}})
|
this.$router.push({path:'/qa/answer',query:{id:data.id}})
|
||||||
},
|
},
|
||||||
aduit(row) {
|
aduit(row) {
|
||||||
this.form={...row};
|
this.form={...row};
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ export default {
|
|||||||
headers:{token:getToken(),}
|
headers:{token:getToken(),}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
console.log('111',res.data.result)
|
console.log('111',res.data.result)
|
||||||
console.log('111 gx2',res.data.result)
|
|
||||||
// this.porcessData=response.data.data
|
// this.porcessData=response.data.data
|
||||||
this.porcessData.course=Math.floor(res.data.result.course.total === 0 ? 0: (res.data.result.course.completion/res.data.result.course.total)*100)
|
this.porcessData.course=Math.floor(res.data.result.course.total === 0 ? 0: (res.data.result.course.completion/res.data.result.course.total)*100)
|
||||||
this.porcessData.project=Math.floor(res.data.result.project.total === 0 ? 0: (res.data.result.project.completion/res.data.result.project.total)*100)
|
this.porcessData.project=Math.floor(res.data.result.project.total === 0 ? 0: (res.data.result.project.completion/res.data.result.project.total)*100)
|
||||||
|
|||||||
3118
src/views/study/coursenew_v1.vue
Normal file
@@ -1,372 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="u-page" style="padding-right:32px">
|
|
||||||
<div style="width: 100%; margin-left: 12px;padding: 2px 0px 10px 12px;background-color: white">
|
|
||||||
<el-form :inline="true" style="margin-left: 12px;" :model="pageData" class="demo-form-inline">
|
|
||||||
<el-form-item label="标签ID:" label-width="60px">
|
|
||||||
<el-input id="tag-id" placeholder="请输入标签ID" v-model="pageData.id" clearable />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="标签名称:" label-width="80px">
|
|
||||||
<el-input id="tag-id" placeholder="请输入标签名称" v-model="pageData.tagName" clearable />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="热点标签:" label-width="80px">
|
|
||||||
<el-select v-model="pageData.isHot" style="width: 120px;" clearable placeholder="请选择状态">
|
|
||||||
<el-option label="开启" value="true"></el-option>
|
|
||||||
<el-option label="关闭" value="false"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<el-button @click="getsearch" icon="el-icon-search" type="primary">查询</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
<div style="padding: 5px 0px 2px 12px;">
|
|
||||||
<el-checkbox label="前台公共显示"></el-checkbox>
|
|
||||||
<el-checkbox label="热点标签展示"></el-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="width: 100%; margin-left: 12px;padding: 2px 0px 10px 12px;background-color: white">
|
|
||||||
<el-table style="width: 96%; margin:2px 32px 10px 12px;" :data="pageData.list" border stripe
|
|
||||||
:header-cell-style="{ background: '#E9F0FF' }"
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
@sort-change="handleSortChange">
|
|
||||||
<el-table-column type="selection" width="80px"></el-table-column>
|
|
||||||
<el-table-column label="标签ID" width="200px" prop="id"></el-table-column>
|
|
||||||
<el-table-column label="标签名称" width="235px" prop="tagName"></el-table-column>
|
|
||||||
<el-table-column label="已关联课程" width="220px"
|
|
||||||
prop="useCount"
|
|
||||||
sortable="custom"
|
|
||||||
:sort-orders="['descending', 'ascending']"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
|
||||||
<a v-if="scope.row.useCount > 0"
|
|
||||||
@click="showCourseByTag(`${scope.row.id}`)"
|
|
||||||
style="font-weight:bold; color: #409EFF; text-decoration: underline;">
|
|
||||||
{{ scope.row.useCount }}
|
|
||||||
</a>
|
|
||||||
<span style="font-weight:bold; color: #409EFF; text-decoration: underline;" v-else>0</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="前台公共显示" width="220px" prop="isPublic">
|
|
||||||
<template #default="scope"><!-- 开关状态会直接修改 pageData.list 中的数据 -->
|
|
||||||
<el-switch
|
|
||||||
v-model="scope.row.isPublic"
|
|
||||||
:disabled="scope.row.isHot==1?true:false"
|
|
||||||
@change="handlePublicChange(scope.row)"
|
|
||||||
>
|
|
||||||
</el-switch>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="热点标签展示" width="220px" prop="isHot">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch
|
|
||||||
v-model="scope.row.isHot"
|
|
||||||
:disabled="scope.row.isPublic==0?true:false"
|
|
||||||
@change="handleHotChange(scope.row)"
|
|
||||||
>
|
|
||||||
</el-switch>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div v-if="pageData.list.length > 0" style="text-align: center;margin-top: 50px;">
|
|
||||||
<el-pagination
|
|
||||||
background
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
:current-page="pageData.pageIndex"
|
|
||||||
:page-sizes="[10, 20, 30, 40]"
|
|
||||||
:page-size="pageData.pageSize"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total"
|
|
||||||
></el-pagination>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 标签关联课程弹窗 -->
|
|
||||||
<el-dialog custom-class="g-dialog" title="关联课程"
|
|
||||||
width="850px" top="20px"
|
|
||||||
:visible.sync="dialogVisible"
|
|
||||||
:modal-append-to-body="true"
|
|
||||||
:append-to-body="true">
|
|
||||||
<div class="dialog-content-container">
|
|
||||||
<el-table
|
|
||||||
:data="pageData.list2"
|
|
||||||
border stripe style="width: 100%"
|
|
||||||
:header-cell-style="{ background: '#E9F0FF' }"
|
|
||||||
@sort-change="handleSortChange2">
|
|
||||||
<el-table-column label="序号" width="60px" align="center">
|
|
||||||
<template #default="scope">
|
|
||||||
{{ scope.$index + 1 }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="关联课程名称" width="200px" prop="courseName"></el-table-column>
|
|
||||||
<el-table-column label="关联课程ID" width="100px" prop="courseId"></el-table-column>
|
|
||||||
<el-table-column label="关联人" width="80px" prop="sysCreateBy"></el-table-column>
|
|
||||||
<el-table-column label="关联时间" width="110px" prop="sysCreateTime"
|
|
||||||
:formatter="dateFormat" sortable="custom"
|
|
||||||
:sort-orders="['descending', 'ascending']"></el-table-column>
|
|
||||||
<el-table-column label="本课程绑定的其他标签" width="200px" prop="otherTags"></el-table-column>
|
|
||||||
<el-table-column label="操作" width="60px">
|
|
||||||
<template #default="scope">
|
|
||||||
<a @click="unbindCurrentTag(scope.row)"
|
|
||||||
style="font-weight:bold; color: #409EFF;">
|
|
||||||
解绑
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div v-if="pageData.list2.length > 0" class="pagination-container">
|
|
||||||
<el-pagination
|
|
||||||
background
|
|
||||||
@size-change="handleSizeChange2"
|
|
||||||
@current-change="handleCurrentChange2"
|
|
||||||
:current-page="pageData.pageIndex2"
|
|
||||||
:page-sizes="[10, 20, 30, 40]"
|
|
||||||
:page-size="pageData.pageSize2"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total2">
|
|
||||||
</el-pagination>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import moment from 'moment';
|
|
||||||
import apiCourseTag from '@/api/modules/courseTag.js'
|
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
export default {
|
|
||||||
name: 'courseTagItems',
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['userInfo'])
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pageData: {
|
|
||||||
pageIndex: 1,
|
|
||||||
pageIndex2: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
pageSize2: 10,
|
|
||||||
list:[],
|
|
||||||
list2:[],
|
|
||||||
orderField: null,
|
|
||||||
orderAsc: null,
|
|
||||||
orderField2: null,
|
|
||||||
orderAsc2: null,
|
|
||||||
},
|
|
||||||
total: 0,
|
|
||||||
total2: 0,
|
|
||||||
dialogVisible: false,
|
|
||||||
tagId: null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getCourseTagList()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
//初始化:课程标签列表
|
|
||||||
getsearch(){
|
|
||||||
this.pageData.pageIndex = 1;
|
|
||||||
this.getCourseTagList()
|
|
||||||
},
|
|
||||||
|
|
||||||
//课程标签列表:排序
|
|
||||||
handleSortChange({ prop, order }) {
|
|
||||||
this.pageData.orderField = prop; // 当前排序字段
|
|
||||||
this.pageData.orderAsc = order === 'ascending'; // 排序方向
|
|
||||||
this.getCourseTagList(); // 重新获取数据
|
|
||||||
},
|
|
||||||
|
|
||||||
//TODO:课程标签列表:监听选中项变化(批量的设置标签公共显示|热点标签)
|
|
||||||
handleSelectionChange(selection) {
|
|
||||||
this.selectedRows = selection; // 更新选中的行数据
|
|
||||||
},
|
|
||||||
|
|
||||||
//课程标签列表:获取课程标签列表数据
|
|
||||||
getCourseTagList() {
|
|
||||||
const { pageIndex, pageSize, orderField, orderAsc } = this.pageData
|
|
||||||
let query = { pageIndex, pageSize, orderField, orderAsc}
|
|
||||||
//拼接查询条件
|
|
||||||
if (this.pageData.id) {
|
|
||||||
const { id } = this.pageData
|
|
||||||
query.id = id
|
|
||||||
}
|
|
||||||
if (this.pageData.tagName) {
|
|
||||||
const { tagName } = this.pageData
|
|
||||||
query.tagName = tagName
|
|
||||||
}
|
|
||||||
if (this.pageData.isHot) {
|
|
||||||
const { isHot } = this.pageData
|
|
||||||
query.isHot = isHot
|
|
||||||
}
|
|
||||||
apiCourseTag.portalPageList(query).then((res) => {
|
|
||||||
if (res.status == 200) {
|
|
||||||
this.total = res.result.count
|
|
||||||
this.pageData.list = res.result.list
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.$message.error('获取数据失败')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
//课程标签列表:改变标签的公共属性
|
|
||||||
async handlePublicChange(row) {
|
|
||||||
// 保存原始状态用于回滚
|
|
||||||
const originalStatus = row.isPublic;
|
|
||||||
try {
|
|
||||||
// 调用 API 更新状态
|
|
||||||
await apiCourseTag.changeTagPublic(row);
|
|
||||||
this.$message.success('更新成功');
|
|
||||||
} catch (error) {
|
|
||||||
// 发生错误时回滚状态
|
|
||||||
row.isPublic = originalStatus;
|
|
||||||
this.$message.error('更新失败:' + error.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//课程标签列表:改变标签的热点属性
|
|
||||||
async handleHotChange(row) {
|
|
||||||
const isPublic=row.isPublic;
|
|
||||||
// 保存原始状态用于回滚
|
|
||||||
const originalStatus = row.isHot;
|
|
||||||
try {
|
|
||||||
// 调用 API 更新状态
|
|
||||||
await apiCourseTag.changeTagHot(row);
|
|
||||||
this.$message.success('更新成功');
|
|
||||||
} catch (error) {
|
|
||||||
// 发生错误时回滚状态
|
|
||||||
row.isHot = originalStatus;
|
|
||||||
this.$message.error('更新失败:' + error.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//课程标签列表:改变条数的回调
|
|
||||||
handleSizeChange(value) {
|
|
||||||
this.pageData.pageIndex = 1;
|
|
||||||
this.pageData.pageSize = value;
|
|
||||||
this.getCourseTagList();
|
|
||||||
},
|
|
||||||
//课程标签列表:改变页数的回调
|
|
||||||
handleCurrentChange(value) {
|
|
||||||
this.pageData.pageIndex = value;
|
|
||||||
this.getCourseTagList();
|
|
||||||
},
|
|
||||||
|
|
||||||
//标签关联的所有课程弹出框:显示指定标签id关联的课程列表
|
|
||||||
showCourseByTag(tagId) {
|
|
||||||
this.tagId=tagId;
|
|
||||||
this.getCourseOfTagList(tagId);
|
|
||||||
this.dialogVisible=true;
|
|
||||||
},
|
|
||||||
|
|
||||||
//分页查询指定标签关联的所有课程
|
|
||||||
getCourseOfTagList(){
|
|
||||||
const { pageIndex2:pageIndex, pageSize2:pageSize, orderField2:orderField, orderAsc2:orderAsc } = this.pageData
|
|
||||||
let query = { pageIndex, pageSize, orderField, orderAsc }
|
|
||||||
//拼接查询条件
|
|
||||||
if (this.tagId) {
|
|
||||||
query.id = this.tagId
|
|
||||||
apiCourseTag.showCourseByTag(query).then((res) => {
|
|
||||||
if (res.status == 200) {
|
|
||||||
this.total2 = res.result.count
|
|
||||||
this.pageData.list2 = res.result.list
|
|
||||||
if (this.total2==0){
|
|
||||||
this.dialogVisible=false
|
|
||||||
this.getCourseTagList(); // 重新获取课程标签列表数据
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.$message.error('获取数据失败')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//标签关联课程列表:排序
|
|
||||||
handleSortChange2({ prop, order }) {
|
|
||||||
this.pageData.orderField2 = prop; // 当前排序字段
|
|
||||||
this.pageData.orderAsc2 = order === 'ascending'; // 排序方向
|
|
||||||
this.getCourseOfTagList(); // 重新获取数据
|
|
||||||
},
|
|
||||||
|
|
||||||
//标签关联的所有课程列表:改变条数的回调
|
|
||||||
handleSizeChange2(value) {
|
|
||||||
this.pageData.pageIndex2= 1;
|
|
||||||
this.pageData.pageSize2 = value;
|
|
||||||
this.getCourseOfTagList();
|
|
||||||
},
|
|
||||||
//标签关联的所有课程列表:改变页数的回调
|
|
||||||
handleCurrentChange2(value) {
|
|
||||||
this.pageData.pageIndex2 = value;
|
|
||||||
this.getCourseOfTagList();
|
|
||||||
},
|
|
||||||
//关联时间格式化
|
|
||||||
dateFormat(row, column) {
|
|
||||||
return row[column.property] ?
|
|
||||||
moment(row[column.property]).format('YYYY-MM-DD') : '';
|
|
||||||
},
|
|
||||||
|
|
||||||
//解除指定课程和当前标签的关联关系
|
|
||||||
unbindCurrentTag (row) {
|
|
||||||
let id = row.id;
|
|
||||||
let tagId = this.tagId;
|
|
||||||
let courseId = row.courseId;
|
|
||||||
//拼接查询条件
|
|
||||||
if (tagId && courseId) {
|
|
||||||
let params = { id, tagId, courseId }
|
|
||||||
apiCourseTag.unbindCourseTagRelation(params).then((res) => {
|
|
||||||
if (res.status == 200) {
|
|
||||||
//刷新列表
|
|
||||||
this.getCourseOfTagList(this.tagId);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.$message.error('解绑失败!')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.demo-form-inline {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 10px; /* 间距 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-form-inline .el-form-item {
|
|
||||||
margin-bottom: 0; /* 消除默认底部间距 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-content-container {
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination-container {
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-dialog .el-dialog__header {
|
|
||||||
background-color: #409EFF;
|
|
||||||
padding: 15px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-dialog .el-dialog__title {
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-dialog .el-dialog__headerbtn .el-dialog__close {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item command="total">累计</el-dropdown-item>
|
<el-dropdown-item command="total">累计</el-dropdown-item>
|
||||||
<el-dropdown-item command="now">当前年</el-dropdown-item>
|
<el-dropdown-item command="now">当前</el-dropdown-item>
|
||||||
<!-- <el-dropdown-item command="weeks">本周</el-dropdown-item>
|
<!-- <el-dropdown-item command="weeks">本周</el-dropdown-item>
|
||||||
<el-dropdown-item command="months">本月</el-dropdown-item>
|
<el-dropdown-item command="months">本月</el-dropdown-item>
|
||||||
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="myselftext">
|
<div class="myselftext">
|
||||||
<div class="myranking">
|
<div class="myranking">
|
||||||
{{isNow ? '当前年' : '累计'}}排名 : <span> {{currentUserRankingTotalData.rankNo}}</span>
|
{{isNow ? '当前' : '累计'}}排名 : <span> {{currentUserRankingTotalData.rankNo}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="myexperience">
|
<div class="myexperience">
|
||||||
{{isNow ? '当前年' : '累计'}}经验值 : <span>{{currentUserRankingTotalData.rankValue}}</span>
|
{{isNow ? '当前' : '累计'}}经验值 : <span>{{currentUserRankingTotalData.rankValue}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item command="total">累计</el-dropdown-item>
|
<el-dropdown-item command="total">累计</el-dropdown-item>
|
||||||
<el-dropdown-item command="now">当前年</el-dropdown-item>
|
<el-dropdown-item command="now">当前</el-dropdown-item>
|
||||||
<!-- <el-dropdown-item command="weeks">本周</el-dropdown-item>
|
<!-- <el-dropdown-item command="weeks">本周</el-dropdown-item>
|
||||||
<el-dropdown-item command="months">本月</el-dropdown-item>
|
<el-dropdown-item command="months">本月</el-dropdown-item>
|
||||||
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
||||||
@@ -127,10 +127,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="myselftext">
|
<div class="myselftext">
|
||||||
<div class="myranking">
|
<div class="myranking">
|
||||||
{{isStudyTime ? '当前年' : '累计'}}排名 : <span> {{learningDurationTotalData.rankNo}}</span>
|
{{isStudyTime ? '当前' : '累计'}}排名 : <span> {{learningDurationTotalData.rankNo}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="myexperience">
|
<div class="myexperience">
|
||||||
{{isStudyTime ? '当前年' : '累计'}}学习时长: <span> {{formatSecondToHour(learningDurationTotalData.rankValue)}}</span> h
|
{{isStudyTime ? '当前' : '累计'}}学习时长: <span> {{formatSecondToHour(learningDurationTotalData.rankValue)}}</span> h
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="exp-table" style="margin-top:20px;">
|
<div class="exp-table" style="margin-top:20px;">
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item command="total">累计</el-dropdown-item>
|
<el-dropdown-item command="total">累计</el-dropdown-item>
|
||||||
<el-dropdown-item command="now">当前年</el-dropdown-item>
|
<!-- <el-dropdown-item command="now">当前</el-dropdown-item> -->
|
||||||
<!-- <el-dropdown-item command="weeks">本周</el-dropdown-item>
|
<!-- <el-dropdown-item command="weeks">本周</el-dropdown-item>
|
||||||
<el-dropdown-item command="months">本月</el-dropdown-item>
|
<el-dropdown-item command="months">本月</el-dropdown-item>
|
||||||
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
||||||
@@ -216,10 +216,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="myselftext">
|
<div class="myselftext">
|
||||||
<div class="myranking">
|
<div class="myranking">
|
||||||
{{isStudyDay ? '当前年' : '累计'}}排名 : <span> {{learningDaysTotalData.rankNo}}</span>
|
{{isStudyDay ? '当前' : '累计'}}排名 : <span> {{learningDaysTotalData.rankNo}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="myexperience">
|
<div class="myexperience">
|
||||||
{{isStudyDay ? '当前年' : '累计'}}学习天数 : <span>{{learningDaysTotalData.rankValue}}</span>
|
{{isStudyDay ? '当前' : '累计'}}学习天数 : <span>{{learningDaysTotalData.rankValue}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="exp-table" style="margin-top:20px;">
|
<div class="exp-table" style="margin-top:20px;">
|
||||||
@@ -311,7 +311,7 @@ export default {
|
|||||||
formatSecondToHour:formatSecondToHour,
|
formatSecondToHour:formatSecondToHour,
|
||||||
experience:{
|
experience:{
|
||||||
field:'now',
|
field:'now',
|
||||||
name:'当前年',
|
name:'当前',
|
||||||
data:{
|
data:{
|
||||||
rankingNo:0,
|
rankingNo:0,
|
||||||
total:0
|
total:0
|
||||||
@@ -320,7 +320,7 @@ export default {
|
|||||||
},
|
},
|
||||||
learningDuration:{
|
learningDuration:{
|
||||||
field:'now',
|
field:'now',
|
||||||
name:'当前年',
|
name:'当前',
|
||||||
data:{
|
data:{
|
||||||
rankingNo:0,
|
rankingNo:0,
|
||||||
total:0
|
total:0
|
||||||
|
|||||||