Compare commits

..

6 Commits

72 changed files with 18421 additions and 15958 deletions

22046
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,6 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@mermaid-js/parser": "^0.6.3",
"axios": "^0.21.4",
"core-js": "^3.6.5",
"driver.js": "^0.9.8",
@@ -24,15 +23,9 @@
"element-ui": "^2.15.7",
"file-saver": "^2.0.5",
"fuse.js": "^6.4.6",
"highlight.js": "^11.11.1",
"image-conversion": "^2.1.1",
"jsencrypt": "^3.2.1",
"json-bigint": "^1.0.0",
"katex": "^0.16.25",
"markdown-it": "^14.1.0",
"markdown-it-highlightjs": "^4.2.0",
"markdown-it-mermaid": "^0.2.5",
"mermaid": "^8.13.10",
"mockjs": "^1.1.0",
"moment": "^2.29.1",
"nprogress": "^0.2.0",
@@ -50,7 +43,6 @@
"vue": "^2.6.11",
"vue-awesome-swiper": "^3.1.3",
"vue-cookies": "^1.7.4",
"vue-katex": "^0.5.0",
"vue-pdf": "^4.2.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.5.2",
@@ -68,7 +60,6 @@
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.1",
"less-loader": "^6.2.0",
"null-loader": "^4.0.1",
"sass": "^1.32.13",
"sass-loader": "^10.1.0",
"vue-template-compiler": "^2.6.11"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

View File

@@ -1,74 +1,25 @@
<template>
<div id="app" style="width: 100vw">
<div id="app">
<keep-alive :include="['case']">
<router-view />
12312
</keep-alive>
<!-- 添加AI Call组件 -->
<AICall
:dialogVisible="showAICall"
@close="onCloseAICall"
@restore="onRestoreAICall"
/>
</div>
</template>
<script>
import { mapGetters, mapState } from 'vuex';
import AICall from '@/views/portal/case/AICall.vue';
import { mapGetters } from 'vuex';
export default{
name: 'App',
components: {
AICall
},
computed: {
...mapGetters(['userInfo']),
...mapState('app', ['showAICall', 'showAICallMinimized'])
...mapGetters(['userInfo'])
},
methods: {
onCloseAICall() {
// 通过Vuex关闭AI Call组件
this.$store.dispatch('app/setShowAICall', false);
},
onRestoreAICall() {
// 通过Vuex显示AI Call组件
this.$store.dispatch('app/setShowAICall', true);
},
// 检查当前路由是否应该显示AI弹窗
checkRouteForAICall() {
const currentRoute = this.$route.name;
// 只在case或caseDetail路由显示弹窗
if (currentRoute === 'case' || currentRoute === 'caseDetail') {
// 设置最小化窗口显示状态为true
this.$store.dispatch('app/setShowAICallMinimized', true);
// 注意这里不再强制设置showAICall为true保留用户之前的操作状态
} else {
// 其他路由关闭弹窗
this.$store.dispatch('app/setShowAICall', false);
// 设置最小化窗口显示状态为false
this.$store.dispatch('app/setShowAICallMinimized', false);
}
}
},
mounted() {
mounted() {
//从状态值中取,因为登录处理所以移动watch中
// console.log(this.userInfo);
// if(this.userInfo && this.userInfo.name!=''){
// this.$watermark.set(this.userInfo.name+this.userInfo.loginName);
// }
// 初始化检查路由
this.checkRouteForAICall();
},
watch: {
// 监听路由变化
$route(to, from) {
this.checkRouteForAICall();
}
}
// watch:{
// userInfo(newVal,oldVal){
// if(newVal && newVal.name!=''){
@@ -88,3 +39,4 @@
box-shadow: 0px 1px 5px 1px rgba(92,98,111,.3);
}
</style>

View File

@@ -1,30 +0,0 @@
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')
}

View File

@@ -103,14 +103,6 @@ const getUsersByIds = function(ids) {
return ajax.postJson(baseURL,'/user/getUserMessageToDai',ids);
}
/**
* 根据关键字检索用户(创建人下拉)
* @param {string} keyword
*/
const selectUser = function(keyword = '') {
return ajax.postJson(baseURL,'/user/selectuser',{ keyword });
}
export default {
userParentOrg,
findOrgsByKeyword,
@@ -124,6 +116,5 @@ export default {
getInAudienceIds,
getUsersByIds,
updateUser,
logout,
selectUser
logout
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@ const pageList = function(data) {
/**
* 选择课件的查询,这里也是分页查询,只是返回的内容,字段会很少,用于课件制作那选择已有课件内容。
*
*
* @param {Object} data
* 查询参数如上面pageList方法
*/
@@ -47,9 +47,7 @@ const findList = function(data) {
}
*/
const saveUpload = function(data) {
return ajax.post('/xboe/m/course/file/upload/save', data, {
timeout: 60000
});
return ajax.post('/xboe/m/course/file/upload/save', data);
}
/**
@@ -90,4 +88,4 @@ export default {
batchUpdate,
detail,
delFile
}
}

View File

@@ -102,24 +102,6 @@ const courseSearch=function(query){
const detailStudy = function(courseId,aid) {
return ajax.get(`/xboe/m/course/portal/detail-study?courseId=${courseId}&aid=${aid}`);
}
/**
* 课程学习进度的详细信息-分页
* @param {Object} data
*/
const detailStudyPage = function(data) {
return ajax.get(`/xboe/m/course/portal/detail-study-page?courseId=${data.courseId}&aid=${data.aid}&pageIndex=${data.pageIndex}&pageSize=${data.pageSize}`);
}
/**
* 资源学习情况列列表-分页
* @param {Object} data
*/
const pageListResource=function(data){
return ajax.post('/xboe/school/study/course/pagelist-resource',data);
}
export default {
list,
pageList,
@@ -130,7 +112,5 @@ export default {
studyCounts,
courseSearch,
detailStudy,
detailPost,
detailStudyPage,
pageListResource
detailPost
}

View File

@@ -165,7 +165,7 @@ const appendStudyTime = function(data) {
* name: 学习人的姓名
*/
const studyRecords = function(data) {
return ajax.post('/xboe/school/study/course/pagelistEx',data);
return ajax.post('/xboe/school/study/course/pagelist',data);
}
/**
@@ -189,7 +189,7 @@ const studyContentRecords = function(data) {
}
*/
const studyExport = function(data) {
return ajax.post('/xboe/school/study/course/export',data, { responseType: 'blob' });
return ajax.post('/xboe/school/study/course/export',data);
}
/**
@@ -402,31 +402,6 @@ const findByIds=function (ids){
return ajax.postJson('/xboe/school/study/es/list-by-ids',ids);
}
const exportSignup=function (data){
return ajax.post('/xboe/school/study/course/export-signup',data, { responseType: 'blob' });
}
// 作业导出
const exportHomework=function (data){
return ajax.post('/xboe/school/study/course/contents-homework-export',data, { responseType: 'blob' });
}
// 考试导出
const exportExam=function (data){
return ajax.post('/xboe/school/study/course/contents-exam-export',data, { responseType: 'blob' });
}
// 评估类型资源
const contentsAssess=function (data){
return ajax.post('/xboe/school/study/course/contents-assess',data);
}
// 考试类型资源
const contentsExam=function (data){
return ajax.post('/xboe/school/study/course/contents-exam',data);
}
export default {
hasSignup,
signup,
@@ -463,10 +438,5 @@ export default {
deleteSignUp,
ids,
followIds,
studyIndexPost,
exportSignup,
exportHomework,
exportExam,
contentsAssess,
contentsExam
studyIndexPost
}

View File

@@ -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
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="14px" viewBox="0 0 12 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>新建课程</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版" transform="translate(-253, -258)" fill="#4284F7" fill-rule="nonzero">
<path d="M263.588235,258 C264.367931,258 265,258.600685 265,259.341667 L265,265.459375 C265,265.737243 264.762974,265.9625 264.470588,265.9625 C264.178202,265.9625 263.941176,265.737243 263.941176,265.459375 L263.941176,259.341667 C263.941176,259.252709 263.903992,259.167394 263.837802,259.104491 C263.771613,259.041588 263.681841,259.00625 263.588235,259.00625 L254.411765,259.00625 C254.318159,259.00625 254.228387,259.041588 254.162198,259.104491 C254.096008,259.167394 254.058824,259.252709 254.058824,259.341667 L254.058824,270.658333 C254.058824,270.747291 254.096008,270.832606 254.162198,270.895509 C254.228387,270.958412 254.318159,270.99375 254.411765,270.99375 L257.411765,270.99375 C257.704116,270.993797 257.941087,271.21904 257.941087,271.496875 C257.941087,271.77471 257.704116,272 257.411765,272 L254.411765,272 C253.632069,272 253,271.399315 253,270.658333 L253,259.341667 C253,258.600685 253.632069,258 254.411765,258 L263.588235,258 Z M261.812997,265.982255 C262.658243,265.982255 263.46887,266.299261 264.066549,266.863534 C264.664227,267.427807 265,268.193125 265,268.991128 C265,270.652882 263.57313,272 261.812997,272 C260.052864,272 258.625995,270.652882 258.625995,268.991128 C258.625995,267.329373 260.052864,265.982255 261.812997,265.982255 Z M261.812997,266.851485 C260.561347,266.851485 259.546684,267.809436 259.546684,268.991128 C259.546684,270.17282 260.561347,271.13077 261.812997,271.13077 C263.063839,271.128929 264.07736,270.172056 264.07931,268.991128 C264.07931,267.809436 263.064647,266.851485 261.812997,266.851485 Z M261.741379,267.495134 C261.93817,267.495134 262.097701,267.646158 262.097701,267.832455 L262.097701,268.675757 L262.988506,268.675757 C263.185297,268.675757 263.344828,268.826781 263.344828,269.013078 C263.344828,269.199375 263.185297,269.350399 262.988506,269.350399 L262.097701,269.350399 L262.097701,270.193701 C262.097701,270.379998 261.93817,270.531022 261.741379,270.531022 C261.544588,270.531022 261.385057,270.379998 261.385057,270.193701 L261.385057,269.350399 L260.494253,269.350399 C260.297462,269.350399 260.137931,269.199375 260.137931,269.013078 C260.137931,268.826781 260.297462,268.675757 260.494253,268.675757 L261.385057,268.675757 L261.385057,267.832455 C261.385057,267.646158 261.544588,267.495134 261.741379,267.495134 Z M259.157162,264.14695 C259.450517,264.14695 259.688329,264.37147 259.688329,264.648429 C259.688329,264.925388 259.450517,265.149908 259.157162,265.149908 L256.324271,265.149908 C256.030915,265.149908 255.793103,264.925388 255.793103,264.648429 C255.793103,264.37147 256.030915,264.14695 256.324271,264.14695 L259.157162,264.14695 Z M261.28183,261.138078 C261.575151,261.138125 261.812907,261.362631 261.812907,261.639557 C261.812907,261.916482 261.575151,262.140988 261.28183,262.141035 L256.324271,262.141035 C256.03095,262.140988 255.793193,261.916482 255.793193,261.639557 C255.793193,261.362631 256.03095,261.138125 256.324271,261.138078 L261.28183,261.138078 Z" id="新建课程"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="14px" viewBox="0 0 12 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>新建课程2</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版_展开" transform="translate(-253, -304)" fill="#FFFFFF" fill-rule="nonzero">
<path d="M263.588235,304 C264.367931,304 265,304.600685 265,305.341667 L265,311.459375 C265,311.737243 264.762974,311.9625 264.470588,311.9625 C264.178202,311.9625 263.941176,311.737243 263.941176,311.459375 L263.941176,305.341667 C263.941176,305.252709 263.903992,305.167394 263.837802,305.104491 C263.771613,305.041588 263.681841,305.00625 263.588235,305.00625 L254.411765,305.00625 C254.318159,305.00625 254.228387,305.041588 254.162198,305.104491 C254.096008,305.167394 254.058824,305.252709 254.058824,305.341667 L254.058824,316.658333 C254.058824,316.747291 254.096008,316.832606 254.162198,316.895509 C254.228387,316.958412 254.318159,316.99375 254.411765,316.99375 L257.411765,316.99375 C257.704116,316.993797 257.941087,317.21904 257.941087,317.496875 C257.941087,317.77471 257.704116,318 257.411765,318 L254.411765,318 C253.632069,318 253,317.399315 253,316.658333 L253,305.341667 C253,304.600685 253.632069,304 254.411765,304 L263.588235,304 Z M261.812997,311.982255 C262.658243,311.982255 263.46887,312.299261 264.066549,312.863534 C264.664227,313.427807 265,314.193125 265,314.991128 C265,316.652882 263.57313,318 261.812997,318 C260.052864,318 258.625995,316.652882 258.625995,314.991128 C258.625995,313.329373 260.052864,311.982255 261.812997,311.982255 Z M261.812997,312.851485 C260.561347,312.851485 259.546684,313.809436 259.546684,314.991128 C259.546684,316.17282 260.561347,317.13077 261.812997,317.13077 C263.063839,317.128929 264.07736,316.172056 264.07931,314.991128 C264.07931,313.809436 263.064647,312.851485 261.812997,312.851485 Z M261.741379,313.495134 C261.93817,313.495134 262.097701,313.646158 262.097701,313.832455 L262.097701,314.675757 L262.988506,314.675757 C263.185297,314.675757 263.344828,314.826781 263.344828,315.013078 C263.344828,315.199375 263.185297,315.350399 262.988506,315.350399 L262.097701,315.350399 L262.097701,316.193701 C262.097701,316.379998 261.93817,316.531022 261.741379,316.531022 C261.544588,316.531022 261.385057,316.379998 261.385057,316.193701 L261.385057,315.350399 L260.494253,315.350399 C260.297462,315.350399 260.137931,315.199375 260.137931,315.013078 C260.137931,314.826781 260.297462,314.675757 260.494253,314.675757 L261.385057,314.675757 L261.385057,313.832455 C261.385057,313.646158 261.544588,313.495134 261.741379,313.495134 Z M259.157162,310.14695 C259.450517,310.14695 259.688329,310.37147 259.688329,310.648429 C259.688329,310.925388 259.450517,311.149908 259.157162,311.149908 L256.324271,311.149908 C256.030915,311.149908 255.793103,310.925388 255.793103,310.648429 C255.793103,310.37147 256.030915,310.14695 256.324271,310.14695 L259.157162,310.14695 Z M261.28183,307.138078 C261.575151,307.138125 261.812907,307.362631 261.812907,307.639557 C261.812907,307.916482 261.575151,308.140988 261.28183,308.141035 L256.324271,308.141035 C256.03095,308.140988 255.793193,307.916482 255.793193,307.639557 C255.793193,307.362631 256.03095,307.138125 256.324271,307.138078 L261.28183,307.138078 Z" id="新建课程2"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>导出</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版" transform="translate(-406, -258)" fill="#999999" fill-rule="nonzero">
<path d="M407.8375,272 C407.3125,272 406.875,271.822785 406.525,271.468354 C406.175,271.113924 406,270.670886 406,270.139241 L406,267.56962 C406,267.392405 406.0875,267.21519 406.175,267.126582 C406.2625,267.037975 406.4375,266.949367 406.6125,266.949367 C406.7875,266.949367 406.9625,267.037975 407.05,267.126582 C407.1375,267.21519 407.225,267.392405 407.225,267.56962 L407.225,270.139241 C407.225,270.316456 407.3125,270.582278 407.4,270.670886 C407.4875,270.759494 407.6625,270.848101 407.925,270.848101 L418.075,270.848101 C418.25,270.848101 418.5125,270.759494 418.6,270.670886 C418.6875,270.582278 418.775,270.405063 418.775,270.139241 L418.775,267.56962 C418.775,267.392405 418.8625,267.21519 418.95,267.126582 C419.0375,267.037975 419.2125,266.949367 419.3875,266.949367 C419.5625,266.949367 419.7375,267.037975 419.825,267.126582 C419.9125,267.21519 420,267.392405 420,267.56962 L420,270.139241 C420,270.670886 419.825,271.113924 419.475,271.468354 C419.125,271.822785 418.6875,272 418.1625,272 L407.8375,272 Z M413,268.189873 C412.825,268.189873 412.65,268.101266 412.5625,268.012658 C412.475,267.924051 412.3875,267.746835 412.3875,267.56962 L412.3875,260.126582 C412.3875,260.126582 412.3875,260.037975 412.3,260.037975 L412.2125,260.037975 L410.2,262.253165 C410.1125,262.341772 409.85,262.43038 409.85,262.43038 C409.675,262.43038 409.5,262.341772 409.4125,262.253165 C409.2375,262.075949 409.15,261.987342 409.15,261.898734 C409.15,261.721519 409.2375,261.544304 409.325,261.455696 L412.475,258.265823 C412.65,258.088608 412.825,258 413,258 C413.175,258 413.35,258.088608 413.4375,258.177215 L416.5,261.455696 C416.5875,261.544304 416.675,261.721519 416.675,261.898734 C416.675,262.075949 416.5875,262.253165 416.5,262.341772 C416.4125,262.43038 416.2375,262.518987 416.0625,262.518987 C415.8875,262.518987 415.8,262.341772 415.7125,262.253165 L413.6125,260.037975 L413.525,260.037975 C413.525,260.037975 413.4375,260.037975 413.4375,260.126582 L413.4375,267.658228 C413.4375,267.835443 413.35,268.012658 413.2625,268.101266 C413.175,268.189873 413.0875,268.189873 413,268.189873 Z" id="导出"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>导出</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版_展开" transform="translate(-399, -295)">
<g id="导出" transform="translate(399, 295)">
<rect id="矩形" fill="#000000" opacity="0.05" x="0" y="0" width="32" height="32" rx="4"></rect>
<path d="M10.8375,23 C10.3125,23 9.875,22.8227848 9.525,22.4683544 C9.175,22.1139241 9,21.6708861 9,21.1392405 L9,18.5696203 C9,18.3924051 9.0875,18.2151899 9.175,18.1265823 C9.2625,18.0379747 9.4375,17.9493671 9.6125,17.9493671 C9.7875,17.9493671 9.9625,18.0379747 10.05,18.1265823 C10.1375,18.2151899 10.225,18.3924051 10.225,18.5696203 L10.225,21.1392405 C10.225,21.3164557 10.3125,21.5822785 10.4,21.6708861 C10.4875,21.7594937 10.6625,21.8481013 10.925,21.8481013 L21.075,21.8481013 C21.25,21.8481013 21.5125,21.7594937 21.6,21.6708861 C21.6875,21.5822785 21.775,21.4050633 21.775,21.1392405 L21.775,18.5696203 C21.775,18.3924051 21.8625,18.2151899 21.95,18.1265823 C22.0375,18.0379747 22.2125,17.9493671 22.3875,17.9493671 C22.5625,17.9493671 22.7375,18.0379747 22.825,18.1265823 C22.9125,18.2151899 23,18.3924051 23,18.5696203 L23,21.1392405 C23,21.6708861 22.825,22.1139241 22.475,22.4683544 C22.125,22.8227848 21.6875,23 21.1625,23 L10.8375,23 Z M16,19.1898734 C15.825,19.1898734 15.65,19.1012658 15.5625,19.0126582 C15.475,18.9240506 15.3875,18.7468354 15.3875,18.5696203 L15.3875,11.1265823 C15.3875,11.1265823 15.3875,11.0379747 15.3,11.0379747 L15.2125,11.0379747 L13.2,13.2531646 C13.1125,13.3417722 12.85,13.4303797 12.85,13.4303797 C12.675,13.4303797 12.5,13.3417722 12.4125,13.2531646 C12.2375,13.0759494 12.15,12.9873418 12.15,12.8987342 C12.15,12.721519 12.2375,12.5443038 12.325,12.4556962 L15.475,9.26582278 C15.65,9.08860759 15.825,9 16,9 C16.175,9 16.35,9.08860759 16.4375,9.17721519 L19.5,12.4556962 C19.5875,12.5443038 19.675,12.721519 19.675,12.8987342 C19.675,13.0759494 19.5875,13.2531646 19.5,13.3417722 C19.4125,13.4303797 19.2375,13.5189873 19.0625,13.5189873 C18.8875,13.5189873 18.8,13.3417722 18.7125,13.2531646 L16.6125,11.0379747 L16.525,11.0379747 C16.525,11.0379747 16.4375,11.0379747 16.4375,11.1265823 L16.4375,18.6582278 C16.4375,18.835443 16.35,19.0126582 16.2625,19.1012658 C16.175,19.1898734 16.0875,19.1898734 16,19.1898734 Z" id="形状" fill="#4284F7" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="14px" viewBox="0 0 10 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>置顶</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版" transform="translate(-370, -258)" fill="#999999" fill-rule="nonzero">
<path d="M379.893423,258.616603 C379.893423,258.957143 379.62302,259.233205 379.289461,259.233205 L370.613945,259.233205 C370.280386,259.233205 370.009984,258.957143 370.009984,258.616603 C370.009984,258.276062 370.280386,258 370.613945,258 L379.289461,258 C379.62302,258 379.893423,258.276062 379.893423,258.616603 Z M375.000061,260.909695 C374.666502,260.909695 374.3961,261.185758 374.3961,261.526298 L374.3961,271.383397 C374.3961,271.723938 374.666502,272 375.000061,272 C375.33362,272 375.604022,271.723938 375.604022,271.383397 L375.604022,261.526298 C375.604022,261.185758 375.33362,260.909695 375.000061,260.909695 Z M374.605006,260.423894 L370.155854,264.965705 C369.936707,265.189438 369.950361,265.566044 370.18612,265.806738 C370.422106,266.047663 370.790764,266.061371 371.009911,265.837637 L375.458835,261.295827 C375.677754,261.072094 375.664327,260.695487 375.428569,260.454794 C375.19281,260.214101 374.823925,260.200161 374.605006,260.423894 Z M374.571553,260.454794 C374.335794,260.695487 374.32214,261.072094 374.541287,261.295827 L378.990211,265.83787 C379.20913,266.061371 379.578015,266.047663 379.814002,265.806738 C380.049761,265.566044 380.063187,265.189438 379.844041,264.965705 L375.395344,260.423894 C375.176197,260.200161 374.807312,260.214101 374.571553,260.454794 Z" id="置顶"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>置顶</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版_展开" transform="translate(-359, -295)">
<g id="置顶" transform="translate(359, 295)">
<rect id="矩形" fill="#000000" opacity="0.05" x="0" y="0" width="32" height="32" rx="4"></rect>
<path d="M20.8934226,9.61660263 C20.8934226,9.95714285 20.6230199,10.2332053 20.2894612,10.2332053 L11.613945,10.2332053 C11.2803864,10.2332053 11.0099836,9.95714285 11.0099836,9.61660263 C11.0099836,9.2760624 11.2803864,9 11.613945,9 L20.2894612,9 C20.6230199,9 20.8934226,9.2760624 20.8934226,9.61660263 Z M16.000061,11.9096953 C15.6665023,11.9096953 15.3960996,12.1857577 15.3960996,12.5262979 L15.3960996,22.3833974 C15.3960996,22.7239376 15.6665023,23 16.000061,23 C16.3336196,23 16.6040224,22.7239376 16.6040224,22.3833974 L16.6040224,12.5262979 C16.6040224,12.1857577 16.3336196,11.9096953 16.000061,11.9096953 Z M15.6050056,11.4238942 L11.1558537,15.9657046 C10.9367072,16.1894379 10.9503612,16.5660441 11.1861201,16.8067376 C11.4221065,17.0476633 11.7907642,17.0613707 12.0099107,16.8376374 L16.458835,12.295827 C16.6777539,12.0720936 16.6643275,11.6954874 16.4285686,11.454794 C16.1928098,11.2141006 15.8239245,11.2001608 15.6050056,11.4238942 Z M15.5715533,11.454794 C15.3357945,11.6954874 15.3221405,12.0720936 15.541287,12.295827 L19.9902113,16.8378697 C20.2091302,17.0613707 20.5780155,17.0476633 20.8140019,16.8067376 C21.0497608,16.5660441 21.0631872,16.1894379 20.8440407,15.9657046 L16.3953439,11.4238942 C16.1761974,11.2001608 15.8073122,11.2141006 15.5715533,11.454794 Z" fill="#4284F7" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="15px" height="14px" viewBox="0 0 15 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>重置</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版" transform="translate(-1856, -184)" fill="#999999" fill-rule="nonzero">
<path d="M1869.71817,192.111106 C1869.4322,192.034115 1869.13954,192.209582 1869.06445,192.503055 C1868.40237,195.092745 1866.11453,196.901755 1863.50209,196.901755 C1861.15555,196.899152 1859.04494,195.436448 1858.16588,193.203628 L1859.21633,193.203628 L1857.5998,190.995338 L1856,193.203628 L1857.02588,193.203628 C1857.04017,193.247973 1857.05486,193.292079 1857.06996,193.335947 C1858.03525,196.131656 1860.61197,198.000082 1863.50209,198 C1866.60098,198 1869.31413,195.854292 1870.10009,192.781997 C1870.17511,192.488507 1870.00413,192.188163 1869.71817,192.111106 L1869.71817,192.111106 Z M1857.27782,189.936967 C1857.41541,189.973056 1857.56135,189.951488 1857.68343,189.877019 C1857.80551,189.802551 1857.89371,189.6813 1857.92858,189.540011 C1858.57704,186.92501 1860.8728,185.095707 1863.50209,185.098933 C1865.88559,185.098933 1867.97254,186.565167 1868.84057,188.800279 L1867.78367,188.800279 L1869.4002,191.008569 L1871,188.800279 L1869.97935,188.800279 C1869.02652,185.848952 1866.29164,183.895768 1863.26396,184.004305 C1860.23628,184.112842 1857.64087,186.257109 1856.89102,189.269473 C1856.81842,189.563384 1856.99152,189.8621 1857.27782,189.936967 Z" id="重置"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>zhongzhi-</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版_展开" transform="translate(-867, -217)">
<g id="zhongzhi-" transform="translate(867, 217)">
<rect id="矩形备份-12" fill="#000000" opacity="0.05" x="0" y="0" width="32" height="32" rx="6"></rect>
<path d="M22.7181736,17.1111055 C22.4321954,17.0341148 22.1395394,17.209582 22.0644543,17.5030548 C21.4023719,20.092745 19.1145286,21.9017553 16.5020908,21.9017553 C14.1555467,21.8991521 12.0449381,20.4364475 11.1658807,18.2036283 L12.2163267,18.2036283 L10.5998002,15.9953376 L9,18.2036283 L10.0258793,18.2036283 C10.0401663,18.2479729 10.0548599,18.2920791 10.06996,18.3359469 C11.0352515,21.1316558 13.6119724,23.0000823 16.5020908,23 C19.600985,23 22.3141291,20.8542924 23.1000906,17.7819967 C23.1751107,17.4885065 23.0041347,17.1881629 22.7181736,17.1111055 L22.7181736,17.1111055 Z M10.2778191,14.9369673 C10.4154149,14.9730564 10.5613478,14.951488 10.6834293,14.8770194 C10.8055109,14.8025508 10.8937114,14.6813 10.9285764,14.5400114 C11.5770444,11.9250098 13.8728029,10.0957074 16.5020908,10.0989331 C18.8855875,10.0989331 20.972541,11.5651666 21.8405659,13.8002787 L20.7836733,13.8002787 L22.4001998,16.0085694 L24,13.8002787 L22.9793477,13.8002787 C22.0265159,10.848952 19.2916412,8.89576768 16.2639616,9.00430498 C13.2362819,9.11284227 10.6408709,11.2571085 9.89102356,14.2694734 C9.8184212,14.5633845 9.9915194,14.8621004 10.2778191,14.9369673 Z" id="形状" fill="#999999" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>sousuo</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="京东方_在线管理3版" transform="translate(-1496, -191)" fill="#FFFFFF" fill-rule="nonzero">
<g id="chaxun" transform="translate(1482, 179)">
<g id="sousuo" transform="translate(14, 12)">
<path d="M15.8180325,14.9374363 L12.4571361,11.5685482 C13.5099726,10.3025262 14.0854618,8.70594283 14.0830354,7.05780481 C14.0830354,3.15992486 10.9303387,0 7.04166051,0 C3.15269672,0 0,3.16021111 0,7.05780481 C0,10.9553985 3.15269672,14.1153234 7.04166051,14.1153234 C8.70394773,14.1177783 10.3130671,13.5283697 11.5820693,12.452205 L14.9398241,15.8176581 C15.0612025,15.9393148 15.219994,16 15.3790711,16 C15.6301938,16 15.8565501,15.8482487 15.952674,15.6157194 C16.048798,15.38319 15.9957782,15.1155246 15.8183181,14.9374363 L15.8180325,14.9374363 Z M7.04166051,12.8704224 C5.50312892,12.872373 4.0272712,12.2596195 2.94078432,11.1677968 C1.85145906,10.0788189 1.24010717,8.59957752 1.24205333,7.05751856 C1.24010717,5.51545961 1.85145906,4.0362182 2.94078432,2.94724036 C4.02736505,1.8556276 5.50321116,1.24308494 7.04166051,1.24518646 C8.5801921,1.2432366 10.0560498,1.85599012 11.1425367,2.94781286 C12.2316602,4.03678569 12.8428963,5.51589252 12.8409821,7.05780481 C12.8429283,8.59986377 12.2315764,10.0791052 11.1422511,11.168083 C10.0557872,12.2597304 8.58005203,12.8723727 7.04166051,12.8704224 L7.04166051,12.8704224 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>chaxun</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="管理端列表页2版" transform="translate(-1807, -175)">
<g id="chaxun" transform="translate(1807, 175)">
<rect id="矩形备份-11" fill="#4284F7" x="0" y="0" width="32" height="32" rx="6"></rect>
<path d="M23.8180325,22.9374363 L20.4571361,19.5685482 C21.5099726,18.3025262 22.0854618,16.7059428 22.0830354,15.0578048 C22.0830354,11.1599249 18.9303387,8 15.0416605,8 C11.1526967,8 8,11.1602111 8,15.0578048 C8,18.9553985 11.1526967,22.1153234 15.0416605,22.1153234 C16.7039477,22.1177783 18.3130671,21.5283697 19.5820693,20.452205 L22.9398241,23.8176581 C23.0612025,23.9393148 23.219994,24 23.3790711,24 C23.6301938,24 23.8565501,23.8482487 23.952674,23.6157194 C24.048798,23.38319 23.9957782,23.1155246 23.8183181,22.9374363 L23.8180325,22.9374363 Z M15.0416605,20.8704224 C13.5031289,20.872373 12.0272712,20.2596195 10.9407843,19.1677968 C9.85145906,18.0788189 9.24010717,16.5995775 9.24205333,15.0575186 C9.24010717,13.5154596 9.85145906,12.0362182 10.9407843,10.9472404 C12.0273651,9.8556276 13.5032112,9.24308494 15.0416605,9.24518646 C16.5801921,9.2432366 18.0560498,9.85599012 19.1425367,10.9478129 C20.2316602,12.0367857 20.8428963,13.5158925 20.8409821,15.0578048 C20.8429283,16.5998638 20.2315764,18.0791052 19.1422511,19.168083 C18.0557872,20.2597304 16.580052,20.8723727 15.0416605,20.8704224 L15.0416605,20.8704224 Z" id="搜索" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="6px" viewBox="0 0 10 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>收起</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="京东方_在线管理_展开" transform="translate(-864, -257)" fill="#4284F7" fill-rule="nonzero">
<g id="收起" transform="translate(869, 260) scale(-1, -1) rotate(-270) translate(-869, -260)translate(866, 255)">
<path d="M0.828204731,0.121981959 C0.622033338,-0.0563083543 0.311020892,-0.036938598 0.12859169,0.165553637 C-0.0538375124,0.368045871 -0.040602445,0.679202183 0.158363572,0.865490299 L4.75263287,4.99731525 L0.186899406,9.12914019 C-0.000258078139,9.29809982 -0.0324364247,9.57982078 0.111805105,9.78658969 L0.151855399,9.83562322 C0.337423297,10.0402931 0.653830189,10.05597 0.85874308,9.87064716 L5.83549268,5.36756839 C5.94042055,5.2725631 6.00019036,5.13759575 6,4.99609231 C5.99980873,4.85458886 5.93967513,4.71978301 5.83449142,4.62506073 L0.828204731,0.121981959 Z" id="路径"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -392,99 +392,3 @@ li{
}
}
.custom-confirm-dialog {
max-width: 692px;
min-width: 692px;
min-height: 222px !important;
padding: 0px 0px 0px;
border-radius: 10px;
height: auto !important;
.el-message-box__header {
// padding: 0 0 16px 0;
padding: 2px 8px 2px 16px;
display: block;
.el-message-box__title {
font-size: 16px;
color: #000;
line-height: 32px;
}
.el-message-box__headerbtn {
top: 8px;
right: 10px;
.el-message-box__close {
font-size: 22px;
color: #b2b2b2;
}
}
}
.el-message-box__content {
padding: 0 0 28px 0;
margin-top: 30px;
.el-message-box__status {
margin-right: 14px;
font-size: 24px;
color: #e32e2e;
// display: block;
}
.el-message-box__message {
margin-left: 0;
color: #000;
font-size: 16px;
line-height: 32px;
font-weight: normal;
display: flex;
align-items: center;
justify-content: center;
padding: 0 20px;
p{
display: flex;
align-items: center;
justify-content: center;
.el-icon-warning-outline{
margin-right: 6px;
font-size: 18px;
color: #e32e2e;
}
}
}
}
.el-message-box__btns {
padding: 0;
display: flex;
justify-content: flex-end;
padding-right: 20px;
margin-top: 40px;
padding-bottom: 20px;
.el-button {
min-width: 120px;
height: 40px;
font-size: 16px;
border-radius: 6px;
padding: 0 18px;
}
.el-button--default {
color: rgba(0, 0, 0, .2);
border-color: rgba(0, 0, 0, .1);
background-color: #FFFFFF;
}
.el-button--primary {
background-color: #3b7cff;
border-color: #3b7cff;
color: #fff;
}
}
}
.custom-message-dialog {
}

View File

@@ -432,37 +432,6 @@
color: #333333;
}
}
.el-message.new-message {
background-color: #edf2fc !important;
box-shadow: none !important;
border-color: #EBEEF5 !important;
min-width: 170px !important;
border-radius: 10px !important;
}
.el-message--success.new-message {
background-color: #f0f9eb !important;
box-shadow: none !important;
border-color: #e1f3d8 !important;
min-width: 170px !important;
border-radius: 10px !important
}
.el-message--error.new-message {
background-color: #fef0f0 !important;
box-shadow: none !important;
border-color: #fde2e2 !important;
min-width: 170px !important;
border-radius: 10px !important
}
.el-message--warning.new-message {
background-color: #fdf6ec !important;
box-shadow: none !important;
border-color: #faecd8 !important;
min-width: 170px !important;
border-radius: 10px !important
}
.el-badge__content{// badge去掉白色边框
border:1px solid #f56c6c;
}

View File

@@ -1,234 +0,0 @@
<template>
<el-dialog
title="置顶排序"
:visible.sync="dialogVisible"
custom-class="g-dialog top-course-sorter-dialog"
width="820px"
:close-on-click-modal="false"
@closed="handleClosed"
append-to-body
>
<div class="top-course-sorter" v-loading="loading">
<div class="top-course-sorter__table" v-if="topList.length">
<div class="sorter-header">
<div class="header-cell header-cell--handle"></div>
<div class="header-cell header-cell--order">排序</div>
<div class="header-cell header-cell--name">课程名称</div>
<div class="header-cell header-cell--teacher">授课教师</div>
</div>
<div
class="sorter-row"
v-for="(item, index) in topList"
:key="item.id"
draggable="true"
@dragstart="handleDragStart(index, $event)"
@dragover.prevent
@drop="handleDrop(index)"
@dragend="handleDragEnd"
:class="{ 'is-dragging': draggingIndex === index }"
>
<div class="row-cell row-cell--handle">
<i class="el-icon-s-operation"></i>
</div>
<div class="row-cell row-cell--order">{{ index + 1 }}</div>
<div class="row-cell row-cell--name" :title="item.name">{{ item.name }}</div>
<div class="row-cell row-cell--teacher" :title="item.teacherName || '-'">
{{ item.teacherName || '-' }}
</div>
</div>
</div>
<el-empty v-else-if="!loading" description="暂无置顶课程"></el-empty>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :disabled="!topList.length" :loading="saving" @click="handleSave">确定</el-button>
</span>
</el-dialog>
</template>
<script>
import apiCourse from '@/api/modules/course.js';
export default {
name: 'TopCourseSorter',
data() {
return {
dialogVisible: false,
loading: false,
saving: false,
topList: [],
draggingIndex: null,
};
},
methods: {
open() {
this.dialogVisible = true;
this.fetchTopList();
},
async fetchTopList() {
this.loading = true;
try {
const res = await apiCourse.fetchTopCourseList();
if (res.status === 200) {
this.topList = Array.isArray(res.result) ? [...res.result] : [];
} else {
this.$message.error(res.message || '获取置顶课程失败');
this.topList = [];
}
} catch (error) {
this.$message.error(error.message || '获取置顶课程失败');
this.topList = [];
} finally {
this.loading = false;
}
},
handleDragStart(index, event) {
this.draggingIndex = index;
if (event && event.dataTransfer) {
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', index);
}
},
handleDrop(targetIndex) {
if (this.draggingIndex === null || this.draggingIndex === targetIndex) {
return;
}
const movingItem = this.topList.splice(this.draggingIndex, 1)[0];
this.topList.splice(targetIndex, 0, movingItem);
this.draggingIndex = targetIndex;
},
handleDragEnd() {
this.draggingIndex = null;
},
async handleSave() {
if (!this.topList.length) {
this.$message.warning('暂无需要保存的排序');
return;
}
const payload = this.topList.map((item, index) => ({
id: item.id,
sortWeight: index,
}));
this.saving = true;
try {
const res = await apiCourse.updateTopCourseSort(payload);
if (res.status === 200) {
this.$message.success('排序更新成功');
this.$emit('sorted');
this.dialogVisible = false;
} else {
throw new Error(res.message || '排序更新失败');
}
} catch (error) {
this.$message.error(error.message || '排序更新失败');
} finally {
this.saving = false;
}
},
handleClosed() {
this.topList = [];
this.draggingIndex = null;
this.loading = false;
this.saving = false;
},
},
};
</script>
<style lang="scss" scoped>
.top-course-sorter {
min-height: 200px;
padding-top: 8px;
}
.top-course-sorter__table {
border: 1px solid #ebeef5;
border-radius: 6px;
overflow: hidden;
}
.sorter-header,
.sorter-row {
display: grid;
grid-template-columns: 60px 80px 1fr 160px;
align-items: center;
}
.sorter-header {
background-color: #f5f7fa;
height: 48px;
font-weight: 600;
color: #303133;
border-bottom: 1px solid #ebeef5;
}
.sorter-row {
min-height: 56px;
border-bottom: 1px solid #f2f6fc;
cursor: move;
transition: background-color 0.2s ease;
}
.sorter-row:last-child {
border-bottom: none;
}
.sorter-row:hover {
background-color: #f9fbff;
}
.sorter-row.is-dragging {
opacity: 0.7;
background-color: #ecf5ff;
}
.header-cell,
.row-cell {
padding: 0 16px;
display: flex;
align-items: center;
}
.header-cell--handle,
.row-cell--handle {
justify-content: center;
}
.header-cell--order,
.row-cell--order {
justify-content: flex-start;
}
.row-cell--name,
.row-cell--teacher {
color: #303133;
}
.row-cell--name {
font-weight: 500;
}
.row-cell--teacher {
color: #666;
}
.row-cell--handle i {
font-size: 20px;
color: #c0c4cc;
}
.dialog-footer {
text-align: right;
}
</style>

View File

@@ -50,7 +50,7 @@
<el-input-number v-model="duration" size="mini" :min="1" :max="100"></el-input-number>
</span>
</div>
<el-upload ref="uploadRef" class="upload-demo" :headers="headers" :data="data" drag :action="uploadFileUrl" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload">
<el-upload class="upload-demo" :headers="headers" :data="data" drag :action="uploadFileUrl" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">文件大小限制{{curComType.maxSizeName}},支持的文件类型{{curComType.fileTypes.join(',')}}</div>
@@ -195,7 +195,6 @@
// this.cware.content.content=result.filePath;
}else{
this.$message.error(rs.message);
this.$refs.uploadRef.clearFiles();
}
});
}else{

File diff suppressed because it is too large Load Diff

View File

@@ -1,400 +0,0 @@
<template>
<div class="tag-container" @click="handleContainerClick">
<el-select style="width: 100%;"
v-model="selectedTags"
multiple
filterable
value-key="id"
remote
reserve-keyword
:remote-method="debouncedSearch"
:loading="loading"
:placeholder="'回车创建新标签'"
:no-data-text="'无此标签,按回车键创建'"
@remove-tag="handleTagRemove"
@change="handleSelectionChange"
@keyup.enter.native="handleEnterKey"
@keyup.delete.native="handleDeleteKey"
@focus="handleFocus"
ref="tagSelect"
>
<el-option
v-for="item in searchResults"
:key="item.id"
:label="item.tagName"
:value="item"
:disabled="isTagDisabled(item)"
/>
</el-select>
<!-- 添加标签计数显示 -->
<div class="tag-count">
{{ selectedTags.length }}/5
</div>
</div>
</template>
<script>
import { debounce } from 'lodash'
import apiCourseTag from '@/api/modules/courseTag.js'
import { mapGetters } from 'vuex';
export default {
props: {
courseId:{
type:String,
require:true,
},
sysTypeList:{
type:Array,
require:true,
default: []
},
maxTags: {
type: Number,
default: 5
},
// 添加接收初始标签数据的props
initialTags: {
type: Array,
default: () => []
}
},
data() {
return {
selectedTags: [],
searchResults: [],
loading: false,
tagMap: new Map(),
inputBuffer: '',
params: {},
tag: {},
// 添加临时存储用于回滚
previousTags: []
}
},
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);
});
},
// 监听分类变化,重新加载搜索结果
sysTypeList: {
handler() {
// 只有在已选择分类且有焦点时才重新加载
if (this.sysTypeList.length > 0 && this.$refs.tagSelect && this.$refs.tagSelect.visible) {
this.doSearch('');
}
},
deep: true
}
},
methods: {
// 新增:检查标签是否应该被禁用
isTagDisabled(tag) {
// 如果标签已经被选中,不应该禁用(允许取消选择)
const isSelected = this.selectedTags.some(selectedTag => selectedTag.id === tag.id);
if (isSelected) {
return false;
}
// 如果标签未被选中且已达到最大数量,则禁用
return this.selectedTags.length >= this.maxTags;
},
// 新增:处理输入框获得焦点事件
async handleFocus() {
this.previousTags = [...this.selectedTags];
// 当输入框获得焦点时,加载默认的搜索结果
if (this.sysTypeList.length > 0) {
await this.doSearch('');
}
this.$emit('focus');
},
handleContainerClick() {
// 容器点击时也触发焦点事件
this.$emit('focus');
},
// 新增:重置标签状态的方法
resetTagState() {
this.selectedTags = [];
this.searchResults = [];
this.tagMap.clear();
this.loading = false;
this.params = {};
},
handleTagRemove(tagId) {
this.selectedTags = this.selectedTags.filter(id => id !== tagId)
this.$emit('change', this.displayTags)
this.clearInput();
},
removeTag(tagId) {
this.handleTagRemove(tagId)
},
// 新增:处理删除键事件
handleDeleteKey(event) {
// 如果输入框内容为空,不执行任何搜索
if (!event.target.value.trim()) {
this.searchResults = []
}
},
//按回车键,创建新标签
handleEnterKey(event) {
const inputVal = event.target.value?.trim()
if (!inputVal) return;
// 检查是否与已选择的标签重复
const isDuplicate = this.selectedTags.some(tag => tag.tagName === inputVal);
if (isDuplicate) {
this.$message.warning('该标签已存在,无需重复创建');
event.target.value = '';
return;
}
if (!isDuplicate && inputVal && this.selectedTags.length < this.maxTags) {
this.createNewTag(event.target.value.trim())
this.clearInput();
} else if (this.selectedTags.length >= this.maxTags) {
this.$message.warning('最多只能添加5个标签')
this.clearInput();
} else {
this.clearInput();
}
},
// 新增:处理选择变化事件
handleSelectionChange(newValues) {
// 检查每个标签对象是否完整
newValues.forEach((tag, index) => {
if (!tag.tagName) {
console.error(`${index}个标签缺少tagName:`, tag);
}
});
// 检查数量限制
if (newValues.length > this.maxTags) {
this.$message.warning(`最多只能选择${this.maxTags}个标签`);
// 回滚到之前的状态
this.selectedTags = [...this.previousTags];
return;
}
// 更新前保存当前状态
this.previousTags = [...newValues];
this.$emit('change', this.displayTags);
this.clearInput();
this.$nextTick(() => {
this.$refs.tagSelect.visible = false;
});
},
clearInput() {
if (this.$refs.tagSelect) {
const input = this.$refs.tagSelect.$refs.input;
if (input) {
input.value = '';
}
}
},
//创建新标签
async createNewTag(tagName) {
// 标签不能超过八个字
if (tagName.length > 8) {
this.$message.error('标签不能超过8个字')
return;
}
// 检查标签是否在下拉框中已存在
const isExistInSearch = this.searchResults.some(tag => tag.tagName === tagName);
if (isExistInSearch) {
this.$message.warning('已存在此标签,请选择');
return;
}
// 首先检查是否与已选择的标签重复
const isDuplicate = this.selectedTags.some(tag => tag.tagName === tagName);
if (isDuplicate) {
this.$message.warning('该标签已存在,无需重复创建');
return;
}
// 标签格式验证:仅支持中文、英文、数字、下划线、中横线
const tagPattern = /^[\u4e00-\u9fa5a-zA-Z0-9_-]+$/;
if (!tagPattern.test(tagName)) {
this.$message.error('标签名称仅支持中文、英文、数字、下划线(_)和中横线(-),不支持空格、点和特殊字符');
return;
}
// 添加标签数量限制检查
if (this.selectedTags.length >= this.maxTags) {
this.$message.warning('最多只能添加5个标签')
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('标签创建成功',newTag);
this.selectedTags = [...this.selectedTags, newTag];
// 更新搜索结果的逻辑保持不变
this.searchResults = [newTag, ...this.searchResults];
this.tagMap.set(newTag.id, newTag)
this.$emit('change', this.displayTags)
this.$nextTick(() => {
// 强制重新设置selectedTags来触发更新
const tempTags = [...this.selectedTags];
this.selectedTags = [];
this.$nextTick(() => {
this.selectedTags = tempTags;
});
this.$refs.tagSelect.visible = false;
});
} finally {
this.loading = false
}
},
// 修改doSearch方法添加搜索结果为空时的提示
async doSearch(query) {
// 不再在空查询时清空搜索结果
// if (!query.trim()) {
// this.searchResults = []
// return
// }
console.log("---- doSearch ------ query = " + query )
this.loading = true
try {
// 获取 typeId取 sysTypeList 最后一个有效的值
const typeId = this.sysTypeList.length > 2 ? this.sysTypeList[2] :
this.sysTypeList.length > 1 ? this.sysTypeList[1] :
this.sysTypeList.length > 0 ? this.sysTypeList[0] : null;
console.log("---- doSearch searchTags ------ query = " + query + " , typeId = " + typeId )
const {result:tags} = await apiCourseTag.searchTags({tagName:query,typeId:typeId})
console.log("-- searchTags 查询结果 tags = " + tags )
tags.forEach(item => {
this.tagMap.set(item.id, item)
})
this.searchResults = tags
// 当搜索结果为空时,提示用户可以按回车键创建标签
if (tags.length === 0) {
// this.$message.info('无此标签,按回车键创建')
}
} finally {
this.loading = false
}
}
}
}
</script>
<style scoped>
.tag-container {
position: relative;
}
.tag-preview {
margin-top: 8px;
}
.el-tag {
margin-right: 6px;
margin-bottom: 6px;
}
/* 添加标签计数样式 */
.tag-count {
position: absolute;
right: 10px;
top: 47%;
transform: translateY(-40%);
font-size: 12px;
color: #999;
background: white;
padding: 0 5px;
pointer-events: none;
/* 添加高度限制 */
height: 25px;
line-height: 25px; /* 垂直居中文字 */
box-sizing: border-box; /* 确保padding包含在height内 */
}
::v-deep(.el-select__tags) {
display: flex;
flex-wrap: wrap;
align-items: center;
}
/*
::v-deep(.el-tag) {
flex: 0 0 calc(50% - 8px);
max-width: calc(50% - 8px);
box-sizing: border-box;
margin-right: 8px;
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}*/
::v-deep(.el-tag) {
flex: 1 1 auto; /* 自动调整宽度 */
min-width: 30%; /* 设置最小宽度 */
max-width: 48%; /* 设置最大宽度,留出边距 */
box-sizing: border-box;
margin-right: 8px;
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
justify-content: center;
text-align: center;
}
::v-deep(.el-select__input) {
flex: 1;
min-width: 60px;
}
</style>

View File

@@ -1,87 +0,0 @@
<template>
<div>
<el-dialog width="40%" class="simple-message-box" :title="title" :visible.sync="visible" append-to-body>
<div class="message-box-content"><svg-icon style="margin-right: 5px;font-size:16px"
icon-class="jingti"></svg-icon>{{message}}</div>
<span slot="footer" class="dialog-footer">
<el-button class="cancel" @click="cancel">{{cancelButtonText}}</el-button>
<el-button class="confirm" type="primary" @click="confirm">{{confirmButtonText}}</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "SimpleMessageBox",
data() {
return {
visible: false,
title: "",
message: "",
confirmButtonText: "确 认",
cancelButtonText: "取 消",
handleConfirm: null,
handleCancel: null,
};
},
methods: {
open() {
this.visible = true;
},
cancel() {
this.visible = false;
this.handleCancel();
},
confirm() {
this.visible = false;
this.handleConfirm();
},
},
};
</script>
<style lang="scss" scoped>
.simple-message-box {
::v-deep .el-dialog {
border-radius: 12px;
}
::v-deep .el-dialog__title {
font-size: 16px;
color: #000000;
}
.message-box-content {
display: flex;
justify-content: center;
font-size: 16px;
align-items: center;
color: #000000;
}
.cancel {
width: 120px;
height: 40px;
background: rgba(#4284f7,0.1);
border-radius: 8px;
margin-right: 8px;
border: none;
span {
font-weight: bold;
font-size: 14px;
color: #4284f7;
line-height: 40px;
text-align: center;
}
}
.confirm {
width: 120px;
height: 40px;
background: #4284f7;
border-radius: 8px;
span {
font-weight: bold;
font-size: 14px;
color: #ffffff;
line-height: 40px;
}
}
}
</style>

View File

@@ -414,11 +414,6 @@ export default {
if(meta.title == '添加受众' || meta.title == '查看受众'){
meta.activeMenu = '/manage/ugroups'
}
if(route.path == '/course/coursemanage'){
console.log('进入课程管理');
meta.activeMenu = '/need/course'
}
if (meta.activeMenu) {
return meta.activeMenu;
}

View File

@@ -1,4 +1,4 @@
<script>
<script setup>
import {getCertificationProcess} from "@/api/modules/lecturer";
export default {

View File

@@ -29,9 +29,6 @@ export const pages=[
{title:'课程首页',path:'index',component:'course/Index',hidden:true},
{title:'课程建设',path:'mylist',component:'course/TeacherList',hidden:true},
{title:'课程管理',path:'manage',component:'course/ManageList',hidden:false},
{title:'课程管理',path:'coursemanage',component:'course/CourseManage',hidden:true},
{title:'课程管理新版',path:'manage-remote',component:'course/ManageListRemote',hidden:false},
{title:'课程管理新版',path:'coursemanage-remote',component:'course/CourseManageRemote',hidden:true},
{title:'课程统计',path:'stat',component:'course/StatIndex',hidden:false},
{title:'课件管理',path:'courseware',component:'course/Courseware',hidden:false},
{title:'报名管理',path:'msignup',component:'study/ManageSignup',hidden:true},
@@ -120,8 +117,6 @@ export const iframes=[
{title:'嵌入测试', path:'/iframe/index',hidden:false,component:'portal/iframe'},
{title:'课件管理', path:'/iframe/course/coursewares',hidden:false,component:'course/Courseware'},
{title:'课程管理', path:'/iframe/course/manages',hidden:false,component:'course/ManageList'},
{title:'课程管理新版', path:'/iframe/course/manage-remote',hidden:false,component:'course/ManageListRemote'},
{title:'课程管理新版', path:'/iframe/course/coursemanage-remote',hidden:false,component:'course/CourseManageRemote'},
{title:'考试试题管理', path:'/iframe/exam/questions',hidden:false,component:'exam/Question'},
{title:'查看答卷', path:'/iframe/exam/viewanswer',hidden:false,component:'exam/viewAnswer'},
{title:'考试试卷管理', path:'/iframe/exam/papers',hidden:false,component:'exam/TestPaper'},
@@ -133,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'}
]

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="10px" viewBox="0 0 10 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>check 2</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-178, -894)" fill="#000000" fill-rule="nonzero">
<g id="check" transform="translate(178, 894)">
<path d="M1.04597978,8.4501514 L8.95402022,8.4501514 C9.18512277,8.4501514 9.40057776,8.37277111 9.56186808,8.23258944 C9.72556572,8.09128631 9.81584015,7.90063923 9.81584015,7.69653471 L9.81584015,6.30368958 C9.81584015,5.89548054 9.42103996,5.55007289 8.95402022,5.55007289 L6.73206548,5.55007289 L6.50096293,4.29068072 C7.27250843,3.88247168 7.74915744,3.13334081 7.74915744,2.32253 C7.74915744,2.01300886 7.67693789,1.71021644 7.53490611,1.42424582 C7.39768897,1.14836829 7.2026962,0.89940563 6.95474242,0.68520803 C6.44198363,0.243355389 5.76793452,0 5.05416466,0 C4.32956187,0 3.6482908,0.241112482 3.13553202,0.677357856 C2.62156957,1.11584614 2.33750602,1.70012336 2.33750602,2.32253 C2.33750602,3.13334081 2.81415503,3.88135023 3.58570053,4.29068072 L3.35459798,5.55007289 L1.04597978,5.55007289 C0.814877227,5.55007289 0.599422244,5.62745318 0.438131921,5.76763485 C0.27443428,5.90893798 0.184159846,6.09958506 0.184159846,6.30368958 L0.184159846,7.69653471 C0.184159846,8.10474375 0.578960039,8.4501514 1.04597978,8.4501514 Z M1.14106885,6.43041382 L3.45450169,6.43041382 C3.87578238,6.43041382 4.24289841,6.13098576 4.29345209,5.74857015 L4.5907559,4.35908938 L4.59195956,4.35460357 C4.64010592,4.04396097 4.47400096,3.754626 4.15984593,3.59874397 C3.64347617,3.3430526 3.33533943,2.87316362 3.33533943,2.34159471 C3.33533943,1.52405518 4.10568127,0.860154761 5.052961,0.860154761 C6.00024073,0.860154761 6.77058257,1.516205 6.77058257,2.32253 C6.77058257,2.85409891 6.46244584,3.32398789 5.94607607,3.57967926 C5.63914299,3.73219693 5.46461242,4.04283952 5.51396245,4.35460357 L5.51396245,4.35684647 L5.81246991,5.74857015 C5.86302359,6.13098576 6.23134328,6.43041382 6.65262398,6.43041382 L8.86013481,6.43041382 L8.86013481,7.58999664 L1.14106885,7.58999664 L1.14106885,6.43041382 Z M9.51612903,9.09835146 L0.483870968,9.09835146 C0.217862301,9.09835146 0,9.30133453 0,9.54917573 C0,9.79701693 0.217862301,10 0.483870968,10 L9.51612903,10 C9.7821377,10 10,9.79701693 10,9.54917573 C10,9.30133453 9.78334136,9.09835146 9.51612903,9.09835146 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="10px" viewBox="0 0 10 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>check</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-178, -920)" fill="#4284F7" fill-rule="nonzero">
<g id="check" transform="translate(178, 920)">
<path d="M1.04597978,8.4501514 L8.95402022,8.4501514 C9.18512277,8.4501514 9.40057776,8.37277111 9.56186808,8.23258944 C9.72556572,8.09128631 9.81584015,7.90063923 9.81584015,7.69653471 L9.81584015,6.30368958 C9.81584015,5.89548054 9.42103996,5.55007289 8.95402022,5.55007289 L6.73206548,5.55007289 L6.50096293,4.29068072 C7.27250843,3.88247168 7.74915744,3.13334081 7.74915744,2.32253 C7.74915744,2.01300886 7.67693789,1.71021644 7.53490611,1.42424582 C7.39768897,1.14836829 7.2026962,0.89940563 6.95474242,0.68520803 C6.44198363,0.243355389 5.76793452,0 5.05416466,0 C4.32956187,0 3.6482908,0.241112482 3.13553202,0.677357856 C2.62156957,1.11584614 2.33750602,1.70012336 2.33750602,2.32253 C2.33750602,3.13334081 2.81415503,3.88135023 3.58570053,4.29068072 L3.35459798,5.55007289 L1.04597978,5.55007289 C0.814877227,5.55007289 0.599422244,5.62745318 0.438131921,5.76763485 C0.27443428,5.90893798 0.184159846,6.09958506 0.184159846,6.30368958 L0.184159846,7.69653471 C0.184159846,8.10474375 0.578960039,8.4501514 1.04597978,8.4501514 Z M1.14106885,6.43041382 L3.45450169,6.43041382 C3.87578238,6.43041382 4.24289841,6.13098576 4.29345209,5.74857015 L4.5907559,4.35908938 L4.59195956,4.35460357 C4.64010592,4.04396097 4.47400096,3.754626 4.15984593,3.59874397 C3.64347617,3.3430526 3.33533943,2.87316362 3.33533943,2.34159471 C3.33533943,1.52405518 4.10568127,0.860154761 5.052961,0.860154761 C6.00024073,0.860154761 6.77058257,1.516205 6.77058257,2.32253 C6.77058257,2.85409891 6.46244584,3.32398789 5.94607607,3.57967926 C5.63914299,3.73219693 5.46461242,4.04283952 5.51396245,4.35460357 L5.51396245,4.35684647 L5.81246991,5.74857015 C5.86302359,6.13098576 6.23134328,6.43041382 6.65262398,6.43041382 L8.86013481,6.43041382 L8.86013481,7.58999664 L1.14106885,7.58999664 L1.14106885,6.43041382 Z M9.51612903,9.09835146 L0.483870968,9.09835146 C0.217862301,9.09835146 0,9.30133453 0,9.54917573 C0,9.79701693 0.217862301,10 0.483870968,10 L9.51612903,10 C9.7821377,10 10,9.79701693 10,9.54917573 C10,9.30133453 9.78334136,9.09835146 9.51612903,9.09835146 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="11px" height="12px" viewBox="0 0 11 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>shanchu</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-436, -918)" fill="#FF1818" fill-rule="nonzero">
<g id="shanchu" transform="translate(436, 918)">
<path d="M10.4999537,3.19289906 L0.500046316,3.19289906 C0.223878361,3.19289906 0,2.97107081 0,2.6974318 C0,2.42379279 0.223878361,2.20196454 0.500046316,2.20196454 L10.4999537,2.20196454 C10.7761216,2.20196454 11,2.42379279 11,2.6974318 C11,2.97107081 10.7761216,3.19289906 10.4999537,3.19289906 Z" id="路径"></path>
<path d="M8.27763883,12 L2.72210644,12 C1.83281125,11.9990263 1.11214015,11.2849546 1.11115743,10.4038029 L1.11115743,2.6974318 C1.11115743,2.42379279 1.33503579,2.20196454 1.61120374,2.20196454 C1.8873717,2.20196454 2.11125006,2.42379279 2.11125006,2.6974318 L2.11125006,10.4038029 C2.11125006,10.738359 2.38496787,11.0095703 2.7226159,11.0095703 L8.2781483,11.0095703 C8.61579634,11.0095703 8.88951415,10.738359 8.88951415,10.4038029 L8.88951415,2.6974318 C8.88951415,2.42379279 9.11339251,2.20196454 9.38956046,2.20196454 C9.66572842,2.20196454 9.88960678,2.42379279 9.88960678,2.6974318 L9.88960678,10.4038029 C9.88862317,11.2853484 9.16733192,11.9995828 8.27763883,12 Z M7.72206011,3.19289906 C7.4459504,3.1927598 7.22215435,2.9710131 7.22201381,2.6974318 L7.22201381,1.59619712 C7.22201381,1.43553761 7.15760223,1.2814583 7.04294889,1.16785488 C6.92829555,1.05425145 6.77279226,0.990429712 6.61064795,0.990429715 L4.3890973,0.990429715 C4.05144927,0.990429715 3.77773146,1.26164102 3.77773146,1.59619712 L3.77773146,2.6974318 C3.77773146,2.97107081 3.5538531,3.19289906 3.27768515,3.19289906 C3.00151719,3.19289906 2.77763883,2.97107081 2.77763883,2.6974318 L2.77763883,1.59619712 C2.77862156,0.715045435 3.49929265,0.000973720991 4.38858784,0 L6.6109027,0 C7.50019788,0.000973727448 8.22086897,0.71504544 8.2218517,1.59619712 L8.2218517,2.6974318 C8.22171131,2.97091464 7.99807034,3.19262061 7.72206011,3.19289906 L7.72206011,3.19289906 Z" id="形状"></path>
<path d="M4.3890973,9.2475444 C4.11292935,9.2475444 3.88905099,9.02571608 3.88905099,8.75207707 L3.88905099,5.44938266 C3.88902352,5.27235111 3.9843258,5.10875556 4.13905195,5.02023193 C4.2937781,4.93170829 4.48441652,4.93170829 4.63914267,5.02023193 C4.79386882,5.10875556 4.8891711,5.27235111 4.88914369,5.44938266 L4.88914369,8.75207707 C4.88921124,8.88350369 4.83654966,9.00956666 4.74275812,9.10249932 C4.64896658,9.19543199 4.52173855,9.24761133 4.3890973,9.2475444 L4.3890973,9.2475444 Z" id="路径"></path>
<path d="M6.61115743,9.24754433 C6.33498947,9.24754433 6.11111111,9.02571608 6.11111111,8.75207707 L6.11111111,5.44938266 C6.11111111,5.17574365 6.33498947,4.9539154 6.61115743,4.9539154 C6.88732538,4.9539154 7.11120374,5.17574365 7.11120374,5.44938266 L7.11120374,8.75207707 C7.11120374,9.02571608 6.88732538,9.24754433 6.61115743,9.24754433 L6.61115743,9.24754433 Z" id="路径"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>chakan</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-326, -920)" fill="#4284F7" fill-rule="nonzero">
<g id="chakan" transform="translate(326, 920)">
<path d="M8.94642857,0 C9.61213393,0 10.1517857,0.539651786 10.1517857,1.20535714 L10.1517857,3.16071429 L11.0625,3.16071429 C11.5750848,3.16071429 11.9915893,3.57208929 11.9998661,4.08270536 L12,4.09821429 L12,10.7946429 C12,11.453692 11.4710759,11.989192 10.8145714,11.9998393 L10.7946429,12 L1.20535714,12 C0.546308036,12 0.0108080357,11.4710759 0.000160714286,10.8145714 L0,10.7946429 L0,4.09821429 C0,3.58562946 0.411375,3.169125 0.921991071,3.16084821 L0.9375,3.16071429 L1.84821429,3.16071429 L1.84821429,1.20535714 C1.84821429,0.546308036 2.37713839,0.0108080357 3.03364286,0.000160714286 L3.05357143,0 L8.94642857,0 Z M11.1964286,8.83928571 L0.803571429,8.83928571 L0.803571429,10.7946429 C0.803571429,11.0143259 0.979875,11.1928259 1.19871429,11.196375 L1.20535714,11.1964286 L10.7946429,11.1964286 C11.0143259,11.1964286 11.1928259,11.020125 11.1964286,10.8012857 L11.1964286,10.7946429 L11.1964286,8.83928571 Z M1.84821429,3.96428571 L0.9375,3.96428571 C0.864776786,3.96428571 0.805607143,4.02223661 0.803625,4.09446429 L0.803571429,4.09821429 L0.803571429,8.03571429 L1.84821429,8.03571429 L1.84821429,3.96428571 Z M11.0625,3.96428571 L10.1517857,3.96428571 L10.1517857,8.03571429 L11.1964286,8.03571429 L11.1964286,4.09821429 C11.1964286,4.02549107 11.1384777,3.96632143 11.06625,3.96433929 L11.0625,3.96428571 Z M8.95307143,0.803571429 L3.05357143,0.803571429 C2.83166518,0.803571429 2.65178571,0.983450893 2.65178571,1.20535714 L2.65178571,8.03571429 L9.34821429,8.03571429 L9.34821429,1.20535714 C9.34821429,0.985674107 9.17191071,0.807174107 8.95307143,0.803571429 Z M5.69866071,1.47321429 C7.1595,1.47321429 8.34375,2.65746429 8.34375,4.11830357 C8.34375,4.70375893 8.15354464,5.24479018 7.83155357,5.68297768 L8.65222768,6.50366518 C8.80913839,6.6605625 8.80913839,6.91495982 8.65222768,7.07187054 C8.49531696,7.22878125 8.24093304,7.22878125 8.08402232,7.07187054 L7.26333482,6.25119643 C6.82513393,6.5731875 6.28411607,6.76339286 5.69866071,6.76339286 C4.23782143,6.76339286 3.05357143,5.57914286 3.05357143,4.11830357 C3.05357143,2.65746429 4.23782143,1.47321429 5.69866071,1.47321429 Z M5.69866071,2.27678571 C4.68160714,2.27678571 3.85714286,3.10125 3.85714286,4.11830357 C3.85714286,5.13535714 4.68160714,5.95982143 5.69866071,5.95982143 C6.71571429,5.95982143 7.54017857,5.13535714 7.54017857,4.11830357 C7.54017857,3.10125 6.71571429,2.27678571 5.69866071,2.27678571 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>a-zidingyipoppy_icon_zidinyi2备份 11 2</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-64, -893)" fill="#000000" fill-rule="nonzero">
<g id="a-zidingyipoppy_icon_zidinyi2备份-11" transform="translate(64, 893)">
<path d="M9.824,2.11948459 L7.938,0.198782456 C7.67766676,-0.0662608185 7.25566656,-0.0662608185 6.99533333,0.198782456 L1.11533333,6.18697362 L0.123333328,9.21908947 C0.0430921896,9.46316182 0.105275196,9.73245695 0.28391775,9.91453032 C0.462560305,10.0966037 0.726940747,10.1601436 0.966666672,10.0786189 L3.944,9.06768735 L9.824,3.08017513 C10.0842546,2.8150518 10.0842546,2.38528686 9.824,2.12016352 L9.824,2.11948459 Z M8.88266667,2.60016932 L3.46133333,8.12193334 L1.32933333,8.84974978 L2.04666667,6.68123702 L7.46866667,1.16015192 L8.88266667,2.60016932 L8.88266667,2.60016932 Z M0,10.9816001 L12,10.9816001 L12,12 L0,12 L0,10.9816001 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>a-zidingyipoppy_icon_zidinyi2备份 11</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-64, -919)" fill="#4284F7" fill-rule="nonzero">
<g id="a-zidingyipoppy_icon_zidinyi2备份-11" transform="translate(64, 919)">
<path d="M9.824,2.11948459 L7.938,0.198782456 C7.67766676,-0.0662608185 7.25566656,-0.0662608185 6.99533333,0.198782456 L1.11533333,6.18697362 L0.123333328,9.21908947 C0.0430921896,9.46316182 0.105275196,9.73245695 0.28391775,9.91453032 C0.462560305,10.0966037 0.726940747,10.1601436 0.966666672,10.0786189 L3.944,9.06768735 L9.824,3.08017513 C10.0842546,2.8150518 10.0842546,2.38528686 9.824,2.12016352 L9.824,2.11948459 Z M8.88266667,2.60016932 L3.46133333,8.12193334 L1.32933333,8.84974978 L2.04666667,6.68123702 L7.46866667,1.16015192 L8.88266667,2.60016932 L8.88266667,2.60016932 Z M0,10.9816001 L12,10.9816001 L12,12 L0,12 L0,10.9816001 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>erweima 2</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-258, -893)" fill="#000000" fill-rule="nonzero">
<g id="erweima" transform="translate(258, 893)">
<path d="M4,6.66666667 L1.33333333,6.66666667 C0.6,6.66666667 0,7.26666667 0,8 L0,10.6666667 C0,11.4 0.6,12 1.33333333,12 L4,12 C4.73333333,12 5.33333333,11.4 5.33333333,10.6666667 L5.33333333,8 C5.33333333,7.26666667 4.73333333,6.66666667 4,6.66666667 Z M4.44444444,10.6666667 C4.44444444,10.9111111 4.24444444,11.1111111 4,11.1111111 L1.33333333,11.1111111 C1.08888889,11.1111111 0.888888889,10.9111111 0.888888889,10.6666667 L0.888888889,8 C0.888888889,7.75555556 1.08888889,7.55555556 1.33333333,7.55555556 L4,7.55555556 C4.24444444,7.55555556 4.44444444,7.75555556 4.44444444,8 L4.44444444,10.6666667 Z M4,0 L1.33333333,0 C0.6,0 0,0.6 0,1.33333333 L0,4 C0,4.73333333 0.6,5.33333333 1.33333333,5.33333333 L4,5.33333333 C4.73333333,5.33333333 5.33333333,4.73333333 5.33333333,4 L5.33333333,1.33333333 C5.33333333,0.6 4.73333333,0 4,0 Z M4.44444444,4 C4.44444444,4.24444444 4.24444444,4.44444444 4,4.44444444 L1.33333333,4.44444444 C1.08888889,4.44444444 0.888888889,4.24444444 0.888888889,4 L0.888888889,1.33333333 C0.888888889,1.08888889 1.08888889,0.888888889 1.33333333,0.888888889 L4,0.888888889 C4.24444444,0.888888889 4.44444444,1.08888889 4.44444444,1.33333333 L4.44444444,4 Z M11.3333333,6.66666667 C11.0888889,6.66666667 10.8888889,6.86666667 10.8888889,7.11111111 L10.8888889,11.5555556 C10.8888889,11.8 11.0888889,12 11.3333333,12 C11.5777778,12 11.7777778,11.8 11.7777778,11.5555556 L11.7777778,7.11111111 C11.7777778,6.86666667 11.5777778,6.66666667 11.3333333,6.66666667 Z M10.6666667,0 L8,0 C7.26666667,0 6.66666667,0.6 6.66666667,1.33333333 L6.66666667,4 C6.66666667,4.73333333 7.26666667,5.33333333 8,5.33333333 L10.6666667,5.33333333 C11.4,5.33333333 12,4.73333333 12,4 L12,1.33333333 C12,0.6 11.4,0 10.6666667,0 Z M11.1111111,4 C11.1111111,4.24444444 10.9111111,4.44444444 10.6666667,4.44444444 L8,4.44444444 C7.75555556,4.44444444 7.55555556,4.24444444 7.55555556,4 L7.55555556,1.33333333 C7.55555556,1.08888889 7.75555556,0.888888889 8,0.888888889 L10.6666667,0.888888889 C10.9111111,0.888888889 11.1111111,1.08888889 11.1111111,1.33333333 L11.1111111,4 Z M7.33333333,7.33333333 C7.08888889,7.33333333 6.88888889,7.53333333 6.88888889,7.77777778 L6.88888889,11.5555556 C6.88888889,11.8 7.08888889,12 7.33333333,12 C7.57777778,12 7.77777778,11.8 7.77777778,11.5555556 L7.77777778,7.77777778 C7.77777778,7.53333333 7.57777778,7.33333333 7.33333333,7.33333333 Z M9.33333333,8.66666667 C9.08888889,8.66666667 8.88888889,8.86666667 8.88888889,9.11111111 L8.88888889,11.5555556 C8.88888889,11.8 9.08888889,12 9.33333333,12 C9.57777778,12 9.77777778,11.8 9.77777778,11.5555556 L9.77777778,9.11111111 C9.77777778,8.86666667 9.57777778,8.66666667 9.33333333,8.66666667 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>erweima</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-258, -919)" fill="#4284F7" fill-rule="nonzero">
<g id="erweima" transform="translate(258, 919)">
<path d="M4,6.66666667 L1.33333333,6.66666667 C0.6,6.66666667 0,7.26666667 0,8 L0,10.6666667 C0,11.4 0.6,12 1.33333333,12 L4,12 C4.73333333,12 5.33333333,11.4 5.33333333,10.6666667 L5.33333333,8 C5.33333333,7.26666667 4.73333333,6.66666667 4,6.66666667 Z M4.44444444,10.6666667 C4.44444444,10.9111111 4.24444444,11.1111111 4,11.1111111 L1.33333333,11.1111111 C1.08888889,11.1111111 0.888888889,10.9111111 0.888888889,10.6666667 L0.888888889,8 C0.888888889,7.75555556 1.08888889,7.55555556 1.33333333,7.55555556 L4,7.55555556 C4.24444444,7.55555556 4.44444444,7.75555556 4.44444444,8 L4.44444444,10.6666667 Z M4,0 L1.33333333,0 C0.6,0 0,0.6 0,1.33333333 L0,4 C0,4.73333333 0.6,5.33333333 1.33333333,5.33333333 L4,5.33333333 C4.73333333,5.33333333 5.33333333,4.73333333 5.33333333,4 L5.33333333,1.33333333 C5.33333333,0.6 4.73333333,0 4,0 Z M4.44444444,4 C4.44444444,4.24444444 4.24444444,4.44444444 4,4.44444444 L1.33333333,4.44444444 C1.08888889,4.44444444 0.888888889,4.24444444 0.888888889,4 L0.888888889,1.33333333 C0.888888889,1.08888889 1.08888889,0.888888889 1.33333333,0.888888889 L4,0.888888889 C4.24444444,0.888888889 4.44444444,1.08888889 4.44444444,1.33333333 L4.44444444,4 Z M11.3333333,6.66666667 C11.0888889,6.66666667 10.8888889,6.86666667 10.8888889,7.11111111 L10.8888889,11.5555556 C10.8888889,11.8 11.0888889,12 11.3333333,12 C11.5777778,12 11.7777778,11.8 11.7777778,11.5555556 L11.7777778,7.11111111 C11.7777778,6.86666667 11.5777778,6.66666667 11.3333333,6.66666667 Z M10.6666667,0 L8,0 C7.26666667,0 6.66666667,0.6 6.66666667,1.33333333 L6.66666667,4 C6.66666667,4.73333333 7.26666667,5.33333333 8,5.33333333 L10.6666667,5.33333333 C11.4,5.33333333 12,4.73333333 12,4 L12,1.33333333 C12,0.6 11.4,0 10.6666667,0 Z M11.1111111,4 C11.1111111,4.24444444 10.9111111,4.44444444 10.6666667,4.44444444 L8,4.44444444 C7.75555556,4.44444444 7.55555556,4.24444444 7.55555556,4 L7.55555556,1.33333333 C7.55555556,1.08888889 7.75555556,0.888888889 8,0.888888889 L10.6666667,0.888888889 C10.9111111,0.888888889 11.1111111,1.08888889 11.1111111,1.33333333 L11.1111111,4 Z M7.33333333,7.33333333 C7.08888889,7.33333333 6.88888889,7.53333333 6.88888889,7.77777778 L6.88888889,11.5555556 C6.88888889,11.8 7.08888889,12 7.33333333,12 C7.57777778,12 7.77777778,11.8 7.77777778,11.5555556 L7.77777778,7.77777778 C7.77777778,7.53333333 7.57777778,7.33333333 7.33333333,7.33333333 Z M9.33333333,8.66666667 C9.08888889,8.66666667 8.88888889,8.86666667 8.88888889,9.11111111 L8.88888889,11.5555556 C8.88888889,11.8 9.08888889,12 9.33333333,12 C9.57777778,12 9.77777778,11.8 9.77777778,11.5555556 L9.77777778,9.11111111 C9.77777778,8.86666667 9.57777778,8.66666667 9.33333333,8.66666667 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>jingti-copy</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="删除_弹框" transform="translate(-806, -410)" fill="#FB2727" fill-rule="nonzero">
<g id="jingti-copy" transform="translate(806, 410)">
<path d="M8,1.125 C8.928125,1.125 9.828125,1.30625 10.675,1.6640625 C11.49375,2.0109375 12.228125,2.50625 12.8609375,3.1375 C13.4921875,3.76875 13.9890625,4.5046875 14.334375,5.3234375 C14.69375,6.171875 14.875,7.071875 14.875,8 C14.875,8.928125 14.69375,9.828125 14.3359375,10.675 C13.9890625,11.49375 13.49375,12.228125 12.8625,12.8609375 C12.23125,13.4921875 11.4953125,13.9890625 10.6765625,14.334375 C9.828125,14.69375 8.928125,14.875 8,14.875 C7.071875,14.875 6.171875,14.69375 5.325,14.3359375 C4.50625,13.9890625 3.771875,13.49375 3.1390625,12.8625 C2.5078125,12.23125 2.0109375,11.4953125 1.665625,10.6765625 C1.30625,9.828125 1.125,8.928125 1.125,8 C1.125,7.071875 1.30625,6.171875 1.6640625,5.325 C2.0109375,4.50625 2.50625,3.771875 3.1375,3.1390625 C3.76875,2.5078125 4.5046875,2.0109375 5.3234375,1.665625 C6.171875,1.30625 7.071875,1.125 8,1.125 Z M8,0 C3.58125,0 0,3.58125 0,8 C0,12.41875 3.58125,16 8,16 C12.41875,16 16,12.41875 16,8 C16,3.58125 12.41875,0 8,0 Z M8,10 C7.6546875,10 7.375,9.7203125 7.375,9.375 L7.375,3.609375 C7.375,3.2640625 7.6546875,2.984375 8,2.984375 C8.3453125,2.984375 8.625,3.2640625 8.625,3.609375 L8.625,9.375 C8.625,9.7203125 8.3453125,10 8,10 Z M7.296875,11.703125 C7.296875,12.0914531 7.61167187,12.40625 8,12.40625 C8.38832813,12.40625 8.703125,12.0914531 8.703125,11.703125 C8.703125,11.3147969 8.38832812,11 8,11 C7.61167188,11 7.296875,11.3147969 7.296875,11.703125 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>guanli 2</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-124, -894)" fill="#000000" fill-rule="nonzero">
<g id="guanli" transform="translate(124, 894)">
<path d="M4.49064449,5.50676379 L0.997920994,5.50676379 C0.449064449,5.50676379 0,5.05723205 0,4.50780437 L0,1.01144641 C0,0.462018737 0.449064449,0.0124869995 0.997920994,0.0124869995 L4.49064449,0.0124869995 C5.03950104,0.0124869995 5.48856549,0.462018737 5.48856549,1.01144641 L5.48856549,4.50780437 C5.48856549,5.05723205 5.03950104,5.50676379 4.49064449,5.50676379 Z M4.5347973,4.50780437 L4.5347973,5.00728409 L4.5347973,4.50780437 Z M0.997920994,1.01144641 L0.997920994,4.50780437 L4.49064449,4.50780437 L4.49064449,1.01144641 L0.997920994,1.01144641 Z M9.00623701,6.0062435 C8.75675676,6.0062435 8.53222453,5.90634756 8.35758836,5.73152966 L6.28690229,3.65868887 C6.11226612,3.48387098 6.01247401,3.25910511 6.01247401,3.00936525 C6.01247401,2.75962539 6.11226611,2.53485953 6.28690229,2.36004162 L8.35758836,0.26222685 C8.70686072,-0.0874089499 9.30561332,-0.0874089499 9.65488566,0.26222685 L11.7255717,2.36004162 C11.9002079,2.53485952 12,2.75962539 12,3.00936525 C12,3.25910511 11.9002079,3.48387097 11.7255717,3.65868887 L9.65488566,5.73152966 C9.48024949,5.90634755 9.25571726,6.0062435 9.00623701,6.0062435 L9.00623701,6.0062435 Z M7.06029106,3.00936525 L9.03118504,4.98231009 L10.977131,3.00936525 L9.00623701,1.03642041 L7.06029106,3.00936525 Z M4.49064449,12 L0.997920994,12 C0.449064449,12 0,11.5504683 0,11.0010406 L0,7.50468262 C0,6.95525495 0.449064449,6.50572321 0.997920994,6.50572321 L4.49064449,6.50572321 C5.03950104,6.50572321 5.48856549,6.95525495 5.48856549,7.50468262 L5.48856549,11.0010406 C5.48856549,11.5504683 5.03950104,12 4.49064449,12 Z M4.5347973,11.0010406 L4.5347973,11.5005203 L4.5347973,11.0010406 Z M0.997920994,7.50468262 L0.997920994,11.0010406 L4.49064449,11.0010406 L4.49064449,7.50468262 L0.997920994,7.50468262 Z M11.002079,12 L7.50935551,12 C6.96049896,12 6.51143451,11.5504683 6.51143451,11.0010406 L6.51143451,7.50468262 C6.51143451,6.95525495 6.96049896,6.50572321 7.50935551,6.50572321 L11.002079,6.50572321 C11.5509356,6.50572321 12,6.95525495 12,7.50468262 L12,11.0010406 C12,11.5504683 11.5509356,12 11.002079,12 Z M11.0462318,11.0010406 L11.0462318,11.5005203 L11.0462318,11.0010406 Z M7.50935551,7.50468262 L7.50935551,11.0010406 L11.002079,11.0010406 L11.002079,7.50468262 L7.50935551,7.50468262 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>guanli</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" transform="translate(-124, -920)" fill="#4284F7" fill-rule="nonzero">
<g id="guanli" transform="translate(124, 920)">
<path d="M4.49064449,5.50676379 L0.997920994,5.50676379 C0.449064449,5.50676379 0,5.05723205 0,4.50780437 L0,1.01144641 C0,0.462018737 0.449064449,0.0124869995 0.997920994,0.0124869995 L4.49064449,0.0124869995 C5.03950104,0.0124869995 5.48856549,0.462018737 5.48856549,1.01144641 L5.48856549,4.50780437 C5.48856549,5.05723205 5.03950104,5.50676379 4.49064449,5.50676379 Z M4.5347973,4.50780437 L4.5347973,5.00728409 L4.5347973,4.50780437 Z M0.997920994,1.01144641 L0.997920994,4.50780437 L4.49064449,4.50780437 L4.49064449,1.01144641 L0.997920994,1.01144641 Z M9.00623701,6.0062435 C8.75675676,6.0062435 8.53222453,5.90634756 8.35758836,5.73152966 L6.28690229,3.65868887 C6.11226612,3.48387098 6.01247401,3.25910511 6.01247401,3.00936525 C6.01247401,2.75962539 6.11226611,2.53485953 6.28690229,2.36004162 L8.35758836,0.26222685 C8.70686072,-0.0874089499 9.30561332,-0.0874089499 9.65488566,0.26222685 L11.7255717,2.36004162 C11.9002079,2.53485952 12,2.75962539 12,3.00936525 C12,3.25910511 11.9002079,3.48387097 11.7255717,3.65868887 L9.65488566,5.73152966 C9.48024949,5.90634755 9.25571726,6.0062435 9.00623701,6.0062435 L9.00623701,6.0062435 Z M7.06029106,3.00936525 L9.03118504,4.98231009 L10.977131,3.00936525 L9.00623701,1.03642041 L7.06029106,3.00936525 Z M4.49064449,12 L0.997920994,12 C0.449064449,12 0,11.5504683 0,11.0010406 L0,7.50468262 C0,6.95525495 0.449064449,6.50572321 0.997920994,6.50572321 L4.49064449,6.50572321 C5.03950104,6.50572321 5.48856549,6.95525495 5.48856549,7.50468262 L5.48856549,11.0010406 C5.48856549,11.5504683 5.03950104,12 4.49064449,12 Z M4.5347973,11.0010406 L4.5347973,11.5005203 L4.5347973,11.0010406 Z M0.997920994,7.50468262 L0.997920994,11.0010406 L4.49064449,11.0010406 L4.49064449,7.50468262 L0.997920994,7.50468262 Z M11.002079,12 L7.50935551,12 C6.96049896,12 6.51143451,11.5504683 6.51143451,11.0010406 L6.51143451,7.50468262 C6.51143451,6.95525495 6.96049896,6.50572321 7.50935551,6.50572321 L11.002079,6.50572321 C11.5509356,6.50572321 12,6.95525495 12,7.50468262 L12,11.0010406 C12,11.5504683 11.5509356,12 11.002079,12 Z M11.0462318,11.0010406 L11.0462318,11.5005203 L11.0462318,11.0010406 Z M7.50935551,7.50468262 L7.50935551,11.0010406 L11.002079,11.0010406 L11.002079,7.50468262 L7.50935551,7.50468262 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -3,22 +3,6 @@ import App from './App.vue'
import router from './router'
import store from './store'
import vueKatexEs from "vue-katex";
import "katex/dist/katex.min.css"
Vue.use(vueKatexEs,{
globalOptions:{
delimiters:[
{left:"$$",right:"$$",display:true},
{left:"$",right:"$",display:false},
{left:"\\[",right:"\\]",display:true},
{left:"\\(",right:"\\)",display:false}
],
throwOnError:true
}
})
//import './mock/index'
import xpage from '@/utils/xpage'
@@ -41,14 +25,6 @@ import 'swiper/dist/css/swiper.css';
Vue.use(VueAwesomeSwiper)
import watermark from './utils/warterMark.js'
import Bus from './utils/bus.js'
import {showMessage} from './utils/index.js'
import MessageBoxService from './utils/simpleMessageBox.js'
Vue.use(MessageBoxService)
Vue.prototype.$showMessage = showMessage
Vue.prototype.$bus = Bus

View File

@@ -7,11 +7,7 @@ const state = {
withoutAnimation: false
},
device: 'desktop',//默认是桌面以后会有android,ios,minapp
size: Cookies.get('size') || 'medium', //字段大小
// 添加AI Call组件显示控制状态
showAICall: false,
// 控制AI Call最小化窗口在特定路由下显示的状态
showAICallMinimized: false
size: Cookies.get('size') || 'medium' //字段大小
}
const mutations = {
@@ -38,14 +34,6 @@ const mutations = {
SET_SIZE: (state, size) => {
state.size = size
Cookies.set('size', size)
},
// 添加控制AI Call组件显示的mutation
SET_SHOW_AI_CALL: (state, show) => {
state.showAICall = show
},
// 控制AI Call最小化窗口显示的mutation
SET_SHOW_AI_CALL_MINIMIZED: (state, show) => {
state.showAICallMinimized = show
}
}
@@ -61,14 +49,6 @@ const actions = {
},
setSize({ commit }, size) {
commit('SET_SIZE', size)
},
// 添加控制AI Call组件显示的action
setShowAICall({ commit }, show) {
commit('SET_SHOW_AI_CALL', show)
},
// 控制AI Call最小化窗口显示的action
setShowAICallMinimized({ commit }, show) {
commit('SET_SHOW_AI_CALL_MINIMIZED', show)
}
}
@@ -77,4 +57,4 @@ export default {
state,
mutations,
actions
}
}

View File

@@ -455,13 +455,4 @@ export function resOwnerListMap(source) {
})
let name = resOwnerList.get('GC005001')
return name;
}
export function showMessage(message, status) {
this.$message({
message: message,
type: status,
duration: 5000,
customClass: 'new-message'
});
}

View File

@@ -1,50 +0,0 @@
import Vue from 'vue'
import MessageBox from '@/components/SimpleMessageBox/index.vue'
// 创建 MessageBox 构造器
const MessageBoxConstructor = Vue.extend(MessageBox)
let messageBoxInstance = null
const MessageBoxService = {
open(options = {}) {
// 如果已有实例,先销毁
if (messageBoxInstance) {
messageBoxInstance.$destroy()
const el = messageBoxInstance.$el
if (el && el.parentNode) {
el.parentNode.removeChild(el)
}
}
// 创建新实例
messageBoxInstance = new MessageBoxConstructor({
el: document.createElement('div'),
data: options
})
// 挂载到 body
document.body.appendChild(messageBoxInstance.$el)
// 显示并返回 Promise
return messageBoxInstance.open(options)
},
cancel() {
messageBoxInstance.cancel()
},
confirm(options) {
return this.open({
...options
})
},
}
// 添加到 Vue 原型
MessageBoxService.install = function (Vue) {
Vue.prototype.$messageBox = MessageBoxService
}
// 导出
export default MessageBoxService

View File

@@ -1,83 +0,0 @@
/**
* 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)
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
<template>
<section class="app-main xuc-content">
<div class="main-body">
<CourseManage />
</div>
</section>
</template>
<script>
import CourseManage from './CourseManage.vue';
export default {
name: 'RemoteCourseManage',
components: { CourseManage },
};
</script>
<style lang="scss" scoped>
.app-main {
// padding-top: 20px;
}
.xuc-content {
margin: 0 auto;
}
.main-body {
background-color: #fff;
padding: 30px 20px;
}
</style>

View File

@@ -483,11 +483,8 @@ export default {
} else if (this.form.device2 === true) {
this.form.device = 2;
}
// 时长,秒与分钟的转化
if (this.form.minute) {
this.form.duration = this.form.minute * 60;
}
//时长,秒与分钟的转化
//if(this.form.)
try {
const { status,message} = await coueseFile.batchUpdate([this.form]);
if (status === 200) {

View File

@@ -123,6 +123,16 @@
</el-table-column>
<el-table-column label="创建人" prop="sysCreateBy"></el-table-column>
<el-table-column label="创建时间" prop="sysCreateTime" width="230px" show-overflow-tooltip></el-table-column>
<el-table-column label="审核人" prop="auditUser" width="130px" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.auditUser || '-' }}
</template>
</el-table-column>
<el-table-column label="审核时间" prop="auditTime" width="230px" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.auditTime || '-' }}
</template>
</el-table-column>
<el-table-column label="是否停用" width="130px">
<template slot-scope="scope">
{{ scope.row.enabled == true ? '启用' : '停用' }}

File diff suppressed because it is too large Load Diff

View File

@@ -6,60 +6,32 @@
3.建设课程邀请人流程提交审核流程都需要讨论 <br/>
4.有哪种几状态和哪几种操作需要讨论定一下 在哪种状态下可以有哪些操作<br/>
</Remark> -->
<el-row style="margin: 0 20px 20px 15px;" :gutter="8">
<el-col :span="8">
<div class="grid-content bg-purple"><el-input :maxlength="50" v-model="params.name" clearable
placeholder="课程名称" /></div>
</el-col>
<el-col :span="3">
<div class="grid-content bg-purple">
<el-select v-model="params.publish" placeholder="发布状态" clearable>
<el-option label="未发布" :value="false"></el-option>
<el-option label="已发布" :value="true"></el-option>
<div style="display: flex;justify-content:space-between;position: relative;">
<div style="display: flex;justify-content: flex-start; padding: 12px 32px 10px 12px;">
<!-- <div style="padding-left: 10px;">
<el-select style="width: 120px;" v-model="params.type" clearable placeholder="课程类型">
<el-option label="全部" :value="null"></el-option>
<el-option label="微课" :value="10"></el-option>
<el-option label="在线课" :value="20"></el-option>
</el-select>
</div> -->
<div style="padding-left: 10px;">
<el-select style="width: 120px;" v-model="params.status" clearable placeholder="状态">
<el-option label="全部" :value="null"></el-option>
<el-option label="草稿" :value="1"></el-option>
<el-option label="待审核" :value="2"></el-option>
<el-option label="已审核" :value="5"></el-option>
</el-select>
</div>
</el-col>
<el-col :span="3">
<div class="grid-content bg-purple">
<el-select v-model="params.enabled" placeholder="启停用状态" clearable>
<el-option label="停用" :value="false"></el-option>
<el-option label="启用" :value="true"></el-option>
</el-select>
</div>
</el-col>
<el-col :span="3">
<div class="grid-content bg-purple">
<el-select v-model="params.status" placeholder="审核状态" clearable>
<el-option label="-" :value="1"></el-option>
<el-option label="审核中" :value="2"></el-option>
<el-option label="审核驳回" :value="3"></el-option>
<el-option label="审核通过" :value="5"></el-option>
</el-select>
</div>
</el-col>
<el-col :span="2">
<div class="grid-content bg-purple">
<el-button type="primary" @click="findList"> </el-button>
</div>
</el-col>
<el-col :span="2">
<div class="grid-content bg-purple">
<el-button @click="reset"> </el-button>
</div>
</el-col>
<el-col :span="2">
<div class="grid-content bg-purple" style="text-align: right;">
<el-button type="primary" icon="el-icon-plus" @click="addNewCourse">新建课程</el-button>
</div>
</el-col>
</el-row>
<div style="margin-left:10px"><el-input v-model="params.keyword" placeholder="名称关键字" clearable></el-input></div>
<div style="padding-left: 10px;"><el-button type="primary" icon="el-icon-search" @click="findList()">搜索</el-button></div>
<div style="padding: 0px 5px;"><el-button icon="el-icon-refresh-right" type="primary" @click="reset">重置</el-button></div>
<div class="Create-coures"><el-button type="primary" @click="addNewCourse()" icon="el-icon-plus">新建课程</el-button></div>
</div>
</div>
<!--课程列表内容-->
<div v-infinite-scroll="load" style="overflow:auto;height:1000px" infinite-scroll-distance="50"
:infinite-scroll-immediate="false" :infinite-scroll-disabled="disabled">
<div style="">
<div class="uc-course" v-for="(item, idx) in couresList" :key="idx" @click="jumpRouter(item)">
<div class="uc-course-img" style="width: 212px;height:119px">
<course-image :course="item"></course-image>
@@ -67,38 +39,34 @@
</div>
<div class="uc-course-info">
<div class="uc-course-name">
<el-tooltip class="item" effect="dark" :content="item.name" placement="top-start">
<span style="font-size:18px;color:#333">{{ item.name }}</span>
</el-tooltip>
<!-- <span class="uc-course-type1">{{courseType(item.type)}}</span> -->
<span v-if="item.type == 10" class="uc-course-type1">录播</span>
<span v-if="item.type == 20" class="uc-course-type1">录播</span>
<span class="caogao" v-if="item.status == 1">草稿</span>
<span class="daishenhe" v-if="item.status == 2">待审核</span>
<span class="weitongguo" v-if="item.status == 3">审核未通过</span>
<span class="yishenhe" v-if="item.status == 5">已审核</span>
<!-- <a :href="`${webBaseUrl}/course/detail?id=${item.id}`" target="_blank"> {{item.name}}</a> -->
<span style="font-size:18px;color:#333">{{ item.name }}</span>
</div>
<div class="uc-course-item">
<div class="summary-item">
<div>{{ item.summary }}</div>
</div>
<div class="uc-course-text">
上次修改时间{{ item.sysUpdateTime }}
</div>
<div class="uc-course-item">
<div class="status-item">发布状态{{ item.published ? '发布' : '未发布' }}</div>
<div class="status-item">启停用状态{{ item.enabled ? '启用' : '停用' }}</div>
<div class="status-item">审核状态<el-link :type="getStatusLabel(item.status).type" @click.stop=""
:underline="false">{{getStatusLabel(item.status).label}}</el-link></div>
</div>
<div class="btn-container">
<el-link class="btn-item" @mouseenter.native="$set(hoverStates, it.uniqueKey, true )"
@mouseleave.native="$set(hoverStates, it.uniqueKey, false )"
:style="{color: it.labelColor ? it.labelColor : (hoverStates[it.uniqueKey] ? '#4284F7' : '#000000')}"
v-for="(it, idx) in availableActions(item)" :key="idx" :underline="false" type="primary"
@click.stop="it.handler(item)"><svg-icon
style="margin-right: 5px;font-size:19px;padding-top: 4px;color:#000000"
:icon-class="hoverStates[it.uniqueKey] ? it.hoverIcon : it.icon"></svg-icon>{{it.label}}</el-link>
<span type="text" style="margin-left:10px;font-size:14px;cursor: pointer;color:#666" @click.stop="toExamine(item)">查看审核记录</span>
</div>
</div>
<div class="uc-course-btns" style="line-height: 30px;">
<el-link style="display:block" :underline="false" @click.stop="examine(item)" type="primary" v-if="item.status == 1" icon="el-icon-document-checked">提交审核</el-link>
<el-link style="display:block" :underline="false" @click.stop="editCourse(item)" v-if="item.status == 3 || item.status == 4" type="primary" icon="el-icon-edit">编辑</el-link>
<el-link style="display:block" :underline="false" @click.stop="editCourse(item)" v-if="item.status == 1" type="primary" icon="el-icon-edit">去开发</el-link>
<el-link style="display:block" :underline="false" @click.stop="delItem(item)" v-if="item.status == 1" type="danger" icon="el-icon-delete">删除</el-link>
<el-link style="display:block" :underline="false" @click.stop="withdraw(item)" v-if="item.status == 2" type="info" icon="el-icon-delete">撤回</el-link>
</div>
</div>
<p v-if="loading" class="page-tip">加载中...</p>
<div v-if="couresList.length == 0 && !loading">
<div v-if="isSearh" class="zan-wu">没有查询到相关内容</div>
<div v-else class="zan-wu">暂无数据</div>
</div>
<p v-else-if="noMore" class="page-tip">没有更多了</p>
</div>
<!-- <div v-if="couresList.length > 0" style="text-align: center; margin-top:57px;">
<div v-if="couresList.length > 0" style="text-align: center; margin-top:57px;">
<el-pagination
background
@size-change="handleSizeChange"
@@ -111,146 +79,48 @@
></el-pagination>
</div>
<div v-else>
</div> -->
<div v-if="couresList.length == 0">
<div v-if="isSearh" class="zan-wu">没有查询到相关内容</div>
<div v-else class="zan-wu">暂无数据</div>
</div>
</div>
<div></div>
<el-dialog title="二维码" :visible.sync="qrCodedialogVisible" width="900px" @close="closeCode" custom-class="g-dialog">
<div>
<el-form size="medium" label-width="100px">
<el-form-item label="二维码">
<div id="qrcode" ref="qrcode" class="qrcode-img" @mouseenter="showDownloadButton = true"
@mouseleave="showDownloadButton = false">
<div v-show="showDownloadButton" @click="downloadQrcode" class="downloadn-container">
<i class="el-icon-download" style="color: #409EFF;font-size:18px;margin-bottom:5px"></i>
<span>下载</span>
</div>
</div>
</el-form-item>
<el-form-item label="链接">
<el-input v-model="copyUrl" readonly class="input-with-select" id="text">
<el-button slot="append" @click="handleCopyUrl">复制</el-button>
</el-input>
</el-form-item>
<el-form-item label="">上述内容兼容PC端与移动端您可按需分享</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer"><el-button @click="closeCode"> </el-button></span>
</el-dialog>
<!-- TODO 修改展示字段 -->
<el-dialog title="审核记录" :visible.sync="dialogVisible" width="900px" custom-class="g-dialog">
<div>
<el-table max-height="500" border :data="inviteTeacher" style="width: 100%;">
<el-table-column prop="type" label="审核类型">
<el-table-column prop="sysCreateBy" label="姓名" width="180"></el-table-column>
<el-table-column prop="type" label="审核状态">
<template slot-scope="scope">
{{ scope.row.auditState ? '通过' : '不通过' }}
</template>
</el-table-column>
<el-table-column prop="type" label="审核状态">
<template slot-scope="scope">
{{ auditEnum[scope.row.status] }}
</template>
</el-table-column>
<el-table-column prop="auditUser" label="审核人"></el-table-column>
<el-table-column prop="auditTime" label="审核结果"></el-table-column>
<el-table-column prop="auditTime" label="审核时间"></el-table-column>
<el-table-column prop="auditRemark" label="审核意见"></el-table-column>
<el-table-column prop="auditRemark" label="备注"></el-table-column>
</el-table>
</div>
<span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false"> </el-button></span>
<span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false"> </el-button></span>
</el-dialog>
<course-form ref="courseForm" @submitSuccess="getNewList"></course-form>
<course-form ref="courseForm" @submitSuccess="getList"></course-form>
</div>
</template>
<script>
import QRCode from "qrcodejs2";
import courseImage from "@/components/Course/courseImage.vue";
import { mapGetters } from "vuex";
import studyItem from "@/components/Course/studyItem.vue";
import courseForm from "@/components/Course/courseForm.vue";
import apiCourse from "@/api/modules/course.js";
import { courseType } from "@/utils/tools.js";
import apiAudit from "@/api/system/audit.js";
import apiHRBP from "@/api/boe/HRBP.js";
import apiOrg from "@/api/system/organiza.js";
import apiUserBasic from "@/api/boe/userbasic.js";
// 状态权限映射
const STATUS_PERMISSIONS = {
// 未发布状态
unpublished: {
1: ["edit", "delete"], // 无审核状态
2: ["auditRecord"], // 审核中'withdraw'
3: ["edit", "delete", "auditRecord"], // 审核驳回
},
// 已发布状态
published: {
enabled: {
1: ["edit", "manage", "auditRecord", "qrcode"], //'offShelfApply', 'viewCurrent'
2: ["manage", "auditRecord", "qrcode"], // withdraw , 'viewCurrent'
3: ["edit", "manage", "auditRecord", "qrcode"], //'offShelfApply', 'viewCurrent'
5: ["edit", "manage", "auditRecord", "qrcode"], //'offShelfApply', 'viewCurrent'
},
disabled: {
// 所有状态在停用时操作一致
1: ["manage", "auditRecord"], //, 'viewCurrent'
2: ["manage", "auditRecord"], //, 'viewCurrent'
3: ["manage", "auditRecord"], //, 'viewCurrent'
5: ["manage", "auditRecord"], //, 'viewCurrent'
},
},
};
// 操作配置映射表
const ACTION_CONFIG = {
edit: {
label: "编辑",
handler: "editCourse",
icon: "edit",
hoverIcon: "editHover",
},
manage: {
label: "管理",
handler: "handleManage",
icon: "manage",
hoverIcon: "manageHover",
},
// withdraw: { label: '撤回', handler: 'handleWithdraw' },
auditRecord: {
label: "审核记录",
handler: "toExamine",
icon: "check",
hoverIcon: "checkHover",
},
qrcode: {
label: "二维码",
handler: "handleQrcode",
icon: "ercode",
hoverIcon: "ercodeHover",
},
// offShelfApply: { label: '下架申请', handler: 'handleOffShelfApply' },
// viewCurrent: { label: '查看当前版本', handler: 'handleViewCurrent', icon: 'detail' },
delete: {
label: "删除",
labelColor: "#FF1718",
handler: "delItem",
icon: "del",
hoverIcon: "del",
},
};
import courseImage from '@/components/Course/courseImage.vue';
import { mapGetters } from 'vuex';
import studyItem from '@/components/Course/studyItem.vue';
import courseForm from '@/components/Course/courseForm.vue';
import apiCourse from '@/api/modules/course.js';
import { courseType } from '@/utils/tools.js';
import apiAudit from '@/api/system/audit.js';
import apiHRBP from '@/api/boe/HRBP.js';
import apiOrg from '@/api/system/organiza.js';
import apiUserBasic from '@/api/boe/userbasic.js';
export default {
name: "ucStudyIndex",
name: 'ucStudyIndex',
components: { studyItem, courseForm, courseImage },
computed: {
...mapGetters(["userInfo"]),
disabled() {
return this.loading || this.noMore;
},
...mapGetters(['userInfo'])
},
data() {
@@ -260,42 +130,19 @@ export default {
courseType: courseType,
fileBaseUrl: process.env.VUE_APP_FILE_BASE_URL,
count: 0,
params: {
name: "",
publish: "",
status: "",
enabled: "",
pageIndex: 0,
pageSize: 10,
},
params: { keyword: '', type: '', status: '', createUser: '', pageIndex: 1, pageSize: 10, sysCreateAid: '' },
couresList: [],
flag: true,
isSearh: false,
qrCodedialogVisible: false,
copyUrl: "",
qrcodeImgUrl: "",
showDownloadButton: false, // 是否显示下载按钮
loading: false,
noMore: false,
auditEnum: {
1: "未审核",
2: "审核不通过",
9: "审核通过",
},
hoverStates: {},
isSearh:false,
};
},
mounted() {
if (
this.$route.query &&
this.$route.query.open &&
this.$route.query.open == "new"
) {
this.addNewCourse();
if(this.$route.query && this.$route.query.open && this.$route.query.open == 'new') {
this.addNewCourse();
}
// this.getList();
this.getList();
},
watch: {
watch:{
// '$route.query.open':function(val){
// if(val == 'new') {
// this.addNewCourse();
@@ -303,331 +150,236 @@ export default {
// }
},
methods: {
handleM() {
console.log("handleM");
},
load() {
this.loading = true;
this.params.pageIndex++;
this.getList();
},
getNewList() {
this.couresList = [];
this.params.pageIndex = 1;
this.getList();
},
getStatusLabel(code) {
if (code == "1") {
return { type: "info", label: "-" };
} else if (code == "2") {
return { type: "warning", label: "审核中" };
} else if (code == "3") {
return { type: "danger", label: "审核驳回" };
} else if (code == "5") {
return { type: "success", label: "审核通过" };
}
},
// 获取可用的操作配置
availableActions(item) {
const { status, published, enabled } = item;
let actionKeys = [];
if (!published) {
// 未发布状态
actionKeys = STATUS_PERMISSIONS.unpublished[status] || [];
} else {
// 已发布状态
const stateKey = enabled ? "enabled" : "disabled";
actionKeys = STATUS_PERMISSIONS.published[stateKey][status] || [];
}
return actionKeys
.map((key, index) => ({
name: key,
label: ACTION_CONFIG[key].label,
handler: this[ACTION_CONFIG[key].handler],
icon: ACTION_CONFIG[key].icon,
hoverIcon: ACTION_CONFIG[key].hoverIcon,
labelColor: ACTION_CONFIG[key].labelColor,
uniqueKey: `${item.id}-${key}-${index}`,
}))
.filter(Boolean);
},
handleManage(item) {
sessionStorage.setItem("courseDetail", JSON.stringify(item));
this.$router.push({ path: "/course/coursemanage" });
},
downloadQrcode() {
let img = document
.getElementById("qrcode")
.getElementsByTagName("img")[0];
let canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
let tempUrl = canvas.toDataURL("image/png");
// 创建a标签下载
let link = document.createElement("a"); //创建a标签
link.style.display = "none"; //使其隐藏
link.download = tempUrl;
link.setAttribute("target", "_blank");
link.href = tempUrl; //赋予文件下载地址
link.setAttribute("download", "二维码.jpg"); //设置下载属性 以及文件名
document.body.appendChild(link); //a标签插至页面中
link.click(); //强制触发a标签事件
document.body.removeChild(link);
},
handleCopyUrl() {
document.getElementById("text").select();
document.execCommand("Copy");
this.$showMessage('复制成功', 'success')
},
handleQrcode(row) {
this.qrCodedialogVisible = true;
let urlPre = window.location.protocol + "//" + window.location.host;
//动态的地址
//urlPre=urlPre+'/m?returnUrl='+urlPre+'/mobile/pages/login/loading?returnUrl=';
//固定的地址
// let returnUrl=urlPre+'/mobile/pages/login/loading?returnUrl=/pages/study/courseStudy?id='+row.id;
// let mobilePre=urlPre+'/m?returnUrl=';
// this.qrcodeImgUrl = mobilePre+encodeURIComponent(returnUrl);
// this.copyUrl=urlPre+this.webBaseUrl+'/course/studyindex?id='+row.id;
// if(row.type==20){
// this.copyUrl=urlPre+this.webBaseUrl+'/course/detail?id='+row.id;
// }
this.copyUrl = this.qrcodeImgUrl =
process.env.VUE_APP_BOE_WEB_URL +
"/systemapi/xboe/m/course/manage/redirectDetail?courseId=" +
row.id;
console.log("qrcodeImgUrl", this.qrcodeImgUrl);
console.log("webBaseUrl", this.webBaseUrl);
// 使用$nextTick确保数据渲染
this.$nextTick(() => {
this.crateQrcode();
});
},
// 生成二维码
crateQrcode() {
let qrcode = new QRCode("qrcode", {
width: 150,
height: 150, // 高度
text: this.qrcodeImgUrl, // 二维码内容
// render: 'canvas' // 设置渲染方式(有两种方式 table和canvas默认是canvas
// background: '#f0f'
// foreground: '#ff0'
});
console.log("qrcode", qrcode);
},
// 关闭弹框,清除已经生成的二维码
closeCode() {
this.qrCodedialogVisible = false;
// 逐个节点移除防止事件一起移除
let images = document.querySelectorAll(".qrcode-img img");
images.forEach((img) => img.remove());
let canvas = document.querySelectorAll(".qrcode-img canvas");
canvas.forEach((canvas) => canvas.remove());
},
// 撤回接口
withdraw(item) {
this.$confirm("此操作将撤回审核中的课程, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
this.$confirm('此操作将撤回审核中的课程, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
apiCourse.revokeSubmit(item.id).then((res) => {
apiCourse.revokeSubmit(item.id).then(res => {
if (res.status == 200) {
if (res.result) {
this.$message({
type: "success",
message: "撤回成功!",
type: 'success',
message: '撤回成功!'
});
this.getNewList();
this.getList();
}
}
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消撤回",
type: 'info',
message: '已取消撤回'
});
});
},
reset() {
this.params.name = "";
this.params.publish = "";
this.params.status = "";
this.params.enabled = "";
this.params.keyword = '';
this.params.status = '';
this.params.type = '';
this.params.pageIndex = 1;
this.getNewList();
this.isSearh = false;
this.getList();
this.isSearh = false;
},
toExamine(row) {
// this.detailType = row.type;
this.dialogVisible = true;
apiCourse
.auditCourseRecords({
courseId: row.id,
})
.then((res) => {
if (res.status === 200) {
this.inviteTeacher = res.result;
} else {
this.$message.error(res.message);
}
});
},
examine(row) {
if (!row.orgId) {
this.$message.error("课程还未设置资源归属,请先设置资源归属");
return;
}
let $this = this;
this.$confirm("您确定要直接提交审核所选课程吗?", "友情提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
//新的提交流程
apiUserBasic.getOrgHrbpInfo(row.orgId).then((rs) => {
if (rs.status == 200 && rs.result) {
let req = {
courseId: row.id,
email: rs.result.email,
courseUser: row.sysCreateBy,
courseName: row.name,
ucode: rs.result.userNo,
auditUser: rs.result.name,
//ukid:hrbpUser.user_id,
orgId: row.orgId,
orgName: rs.result.orgNamePath + "/" + rs.result.name,
};
apiCourse.sumbits(req).then((res) => {
if (res.status == 200) {
$this.$message.success("提交成功");
row.status = 2;
}
if (res.status == 400) {
$this.$message.error("提交失败:" + res.message);
}
});
} else {
$this.$message.error("获取HRBP审核人员失败:" + rs.message);
}
});
apiAudit.page(1, row.id).then(res => {
if (res.status === 200) {
this.inviteTeacher = res.result;
} else {
this.$message.error(res.message);
}
});
},
async delItem(row) {
this.$messageBox.confirm({
title: "删除确认",
message: `确认删除${row.name}吗?`,
handleConfirm: async () => {
examine(row) {
if(!row.orgId){
this.$message.error("课程还未设置资源归属,请先设置资源归属");
return;
}
let $this=this;
this.$confirm('您确定要直接提交审核所选课程吗?', '友情提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(()=>{
//新的提交流程
apiUserBasic.getOrgHrbpInfo(row.orgId).then(rs=>{
if(rs.status==200 && rs.result){
let req={
courseId:row.id,
email:rs.result.email,
courseUser:row.sysCreateBy,
courseName:row.name,
ucode:rs.result.userNo,
auditUser:rs.result.name,
//ukid:hrbpUser.user_id,
orgId:row.orgId,
orgName:rs.result.orgNamePath +'/'+rs.result.name
}
apiCourse.sumbits(req).then(res=>{
if(res.status==200){
$this.$message.success('提交成功');
row.status=2
}
if(res.status==400){
$this.$message.error('提交失败:'+res.message);
}
})
}else{
$this.$message.error("获取HRBP审核人员失败:"+rs.message);
}
});
// apiOrg.getSimple(row.orgId).then(rrs=>{
// if(rrs.status==200){
// apiHRBP.getHRBP(rrs.result.kid).then(rs=>{
// if(rs.status==200 && rs.result.length>0){
// let hrbpUser=rs.result[0];
// let req={
// courseId:row.id,
// email:hrbpUser.email,
// courseUser:row.sysCreateBy,
// courseName:row.name,
// ucode:hrbpUser.user_no,
// auditUser:hrbpUser.real_name,
// ukid:hrbpUser.user_id,
// orgId:row.orgId,
// orgName:rs.result.orgnization_name_path+'/'+rrs.result.name
// }
// apiCourse.sumbits(req).then(res=>{
// if(res.status==200){
// $this.$message.success('提交成功');
// row.status=2
// }
// if(res.status==400){
// $this.$message.error('提交失败:'+res.message);
// }
// })
// }else{
// $this.$message.error("获取HRBP审核人员失败:"+rs.message);
// }
// })
// }else{
// $this.$message.error("处理资源归属失败,请重新设置资源归属");
// }
// })
})
},
delItem(row) {
this.$confirm('您确定要删除所选课程吗?', '删除提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
let params = {
id: row.id,
title: row.name,
title: row.name
};
try {
// {id:课程id,多个使用逗号分隔,Boolean erasable 是否物理删除,title:课程的名称, remark 备注}
const { status } = await apiCourse.del(params);
if (status === 200) {
this.$showMessage('删除成功', 'success')
// this.$message.success("操作成功!");
this.getNewList();
} else {
this.$showMessage('删除失败', 'error')
this.$message.success('操作成功!');
//事件移到后端处理
// if(!row.erasable){
// let event = {
// key: "DeleteCourse",//被管理员删除
// title: '自己删除课程',//事件的标题
// parameters:"author:"+this.userInfo.aid,//自己删除自己的课程,作者就是当前人
// content: '自己删除课程',//事件的内容
// objId: row.id,//关联的id
// objType: "1",//关联的类型
// objInfo:row.name,
// aid: this.userInfo.aid, //当前登录人的id
// aname: this.userInfo.name,//当前人的姓名
// status: 1 //状态直接写1
// }
// this.$store.dispatch("userTrigger", event);
// }
this.getList();
}
} catch (error) {
console.log(error);
}
},
handleCancel: () => {
this.$showMessage('已取消删除', 'warning')
},
});
})
.catch(err => {
this.$message({ type: 'info', message: '已取消删除', offset: 50 });
});
},
jumpRouter(item) {
if (item.published) {
// if (item.type == 10) {
// let routeData = this.$router.resolve({ path: '/course/micro?id='+item.id});
// window.open(this.webBaseUrl+routeData.href, '_blank');
// let routeData = this.$router.resolve({ path: '/course/micro?id='+item.id});
// window.open(this.webBaseUrl+routeData.href, '_blank');
// window.open(this.webBaseUrl + '/course/micro?id=' + item.id, '_blank');
// this.$router.push({path:'/course/micro',query:{id:item.id}})
// this.$router.push({path:'/course/micro',query:{id:item.id}})
// }
// if (item.type == 20) {
// let routeData = this.$router.resolve({ path: '/course/detail?id='+item.id});
// window.open(this.webBaseUrl+routeData.href, '_blank');
// window.open(this.webBaseUrl + '/course/detail?id=' + item.id, '_blank');
//this.$router.push({path:'/course/detail',query:{id:item.id}})
this.$router.push({
path: "/course/studyindex",
query: { id: item.id },
});
// }
// let routeData = this.$router.resolve({ path: '/course/detail?id='+item.id});
// window.open(this.webBaseUrl+routeData.href, '_blank');
// window.open(this.webBaseUrl + '/course/detail?id=' + item.id, '_blank');
//this.$router.push({path:'/course/detail',query:{id:item.id}})
this.$router.push({path:'/course/studyindex',query:{id:item.id}})
// }
} else {
// if (item.type == 10) {
// // window.open(`${this.webBaseUrl}/course/microPreview?id=${item.id}`);
// this.$router.push({path:'/course/microPreview',query:{id:item.id}})
// } else {
// window.open(`${this.webBaseUrl}/course/rePreview?id=${item.id}`);
this.$router.push({
path: "/course/rePreview",
query: { id: item.id },
});
this.$router.push({path:'/course/rePreview',query:{id:item.id}})
// }
}
},
findList() {
this.params.pageIndex = 1;
this.isSearh = true;
this.getNewList();
this.getList();
},
getList() {
this.noMore = false;
// this.params.teacherId = this.userInfo.aid;
apiCourse.courseList(this.params).then((res) => {
this.loading = false;
this.params.aid = this.userInfo.aid;
apiCourse.pageList(this.params).then(res => {
if (res.status == 200) {
this.couresList = [...this.couresList, ...res.result.list];
this.couresList = res.result.list;
this.count = res.result.count;
console.log(this.couresList.length, "this.count", this.count);
if (this.couresList.length >= this.count) {
this.noMore = true;
}
} else {
this.$showMessage(res.message, 'error')
this.$message.error(res.message);
}
});
},
handleSizeChange(val) {
this.params.pageSize = val;
// this.params.pageIndex = 1;
this.getList();
},
handleCurrentChange(val) {
this.params.pageIndex = val;
this.getList();
},
addNewCourse() {
this.$refs.courseForm.initShow();
},
editCourse(row) {
console.log(row, "editCourse");
this.$refs.courseForm.initShow(row);
},
lastTabChange(tab, event) {
console.log(tab.name);
},
},
}
}
};
</script>
<style scoped lang="scss">
.page-tip {
margin: 20px auto;
text-align: center;
font-size: 13px;
}
.list-wu {
.list-wu{
text-align: center;
margin: 40px;
color: #333;
@@ -670,35 +422,6 @@ export default {
margin-top: 10px;
margin-right: 40px;
}
.qrcode-img {
width: 150px;
height: 150px;
display: block;
position: relative;
.downloadn-container {
position: absolute;
width: 40px;
height: 45px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 99;
background: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
cursor: pointer;
span {
color: #409eff;
display: block;
font-size: 12px;
line-height: 12px;
}
}
}
.uc-course {
cursor: pointer;
display: flex;
@@ -706,11 +429,10 @@ export default {
border-bottom: 1px solid #e8e8e8;
padding: 20px 0px 15px 0px;
margin: 0 32px 0 22px;
::v-deep .uc-course-img {
::v-deep .uc-course-img {
width: 212px;
img {
width: 212px;
height: 119px;
width: 212px;height:119px;
border: 1px solid #f4f4f5;
}
}
@@ -726,7 +448,7 @@ export default {
font-size: 14px;
overflow: hidden;
width: 90%;
word-break: break-all;
word-break:break-all;
display: -webkit-box;
// overflow: hidden;
-webkit-box-orient: vertical;
@@ -735,36 +457,22 @@ export default {
.uc-course-name {
font-size: 16px;
display: -webkit-box;
white-space: pre-wrap;
// word-wrap: break-word;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
word-break: break-all;
white-space:pre-wrap;
// word-wrap: break-word;
overflow: hidden;
text-overflow:ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
word-break:break-all;
// font-weight: 700;
}
.uc-course-item {
.uc-course-text {
color: #666;
// margin-top: 4px;
font-size: 14px;
display: flex;
// flex-wrap: nowrap;
.status-item {
margin-right: 20px;
flex-shrink: 0;
}
}
.btn-container {
margin-top: 10px;
display: flex;
.btn-item {
margin-right: 20px;
}
margin-top: 28px;
}
}
.uc-course-btns {
text-align: right;
.btn1 {
height: 44px;

View File

@@ -1,873 +0,0 @@
<template>
<div>
<!-- 最大化状态的弹窗 -->
<el-dialog
v-show=" windowState === 'maximized'"
v-if="dialogVisible"
:visible="true"
:close-on-click-modal="false"
:show-close="true"
@close="onClose"
class="case-expert-dialog"
:modal="false"
:append-to-body="true"
:fullscreen="false"
top="10vh"
v-resizeable
v-draggable
>
<!-- 标题 -->
<div slot="title" class="dialog-title">
<span>案例专家</span>
<el-button
style="color:#96999f"
type="text"
class="window-control-btn"
@click="minimizeWindow"
>
<i class="el-icon-minus"></i>
</el-button>
</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" @getMinWindow="minimizeWindow"></messages>
</div>
<div class="message-suggestions" v-if="messageList.length > 0 && 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>
<!-- 最小化状态的弹窗 -->
<div
class="minimized-window"
v-show="windowState === 'minimized' && showMinimizedWindow"
@click="onMinimizedWindowClick"
>
<div class="minimized-content">
<span class="window-title">案例专家</span>
<div style="display: flex;align-items: center">
<el-button
type="text"
class="window-control-btn"
@click.stop="onMinimizedWindowClick"
>
<img :src="openImg" alt="" style="width: 17px">
</el-button>
<el-button
style="margin-left: 1px;color:#96999f"
type="text"
class="window-control-btn"
@click.stop="closeMinimizedWindow"
>
<i class="el-icon-close"></i>
</el-button>
</div>
</div>
<div class="minimized-message">
<div v-if="messageList.length <= 1 && messageList[0].isBot">
当前暂无对话内容去创建对话吧
</div>
<div v-else>
{{ getLastUserMessage() }}
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import messages from './components/messages.vue'
import sendMessage from './components/sendMessage.vue'
import openImg from './components/open.png'
export default {
name: 'CaseExpertDialog',
props: {
dialogVisible: {
type: Boolean,
default: false
}
},
components: {
messages,
sendMessage
},
directives: {
draggable: {
bind(el, binding, vnode) {
vnode.context.$nextTick(() => {
const dialogEl = el.querySelector('.el-dialog');
if (!dialogEl) return;
const headerEl = dialogEl.querySelector('.dialog-title');
if (!headerEl) return;
// 检查是否有保存的位置状态
const savedPosition = sessionStorage.getItem('aiCallDialogPosition');
if (savedPosition) {
const { left, top } = JSON.parse(savedPosition);
dialogEl.style.left = left + 'px';
dialogEl.style.top = top + 'px';
} else {
// 设置初始样式
dialogEl.style.position = 'fixed';
dialogEl.style.top = '100px';
dialogEl.style.left = (window.innerWidth - dialogEl.offsetWidth) / 2 + 'px';
}
dialogEl.style.margin = '0';
let isDragging = false;
let startX = 0;
let startY = 0;
let startLeft = 0;
let startTop = 0;
const startDrag = (event) => {
// 只有在标题栏上按下鼠标才开始拖动
if (event.target.closest('.resize-handle')) {
return; // 如果点击的是resize-handle则不触发拖动
}
isDragging = true;
startX = event.clientX;
startY = event.clientY;
startLeft = parseInt(dialogEl.style.left) || dialogEl.offsetLeft;
startTop = parseInt(dialogEl.style.top) || dialogEl.offsetTop;
event.preventDefault();
event.stopPropagation();
// 添加全局事件监听
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', stopDrag);
};
const handleMouseMove = (event) => {
if (!isDragging) return;
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
dialogEl.style.left = (startLeft + deltaX) + 'px';
dialogEl.style.top = (startTop + deltaY) + 'px';
};
const stopDrag = () => {
isDragging = false;
// 保存当前位置到 sessionStorage
const currentPosition = {
left: parseInt(dialogEl.style.left),
top: parseInt(dialogEl.style.top)
};
sessionStorage.setItem('aiCallDialogPosition', JSON.stringify(currentPosition));
// 移除全局事件监听
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', stopDrag);
};
// 为标题栏绑定拖动事件
headerEl.addEventListener('mousedown', startDrag);
});
}
},
resizeable: {
bind(el, binding, vnode) {
// 确保元素已插入DOM
vnode.context.$nextTick(() => {
const dialogEl = el.querySelector('.el-dialog');
if (!dialogEl) return;
// 检查是否有保存的尺寸状态
const savedSize = sessionStorage.getItem('aiCallDialogSize');
if (savedSize) {
const { width, height, left, top } = JSON.parse(savedSize);
dialogEl.style.width = width + 'px';
dialogEl.style.height = height + 'px';
dialogEl.style.left = left + 'px';
dialogEl.style.top = top + 'px';
} else {
// 设置初始样式
dialogEl.style.position = 'fixed';
dialogEl.style.top = '100px';
dialogEl.style.left = (window.innerWidth - dialogEl.offsetWidth) / 2 + 'px';
}
// 创建拖拽手柄
const createHandle = (direction) => {
const handle = document.createElement('div');
handle.className = `resize-handle ${direction}`;
handle.style.position = 'absolute';
handle.style.zIndex = '10';
switch (direction) {
case 'left':
case 'right':
handle.style.width = '6px';
handle.style.height = '100%';
handle.style.top = '0';
handle.style.cursor = 'ew-resize';
break;
case 'top':
case 'bottom':
handle.style.width = '100%';
handle.style.height = '6px';
handle.style.left = '0';
handle.style.cursor = 'ns-resize';
break;
case 'top-left':
case 'top-right':
case 'bottom-left':
case 'bottom-right':
handle.style.width = '10px';
handle.style.height = '10px';
handle.style.zIndex = '20';
break;
}
switch (direction) {
case 'left':
handle.style.left = '0';
break;
case 'right':
handle.style.right = '0';
break;
case 'top':
handle.style.top = '0';
break;
case 'bottom':
handle.style.bottom = '0';
break;
case 'top-left':
handle.style.top = '0';
handle.style.left = '0';
handle.style.cursor = 'nw-resize';
break;
case 'top-right':
handle.style.top = '0';
handle.style.right = '0';
handle.style.cursor = 'ne-resize';
break;
case 'bottom-left':
handle.style.bottom = '0';
handle.style.left = '0';
handle.style.cursor = 'sw-resize';
break;
case 'bottom-right':
handle.style.bottom = '0';
handle.style.right = '0';
handle.style.cursor = 'se-resize';
break;
}
// 防止拖拽手柄的事件冒泡到标题栏
handle.addEventListener('mousedown', (e) => {
e.stopPropagation();
});
dialogEl.appendChild(handle);
return handle;
};
// 创建8个拖拽手柄
const handles = {
left: createHandle('left'),
right: createHandle('right'),
top: createHandle('top'),
bottom: createHandle('bottom'),
topLeft: createHandle('top-left'),
topRight: createHandle('top-right'),
bottomLeft: createHandle('bottom-left'),
bottomRight: createHandle('bottom-right')
};
// 添加拖拽事件处理
let isResizing = false;
let resizeDirection = '';
let startX = 0;
let startY = 0;
let startWidth = 0;
let startHeight = 0;
let startLeft = 0;
let startTop = 0;
const startResize = (direction, event) => {
event.preventDefault();
event.stopPropagation();
isResizing = true;
resizeDirection = direction;
startX = event.clientX;
startY = event.clientY;
startWidth = dialogEl.offsetWidth;
startHeight = dialogEl.offsetHeight;
// 统一使用计算后的样式值
startLeft = parseInt(dialogEl.style.left) || 0;
startTop = parseInt(dialogEl.style.top) || 0;
// 添加全局事件监听
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', stopResize);
};
const handleMouseMove = (event) => {
if (!isResizing) return;
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
let newWidth, newHeight, newLeft, newTop;
switch (resizeDirection) {
case 'right':
newWidth = Math.max(400, startWidth + deltaX);
dialogEl.style.width = newWidth + 'px';
break;
case 'left':
newWidth = Math.max(400, startWidth - deltaX);
newLeft = startLeft + startWidth - newWidth;
dialogEl.style.width = newWidth + 'px';
dialogEl.style.left = newLeft + 'px';
break;
case 'bottom':
newHeight = Math.max(600, startHeight + deltaY);
dialogEl.style.height = newHeight + 'px';
break;
case 'top':
// 当窗口高度达到最小值时,不再调整高度和位置
if (startHeight - deltaY >= 600) {
newHeight = startHeight - deltaY;
newTop = startTop + deltaY;
dialogEl.style.height = newHeight + 'px';
dialogEl.style.top = newTop + 'px';
}
break;
case 'bottom-right':
newWidth = Math.max(400, startWidth + deltaX);
newHeight = Math.max(600, startHeight + deltaY);
dialogEl.style.width = newWidth + 'px';
dialogEl.style.height = newHeight + 'px';
break;
case 'bottom-left':
newWidth = Math.max(400, startWidth - deltaX);
newHeight = Math.max(600, startHeight + deltaY);
newLeft = startLeft + startWidth - newWidth;
dialogEl.style.width = newWidth + 'px';
dialogEl.style.left = newLeft + 'px';
dialogEl.style.height = newHeight + 'px';
break;
case 'top-right':
// 当窗口高度达到最小值时,不再调整高度和位置
if (startHeight - deltaY >= 600) {
newHeight = startHeight - deltaY;
newTop = startTop + deltaY;
newWidth = Math.max(400, startWidth + deltaX);
dialogEl.style.height = newHeight + 'px';
dialogEl.style.top = newTop + 'px';
dialogEl.style.width = newWidth + 'px';
}
break;
case 'top-left':
// 当窗口高度达到最小值时,不再调整高度和位置
if (startHeight - deltaY >= 600) {
newHeight = startHeight - deltaY;
newTop = startTop + deltaY;
newWidth = Math.max(400, startWidth - deltaX);
newLeft = startLeft + startWidth - newWidth;
dialogEl.style.height = newHeight + 'px';
dialogEl.style.top = newTop + 'px';
dialogEl.style.width = newWidth + 'px';
dialogEl.style.left = newLeft + 'px';
}
break;
}
let doc = document.querySelector('.welcome-message')
let sendBox = document.querySelector('.input-area-wrapper');
// sendBox 的高度
if (doc && sendBox) {
doc.style.height = `calc(${dialogEl.style.height} - ${sendBox.offsetHeight}px - 120px)`;
}
};
const stopResize = () => {
isResizing = false;
resizeDirection = '';
// 保存当前尺寸和位置到 sessionStorage
const currentSize = {
width: parseInt(dialogEl.style.width),
height: parseInt(dialogEl.style.height),
left: parseInt(dialogEl.style.left),
top: parseInt(dialogEl.style.top)
};
sessionStorage.setItem('aiCallDialogSize', JSON.stringify(currentSize));
// 移除全局事件监听
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', stopResize);
};
// 为每个手柄绑定事件
handles.left.addEventListener('mousedown', (e) => startResize('left', e));
handles.right.addEventListener('mousedown', (e) => startResize('right', e));
handles.top.addEventListener('mousedown', (e) => startResize('top', e));
handles.bottom.addEventListener('mousedown', (e) => startResize('bottom', e));
handles.topLeft.addEventListener('mousedown', (e) => startResize('top-left', e));
handles.topRight.addEventListener('mousedown', (e) => startResize('top-right', e));
handles.bottomLeft.addEventListener('mousedown', (e) => startResize('bottom-left', e));
handles.bottomRight.addEventListener('mousedown', (e) => startResize('bottom-right', e));
});
}
}
},
computed: {
...mapState('app', ['showAICallMinimized']),
showMinimizedWindow() {
// 只有在Vuex状态为true时才显示最小化窗口
return this.showAICallMinimized;
}
},
data() {
return {
openImg,
AIContent: '',
isLoading: false,
windowState: 'maximized', // 'maximized' 或 'minimized'
messageList: [
{
typing:true,
isBot: true, // 是否为机器人
text: `<p><b>您好!我是京东方案例智能问答助手,随时为您服务。</b></p>
<p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p>
<p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p>
<p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>`
}
],
suggestions:[],
isAutoScroll: true, // 是否自动滚动
// 添加一个标志位,用于标识组件是否已经初始化完成
isComponentReady: false
}
},
mounted() {
// 组件挂载完成后,标记为已准备就绪
this.$nextTick(() => {
this.isComponentReady = true;
});
},
watch: {
dialogVisible: {
handler(newVal) {
if (newVal) {
this.$nextTick(() => {
// 获取对话框元素
const dialogEl = document.querySelector('.case-expert-dialog .el-dialog');
if (dialogEl) {
// 检查是否有保存的尺寸状态
const savedSize = sessionStorage.getItem('aiCallDialogSize');
if (savedSize) {
const { width, height, left, top } = JSON.parse(savedSize);
dialogEl.style.width = width + 'px';
dialogEl.style.height = height + 'px';
dialogEl.style.left = left + 'px';
dialogEl.style.top = top + 'px';
}
// 检查是否有保存的位置状态
const savedPosition = sessionStorage.getItem('aiCallDialogPosition');
if (savedPosition) {
const { left, top } = JSON.parse(savedPosition);
dialogEl.style.left = left + 'px';
dialogEl.style.top = top + 'px';
}
}
let doc = document.querySelector('.welcome-message')
let sendBox = document.querySelector('.input-area-wrapper');
// 只有在没有保存的尺寸状态时才使用默认值
if (doc && sendBox) {
const savedSize = sessionStorage.getItem('aiCallDialogSize');
if (!savedSize) {
doc.style.height = `calc(600px - ${sendBox.offsetHeight}px - 120px)`;
} else {
const { height } = JSON.parse(savedSize);
doc.style.height = `calc(${height}px - ${sendBox.offsetHeight}px - 120px)`;
}
}
});
}
},
immediate: true
},
messageList: {
handler() {
// 只有在组件准备就绪后才执行滚动操作
if (this.isComponentReady) {
this.$nextTick(() => {
this.scrollToBottom();
});
}
},
deep: true
}
},
methods: {
// / 关闭最小化窗口
closeMinimizedWindow() {
this.$store.commit('app/SET_SHOW_AI_CALL_MINIMIZED', false);
this.$store.commit('app/SET_SHOW_AI_CALL', false);
this.windowState = 'maximized';
},
getMinWidow(vis){
// this.showAICallMinimized = vis
this.windowState = 'minimized';
},
onClose() {
console.log('关闭弹窗')
// 清除保存的状态
sessionStorage.removeItem('aiCallDialogSize');
sessionStorage.removeItem('aiCallDialogPosition');
this.$emit('close')
// 可以在这里执行其他逻辑
},
minimizeWindow() {
this.windowState = 'minimized';
this.$store.commit('app/SET_SHOW_AI_CALL_MINIMIZED', true);
},
maximizeWindow() {
this.windowState = 'maximized';
},
getLastUserMessage() {
// 从后往前找用户消息
for (let i = this.messageList.length - 1; i >= 0; i--) {
if (!this.messageList[i].isBot) {
// 移除HTML标签只返回纯文本
const tempDiv = document.createElement('div');
tempDiv.innerHTML = this.messageList[i].text;
return tempDiv.textContent || tempDiv.innerText || '';
}
}
return '';
},
// 处理加载状态
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.isComponentReady = false;
this.messageList = [
{
isBot: true,
text: `<p><b>您好!我是京东方案例智能问答助手,随时为您服务。</b></p>
<p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p>
<p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p>
<p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>`
}
];
this.AIContent = '';
this.isLoading = false;
// 在下一个 tick 中重新标记为准备就绪
this.$nextTick(() => {
this.isComponentReady = true;
});
},
// 处理滚动事件
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;
}
},
// 最小化窗口的点击事件处理方法
onMinimizedWindowClick() {
// 当点击最小化窗口时如果dialogVisible为false则通过事件通知父组件显示对话框
if (!this.dialogVisible) {
this.$emit('restore');
}
// 然后将窗口状态设置为最大化
this.windowState = 'maximized';
}
}
}
</script>
<style scoped lang="scss">
.case-expert-dialog {
::v-deep .el-dialog{
background: url("./components/u762.svg") no-repeat ;
background-size: cover;
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
//background-color: rgba(255, 255, 255, 0.8);
}
::v-deep .el-dialog__body{
padding: 10px;
flex:1;
//font-size: 12px;
*{
font-size:unset ;
}
}
.dialog-title {
background: transparent;
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
font-size: 16px;
font-weight: 600;
color: #333;
padding-right: 20px;
cursor: move; /* 添加拖动样式 */
.icon {
width: 24px;
height: 24px;
}
.window-control-btn {
font-size: 18px;
padding: 5px 10px;
color: #333; /* 黑色图标 */
}
}
.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;
min-height: 500px;
height:100%;
position: relative;
//margin-bottom: 20px;
display: flex;
flex-direction: column;
.welcome-message {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 10px;
height: 400px;
//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);
}
}
}
}
.minimized-window {
position: fixed;
right: 20px;
bottom: 20px;
width: 300px;
background: url("./components/u762.svg") no-repeat;
background-size: cover;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 2000;
cursor: pointer;
.minimized-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
border-bottom: 1px solid #eee;
.window-title {
font-weight: 600;
color: #333;
}
.window-control-btn {
font-size: 16px;
padding: 3px 8px;
color: #000000; /* 黑色图标 */
}
}
.minimized-message {
padding: 15px;
font-size: 14px;
color: #666;
min-height: 60px;
display: flex;
align-items: center;
}
}
</style>

View File

@@ -1,9 +1,7 @@
<template>
<div id="case-list-content">
<div style="margin-bottom:30px" class="case-banner">
<portal-header current="case" textColor="#fff" :goSearch="2">
</portal-header>
<portal-header current="case" textColor="#fff" :goSearch="2"></portal-header>
</div>
<div class="">
<div class="xcontent2">
@@ -111,7 +109,6 @@
</div>
</div>
<div class="xcontent2-minor" :style="{ display: zoomShow ? '' : 'none' }">
<AICaseConsult />
<div id="fixd-box">
<router-link class="the_charts" to="/case/charts">
<div class="text">排行榜</div>
@@ -240,10 +237,9 @@ import { formatDate } from "@/utils/datetime.js"
import { cutFullName } from "@/utils/tools.js";
import apiPlace from "@/api/phase2/place.js"
import portalFloatTools from "@/components/PortalFloatTools.vue";
import AICaseConsult from "@/views/portal/case/components/AICaseConsult.vue";
export default {
name: 'atticle',
components: {AICaseConsult, portalHeader, portalFloatTools, portalFooter, interactBar, author, comments, pdfPreview },
components: { portalHeader, portalFloatTools, portalFooter, interactBar, author, comments, pdfPreview },
computed: {
...mapGetters(['userInfo'])
},

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
<template>
<div>
<div class="AI-case" style="position: relative; margin-bottom: 10px;" v-if="showAiCase" @click.stop="getAICase()">
<img src="../../../../../public/images/case-logo.png" alt="">
<span @click="getAICase()" style="position: absolute; bottom: 65px;left: 15px;z-index: 1;width: 40%;height: 30px;"></span>
</div>
<!-- 移除直接使用的AICall组件 -->
</div>
</template>
<script>
import { showCaseAiEntrance } from '@/api/boe/aiChat.js'
import { mapState } from 'vuex'
export default {
name: 'AICaseConsult',
data() {
return {
showAiCase: false
}
},
computed: {
// 从Vuex中获取showAICall状态虽然当前组件不使用但保持连接
...mapState('app', ['showAICall'])
},
mounted() {
this.getShowAiCase()
},
methods: {
// 是否展示入口
getShowAiCase() {
showCaseAiEntrance().then(res => {
this.showAiCase = res.result
})
},
// 案例立即咨询
getAICase() {
// 通过Vuex控制AICall组件显示
this.$store.dispatch('app/setShowAICall', true)
}
}
}
</script>
<style scoped lang="scss">
.AI-case {
margin-bottom: 10px;
position: relative;
img {
width: 100%;
}
span {
width: 160px;
height: 40px;
position: absolute;
left: 20px;
top: 105px;
cursor: pointer;
}
}
</style>

View File

@@ -1 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,423 +0,0 @@
<template>
<div class="messages">
<!-- 机器人消息 -->
<div v-if="messageData.isBot" class="bot-message">
<!-- 思考中提示 -->
<div v-if="messageData.thinkText" class="bot-think" v-katex:auto v-html="md.render(messageData.thinkText)"></div>
<!-- 主要回复内容 -->
<div
ref="contentContainer"
class="message-content"
v-katex:auto
v-html="md.render(displayText)"
></div>
<!-- 引用案例 -->
<div v-if="messageData.caseRefers && messageData.caseRefers.length > 0 && messageData.textCompleted" 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
v-for="item in displayedCaseRefers"
:key="item.caseId"
class="case-refers-item"
>
<div class="case-refers-item-title">
<a @click="toUrl(item)" 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 case-content" v-html="md.render(item.content)"></div>
</div>
</div>
</div>
</div>
<!-- 用户消息 -->
<div v-else class="user-message">
<div class="message-text" v-html="messageData.text"></div>
</div>
<!-- 推荐问题 -->
<!-- <div v-if="suggestions && suggestions.length > 0" class="suggestions">-->
<!-- <div class="suggestions-title">💡 推荐问题</div>-->
<!-- <div class="suggestions-list">-->
<!-- <button-->
<!-- v-for="(item, index) in suggestions"-->
<!-- :key="index"-->
<!-- class="suggestions-item"-->
<!-- @click="$emit('suggestion-click', item)"-->
<!-- >-->
<!-- {{ item }}-->
<!-- </button>-->
<!-- </div>-->
<!-- </div>-->
</div>
</template>
<script>
import MarkdownIt from 'markdown-it';
import highlight from 'markdown-it-highlightjs';
import 'highlight.js/styles/a11y-dark.css';
import markdownItMermaid from 'markdown-it-mermaid';
import mermaid from 'mermaid';
// 初始化 Mermaid
mermaid.initialize({ startOnLoad: false });
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
});
md.use(highlight).use(markdownItMermaid);
export default {
name: 'Message',
props: {
messageData: {
type: Object,
required: true,
default: () => ({}),
},
suggestions: {
type: Array,
default: () => [],
},
},
data() {
return {
md,
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.displayText = '';
return;
}
if (this.messageData.isBot && !this.messageData.typing) {
// this.startTyping(newVal); // 启动打字机效果/**/
this.displayText = newVal || ''
} else {
this.displayText = this.md.render(newVal);
this.$nextTick(this.renderMermaid); // 直接渲染 Mermaid
}
},
immediate: true,
},
},
methods: {
toUrl(item) {
this.$router.push({
path: '/case/detail',
query: { id: item.caseId },
});
this.$emit('getMinWindow')
},
// 正确的打字机效果:先整体渲染 Markdown再逐字显示 HTML
startTyping(fullText) {
const renderedText = this.md.render(fullText);
this.displayText = '';
let index = 0;
if (this.typingTimer) {
clearInterval(this.typingTimer);
}
this.typingTimer = setInterval(() => {
if (index < renderedText.length) {
this.displayText += renderedText[index];
index++;
} else {
clearInterval(this.typingTimer);
this.typingTimer = null;
this.$nextTick(this.renderMermaid); // 渲染 Mermaid 图表
}
}, this.typingSpeed);
},
// 触发 Mermaid 渲染
renderMermaid() {
this.$nextTick(() => {
const mermaidEls = this.$el.querySelectorAll('.mermaid');
if (mermaidEls.length > 0) {
try {
// mermaid 8.x 版本使用 init 方法而不是 run
if (typeof mermaid.init === 'function') {
mermaid.init(undefined, '.mermaid');
} else if (mermaid.default && typeof mermaid.default.init === 'function') {
mermaid.default.init(undefined, '.mermaid');
}
} catch (e) {
console.warn('Mermaid 渲染失败:', e);
}
}
});
},
// 切换案例引用显示数量
toggleShowAllCaseRefers() {
this.showAllCaseRefers = !this.showAllCaseRefers;
// 切换后重新渲染 Mermaid如果内容中有图表
this.$nextTick(this.renderMermaid);
},
},
beforeDestroy() {
if (this.typingTimer) {
clearInterval(this.typingTimer);
this.typingTimer = null;
}
},
};
</script>
<style scoped lang="scss">
::v-deep .mermaid{
width: 100%;
height: auto;
}
::v-deep svg[id^="mermaid-"]{
width: 100%;
height: 100%;
}
.messages {
width: 100%;
word-wrap: break-word;
.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);
}
}
.message-content {
font-size: 14px;
line-height: 1.6;
}
.case-content {
font-size: 12px !important;
margin-top: 8px;
padding: 6px 10px;
//background-color: #f9f9f9;
border-radius: 4px;
//border: 1px solid #eee;
}
}
.user-message {
float: right;
padding: 8px 15px;
max-width: 80%;
background-color: #e4e7ed;
border-radius: 5px;
margin-bottom: 10px;
font-size: 14px;
word-break: break-word;
}
/* ========== 案例引用样式 ========== */
.case-refers {
margin-top: 12px;
.case-refers-title {
font-weight: bold;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
color: #333;
.icon-think {
background-image: url('./map.svg');
width: 15px;
height: 13px;
display: inline-block;
background-repeat: no-repeat;
background-size: 100% 100%;
margin-right: 6px;
}
.more {
font-size: 12px;
padding: 2px 8px;
background-color: #f4f7fd;
border-radius: 5px;
color: #577ee1;
font-weight: normal;
cursor: pointer;
}
}
.case-refers-list {
display: flex;
flex-direction: column;
gap: 8px;
.case-refers-item {
border: 1px solid rgba(144, 147, 153, 0.44);
padding: 8px;
border-radius: 6px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
.case-refers-item-title {
font-size: 14px;
margin-bottom: 6px;
font-weight: 600;
color: #000;
display: flex;
align-items: center;
justify-content: space-between;
.title {
max-width: 70%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #000;
cursor: pointer;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.case-refers-item-timer {
font-size: 11px;
color: #aaa;
font-weight: normal;
}
}
.case-refers-item-author {
display: flex;
align-items: center;
font-size: 12px;
color: #555;
margin-bottom: 5px;
.user {
background-image: url('./user.svg');
width: 15px;
height: 15px;
display: inline-block;
background-repeat: no-repeat;
background-size: 100% 100%;
margin-right: 6px;
}
.case-inter-orginInfo {
font-size: 11px;
color: #999;
margin-left: 6px;
}
}
.case-refers-item-keywords {
margin-top: 4px;
font-size: 12px;
span {
padding: 2px 6px;
background-color: #f4f7fd;
border-radius: 5px;
font-size: 11px !important;
color: #577ee1;
}
span + span {
margin-left: 8px;
}
}
}
}
}
/* ========== 推荐问题 ========== */
.suggestions {
margin-top: 10px;
font-size: 14px;
.suggestions-title {
font-weight: bold;
margin-bottom: 6px;
color: #333;
}
.suggestions-list {
display: flex;
flex-direction: column;
gap: 6px;
.suggestions-item {
padding: 6px 10px;
background-color: #f0f4fc;
border: none;
border-radius: 6px;
text-align: left;
color: #1a73e8;
cursor: pointer;
font-size: 13px;
transition: background-color 0.2s;
&:hover {
background-color: #e1e8f5;
}
}
}
}
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

View File

@@ -1,391 +0,0 @@
<template>
<div class="input-area">
<el-input
v-model="inputContent"
type="textarea"
class="input-placeholder"
placeholder="有问题,尽管问"
@keyup.enter.native="handleSend"
:disabled="disabled"
:autosize="{ minRows: 2, maxRows: 4}"
resize="none"
></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',
"accept": "text/event-stream",
},
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 = 30; // 每个字符的间隔时间(毫秒)
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;
sessionStorage.setItem('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.conversationId = ''
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>

View File

@@ -1,12 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 858 B

View File

@@ -1 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -30,19 +30,13 @@
<!-- <div class="course-title-right"> -->
<!-- <interactBar :readonly="!stuStusts || stuStusts==0" :type="1" :data="courseInfo" :comments="false" :views="false"></interactBar> -->
<!-- </div> -->
<!-- <div class="label-div">
<el-tag class="label-item" effect="plain" v-for="(item,tagIdx) in tagArray" :key="tagIdx">{{item}}</el-tag>
</div>-->
<div class="label-div">
<div v-for="(item, tagIdx) in tagArray" :key="tagIdx" class="keyword-tag">
{{ item }}
</div>
</div>
<div>
<div class="study-count">{{courseInfo.studys}}人学习</div>
<!-- <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>
</div>
<!-- <div style="width:160px;height:50px"> -->
<!-- </div> -->
<!-- <div class="label-div">
@@ -425,7 +419,7 @@ export default {
.course-title{
position: relative;
height: auto;
height: 90px;
display: flex;
justify-content: space-between;
.title {
@@ -458,43 +452,18 @@ export default {
padding: 24px 24px 5px 24px;
// margin-right: 361px;
.study-count {
margin-top: 30px;
margin-top: 10px;
font-size: 16px;
color: #444444;
}
/*.label-div {
margin: 5px 0;
min-height: 20px;
.label-item {
padding: 0px 8px;
margin-top: 5px;
float: left;
line-height: 24px;
font-size: 12px;
border-radius: 2px;
margin-right: 8px;
color: #2C68FF;
height: 24px;
background: rgba(44, 104, 255, 0.06);
border: none; // 或者使用 border-color: transparent;
}
}*/
.label-div {
margin: 5px 0;
min-height: 20px;
.keyword-tag {
padding: 0px 10px;
margin-top: 7px;
float: left;
line-height: 24px;
font-size: 12px;
border-radius: 2px;
margin-right: 10px;
color: #2C68FF;
height: 24px;
background: rgba(44, 104, 255, 0.06);
.label-item {
padding: 0 7px;
margin-right: 8px;
margin-bottom: 0px;
}
}
::v-deep .el-rate__icon {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -123,20 +123,13 @@
<div>
<div class="course-interact">
<div class="score" style="display: flex;">
<div v-if="!scoreInfo.has" style="margin-left:10px;cursor: pointer;padding-top:10px;display: flex;align-items: center;">
<div v-if="!scoreInfo.has" style="margin-left:10px;cursor: pointer;padding-top:18px">
<!-- <el-popover placement="top" width="300" trigger="hover"> -->
<!-- <div style="text-align:center;line-height:50px;padding:20px 0px">
<div style="padding-top:30px"><el-button @click="addScore">提交评分</el-button></div>
</div> -->
<p style="margin-right:10px">告诉我们您的喜欢程度</p>
<el-rate v-model="scoreInfo.score" @change="showConfirmScore" :allow-half="true"></el-rate>
<div v-if="isShowScoreConfirm">
<span class="score-text">{{ toScore(scoreInfo.score) }}</span>
<span style="font-size: 18px;"></span>
<el-button style="margin-left:10px" type="primary" size="mini" @click="addScore" >确定</el-button>
<el-button size="mini" @click="handleCancelScore">取消</el-button>
</div>
<el-rate v-model="scoreInfo.score" @change="addScore"></el-rate>
<!-- <el-tag class="ref-score" slot="reference">去评分</el-tag> -->
<!-- </el-popover> -->
</div>
@@ -195,7 +188,7 @@
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose">
<el-submenu :index="item.section.id" v-if="catalogTree.length > 1">
<el-submenu :index="item.section.id">
<template slot="title">
<div style="display: flex;justify-content: space-between;">
<div style="width: 240px;font-weight: 700;font-size: 16px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;" :title="item.section.name">{{item.section.name}}</div>
@@ -222,27 +215,6 @@
</div>
</el-menu-item-group>
</el-submenu>
<div v-else>
<el-menu-item-group v-for="(ele, i) in item.children" :key="i">
<div class="units-info" :class="{'units-active':contentData.id == ele.id}" @click="showRes(ele,i,index,item)">
<el-menu-item :index="ele.id" style="padding: 0;padding-left: 10px;">
<div style="display: flex;justify-content: space-between;">
<div style="width: 200px;font-size: 16px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;" :title="ele.contentName">{{i+1}}. {{ ele.contentName }}</div>
<div>
<span v-if="contentData.id == ele.id" style="color: #387DF7;font-size: 14px;margin-right: 4px;">学习中</span>
<!-- <img v-if="contentData.id == ele.id" :src="`${webBaseUrl}/images/playicon.png`" alt=""> -->
<img v-if="contentData.id == ele.id && ele.status == 9" style="width: 16px;height: 16px;" src="@/assets/images/over.png" alt="">
<img v-if="contentData.id == ele.id && ele.status == 0" style="width: 16px;height: 16px;" src="@/assets/images/nowNot.png" alt="">
<img v-if="contentData.id == ele.id && (ele.status != 9&&ele.status != 0)" style="width: 16px;height: 16px;" src="@/assets/images/ban1.png" alt="">
<img v-if="contentData.id != ele.id && ele.status == 9" style="width: 16px;height: 16px;" src="@/assets/images/notNew.png" alt="">
<img v-if="contentData.id != ele.id && ele.status == 0" style="width: 16px;height: 16px;" src="@/assets/images/not.png" alt="">
<img v-if="contentData.id != ele.id && (ele.status != 9&&ele.status != 0)" style="width: 16px;height: 16px;" src="@/assets/images/newBan.png" alt="">
</div>
</div>
</el-menu-item>
</div>
</el-menu-item-group>
</div>
</el-menu>
</div>
<!-- <div v-for="(item, index) in catalogTree" :key="index" :name="index">
@@ -418,7 +390,6 @@
},
data() {
return {
isShowScoreConfirm: false,
protocolDialogVisible: false,
tentative: false,
isContentTypeTwo: null,
@@ -509,7 +480,6 @@
defaultMaxTime:1800, //非音频默认最大时间
warn:"测试内容",
warnTitle:"测试标题",
isFinishingStudyItem: false, // 防止重复调用完成状态更新接口
}
},
mounted() {
@@ -562,13 +532,6 @@
}
},
methods: {
handleCancelScore() {
this.isShowScoreConfirm = false;
this.scoreInfo.score = 5
},
showConfirmScore() {
this.isShowScoreConfirm = true;
},
handleOpen(key,path){
if(this.isFalse){
this.defaultOpeneds = [key]
@@ -1721,17 +1684,12 @@
//这种可能没有不过这里也是为了万中那个1
!this.tentative && this.saveStudyInfo();
} else {
// 如果正在处理完成请求,则直接返回,避免重复调用
if (this.isFinishingStudyItem) {
return;
}
let params = {
itemId: this.contentData.studyItemId,
studyId: this.studyId,
courseId: this.courseId,
cnum: this.totalContent
}
this.isFinishingStudyItem = true; // 设置标志位
apiVideoStudy.finishStudyItem(params).then(res => {
if (res.status == 200) {
this.contentData.status = 9;
@@ -1739,10 +1697,6 @@
} else {
console.log("记录完成学习失败:" + res.message + "" + res.error);
}
this.isFinishingStudyItem = false; // 重置标志位
}).catch(error => {
console.error("记录完成学习出错:", error);
this.isFinishingStudyItem = false; // 出错时也重置标志位
});
}
},
@@ -2006,19 +1960,16 @@
}
.player-box {
position: absolute;
position: relative;
width: 100%;
max-width: 300px;
margin: 20px auto;
height: 187px;
background: rgba(74, 74, 74, .8);
background: rgba(74, 74, 74, .5);
border-radius: 33px;
text-align: center;
padding: 20px;
top: 50%;
box-sizing: border-box;
left: 50%;
transform: translate(-50%, -50%);
.player-praise {
margin-top: 25px;

View File

@@ -1,389 +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-button @click="resetSearch" icon="el-icon-refresh">重置</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: {
//重置搜索条件
resetSearch() {
this.pageData.id = '';
this.pageData.tagName = '';
this.pageData.isHot = '';
this.pageData.pageIndex = 1;
this.getCourseTagList(); // 重置后重新加载列表
},
//初始化:课程标签列表
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).then((res)=>{
if (res.status == 200){
this.$message.success(res.message);
}else {
row.isHot=false;
this.$message.warning(res.message);
}
});
} 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>

View File

@@ -57,13 +57,6 @@ module.exports = {
// set svg-sprite-loader
config.plugins.delete('preload')
config.plugins.delete('prefetch')
// 添加对 mathxyjax3 的处理规则
config.module
.rule('mathxyjax3')
.test(/node_modules[\/\\]mathxyjax3[\/\\].*\.js$/)
.use('null-loader')
.loader('null-loader')
.end()
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))