Compare commits

...

8 Commits

Author SHA1 Message Date
liu.zixi
e6e60ae2e6 Merge remote-tracking branch 'origin/master-20251219' into master-20251219 2025-12-19 17:35:26 +08:00
lwj
19618e3b90 style:调整列宽度 2025-12-19 17:28:13 +08:00
dong.ai
4d4a93698f feat(messages): 添加点踩反馈功能并优化交互逻辑 2025-12-19 17:18:07 +08:00
chong.yanning@ebiz-digits.com
7e53ed11c2 feat(portal): 移除组件props中的conversationId并将其移至data中
将sendMessage.vue组件中的conversationId属性从props移动到data中,以便更好地管理组件内部状态。
2025-12-19 17:17:26 +08:00
chong.yanning@ebiz-digits.com
85152e2e25 feat(AICall): 实现对话框拖拽边界限制并优化显示逻辑
调整了 AI 呼叫页面中对话框的拖拽行为,新增边界检测以防止拖出可视区域。
同时修正内容区域的条件渲染逻辑,确保在不同语言服务状态下的正确显示。
2025-12-19 17:17:25 +08:00
chong.yanning@ebiz-digits.com
a1d5d0f079 feat(cases): 规范化案例模块接口调用及新增AI会话初始化功能
- 新增 initChat 方法用于获取AI会话ID
- 新增 handleStop方法 停止当前会话功能
2025-12-19 17:17:24 +08:00
lwj
99760c9940 fix:在线课程管理列表中添加审核人审核时间 2025-12-19 16:51:24 +08:00
huanyue26
3cfd025858 styles fix 2025-12-19 02:53:01 +08:00
30 changed files with 1536 additions and 948 deletions

View File

@@ -1,14 +1,14 @@
/* 案例模块的相关处理*/ /* 案例模块的相关处理*/
import ajax from '@/utils/xajax.js' import ajax from "@/utils/xajax.js";
import ajaxs from '@/api/ajax.js' import ajaxs from "@/api/ajax.js";
/**首页查询 /**首页查询
* pageSize * pageSize
* orderField * orderField
* orderAsc * orderAsc
*/ */
const indexList = function (query) { const indexList = function (query) {
return ajax.post('/xboe/m/boe/cases/case-random', query); return ajax.post("/xboe/m/boe/cases/case-random", query);
} };
/* /*
*案例分页搜索查询 是否推荐 *案例分页搜索查询 是否推荐
*@param(String) keyWord 关键词 *@param(String) keyWord 关键词
@@ -20,11 +20,11 @@ const indexList = function (query) {
* @param(String) majorDomain 专业领域 * @param(String) majorDomain 专业领域
*/ */
const queryList = function (query) { const queryList = function (query) {
return ajax.post('/xboe/m/boe/cases/queryList', query); return ajax.post("/xboe/m/boe/cases/queryList", query);
} };
const queryListV2 = function (query) { const queryListV2 = function (query) {
return ajax.postJson('/xboe/m/boe/cases/queryListV2', query); return ajax.postJson("/xboe/m/boe/cases/queryListV2", query);
} };
/* 案例分页搜索查询 是否置顶 /* 案例分页搜索查询 是否置顶
*@param(String) keyWord 关键词 *@param(String) keyWord 关键词
@param(Boolean) isTop 是否置顶 true或false @param(Boolean) isTop 是否置顶 true或false
@@ -33,32 +33,32 @@ const queryListV2 = function (query) {
* @param(String) majorDomain 专业领域 * @param(String) majorDomain 专业领域
*/ */
const isTopList = function (query) { const isTopList = function (query) {
return ajax.post('/xboe/m/boe/cases/isTopList', query); return ajax.post("/xboe/m/boe/cases/isTopList", query);
} };
/* 设置置顶 取消置顶 /* 设置置顶 取消置顶
@param(String) id @param(String) id
@param(Integer) isTop 是否置顶 0未置顶1已置顶 @param(Integer) isTop 是否置顶 0未置顶1已置顶
*/ */
const updateTop = function (id, isTop) { const updateTop = function (id, isTop) {
return ajax.get(`/xboe/m/boe/cases/updateTop?id=${id}&isTop=${isTop}`); return ajax.get(`/xboe/m/boe/cases/updateTop?id=${id}&isTop=${isTop}`);
} };
/* 删除案例 /* 删除案例
*param(String) id 案例的id *param(String) id 案例的id
*/ */
const del = function (id) { const del = function (id) {
return ajax.get('/xboe/m/boe/cases/delete?id=' + id); return ajax.get("/xboe/m/boe/cases/delete?id=" + id);
} };
/*案例详情 /*案例详情
@param(String) id 案例的id @param(String) id 案例的id
@param(Boolean) addView 是否增加浏览量 @param(Boolean) addView 是否增加浏览量
*/ */
const detail = function (id, addView) { const detail = function (id, addView) {
let pars = 'id=' + id; let pars = "id=" + id;
if (addView) { if (addView) {
pars += '&addView=' + addView pars += "&addView=" + addView;
}
return ajax.get('/xboe/m/boe/cases/detail?' + pars);
} }
return ajax.get("/xboe/m/boe/cases/detail?" + pars);
};
/*推荐 /*推荐
*@param (String) id 案例的id *@param (String) id 案例的id
*@param (String) title 案例的标题 *@param (String) title 案例的标题
@@ -66,61 +66,65 @@ const detail = function (id, addView) {
*@param (String) recommentThat 推荐说明 *@param (String) recommentThat 推荐说明
*/ */
const savaRecommend = function (data) { const savaRecommend = function (data) {
return ajax.post('/xboe/m/boe/recommend/save', data); return ajax.post("/xboe/m/boe/recommend/save", data);
} };
/* 推荐列表 /* 推荐列表
*没有参数 *没有参数
*/ */
const query = function () { const query = function () {
return ajax.get('/xboe/m/boe/recommend/query'); return ajax.get("/xboe/m/boe/recommend/query");
} };
/* /*
*作者排行榜 *作者排行榜
@param pageSize 长度 @param pageSize 长度
*/ */
const usernameList = function (pageSize) { const usernameList = function (pageSize) {
return ajax.get(`/xboe/m/boe/cases/usernamelist?pageSize=${pageSize}`); return ajax.get(`/xboe/m/boe/cases/usernamelist?pageSize=${pageSize}`);
} };
/* /*
人气榜 人气榜
@param pageSize 长度 @param pageSize 长度
*/ */
const queryPraises = function (pageSize) { const queryPraises = function (pageSize) {
return ajax.get(`/xboe/m/boe/cases/query-praises?pageSize=${pageSize}`); return ajax.get(`/xboe/m/boe/cases/query-praises?pageSize=${pageSize}`);
} };
const queryPraisesNew = function (pageSize, rankType) { const queryPraisesNew = function (pageSize, rankType) {
return ajax.get(`/xboe/m/boe/cases/queryPopularity?pageSize=${pageSize}&rankType=${rankType}`); return ajax.get(
} `/xboe/m/boe/cases/queryPopularity?pageSize=${pageSize}&rankType=${rankType}`
);
};
const queryRecommendRank = function (pageSize) { const queryRecommendRank = function (pageSize) {
return ajax.get(`/xboe/m/boe/cases/queryRecommendRank?pageSize=${pageSize}`); return ajax.get(`/xboe/m/boe/cases/queryRecommendRank?pageSize=${pageSize}`);
} };
/* /*
好评榜 好评榜
@param pageSize 长度 @param pageSize 长度
*/ */
const queryComments = function (pageSize) { const queryComments = function (pageSize) {
return ajax.get(`/xboe/m/boe/cases/query-comments?pageSize=${pageSize}`); return ajax.get(`/xboe/m/boe/cases/query-comments?pageSize=${pageSize}`);
} };
const queryCommentsNew = function (pageSize, rankType) { const queryCommentsNew = function (pageSize, rankType) {
return ajax.get(`/xboe/m/boe/cases/queryHighOpinion?pageSize=${pageSize}&rankType=${rankType}`); return ajax.get(
} `/xboe/m/boe/cases/queryHighOpinion?pageSize=${pageSize}&rankType=${rankType}`
);
};
/** /**
* 专业分类 * 专业分类
* */ * */
const majorTypes = function () { const majorTypes = function () {
return ajax.get('/xboe/m/boe/cases/majorTypes'); return ajax.get("/xboe/m/boe/cases/majorTypes");
} };
/** /**
* 详情新*/ * 详情新*/
const details = function (id, addView) { const details = function (id, addView) {
let pars = 'id=' + id; let pars = "id=" + id;
if (addView) { if (addView) {
pars += '&addView=' + addView pars += "&addView=" + addView;
}
return ajax.get('/xboe/m/boe/cases/details?' + pars);
} }
return ajax.get("/xboe/m/boe/cases/details?" + pars);
};
/** /**
* 二次查询 * 二次查询
@@ -129,8 +133,8 @@ const details = function (id, addView) {
* } * }
* */ * */
const ids = function (data) { const ids = function (data) {
return ajax.postJson('/xboe/m/boe/cases/ids', data); return ajax.postJson("/xboe/m/boe/cases/ids", data);
} };
/** /**
* 设置和取消优秀案例 * 设置和取消优秀案例
@@ -140,9 +144,8 @@ const ids = function (data) {
* } * }
* */ * */
const excellent = function (data) { const excellent = function (data) {
return ajax.post('/xboe/m/boe/cases/excellent', data) return ajax.post("/xboe/m/boe/cases/excellent", data);
} };
/** /**
*我的案例 *我的案例
@@ -152,8 +155,8 @@ const excellent = function (data) {
* } * }
* */ * */
const mylist = function (query) { const mylist = function (query) {
return ajax.post('/xboe/m/boe/cases/mylist', query); return ajax.post("/xboe/m/boe/cases/mylist", query);
} };
/** /**
* 导出 * 导出
@@ -163,21 +166,26 @@ const mylist = function (query) {
* } * }
* */ * */
const exportCases = function (query) { const exportCases = function (query) {
return ajax.post('/xboe/m/boe/cases/export', query); return ajax.post("/xboe/m/boe/cases/export", query);
} };
/** /**
* 导出案例后加的 * 导出案例后加的
* */ * */
const exports = function (query) { const exports = function (query) {
return ajax.post('/xboe/m/boe/cases/exportCase', query, { responseType: 'blob' }); return ajax.post("/xboe/m/boe/cases/exportCase", query, {
} responseType: "blob",
});
};
/** /**
* @param * @param
* 记录查看开始时间 * 记录查看开始时间
* caseRecommendId读取的案例的id * caseRecommendId读取的案例的id
*/ */
const startReadTimer = (caseRecommendId) => ajax.get(`/xboe/m/boe/cases/recommend/startRead?caseRecommendId=${caseRecommendId}`); const startReadTimer = (caseRecommendId) =>
ajax.get(
`/xboe/m/boe/cases/recommend/startRead?caseRecommendId=${caseRecommendId}`
);
/** /**
* @param * @param
@@ -187,34 +195,56 @@ const startReadTimer = (caseRecommendId) => ajax.get(`/xboe/m/boe/cases/recomm
* browseDuration [浏览时间秒] * browseDuration [浏览时间秒]
* } * }
*/ */
const endReadTimer = (data)=> ajax.postJson('/xboe/m/boe/cases/recommend/recordBrowseDuration',data) const endReadTimer = (data) =>
ajax.postJson("/xboe/m/boe/cases/recommend/recordBrowseDuration", data);
/**年份查询 /**年份查询
* *
*/ */
const caseYears = function (query = {}) { const caseYears = function (query = {}) {
return ajax.post('/xboe/m/boe/cases/caseYears', query); return ajax.post("/xboe/m/boe/cases/caseYears", query);
} };
//案例推荐榜单 //案例推荐榜单
const getQueryRecommendRank = function (params) { const getQueryRecommendRank = function (params) {
return ajax.get(`/xboe/m/boe/cases/queryRecommendRank?pageSize=${params.pageSize}`) return ajax.get(
} `/xboe/m/boe/cases/queryRecommendRank?pageSize=${params.pageSize}`
);
};
//案例上榜 //案例上榜
const riseIntoRank = (data) => ajax.post(`/xboe/m/boe/cases/riseIntoRank?caseId=${data.caseId}`) const riseIntoRank = (data) =>
ajax.post(`/xboe/m/boe/cases/riseIntoRank?caseId=${data.caseId}`);
//取消上榜 //取消上榜
const cancelRiseIntoRank = (data) => ajax.post(`/xboe/m/boe/cases/cancelRiseIntoRank?caseId=${data.caseId}`) const cancelRiseIntoRank = (data) =>
ajax.post(`/xboe/m/boe/cases/cancelRiseIntoRank?caseId=${data.caseId}`);
//调整榜单 //调整榜单
const adjustRank = (data) => ajax.post(`/xboe/m/boe/cases/adjustRank?caseIds=${data.caseIds}`) const adjustRank = (data) =>
ajax.post(`/xboe/m/boe/cases/adjustRank?caseIds=${data.caseIds}`);
//收藏案例 //收藏案例
const queryFavoriteCaseOfIndex = (params) => ajax.get(`/xboe/m/boe/cases/queryFavoriteCaseOfIndex?pageIndex=${params.pageIndex}&pageSize=${params.pageSize}&orderField=${params.orderField}&orderAsc=${params.orderAsc}`) const queryFavoriteCaseOfIndex = (params) =>
ajax.get(
`/xboe/m/boe/cases/queryFavoriteCaseOfIndex?pageIndex=${params.pageIndex}&pageSize=${params.pageSize}&orderField=${params.orderField}&orderAsc=${params.orderAsc}`
);
//浏览记录 //浏览记录
const queryViewRecord = (data) => ajaxs.post(`/statApi/xboe/m/stat/userdynamic/list?pageIndex=${data.pageIndex}&pageSize=${data.pageSize}&contentType=${data.contentType}&aid=${data.aid}&hidden=${data.hidden}&eventKey=${data.eventKey}`) const queryViewRecord = (data) =>
ajaxs.post(
`/statApi/xboe/m/stat/userdynamic/list?pageIndex=${data.pageIndex}&pageSize=${data.pageSize}&contentType=${data.contentType}&aid=${data.aid}&hidden=${data.hidden}&eventKey=${data.eventKey}`
);
//浏览量TOP榜单 //浏览量TOP榜单
const queryPopularityOfMajor = (params) => ajax.get(`/xboe/m/boe/cases/queryPopularityOfMajor?pageSize=${params.pageSize}&rankMonth=${params.rankMonth}&majorId=${params.majorId}`) const queryPopularityOfMajor = (params) =>
ajax.get(
`/xboe/m/boe/cases/queryPopularityOfMajor?pageSize=${params.pageSize}&rankMonth=${params.rankMonth}&majorId=${params.majorId}`
);
//浏览记录新 //浏览记录新
const browsingHistory = (params) => ajax.get(`/xboe/m/boe/cases/browsingHistory?pageIndex=${params.pageIndex}&pageSize=5`) const browsingHistory = (params) =>
ajax.get(
`/xboe/m/boe/cases/browsingHistory?pageIndex=${params.pageIndex}&pageSize=5`
);
//获取所有的专业月份 //获取所有的专业月份
const queryAllTimePopularityOfMajor = () => ajax.get('/xboe/m/boe/cases/queryAllTimePopularityOfMajor') const queryAllTimePopularityOfMajor = () =>
ajax.get("/xboe/m/boe/cases/queryAllTimePopularityOfMajor");
// 获取会话ID
const initChat = () => ajax.get("/xboe/m/boe/case/ai/initChat");
export default { export default {
queryAllTimePopularityOfMajor, queryAllTimePopularityOfMajor,
getQueryRecommendRank, getQueryRecommendRank,
@@ -249,5 +279,6 @@ export default {
exports, exports,
startReadTimer, startReadTimer,
endReadTimer, endReadTimer,
caseYears caseYears,
} initChat,
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -40,6 +40,9 @@ export default {
} }
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-colleage-active');
let list = colleage.colleage; let list = colleage.colleage;
list.forEach(element => { list.forEach(element => {
let temp = element.org.split('/') let temp = element.org.split('/')
@@ -47,39 +50,44 @@ export default {
}); });
this.colleageList = list; this.colleageList = list;
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-colleage-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-colleage-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-colleage-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-colleage-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-colleage-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-colleage-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-colleage-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-colleage-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-colleage-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-colleage-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -49,41 +49,49 @@ export default {
}, },
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-course-active');
this.courseList = course.course; this.courseList = course.course;
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-course-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-course-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-course-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-course-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-course-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-course-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-course-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-course-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-course-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-course-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -98,6 +98,9 @@ export default {
}; };
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('course-detail-page-active');
this.id = this.$route.params.id this.id = this.$route.params.id
let list = course.course; let list = course.course;
let pid = this.id let pid = this.id
@@ -124,45 +127,50 @@ export default {
} }
} }
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('course-detail-page-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.course-detail-page-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.course-detail-page-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.course-detail-page-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.course-detail-page-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.course-detail-page-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.course-detail-page-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.course-detail-page-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.course-detail-page-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.course-detail-page-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }
</style> </style>
<style> <style>
body { body.course-detail-page-active {
background-color: #e0ded9; background-color: #e0ded9;
} }
</style> </style>

View File

@@ -123,6 +123,9 @@ export default {
}; };
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-project-detail-active');
this.id = this.$route.params.id; this.id = this.$route.params.id;
let list = project.project; let list = project.project;
let pid = this.id; let pid = this.id;
@@ -154,45 +157,50 @@ export default {
} }
} }
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-project-detail-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-project-detail-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-project-detail-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-project-detail-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-project-detail-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-project-detail-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-project-detail-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-project-detail-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-project-detail-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-project-detail-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }
</style> </style>
<style> <style>
body { body.contributor-conference-project-detail-active {
background-color: #e0ded9; background-color: #e0ded9;
} }
</style> </style>

View File

@@ -52,6 +52,9 @@ export default {
}, },
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-example-active');
let list = example.example let list = example.example
for(let i = 0; i<list.length; i++){ for(let i = 0; i<list.length; i++){
if(list[i].content.length > 200){ if(list[i].content.length > 200){
@@ -60,40 +63,45 @@ export default {
} }
this.exampleList = list this.exampleList = list
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-example-active');
},
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-example-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-example-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-example-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-example-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-example-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-example-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-example-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-example-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-example-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -383,41 +383,49 @@ export default {
// if (res && res.code == "0") { // if (res && res.code == "0") {
// console.log(res); // console.log(res);
// } // }
},
mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-index-active');
},
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-index-active');
} }
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-index-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-index-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-index-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-index-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-index-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-index-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-index-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-index-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-index-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -111,39 +111,48 @@ export default {
this.$router.back('/contributor/index') this.$router.back('/contributor/index')
} }
}, },
mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-project-active');
},
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-project-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-project-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-project-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-project-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-project-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-project-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-project-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-project-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-project-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-project-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -43,6 +43,9 @@ export default {
} }
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-teacher-active');
let list = teacher.teacher; let list = teacher.teacher;
list.forEach(element => { list.forEach(element => {
let temp = element.org.split('/') let temp = element.org.split('/')
@@ -51,38 +54,43 @@ export default {
this.teacherList = list this.teacherList = list
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-teacher-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-teacher-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-teacher-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-teacher-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-teacher-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-teacher-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-teacher-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-teacher-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-teacher-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-teacher-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -40,6 +40,9 @@ export default {
} }
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-colleage-active');
let list = colleage.colleage; let list = colleage.colleage;
list.forEach(element => { list.forEach(element => {
let temp = element.org.split('/') let temp = element.org.split('/')
@@ -49,39 +52,44 @@ export default {
}); });
this.colleageList = list; this.colleageList = list;
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-colleage-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-colleage-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-colleage-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-colleage-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-colleage-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-colleage-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-colleage-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-colleage-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-colleage-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-colleage-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -50,41 +50,49 @@ export default {
}, },
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-course-active');
this.courseList = course.course; this.courseList = course.course;
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-course-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-course-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-course-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-course-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-course-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-course-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-course-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-course-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-course-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-course-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -98,6 +98,9 @@ export default {
}; };
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-course-detail-active');
this.id = this.$route.params.id this.id = this.$route.params.id
let list = course.course; let list = course.course;
let pid = this.id let pid = this.id
@@ -124,45 +127,50 @@ export default {
} }
} }
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-course-detail-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-course-detail-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-course-detail-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-course-detail-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-course-detail-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-course-detail-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-course-detail-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-course-detail-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-course-detail-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-course-detail-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }
</style> </style>
<style> <style>
body { body.contributor-conference-2024-course-detail-active {
background-color: #e0ded9; background-color: #e0ded9;
} }
</style> </style>

View File

@@ -129,6 +129,9 @@ export default {
}; };
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-project-detail-active');
this.id = this.$route.params.id; this.id = this.$route.params.id;
let list = project.project; let list = project.project;
let pid = this.id; let pid = this.id;
@@ -160,45 +163,50 @@ export default {
} }
} }
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-project-detail-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-project-detail-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-project-detail-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-project-detail-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-project-detail-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-project-detail-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-project-detail-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-project-detail-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-project-detail-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-project-detail-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }
</style> </style>
<style> <style>
body { body.contributor-conference-2024-project-detail-active {
background-color: #e0ded9; background-color: #e0ded9;
} }
</style> </style>

View File

@@ -52,6 +52,9 @@ export default {
}, },
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-example-active');
let list = example.example let list = example.example
for(let i = 0; i<list.length; i++){ for(let i = 0; i<list.length; i++){
if(list[i].content.length > 200){ if(list[i].content.length > 200){
@@ -60,40 +63,45 @@ export default {
} }
this.exampleList = list this.exampleList = list
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-example-active');
},
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-example-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-example-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-example-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-example-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-example-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-example-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-example-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-example-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-example-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -408,6 +408,14 @@ export default {
// if (res && res.code == "0") { // if (res && res.code == "0") {
// console.log(res); // console.log(res);
// } // }
},
mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-index-active');
},
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-index-active');
} }
} }
@@ -425,35 +433,36 @@ export default {
font-family: 'biaoti2'; font-family: 'biaoti2';
src: url('../../assets/fonts/KMQfP4.ttf'); src: url('../../assets/fonts/KMQfP4.ttf');
} }
// 使用 body.contributor-conference-2024-index-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-index-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-index-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-index-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-index-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-index-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-index-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-index-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-index-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -139,39 +139,48 @@ export default {
this.$router.back('/contributor_2024/index') this.$router.back('/contributor_2024/index')
} }
}, },
mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-project-active');
},
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-project-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-project-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-project-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-project-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-project-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-project-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-project-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-project-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-project-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-project-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -43,6 +43,9 @@ export default {
} }
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-2024-teacher-active');
let list = teacher.teacher; let list = teacher.teacher;
list.forEach(element => { list.forEach(element => {
let temp = element.org.split('/') let temp = element.org.split('/')
@@ -51,38 +54,43 @@ export default {
this.teacherList = list this.teacherList = list
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-2024-teacher-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-2024-teacher-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-2024-teacher-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-2024-teacher-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-2024-teacher-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-2024-teacher-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-2024-teacher-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-2024-teacher-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-2024-teacher-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-2024-teacher-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -40,6 +40,9 @@ export default {
} }
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-colleage-active');
let list = colleage.colleage; let list = colleage.colleage;
list.forEach(element => { list.forEach(element => {
let temp = element.org.split('/') let temp = element.org.split('/')
@@ -47,39 +50,44 @@ export default {
}); });
this.colleageList = list; this.colleageList = list;
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-colleage-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-colleage-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-colleage-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-colleage-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-colleage-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-colleage-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-colleage-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-colleage-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-colleage-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-colleage-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -50,41 +50,49 @@ export default {
}, },
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-course-active');
this.courseList = course.course; this.courseList = course.course;
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-course-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-course-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-course-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-course-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-course-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-course-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-course-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-course-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-course-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-course-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -98,6 +98,9 @@ export default {
}; };
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-course-detail-active');
this.id = this.$route.params.id this.id = this.$route.params.id
let list = course.course; let list = course.course;
let pid = this.id let pid = this.id
@@ -124,45 +127,50 @@ export default {
} }
} }
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-course-detail-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-course-detail-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-course-detail-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-course-detail-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-course-detail-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-course-detail-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-course-detail-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-course-detail-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-course-detail-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-course-detail-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }
</style> </style>
<style> <style>
body { body.contributor-conference-new-course-detail-active {
background-color: #e0ded9; background-color: #e0ded9;
} }
</style> </style>

View File

@@ -129,6 +129,9 @@ export default {
}; };
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-project-detail-active');
this.id = this.$route.params.id; this.id = this.$route.params.id;
let list = project.project; let list = project.project;
let pid = this.id; let pid = this.id;
@@ -160,45 +163,50 @@ export default {
} }
} }
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-project-detail-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-project-detail-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-project-detail-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-project-detail-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-project-detail-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-project-detail-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-project-detail-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-project-detail-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-project-detail-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-project-detail-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }
</style> </style>
<style> <style>
body { body.contributor-conference-new-project-detail-active {
background-color: #e0ded9; background-color: #e0ded9;
} }
</style> </style>

View File

@@ -52,6 +52,9 @@ export default {
}, },
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-example-active');
let list = example.example let list = example.example
for(let i = 0; i<list.length; i++){ for(let i = 0; i<list.length; i++){
if(list[i].content.length > 200){ if(list[i].content.length > 200){
@@ -60,40 +63,45 @@ export default {
} }
this.exampleList = list this.exampleList = list
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-example-active');
},
} }
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-example-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-example-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-example-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-example-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-example-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-example-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-example-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-example-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-example-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -401,6 +401,14 @@ export default {
// if (res && res.code == "0") { // if (res && res.code == "0") {
// console.log(res); // console.log(res);
// } // }
},
mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-index-active');
},
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-index-active');
} }
@@ -419,35 +427,36 @@ export default {
font-family: 'biaoti2'; font-family: 'biaoti2';
src: url('../../assets/fonts/KMQfP4.ttf'); src: url('../../assets/fonts/KMQfP4.ttf');
} }
// 使用 body.contributor-conference-new-index-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-index-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-index-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-index-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-index-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-index-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-index-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-index-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-index-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -183,39 +183,48 @@ export default {
this.$router.back('/contributornew/index') this.$router.back('/contributornew/index')
} }
}, },
mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-project-active');
},
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-project-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-project-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-project-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-project-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-project-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-project-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-project-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-project-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-project-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-project-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -43,6 +43,9 @@ export default {
} }
}, },
mounted() { mounted() {
// 给 body 添加特定类名,用于限制样式作用域
document.body.classList.add('contributor-conference-new-teacher-active');
let list = teacher.teacher; let list = teacher.teacher;
list.forEach(element => { list.forEach(element => {
let temp = element.org.split('/') let temp = element.org.split('/')
@@ -51,38 +54,43 @@ export default {
this.teacherList = list this.teacherList = list
}, },
beforeDestroy() {
// 组件销毁时移除类名
document.body.classList.remove('contributor-conference-new-teacher-active');
},
}; };
</script> </script>
<style lang='scss'> <style lang='scss'>
// 使用 body.contributor-conference-new-teacher-active 类名限制样式只在该页面生效
@media screen and (min-width: 1440px) and (max-width: 1600px){ @media screen and (min-width: 1440px) and (max-width: 1600px){
body{ body.contributor-conference-new-teacher-active{
zoom: 79%; zoom: 79%;
} }
#bg{ body.contributor-conference-new-teacher-active #bg{
width: 1900px !important; width: 1900px !important;
} }
} }
@media screen and (min-width: 1366px) and (max-width: 1440px){ @media screen and (min-width: 1366px) and (max-width: 1440px){
body{ body.contributor-conference-new-teacher-active{
zoom: 74%; zoom: 74%;
} }
#bg{ body.contributor-conference-new-teacher-active #bg{
width: 1869px !important; width: 1869px !important;
} }
} }
@media screen and (min-width: 1280px) and (max-width: 1366px){ @media screen and (min-width: 1280px) and (max-width: 1366px){
body{ body.contributor-conference-new-teacher-active{
zoom: 72%; zoom: 72%;
} }
#bg{ body.contributor-conference-new-teacher-active #bg{
width: 1874px !important; width: 1874px !important;
} }
} }
@media screen and (max-width: 1280px){ @media screen and (max-width: 1280px){
body{ body.contributor-conference-new-teacher-active{
zoom: 67%; zoom: 67%;
} }
#bg{ body.contributor-conference-new-teacher-active #bg{
width: 1885px !important; width: 1885px !important;
} }
} }

View File

@@ -71,7 +71,9 @@
</el-row> </el-row>
</div> </div>
<div style="margin-right:30px;"> <div style="margin-right:30px;">
<el-table style="margin:10px 32px 10px 22px;" :data="pageData" border stripe> <!-- ai播放器相关 -->
<el-table style="margin:10px 32px 10px 22px;" :data="pageData" border stripe @selection-change="handleSelectionChange">
<el-table-column v-if="aiPermission" type="selection" width="55"></el-table-column>
<el-table-column label="序号" type="index" width="50"></el-table-column> <el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column v-if="forChoose" label="选择" width="80"> <el-table-column v-if="forChoose" label="选择" width="80">
<template slot-scope="scope" v-if="scope.row.published"> <template slot-scope="scope" v-if="scope.row.published">
@@ -107,7 +109,7 @@
{{ courseType(scope.row.type)}} {{ courseType(scope.row.type)}}
</template> </template>
</el-table-column> --> </el-table-column> -->
<el-table-column label="状态" prop="status" width="120px"> <el-table-column label="状态" prop="status" width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 1未提交 2.已提交 = 未审核 5 已审核 --> <!-- 1未提交 2.已提交 = 未审核 5 已审核 -->
<span v-if="scope.row.status == 1">未提交</span> <span v-if="scope.row.status == 1">未提交</span>
@@ -116,23 +118,25 @@
<span v-if="scope.row.status == 3">审核未通过</span> <span v-if="scope.row.status == 3">审核未通过</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否发布" width="130px"> <el-table-column label="是否发布" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.published == true ? '已发布' : '未发布' }} {{ scope.row.published == true ? '已发布' : '未发布' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建人" prop="sysCreateBy"></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="sysCreateTime" width="150" show-overflow-tooltip></el-table-column>
<el-table-column label="是否停用" width="130px"> <el-table-column label="是否停用" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.enabled == true ? '启用' : '停用' }} {{ scope.row.enabled == true ? '启用' : '停用' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否置顶" width="130px"> <el-table-column label="是否置顶" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.isTop == true ? '置顶' : '未置顶' }} {{ scope.row.isTop == true ? '置顶' : '未置顶' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="审核人" prop="auditUser" width="80"></el-table-column>
<el-table-column label="审核时间" prop="auditTime" width="150" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="180px" fixed="right"> <el-table-column label="操作" width="180px" fixed="right">
<template slot-scope="scope" class="btn-gl"> <template slot-scope="scope" class="btn-gl">
<!-- 20240621 修改scope.row.isPermission = fasle 时不展示操作按钮--> <!-- 20240621 修改scope.row.isPermission = fasle 时不展示操作按钮-->
@@ -299,7 +303,7 @@ import auditCourse2 from '@/components/Course/auditCourse2.vue';
import adminPage from '@/components/Administration/adminPage.vue'; import adminPage from '@/components/Administration/adminPage.vue';
import apiResowner from '../../api/modules/resowner.js'; import apiResowner from '../../api/modules/resowner.js';
import apiType from '../../api/modules/type.js' import apiType from '../../api/modules/type.js'
import {courseType} from '../../utils/tools.js'; import {courseType, deepCopy} from '../../utils/tools.js';
import apiCourse from '../../api/modules/course.js'; import apiCourse from '../../api/modules/course.js';
// import {resOwnerIndexName,sysTypeIndexName} from '@/utils/type.js'; // import {resOwnerIndexName,sysTypeIndexName} from '@/utils/type.js';
import { mapGetters,mapActions } from 'vuex'; import { mapGetters,mapActions } from 'vuex';
@@ -307,8 +311,9 @@ import apiUserbasic from "@/api/boe/userbasic.js"
export default { export default {
name: 'manageCourse', name: 'manageCourse',
components: {courseForm, manager, auditCourse1, auditCourse2,adminPage}, components: {courseForm, manager, auditCourse1, auditCourse2,adminPage},
// ai播放器相关
computed: { computed: {
...mapGetters(['resOwnerMap','sysTypeMap','userInfo']), ...mapGetters(['resOwnerMap','sysTypeMap','userInfo', 'selectAllLang']),
}, },
data() { data() {
return { return {
@@ -426,6 +431,7 @@ export default {
}, },
methods: { methods: {
getAudiences(){ getAudiences(){
apiUserbasic.getInAudienceIds().then(res=>{ apiUserbasic.getInAudienceIds().then(res=>{
if (res.status == 200) { if (res.status == 200) {
@@ -449,6 +455,7 @@ export default {
inputOn() { inputOn() {
this.$forceUpdate(); this.$forceUpdate();
}, },
// 置顶 // 置顶
setTop(row) { setTop(row) {
let params = { let params = {

View File

@@ -19,22 +19,27 @@
<span>案例专家</span> <span>案例专家</span>
<div class="window-control-btn"> <div class="window-control-btn">
<el-button <el-button
style="color:#96999f;margin-right: 6px;" style="color: #96999f; margin-right: 6px"
type="text" type="text"
@click="minimizeWindow" @click="minimizeWindow"
> >
<i class="el-icon-minus"></i> <i class="el-icon-minus"></i>
</el-button> </el-button>
<el-button <el-button type="text" style="color: #96999f">
type="text" <img
style="color:#96999f;" v-if="!dialogFullscreen"
> @click="onbigWindowClick"
<img v-if="!dialogFullscreen" @click="onbigWindowClick" :src="openImg" alt="" style="width: 17px"> :src="openImg"
<i v-else @click="onRestoreWindowClick" class="el-icon-copy-document"></i> alt=""
style="width: 17px"
/>
<i
v-else
@click="onRestoreWindowClick"
class="el-icon-copy-document"
></i>
</el-button> </el-button>
</div> </div>
</div> </div>
<div class="content-wrapper" v-show="isLan"> <div class="content-wrapper" v-show="isLan">
@@ -48,11 +53,31 @@
@scroll="handleScroll" @scroll="handleScroll"
@wheel="handleWheel" @wheel="handleWheel"
> >
<div class="message-text" v-for="(item, index) in messageList" :key="index"> <div
<messages :messageData="item" @update:messageData="val=> $set(messageList, index, val)" :suggestions="suggestions" @getMinWindow="minimizeWindow" :isFirstMessage="item.isFirstMessage"></messages> class="message-text"
v-for="(item, index) in messageList"
:key="index"
>
<messages
:messageData="item"
@update:messageData="(val) => $set(messageList, index, val)"
:suggestions="suggestions"
@getMinWindow="minimizeWindow"
:isFirstMessage="item.isFirstMessage"
></messages>
</div> </div>
<div class="message-suggestions" v-if="messageList.length > 0 && messageList[messageList.length-1].textCompleted"> <div
<div class="suggestion-item" v-for="(item, index) in suggestions" :key="index"> 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> <a @click="sendSuggestions(item)"> {{ item }} →</a>
</div> </div>
</div> </div>
@@ -75,6 +100,8 @@
@update-suggestions="updateSuggestions" @update-suggestions="updateSuggestions"
@new-conversation="startNewConversation" @new-conversation="startNewConversation"
:disabled="isLoading" :disabled="isLoading"
:stopShow="stopShow"
:sendShow="sendShow"
class="input-area-wrapper" class="input-area-wrapper"
ref="sendMessage" ref="sendMessage"
/> />
@@ -95,7 +122,7 @@
class="window-control-btn" class="window-control-btn"
@click.stop="onMinimizedWindowClick" @click.stop="onMinimizedWindowClick"
> >
<img :src="openImg" alt="" style="width: 17px"> <img :src="openImg" alt="" style="width: 17px" />
</el-button> </el-button>
<el-button <el-button
@@ -121,47 +148,48 @@
</template> </template>
<script> <script>
import { mapState } from 'vuex' import { mapState } from "vuex";
import messages from './components/messages.vue' import messages from "./components/messages.vue";
import sendMessage from './components/sendMessage.vue' import sendMessage from "./components/sendMessage.vue";
import openImg from './components/open.png' import openImg from "./components/open.png";
import LanServiceChecker from "@/components/LanServiceChecker.vue"; import LanServiceChecker from "@/components/LanServiceChecker.vue";
export default { export default {
name: 'CaseExpertDialog', name: "CaseExpertDialog",
props: { props: {
dialogVisible: { dialogVisible: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}, },
components: { components: {
LanServiceChecker, LanServiceChecker,
messages, messages,
sendMessage sendMessage,
}, },
directives: { directives: {
draggable: { draggable: {
bind(el, binding, vnode) { bind(el, binding, vnode) {
vnode.context.$nextTick(() => { vnode.context.$nextTick(() => {
const dialogEl = el.querySelector('.el-dialog'); const dialogEl = el.querySelector(".el-dialog");
if (!dialogEl) return; if (!dialogEl) return;
const headerEl = dialogEl.querySelector('.dialog-title'); const headerEl = dialogEl.querySelector(".dialog-title");
if (!headerEl) return; if (!headerEl) return;
// 检查是否有保存的位置状态 // 检查是否有保存的位置状态
const savedPosition = sessionStorage.getItem('aiCallDialogPosition'); const savedPosition = sessionStorage.getItem("aiCallDialogPosition");
if (savedPosition) { if (savedPosition) {
const { left, top } = JSON.parse(savedPosition); const { left, top } = JSON.parse(savedPosition);
dialogEl.style.left = left + 'px'; dialogEl.style.left = left + "px";
dialogEl.style.top = top + 'px'; dialogEl.style.top = top + "px";
} else { } else {
// 设置初始样式 // 设置初始样式
dialogEl.style.position = 'fixed'; dialogEl.style.position = "fixed";
dialogEl.style.top = '100px'; dialogEl.style.top = "100px";
dialogEl.style.left = (window.innerWidth - dialogEl.offsetWidth) / 2 + 'px'; dialogEl.style.left =
(window.innerWidth - dialogEl.offsetWidth) / 2 + "px";
} }
dialogEl.style.margin = '0'; dialogEl.style.margin = "0";
let isDragging = false; let isDragging = false;
let startX = 0; let startX = 0;
@@ -170,10 +198,10 @@ export default {
let startTop = 0; let startTop = 0;
const startDrag = (event) => { const startDrag = (event) => {
// 只有在标题栏上按下鼠标才开始拖动 // 只有在标题栏上按下鼠标才开始拖动
if (event.target.closest('.resize-handle')) { if (event.target.closest(".resize-handle")) {
return; // 如果点击的是resize-handle则不触发拖动 return; // 如果点击的是resize-handle则不触发拖动
} }
if (event.target.closest('.window-control-btn')) { if (event.target.closest(".window-control-btn")) {
return; // 如果点击的是控制按钮,则不触发拖动 return; // 如果点击的是控制按钮,则不触发拖动
} }
// 全屏状态下拖动为正常弹窗大小 // 全屏状态下拖动为正常弹窗大小
@@ -191,8 +219,8 @@ export default {
event.stopPropagation(); event.stopPropagation();
// 添加全局事件监听 // 添加全局事件监听
document.addEventListener('mousemove', handleMouseMove); document.addEventListener("mousemove", handleMouseMove);
document.addEventListener('mouseup', stopDrag); document.addEventListener("mouseup", stopDrag);
}; };
const handleMouseMove = (event) => { const handleMouseMove = (event) => {
@@ -201,8 +229,26 @@ export default {
const deltaX = event.clientX - startX; const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY; const deltaY = event.clientY - startY;
dialogEl.style.left = (startLeft + deltaX) + 'px'; // 计算新位置
dialogEl.style.top = (startTop + deltaY) + 'px'; let newLeft = startLeft + deltaX;
let newTop = startTop + deltaY;
// 获取对话框尺寸
const dialogWidth = dialogEl.offsetWidth;
const dialogHeight = dialogEl.offsetHeight;
// 限制拖拽范围在浏览器可视区域内
// 左边界
newLeft = Math.max(-500, newLeft);
// 右边界
newLeft = Math.min(window.innerWidth - dialogWidth, newLeft);
// 上边界
newTop = Math.max(0, newTop);
// 下边界 (确保标题栏始终可见标题栏高度约为80px)
newTop = Math.min(window.innerHeight - 80, newTop);
dialogEl.style.left = newLeft + "px";
dialogEl.style.top = newTop + "px";
}; };
const stopDrag = () => { const stopDrag = () => {
@@ -210,114 +256,113 @@ export default {
// 保存当前位置到 sessionStorage // 保存当前位置到 sessionStorage
const currentPosition = { const currentPosition = {
left: parseInt(dialogEl.style.left), left: parseInt(dialogEl.style.left),
top: parseInt(dialogEl.style.top) top: parseInt(dialogEl.style.top),
}; };
// sessionStorage.setItem('aiCallDialogPosition', JSON.stringify(currentPosition)); // sessionStorage.setItem('aiCallDialogPosition', JSON.stringify(currentPosition));
// 移除全局事件监听 // 移除全局事件监听
document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener('mouseup', stopDrag); document.removeEventListener("mouseup", stopDrag);
}; };
// 为标题栏绑定拖动事件 // 为标题栏绑定拖动事件
headerEl.addEventListener('mousedown', startDrag); headerEl.addEventListener("mousedown", startDrag);
}); });
} },
}, },
resizeable: { resizeable: {
bind(el, binding, vnode) { bind(el, binding, vnode) {
// 确保元素已插入DOM // 确保元素已插入DOM
vnode.context.$nextTick(() => { vnode.context.$nextTick(() => {
const dialogEl = el.querySelector('.el-dialog'); const dialogEl = el.querySelector(".el-dialog");
if (!dialogEl) return; if (!dialogEl) return;
// 检查是否有保存的尺寸状态 // 检查是否有保存的尺寸状态
const savedSize = sessionStorage.getItem('aiCallDialogSize'); const savedSize = sessionStorage.getItem("aiCallDialogSize");
if (savedSize) { if (savedSize) {
const { width, height, left, top } = JSON.parse(savedSize); const { width, height, left, top } = JSON.parse(savedSize);
dialogEl.style.width = width + 'px'; dialogEl.style.width = width + "px";
dialogEl.style.height = height + 'px'; dialogEl.style.height = height + "px";
dialogEl.style.left = left + 'px'; dialogEl.style.left = left + "px";
dialogEl.style.top = top + 'px'; dialogEl.style.top = top + "px";
} else { } else {
// 设置初始样式 // 设置初始样式
dialogEl.style.position = 'fixed'; dialogEl.style.position = "fixed";
dialogEl.style.top = '100px'; dialogEl.style.top = "100px";
dialogEl.style.left = (window.innerWidth - dialogEl.offsetWidth) / 2 + 'px'; dialogEl.style.left =
(window.innerWidth - dialogEl.offsetWidth) / 2 + "px";
} }
// 创建拖拽手柄 // 创建拖拽手柄
const createHandle = (direction) => { const createHandle = (direction) => {
const handle = document.createElement('div'); const handle = document.createElement("div");
handle.className = `resize-handle ${direction}`; handle.className = `resize-handle ${direction}`;
handle.style.position = 'absolute'; handle.style.position = "absolute";
handle.style.zIndex = '10'; handle.style.zIndex = "10";
switch (direction) { switch (direction) {
case 'left': case "left":
case 'right': case "right":
handle.style.width = '6px'; handle.style.width = "6px";
handle.style.height = '100%'; handle.style.height = "100%";
handle.style.top = '0'; handle.style.top = "0";
handle.style.cursor = 'ew-resize'; handle.style.cursor = "ew-resize";
break; break;
case 'top': case "top":
case 'bottom': case "bottom":
handle.style.width = '100%'; handle.style.width = "100%";
handle.style.height = '6px'; handle.style.height = "6px";
handle.style.left = '0'; handle.style.left = "0";
handle.style.cursor = 'ns-resize'; handle.style.cursor = "ns-resize";
break; break;
case 'top-left': case "top-left":
case 'top-right': case "top-right":
case 'bottom-left': case "bottom-left":
case 'bottom-right': case "bottom-right":
handle.style.width = '10px'; handle.style.width = "10px";
handle.style.height = '10px'; handle.style.height = "10px";
handle.style.zIndex = '20'; handle.style.zIndex = "20";
break; break;
} }
switch (direction) { switch (direction) {
case 'left': case "left":
handle.style.left = '0'; handle.style.left = "0";
break; break;
case 'right': case "right":
handle.style.right = '0'; handle.style.right = "0";
break; break;
case 'top': case "top":
handle.style.top = '0'; handle.style.top = "0";
break; break;
case 'bottom': case "bottom":
handle.style.bottom = '0'; handle.style.bottom = "0";
break; break;
case 'top-left': case "top-left":
handle.style.top = '0'; handle.style.top = "0";
handle.style.left = '0'; handle.style.left = "0";
handle.style.cursor = 'nw-resize'; handle.style.cursor = "nw-resize";
break; break;
case 'top-right': case "top-right":
handle.style.top = '0'; handle.style.top = "0";
handle.style.right = '0'; handle.style.right = "0";
handle.style.cursor = 'ne-resize'; handle.style.cursor = "ne-resize";
break; break;
case 'bottom-left': case "bottom-left":
handle.style.bottom = '0'; handle.style.bottom = "0";
handle.style.left = '0'; handle.style.left = "0";
handle.style.cursor = 'sw-resize'; handle.style.cursor = "sw-resize";
break; break;
case 'bottom-right': case "bottom-right":
handle.style.bottom = '0'; handle.style.bottom = "0";
handle.style.right = '0'; handle.style.right = "0";
handle.style.cursor = 'se-resize'; handle.style.cursor = "se-resize";
break; break;
} }
// 防止拖拽手柄的事件冒泡到标题栏 // 防止拖拽手柄的事件冒泡到标题栏
handle.addEventListener('mousedown', (e) => { handle.addEventListener("mousedown", (e) => {
e.stopPropagation(); e.stopPropagation();
}); });
dialogEl.appendChild(handle); dialogEl.appendChild(handle);
@@ -326,19 +371,19 @@ export default {
// 创建8个拖拽手柄 // 创建8个拖拽手柄
const handles = { const handles = {
left: createHandle('left'), left: createHandle("left"),
right: createHandle('right'), right: createHandle("right"),
top: createHandle('top'), top: createHandle("top"),
bottom: createHandle('bottom'), bottom: createHandle("bottom"),
topLeft: createHandle('top-left'), topLeft: createHandle("top-left"),
topRight: createHandle('top-right'), topRight: createHandle("top-right"),
bottomLeft: createHandle('bottom-left'), bottomLeft: createHandle("bottom-left"),
bottomRight: createHandle('bottom-right') bottomRight: createHandle("bottom-right"),
}; };
// 添加拖拽事件处理 // 添加拖拽事件处理
let isResizing = false; let isResizing = false;
let resizeDirection = ''; let resizeDirection = "";
let startX = 0; let startX = 0;
let startY = 0; let startY = 0;
let startWidth = 0; let startWidth = 0;
@@ -363,8 +408,8 @@ export default {
startTop = parseInt(dialogEl.style.top) || 0; startTop = parseInt(dialogEl.style.top) || 0;
// 添加全局事件监听 // 添加全局事件监听
document.addEventListener('mousemove', handleMouseMove); document.addEventListener("mousemove", handleMouseMove);
document.addEventListener('mouseup', stopResize); document.addEventListener("mouseup", stopResize);
}; };
const handleMouseMove = (event) => { const handleMouseMove = (event) => {
@@ -376,71 +421,71 @@ export default {
let newWidth, newHeight, newLeft, newTop; let newWidth, newHeight, newLeft, newTop;
switch (resizeDirection) { switch (resizeDirection) {
case 'right': case "right":
newWidth = Math.max(400, startWidth + deltaX); newWidth = Math.max(400, startWidth + deltaX);
dialogEl.style.width = newWidth + 'px'; dialogEl.style.width = newWidth + "px";
break; break;
case 'left': case "left":
newWidth = Math.max(400, startWidth - deltaX); newWidth = Math.max(400, startWidth - deltaX);
newLeft = startLeft + startWidth - newWidth; newLeft = startLeft + startWidth - newWidth;
dialogEl.style.width = newWidth + 'px'; dialogEl.style.width = newWidth + "px";
dialogEl.style.left = newLeft + 'px'; dialogEl.style.left = newLeft + "px";
break; break;
case 'bottom': case "bottom":
newHeight = Math.max(600, startHeight + deltaY); newHeight = Math.max(600, startHeight + deltaY);
dialogEl.style.height = newHeight + 'px'; dialogEl.style.height = newHeight + "px";
break; break;
case 'top': case "top":
// 当窗口高度达到最小值时,不再调整高度和位置 // 当窗口高度达到最小值时,不再调整高度和位置
if (startHeight - deltaY >= 600) { if (startHeight - deltaY >= 600) {
newHeight = startHeight - deltaY; newHeight = startHeight - deltaY;
newTop = startTop + deltaY; newTop = startTop + deltaY;
dialogEl.style.height = newHeight + 'px'; dialogEl.style.height = newHeight + "px";
dialogEl.style.top = newTop + 'px'; dialogEl.style.top = newTop + "px";
} }
break; break;
case 'bottom-right': case "bottom-right":
newWidth = Math.max(400, startWidth + deltaX); newWidth = Math.max(400, startWidth + deltaX);
newHeight = Math.max(600, startHeight + deltaY); newHeight = Math.max(600, startHeight + deltaY);
dialogEl.style.width = newWidth + 'px'; dialogEl.style.width = newWidth + "px";
dialogEl.style.height = newHeight + 'px'; dialogEl.style.height = newHeight + "px";
break; break;
case 'bottom-left': case "bottom-left":
newWidth = Math.max(400, startWidth - deltaX); newWidth = Math.max(400, startWidth - deltaX);
newHeight = Math.max(600, startHeight + deltaY); newHeight = Math.max(600, startHeight + deltaY);
newLeft = startLeft + startWidth - newWidth; newLeft = startLeft + startWidth - newWidth;
dialogEl.style.width = newWidth + 'px'; dialogEl.style.width = newWidth + "px";
dialogEl.style.left = newLeft + 'px'; dialogEl.style.left = newLeft + "px";
dialogEl.style.height = newHeight + 'px'; dialogEl.style.height = newHeight + "px";
break; break;
case 'top-right': case "top-right":
// 当窗口高度达到最小值时,不再调整高度和位置 // 当窗口高度达到最小值时,不再调整高度和位置
if (startHeight - deltaY >= 600) { if (startHeight - deltaY >= 600) {
newHeight = startHeight - deltaY; newHeight = startHeight - deltaY;
newTop = startTop + deltaY; newTop = startTop + deltaY;
newWidth = Math.max(400, startWidth + deltaX); newWidth = Math.max(400, startWidth + deltaX);
dialogEl.style.height = newHeight + 'px'; dialogEl.style.height = newHeight + "px";
dialogEl.style.top = newTop + 'px'; dialogEl.style.top = newTop + "px";
dialogEl.style.width = newWidth + 'px'; dialogEl.style.width = newWidth + "px";
} }
break; break;
case 'top-left': case "top-left":
// 当窗口高度达到最小值时,不再调整高度和位置 // 当窗口高度达到最小值时,不再调整高度和位置
if (startHeight - deltaY >= 600) { if (startHeight - deltaY >= 600) {
newHeight = startHeight - deltaY; newHeight = startHeight - deltaY;
newTop = startTop + deltaY; newTop = startTop + deltaY;
newWidth = Math.max(400, startWidth - deltaX); newWidth = Math.max(400, startWidth - deltaX);
newLeft = startLeft + startWidth - newWidth; newLeft = startLeft + startWidth - newWidth;
dialogEl.style.height = newHeight + 'px'; dialogEl.style.height = newHeight + "px";
dialogEl.style.top = newTop + 'px'; dialogEl.style.top = newTop + "px";
dialogEl.style.width = newWidth + 'px'; dialogEl.style.width = newWidth + "px";
dialogEl.style.left = newLeft + 'px'; dialogEl.style.left = newLeft + "px";
} }
break; break;
} }
let doc = document.querySelector('.welcome-message') let doc = document.querySelector(".welcome-message");
let sendBox = document.querySelector('.input-area-wrapper'); let sendBox = document.querySelector(".input-area-wrapper");
// sendBox 的高度 // sendBox 的高度
if (doc && sendBox) { if (doc && sendBox) {
doc.style.height = `calc(${dialogEl.style.height} - ${sendBox.offsetHeight}px - 120px)`; doc.style.height = `calc(${dialogEl.style.height} - ${sendBox.offsetHeight}px - 120px)`;
@@ -449,50 +494,71 @@ export default {
const stopResize = () => { const stopResize = () => {
isResizing = false; isResizing = false;
resizeDirection = ''; resizeDirection = "";
// 保存当前尺寸和位置到 sessionStorage // 保存当前尺寸和位置到 sessionStorage
const currentSize = { const currentSize = {
width: parseInt(dialogEl.style.width), width: parseInt(dialogEl.style.width),
height: parseInt(dialogEl.style.height), height: parseInt(dialogEl.style.height),
left: parseInt(dialogEl.style.left), left: parseInt(dialogEl.style.left),
top: parseInt(dialogEl.style.top) top: parseInt(dialogEl.style.top),
}; };
sessionStorage.setItem('aiCallDialogSize', JSON.stringify(currentSize)); sessionStorage.setItem(
"aiCallDialogSize",
JSON.stringify(currentSize)
);
// 移除全局事件监听 // 移除全局事件监听
document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener('mouseup', stopResize); document.removeEventListener("mouseup", stopResize);
}; };
// 为每个手柄绑定事件 // 为每个手柄绑定事件
handles.left.addEventListener('mousedown', (e) => startResize('left', e)); handles.left.addEventListener("mousedown", (e) =>
handles.right.addEventListener('mousedown', (e) => startResize('right', e)); startResize("left", e)
handles.top.addEventListener('mousedown', (e) => startResize('top', e)); );
handles.bottom.addEventListener('mousedown', (e) => startResize('bottom', e)); handles.right.addEventListener("mousedown", (e) =>
handles.topLeft.addEventListener('mousedown', (e) => startResize('top-left', e)); startResize("right", e)
handles.topRight.addEventListener('mousedown', (e) => startResize('top-right', e)); );
handles.bottomLeft.addEventListener('mousedown', (e) => startResize('bottom-left', e)); handles.top.addEventListener("mousedown", (e) =>
handles.bottomRight.addEventListener('mousedown', (e) => startResize('bottom-right', 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: { computed: {
...mapState('app', ['showAICallMinimized']), ...mapState("app", ["showAICallMinimized"]),
showMinimizedWindow() { showMinimizedWindow() {
// 只有在Vuex状态为true时才显示最小化窗口 // 只有在Vuex状态为true时才显示最小化窗口
return this.showAICallMinimized; return this.showAICallMinimized;
} },
}, },
data() { data() {
return { return {
dialogFullscreen: false, dialogFullscreen: false,
isLan: true, isLan: true,
openImg, openImg,
AIContent: '', AIContent: "",
isLoading: false, isLoading: false,
windowState: 'maximized', // 'maximized' 或 'minimized' stopShow: false,
sendShow: true,
windowState: "maximized", // 'maximized' 或 'minimized'
messageList: [ messageList: [
{ {
typing: true, typing: true,
@@ -501,14 +567,14 @@ export default {
text: `<p><b>您好!我是京东方案例智能问答助手,随时为您服务。</b></p> text: `<p><b>您好!我是京东方案例智能问答助手,随时为您服务。</b></p>
<p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p> <p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p>
<p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p> <p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p>
<p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>` <p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>`,
} },
], ],
suggestions: [], suggestions: [],
isAutoScroll: true, // 是否自动滚动 isAutoScroll: true, // 是否自动滚动
// 添加一个标志位,用于标识组件是否已经初始化完成 // 添加一个标志位,用于标识组件是否已经初始化完成
isComponentReady: false isComponentReady: false,
} };
}, },
mounted() { mounted() {
// 组件挂载完成后,标记为已准备就绪 // 组件挂载完成后,标记为已准备就绪
@@ -519,22 +585,24 @@ export default {
watch: { watch: {
dialogVisible: { dialogVisible: {
handler(newVal) { handler(newVal) {
console.log('dialogVisible发生变化'); console.log("dialogVisible发生变化");
console.log(newVal); console.log(newVal);
console.log(this.windowState); console.log(this.windowState);
if (newVal) { if (newVal) {
this.$nextTick(() => { this.$nextTick(() => {
// 获取对话框元素 // 获取对话框元素
const dialogEl = document.querySelector('.case-expert-dialog .el-dialog'); const dialogEl = document.querySelector(
".case-expert-dialog .el-dialog"
);
if (dialogEl) { if (dialogEl) {
// 检查是否有保存的尺寸状态 // 检查是否有保存的尺寸状态
const savedSize = sessionStorage.getItem('aiCallDialogSize'); const savedSize = sessionStorage.getItem("aiCallDialogSize");
if (savedSize) { if (savedSize) {
const { width, height, left, top } = JSON.parse(savedSize); const { width, height, left, top } = JSON.parse(savedSize);
dialogEl.style.width = width + 'px'; dialogEl.style.width = width + "px";
dialogEl.style.height = height + 'px'; dialogEl.style.height = height + "px";
dialogEl.style.left = left + 'px'; dialogEl.style.left = left + "px";
dialogEl.style.top = top + 'px'; dialogEl.style.top = top + "px";
} }
// 检查是否有保存的位置状态 // 检查是否有保存的位置状态
@@ -546,11 +614,11 @@ export default {
// } // }
} }
let doc = document.querySelector('.welcome-message') let doc = document.querySelector(".welcome-message");
let sendBox = document.querySelector('.input-area-wrapper'); let sendBox = document.querySelector(".input-area-wrapper");
// 只有在没有保存的尺寸状态时才使用默认值 // 只有在没有保存的尺寸状态时才使用默认值
if (doc && sendBox) { if (doc && sendBox) {
const savedSize = sessionStorage.getItem('aiCallDialogSize'); const savedSize = sessionStorage.getItem("aiCallDialogSize");
if (!savedSize) { if (!savedSize) {
doc.style.height = `calc(600px - ${sendBox.offsetHeight}px - 120px)`; doc.style.height = `calc(600px - ${sendBox.offsetHeight}px - 120px)`;
} else { } else {
@@ -561,7 +629,7 @@ export default {
}); });
} }
}, },
immediate: true immediate: true,
}, },
messageList: { messageList: {
handler() { handler() {
@@ -572,23 +640,28 @@ export default {
}); });
} }
}, },
deep: true deep: true,
} },
}, },
methods: { methods: {
onbigWindowClick() { onbigWindowClick() {
console.log('放大'); console.log("放大");
// 保存当前非全屏状态的尺寸和位置(仅当当前不是全屏状态时) // 保存当前非全屏状态的尺寸和位置(仅当当前不是全屏状态时)
if (!this.dialogFullscreen) { if (!this.dialogFullscreen) {
const dialogEl = document.querySelector('.case-expert-dialog .el-dialog'); const dialogEl = document.querySelector(
".case-expert-dialog .el-dialog"
);
if (dialogEl) { if (dialogEl) {
const normalSize = { const normalSize = {
width: parseInt(dialogEl.style.width) || dialogEl.offsetWidth, width: parseInt(dialogEl.style.width) || dialogEl.offsetWidth,
height: parseInt(dialogEl.style.height) || dialogEl.offsetHeight, height: parseInt(dialogEl.style.height) || dialogEl.offsetHeight,
left: parseInt(dialogEl.style.left) || dialogEl.offsetLeft, left: parseInt(dialogEl.style.left) || dialogEl.offsetLeft,
top: parseInt(dialogEl.style.top) || dialogEl.offsetTop top: parseInt(dialogEl.style.top) || dialogEl.offsetTop,
}; };
sessionStorage.setItem('aiCallDialogNormalSize', JSON.stringify(normalSize)); sessionStorage.setItem(
"aiCallDialogNormalSize",
JSON.stringify(normalSize)
);
} }
} }
@@ -597,16 +670,18 @@ export default {
// 设置全屏尺寸和位置 // 设置全屏尺寸和位置
this.$nextTick(() => { this.$nextTick(() => {
const dialogEl = document.querySelector('.case-expert-dialog .el-dialog'); const dialogEl = document.querySelector(
".case-expert-dialog .el-dialog"
);
if (dialogEl) { if (dialogEl) {
dialogEl.style.width = '100vw'; dialogEl.style.width = "100vw";
dialogEl.style.height = '100vh'; dialogEl.style.height = "100vh";
dialogEl.style.left = '0px'; dialogEl.style.left = "0px";
dialogEl.style.top = '0px'; dialogEl.style.top = "0px";
// 更新消息容器高度 // 更新消息容器高度
const messageContainer = document.querySelector('.welcome-message'); const messageContainer = document.querySelector(".welcome-message");
const inputArea = document.querySelector('.input-area-wrapper'); const inputArea = document.querySelector(".input-area-wrapper");
if (messageContainer && inputArea) { if (messageContainer && inputArea) {
messageContainer.style.height = `calc(100vh - ${inputArea.offsetHeight}px - 120px)`; messageContainer.style.height = `calc(100vh - ${inputArea.offsetHeight}px - 120px)`;
} }
@@ -614,45 +689,49 @@ export default {
}); });
}, },
onRestoreWindowClick() { onRestoreWindowClick() {
console.log('缩小'); console.log("缩小");
this.dialogFullscreen = false; this.dialogFullscreen = false;
this.$nextTick(() => { this.$nextTick(() => {
const dialogEl = document.querySelector('.case-expert-dialog .el-dialog'); const dialogEl = document.querySelector(
".case-expert-dialog .el-dialog"
);
if (dialogEl) { if (dialogEl) {
// 从 sessionStorage 中获取保存的正常窗口尺寸和位置 // 从 sessionStorage 中获取保存的正常窗口尺寸和位置
const savedNormalSize = sessionStorage.getItem('aiCallDialogNormalSize'); const savedNormalSize = sessionStorage.getItem(
const savedSize = sessionStorage.getItem('aiCallDialogSize'); "aiCallDialogNormalSize"
const savedPosition = sessionStorage.getItem('aiCallDialogPosition'); );
const savedSize = sessionStorage.getItem("aiCallDialogSize");
const savedPosition = sessionStorage.getItem("aiCallDialogPosition");
if (savedNormalSize) { if (savedNormalSize) {
// 使用之前保存的正常尺寸 // 使用之前保存的正常尺寸
const { width, height, left, top } = JSON.parse(savedNormalSize); const { width, height, left, top } = JSON.parse(savedNormalSize);
dialogEl.style.width = width + 'px'; dialogEl.style.width = width + "px";
dialogEl.style.height = height + 'px'; dialogEl.style.height = height + "px";
dialogEl.style.left = left + 'px'; dialogEl.style.left = left + "px";
dialogEl.style.top = top + 'px'; dialogEl.style.top = top + "px";
} else if (savedSize) { } else if (savedSize) {
// 回退到通用保存的尺寸 // 回退到通用保存的尺寸
const { width, height, left, top } = JSON.parse(savedSize); const { width, height, left, top } = JSON.parse(savedSize);
dialogEl.style.width = width + 'px'; dialogEl.style.width = width + "px";
dialogEl.style.height = height + 'px'; dialogEl.style.height = height + "px";
dialogEl.style.left = left + 'px'; dialogEl.style.left = left + "px";
dialogEl.style.top = top + 'px'; dialogEl.style.top = top + "px";
} else { } else {
// 如果没有保存的尺寸,则使用默认值 // 如果没有保存的尺寸,则使用默认值
dialogEl.style.width = '800px'; dialogEl.style.width = "800px";
dialogEl.style.height = '600px'; dialogEl.style.height = "600px";
dialogEl.style.left = (window.innerWidth - 800) / 2 + 'px'; dialogEl.style.left = (window.innerWidth - 800) / 2 + "px";
dialogEl.style.top = '100px'; dialogEl.style.top = "100px";
} }
// 应用相应的消息容器高度 // 应用相应的消息容器高度
this.$nextTick(() => { this.$nextTick(() => {
const messageContainer = document.querySelector('.welcome-message'); const messageContainer = document.querySelector(".welcome-message");
const inputArea = document.querySelector('.input-area-wrapper'); const inputArea = document.querySelector(".input-area-wrapper");
if (messageContainer && inputArea) { if (messageContainer && inputArea) {
const dialogHeight = dialogEl.style.height || '600px'; const dialogHeight = dialogEl.style.height || "600px";
messageContainer.style.height = `calc(${dialogHeight} - ${inputArea.offsetHeight}px - 120px)`; messageContainer.style.height = `calc(${dialogHeight} - ${inputArea.offsetHeight}px - 120px)`;
} }
}); });
@@ -662,33 +741,33 @@ onRestoreWindowClick(){
// / 关闭最小化窗口 // / 关闭最小化窗口
closeMinimizedWindow() { closeMinimizedWindow() {
this.$store.commit('app/SET_SHOW_AI_CALL_MINIMIZED', false); this.$store.commit("app/SET_SHOW_AI_CALL_MINIMIZED", false);
this.$store.commit('app/SET_SHOW_AI_CALL', false); this.$store.commit("app/SET_SHOW_AI_CALL", false);
this.windowState = 'maximized'; this.windowState = "maximized";
}, },
getMinWidow(vis) { getMinWidow(vis) {
// this.showAICallMinimized = vis // this.showAICallMinimized = vis
this.windowState = 'minimized'; this.windowState = "minimized";
}, },
onClose() { onClose() {
console.log('关闭弹窗') console.log("关闭弹窗");
// 清除保存的状态 // 清除保存的状态
sessionStorage.removeItem('aiCallDialogSize'); sessionStorage.removeItem("aiCallDialogSize");
// sessionStorage.removeItem('aiCallDialogPosition'); // sessionStorage.removeItem('aiCallDialogPosition');
this.$emit('close') this.$emit("close");
this.dialogFullscreen=false this.dialogFullscreen = false;
// 可以在这里执行其他逻辑 // 可以在这里执行其他逻辑
}, },
minimizeWindow() { minimizeWindow() {
console.log(131); console.log(131);
this.windowState = 'minimized'; this.windowState = "minimized";
this.$store.commit('app/SET_SHOW_AI_CALL_MINIMIZED', true); this.$store.commit("app/SET_SHOW_AI_CALL_MINIMIZED", true);
}, },
maximizeWindow() { maximizeWindow() {
this.windowState = 'maximized'; this.windowState = "maximized";
}, },
getLastUserMessage() { getLastUserMessage() {
@@ -696,18 +775,20 @@ closeMinimizedWindow() {
for (let i = this.messageList.length - 1; i >= 0; i--) { for (let i = this.messageList.length - 1; i >= 0; i--) {
if (!this.messageList[i].isBot) { if (!this.messageList[i].isBot) {
// 移除HTML标签只返回纯文本 // 移除HTML标签只返回纯文本
const tempDiv = document.createElement('div'); const tempDiv = document.createElement("div");
tempDiv.innerHTML = this.messageList[i].text; tempDiv.innerHTML = this.messageList[i].text;
return tempDiv.textContent || tempDiv.innerText || ''; return tempDiv.textContent || tempDiv.innerText || "";
} }
} }
return ''; return "";
}, },
// 处理加载状态 // 处理加载状态
handleLoading(status) { handleLoading(status) {
console.log('handleLoading---'+status); console.log("handleLoading---" + status);
this.isLoading = status; this.isLoading = status;
this.sendShow = !status;
this.stopShow = status;
}, },
// 更新消息 // 更新消息
@@ -716,16 +797,16 @@ closeMinimizedWindow() {
// 这里不需要额外的操作 // 这里不需要额外的操作
}, },
updateSuggestions(arr) { updateSuggestions(arr) {
this.suggestions = arr this.suggestions = arr;
}, },
// 处理建议 // 处理建议
sendSuggestions(item) { sendSuggestions(item) {
// this.suggestions = [] // this.suggestions = []
this.AIContent = item this.AIContent = item;
setTimeout(() => { setTimeout(() => {
this.$refs.sendMessage.handleSend() this.$refs.sendMessage.handleSend();
this.AIContent = '' this.AIContent = "";
},500) }, 500);
}, },
startNewConversation() { startNewConversation() {
// 重置对话时,先标记组件为未准备就绪状态 // 重置对话时,先标记组件为未准备就绪状态
@@ -738,10 +819,10 @@ closeMinimizedWindow() {
text: `<p><b>您好!我是京东方案例智能问答助手,随时为您服务。</b></p> text: `<p><b>您好!我是京东方案例智能问答助手,随时为您服务。</b></p>
<p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p> <p>我可以帮您快速查找和解读平台内的各类案例内容。只需输入您想了解的问题或关键词,我会从案例库中精准匹配相关信息,并提供清晰的解答。每条回答都会附上来源链接,方便您随时查阅原始案例全文。</p>
<p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p> <p>我还会根据您的提问,智能推荐相关延伸问题,助您更高效地探索知识、解决问题。</p>
<p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>` <p>现在,欢迎随时向我提问,开启高效的知识查询体验吧!</p>`,
} },
]; ];
this.AIContent = ''; this.AIContent = "";
this.isLoading = false; this.isLoading = false;
// 在下一个 tick 中重新标记为准备就绪 // 在下一个 tick 中重新标记为准备就绪
@@ -754,7 +835,8 @@ closeMinimizedWindow() {
handleScroll(event) { handleScroll(event) {
const element = event.target; const element = event.target;
// 判断是否滚动到底部 // 判断是否滚动到底部
const isAtBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + 1; const isAtBottom =
element.scrollHeight - element.scrollTop <= element.clientHeight + 1;
// 如果滚动到底部,则开启自动滚动 // 如果滚动到底部,则开启自动滚动
// 如果离开底部,则关闭自动滚动 // 如果离开底部,则关闭自动滚动
@@ -764,7 +846,8 @@ closeMinimizedWindow() {
// 滚动到底部 // 滚动到底部
scrollToBottom() { scrollToBottom() {
if (this.isAutoScroll && this.$refs.messageContainer) { if (this.isAutoScroll && this.$refs.messageContainer) {
this.$refs.messageContainer.scrollTop = this.$refs.messageContainer.scrollHeight; this.$refs.messageContainer.scrollTop =
this.$refs.messageContainer.scrollHeight;
} }
}, },
@@ -783,7 +866,10 @@ closeMinimizedWindow() {
if (delta < 0 && element.scrollTop === 0) { if (delta < 0 && element.scrollTop === 0) {
// 向上滚动且已在顶部,阻止默认行为 // 向上滚动且已在顶部,阻止默认行为
event.preventDefault(); event.preventDefault();
} else if (delta > 0 && element.scrollHeight - element.scrollTop <= element.clientHeight) { } else if (
delta > 0 &&
element.scrollHeight - element.scrollTop <= element.clientHeight
) {
// 向下滚动且已在底部,阻止默认行为 // 向下滚动且已在底部,阻止默认行为
event.preventDefault(); event.preventDefault();
} else { } else {
@@ -797,13 +883,13 @@ closeMinimizedWindow() {
onMinimizedWindowClick() { onMinimizedWindowClick() {
// 当点击最小化窗口时如果dialogVisible为false则通过事件通知父组件显示对话框 // 当点击最小化窗口时如果dialogVisible为false则通过事件通知父组件显示对话框
if (!this.dialogVisible) { if (!this.dialogVisible) {
this.$emit('restore'); this.$emit("restore");
} }
// 然后将窗口状态设置为最大化 // 然后将窗口状态设置为最大化
this.windowState = 'maximized'; this.windowState = "maximized";
} },
} },
} };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -857,7 +943,6 @@ closeMinimizedWindow() {
} }
} }
.message-suggestions { .message-suggestions {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -966,7 +1051,9 @@ closeMinimizedWindow() {
} }
@keyframes loading { @keyframes loading {
0%, 80%, 100% { 0%,
80%,
100% {
transform: scale(0); transform: scale(0);
} }
40% { 40% {

View File

@@ -44,6 +44,7 @@
<img :src="messageData.isLike == 1 ? require('@/assets/images/case/zan-yes.svg') : require('@/assets/images/case/zan.svg')" <img :src="messageData.isLike == 1 ? require('@/assets/images/case/zan-yes.svg') : require('@/assets/images/case/zan.svg')"
@click="toggleStar(1)" alt="zan" class="zan_img"> @click="toggleStar(1)" alt="zan" class="zan_img">
</el-tooltip> </el-tooltip>
<el-tooltip class="item" effect="dark" content="点踩" placement="bottom">
<el-popover placement="bottom" trigger="manual" v-model="caiDialogShow"> <el-popover placement="bottom" trigger="manual" v-model="caiDialogShow">
<div class="feedback-class"> <div class="feedback-class">
<span>反馈</span> <span>反馈</span>
@@ -58,11 +59,11 @@
<div style="text-align: right; margin: 0"> <div style="text-align: right; margin: 0">
<el-button style="margin-top: 10px;" type="primary" size="mini" @click="handleSure">确定</el-button> <el-button style="margin-top: 10px;" type="primary" size="mini" @click="handleSure">确定</el-button>
</div> </div>
<!-- 修改为根据 isLike 值判断状态使用 == 而不是 === -->
<img slot="reference" <img slot="reference"
:src="messageData.isLike == -1 ? require('@/assets/images/case/cai-yes.svg') : require('@/assets/images/case/cai.svg')" :src="messageData.isLike == -1 ? require('@/assets/images/case/cai-yes.svg') : require('@/assets/images/case/cai.svg')"
@click="toggleStar(-1)" alt="cai" class="zan_img" style="margin-left:10px"> @click="toggleStar(-1)" alt="cai" class="zan_img" style="margin-left:10px">
</el-popover> </el-popover>
</el-tooltip>
</div> </div>
</div> </div>
@@ -195,6 +196,7 @@ export default {
} else { } else {
newIsLike = type; newIsLike = type;
if (type === -1) { if (type === -1) {
this.feedbackText = ''
this.caiDialogShow = true; this.caiDialogShow = true;
} else { } else {
this.caiDialogShow = false; this.caiDialogShow = false;
@@ -221,6 +223,10 @@ export default {
}, },
// 确定 // 确定
handleSure() { handleSure() {
if(this.feedbackText == ''){
this.$message({ type: "error", message: "请输入反馈内容"});
return;
}
let params = { let params = {
docId: this.messageData.docId, docId: this.messageData.docId,
feedback: this.feedbackText feedback: this.feedbackText

View File

@@ -1,123 +1,245 @@
<template> <template>
<div class="input-area"> <div class="input-area">
<el-input v-model="inputContent" type="textarea" class="input-placeholder" placeholder="有问题,尽管问" <el-input
@keyup.enter.native.prevent="handleSend" :disabled="disabled" :autosize="{ minRows: 2, maxRows: 4 }" v-model="inputContent"
resize="none"></el-input> type="textarea"
class="input-placeholder"
placeholder="有问题,尽管问"
@keyup.enter.native.prevent="handleSend"
:disabled="disabled"
:autosize="{ minRows: 2, maxRows: 4 }"
resize="none"
></el-input>
<div class="action-buttons"> <div class="action-buttons">
<el-button type="primary" size="small" class="start-btn" @click="handleNewConversation"> <el-button
type="primary"
size="small"
class="start-btn"
@click="handleNewConversation"
>
+ 开启新对话 + 开启新对话
</el-button> </el-button>
<el-button type="text" class="send-btn" @click="handleSend" :disabled="disabled"> <el-button
type="text"
class="send-btn"
@click="handleSend"
v-if="sendShow"
>
<i class="el-icon-s-promotion"></i> <i class="el-icon-s-promotion"></i>
</el-button> </el-button>
<el-button
type="text"
class="send-btn"
@click="handleStop"
v-if="stopShow"
>
<img class="stop" src="@/assets/images/case/stop.png" alt="" />
</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { aiChat } from '@/api/boe/aiChat.js' import { aiChat } from "@/api/boe/aiChat.js";
import apiCase from "@/api/modules/cases.js";
export default { export default {
name: 'SendMessage', name: "SendMessage",
props: { props: {
value: { value: {
type: String, type: String,
default: '' default: "",
}, },
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false,
},
sendShow: {
type: Boolean,
default: true,
},
stopShow: {
type: Boolean,
default: false,
}, },
messageList: { messageList: {
type: Array, type: Array,
default: () => [] default: () => [],
}, },
suggestions: { suggestions: {
type: Array, type: Array,
default: () => [] default: () => [],
} },
}, },
data() { data() {
return { return {
inputContent: this.value, inputContent: this.value,
conversationId: '' // 会话ID currentAbortController: null, // 添加abort controller引用
} isStopped: false, // 添加停止状态
typingTimer: null, // 添加这一行
thinkTypingTimer: null, // 添加这一行
conversationId: "",
};
}, },
watch: { watch: {
value(newVal) { value(newVal) {
this.inputContent = newVal this.inputContent = newVal;
}
}, },
},
mounted() {
this.getConversationId();
},
methods: { methods: {
getConversationId() {
apiCase.initChat().then((res) => {
if (res.status == 200) {
const { result } = res;
// console.log(result);
this.conversationId = result;
sessionStorage.setItem("conversationId", this.conversationId);
}
});
},
handleSend(event) { handleSend(event) {
// 阻止事件的默认行为和冒泡 // 阻止事件的默认行为和冒泡
if (event) { if (event) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
console.log('preventDefault'); console.log("preventDefault");
} }
console.log('handleSend'); console.log("handleSend");
if (!this.inputContent.trim() || this.disabled) return if (!this.inputContent.trim() || this.disabled) return;
// 重置停止状态,确保可以正常发送新消息
this.isStopped = false;
// 添加用户消息到列表 // 添加用户消息到列表
const userMessage = { const userMessage = {
isBot: false, isBot: false,
text: this.inputContent text: this.inputContent,
}; };
this.messageList.push(userMessage); this.messageList.push(userMessage);
// 显示加载状态 // 显示加载状态
this.$emit('loading', true); this.$emit("loading", true);
// 调用AI聊天接口 (暂时注释掉SSE使用模拟数据) // 调用AI聊天接口 (暂时注释掉SSE使用模拟数据)
this.callAIChat(this.inputContent); this.callAIChat(this.inputContent);
// 清空输入框 // 清空输入框
this.inputContent = '' this.inputContent = "";
}, },
handleStop() {
console.log(this.accumulatedContent, "accumulatedContent");
// 设置停止状态
this.isStopped = true;
// 清除打字机定时器
if (this.typingTimer) {
clearInterval(this.typingTimer);
this.typingTimer = null;
}
if (this.thinkTypingTimer) {
clearInterval(this.thinkTypingTimer);
this.thinkTypingTimer = null;
}
if (this.conversationId) {
// const stopAbortController = new AbortController();
fetch(
`/systemapi/xboe/m/boe/case/ai/stop?conversationId=${this.conversationId}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
// signal: stopAbortController.signal,
}
)
.then((response) => {
if (response.ok) {
console.log("成功发送停止请求"); // 通知父组件需要重新获取会话ID
this.$emit("need-new-conversation-id");
} else {
console.error("停止请求失败:", response.status);
}
})
.catch((error) => {
console.error("停止请求出错:", error);
});
}
// 终止当前正在进行的聊天请求
if (this.currentAbortController) {
this.currentAbortController.abort();
}
// 立即发送加载完成事件,停止按钮状态切换
this.$emit("loading", false);
// 发送按钮状态更新事件
this.$emit("update-button-state", {
sendShow: true,
stopShow: false,
});
},
// 真实的SSE实现暂时注释掉 // 真实的SSE实现暂时注释掉
callAIChat(question) { callAIChat(question) {
// 重置停止状态
this.isStopped = false;
// 开始请求时显示加载状态
this.$emit("loading", true);
// 创建AbortController实例
this.currentAbortController = new AbortController();
// 创建新的AI消息对象 // 创建新的AI消息对象
const aiMessage = { const aiMessage = {
docId: '', docId: "",
isBot: true, isBot: true,
text: '', text: "",
status: null, status: null,
thinkText: '', thinkText: "",
caseRefers: [], // 添加caseRefers字段 caseRefers: [], // 添加caseRefers字段
textCompleted: false // 添加文字处理完成状态默认为false textCompleted: false, // 添加文字处理完成状态默认为false
}; };
this.messageList.push(aiMessage); this.messageList.push(aiMessage);
let hasFinished = false; // 新增
// 构造请求参数 // 构造请求参数
const requestData = { const requestData = {
conversationId: this.conversationId, conversationId: this.conversationId,
query: question query: question,
}; };
// 创建POST请求 // 创建POST请求
fetch('/systemapi/xboe/m/boe/case/ai/chat', { fetch("/systemapi/xboe/m/boe/case/ai/chat", {
method: 'POST', method: "POST",
headers: { headers: {
'Content-Type': 'application/json', "Content-Type": "application/json",
"accept": "text/event-stream", accept: "text/event-stream",
}, },
body: JSON.stringify(requestData) body: JSON.stringify(requestData),
}).then(r => { signal: this.currentAbortController.signal, // 添加signal
return r })
}).then(response => { .then((r) => {
return r;
})
.then((response) => {
// 处理流式响应 // 处理流式响应
const reader = response.body.getReader(); const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8'); const decoder = new TextDecoder("utf-8");
let buffer = ''; let buffer = "";
let accumulatedContent = ''; // 累积的内容用于打字机效果 let accumulatedContent = ""; // 累积的内容用于打字机效果
let accumulatedThinkContent = ''; // 累积的思考内容 let accumulatedThinkContent = ""; // 累积的思考内容
let inThinkSection = false; // 是否在思考部分 let inThinkSection = false; // 是否在思考部分
let typingTimer = null; // 打字机定时器 let typingTimer = null; // 打字机定时器
let thinkTypingTimer = null; // 思考内容打字机定时器 let thinkTypingTimer = null; // 思考内容打字机定时器
// 逐字显示文本的函数 // 逐字显示文本的函数
const typeText = (message, fullContent) => { const typeText = (message, fullContent) => {
// 如果已经停止,则直接显示全部内容
if (this.isStopped) {
message.text = fullContent;
this.$emit("update-message", message);
return;
}
// 如果已有定时器在运行,先清除它 // 如果已有定时器在运行,先清除它
if (typingTimer) { if (typingTimer) {
clearInterval(typingTimer); clearInterval(typingTimer);
@@ -136,11 +258,19 @@ export default {
const typingSpeed = 30; // 每个字符的间隔时间(毫秒) const typingSpeed = 30; // 每个字符的间隔时间(毫秒)
typingTimer = setInterval(() => { typingTimer = setInterval(() => {
// 如果已停止,立即停止渲染并保持当前内容
if (this.isStopped) {
clearInterval(typingTimer);
typingTimer = null;
// 保持当前已渲染的内容,不显示剩余内容
this.$emit("update-message", message);
return;
}
// 计算下一个要显示的字符索引 // 计算下一个要显示的字符索引
const nextIndex = message.text.length + 1; const nextIndex = message.text.length + 1;
if (nextIndex <= targetLength) { if (nextIndex <= targetLength) {
message.text = fullContent.substring(0, nextIndex); message.text = fullContent.substring(0, nextIndex);
this.$emit('update-message', message); this.$emit("update-message", message);
} else { } else {
clearInterval(typingTimer); clearInterval(typingTimer);
typingTimer = null; typingTimer = null;
@@ -157,6 +287,17 @@ export default {
// 逐字显示思考内容的函数 // 逐字显示思考内容的函数
const typeThinkText = (message, fullThinkContent) => { const typeThinkText = (message, fullThinkContent) => {
// 如果已经停止,则直接显示当前已渲染的内容并清理定时器
if (this.isStopped) {
// 清理可能存在的定时器
if (thinkTypingTimer) {
clearInterval(thinkTypingTimer);
thinkTypingTimer = null;
}
// 保持当前已渲染的内容,不显示完整内容
this.$emit("update-message", message);
return;
}
// 如果已有定时器在运行,先清除它 // 如果已有定时器在运行,先清除它
if (thinkTypingTimer) { if (thinkTypingTimer) {
clearInterval(thinkTypingTimer); clearInterval(thinkTypingTimer);
@@ -178,11 +319,19 @@ export default {
const typingSpeed = 20; // 每个字符的间隔时间(毫秒) const typingSpeed = 20; // 每个字符的间隔时间(毫秒)
thinkTypingTimer = setInterval(() => { thinkTypingTimer = setInterval(() => {
// 如果已停止,立即停止渲染并保持当前内容
if (this.isStopped) {
clearInterval(thinkTypingTimer);
thinkTypingTimer = null;
// 保持当前已渲染的内容,不显示剩余内容
this.$emit("update-message", message);
return;
}
// 计算下一个要显示的字符索引 // 计算下一个要显示的字符索引
const nextIndex = message.thinkText.length + 1; const nextIndex = message.thinkText.length + 1;
if (nextIndex <= targetLength) { if (nextIndex <= targetLength) {
message.thinkText = fullThinkContent.substring(0, nextIndex); message.thinkText = fullThinkContent.substring(0, nextIndex);
this.$emit('update-message', message); this.$emit("update-message", message);
} else { } else {
clearInterval(thinkTypingTimer); clearInterval(thinkTypingTimer);
thinkTypingTimer = null; thinkTypingTimer = null;
@@ -197,12 +346,26 @@ export default {
// 读取流数据 // 读取流数据
const read = () => { const read = () => {
reader.read().then(({ done, value }) => { // 如果已停止,直接返回
if (this.isStopped || hasFinished) {
this.$emit("loading", false);
return;
}
reader
.read()
.then(({ done, value }) => {
// 如果已停止,直接返回
if (this.isStopped || hasFinished) {
this.$emit("loading", false);
return;
}
if (done) { if (done) {
// 当流结束时,等待打字机效果完成 // 当流结束时,等待打字机效果完成
const waitForTyping = () => { const waitForTyping = () => {
if (!typingTimer) { if (!typingTimer) {
this.$emit('loading', false); this.$emit("loading", false);
} else { } else {
setTimeout(waitForTyping, 100); setTimeout(waitForTyping, 100);
} }
@@ -215,42 +378,61 @@ export default {
buffer += decoder.decode(value, { stream: true }); buffer += decoder.decode(value, { stream: true });
// 按行分割数据 // 按行分割数据
const lines = buffer.split('\n'); const lines = buffer.split("\n");
buffer = lines.pop(); // 保留不完整的行 buffer = lines.pop(); // 保留不完整的行
for (const line of lines) { for (const line of lines) {
if (line.startsWith('data:')) { // 如果已停止,跳出循环
if (this.isStopped) {
this.$emit("loading", false);
return;
}
if (line.startsWith("data:")) {
try { try {
const jsonData = JSON.parse(line.substring(5)); const jsonData = JSON.parse(line.substring(5));
// 根据status处理不同类型的数据 // 根据status处理不同类型的数据
switch (jsonData.status) { switch (jsonData.status) {
case 0: // 引用文件 case 0: // 引用文件
// 处理引用文件信息 // 处理引用文件信息
if (jsonData.fileRefer && jsonData.fileRefer.caseRefers) { if (
aiMessage.caseRefers = jsonData.fileRefer.caseRefers; jsonData.fileRefer &&
jsonData.fileRefer.caseRefers
) {
aiMessage.caseRefers =
jsonData.fileRefer.caseRefers;
// 更新父组件的messageList // 更新父组件的messageList
this.$emit('update-message', aiMessage); this.$emit("update-message", aiMessage);
} }
// 从响应中获取并保存conversationId // 从响应中获取并保存conversationId
if (jsonData.conversationId) { // if (jsonData.conversationId) {
this.conversationId = jsonData.conversationId; // this.conversationId = jsonData.conversationId;
sessionStorage.setItem('conversationId', jsonData.conversationId); // sessionStorage.setItem(
} // "conversationId",
// jsonData.conversationId
// );
// }
break; break;
case 1: // 流式对话内容 case 1: // 流式对话内容
if (!this.isStopped) {
// 处理 // 处理
const content = jsonData.content; const content = jsonData.content;
aiMessage.hasThink = false; aiMessage.hasThink = false;
if (content.startsWith('<think>')) { if (content.startsWith("<think>")) {
aiMessage.hasThink = true aiMessage.hasThink = true;
inThinkSection = true; inThinkSection = true;
accumulatedThinkContent = content.replace('<think>', ''); accumulatedThinkContent = content.replace(
"<think>",
""
);
// 使用打字机效果显示think内容 // 使用打字机效果显示think内容
typeThinkText(aiMessage, accumulatedThinkContent); typeThinkText(aiMessage, accumulatedThinkContent);
} else if (content.startsWith('</think>')) { } else if (content.startsWith("</think>")) {
inThinkSection = false; inThinkSection = false;
accumulatedThinkContent += content.replace('</think>', ''); accumulatedThinkContent += content.replace(
"</think>",
""
);
// 使用打字机效果显示think内容 // 使用打字机效果显示think内容
typeThinkText(aiMessage, accumulatedThinkContent); typeThinkText(aiMessage, accumulatedThinkContent);
} else if (inThinkSection) { } else if (inThinkSection) {
@@ -262,13 +444,21 @@ export default {
accumulatedContent += content; accumulatedContent += content;
// 如果thinkText已经显示完整则继续使用打字机效果显示内容 // 如果thinkText已经显示完整则继续使用打字机效果显示内容
if (aiMessage.hasThink) { if (aiMessage.hasThink) {
if (aiMessage.thinkText.length >= accumulatedThinkContent.length) { if (
aiMessage.thinkText.length >=
accumulatedThinkContent.length
) {
typeText(aiMessage, accumulatedContent); typeText(aiMessage, accumulatedContent);
} }
} else { } else {
typeText(aiMessage, accumulatedContent); typeText(aiMessage, accumulatedContent);
} }
}
// 发送事件更新按钮状态:显示停止按钮
this.$emit("update-button-state", {
sendShow: false,
stopShow: true,
});
} }
// 不在这里直接更新,让打字机效果处理更新 // 不在这里直接更新,让打字机效果处理更新
break; break;
@@ -276,88 +466,153 @@ export default {
case 2: // 回答完成 case 2: // 回答完成
// 不再在这里设置textCompleted状态 // 不再在这里设置textCompleted状态
// 更新父组件的messageList // 更新父组件的messageList
this.$emit('update-message', aiMessage); // 只有在未停止状态下才更新
if (!this.isStopped) {
// 更新父组件的messageList
this.$emit("update-message", aiMessage);
// 发送事件更新按钮状态:显示停止按钮
this.$emit("update-button-state", {
sendShow: false,
stopShow: true,
});
}
// 从响应中获取并保存conversationId // 从响应中获取并保存conversationId
break; break;
case 3: // 返回建议 case 3: // 返回建议
// 只有在未停止状态下才处理建议
if (!this.isStopped) {
// 这里可以处理建议问题 // 这里可以处理建议问题
this.$emit('update-suggestions', jsonData.suggestions); this.$emit(
"update-suggestions",
jsonData.suggestions
);
// 发送事件更新按钮状态:显示停止按钮
this.$emit("update-button-state", {
sendShow: false,
stopShow: true,
});
}
break; break;
case 4: // 交互完成 case 4: // 交互完成
aiMessage.status = 4 // 只有在未停止状态下才处理完成状态
if (!this.isStopped) {
aiMessage.status = 4;
// 从响应中获取并保存conversationId // 从响应中获取并保存conversationId
this.$emit('loading', false); // this.$emit("loading", false);
// 检查文本是否已经完全显示如果是则设置textCompleted为true // 检查文本是否已经完全显示如果是则设置textCompleted为true
if (isTextDisplayCompleted(aiMessage, accumulatedContent)) { if (
isTextDisplayCompleted(
aiMessage,
accumulatedContent
)
) {
// aiMessage.textCompleted = true; // aiMessage.textCompleted = true;
this.$emit('update-message', aiMessage); this.$emit("update-message", aiMessage);
// 发送事件更新按钮状态:显示发送按钮
hasFinished = true; // 标记完成
this.$emit("update-button-state", {
sendShow: true,
stopShow: false,
});
}
} }
break; break;
case 9: case 9:
if (jsonData.docId) { // 只有在未停止状态下才处理docId
aiMessage.docId = jsonData.docId if (!this.isStopped && jsonData.docId) {
this.$emit('update-message', aiMessage); aiMessage.docId = jsonData.docId;
this.$emit("update-message", aiMessage);
} }
console.log(jsonData) // 显示发送按钮,隐藏停止按钮
break // this.$emit("loading", false);
console.log(jsonData);
// 发送事件更新按钮状态:显示发送按钮
hasFinished = true; // 标记完成
this.$emit("update-button-state", {
sendShow: true,
stopShow: false,
});
break;
default: default:
if (jsonData.docId) { if (!this.isStopped && jsonData.docId) {
aiMessage.docId = jsonData.docId aiMessage.docId = jsonData.docId;
this.$emit('update-message', aiMessage); this.$emit("update-message", aiMessage);
} }
break break;
} }
} catch (error) { } catch (error) {
console.error('解析SSE数据错误:', error); console.error("解析SSE数据错误:", error);
} }
} }
} }
// 继续读取(除非已停止)
// 继续读取 if (!this.isStopped) {
read(); read();
}).catch(error => { }
console.error('SSE连接错误:', error); // 继续读取
// read();
})
.catch((error) => {
// 处理AbortError
if (error.name === "AbortError") {
console.log("请求已被用户取消");
// aiMessage.text = "请求已被取消";
aiMessage.textCompleted = true;
this.$emit("update-message", aiMessage);
} else {
console.error("SSE连接错误:", error);
// 出错时也设置文字处理完成状态 // 出错时也设置文字处理完成状态
if (typingTimer) { if (typingTimer) {
clearInterval(typingTimer); clearInterval(typingTimer);
typingTimer = null; typingTimer = null;
} }
aiMessage.textCompleted = true; aiMessage.textCompleted = true;
this.$emit('loading', false); aiMessage.text = "当前无法获取回答,请稍后重试";
aiMessage.text = '当前无法获取回答,请稍后重试';
// 更新父组件的messageList // 更新父组件的messageList
this.$emit('update-message', aiMessage); this.$emit("update-message", aiMessage);
}
this.$emit("loading", false);
}); });
}; };
// 继续读取(除非已停止)
// 开始读取数据 if (!this.isStopped) {
read(); read();
}).catch(error => { }
console.error('请求失败:', error); })
.catch((error) => {
// 处理AbortError
if (error.name === "AbortError") {
console.log("请求已被用户取消");
aiMessage.text = "请求已被取消";
aiMessage.textCompleted = true;
this.$emit("update-message", aiMessage);
} else {
console.error("请求失败:", error);
// 出错时也设置文字处理完成状态 // 出错时也设置文字处理完成状态
aiMessage.textCompleted = true; aiMessage.textCompleted = true;
this.$emit('loading', false); aiMessage.text = "当前无法获取回答,请稍后重试";
aiMessage.text = '当前无法获取回答,请稍后重试';
// 更新父组件的messageList // 更新父组件的messageList
this.$emit('update-message', aiMessage); this.$emit("update-message", aiMessage);
}
// 只有在非停止状态下才发送 loading 事件
if (!this.isStopped) {
this.$emit("loading", false);
}
}); });
}, },
handleNewConversation() { handleNewConversation() {
this.conversationId = '' // this.conversationId = "";
this.$emit('new-conversation') this.$emit("new-conversation");
} this.getConversationId();
} },
} },
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.input-area { .input-area {
background-color: white; background-color: white;
@@ -405,5 +660,10 @@ export default {
} }
} }
} }
.stop {
width: 18px;
height: 18px;
display: block;
}
} }
</style> </style>