Compare commits
124 Commits
20250708_a
...
20250922-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c630eac70 | ||
|
|
483b57f667 | ||
|
|
be411ec72d | ||
|
|
d7e425ce9d | ||
|
|
8b68489b25 | ||
|
|
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 | ||
|
|
44f79c93a5 | ||
|
|
e501b8d23f | ||
|
|
ea8143db2b | ||
|
|
89277f8868 | ||
|
|
13af8ba4e0 | ||
|
|
e3735e4b92 | ||
|
|
f4c9b921bb | ||
|
|
ed899cdd2c | ||
|
|
c24b54957a | ||
|
|
1dc9c941d7 | ||
|
|
33c9d2140f | ||
|
|
afd1bec458 | ||
|
|
202bf7b123 | ||
|
|
ce1d662350 | ||
|
|
81602506c7 | ||
|
|
053a2a60b2 | ||
|
|
b9f23eb657 | ||
|
|
ceeb3efcf5 | ||
|
|
147366f738 | ||
|
|
4ac09a8793 | ||
|
|
9c768337c6 | ||
|
|
e202946fe7 | ||
|
|
fbddf6806a | ||
|
|
3cfa3ffec3 | ||
|
|
a8bcd3832b | ||
|
|
d9f69001a5 | ||
|
|
93e769be42 | ||
|
|
206f0e825d | ||
|
|
3bb4b519f1 |
@@ -1 +0,0 @@
|
||||
60ab8a4b97b446b2dcd32889
|
||||
BIN
public/images/case-logo.png
Normal file
|
After Width: | Height: | Size: 438 KiB |
BIN
public/images/qualityBg.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
30
src/api/boe/aiChat.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import ajax from '@/utils/xajax.js'
|
||||
|
||||
/**
|
||||
* AI聊天对话接口
|
||||
* @param {Object} data - 请求参数
|
||||
* @param {string} data.conversationId - 会话ID,如果为空则创建新会话
|
||||
* @param {string} data.query - 用户提问内容
|
||||
* @returns {Promise} - 返回SSE流
|
||||
*/
|
||||
export function aiChat(data) {
|
||||
return ajax.postJson('http://192.168.3.178/xboe/m/boe/case/ai/chat', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会话消息记录接口
|
||||
* @param {string} conversationId - 会话ID
|
||||
* @returns {Promise} - 返回会话历史记录
|
||||
*/
|
||||
export function getChatMessages(conversationId) {
|
||||
return ajax.get('/xboe/m/boe/case/ai/messages?conversationId=' + conversationId)
|
||||
}
|
||||
|
||||
/**
|
||||
* 案例专家功能入口显示权限判断接口
|
||||
* 判断当前登录用户是否显示"案例专家"功能入口
|
||||
* @returns {Promise} - 返回是否显示功能入口的布尔值
|
||||
*/
|
||||
export function showCaseAiEntrance() {
|
||||
return ajax.get('/xboe/m/boe/case/ai/show-entrance')
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取学员指定新员工转正项目的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 {
|
||||
getTaskNum,
|
||||
userTaskList,
|
||||
userDeleteStudy,
|
||||
userRsSginupCourse,
|
||||
getStudntProjectInfo,
|
||||
signUpBpmProjectNow,
|
||||
signUpBpmProjectAgain,
|
||||
getNewSocialHireProject
|
||||
userRsSginupCourse
|
||||
}
|
||||
|
||||
@@ -170,7 +170,9 @@ const updateContentOrders = function(cid,items) {
|
||||
const detail = function(id) {
|
||||
return ajax.get('/xboe/m/course/manage/detail?id=' + id);
|
||||
}
|
||||
|
||||
const getDictIds = function(pid,type) {
|
||||
return ajax.get(`/xboe/m/course/manage/getDictIds?pid=${pid}&type=${type}`);
|
||||
}
|
||||
/**
|
||||
* 更新内容的名称
|
||||
* @param {Object} data
|
||||
@@ -446,6 +448,7 @@ export default {
|
||||
findUpdateLogs,
|
||||
getUpdateLog,
|
||||
detail,
|
||||
getDictIds,
|
||||
saveContent,
|
||||
pageList,
|
||||
setEnabled,
|
||||
|
||||
@@ -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 http from '../unionAjax'
|
||||
import httpAjax from '../httpAjax'
|
||||
|
||||
const baseURL = process.env.VUE_APP_MANAGER_API_PATH;
|
||||
|
||||
|
||||
@@ -47,6 +49,18 @@ const articlelist=function (type){
|
||||
const courselist=function (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,
|
||||
courselist,
|
||||
newCases,
|
||||
getRecommendList
|
||||
getRecommendList,
|
||||
qualitylist,
|
||||
qualityPageList
|
||||
}
|
||||
|
||||
BIN
src/assets/images/course/courseBackground.png
Normal file
|
After Width: | Height: | Size: 166 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: 34 KiB |
|
Before Width: | Height: | Size: 437 KiB |
|
Before Width: | Height: | Size: 42 KiB |
@@ -141,6 +141,7 @@
|
||||
<el-radio style="margin-right: 10px;" v-model="courseInfo.device" :label="1">PC端可见</el-radio>
|
||||
<el-radio style="margin-right: 10px;" v-model="courseInfo.device" :label="2">移动端可见</el-radio>
|
||||
<el-radio style="margin-right: 10px;" v-model="courseInfo.device" :label="3">多端可见</el-radio>
|
||||
<el-radio style="margin-right: 10px;" v-model="courseInfo.device" v-if="isPermission" :label="4">仅内网访问</el-radio>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="!weike.onlyRequired" label="课程来源">
|
||||
<el-radio-group v-model="courseInfo.source">
|
||||
@@ -253,9 +254,6 @@
|
||||
</el-select> -->
|
||||
<choice :teacherValue="teacherValues" @getTeacherList="getTeacherList"></choice>
|
||||
</el-form-item>
|
||||
<el-form-item label="标签" required>
|
||||
<courseTag ref="courseTag" :courseId="curCourseId" :sysTypeList="sysTypeList" :initialTags="courseTags" @change="handleTagsChange"></courseTag>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字">
|
||||
<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)">
|
||||
@@ -308,6 +306,7 @@
|
||||
<el-radio v-model="courseInfo.device" :label="1">PC端可见</el-radio>
|
||||
<el-radio v-model="courseInfo.device" :label="2">移动端可见</el-radio>
|
||||
<el-radio v-model="courseInfo.device" :label="3">多端可见</el-radio>
|
||||
<el-radio style="margin-right: 10px;" v-model="courseInfo.device" v-if="isPermission" :label="4">仅内网访问</el-radio>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="课程来源">
|
||||
@@ -405,7 +404,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import courseTag from "@/components/Course/courseTag.vue";
|
||||
import choice from '@/components/Course/choice.vue';
|
||||
import agreement from '@/components/Portal/agreement.vue';
|
||||
import weikeContent from '@/components/Course/weikeContent.vue';
|
||||
@@ -422,7 +420,6 @@ import apiCourse from '../../api/modules/course.js';
|
||||
import apiCourseAudit from '../../api/modules/courseAudit.js';
|
||||
import apiOrg from '../../api/system/organiza.js';
|
||||
import apiUser from '../../api/system/user.js';
|
||||
import apiCourseTag from '../../api/modules/courseTag.js';
|
||||
import WxEditor from '@/components/Editor/index.vue';
|
||||
import catalogSort from '@/components/Course/catalogSort.vue';
|
||||
import { courseType, getType } from '../../utils/tools.js';
|
||||
@@ -431,7 +428,7 @@ import filecloud from '@/components/FileCloud/index.vue';
|
||||
import chooseOrg from '@/components/System/chooseOrg.vue';
|
||||
export default {
|
||||
props: {},
|
||||
components: { courseTag, weikeContent, catalogCourseware, imageUpload, WxEditor, catalogSort,agreement,filecloud,choice,chooseOrg},
|
||||
components: { weikeContent, catalogCourseware, imageUpload, WxEditor, catalogSort,agreement,filecloud,choice,chooseOrg},
|
||||
data() {
|
||||
return {
|
||||
keywords:'',//关键字的定义
|
||||
@@ -471,7 +468,6 @@ export default {
|
||||
orgName:'',
|
||||
orgNamePath:'',
|
||||
orgKid:'',
|
||||
courseTags:[],
|
||||
courseInfo: {
|
||||
id: '',
|
||||
name: '',
|
||||
@@ -494,6 +490,8 @@ export default {
|
||||
refType:''
|
||||
},
|
||||
visibleShow:false,
|
||||
isPermission:false,
|
||||
dicts:[],
|
||||
extendRefId:'',
|
||||
extendRefType:'',
|
||||
courseTeachers: [], //课程的老师
|
||||
@@ -533,7 +531,11 @@ export default {
|
||||
dlgShow: false
|
||||
},
|
||||
rightTypeId: {},
|
||||
catalogSortDialogShow: false
|
||||
catalogSortDialogShow: false,
|
||||
selectedOrg: {
|
||||
orgId: null,
|
||||
name: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@@ -558,14 +560,18 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
courseInfo: {
|
||||
handler(newVal) {
|
||||
handler(newVal, oldVal) {
|
||||
// 需要保存
|
||||
this.requireSaveCourse = true;
|
||||
|
||||
console.log("--- watch比较 = ", oldVal.orgId, newVal.orgId);
|
||||
this.checkOrgPermission(newVal.orgId);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getDictIds();
|
||||
let extendFlag=this.$route.query.f; //是否是管理端过来的
|
||||
this.extendRefId=this.$route.query.refId;
|
||||
this.extendRefType=this.$route.query.refType;
|
||||
@@ -587,6 +593,19 @@ export default {
|
||||
this.loadUserGroup();
|
||||
},
|
||||
methods: {
|
||||
// 检查机构权限
|
||||
checkOrgPermission(orgId) {
|
||||
console.log("--- 监测组织id orgId = ",orgId)
|
||||
console.log("--- this.isPermission = ",this.isPermission)
|
||||
console.log("--- device = ",this.courseInfo.device)
|
||||
if (!orgId) {
|
||||
this.isPermission = false;
|
||||
return;
|
||||
}
|
||||
console.log("--- this.dicts = ",this.dicts)
|
||||
this.isPermission = this.dicts.includes(orgId);
|
||||
console.log("--- 监听结束 this.isPermission = ",this.isPermission)
|
||||
},
|
||||
// 关键字的更改
|
||||
changeKeywords(option){
|
||||
if(option.target.value){
|
||||
@@ -598,15 +617,6 @@ export default {
|
||||
closeKeywordsTag(item,index){
|
||||
this.tips.splice(index, 1);
|
||||
},
|
||||
// 处理标签变化事件
|
||||
handleTagsChange(tags) {
|
||||
console.log("父组件:",tags)
|
||||
let ids = "";
|
||||
tags.forEach(tag=>{
|
||||
ids += tag.id + ',';
|
||||
})
|
||||
this.courseInfo.tags = ids;
|
||||
},
|
||||
showChooseOrg(){
|
||||
this.$refs.refChooseOrg.dlgShow = true;
|
||||
},
|
||||
@@ -737,7 +747,6 @@ export default {
|
||||
this.$emit('close');
|
||||
},
|
||||
initShow(editData) {
|
||||
console.log('初始化显示内容============', editData)
|
||||
//console.log(this.$refs.weikePanel,'this.$refs.weikePanel');
|
||||
//this.$refs.weikePanel.init();
|
||||
//this.$refs.onlineCourse.resetData();
|
||||
@@ -785,8 +794,6 @@ export default {
|
||||
this.tips=[];
|
||||
|
||||
if (!editData) {
|
||||
this.tips=[];
|
||||
this.courseTags=[],
|
||||
//console.log("新建课程?");
|
||||
//以下为了保证初始化处理
|
||||
this.weikeReset = Math.round(Math.random()) + '';
|
||||
@@ -883,8 +890,6 @@ export default {
|
||||
if (rs.status == 200) {
|
||||
this.courseChooseShow = false;
|
||||
this.courseInfo = rs.result;
|
||||
this.curCourseId = this.courseInfo.id
|
||||
console.log('保存课程成功',this.curCourseId)
|
||||
if (this.courseChooseId == 1) {
|
||||
this.weike.dlgShow = true;
|
||||
} else {
|
||||
@@ -905,16 +910,30 @@ export default {
|
||||
this.courseCoverurl = '';
|
||||
this.courseInfo.coverImg = '';
|
||||
},
|
||||
//获取字典信息
|
||||
async getDictIds() {
|
||||
console.log("--- 获取字典信息 1 = ", this.dicts);
|
||||
try {
|
||||
const response = await apiCourse.getDictIds(637, 1); // 确保返回 Promise
|
||||
console.log("--- 获取字典信息 2 result= ", response);
|
||||
|
||||
if (response.status === 200) {
|
||||
this.dicts = response.result.dicts; // 正确提取 dicts
|
||||
console.log("--- 获取字典信息 3 = ", this.dicts);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取字典信息失败:", error);
|
||||
}
|
||||
},
|
||||
//获取课程信息
|
||||
async getDetail(id) {
|
||||
this.curCourseId = id;
|
||||
this.orgName='';
|
||||
this.isPermission = false;
|
||||
let $this = this;
|
||||
try {
|
||||
const { result, status } = await apiCourse.detail(id);
|
||||
if (status === 200) {
|
||||
this.courseTags = result.tagList;
|
||||
console.log('获取课程信息成功', this.courseTags);
|
||||
//把数据附给三个对象
|
||||
if(result.course.visible==''){
|
||||
result.course.visible=false;
|
||||
@@ -928,7 +947,10 @@ export default {
|
||||
this.contentInfo.list = result.contents;
|
||||
this.sectionInfo.list = result.sections;
|
||||
this.courseTeachers = result.teachers; //课程的老师信息
|
||||
|
||||
this.isPermission = result.isPermission; //课程的老师信息
|
||||
this.dicts = result.dicts; //课程的老师信息
|
||||
console.log("--- 编辑查看 this.isPermission = ",this.isPermission)
|
||||
console.log("--- 编辑查看 this.dicts = ",this.dicts)
|
||||
if(!this.courseInfo.orgId){
|
||||
//根据课程创建者获取机构id
|
||||
apiUser.getOrgSimpleByUserId(result.course.sysCreateAid).then(ors=>{
|
||||
@@ -980,6 +1002,7 @@ export default {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.resOwnerArray=[];
|
||||
if (result.course.resOwner1 == '') {
|
||||
this.resOwnerArray.push(result.course.resOwner1);
|
||||
@@ -1264,7 +1287,7 @@ export default {
|
||||
teachers: saveTeachers,
|
||||
crowds:crowds
|
||||
};
|
||||
console.log(postData);
|
||||
//console.log(postData);
|
||||
//this.btnLoading=false;
|
||||
apiCourse
|
||||
.saveBase(postData)
|
||||
|
||||
@@ -48,17 +48,13 @@ export default {
|
||||
let name = '';
|
||||
if (this.course && this.course.name && this.course.name !== '') {
|
||||
name = this.course.name.replace('color:#FF0000', 'color:#fff');
|
||||
console.log("name gengxindata1 : ",name)
|
||||
}
|
||||
if (this.course && this.course.courseName && this.course.courseName !== '') {
|
||||
name = this.course.courseName.replace('color:#FF0000', 'color:#fff');
|
||||
console.log("name gengxindata2 : ",name)
|
||||
}
|
||||
if (this.course && this.course.title && this.course.title !== '') {
|
||||
name = this.course.title.replace('color:#FF0000', 'color:#fff');
|
||||
console.log("name gengxindata3 : ",name)
|
||||
}
|
||||
console.log("name gengxindata4 : ",name)
|
||||
return name;
|
||||
// course.name || course.courseName || course.title
|
||||
},
|
||||
|
||||
@@ -1,200 +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"
|
||||
@change="handleSelectionChange"
|
||||
@keyup.enter.native="handleEnterKey"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in searchResults"
|
||||
:key="item.id"
|
||||
:label="item.tagName"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</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
|
||||
},
|
||||
// 添加:接收初始标签数据的props
|
||||
initialTags: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedTags: [],
|
||||
searchResults: [],
|
||||
loading: false,
|
||||
tagMap: new Map(),
|
||||
inputBuffer: '',
|
||||
params: {},
|
||||
tag: {}
|
||||
}
|
||||
},
|
||||
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))
|
||||
},
|
||||
// 添加:挂载时初始化标签数据
|
||||
mounted() {
|
||||
if (this.initialTags && this.initialTags.length > 0) {
|
||||
this.selectedTags = this.initialTags;
|
||||
this.searchResults = this.initialTags;
|
||||
// 将初始标签添加到tagMap中,确保删除功能正常
|
||||
this.initialTags.forEach(tag => {
|
||||
if (tag.id) {
|
||||
this.tagMap.set(tag.id, tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听课程ID变化,重置所有状态
|
||||
courseId(newVal) {
|
||||
this.resetTagState();
|
||||
},
|
||||
// 监听初始标签变化,重新加载
|
||||
initialTags(newVal) {
|
||||
this.selectedTags = newVal || [];
|
||||
this.searchResults = newVal || [];
|
||||
this.tagMap.clear(); // 清空旧缓存
|
||||
newVal.forEach(tag => {
|
||||
if (tag.id) this.tagMap.set(tag.id, tag);
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 新增:重置标签状态的方法
|
||||
resetTagState() {
|
||||
this.selectedTags = [];
|
||||
this.searchResults = [];
|
||||
this.tagMap.clear();
|
||||
this.loading = false;
|
||||
this.params = {};
|
||||
},
|
||||
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 = ''
|
||||
}
|
||||
},
|
||||
|
||||
// 新增:处理选择变化事件
|
||||
handleSelectionChange() {
|
||||
this.$emit('change', this.displayTags)
|
||||
},
|
||||
//创建新标签
|
||||
async createNewTag(tagName) {
|
||||
// 标签不能超过八个字
|
||||
if (tagName.length > 8) {
|
||||
this.$message.error('标签不能超过8个字')
|
||||
return;
|
||||
}
|
||||
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.$message.success('标签创建成功');
|
||||
this.searchResults.push(newTag)
|
||||
console.log("----------newTag---------->",this.searchResults)
|
||||
this.tagMap.set(newTag.id, newTag)
|
||||
this.$emit('change', this.displayTags)
|
||||
} 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.loadData(false);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
@@ -633,7 +633,6 @@
|
||||
this.$message.error(res.message);
|
||||
}
|
||||
});
|
||||
this.loadData(false);
|
||||
},
|
||||
delCommnet(com,idx){
|
||||
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> -->
|
||||
<div v-else class="is_favorite" :class="isFavorite?'is_favorite_a':'is_favorite'"></div>
|
||||
</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 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">
|
||||
@@ -114,6 +114,8 @@ export default {
|
||||
shares:0,
|
||||
praises:0,
|
||||
views:0,
|
||||
courseId:'',
|
||||
courseName:''
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -234,7 +236,7 @@ export default {
|
||||
created(){
|
||||
},
|
||||
mounted() {
|
||||
if(this.data && this.data.id && !this.readonly){
|
||||
if(this.data && (this.data.id||this.data.courseId) && !this.readonly){
|
||||
this.checkHas();
|
||||
}
|
||||
|
||||
@@ -308,7 +310,7 @@ export default {
|
||||
}
|
||||
let msgPageParams=this.pageParams;
|
||||
if(!msgPageParams){
|
||||
msgPageParams=this.data.id;
|
||||
msgPageParams=this.data.id ?this.data.id: this.data.courseId;
|
||||
}
|
||||
let message={
|
||||
content,
|
||||
@@ -331,9 +333,9 @@ export default {
|
||||
})
|
||||
},
|
||||
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){
|
||||
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){
|
||||
this.isFavorite=true;
|
||||
}else{
|
||||
@@ -506,9 +508,11 @@ export default {
|
||||
return;
|
||||
}
|
||||
//需要判断是否已点赞,已点赞的不再加
|
||||
console.log(this.data,'---------------');
|
||||
|
||||
let postData={
|
||||
objType:this.type,
|
||||
objId:this.data.id,
|
||||
objId:this.data.id ?this.data.id: this.data.courseId,
|
||||
title:'',
|
||||
}
|
||||
if(this.loading) {
|
||||
@@ -516,7 +520,7 @@ export default {
|
||||
}
|
||||
this.loading=true;
|
||||
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){
|
||||
postData.title=this.data.content;
|
||||
} else if(this.type==5){
|
||||
@@ -525,7 +529,7 @@ export default {
|
||||
postData.title=this.data.title;
|
||||
}
|
||||
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;
|
||||
if(res.status==200){
|
||||
this.isFavorite=false;
|
||||
@@ -554,7 +558,7 @@ export default {
|
||||
this.$store.dispatch("unicomFavorites",true)
|
||||
}
|
||||
//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.$emit('addFavorite',res.result);//添加收藏,如果是true代表添加成功,false代表已存在
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
</router-link>
|
||||
</div>
|
||||
<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>
|
||||
</router-link>
|
||||
</a>
|
||||
</div>
|
||||
<div class="top-nav" :style="{color:textColor}" :class="current == 'case' ? activeNav : ''">
|
||||
<router-link to="/case">案例
|
||||
@@ -137,30 +137,6 @@
|
||||
</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>
|
||||
<popup></popup><yearMedal></yearMedal>
|
||||
</div>
|
||||
@@ -168,7 +144,6 @@
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import apiMessage from '@/api/system/message.js';
|
||||
import apiManage from '@/api/manage/manage.js';
|
||||
import popup from '@/components/AlertPopup.vue';
|
||||
import yearMedal from '@/components/Popup/China2023.vue';
|
||||
import apiBoeCourse from '@/api/boe/course.js';
|
||||
@@ -229,8 +204,6 @@ export default {
|
||||
keyword: '',
|
||||
isTiao: false,
|
||||
sex:'',
|
||||
projectDialogVisible: false,
|
||||
studentInfo: {},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -241,22 +214,13 @@ export default {
|
||||
//this.loadPopupConfig();
|
||||
},
|
||||
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;
|
||||
})
|
||||
handleChangeCourse() {
|
||||
const paths = ["/course","/qualityCourse"]
|
||||
// 如果是 课程 和 精品课程, 那么就不再重定向
|
||||
const needReload = paths.findIndex(e=> e === this.$route.path) === -1
|
||||
if (needReload) this.$router.push({path: paths[0]})
|
||||
},
|
||||
|
||||
setCurIdentity(iden){
|
||||
this.$store.dispatch('SetCurIdentity',iden);
|
||||
},
|
||||
@@ -297,28 +261,6 @@ export default {
|
||||
if (val === "four") {
|
||||
window.open("https://m.qingxuetang.com/x/?appId=qxtcorp306130")
|
||||
// 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 {
|
||||
let urlPre = window.location.protocol + "//" + window.location.host;
|
||||
// process.env.VUE_APP_BOE_WEB_URL
|
||||
@@ -328,7 +270,7 @@ export default {
|
||||
two: urlPre + "/grow180/login",
|
||||
three: this.webBaseUrl + "/study/index?study=1",
|
||||
// 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",
|
||||
seven: this.webBaseUrl + '/grateful/index'
|
||||
};
|
||||
@@ -662,27 +604,4 @@ text-align: center;
|
||||
margin-right: 8px;
|
||||
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>
|
||||
|
||||
@@ -37,7 +37,6 @@ export default {
|
||||
},
|
||||
isDrag:{
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
blobId:{
|
||||
type: String,
|
||||
@@ -73,7 +72,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
down(e) {
|
||||
if (!this.isDrag) return;
|
||||
// if(this.isDrag) {
|
||||
this.$emit("getMouseDownStatus", true);
|
||||
this.is_mousedown_progress = true;
|
||||
// 获取完整进度条的clientX(dom左上角)
|
||||
@@ -86,13 +85,16 @@ export default {
|
||||
if(current<0) current = 0;
|
||||
var time = localStorage.getItem('videoProgressData');
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
//console.log('down arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
||||
// 禁止拖动
|
||||
if(time && arr[this.blobId] < current) return;
|
||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||
|
||||
this.$emit("updateProgress", current);
|
||||
// }
|
||||
|
||||
},
|
||||
move(e) {
|
||||
if (!this.isDrag || !this.is_mousedown_progress) return;
|
||||
if (this.is_mousedown_progress) {
|
||||
let init_clientX = this.dom_full.getBoundingClientRect().left;
|
||||
this.current_width_px = e.clientX - init_clientX;
|
||||
let current = (e.clientX - init_clientX) / this.dom_full.clientWidth;
|
||||
@@ -100,12 +102,14 @@ export default {
|
||||
if(current<0) current = 0;
|
||||
var time = localStorage.getItem('videoProgressData');
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
//console.log('move arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
||||
// 禁止拖动
|
||||
if(time && arr[this.blobId] < current) return;
|
||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||
this.$emit("updateProgress", current);
|
||||
}
|
||||
},
|
||||
up() {
|
||||
if (!this.isDrag || !this.is_mousedown_progress) return;
|
||||
if (this.is_mousedown_progress) {
|
||||
// 标记鼠标不处于按下的状态了
|
||||
this.is_mousedown_progress = false;
|
||||
// 松开鼠标后,即调整进度条后,此时的进度(0-1)
|
||||
@@ -114,10 +118,13 @@ export default {
|
||||
if(current<0) current = 0;
|
||||
var time = localStorage.getItem('videoProgressData');
|
||||
var arr = time&&JSON.parse(time) || {}
|
||||
//console.log('up arr:',this.isDrag,this.blobId,arr,arr[this.blobId],current)
|
||||
this.$emit("getMouseDownStatus", false);
|
||||
// 禁止拖动
|
||||
if(time && arr[this.blobId] < current) return;
|
||||
if(!this.isDrag && time && arr[this.blobId] < current) return;
|
||||
this.$emit("updateProgress", current);
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -128,8 +128,7 @@ export const iframes=[
|
||||
{title:'查看受众', path:'/iframe/ugroup/view',hidden:false,component:'manage/AudienceView'},
|
||||
{title:'问答管理', path:'/iframe/qa/manages',hidden:false,component:'qa/ManageList'},
|
||||
{title:'待审核课程', path:'/iframe/course/noapproved',hidden:false,component:'examine/NotApproved'},
|
||||
{title:'已审核课程', path:'/iframe/course/reviewed',hidden:false,component:'examine/Reviewed'},
|
||||
{title:'标签管理', path:'/iframe/tag/manages',hidden:false,component:'tag/TagManageList'},
|
||||
{title:'已审核课程', path:'/iframe/course/reviewed',hidden:false,component:'examine/Reviewed'}
|
||||
|
||||
]
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
/* Layout */
|
||||
import Layout from '@/layout/index'
|
||||
import LayoutPortal from '@/layout/portal'
|
||||
import Grateful from '@/views/grateful'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
@@ -362,7 +361,15 @@ export const constantRoutes = [{
|
||||
path: '/500',
|
||||
component: (resolve) => require(['@/views/error/500'], resolve),
|
||||
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({
|
||||
|
||||
83
src/utils/sseHelper.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* SSE流式数据处理工具
|
||||
*/
|
||||
|
||||
/**
|
||||
* 处理SSE响应数据
|
||||
* @param {String} data - SSE响应数据
|
||||
* @param {Function} onMessage - 处理消息的回调函数
|
||||
* @param {Function} onComplete - 完成时的回调函数
|
||||
* @param {Function} onError - 错误处理回调函数
|
||||
*/
|
||||
export function processSSEData(data, onMessage, onComplete, onError) {
|
||||
try {
|
||||
const lines = data.split('\n')
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data: ')) {
|
||||
const jsonData = JSON.parse(line.substring(6))
|
||||
onMessage(jsonData)
|
||||
|
||||
// 如果状态为4,表示对话结束
|
||||
if (jsonData.data && jsonData.data.status === 4) {
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理SSE数据时出错:', error)
|
||||
if (onError) {
|
||||
onError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建SSE连接
|
||||
* @param {String} url - 请求地址
|
||||
* @param {Object} data - 请求数据
|
||||
* @param {Function} onMessage - 消息处理回调
|
||||
* @param {Function} onComplete - 完成回调
|
||||
* @param {Function} onError - 错误回调
|
||||
* @returns {Promise} - 返回fetch Promise
|
||||
*/
|
||||
export function createSSEConnection(url, data, onMessage, onComplete, onError) {
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
}).then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const reader = response.body.getReader()
|
||||
const decoder = new TextDecoder('utf-8')
|
||||
let buffer = ''
|
||||
|
||||
function read() {
|
||||
reader.read().then(({ done, value }) => {
|
||||
if (done) {
|
||||
if (onComplete) onComplete()
|
||||
return
|
||||
}
|
||||
|
||||
buffer += decoder.decode(value, { stream: true })
|
||||
processSSEData(buffer, onMessage, onComplete, onError)
|
||||
|
||||
// 继续读取
|
||||
read()
|
||||
}).catch(error => {
|
||||
console.error('SSE读取错误:', error)
|
||||
if (onError) onError(error)
|
||||
})
|
||||
}
|
||||
|
||||
// 开始读取数据
|
||||
read()
|
||||
}).catch(error => {
|
||||
console.error('SSE连接错误:', error)
|
||||
if (onError) onError(error)
|
||||
})
|
||||
}
|
||||
@@ -153,9 +153,85 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="xindex-content">
|
||||
|
||||
<!-- 推荐课程 -->
|
||||
<div class="modules xcontent2">
|
||||
<!-- <div class="xcontent2-main"> -->
|
||||
<!--内容块-->
|
||||
|
||||
<!-- </div> -->
|
||||
<!-- 精品课模块 -->
|
||||
<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">
|
||||
<span class="modules-text">推荐课程</span>
|
||||
@@ -1137,6 +1213,9 @@ export default {
|
||||
orderType: 2,
|
||||
list: [],
|
||||
},
|
||||
qusisityList: {
|
||||
list: [],
|
||||
},
|
||||
// 推荐课程
|
||||
recommendedList:{
|
||||
list: [],
|
||||
@@ -1164,6 +1243,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.getCourseData(1);
|
||||
this.getEsqusiteList();
|
||||
this.getRecommendList();
|
||||
this.getPositive()
|
||||
this.getCaseData();
|
||||
@@ -1227,6 +1307,10 @@ export default {
|
||||
courseComputedTwoList(){
|
||||
return this.courseList.list.slice(3)
|
||||
},
|
||||
// 精品课展示
|
||||
exquisiteList() {
|
||||
return this.qusisityList.list.slice(0,3)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getPositive() {
|
||||
@@ -1421,21 +1505,27 @@ export default {
|
||||
//二期调整,直接改成一个地址
|
||||
//return this.webBaseUrl + '/course/detail?id=' + item.id;
|
||||
let $this = this;
|
||||
let cId = "";
|
||||
if (item.id) {
|
||||
cId = item.id;
|
||||
} else {
|
||||
cId = item.courseId;
|
||||
}
|
||||
if (item.type == 10) {
|
||||
//return this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
||||
//console.log("直接进入学习页面");
|
||||
this.$router.push("/course/studyindex?id=" + item.id);
|
||||
this.$router.push("/course/studyindex?id=" + cId);
|
||||
} else if (item.type == 20) {
|
||||
apiCourseStudy.hasSignup(item.id).then((rs) => {
|
||||
apiCourseStudy.hasSignup(cId).then((rs) => {
|
||||
if (rs.status == 200) {
|
||||
//return $this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
||||
this.$router.push("/course/studyindex?id=" + item.id);
|
||||
//return $this.webBaseUrl + "/course/studyindex?id=" + cId;
|
||||
this.$router.push("/course/studyindex?id=" + cId);
|
||||
} else {
|
||||
//return $this.webBaseUrl + "/course/detail?id=" + item.id;
|
||||
this.$router.push("/course/detail?id=" + item.id);
|
||||
//return $this.webBaseUrl + "/course/detail?id=" + cId;
|
||||
this.$router.push("/course/detail?id=" + cId);
|
||||
}
|
||||
});
|
||||
//return $this.webBaseUrl + "/course/detail?id=" + item.id;
|
||||
//return $this.webBaseUrl + "/course/detail?id=" + cId;
|
||||
}
|
||||
},
|
||||
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) {
|
||||
this.isNext = false;
|
||||
let { orderType, num } = this.courseList;
|
||||
@@ -1671,7 +1784,7 @@ export default {
|
||||
let userIds = [];
|
||||
list.forEach((item, index) => {
|
||||
cres.result.some((courseTeahcer) => {
|
||||
if (courseTeahcer.courseId == item.id) {
|
||||
if (courseTeahcer.courseId == (item.id||item.courseId)) {
|
||||
if (courseTeahcer.teacherIds) {
|
||||
userIds.push(courseTeahcer.teacherIds[0]);
|
||||
item.authorInfo.aid = courseTeahcer.teacherIds[0];
|
||||
@@ -2661,6 +2774,7 @@ export default {
|
||||
// padding-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.course-author-left {
|
||||
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>
|
||||
|
||||
@@ -289,8 +289,8 @@ export default {
|
||||
})
|
||||
},
|
||||
viewTopic(data) {
|
||||
window.open(this.webBaseUrl+'/article/detail?id='+data.id , '_blank')
|
||||
// this.$router.push({path:'/article/detail',query:{id:data.id}})
|
||||
// window.open(this.webBaseUrl+'/article/detail?id='+data.id , '_blank')
|
||||
this.$router.push({path:'/article/detail',query:{id:data.id}})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -697,8 +697,7 @@ export default {
|
||||
},
|
||||
viewTopic(data) {
|
||||
if (data.confidentialityLevel == '内部') {
|
||||
// this.$router.push({ path: '/case/detail', query: { id: data.id } })
|
||||
window.open(this.webBaseUrl+'/case/detail?id='+data.id , '_blank')
|
||||
this.$router.push({ path: '/case/detail', query: { id: data.id } })
|
||||
} else {
|
||||
this.$message.warning("非内部密级案例不能查看");
|
||||
}
|
||||
|
||||
@@ -624,12 +624,8 @@ export default {
|
||||
// if(item.minute){
|
||||
// item.duration=parseFloat(item.minute)*60;
|
||||
// }
|
||||
// 视频文件才可以设置时长,其他类型直接赋值0
|
||||
if (item.fileType === 'mp4' || item.fileType === 'mp3') {
|
||||
item.duration = item.minute ? parseFloat(item.minute) * 60 : 0;
|
||||
} else {
|
||||
item.duration = 0;
|
||||
}
|
||||
// 如果没有给一个默认值30分钟
|
||||
item.duration = item.minute ? parseFloat(item.minute) * 60 : 1800;
|
||||
});
|
||||
this.loading = true;
|
||||
coueseFile.batchUpdate(this.fileList).then(rs => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<swiper :options="swiperOptiontwo">
|
||||
<swiper-slide style="margin: 0 auto" v-for="(item, idx) in resonimg" :key="'a' + idx"
|
||||
class="swiper-slide games pointer" >
|
||||
<div class="bannbox" :style="{
|
||||
<div class="bannbox" @click="handleCarouselClick(item)" :style="{
|
||||
background: `url(${fileBaseUrl + item.image
|
||||
}) center center no-repeat`,
|
||||
}"></div>
|
||||
@@ -18,7 +18,7 @@
|
||||
<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"
|
||||
class="swiper-slide games pointer" >
|
||||
<div class="bannbox" :style="{
|
||||
<div class="bannbox" @click="handleCarouselClick(item)" :style="{
|
||||
background: `url(${fileBaseUrl + item.image
|
||||
}) center center no-repeat`,
|
||||
}"></div>
|
||||
@@ -220,7 +220,7 @@ export default {
|
||||
autoplay: false,
|
||||
// noSwiping: true,
|
||||
},
|
||||
resonimg: [],
|
||||
// resonimg: [],
|
||||
swiperOption: {
|
||||
autoplay: {
|
||||
delay: 2000,
|
||||
@@ -249,6 +249,13 @@ export default {
|
||||
this.getToolData()
|
||||
},
|
||||
methods: {
|
||||
// 添加点击轮播图跳转的方法
|
||||
handleCarouselClick(item) {
|
||||
if (item.url) {
|
||||
window.open(item.url, '_blank');
|
||||
}
|
||||
},
|
||||
|
||||
downTool(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}`)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="navTop">
|
||||
<div>
|
||||
<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 style="position: relative;">
|
||||
<el-input class="portal-input" placeholder="请输入课程名称" style="border-radius: 20px !important; "
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
60ab8a4b97b446b2dcd32889
|
||||
313
src/views/portal/case/AICall.vue
Normal file
@@ -0,0 +1,313 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible="dialogVisible"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
:show-close="true"
|
||||
@close="onClose"
|
||||
class="case-expert-dialog"
|
||||
>
|
||||
<!-- 标题 -->
|
||||
<div slot="title" class="dialog-title">
|
||||
<!-- <img src="@/assets/images/case-expert-icon.png" alt="案例专家" class="icon" /> -->
|
||||
<span>案例专家</span>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="content-wrapper">
|
||||
<div
|
||||
class="welcome-message"
|
||||
ref="messageContainer"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div class="message-text" v-for="(item, index) in messageList" :key="index">
|
||||
<messages :messageData="item" :suggestions="suggestions"></messages>
|
||||
|
||||
</div>
|
||||
<div class="message-suggestions" v-if="messageList[messageList.length-1].textCompleted">
|
||||
<div class="suggestion-item" v-for="(item, index) in suggestions" :key="index">
|
||||
<a @click="sendSuggestions(item)"> {{ item }} →</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isLoading" class="loading-message">
|
||||
<div class="loading-dots">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 输入框区域 -->
|
||||
<send-message
|
||||
v-model="AIContent"
|
||||
:message-list="messageList"
|
||||
:suggestions="suggestions"
|
||||
@loading="handleLoading"
|
||||
@update-message="updateMessage"
|
||||
@update-suggestions="updateSuggestions"
|
||||
@new-conversation="startNewConversation"
|
||||
:disabled="isLoading"
|
||||
class="input-area-wrapper"
|
||||
ref="sendMessage"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 关闭按钮在右上角,由 el-dialog 自动处理 -->
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import messages from './components/messages.vue'
|
||||
import sendMessage from './components/sendMessage.vue'
|
||||
|
||||
export default {
|
||||
name: 'CaseExpertDialog',
|
||||
props: {
|
||||
dialogVisible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
messages,
|
||||
sendMessage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
AIContent: '',
|
||||
isLoading: false,
|
||||
messageList: [
|
||||
{
|
||||
typing:true,
|
||||
isBot: true, // 是否为机器人
|
||||
text: `<p><b>您好!我是京东方案侧智能问答助手,随时为您服务。</b></p>
|
||||
<p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p>
|
||||
<p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p>
|
||||
<p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>`
|
||||
}
|
||||
],
|
||||
suggestions:[],
|
||||
isAutoScroll: true // 是否自动滚动
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
messageList: {
|
||||
handler() {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom();
|
||||
});
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClose() {
|
||||
console.log('关闭弹窗')
|
||||
this.$emit('close')
|
||||
// 可以在这里执行其他逻辑
|
||||
},
|
||||
|
||||
// 处理加载状态
|
||||
handleLoading(status) {
|
||||
this.isLoading = status;
|
||||
},
|
||||
|
||||
// 更新消息
|
||||
updateMessage(message) {
|
||||
// 由于Vue的响应式系统,message对象的更改会自动更新视图
|
||||
// 这里不需要额外的操作
|
||||
},
|
||||
updateSuggestions(arr){
|
||||
this.suggestions = arr
|
||||
},
|
||||
// 处理建议
|
||||
sendSuggestions(item){
|
||||
// this.suggestions = []
|
||||
this.AIContent = item
|
||||
setTimeout(()=>{
|
||||
this.$refs.sendMessage.handleSend()
|
||||
this.AIContent = ''
|
||||
},500)
|
||||
},
|
||||
startNewConversation() {
|
||||
this.messageList = [
|
||||
{
|
||||
isBot: true,
|
||||
text: `<p><b>您好!我是京东方案侧智能问答助手,随时为您服务。</b></p>
|
||||
<p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p>
|
||||
<p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p>
|
||||
<p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>`
|
||||
}
|
||||
];
|
||||
this.AIContent = '';
|
||||
this.isLoading = false;
|
||||
},
|
||||
|
||||
// 处理滚动事件
|
||||
handleScroll(event) {
|
||||
const element = event.target;
|
||||
// 判断是否滚动到底部
|
||||
const isAtBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + 1;
|
||||
|
||||
// 如果滚动到底部,则开启自动滚动
|
||||
// 如果离开底部,则关闭自动滚动
|
||||
this.isAutoScroll = isAtBottom;
|
||||
},
|
||||
|
||||
// 滚动到底部
|
||||
scrollToBottom() {
|
||||
if (this.isAutoScroll && this.$refs.messageContainer) {
|
||||
this.$refs.messageContainer.scrollTop = this.$refs.messageContainer.scrollHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.case-expert-dialog {
|
||||
::v-deep .el-dialog{
|
||||
background: url("./components/u762.svg") no-repeat ;
|
||||
background-size: cover;
|
||||
|
||||
//background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
::v-deep .el-dialog__body{
|
||||
padding: 10px;
|
||||
//font-size: 12px;
|
||||
*{
|
||||
font-size:unset ;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
background: transparent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.message-suggestions{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.suggestion-item{
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
padding: 5px 15px;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(228, 231, 237, 1);
|
||||
border-radius: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
.content-wrapper {
|
||||
padding: 20px;
|
||||
background-color: transparent;
|
||||
border-radius: 8px;
|
||||
height: 550px;
|
||||
position: relative;
|
||||
//margin-bottom: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.welcome-message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
flex:1;
|
||||
overflow-y: auto;
|
||||
|
||||
.avatar {
|
||||
margin-right: 12px;
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background-color: #007aff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.message-text {
|
||||
width: 100%;
|
||||
//margin-bottom: 15px;
|
||||
|
||||
p {
|
||||
color: #333;
|
||||
//font-size: 14px;
|
||||
line-height: 1.6;
|
||||
margin: 8px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-message {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background-color: #007aff;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.loading-dots {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: #999;
|
||||
margin-right: 5px;
|
||||
animation: loading 1.4s infinite ease-in-out both;
|
||||
|
||||
&:nth-child(1) {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-area-wrapper {
|
||||
//position: absolute;
|
||||
//bottom: 10px;
|
||||
//width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
@keyframes loading {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -20,7 +20,7 @@
|
||||
</div>
|
||||
<div class="label">
|
||||
<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 }}</span>
|
||||
<span>工号:{{ authorInfo.code }}</span>
|
||||
@@ -652,7 +652,7 @@ export default {
|
||||
},
|
||||
getCaseData() {
|
||||
// 清空pdf数据
|
||||
// this.pdfPath = '';
|
||||
this.pdfPath = '';
|
||||
|
||||
let $this = this;
|
||||
apiCase.details(this.resolveId, true).then(res => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div id="case-list-content">
|
||||
<div style="margin-bottom:30px" class="case-banner">
|
||||
<portal-header @type1="handleType" :type="queryCondition" current="case" textColor="#fff" @emitInput="emitInput" @showClass="showClass"></portal-header>
|
||||
<portal-header @type1="handleType" :type="queryCondition" current="case" textColor="#fff" @emitInput="emitInput"
|
||||
@showClass="showClass"></portal-header>
|
||||
</div>
|
||||
<div class="xcontent2">
|
||||
<!-- 新增的案例分类 -->
|
||||
@@ -115,7 +116,8 @@
|
||||
<div style="padding:0;" :class="speciAll ? 'fieldactive' : ''" @click="majorall()">全部</div>
|
||||
<div class="fieldbox">
|
||||
<div :class="item.fielclass ? 'fieldactive' : ''" @click="fieldmajor(item)"
|
||||
v-for="(item, idx) in speciData" :key="'d' + idx">{{ item.name }}({{ item.explanation }})</div>
|
||||
v-for="(item, idx) in speciData" :key="'d' + idx">{{ item.name }}({{ item.explanation }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <el-radio-group style="display:flex;" v-model="queryCondition.majorType" size="mini" @change="search()">
|
||||
@@ -156,15 +158,19 @@
|
||||
<div v-if="caseTimeShow" class="pub_time" @click="searchTime">
|
||||
<div class="text">发布时间</div>
|
||||
<div class="triangle">
|
||||
<div :style="{borderBottomColor:pubTimeNum===2?'#387DF7':'#DCDFE6'}" class="up-triangle"></div>
|
||||
<div :style="{borderTopColor:pubTimeNum===1?'#387DF7':'#DCDFE6'}" class="down-triangle"></div>
|
||||
<div :style="{ borderBottomColor: pubTimeNum === 2 ? '#387DF7' : '#DCDFE6' }" class="up-triangle">
|
||||
</div>
|
||||
<div :style="{ borderTopColor: pubTimeNum === 1 ? '#387DF7' : '#DCDFE6' }" class="down-triangle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="caseTimeShow" class="pub_time" @click="searchPageView">
|
||||
<div class="text">浏览量</div>
|
||||
<div class="triangle">
|
||||
<div :style="{borderBottomColor:pageViewNum===2?'#387DF7':'#DCDFE6'}" class="up-triangle"></div>
|
||||
<div :style="{borderTopColor:pageViewNum===1?'#387DF7':'#DCDFE6'}" class="down-triangle"></div>
|
||||
<div :style="{ borderBottomColor: pageViewNum === 2 ? '#387DF7' : '#DCDFE6' }" class="up-triangle">
|
||||
</div>
|
||||
<div :style="{ borderTopColor: pageViewNum === 1 ? '#387DF7' : '#DCDFE6' }" class="down-triangle">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-select v-if="caseTimeShow" @change="yearsChange" v-model="years" multiple collapse-tags
|
||||
@@ -172,7 +178,8 @@
|
||||
<el-option v-for="item in caseYears" :key="item.value" :label="item.label" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div :class="queryCondition.type == 'collect' ? 'collect_active': 'collect'" @click="searchexcellent('collect')">
|
||||
<div :class="queryCondition.type == 'collect' ? 'collect_active' : 'collect'"
|
||||
@click="searchexcellent('collect')">
|
||||
<div class="png"></div>
|
||||
<div class="text">收藏案例</div>
|
||||
</div>
|
||||
@@ -189,28 +196,34 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-content">
|
||||
<div v-for="item in this.caseList.list" :key="isTimeData?item.browsingHistoryId : item.id" class="case-list">
|
||||
<div v-for="item in this.caseList.list" :key="isTimeData ? item.browsingHistoryId : item.id"
|
||||
class="case-list">
|
||||
<div class="case-info">
|
||||
<div class="case-info-cont">
|
||||
<!-- <router-link :to="'/case/detail?id=' + item.id"> -->
|
||||
<div @click="toCaseDetail(item.id, item.refId)" style="cursor: pointer;">
|
||||
<div v-if="isTime" class="case_text">
|
||||
<span style="margin-right:28px">阅读了案例</span>
|
||||
<span>{{ formatDateTime(item.eventTime) }}</span>
|
||||
<span>{{ item.eventTime }}</span>
|
||||
</div>
|
||||
<div class="case-info-title">
|
||||
<div class="case-titdiv">
|
||||
<div class="case-tittext">
|
||||
<span :style="{maxWidth:item.excellentTag&&item.viewRankTags.length != 0?'400px':item.viewRankTags.length != 0?'500px':''}" class="title-line-ellipsis" :title="item.title">{{ item.title || item.contentInfo }}</span>
|
||||
<span
|
||||
:style="{ maxWidth: item.excellentTag && item.viewRankTags.length != 0 ? '400px' : item.viewRankTags.length != 0 ? '500px' : '' }"
|
||||
class="title-line-ellipsis" :title="item.title">{{ item.title || item.contentInfo }}</span>
|
||||
</div>
|
||||
<div class="case-activeText">
|
||||
<!-- <span v-if="item.breCommend" class="comWords"
|
||||
style="background-color:rgba(232, 139, 72);">荐</span>
|
||||
<span v-if="item.excellent" class="comWords" style="background-color:red;">最佳</span> -->
|
||||
<span @click.stop="()=>{}" v-if="item.excellentTag" class="comWords" style="width: 98px;height: 24px;background: #F99000;border-radius: 2px;font-weight: 400;font-size: 12px;color: #FFFFFF;padding: 4px 10px;cursor: auto;">
|
||||
<span @click.stop="() => { }" v-if="item.excellentTag" class="comWords"
|
||||
style="width: 98px;height: 24px;background: #F99000;border-radius: 2px;font-weight: 400;font-size: 12px;color: #FFFFFF;padding: 4px 10px;cursor: auto;">
|
||||
{{ item.excellentTag }}
|
||||
</span>
|
||||
<span @click.stop="toExcellent(tag)" v-if="item.viewRankTags.length != 0" v-for="tag in item.viewRankTags" class="comWords" style="width: 98px;height: 24px;background: #F99000;border-radius: 2px;font-weight: 400;font-size: 12px;color: #FFFFFF;padding: 4px 10px;">
|
||||
<span @click.stop="toExcellent(tag)" v-if="item.viewRankTags.length != 0"
|
||||
v-for="tag in item.viewRankTags" class="comWords"
|
||||
style="width: 98px;height: 24px;background: #F99000;border-radius: 2px;font-weight: 400;font-size: 12px;color: #FFFFFF;padding: 4px 10px;">
|
||||
{{ tag.tagName }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -225,8 +238,9 @@
|
||||
<!-- </router-link> -->
|
||||
<div v-if="!item.id" style="height:25px;padding-top:14px "></div>
|
||||
<div v-if="item.id" style="height:58px;padding-top:14px ">
|
||||
<author :avatar="item.authorInfo.avatar" :name="item.authorInfo.name" :info="item.authorInfo.orgInfo"
|
||||
:sex="item.authorInfo.sex" :authorTags="item.authorTags" :aid="item.authorInfo.aid">
|
||||
<author :avatar="item.authorInfo.avatar" :name="item.authorInfo.name"
|
||||
:info="item.authorInfo.orgInfo" :sex="item.authorInfo.sex" :authorTags="item.authorTags"
|
||||
:aid="item.authorInfo.aid">
|
||||
<template>
|
||||
<div v-if="item.breCommend"
|
||||
style="padding-top: 6px;flex: 1;display: flex;justify-content: flex-end;color: #999;font-size: 12px;">
|
||||
@@ -253,7 +267,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- </router-link> -->
|
||||
<div v-if="item.id" class="case-info-summary two-line-ellipsis" @click="toCaseDetail(item.id, item.refId)">
|
||||
<div v-if="item.id" class="case-info-summary two-line-ellipsis"
|
||||
@click="toCaseDetail(item.id, item.refId)">
|
||||
{{ item.summary }}
|
||||
<!-- <router-link :to="'/case/detail?id='+item.id"> -->
|
||||
<!-- {{displayAll(item)}} -->
|
||||
@@ -264,7 +279,8 @@
|
||||
</div>
|
||||
<div v-if="item.id" style="display: flex;justify-content: flex-end;">
|
||||
<div style="margin:8px 0;">
|
||||
<interactBar @deleteFavorite="deleteFavorite" :type="3" :data="item" :comments="false" :shares="true"></interactBar>
|
||||
<interactBar @deleteFavorite="deleteFavorite" :type="3" :data="item" :comments="false"
|
||||
:shares="true"></interactBar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -292,7 +308,12 @@
|
||||
</div>
|
||||
<!-- 打开排行榜 -->
|
||||
<div class="xcontent2-minor">
|
||||
|
||||
<div id="fixd-box">
|
||||
<div class="AI-case" style="position: relative" v-if="showAiCase ">
|
||||
<img src="../../../../public/images/case-logo.png" alt="">
|
||||
<span @click="getAICase" style="position: absolute; top: 65px;left: 15px;z-index: 1;width: 40%;height: 30px;"></span>
|
||||
</div>
|
||||
<router-link class="the_charts" to="/case/charts">
|
||||
<div class="text">排行榜</div>
|
||||
<div class="icon">></div>
|
||||
@@ -372,7 +393,8 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="recommendRank.length > 0" class="portal-ranking ranking-bg2" style="margin-top:20px;padding: 20px 15px;max-height: 222px;">
|
||||
<div v-if="recommendRank.length > 0" class="portal-ranking ranking-bg2"
|
||||
style="margin-top:20px;padding: 20px 15px;max-height: 222px;">
|
||||
<p class="ranking-title">推荐榜</p>
|
||||
<ul class="ranking-data">
|
||||
<li v-for="(item, index) in recommendRank" :key="index" class="title-line-ellipsis"
|
||||
@@ -458,6 +480,7 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
<AICall :dialogVisible="showAICall" @close="onClose" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -477,6 +500,9 @@ import apiDict from "@/api/modules/dict.js";
|
||||
import apiType from "@/api/modules/type.js";
|
||||
import { cutFullName } from "@/utils/tools.js";
|
||||
import apiPlace from "@/api/phase2/place.js"
|
||||
import AICall from '@/views/portal/case/AICall.vue'
|
||||
import { showCaseAiEntrance } from '@/api/boe/aiChat.js'
|
||||
|
||||
export default {
|
||||
name: "case",
|
||||
components: {
|
||||
@@ -486,9 +512,12 @@ export default {
|
||||
interactBar,
|
||||
timeShow,
|
||||
author,
|
||||
AICall
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAiCase:false,
|
||||
showAICall:false,
|
||||
timeoutId: null,
|
||||
isTimeData: false,
|
||||
articlePageList: [],
|
||||
@@ -761,6 +790,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
let $this = this;
|
||||
this.getShowAiCase()
|
||||
// if(this.speciData.length==0){
|
||||
// this.specialized();
|
||||
// }
|
||||
@@ -845,6 +875,14 @@ export default {
|
||||
|
||||
},
|
||||
methods: {
|
||||
// 是否展示入口
|
||||
getShowAiCase(){
|
||||
showCaseAiEntrance().then(res=>{
|
||||
this.showAiCase = res.data
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
allRequests() {
|
||||
window.addEventListener(
|
||||
"scroll",
|
||||
@@ -862,12 +900,6 @@ export default {
|
||||
this.popularityName = this.switch[e]
|
||||
this.getPopularity()
|
||||
},
|
||||
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)}`;
|
||||
},
|
||||
handleType(msg) {
|
||||
// this.queryCondition.type = msg
|
||||
},
|
||||
@@ -1513,7 +1545,7 @@ export default {
|
||||
};
|
||||
});
|
||||
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.getCaseUserData(res.result.list);
|
||||
@@ -1568,7 +1600,7 @@ export default {
|
||||
};
|
||||
});
|
||||
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.getCaseUserData(res.result.list);
|
||||
@@ -1611,11 +1643,11 @@ export default {
|
||||
}
|
||||
console.log(res?.result?.list, '有没有数据1');
|
||||
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');
|
||||
this.caseList.list = res.result.list
|
||||
// this.getCaseUserData(res.result.list);
|
||||
this.getCaseUserData(res.result.list);
|
||||
// 给所有的赋值
|
||||
this.caseList.count = res.result.count;
|
||||
this.caseList.showPagCount = res.result.count;
|
||||
@@ -1870,6 +1902,13 @@ export default {
|
||||
jumpRouter(item) {
|
||||
// console.log(item)
|
||||
this.$router.push(`/case/detail?id=${item.id}`);
|
||||
},
|
||||
// 案例立即咨询
|
||||
getAICase() {
|
||||
this.showAICall = true
|
||||
},
|
||||
onClose() {
|
||||
this.showAICall = false
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1882,9 +1921,11 @@ export default {
|
||||
font-size: 14px;
|
||||
color: rgba(51, 51, 51, 0.9);
|
||||
}
|
||||
|
||||
.el-icon--right {
|
||||
margin-left: 14px !important;
|
||||
}
|
||||
|
||||
.the_charts {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -1897,10 +1938,12 @@ export default {
|
||||
height: 47px;
|
||||
background: #DDEDFF;
|
||||
border-radius: 8px;
|
||||
|
||||
.text {
|
||||
font-size: 17px;
|
||||
color: #387DF7;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
font-size: 17px;
|
||||
@@ -1911,6 +1954,7 @@ export default {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 课程分类
|
||||
.course-title-style {
|
||||
position: relative;
|
||||
@@ -1982,6 +2026,7 @@ export default {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.u-class {
|
||||
::v-deep .el-dialog {
|
||||
border-radius: 15px;
|
||||
@@ -2112,6 +2157,7 @@ export default {
|
||||
border: 0.96px solid rgba(140, 105, 242, 1);
|
||||
box-shadow: 7px 5px 6px 0px rgba(76, 31, 221, 0.3);
|
||||
}
|
||||
|
||||
.text_msg {
|
||||
margin: 43px 0 0 222px;
|
||||
font-size: 14px;
|
||||
@@ -2495,18 +2541,22 @@ export default {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
// margin-bottom: ;
|
||||
.pub_time {
|
||||
display: flex;
|
||||
margin-right: 25px;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.triangle {
|
||||
margin-left: 5px;
|
||||
|
||||
.up-triangle {
|
||||
width: 0;
|
||||
height: 0;
|
||||
@@ -2515,6 +2565,7 @@ export default {
|
||||
border-bottom: 6px solid #DCDFE6;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.down-triangle {
|
||||
width: 0;
|
||||
height: 0;
|
||||
@@ -2524,6 +2575,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -2533,17 +2585,21 @@ export default {
|
||||
width: 116px;
|
||||
height: 38px;
|
||||
border-radius: 4px;
|
||||
|
||||
// background: #04243C;
|
||||
&:hover {
|
||||
// background: #387DF7;
|
||||
border: 1px solid #387DF7;
|
||||
|
||||
.text {
|
||||
// color: #fff;
|
||||
}
|
||||
|
||||
// .png{
|
||||
// background: url('../../../assets/images/case/wighttime.png') no-repeat;
|
||||
// }
|
||||
}
|
||||
|
||||
.png {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@@ -2551,11 +2607,13 @@ export default {
|
||||
background-size: 100%;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.time::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -2568,6 +2626,7 @@ export default {
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.time_active {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -2577,6 +2636,7 @@ export default {
|
||||
height: 38px;
|
||||
background: #387DF7;
|
||||
border-radius: 4px;
|
||||
|
||||
.png {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -2584,11 +2644,13 @@ export default {
|
||||
background-size: 100%;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.collect {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -2598,17 +2660,21 @@ export default {
|
||||
width: 116px;
|
||||
height: 38px;
|
||||
border-radius: 4px;
|
||||
|
||||
// background: #04243C;
|
||||
&:hover {
|
||||
// background: #387DF7;
|
||||
border: 1px solid #387DF7;
|
||||
|
||||
.text {
|
||||
// color: #fff;
|
||||
}
|
||||
|
||||
// .png{
|
||||
// background: url('../../../assets/images/case/wight.png') no-repeat;
|
||||
// }
|
||||
}
|
||||
|
||||
.png {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@@ -2616,11 +2682,13 @@ export default {
|
||||
background-size: 100%;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.collect::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -2633,6 +2701,7 @@ export default {
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.collect_active {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -2642,6 +2711,7 @@ export default {
|
||||
height: 38px;
|
||||
background: #387DF7;
|
||||
border-radius: 4px;
|
||||
|
||||
.png {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@@ -2649,6 +2719,7 @@ export default {
|
||||
background-size: 100%;
|
||||
margin-right: 9px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
@@ -2661,6 +2732,7 @@ export default {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 40px;
|
||||
|
||||
.search_div_num {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -2673,6 +2745,7 @@ export default {
|
||||
color: #387DF7;
|
||||
}
|
||||
}
|
||||
|
||||
.data-content {
|
||||
background-color: #fff;
|
||||
padding: 5px 50px;
|
||||
@@ -2712,6 +2785,7 @@ export default {
|
||||
color: #666666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.case-info-title {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
@@ -2810,5 +2884,22 @@ export default {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
.AI-case {
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
span {
|
||||
width: 160px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 105px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
1
src/views/portal/case/components/map.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1759024984858" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4686" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25"><path d="M451.673935 994.395699C478.883834 1025.019147 524.254807 1024.808979 551.400292 993.928851 553.755808 991.387908 558.821323 985.796762 565.872444 977.84835 577.572838 964.659017 590.597131 949.62432 604.615947 932.998315 644.662065 885.504506 684.708678 834.717818 722.129538 782.646447 759.658524 730.424619 792.492213 679.709274 819.314991 631.458462 868.685946 542.646317 896 465.543426 896 402.285715 896 180.109449 719.301715 0 501.333333 0 283.364952 0 106.666667 180.109449 106.666667 402.285715 106.666667 465.598716 134.05152 542.80573 183.54613 631.762622 210.371803 679.976529 243.193308 730.651876 280.699364 782.833154 318.155192 834.94455 358.239268 885.77421 398.322835 933.311031 412.354743 949.952073 425.391185 965.00073 437.102468 978.202579 444.160087 986.158466 449.230214 991.754921 451.982775 994.736706L451.673935 994.395699ZM486.822684 961.321348C484.281231 958.568254 479.425084 953.207989 472.585916 945.498359 461.135889 932.591017 448.364015 917.847761 434.602351 901.527215 395.275714 854.888073 355.949587 805.019548 319.289224 754.014863 282.808749 703.260452 250.983685 654.123578 225.158316 607.707522 179.388826 525.445805 154.50505 455.290161 154.50505 402.285715 154.50505 207.039905 309.785362 48.761905 501.333333 48.761905 692.881306 48.761905 848.161617 207.039905 848.161617 402.285715 848.161617 455.246022 823.345286 525.298263 777.693969 607.419251 751.873483 653.867066 720.038415 703.039925 683.537446 753.831262 646.912604 804.794967 607.624538 854.619674 568.335977 901.215038 554.587654 917.520243 541.828177 932.24925 530.389289 945.143797 523.556841 952.845711 518.705521 958.200435 516.166694 960.950526 507.543772 970.748911 495.255793 970.80583 487.131524 961.662353L486.822684 961.321348Z" fill="#979797" p-id="4687"></path><path d="M714.955981 467.028806C723.919106 442.627955 728.565658 416.668998 728.565658 390.095238 728.565658 268.908183 632.184774 170.666667 513.29293 170.666667 394.401086 170.666667 298.020202 268.908183 298.020202 390.095238 298.020202 511.282291 394.401086 609.52381 513.29293 609.52381 549.003859 609.52381 583.510052 600.631947 614.373097 583.874409 626.032316 577.543868 630.449257 562.77782 624.238611 550.893519 618.027966 539.009218 603.541579 534.507006 591.882359 540.837549 567.900883 553.858639 541.111735 560.761905 513.29293 560.761905 420.821495 560.761905 345.858586 484.351836 345.858586 390.095238 345.858586 295.838641 420.821495 219.428572 513.29293 219.428572 605.764365 219.428572 680.727273 295.838641 680.727273 390.095238 680.727273 410.807981 677.117041 430.977316 670.154965 449.930592 665.522846 462.540883 671.796821 476.591108 684.168282 481.312651 696.53974 486.034191 710.323861 479.639095 714.955981 467.028806L714.955981 467.028806Z" fill="#979797" p-id="4688"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
300
src/views/portal/case/components/messages.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<!--消息渲染-->
|
||||
<script>
|
||||
export default {
|
||||
name: "message",
|
||||
props: {
|
||||
messageData: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
suggestions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
displayText: '',
|
||||
typingTimer: null,
|
||||
typingSpeed: 30, // 打字机速度(毫秒/字符)
|
||||
showAllCaseRefers: false // 控制是否显示所有案例引用
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 计算需要显示的案例引用
|
||||
displayedCaseRefers() {
|
||||
if (this.showAllCaseRefers || !this.messageData.caseRefers) {
|
||||
return this.messageData.caseRefers || [];
|
||||
}
|
||||
return this.messageData.caseRefers.slice(0, 3);
|
||||
},
|
||||
// 判断是否需要显示"查看更多"按钮
|
||||
shouldShowMoreButton() {
|
||||
return this.messageData.caseRefers && this.messageData.caseRefers.length > 3;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'messageData.text': {
|
||||
handler(newVal) {
|
||||
if (newVal && this.messageData.isBot && !this.messageData.typing) {
|
||||
// this.startTyping(newVal)
|
||||
this.displayText = newVal || ''
|
||||
} else {
|
||||
this.displayText = newVal || ''
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
startTyping(text) {
|
||||
// 清除之前的定时器
|
||||
if (this.typingTimer) {
|
||||
clearInterval(this.typingTimer)
|
||||
this.typingTimer = null
|
||||
}
|
||||
|
||||
// 初始化
|
||||
// this.displayText = ''
|
||||
let index = 0
|
||||
|
||||
// 开始打字机效果
|
||||
this.typingTimer = setInterval(() => {
|
||||
if (index < text.length) {
|
||||
this.displayText += text.charAt(index)
|
||||
index++
|
||||
} else {
|
||||
// 打字完成,清除定时器
|
||||
clearInterval(this.typingTimer)
|
||||
this.typingTimer = null
|
||||
}
|
||||
}, this.typingSpeed)
|
||||
},
|
||||
// 切换显示所有案例引用
|
||||
toggleShowAllCaseRefers() {
|
||||
this.showAllCaseRefers = !this.showAllCaseRefers;
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 组件销毁前清除定时器
|
||||
if (this.typingTimer) {
|
||||
clearInterval(this.typingTimer)
|
||||
this.typingTimer = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="messages">
|
||||
{{messageData}}
|
||||
<!-- 机器人消息-->
|
||||
<div v-if="messageData.isBot" class="bot-message">
|
||||
<div class="bot-think" v-if="messageData.thinkText" v-html="messageData.thinkText"></div>
|
||||
<div v-html="displayText" ></div>
|
||||
<div v-if="messageData.caseRefers && messageData.caseRefers.length > 0 && messageData.textCompleted">
|
||||
<div class="case-refers">
|
||||
<div class="case-refers-title">
|
||||
<span> <i class="iconfont icon-think"></i> 引用案例</span>
|
||||
<span v-if="shouldShowMoreButton" class="more" @click="toggleShowAllCaseRefers">
|
||||
{{ showAllCaseRefers ? '收起' : '查看更多' }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="case-refers-list">
|
||||
<div class="case-refers-item" v-for="item in displayedCaseRefers" :key="item.caseId">
|
||||
<div class="case-refers-item-title">
|
||||
<a :href="'#case-' + item.caseId" class="title">{{ item.title }}</a>
|
||||
<span class="case-refers-item-timer">{{item.uploadTime}}</span>
|
||||
</div>
|
||||
<div class="case-refers-item-author">
|
||||
<span class="user"></span>
|
||||
<span>{{ item.authorName }}</span>
|
||||
<span class="case-inter-orginInfo">{{ item.orgInfo }}</span>
|
||||
</div>
|
||||
<div class="case-refers-item-keywords">
|
||||
<span v-for="keyword in item.keywords" :key="keyword">{{ keyword }}</span>
|
||||
</div>
|
||||
|
||||
<div class="message-content">{{item.content}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 非机器人消息-->
|
||||
<div v-else class="user-message">
|
||||
<div class="message-text">
|
||||
<div v-html="messageData.text"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 推荐问题-->
|
||||
|
||||
<!-- <div v-if="suggestions && suggestions.length > 0">-->
|
||||
<!-- <div class="suggestions">-->
|
||||
<!-- <div class="suggestions-title">-->
|
||||
<!-- <span>推荐问题</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="suggestions-list">-->
|
||||
<!-- <div class="suggestions-item" v-for="item in suggestions">-->
|
||||
<!-- <div class="suggestions-item-title">-->
|
||||
<!-- {{item}}-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.messages {
|
||||
width: 100%;
|
||||
|
||||
.bot-message {
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.bot-think {
|
||||
color: #909399;
|
||||
padding-bottom: 5px;
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
|
||||
&:before {
|
||||
content: ' ';
|
||||
border-left: 0.5px solid #909399;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
transform: scaleX(0.5);
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.case-refers {
|
||||
margin-top: 10px;
|
||||
|
||||
.case-refers-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.icon-think {
|
||||
background-image: url("./map.svg") ;
|
||||
width: 15px;
|
||||
height: 13px;
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.more{
|
||||
font-size: 10px;
|
||||
padding: 2px 6px;
|
||||
background-color: #F4F7FD;
|
||||
border-radius: 5px;
|
||||
color:#577EE1;font-weight: unset;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.case-refers-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
.case-refers-item {
|
||||
//margin-right: 10px;
|
||||
margin-bottom: 5px;
|
||||
border: 1px solid rgba(144, 147, 153, 0.44);
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
|
||||
.case-refers-item-title {
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
.title{
|
||||
max-width: 70% ;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
|
||||
}
|
||||
.case-refers-item-timer{
|
||||
font-size: 10px;
|
||||
margin-right: 20px;
|
||||
color:#cecece;
|
||||
font-weight: unset!important;
|
||||
}
|
||||
}
|
||||
.case-refers-item-author{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.user{
|
||||
background-image: url("./user.svg");
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.case-inter-orginInfo{
|
||||
font-size: 10px;
|
||||
color: rgba(144, 147, 153, 0.44);margin-left: 5px;
|
||||
|
||||
}
|
||||
}
|
||||
.case-refers-item-author,
|
||||
.case-refers-item-keywords {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-message {
|
||||
float: right;
|
||||
padding: 5px 15px;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(228, 231, 237, 1);
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.case-refers-item-keywords{
|
||||
margin-top: 5px;
|
||||
span{
|
||||
padding: 1px 4px;
|
||||
background-color: #F4F7FD;
|
||||
border-radius: 5px;
|
||||
font-size: 10px!important;
|
||||
color:#577EE1
|
||||
}
|
||||
span + span{
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
.message-content{
|
||||
font-size: 12px!important;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
386
src/views/portal/case/components/sendMessage.vue
Normal file
@@ -0,0 +1,386 @@
|
||||
<template>
|
||||
<div class="input-area">
|
||||
<el-input
|
||||
v-model="inputContent"
|
||||
class="input-placeholder"
|
||||
placeholder="有问题,尽管问"
|
||||
@keyup.enter.native="handleSend"
|
||||
:disabled="disabled"
|
||||
></el-input>
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" size="small" class="start-btn" @click="handleNewConversation">
|
||||
+ 开启新对话
|
||||
</el-button>
|
||||
<el-button type="text" class="send-btn" @click="handleSend" :disabled="disabled">
|
||||
<i class="el-icon-s-promotion"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { aiChat } from '@/api/boe/aiChat.js'
|
||||
|
||||
export default {
|
||||
name: 'SendMessage',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
messageList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
suggestions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inputContent: this.value,
|
||||
conversationId: '' // 会话ID
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newVal) {
|
||||
this.inputContent = newVal
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSend() {
|
||||
if (!this.inputContent.trim() || this.disabled) return
|
||||
// 添加用户消息到列表
|
||||
const userMessage = {
|
||||
isBot: false,
|
||||
text: this.inputContent
|
||||
};
|
||||
this.messageList.push(userMessage);
|
||||
|
||||
// 显示加载状态
|
||||
this.$emit('loading', true);
|
||||
|
||||
// 调用AI聊天接口 (暂时注释掉SSE,使用模拟数据)
|
||||
this.callAIChat(this.inputContent);
|
||||
|
||||
// 清空输入框
|
||||
this.inputContent = ''
|
||||
},
|
||||
|
||||
|
||||
// 真实的SSE实现(暂时注释掉)
|
||||
callAIChat(question) {
|
||||
// 创建新的AI消息对象
|
||||
const aiMessage = {
|
||||
isBot: true,
|
||||
text: '',
|
||||
status:null,
|
||||
thinkText: '',
|
||||
caseRefers: [], // 添加caseRefers字段
|
||||
textCompleted: false // 添加文字处理完成状态,默认为false
|
||||
};
|
||||
this.messageList.push(aiMessage);
|
||||
|
||||
// 构造请求参数
|
||||
const requestData = {
|
||||
conversationId: this.conversationId,
|
||||
query: question
|
||||
};
|
||||
|
||||
// 创建POST请求
|
||||
fetch('/systemapi/xboe/m/boe/case/ai/chat',{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestData)
|
||||
}).then(r=>{
|
||||
return r
|
||||
}).then(response => {
|
||||
// 处理流式响应
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
let buffer = '';
|
||||
let accumulatedContent = ''; // 累积的内容用于打字机效果
|
||||
let accumulatedThinkContent = ''; // 累积的思考内容
|
||||
let inThinkSection = false; // 是否在思考部分
|
||||
let typingTimer = null; // 打字机定时器
|
||||
let thinkTypingTimer = null; // 思考内容打字机定时器
|
||||
|
||||
// 逐字显示文本的函数
|
||||
const typeText = (message, fullContent) => {
|
||||
// 如果已有定时器在运行,先清除它
|
||||
if (typingTimer) {
|
||||
clearInterval(typingTimer);
|
||||
}
|
||||
|
||||
// 获取当前已显示的文本长度
|
||||
const currentLength = message.text.length;
|
||||
// 获取完整文本
|
||||
const targetLength = fullContent.length;
|
||||
|
||||
// 如果已经显示完整文本,不需要继续
|
||||
if (currentLength >= targetLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typingSpeed = 50; // 每个字符的间隔时间(毫秒)
|
||||
|
||||
typingTimer = setInterval(() => {
|
||||
// 计算下一个要显示的字符索引
|
||||
const nextIndex = message.text.length + 1;
|
||||
if (nextIndex <= targetLength) {
|
||||
message.text = fullContent.substring(0, nextIndex);
|
||||
this.$emit('update-message', message);
|
||||
} else {
|
||||
clearInterval(typingTimer);
|
||||
typingTimer = null;
|
||||
// 当打字机效果完成时,检查是否应该设置textCompleted为true
|
||||
// 这应该在status 4(交互完成)时才设置
|
||||
if (message.status === 4) {
|
||||
if (nextIndex >= targetLength) {
|
||||
message.textCompleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, typingSpeed);
|
||||
};
|
||||
|
||||
// 逐字显示思考内容的函数
|
||||
const typeThinkText = (message, fullThinkContent) => {
|
||||
// 如果已有定时器在运行,先清除它
|
||||
if (thinkTypingTimer) {
|
||||
clearInterval(thinkTypingTimer);
|
||||
}
|
||||
|
||||
// 获取当前已显示的文本长度
|
||||
const currentLength = message.thinkText.length;
|
||||
// 获取完整文本
|
||||
const targetLength = fullThinkContent.length;
|
||||
|
||||
// 如果已经显示完整文本,不需要继续
|
||||
if (currentLength >= targetLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从当前显示位置开始继续显示(避免清空重显)
|
||||
const startIndex = currentLength;
|
||||
|
||||
const typingSpeed = 20; // 每个字符的间隔时间(毫秒)
|
||||
|
||||
thinkTypingTimer = setInterval(() => {
|
||||
// 计算下一个要显示的字符索引
|
||||
const nextIndex = message.thinkText.length + 1;
|
||||
if (nextIndex <= targetLength) {
|
||||
message.thinkText = fullThinkContent.substring(0, nextIndex);
|
||||
this.$emit('update-message', message);
|
||||
} else {
|
||||
clearInterval(thinkTypingTimer);
|
||||
thinkTypingTimer = null;
|
||||
}
|
||||
}, typingSpeed);
|
||||
};
|
||||
|
||||
// 添加一个检查是否所有文本都已完成显示的函数
|
||||
const isTextDisplayCompleted = (message, fullContent) => {
|
||||
return message.text.length >= fullContent.length;
|
||||
};
|
||||
|
||||
// 读取流数据
|
||||
const read = () => {
|
||||
reader.read().then(({ done, value }) => {
|
||||
if (done) {
|
||||
// 当流结束时,等待打字机效果完成
|
||||
const waitForTyping = () => {
|
||||
if (!typingTimer) {
|
||||
this.$emit('loading', false);
|
||||
} else {
|
||||
setTimeout(waitForTyping, 100);
|
||||
}
|
||||
};
|
||||
waitForTyping();
|
||||
return;
|
||||
}
|
||||
|
||||
// 解码数据
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
|
||||
// 按行分割数据
|
||||
const lines = buffer.split('\n');
|
||||
buffer = lines.pop(); // 保留不完整的行
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data:')) {
|
||||
try {
|
||||
const jsonData = JSON.parse(line.substring(5));
|
||||
// 根据status处理不同类型的数据
|
||||
switch (jsonData.status) {
|
||||
case 0: // 引用文件
|
||||
// 处理引用文件信息
|
||||
if (jsonData.fileRefer && jsonData.fileRefer.caseRefers) {
|
||||
aiMessage.caseRefers = jsonData.fileRefer.caseRefers;
|
||||
// 更新父组件的messageList
|
||||
this.$emit('update-message', aiMessage);
|
||||
}
|
||||
// 从响应中获取并保存conversationId
|
||||
if (jsonData.conversationId) {
|
||||
this.conversationId = jsonData.conversationId;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 流式对话内容
|
||||
// 处理
|
||||
const content = jsonData.content;
|
||||
aiMessage.hasThink = false;
|
||||
if (content.startsWith('<think>')) {
|
||||
aiMessage.hasThink = true
|
||||
inThinkSection = true;
|
||||
accumulatedThinkContent = content.replace('<think>', '');
|
||||
// 使用打字机效果显示think内容
|
||||
typeThinkText(aiMessage, accumulatedThinkContent);
|
||||
} else if (content.startsWith('</think>')) {
|
||||
inThinkSection = false;
|
||||
accumulatedThinkContent += content.replace('</think>', '');
|
||||
// 使用打字机效果显示think内容
|
||||
typeThinkText(aiMessage, accumulatedThinkContent);
|
||||
} else if (inThinkSection) {
|
||||
accumulatedThinkContent += content;
|
||||
// 使用打字机效果显示think内容
|
||||
typeThinkText(aiMessage, accumulatedThinkContent);
|
||||
} else {
|
||||
// 累积内容并使用打字机效果更新显示
|
||||
accumulatedContent += content;
|
||||
// 如果thinkText已经显示完整,则继续使用打字机效果显示内容
|
||||
if( aiMessage.hasThink){
|
||||
if(aiMessage.thinkText.length >=accumulatedThinkContent.length){
|
||||
typeText(aiMessage, accumulatedContent);
|
||||
}
|
||||
} else {
|
||||
typeText(aiMessage, accumulatedContent);
|
||||
}
|
||||
|
||||
}
|
||||
// 不在这里直接更新,让打字机效果处理更新
|
||||
break;
|
||||
|
||||
case 2: // 回答完成
|
||||
// 不再在这里设置textCompleted状态
|
||||
// 更新父组件的messageList
|
||||
this.$emit('update-message', aiMessage);
|
||||
// 从响应中获取并保存conversationId
|
||||
|
||||
break;
|
||||
|
||||
case 3: // 返回建议
|
||||
// 这里可以处理建议问题
|
||||
this.$emit('update-suggestions', jsonData.suggestions);
|
||||
break;
|
||||
|
||||
case 4: // 交互完成
|
||||
aiMessage.status = 4
|
||||
|
||||
// 从响应中获取并保存conversationId
|
||||
this.$emit('loading', false);
|
||||
// 检查文本是否已经完全显示,如果是则设置textCompleted为true
|
||||
if (isTextDisplayCompleted(aiMessage, accumulatedContent)) {
|
||||
// aiMessage.textCompleted = true;
|
||||
this.$emit('update-message', aiMessage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析SSE数据错误:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 继续读取
|
||||
read();
|
||||
}).catch(error => {
|
||||
console.error('SSE连接错误:', error);
|
||||
// 出错时也设置文字处理完成状态
|
||||
if (typingTimer) {
|
||||
clearInterval(typingTimer);
|
||||
typingTimer = null;
|
||||
}
|
||||
aiMessage.textCompleted = true;
|
||||
this.$emit('loading', false);
|
||||
aiMessage.text = '抱歉,网络连接出现问题,请稍后重试。';
|
||||
// 更新父组件的messageList
|
||||
this.$emit('update-message', aiMessage);
|
||||
});
|
||||
};
|
||||
|
||||
// 开始读取数据
|
||||
read();
|
||||
}).catch(error => {
|
||||
console.error('请求失败:', error);
|
||||
// 出错时也设置文字处理完成状态
|
||||
aiMessage.textCompleted = true;
|
||||
this.$emit('loading', false);
|
||||
aiMessage.text = '抱歉,网络连接出现问题,请稍后重试。';
|
||||
// 更新父组件的messageList
|
||||
this.$emit('update-message', aiMessage);
|
||||
});
|
||||
},
|
||||
handleNewConversation() {
|
||||
this.$emit('new-conversation')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.input-area {
|
||||
background-color: white;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 8px;
|
||||
padding: 5px 16px 10px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.input-placeholder {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
border: none;
|
||||
|
||||
::v-deep .el-input__inner {
|
||||
border: none;
|
||||
padding: 0;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
|
||||
.start-btn {
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
color: #409eff;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
font-size: 18px;
|
||||
color: #409eff;
|
||||
padding: 6px;
|
||||
|
||||
&[disabled] {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
12
src/views/portal/case/components/u762.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="750px" height="850px" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<radialGradient cx="362.789473684209" cy="413.96491228069874" r="1153.015055438179" gradientTransform="matrix(0.023310357358899587 0.999728276703125 -0.9997282767031253 0.02331035735889959 768.1851497765263 41.62434690904212 )" gradientUnits="userSpaceOnUse" id="RadialGradient4">
|
||||
<stop id="Stop5" stop-color="#ffffff" offset="0" />
|
||||
<stop id="Stop6" stop-color="#d4def7" offset="1" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<g>
|
||||
<path d="M 0 5.000000000000001 A 5 5 0 0 1 4.999999999999999 0 L 745 0 A 5 5 0 0 1 750 5 L 750 845 A 5 5 0 0 1 745 850 L 5 850 A 5 5 0 0 1 0 845 L 0 5 Z " fill-rule="nonzero" fill="url(#RadialGradient4)" stroke="none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 858 B |
1
src/views/portal/case/components/user.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1759026139840" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5676" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25"><path d="M512 74.666667C270.933333 74.666667 74.666667 270.933333 74.666667 512S270.933333 949.333333 512 949.333333 949.333333 753.066667 949.333333 512 753.066667 74.666667 512 74.666667zM288 810.666667c0-123.733333 100.266667-224 224-224S736 686.933333 736 810.666667c-61.866667 46.933333-140.8 74.666667-224 74.666666s-162.133333-27.733333-224-74.666666z m128-384c0-53.333333 42.666667-96 96-96s96 42.666667 96 96-42.666667 96-96 96-96-42.666667-96-96z m377.6 328.533333c-19.2-96-85.333333-174.933333-174.933333-211.2 32-29.866667 51.2-70.4 51.2-117.333333 0-87.466667-72.533333-160-160-160s-160 72.533333-160 160c0 46.933333 19.2 87.466667 51.2 117.333333-89.6 36.266667-155.733333 115.2-174.933334 211.2-55.466667-66.133333-91.733333-149.333333-91.733333-243.2 0-204.8 168.533333-373.333333 373.333333-373.333333S885.333333 307.2 885.333333 512c0 93.866667-34.133333 177.066667-91.733333 243.2z" fill="#666666" p-id="5677"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -35,7 +35,7 @@
|
||||
<!-- <div><span style="font-size:20px;color:#ff8e00">{{courseInfo.score ? courseInfo.score.toFixed(1) : 0}}</span><span style="font-size:12px;color:#ff8e00">分</span></div> -->
|
||||
</div>
|
||||
<div class="label-div">
|
||||
<!-- <el-tag class="label-item" effect="plain" v-for="(item,tagIdx) in tagArray" :key="tagIdx">{{item}}</el-tag>-->
|
||||
<el-tag class="label-item" effect="plain" v-for="(item,tagIdx) in tagArray" :key="tagIdx">{{item}}</el-tag>
|
||||
</div>
|
||||
<!-- <div style="width:160px;height:50px"> -->
|
||||
<!-- </div> -->
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
:disabled="!twoList.children.length" :open-delay="0" :close-delay="0" trigger="hover"
|
||||
:visible-arrow="false" @hide="leaveIndex" @show="changeIndex(twoList.id)" transition="none">
|
||||
<div class="course-two-content" slot="reference">{{
|
||||
twoList.name }}</div>-
|
||||
twoList.name }}</div>
|
||||
<!-- 内容 -->
|
||||
<div class="course-three-box">
|
||||
<div class="course-three-box-title">
|
||||
@@ -284,40 +284,32 @@
|
||||
<!-- 内容导航 -->
|
||||
<div class="topNav" v-if="!newData">
|
||||
<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>
|
||||
<span :class="ctypeTagAll ? 'nav-bottbor' : ''"></span>
|
||||
</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 }">
|
||||
<a>录播课</a>
|
||||
<span :class="ctypeList[0].checked ? 'nav-bottbor' : ''"></span>
|
||||
</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 }">
|
||||
<a>线下课</a>
|
||||
<span :class="ctypeList[1].checked ? 'nav-bottbor' : ''"></span>
|
||||
</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 }">
|
||||
<a>学习项目</a>
|
||||
<span :class="ctypeList[2].checked ? 'nav-bottbor' : ''"></span>
|
||||
</div>
|
||||
<a class="option-item">
|
||||
<span @click="uClassClick" class="Uxtext" style="font-weight: bold"> U选小课堂
|
||||
<span @click="uClassClick" class="Uxtext" style=""> U选小课堂
|
||||
<span class="uxicon">
|
||||
<svg-icon icon-class="hot" style="font-size:22px"></svg-icon>
|
||||
</span>
|
||||
</span>
|
||||
</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.tagName}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="fixd-box" class="upload" style="margin-left: 26px;">
|
||||
<div v-if="identity == 2 || identity == 3 || identity == 5">
|
||||
@@ -333,9 +325,9 @@
|
||||
<div v-if="stagList.length > 0 && !newData" class="search-div" style="padding: 0;margin-bottom: 20px;">
|
||||
<div class="searchbar" style="background-color:#f6f7fb;display: flex;justify-content: space-between;">
|
||||
<div style="line-height: 30px;">
|
||||
<span class="item-title"> 搜索条件:</span>
|
||||
<span class="item-title"> 搜索条件</span>
|
||||
<el-tag closable v-for="(tag, tagIdx) in stagList" :key="'t' + tagIdx" @close="stagClose(tag, tagIdx)">{{
|
||||
tag.tagName }}</el-tag>
|
||||
tag.name }}</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<el-button type="primary" size="mini" @click="handleClearTags">清除</el-button>
|
||||
@@ -494,32 +486,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
</template>
|
||||
@@ -541,14 +507,12 @@ import apiTeacher from "@/api/modules/teacher.js";
|
||||
import apiUser from "@/api/system/user.js";
|
||||
import scene from "@/api/modules/scene.js";
|
||||
import apiUserbasic from "@/api/boe/userbasic.js";
|
||||
import apiManage from '@/api/manage/manage.js';
|
||||
import interactBar from "@/components/Portal/interactBar.vue";
|
||||
import courseImage from "@/components/Course/courseImage.vue";
|
||||
import { courseType, getType, toScore, formatDate, formatUserNumber, formatDateByFmt } from "@/utils/tools.js";
|
||||
import { deepClone, param } from "../../../utils";
|
||||
import apiSearchterm from "@/api/modules/searchterm.js";
|
||||
import apiPlace from "@/api/phase2/place.js"
|
||||
import apiCourseTag from '@/api/modules/courseTag.js'
|
||||
export default {
|
||||
name: "index",
|
||||
components: {
|
||||
@@ -570,43 +534,21 @@ export default {
|
||||
},
|
||||
stagList() { //计算出选择的内容
|
||||
let list = [];
|
||||
|
||||
// 关键词
|
||||
if (this.keyword) {
|
||||
list.push({
|
||||
type: 0,
|
||||
id: 'keyword',
|
||||
name: this.keyword,
|
||||
tagName: this.keyword,
|
||||
checked: true
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// 课程类型
|
||||
this.ctypeList.forEach(item => {
|
||||
if (item.checked) {
|
||||
list.push({
|
||||
...item,
|
||||
tagName: item.name
|
||||
});
|
||||
list.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// 热点标签 - 这是关键修复
|
||||
this.hotTagsList.forEach(item => {
|
||||
if (item.checked) {
|
||||
list.push({
|
||||
...item,
|
||||
name: item.tagName || item.name,
|
||||
tagName: item.tagName || item.name,
|
||||
type: 14
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 三级分类
|
||||
this.oneList.forEach(one => {
|
||||
var twoChildChecked = false;
|
||||
var twoChildChecked = false;//是否有下级
|
||||
one.children.forEach(two => {
|
||||
if (two.checked) {
|
||||
twoChildChecked = true;
|
||||
@@ -614,28 +556,34 @@ export default {
|
||||
var threeChildChecked = false;
|
||||
two.children.forEach(three => {
|
||||
if (three.checked) {
|
||||
list.push({
|
||||
...three,
|
||||
tagName: three.name
|
||||
});
|
||||
list.push(three);
|
||||
threeChildChecked = true;
|
||||
}
|
||||
});
|
||||
if (two.checked && !threeChildChecked) {
|
||||
list.push({
|
||||
...two,
|
||||
tagName: two.name
|
||||
});
|
||||
list.push(two);
|
||||
}
|
||||
});
|
||||
if (one.checked && !twoChildChecked) {
|
||||
list.push({
|
||||
...one,
|
||||
tagName: one.name
|
||||
});
|
||||
list.push(one);
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
// this.oneList.forEach(item=>{
|
||||
// if(item.checked){
|
||||
// list.push(item);
|
||||
// }
|
||||
// });
|
||||
// this.twoList.forEach(item=>{
|
||||
// if(item.checked){
|
||||
// list.push(item);
|
||||
// }
|
||||
// });
|
||||
// this.threeList.forEach(item=>{
|
||||
// if(item.checked){
|
||||
// list.push(item);
|
||||
// }
|
||||
// });
|
||||
//console.log(list,'list');
|
||||
return list;
|
||||
},
|
||||
ctypeTagAll() {
|
||||
@@ -665,14 +613,12 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hotTagsList: [],
|
||||
newData: false,//线上品牌系列隐藏
|
||||
navTitle: [],
|
||||
// 设置高亮
|
||||
twoId: '',
|
||||
count: 0,//分页总条条数
|
||||
showUClass: false,
|
||||
projectDialogVisible: false,
|
||||
ctypeList: [
|
||||
{ type: 1, id: 20, name: '录播课', checked: false },
|
||||
{ type: 1, id: 30, name: '线下课', checked: false },
|
||||
@@ -683,7 +629,7 @@ export default {
|
||||
twoList: [], //二级分类{type:12}
|
||||
threeList: [],//三级分类{type:13}
|
||||
searching: false,//是否正在搜索中
|
||||
studentInfo: {},
|
||||
|
||||
resonimg: {},
|
||||
formatDate,
|
||||
formatNum: formatUserNumber,
|
||||
@@ -741,17 +687,6 @@ export default {
|
||||
console.log(rs.message);
|
||||
}
|
||||
})
|
||||
//初始化:获取最新前10个热点标签
|
||||
apiCourseTag.getHotTagList(null).then(rs => {
|
||||
if (rs.status == 200) {
|
||||
this.hotTagsList = rs.result.map(tag => ({
|
||||
...tag,
|
||||
checked: false
|
||||
}));
|
||||
} else {
|
||||
console.log(rs.message);
|
||||
}
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
let screenWidth = window.screen.availWidth;
|
||||
@@ -834,24 +769,6 @@ export default {
|
||||
// window.removeEventListener("scroll", this.handleScroll);
|
||||
},
|
||||
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) {
|
||||
this.course.pageIndex = val
|
||||
@@ -935,54 +852,10 @@ export default {
|
||||
//搜索条件
|
||||
stagClose(tag, tagIndex) {
|
||||
tag.checked = false;
|
||||
|
||||
// 根据标签类型处理不同的清除逻辑
|
||||
if (tag.type == 0) {
|
||||
// 关键词类型
|
||||
this.keyword = '';
|
||||
} else if (tag.type == 1) {
|
||||
// 课程类型(录播课、线下课、学习项目)
|
||||
this.ctypeList.forEach(item => {
|
||||
if (item.id == tag.id) {
|
||||
item.checked = false;
|
||||
}
|
||||
});
|
||||
} else if (tag.type == 14) {
|
||||
// 热点标签类型
|
||||
this.hotTagsList.forEach(item => {
|
||||
if (item.id == tag.id) {
|
||||
item.checked = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 更新course.tags,移除被删除的热点标签
|
||||
const checkedHotTags = this.hotTagsList.filter(tag => tag.checked);
|
||||
let tagIds = checkedHotTags.map(tag => tag.id).join(',');
|
||||
this.course.tags = tagIds;
|
||||
|
||||
} else if (tag.type == 11 || tag.type == 12 || tag.type == 13) {
|
||||
// 三级分类标签
|
||||
this.oneList.forEach(one => {
|
||||
if (one.id == tag.id) {
|
||||
one.checked = false;
|
||||
}
|
||||
one.children.forEach(two => {
|
||||
if (two.id == tag.id) {
|
||||
two.checked = false;
|
||||
}
|
||||
two.children.forEach(three => {
|
||||
if (three.id == tag.id) {
|
||||
three.checked = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 重置导航标题
|
||||
this.navTitle = [];
|
||||
|
||||
// 触发搜索更新
|
||||
this.navTitle = []
|
||||
this.searchData();
|
||||
},
|
||||
|
||||
@@ -1026,25 +899,20 @@ handleClearTags() {
|
||||
this.ctypeList.forEach(item => {
|
||||
item.checked = false;
|
||||
});
|
||||
this.hotTagsList.forEach(item => {
|
||||
item.checked = false;
|
||||
});
|
||||
this.course.tags = ''; // 清空标签ID
|
||||
|
||||
// 添加清除三级分类的逻辑
|
||||
this.oneList.forEach(one => {
|
||||
one.checked = false;
|
||||
one.children.forEach(two => {
|
||||
two.checked = false;
|
||||
two.children.forEach(three => {
|
||||
three.checked = false;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 清空导航标题
|
||||
this.twoList = [];
|
||||
this.threeList = [];
|
||||
this.navTitle = [];
|
||||
|
||||
this.newData = false;
|
||||
sessionStorage.removeItem(this.localSessionKey)
|
||||
this.searchData();
|
||||
},
|
||||
// 导航切换(录播课,线下课,学习项目)
|
||||
@@ -1058,24 +926,11 @@ handleClearTags() {
|
||||
|
||||
this.searchData();
|
||||
},
|
||||
//点击标签
|
||||
handleTagClick(item, list) {
|
||||
item.checked = !item.checked;
|
||||
|
||||
// 更新course.tags
|
||||
const checkedTags = this.hotTagsList.filter(tag => tag.checked);
|
||||
let tagIds = checkedTags.map(tag => tag.id).join(',');
|
||||
this.course.tags = tagIds;
|
||||
|
||||
// 强制触发stagList重新计算
|
||||
this.$nextTick(() => {
|
||||
this.searchData();
|
||||
});
|
||||
},
|
||||
//三级分类
|
||||
handleOptionClick(item, level, list) {
|
||||
// 线上品牌展示效果
|
||||
this.newData = item.newData;
|
||||
console.log(this.newData);
|
||||
// 单选,排除法
|
||||
this.oneList.forEach(one => {
|
||||
one.checked = false;
|
||||
@@ -1361,34 +1216,10 @@ handleClearTags() {
|
||||
let params = encodeURIComponent('courseId=' + courseId);
|
||||
this.$router.push('/forward?to=' + manageApi + '/stu/project/redirectDetail¶ms=' + params);
|
||||
} 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);
|
||||
this.$router.push('/forward?to=' + studentPath + '/projectdetails¶ms=' + params);
|
||||
//this.$router.push('/forward?to='+manageApi+'/stu/project/redirectDetail¶ms='+params);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item.type == 10) {
|
||||
//return this.webBaseUrl + "/course/studyindex?id=" + item.id;
|
||||
@@ -1476,18 +1307,12 @@ handleClearTags() {
|
||||
},
|
||||
getAllChecked() { //获取全部选中的标签
|
||||
let list = [];
|
||||
//获取选中的课程类型
|
||||
|
||||
this.ctypeList.forEach(item => {
|
||||
if (item.checked) {
|
||||
list.push(item);
|
||||
}
|
||||
});
|
||||
//获取选中的热点标签
|
||||
this.hotTagsList.forEach(item => {
|
||||
if (item.checked) {
|
||||
list.push(item);
|
||||
}
|
||||
});
|
||||
this.oneList.forEach(one => {
|
||||
one.children.forEach(two => {
|
||||
two.children.forEach(three => {
|
||||
@@ -1550,18 +1375,7 @@ handleClearTags() {
|
||||
that.course.sysType3 += item.id;
|
||||
}
|
||||
});
|
||||
apiCourseTag.getHotTagList(that.course).then(rs => {
|
||||
if (rs.status == 200) {
|
||||
// 保留已选中标签的状态
|
||||
const currentCheckedTags = this.hotTagsList.filter(tag => tag.checked);
|
||||
this.hotTagsList = rs.result.map(tag => ({
|
||||
...tag,
|
||||
checked: currentCheckedTags.some(checkedTag => checkedTag.id === tag.id)
|
||||
}));
|
||||
} else {
|
||||
console.log(rs.message);
|
||||
}
|
||||
}),
|
||||
|
||||
this.isFind = true;
|
||||
this.course.device = 1;
|
||||
if (this.course.pageIndex == 1) {
|
||||
@@ -2607,73 +2421,4 @@ handleClearTags() {
|
||||
|
||||
.option-active {
|
||||
color: #387DF7;
|
||||
}
|
||||
/* 项目简介 方法一:外部 CSS 类 */
|
||||
::v-deep.el-dialog {
|
||||
border-radius: 3% 3% 1% 1%;
|
||||
padding: 0;
|
||||
}
|
||||
::v-deep.custom-class .el-dialog__header {
|
||||
height: 100px;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
background-image: url('../../../assets/images/project/title-bg.png');
|
||||
background-size: 100% 100%; /* 完全填充 */
|
||||
display: block; /* 避免行内元素空隙 */
|
||||
}
|
||||
::v-deep.custom-class .el-dialog__header .el-dialog__title {
|
||||
padding: 0 !important;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
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;
|
||||
/* 过渡效果,使颜色变化更平滑 */
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
/* 鼠标悬停效果 */
|
||||
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 class="hyper-link" v-if="conLink.openType==2">
|
||||
<div class="hyper-link-row">课程内容是外部连接</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 class="hyper-link-row">{{conLink.url}}</div>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
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>
|
||||
<div style="cursor: pointer; text-align: right;cursor: pointer;" v-if="qa.images && qa.images!==''" @click="jumpDetail(qa)">
|
||||
<img style="width: 156px;height: 105px;border-radius: 4px;margin-left: 18px;" :src="fileBaseUrl + qa.images" alt="图片貌似被外星人劫走了">
|
||||
<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="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -349,7 +349,6 @@ export default {
|
||||
this.$message.success('删除成功');
|
||||
this.queryData.pageIndex = 1;
|
||||
this.queryMessage(true);
|
||||
this.$store.dispatch('refrashMsg');
|
||||
} else {
|
||||
this.$message.error('删除失败' + res.message);
|
||||
}
|
||||
@@ -367,7 +366,6 @@ export default {
|
||||
this.$message.success('删除成功');
|
||||
this.queryData.pageIndex = 1;
|
||||
this.queryMessage(true);
|
||||
this.$store.dispatch('refrashMsg');
|
||||
} else {
|
||||
this.$message.error('删除失败' + res.message);
|
||||
}
|
||||
|
||||
@@ -306,8 +306,8 @@ export default {
|
||||
|
||||
},
|
||||
viewTopic(data) {
|
||||
window.open(this.webBaseUrl+'/qa/answer?id='+data.id, '_blank');
|
||||
// this.$router.push({path:'/qa/answer',query:{id:data.id}})
|
||||
// window.open(this.webBaseUrl+'/qa/answer?id='+data.id, '_blank');
|
||||
this.$router.push({path:'/qa/answer',query:{id:data.id}})
|
||||
},
|
||||
aduit(row) {
|
||||
this.form={...row};
|
||||
|
||||
@@ -140,7 +140,6 @@ export default {
|
||||
headers:{token:getToken(),}
|
||||
}).then((res) => {
|
||||
console.log('111',res.data.result)
|
||||
console.log('111 gx2',res.data.result)
|
||||
// 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.project=Math.floor(res.data.result.project.total === 0 ? 0: (res.data.result.project.completion/res.data.result.project.total)*100)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<div class="course-playbox" ref="coursePlayerBox" id="id_course_player_box">
|
||||
<div class="course-player" ref="coursePlayer" id="id_course_player">
|
||||
<div>
|
||||
<div v-if="renderCourse">
|
||||
<div v-if="resType == null || resType == 0">
|
||||
<!--先显示视频图片-->
|
||||
<course-image v-if="courseInfo.id != ''" :course="courseInfo"></course-image>
|
||||
@@ -91,16 +92,8 @@
|
||||
<div v-if="resType == 52">
|
||||
<div v-if="contentData.content != ''">
|
||||
<div class="hyper-link" v-if="conLink.openType == 2">
|
||||
<div class="hyper-link-row">外链名称: {{ contentData.contentName }}</div>
|
||||
<!-- <button class="copy-button" @click="copyUrl(conLink.url)">复制外链</button>-->
|
||||
<!-- <div class="hyper-link-row">外链地址: {{ conLink.url }}</div>-->
|
||||
<!-- <button class="copy-button" @click="copyUrl(conLink.url)">复制外链</button>-->
|
||||
<div class="hyper-link-url-container">
|
||||
<!-- <span class="hyper-link-url" @click="copyUrl(conLink.url)" >外链地址: {{ conLink.url }}</span>-->
|
||||
<div class="hyper-link-url">
|
||||
<el-button @click="widthOpen(conLink.url)" type="primary" style="margin-left: 15px">点击前往</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hyper-link-row">{{ contentData.contentName }}</div>
|
||||
<div class="hyper-link-row">{{ conLink.url }}</div>
|
||||
</div>
|
||||
<div v-if="conLink.openType == 1"><iframe :src="conLink.url"
|
||||
style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe></div>
|
||||
@@ -117,6 +110,15 @@
|
||||
</assess>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!renderCourse && Internet ==2" style="margin:350px 250px" class="jianjie pdftext" id="pdfPreview">
|
||||
<div style="margin-top:40px;font-weight:700;font-size: 22px;color: #ccc">
|
||||
<span>十分抱歉,您当前的网络环境不符合观看要求。为了保障课程信息的安全,您需要接入公司内网才能观看。</span>
|
||||
</div>
|
||||
<div style="margin-top:20px;text-align:center" @click="refreshPage">
|
||||
<el-button type="primary">重新检测</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--交互部分-->
|
||||
<div>
|
||||
<div class="course-interact">
|
||||
@@ -167,13 +169,13 @@
|
||||
<div class="course-control">
|
||||
<div class="control-tab" v-if="contentList.length>0" >
|
||||
<div v-if="contentList.length>1" @click="heartabone" :class="tab == 1 ? 'control-tab-active' : ' '">
|
||||
<i class="el-icon-reading" style="margin-right:9px;margin-left:9px"></i>
|
||||
<i class="el-icon-reading" style="margin-right:9px;margin-left:9px"></i>课程单元
|
||||
</div>
|
||||
<div @click="heartabtwo" :class="tab == 2 ? 'control-tab-active' : ' '">
|
||||
<i class="el-icon-edit" style="margin-right:9px;margin-left:9px"></i>我的笔记
|
||||
</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<!-- 课程单元 -->
|
||||
<div class="course-units" v-if="tab == 1">
|
||||
<div style="min-height: 350px;max-height: 650px ;overflow-y: auto;">
|
||||
<div class="catalog" v-if="courseInfo.type == 20">
|
||||
@@ -285,18 +287,15 @@
|
||||
<div class="teacher" v-for="(item, idx) in teachers" :key="idx">
|
||||
<div class="teacher-avator" @click="toUserHome(item)" title="点击进入他的主页">
|
||||
<!-- <div class="teacher-text" v-if="item.authorInfo.avatar == ''">{{userAvatarText(item.teacherName)}}</div> -->
|
||||
<div v-if="item.authorInfo && item.authorInfo.avatar">
|
||||
<div v-if="item.authorInfo.avatar !== ''">
|
||||
<el-avatar :src="fileBaseUrl + item.authorInfo.avatar" shape="circle" :size="50"></el-avatar>
|
||||
</div>
|
||||
<div v-else-if="item.photo">
|
||||
<el-avatar :src="item.photo" shape="circle" :size="50"></el-avatar>
|
||||
</div>
|
||||
<div v-else class="teacher-text">
|
||||
<div v-if="item.authorInfo && item.authorInfo.sex === 1"><img src="../../../public/images/Avatarman.png" alt=""></div>
|
||||
<div v-if="item.authorInfo.sex === 1 "><img src="../../../public/images/Avatarman.png" alt=""></div>
|
||||
<div v-else><img src="../../../public/images/Avatarwoman.png" alt=""></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="teacher-info" @click="toUserHome(item)" title="点击进入他的主页">
|
||||
<div class="teacher-info">
|
||||
<div class="teacher-name">
|
||||
<span> {{ item.teacherName }}</span>
|
||||
<!-- <span style="font-size: 12px; color:#666666 ;">( {{cutOrgNamePath(item.authorInfo.orgInfo)}} )</span> -->
|
||||
@@ -314,6 +313,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog class="protocol" :close-on-click-modal="false" :visible="protocolDialogVisible" width="30%"
|
||||
:show-close="false">
|
||||
<div class="protocol-title">{{warnTitle}}</div>
|
||||
<div class="protocol-content">
|
||||
  {{warn}}
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="protocolDialogVisible = false">确
|
||||
定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<!-- <div><portal-footer></portal-footer></div> -->
|
||||
</div>
|
||||
</template>
|
||||
@@ -380,6 +390,7 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
protocolDialogVisible: false,
|
||||
tentative: false,
|
||||
isContentTypeTwo: null,
|
||||
isContentType: null,
|
||||
@@ -401,6 +412,7 @@
|
||||
curCFile: {
|
||||
converStatus: 4,
|
||||
},
|
||||
Internet: 3,//1是成功 2是是失败 3是检测中
|
||||
radio: '',
|
||||
interactRuning: false,
|
||||
playerBoxShow: false,
|
||||
@@ -442,6 +454,7 @@
|
||||
getType: getType,
|
||||
ctabName: 'catalog',
|
||||
resType: null,
|
||||
renderCourse: true,
|
||||
activeNames: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
scoreInfo: {
|
||||
dlgShow: false,
|
||||
@@ -465,9 +478,12 @@
|
||||
cumulativeDuration:0, //非音频累计时长
|
||||
maxDuration:0, //非音频最大时长
|
||||
defaultMaxTime:1800, //非音频默认最大时间
|
||||
warn:"测试内容",
|
||||
warnTitle:"测试标题",
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getInternet();
|
||||
// 增加的用户受众id
|
||||
let localKey = "user_" + this.userInfo.sysId + "_gids";
|
||||
let hasIds = sessionStorage.getItem(localKey);
|
||||
@@ -515,10 +531,6 @@
|
||||
return treeList;
|
||||
}
|
||||
},
|
||||
destroyed(){
|
||||
this.cleanAppendTime();
|
||||
this.stopStudyTime();
|
||||
},
|
||||
methods: {
|
||||
handleOpen(key,path){
|
||||
if(this.isFalse){
|
||||
@@ -717,7 +729,6 @@
|
||||
configUrl=urlPre+configUrl.substring(configUrl.indexOf(':')+1);
|
||||
|
||||
this.scormUrl=configUrl+pars;//播放的首页
|
||||
console.log('scormUrl',this.scormUrl);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1312,6 +1323,17 @@
|
||||
audiences:this.audiences
|
||||
}).then(rs => {
|
||||
if (rs.status == 200) {
|
||||
if(rs.result.isPermission){
|
||||
this.protocolDialogVisible=true
|
||||
}
|
||||
if (!rs.result.isPermission || (rs.result.isPermission && this.Internet==1)){
|
||||
// this.getInternet()
|
||||
this.renderCourse = true
|
||||
}else{
|
||||
// this.Internet=1;
|
||||
this.renderCourse = false
|
||||
this.protocolDialogVisible=true
|
||||
}
|
||||
if(rs.result.contents.length==0){
|
||||
$this.$message.error('课程内容已删除或课程已不再使用');
|
||||
return;
|
||||
@@ -1370,7 +1392,8 @@
|
||||
}
|
||||
}
|
||||
this.courseInfo = rs.result.course;
|
||||
|
||||
this.warn = rs.result.warn;
|
||||
this.warnTitle = rs.result.warnTitle;
|
||||
if (rs.result.teachers && rs.result.teachers.length > 0) {
|
||||
let userIds = [];
|
||||
let ctoUsers = [];
|
||||
@@ -1399,12 +1422,53 @@
|
||||
this.totalContent = rs.result.contents.length;
|
||||
//加载学习的数据
|
||||
this.loadStudyData(rs.result);
|
||||
|
||||
} else {
|
||||
this.$message.error(rs.message);
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
refreshPage() {
|
||||
location.reload();
|
||||
// this.getInternet();
|
||||
// this.loadData();
|
||||
},
|
||||
getXmlHttpRequest() {
|
||||
if (window.XMLHttpRequest) {
|
||||
return new XMLHttpRequest();
|
||||
}
|
||||
else if (window.ActiveXObject) {
|
||||
return new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
},
|
||||
// 检测是否为内网
|
||||
getInternet() {
|
||||
this.Internet = 3;
|
||||
let $this = this;
|
||||
let xmlhttp = this.getXmlHttpRequest();
|
||||
let timedOut = false;
|
||||
let timer = setTimeout(function () {
|
||||
timedOut = true;
|
||||
xmlhttp.abort();
|
||||
}, 1000);
|
||||
xmlhttp.open("HEAD", window.location.protocol + "//uapi.boe.com.cn/500.html", true);
|
||||
xmlhttp.send();
|
||||
xmlhttp.onreadystatechange = function () {
|
||||
if (xmlhttp.readyState == 4) {
|
||||
if (xmlhttp.status == 200) {
|
||||
clearTimeout(timer);
|
||||
$this.Internet = 1;
|
||||
} else {
|
||||
clearTimeout(timer);
|
||||
// $this.protocolDialogVisible=true
|
||||
$this.Internet = 2;
|
||||
}
|
||||
} else {
|
||||
if (timedOut) return;//忽略中止请求
|
||||
clearTimeout(timer);//取消等待的超时
|
||||
}
|
||||
}
|
||||
},
|
||||
loadStudyData(result) {
|
||||
let $this=this;
|
||||
this.loadScorePraiseAndTrample();
|
||||
@@ -1696,21 +1760,11 @@
|
||||
this.trueFalse = false
|
||||
}
|
||||
},
|
||||
copyUrl(currentUrl) {
|
||||
const urlToCopy = currentUrl;
|
||||
|
||||
navigator.clipboard.writeText(urlToCopy)
|
||||
.then(() => {
|
||||
this.$message.success('链接已成功复制到剪贴板');
|
||||
})
|
||||
.catch(err => {
|
||||
this.$message.error('复制失败,请手动复制:' + urlToCopy);
|
||||
console.error('复制错误:', err);
|
||||
});
|
||||
},
|
||||
destroyed(){
|
||||
this.cleanAppendTime();
|
||||
this.stopStudyTime();
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1763,6 +1817,7 @@
|
||||
height: 80%;
|
||||
border: 1px solid #ffffff;
|
||||
padding-right: 20px;
|
||||
background-color: rgb(238, 238, 238);
|
||||
// overflow: auto;
|
||||
}
|
||||
.course-control{ //内容控制区域
|
||||
@@ -2052,7 +2107,7 @@
|
||||
|
||||
.course-interact {
|
||||
flex: 1; // 20%高度
|
||||
min-height: 54px;
|
||||
height: 54px;
|
||||
// padding-top: 10px;
|
||||
// padding-right: 10px;
|
||||
padding: 0 20px;
|
||||
@@ -2415,29 +2470,18 @@
|
||||
height: 200px;
|
||||
background: url('../../../public/images/couresdetail.png');
|
||||
}
|
||||
.copy-button {
|
||||
background-color: #409EFF;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
|
||||
.protocol {
|
||||
.protocol-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.copy-button:hover {
|
||||
background-color: #66b1ff;
|
||||
.protocol-content {
|
||||
font-size: 14px;
|
||||
line-height: 25px;
|
||||
}
|
||||
.hyper-link-url-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.hyper-link-url {
|
||||
max-width: calc(100% - 80px); /* 留出按钮空间 */
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -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>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<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="months">本月</el-dropdown-item>
|
||||
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
||||
@@ -33,10 +33,10 @@
|
||||
</div>
|
||||
<div class="myselftext">
|
||||
<div class="myranking">
|
||||
{{isNow ? '当前年' : '累计'}}排名 : <span> {{currentUserRankingTotalData.rankNo}}</span>
|
||||
{{isNow ? '当前' : '累计'}}排名 : <span> {{currentUserRankingTotalData.rankNo}}</span>
|
||||
</div>
|
||||
<div class="myexperience">
|
||||
{{isNow ? '当前年' : '累计'}}经验值 : <span>{{currentUserRankingTotalData.rankValue}}</span>
|
||||
{{isNow ? '当前' : '累计'}}经验值 : <span>{{currentUserRankingTotalData.rankValue}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<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="months">本月</el-dropdown-item>
|
||||
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
||||
@@ -127,10 +127,10 @@
|
||||
</div>
|
||||
<div class="myselftext">
|
||||
<div class="myranking">
|
||||
{{isStudyTime ? '当前年' : '累计'}}排名 : <span> {{learningDurationTotalData.rankNo}}</span>
|
||||
{{isStudyTime ? '当前' : '累计'}}排名 : <span> {{learningDurationTotalData.rankNo}}</span>
|
||||
</div>
|
||||
<div class="myexperience">
|
||||
{{isStudyTime ? '当前年' : '累计'}}学习时长: <span> {{formatSecondToHour(learningDurationTotalData.rankValue)}}</span> h
|
||||
{{isStudyTime ? '当前' : '累计'}}学习时长: <span> {{formatSecondToHour(learningDurationTotalData.rankValue)}}</span> h
|
||||
</div>
|
||||
</div>
|
||||
<div class="exp-table" style="margin-top:20px;">
|
||||
@@ -206,7 +206,7 @@
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<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="months">本月</el-dropdown-item>
|
||||
<el-dropdown-item command="years">本年</el-dropdown-item> -->
|
||||
@@ -216,10 +216,10 @@
|
||||
</div>
|
||||
<div class="myselftext">
|
||||
<div class="myranking">
|
||||
{{isStudyDay ? '当前年' : '累计'}}排名 : <span> {{learningDaysTotalData.rankNo}}</span>
|
||||
{{isStudyDay ? '当前' : '累计'}}排名 : <span> {{learningDaysTotalData.rankNo}}</span>
|
||||
</div>
|
||||
<div class="myexperience">
|
||||
{{isStudyDay ? '当前年' : '累计'}}学习天数 : <span>{{learningDaysTotalData.rankValue}}</span>
|
||||
{{isStudyDay ? '当前' : '累计'}}学习天数 : <span>{{learningDaysTotalData.rankValue}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="exp-table" style="margin-top:20px;">
|
||||
@@ -311,7 +311,7 @@ export default {
|
||||
formatSecondToHour:formatSecondToHour,
|
||||
experience:{
|
||||
field:'now',
|
||||
name:'当前年',
|
||||
name:'当前',
|
||||
data:{
|
||||
rankingNo:0,
|
||||
total:0
|
||||
@@ -320,7 +320,7 @@ export default {
|
||||
},
|
||||
learningDuration:{
|
||||
field:'now',
|
||||
name:'当前年',
|
||||
name:'当前',
|
||||
data:{
|
||||
rankingNo:0,
|
||||
total:0
|
||||
|
||||