Merge branch 'main' into zouyf_dev

This commit is contained in:
“zouyf” 2024-11-12 15:29:13 +08:00
commit f20ddc1c58
3 changed files with 386 additions and 1 deletions

View File

@ -0,0 +1,308 @@
<template>
<div class="book-wrap">
<el-scrollbar height="100%">
<div class="book-name flex" @click="dialogVisible = true">
<span>{{ curBook.data.itemtitle }}</span>
<i class="iconfont icon-xiangyou"></i>
</div>
<div class="book-list" v-loading="treeLoading">
<el-tree :data="treeData" accordion :props="defaultProps" node-key="id"
:default-expanded-keys="defaultExpandedKeys" :current-node-key="curNode.data.id" highlight-current
@node-click="handleNodeClick">
<template #default="{ node }">
<span :title="node.label" class="tree-label">{{ node.label }}</span>
</template>
</el-tree>
</div>
</el-scrollbar>
</div>
<!--弹窗 选择教材-->
<el-dialog v-model="dialogVisible" append-to-body :show-close="false" width="550"
style="border-radius: 10px; padding: 10px 15px;">
<template #header>
<div class="choose-book-header flex">
<span>切换教材</span>
<i class="iconfont icon-guanbi" @click="dialogVisible = false"></i>
</div>
</template>
<div class="textbook-container">
<el-scrollbar height="450px">
<div class="textbook-item flex" v-for="item in subjectList" :class="curBook.data.id == item.id ? 'active-item' : ''"
:key="item.id" @click="changeBook(item)">
<img v-if="item.avartar" :src="item.avartar.indexOf('http') === 0 ? item.avartar : BaseUrl + item.avartar" class="textbook-img" alt="">
<div v-else class="textbook-img">
<i class="iconfont icon-jiaocaixuanze" style="font-size: 40px;"></i>
</div>
<span class="book-name">{{ item.itemtitle }}</span>
</div>
</el-scrollbar>
</div>
</el-dialog>
</template>
<script setup>
import { onMounted, ref, nextTick, toRaw, reactive } from 'vue';
import { cloneDeep } from 'lodash'
import { sessionStore } from '@/utils/store'
import { useGetSubject } from '@/hooks/useGetSubject'
const BaseUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
// emit
const emit = defineEmits(['nodeClick', 'changeBook'])
let useSubject = null
const subjectList = ref([])
const dialogVisible = ref(false)
//
const treeData = ref([])
const defaultProps = {
children: 'children',
label: 'itemtitle',
class: 'textbook-tree'
}
//
const curBook = reactive({
data: {}
})
//
const curNode = reactive({
data:{}
})
const treeLoading = ref(false)
//
const defaultExpandedKeys = ref([])
//
const changeBook = (data) => {
curBook.data = data
treeData.value = useSubject.getTreeData(data.id)
//
nextTick(() =>{
defaultExpandedKeys.value = [treeData.value[0].id]
curNode.data = getLastLevelData(treeData.value)[0]
handleNodeClick(curNode.data)
})
//
setTimeout(() => {
dialogVisible.value = false
}, 100);
}
const getLastLevelData = (tree) => {
let lastLevelData = [];
//
function traverseTree(nodes) {
nodes.forEach((node) => {
//
if (node.children && node.children.length > 0) {
traverseTree(node.children);
} else {
//
lastLevelData.push(node);
}
});
}
//
traverseTree(tree);
//
return lastLevelData;
}
// id
const findParentByChildId = (treeData, targetNodeId) => {
//
//
for (let node of treeData) {
// ID
if (node.children && node.children.some(child => child.id === targetNodeId)) {
// ID ID
return node;
}
//
if (node.children) {
let parentNode = findParentByChildId(node.children, targetNodeId);
if (parentNode) {
return parentNode;
}
}
}
// null
return null;
}
const handleNodeClick = (data) => {
/**
* data : 当前节点数据
*/
let nodeData = cloneDeep(toRaw(data));
//label label
nodeData.label = nodeData.itemtitle
// null
let parent = {
id: nodeData.parentid,
label: nodeData.parenttitle,
itemtitle: nodeData.parenttitle
}
const parentNode = nodeData.parentid ? parent : null
nodeData.parentNode = parentNode
let curData = {
textBook: {
curBookId: curBook.data.id,
curBookName: curBook.data.itemtitle,
curBookImg: BaseUrl + curBook.data.avartar,
curBookPath: curBook.data.fileurl
},
node: nodeData
}
// :electron-store
emit('nodeClick', curData)
}
onMounted( async () => {
treeLoading.value = true
try{
useSubject = await useGetSubject()
subjectList.value = sessionStore.get('subject.bookList')
//
if(sessionStore.get('subject.curBook')){
curBook.data = sessionStore.get('subject.curBook')
}
else{
curBook.data = subjectList.value[0]
}
// ""
treeData.value = useSubject.getTreeData(curBook.data.id)
nextTick(() =>{
//
if(sessionStore.get('subject.curNode')){
defaultExpandedKeys.value = sessionStore.get('subject.defaultExpandedKeys')
curNode.data = sessionStore.get('subject.curNode')
}else{
defaultExpandedKeys.value = [treeData.value[0].id]
curNode.data = getLastLevelData(treeData.value)[0]
}
handleNodeClick(curNode.data)
})
} finally{
treeLoading.value = false
}
})
</script>
<style lang="scss" scoped>
.book-wrap {
width: 300px;
height: 100%;
background: #ffffff;
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(99, 99, 99, 0.06);
display: flex;
flex-direction: column;
position: relative;
.book-name {
background-color: #ffffff;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 45px;
padding: 0 15px;
z-index: 1;
justify-content: space-between;
align-items: center;
color: #3b3b3b;
cursor: pointer;
border-bottom: solid #f4f5f7 1px;
font-size: 15px;
font-weight: 600;
border-radius: 10px 10px 0 0;
}
.book-list {
padding: 45px 10px 0 10px;
flex: 1;
}
}
:deep(.choose-dialog) {
border-radius: 10px;
}
.choose-book-header {
justify-content: space-between;
font-size: 15px;
font-weight: bold;
.icon-guanbi {
font-size: 20px;
cursor: pointer;
}
}
.textbook-container {
.textbook-item {
padding: 10px 20px;
align-items: center;
border-radius: 5px;
cursor: pointer;
.book-name {
margin-left: 20px;
color: #3b3b3b;
font-size: 13px;
}
&:hover {
background: #f4f7f9;
}
}
.active-item {
background-color: #f4f7f9;
.book-name {
color: #368fff;
font-weight: bold
}
}
.textbook-img {
width: 55px;
height: 70px;
display: flex;
align-items: center;
justify-content: center;
}
}
:deep(.el-tree-node) {
.el-tree-node__content {
height: 40px;
border-radius: 10px;
&:hover {
background-color: #eaf3ff;
}
}
}
.tree-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
:deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content) {
background-color: #eaf3ff !important;
color: #409EFF
}
</style>

View File

@ -0,0 +1,64 @@
<template>
<div style="padding: 10px;">
<el-dialog
v-model="dialogVisible"
width="350"
append-to-body
>
<div style="display: flex;justify-content: center;">
<ChooseTextbook @node-click="nodeClick" />
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click.stop="save">确定</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, defineExpose,defineEmits } from 'vue'
import ChooseTextbook from './chooseTextbook.vue'
const emit = defineEmits(['onsuccess'])
const dialogVisible = ref(false)
const getNodeInfo = ref({})
const openDialog = () => {
dialogVisible.value = true
}
const getFullObj = (node) => {
const obj = []
const recursive = (currentNode) => {
//
if (currentNode.parentNode) {
obj.unshift({id: currentNode.id,title:currentNode.itemtitle})
recursive(currentNode.parentNode)
} else {
obj.unshift({id: currentNode.id,title:currentNode.itemtitle})
}
}
recursive(node)
return obj
}
const nodeClick = (data) => {
getNodeInfo.value = {
textbookId:data.node.rootid,
bookList:getFullObj(data.node)
}
console.log(getNodeInfo.value,'log')
}
const save = () => {
dialogVisible.value = false
emit('onsuccess', getNodeInfo.value)
}
defineExpose({
openDialog
})
</script>

View File

@ -2,6 +2,7 @@
<div v-loading="isLoading" class="page-resource flex"> <div v-loading="isLoading" class="page-resource flex">
<ChooseTextbook @node-click="nodeClick" /> <ChooseTextbook @node-click="nodeClick" />
<div class="page-center-wrap"> <div class="page-center-wrap">
<el-button @click="openChapter" type="primary">打开章节</el-button>
<el-tabs v-model="activeAptTab" style="height: 100%;"> <el-tabs v-model="activeAptTab" style="height: 100%;">
<el-tab-pane label="教学课件" name="教学课件" class="prepare-center-jxkj"> <el-tab-pane label="教学课件" name="教学课件" class="prepare-center-jxkj">
<div class="prepare-center-header"> <div class="prepare-center-header">
@ -140,6 +141,8 @@
<!-- 上课配置 --> <!-- 上课配置 -->
<class-start ref="calssRef" @close="closeChange"/> <class-start ref="calssRef" @close="closeChange"/>
<PptDialog @add-success="addAiPPT" :currentNode="currentNode" :uploadData="uploadData" v-model="pptDialog"/> <PptDialog @add-success="addAiPPT" :currentNode="currentNode" :uploadData="uploadData" v-model="pptDialog"/>
<!-- 章节弹窗 -->
<TreeLog ref="treelogRef"/>
<!-- <button @click="test">test</button> --> <!-- <button @click="test">test</button> -->
</template> </template>
<script setup> <script setup>
@ -178,6 +181,7 @@ import ClassReserv from '@/views/classManage/classReserv.vue'
import classStart from './container/class-start.vue' // import classStart from './container/class-start.vue' //
import MsgEnum from '@/plugins/imChat/msgEnum' // im import MsgEnum from '@/plugins/imChat/msgEnum' // im
import Chat from '@/utils/chat' // im import Chat from '@/utils/chat' // im
import TreeLog from './components/treeLog.vue'
if (!Chat.imChat) Chat.init() if (!Chat.imChat) Chat.init()
const toolStore = useToolState() const toolStore = useToolState()
@ -235,7 +239,9 @@ export default {
isOpenHomework: false, isOpenHomework: false,
// //
activeClass: null, activeClass: null,
pptDialog: false pptDialog: false,
//
treelogRef:null
} }
}, },
computed: { computed: {
@ -630,6 +636,8 @@ export default {
}) })
}, },
async nodeClick(data) { async nodeClick(data) {
console.log(data,'data');
if (this.currentNode.id === data.node.id) return if (this.currentNode.id === data.node.id) return
this.curBookImg = data.textBook.curBookImg this.curBookImg = data.textBook.curBookImg
this.curBookPath = data.textBook.curBookPath this.curBookPath = data.textBook.curBookPath
@ -788,6 +796,11 @@ export default {
'&reservId=' + '&reservId=' +
id id
}) })
},
//
openChapter(){
//
this.$refs.treelogRef.openDialog()
} }
} }
} }