parent
f16452cc6d
commit
c3c6e5e3de
9 changed files with 1251 additions and 0 deletions
@ -0,0 +1,7 @@ |
||||
import request from '@/utils/request' |
||||
// 获取课程章节列表
|
||||
export const getChaptersListApi = (params) => { |
||||
return request.get(`/chapter2/chapter?courseId=${params.id}`) |
||||
} |
||||
// 添加课程章节
|
||||
export const addChaptersApi = (params) => request.post('/chapter2/add', params) |
@ -0,0 +1,35 @@ |
||||
<script lang="ts" setup></script> |
||||
<template> |
||||
<div class="grid-content chapters-details" style="height: 300px"> |
||||
<h1>章节详情</h1> |
||||
<div class="info"> |
||||
<p>本章名称:认识计算机导论</p> |
||||
<p> |
||||
简介: |
||||
适用专业:软件工程专业本章目标:本课程对每个专题的讲座内容进行系统整理,形成了由讲座概要、专题内容、拓展阅读文献、教学课件和教学视频等组成的教学内容体系。学生可以根据自己的学习兴趣,由浅入深地进行拓展学习。通过学术讲座、学术沙龙、学术讨论等形式,使学生掌握较扎实的课程与教学的基础理论知识和其他相关知识,树立先进的教育观念;了解国内外教育改革实践;了解国内外课程与教学研究的历史、现状和动向,形成较强的独立从事课程与教学研究能力;对现实的课程与教学问题具有清晰的认识,能在现代教育观念指导下投入我国基础教育课程改革的实践。 |
||||
主 |
||||
</p> |
||||
<p>章节编号:1110</p> |
||||
<p>章节总学时:26h</p> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<style lang="scss" scoped> |
||||
.chapters-details { |
||||
h1 { |
||||
padding-top: 20px; |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 700; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
.info { |
||||
padding: 20px; |
||||
|
||||
p { |
||||
margin: 10px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,191 @@ |
||||
<script lang="ts" setup> |
||||
import { ref } from 'vue' |
||||
import { useRoute } from 'vue-router' |
||||
import { getCourseDetailApi } from '@/api/user/crouse' |
||||
import { onMounted } from 'vue' |
||||
const route = useRoute() |
||||
const courseId = ref() |
||||
const courseDetails = ref({ |
||||
img: '', |
||||
name: '', |
||||
teacher: '', |
||||
description: '', |
||||
code: '', |
||||
}) |
||||
courseId.value = route.query.id |
||||
console.log(courseId.value, 'id') |
||||
const getCourseDetails = async () => { |
||||
const res = await getCourseDetailApi(courseId.value) |
||||
courseDetails.value = res.data |
||||
// console.log(res) |
||||
console.log(courseDetails.value, 'courseDetails.value') |
||||
} |
||||
onMounted(() => { |
||||
getCourseDetails() |
||||
}) |
||||
</script> |
||||
<template> |
||||
<div class="grid-content course-brief" style="height: 350px"> |
||||
<h1 style="text-align:">课程基本信息</h1> |
||||
<div class="box"> |
||||
<div class="image"> |
||||
<img :src="courseDetails.img" alt="" /> |
||||
</div> |
||||
<div class="text"> |
||||
<h2 class="title"> |
||||
{{ courseDetails.name }} |
||||
<span>主讲教师:{{ courseDetails.teacher }}</span> |
||||
</h2> |
||||
<div> |
||||
<h3> |
||||
课程简介: |
||||
<el-scrollbar height="70px"> |
||||
<p class="pp">{{ courseDetails.description }}</p> |
||||
</el-scrollbar> |
||||
<!-- <textarea name="" id=""></textarea> --> |
||||
</h3> |
||||
<div class="brief"> |
||||
<ul class="ull"> |
||||
<li> |
||||
<p>课程编码</p> |
||||
<p>{{ courseDetails.code }}</p> |
||||
</li> |
||||
<li> |
||||
<p>课程学分</p> |
||||
<p>{{ courseDetails.category }}</p> |
||||
</li> |
||||
<li> |
||||
<p>课程学时</p> |
||||
<p>{{ courseDetails.classhours }}</p> |
||||
</li> |
||||
<li> |
||||
<p>课程性质</p> |
||||
<p>{{ courseDetails.nature }}</p> |
||||
</li> |
||||
<li> |
||||
<p>考核方式</p> |
||||
<p>{{ courseDetails.assessmentway }}</p> |
||||
</li> |
||||
<li> |
||||
<p>考核类型</p> |
||||
<p>{{ courseDetails.assessmenttype }}</p> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<style lang="scss" scoped> |
||||
.course-brief { |
||||
// display: flex; |
||||
|
||||
// justify-content: space-between; |
||||
|
||||
h1 { |
||||
// display: block; |
||||
padding-top: 20px; |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 700; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
.box { |
||||
width: 100%; |
||||
height: 80%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
|
||||
.image { |
||||
// position: relative; |
||||
margin-top: 20px; |
||||
margin-left: 20px; |
||||
margin-right: 20px; |
||||
width: 40%; |
||||
height: 90%; |
||||
border-radius: 6px; |
||||
background-color: rgb(211, 196, 199); |
||||
|
||||
img { |
||||
width: 100%; |
||||
height: 100%; |
||||
border-radius: 6px; |
||||
// margin: 25px; |
||||
// margin: 10px; |
||||
// width: 100%; |
||||
// height: 100%; |
||||
// background-color: rgb(211, 196, 199); |
||||
} |
||||
} |
||||
|
||||
.text { |
||||
width: 60%; |
||||
height: 100%; |
||||
// margin: 50px; |
||||
margin: 20px 60px 60px 0px; |
||||
// background-color: #74deff; |
||||
// background-image: linear-gradient(to right, #4984ff, #74deff); |
||||
border-radius: 20px; |
||||
|
||||
h2 { |
||||
font-weight: 600; |
||||
font-size: 26px; |
||||
margin-bottom: 20px; |
||||
font-family: Inter, Inter; |
||||
color: #333333ff; |
||||
|
||||
span { |
||||
margin-left: 40px; |
||||
font-size: 18px; |
||||
line-height: 30px; |
||||
color: #8a8b99; |
||||
} |
||||
} |
||||
|
||||
h3 { |
||||
color: #8a8b99; |
||||
font-size: 14px; |
||||
|
||||
.pp { |
||||
margin-top: 10px; |
||||
display: inline; |
||||
padding-left: 35px; |
||||
color: #2e2e2e; |
||||
} |
||||
} |
||||
|
||||
.brief { |
||||
border-radius: 4px; |
||||
width: 100%; |
||||
height: 50%; |
||||
|
||||
.ull { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
li { |
||||
// margin-top: 10px; |
||||
margin-right: 80px; |
||||
font-size: 14px; |
||||
text-align: center; |
||||
margin-bottom: 15px; |
||||
|
||||
p { |
||||
margin-top: 10px; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
p:nth-child(1) { |
||||
color: #8a8b99; |
||||
font-size: 14px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,159 @@ |
||||
<script setup lang="ts"> |
||||
import { ref } from 'vue' |
||||
import type Node from 'element-plus/es/components/tree/src/model/node' |
||||
import { ElMessage, ElMessageBox } from 'element-plus' |
||||
import { useRoute } from 'vue-router' |
||||
import { getChaptersListApi, addChaptersApi } from '@/api/user/chapter' |
||||
import { onMounted } from 'vue' |
||||
const route = useRoute() |
||||
// const router = useRouter() |
||||
const courseId = ref() |
||||
onMounted(() => { |
||||
courseId.value = route.query.id |
||||
getChaptersList() |
||||
}) |
||||
|
||||
// console.log(courseId.value, 'courseId.value') |
||||
const getChaptersList = async () => { |
||||
console.log(courseId.value, 'courseId.value') |
||||
const res = await getChaptersListApi({ id: courseId.value }) |
||||
const transformedData: Tree[] = res.data.map((item: any) => ({ |
||||
id: item.id, |
||||
name: item.name, |
||||
pid: item.pid, |
||||
children: item.children.map((children: any) => ({ |
||||
id: children.id, |
||||
name: children.name, |
||||
pid: children.pid, |
||||
|
||||
children: children.children.map((children: any) => ({ |
||||
id: children.id, |
||||
name: children.name, |
||||
pid: children.pid, |
||||
})), |
||||
})), |
||||
})) |
||||
dataSource.value = transformedData |
||||
console.log(res) |
||||
} |
||||
interface Tree { |
||||
id: number |
||||
name: string |
||||
pid: any |
||||
children?: Tree[] |
||||
} |
||||
let id = 1000 |
||||
// 添加 |
||||
const append = async (data: Tree) => { |
||||
ElMessageBox.prompt('请输入章节名称', '添加', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
}).then(async ({ value }) => { |
||||
const newChild = { id: id++, name: `${value}`, pid: data.id, children: [] } |
||||
// const res = await addChaptersApi({ name: value, pid: }) |
||||
const res = await addChaptersApi(newChild) |
||||
// getChaptersList() |
||||
|
||||
console.log(res) |
||||
if (!data.children) { |
||||
data.children = [] |
||||
} |
||||
data.children.push(newChild) |
||||
dataSource.value = [...dataSource.value] |
||||
// getChaptersList() |
||||
// if (res.code === 200) { |
||||
// // 成功添加后更新本地数据源 |
||||
// // dataSource.value = [...dataSource.value] |
||||
// } else { |
||||
// ElMessage({ |
||||
// type: 'error', |
||||
// message: '添加失败,请稍后再试', |
||||
// }) |
||||
// } |
||||
}) |
||||
} |
||||
// 删除 |
||||
const remove = async (node: Node, data: Tree) => { |
||||
await ElMessageBox.confirm('确定删除本章节吗?', '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
center: true, |
||||
}) |
||||
const parent = node.parent |
||||
const children: Tree[] = parent.data.children || parent.data |
||||
const index = children.findIndex((d) => d.id === data.id) |
||||
children.splice(index, 1) |
||||
dataSource.value = [...dataSource.value] |
||||
} |
||||
|
||||
const dataSource = ref<Tree[]>([ |
||||
{ |
||||
id, |
||||
name: '', |
||||
pid: '', |
||||
children: [ |
||||
{ |
||||
id, |
||||
name: '', |
||||
pid: '', |
||||
children: [ |
||||
{ |
||||
id, |
||||
name: '', |
||||
pid: '', |
||||
}, |
||||
], |
||||
}, |
||||
], |
||||
}, |
||||
]) |
||||
</script> |
||||
<template> |
||||
<div class="grid-content course-chapters" style="height: 820px"> |
||||
<h1>课程章节</h1> |
||||
<!-- <button @click="getChaptersList">获取</button> --> |
||||
<div class="custom-tree-container"> |
||||
<el-tree style="max-width: 600px" :data="dataSource" node-key="id" default-expand-all |
||||
:expand-on-click-node="false" empty-text="暂无章节"> |
||||
<template #default="{ node, data }"> |
||||
<span class="custom-tree-node"> |
||||
<span>{{ data.name }}</span> |
||||
<span> |
||||
<el-button @click="append(data)">添加</el-button> |
||||
<el-button @click="remove(node, data)">删除</el-button> |
||||
<!-- <a @click="append(data)"></a> --> |
||||
<!-- <a style="margin-left: 8px" @click="remove(node, data)">删除</a> --> |
||||
</span> |
||||
</span> |
||||
</template> |
||||
</el-tree> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<style lang="scss" scoped> |
||||
.course-chapters { |
||||
.show-checkbox { |
||||
display: false; |
||||
} |
||||
|
||||
h1 { |
||||
padding: 20px; |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 700; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
.custom-tree-node { |
||||
flex: 1; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
font-size: 18px; |
||||
padding-right: 8px; |
||||
// width: 20% |
||||
// width: 200px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,433 @@ |
||||
<script setup lang="ts"> |
||||
import { ref, onMounted } from 'vue' |
||||
import { ElMessage, ElMessageBox } from 'element-plus' |
||||
// import { id } from 'element-plus/es/locales.mjs' |
||||
|
||||
import * as echarts from 'echarts' |
||||
|
||||
// import { useRoute } from 'vue-router' |
||||
const emit = defineEmits(['updateObject']) |
||||
import { |
||||
getCourseList, |
||||
addCourse, |
||||
editCourse, |
||||
deleteCourse, |
||||
getCourseInfo, |
||||
} from '@/api/courseChaptersApi' |
||||
import { useRoute, useRouter } from 'vue-router' |
||||
const route = useRoute() |
||||
const router = useRouter() |
||||
const formData = ref({ |
||||
description: '', |
||||
}) |
||||
const activeIndex = ref(0) |
||||
// 新增 |
||||
const addPoint = (id: any) => { |
||||
console.log(id, 'id') |
||||
activeIndex.value = id |
||||
dialogVisible.value = true |
||||
flog.value = false |
||||
// updateDisabledStatus() |
||||
} |
||||
const params = ref({ |
||||
content: '', |
||||
id: '', |
||||
objectiveId: '', |
||||
}) |
||||
const content = ref('') |
||||
const textChange = async (val: any) => { |
||||
params.value.content = content.value |
||||
console.log(params.value.content, ' params.value.content') |
||||
console.log(params.value, 'params.value') |
||||
console.log(params.value.id, 'params.id') |
||||
|
||||
// const jsonstr = JSON.stringify(params) |
||||
// const res = await editCourse(jsonstr) |
||||
const res = await editCourse({ |
||||
id: params.value.id, |
||||
objectiveId: params.value.objectiveId, |
||||
content: params.value.content, |
||||
}) |
||||
|
||||
console.log(res, 'res') |
||||
|
||||
console.log(content.value, 'text.value') |
||||
} |
||||
// 弹窗 |
||||
const dialogVisible = ref(false) |
||||
// 关闭弹窗 |
||||
const handleClose = () => { |
||||
dialogVisible.value = false |
||||
} |
||||
const close = () => { |
||||
formData.value = { |
||||
id: null, |
||||
target: '', |
||||
description: '', |
||||
} |
||||
dialogVisible.value = false |
||||
} |
||||
// 筛选目标 |
||||
// const filterTarger = (target) => { |
||||
// const res = targetList.value.find((item) => { |
||||
// if (item.id === target) { |
||||
// console.log(item, 'item') |
||||
// return item |
||||
// } |
||||
// }) |
||||
// return res.label |
||||
// } |
||||
const editdata = ref({ id: '', objectiveId: '' }) |
||||
// 编辑事件 |
||||
const flog = ref(false) |
||||
const editBook = async (obj) => { |
||||
// 回显目标详情 |
||||
const res = await getCourseInfo({ id: obj.id }) |
||||
console.log(res, '回显res') |
||||
editdata.value.id = res.data.id |
||||
editdata.value.objectiveId = res.data.objectiveId |
||||
flog.value = true |
||||
// console.log(obj, '回显后obj') |
||||
activeIndex.value = res.data.id |
||||
formData.value.description = res.data.content |
||||
dialogVisible.value = true |
||||
} |
||||
// 弹窗提交事件 |
||||
const submit = async () => { |
||||
if (flog.value) { |
||||
await editCourse({ |
||||
...editdata.value, |
||||
content: formData.value.description, |
||||
}) |
||||
} else { |
||||
await addCourse({ |
||||
objectiveId: activeIndex.value, |
||||
content: formData.value.description, |
||||
}) |
||||
} |
||||
getList() |
||||
dialogVisible.value = false |
||||
formData.value.description = '' |
||||
activeIndex.value = '' |
||||
} |
||||
// 删除课程目标 |
||||
const del = async (obj) => { |
||||
await ElMessageBox.confirm('你确认要删除该课程目标吗', '温馨提示', { |
||||
type: 'warning', |
||||
confirmButtonText: '确认', |
||||
cancelButtonText: '取消', |
||||
}) |
||||
await deleteCourse({ id: obj.id }) |
||||
ElMessage.success('删除成功') |
||||
getList() |
||||
} |
||||
const data = ref({}) |
||||
const courseId = ref(0) |
||||
// 获取课程知识点列表 |
||||
const getList = async () => { |
||||
const res = await getCourseList({ id: courseId.value }) |
||||
console.log(res, 'res') |
||||
data.value = res.data[0] |
||||
params.value = res.data[0].contents[0] |
||||
console.log(params.value, 'params.value') |
||||
|
||||
console.log(data.value, 'data.value') |
||||
content.value = res.data[0].contents[0].content |
||||
} |
||||
|
||||
onMounted(async () => { |
||||
if (!Object.keys(route.query).length) { |
||||
return router.push('/curriculumCenter/courseDetails') |
||||
|
||||
// return router.push('/curriculumCenter/basicCourseInformation') |
||||
} |
||||
courseId.value = route.query.id |
||||
console.log(courseId.value, 'courseid.vlue') |
||||
getList() |
||||
let chartDom = document.getElementById('main') |
||||
let myChart = echarts.init(chartDom) |
||||
let option |
||||
option = { |
||||
radar: [ |
||||
{ |
||||
nameGap: 10, |
||||
indicator: [ |
||||
{ |
||||
text: '目标一\n', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '目标五\n\n', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '目标四\n\n', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '目标三\n\n', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '目标二\n\n', |
||||
max: 100, |
||||
}, |
||||
], |
||||
// 中心位置 |
||||
center: ['50%', '60%'], |
||||
// 半径 |
||||
radius: 100, |
||||
// 圆角起始角度 |
||||
startAngle: 90, |
||||
// 分割数 |
||||
splitNumber: 5, |
||||
shape: 'circle', |
||||
name: { |
||||
formatter: '{value}', |
||||
textStyle: { |
||||
color: '#333333', |
||||
fontSize: 16, |
||||
}, |
||||
gap: 10, |
||||
}, |
||||
splitArea: { |
||||
areaStyle: { |
||||
color: [ |
||||
'transparent', |
||||
'transparent', |
||||
'rgba(114, 172, 209, 0)', |
||||
'transparent', |
||||
'rgba(114, 172, 209, 0)', |
||||
], |
||||
}, |
||||
}, |
||||
// 设置雷达图中间射线的颜色 |
||||
axisLine: { |
||||
lineStyle: { |
||||
color: '#C8D9FF', |
||||
}, |
||||
}, |
||||
splitLine: { |
||||
lineStyle: { |
||||
color: '#DADADA', |
||||
width: 2, |
||||
type: 'dashed', //dashed solid dotted 射线类型【实线 虚线】 |
||||
}, |
||||
}, |
||||
}, |
||||
{ |
||||
nameGap: 10, |
||||
indicator: [ |
||||
{ |
||||
text: '达成度', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '达成度', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '达成度', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '达成度', |
||||
max: 100, |
||||
}, |
||||
{ |
||||
text: '达成度', |
||||
max: 100, |
||||
}, |
||||
], |
||||
|
||||
center: ['50%', '60%'], |
||||
radius: 100, |
||||
startAngle: 90, |
||||
splitNumber: 1, |
||||
shape: 'circle', |
||||
splitArea: { |
||||
show: false, |
||||
}, |
||||
axisLine: { |
||||
show: false, |
||||
}, |
||||
name: { |
||||
formatter: '{value}', |
||||
textStyle: { |
||||
color: 'rgba(0,0,0,0.4)', |
||||
fontSize: 16, |
||||
}, |
||||
}, |
||||
splitLine: { |
||||
lineStyle: { |
||||
color: '#6093FF', |
||||
type: 'solid', |
||||
width: 8, |
||||
}, |
||||
}, |
||||
}, |
||||
], |
||||
series: [ |
||||
{ |
||||
type: 'radar', |
||||
emphasis: { |
||||
lineStyle: { |
||||
width: 20, |
||||
}, |
||||
}, |
||||
symbol: 'none', |
||||
data: [ |
||||
{ |
||||
value: [74, 60, 80, 60, 74], |
||||
name: 'Data C', |
||||
areaStyle: { |
||||
color: '#DBE4F9', |
||||
}, |
||||
}, |
||||
], |
||||
}, |
||||
{ |
||||
type: 'radar', |
||||
emphasis: { |
||||
lineStyle: { |
||||
width: 20, |
||||
}, |
||||
}, |
||||
symbol: 'none', |
||||
data: [ |
||||
{ |
||||
value: [74, 60, 80, 40, 74], |
||||
name: 'Data B', |
||||
areaStyle: { |
||||
color: '#0052FF', |
||||
}, |
||||
}, |
||||
], |
||||
}, |
||||
], |
||||
} |
||||
|
||||
option && myChart.setOption(option) |
||||
}) |
||||
</script> |
||||
<template> |
||||
<div class="grid-content course-object" style="height: 450px"> |
||||
<h1>课程目标</h1> |
||||
<div class="all_content"> |
||||
<div class="graph"> |
||||
<div class="title">课程目标雷达图</div> |
||||
<div id="main" class="radarmap"></div> |
||||
</div> |
||||
<div class="object"> |
||||
<span>课程总目标:</span> |
||||
<!-- <el-scrollbar height="90px"> --> |
||||
<textarea class="textarea" @change="textChange" v-model="content"></textarea> |
||||
<!-- </el-scrollbar> --> |
||||
<div class="demo-collapse"> |
||||
<el-collapse v-model="activeName" accordion> |
||||
<el-collapse-item title="知识目标" name="1"> |
||||
<ul> |
||||
<li>目标一</li> |
||||
<li>目标二</li> |
||||
</ul> |
||||
</el-collapse-item> |
||||
<el-collapse-item title="素质目标" name="2"> |
||||
<ul> |
||||
<li>目标一</li> |
||||
<li>目标二</li> |
||||
</ul> |
||||
</el-collapse-item> |
||||
<el-collapse-item title="价值目标" name="3"> |
||||
<ul> |
||||
<li>目标一</li> |
||||
<li>目标二</li> |
||||
</ul> |
||||
</el-collapse-item> |
||||
<el-collapse-item title="思政目标" name="4"> |
||||
<ul> |
||||
<li>目标一</li> |
||||
<li>目标二</li> |
||||
</ul> |
||||
</el-collapse-item> |
||||
</el-collapse> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<style lang="scss" scoped> |
||||
.course-object { |
||||
h1 { |
||||
padding: 20px; |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 700; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
.all_content { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
|
||||
.graph { |
||||
width: 40%; |
||||
height: 100%; |
||||
|
||||
.title { |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 400; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
.radarmap { |
||||
width: 100%; |
||||
height: 90%; |
||||
margin-top: -60px; |
||||
} |
||||
} |
||||
|
||||
.object { |
||||
width: 60%; |
||||
|
||||
span { |
||||
// text-align: center; |
||||
font-size: 20px; |
||||
font-weight: 400; |
||||
// color: #4984ffff; |
||||
} |
||||
|
||||
// span:hover { |
||||
// color: red; |
||||
// } |
||||
|
||||
.el-scrollbar { |
||||
height: 30%; |
||||
width: 100%; |
||||
} |
||||
|
||||
.textarea { |
||||
width: 90%; |
||||
height: 20%; |
||||
border: none; |
||||
resize: none; |
||||
} |
||||
|
||||
.demo-collapse { |
||||
padding-top: 20px; |
||||
|
||||
.el-collapse { |
||||
--el-collapse-header-font-size: 16px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-collapse-item__header:hover { |
||||
color: #385ea9 !important; |
||||
/* 强制应用样式 */ |
||||
} |
||||
</style> |
@ -0,0 +1,172 @@ |
||||
<script lang="ts" setup> |
||||
// // import { useRouter } from 'vue-router' |
||||
// import { onMounted, ref, reactive, watch } from 'vue' |
||||
// import ForceGraph3D from '3d-force-graph' |
||||
// //@ts-ignore |
||||
// import { |
||||
// CSS2DRenderer, |
||||
// CSS2DObject, |
||||
// } from 'three/examples/jsm/renderers/CSS2DRenderer.js' |
||||
// //@ts-ignore |
||||
// import SpriteText from '../spritetext.js' |
||||
// // const $router = useRouter() |
||||
// // const jsonData = ref(null) |
||||
// let Graph: any = reactive({}) |
||||
// const props = defineProps({ |
||||
// width: { |
||||
// // type: Number, |
||||
// // default: |
||||
// // window.innerWidth || |
||||
// // document.documentElement.clientWidth || |
||||
// // document.body.clientWidth, |
||||
// }, |
||||
// height: { |
||||
// type: Number, |
||||
// // default: |
||||
// // window.innerHeight || |
||||
// // document.documentElement.clientHeight || |
||||
// // document.body.clientHeight, |
||||
// }, |
||||
// }) |
||||
// watch( |
||||
// () => props.width, |
||||
// (ne) => Graph.width(ne), |
||||
// ) |
||||
// watch( |
||||
// () => props.height, |
||||
// (ne) => Graph.height(ne), |
||||
// ) |
||||
// const dom = ref(null) |
||||
// onMounted(() => { |
||||
// Graph = ForceGraph3D({ |
||||
// extraRenderers: [new CSS2DRenderer()], |
||||
// })(document.getElementById('3d-graph') as HTMLElement) |
||||
// .jsonUrl('../../../public/data.json') |
||||
// // .nodeAutoColorBy('group') |
||||
// .nodeThreeObject((node: any) => { |
||||
// const nodeEl = document.createElement('div') |
||||
// nodeEl.textContent = node.label |
||||
// nodeEl.style.color = '#333333' |
||||
// nodeEl.style.borderRadius = '50%' |
||||
// // console.log(node, 111, Graph.graphData().nodes) |
||||
// return new CSS2DObject(nodeEl) |
||||
// }) |
||||
// .linkLabel((link: any) => link.label) // 指定链接上显示的文字属性 |
||||
// .linkWidth(0.8) |
||||
// .linkHoverPrecision(0.5) // 设置链接文字的显示精度,这里设置为一个足够小的值 |
||||
// .linkColor(() => '#dd92fd') // 设置连接线颜色为红色 |
||||
// .backgroundColor('#f5f6fd') |
||||
// .width(props.width) |
||||
// .height(props.height) |
||||
// .linkThreeObjectExtend(true) |
||||
// .nodeColor((node: any) => { |
||||
// return node.color |
||||
// }) |
||||
// .nodeRelSize(7) // 设置节点的相对大小为4 |
||||
// .nodeResolution(20) |
||||
// .linkDirectionalArrowLength(3) // 设置连接线箭头长度为3 |
||||
// .linkDirectionalArrowRelPos(1) // 设置连接线箭头位置为连接线末端 |
||||
// .nodeThreeObjectExtend(true) |
||||
// .onNodeClick((node: any) => { |
||||
// // Aim at node from outside it |
||||
// // 目标距离 |
||||
// const targetDistance = 200 // 设定一个一般的距离 |
||||
|
||||
// // 计算相机新位置 |
||||
// const distRatio = 1 + targetDistance / Math.hypot(node.x, node.y, node.z) |
||||
// const newPos = { |
||||
// x: node.x * distRatio, |
||||
// y: node.y * distRatio, |
||||
// z: node.z * distRatio, |
||||
// } |
||||
|
||||
// // 如果节点位于原点,则特殊处理 |
||||
// if (node.x === 0 && node.y === 0 && node.z === 0) { |
||||
// newPos.z = targetDistance // 将 z 轴设定为目标距离 |
||||
// } |
||||
|
||||
// // 移动相机至新位置 |
||||
// //@ts-ignore |
||||
// Graph.cameraPosition( |
||||
// newPos, // 新位置 |
||||
// node, // 视角焦点 |
||||
// 3000, // 过渡时长 |
||||
// ) |
||||
|
||||
// // 获取图表数据 |
||||
// //@ts-ignore |
||||
// const graphData = Graph.graphData() |
||||
|
||||
// // 遍历连接线,检查每条连接线的起点和终点是否与当前点击的节点相关联 |
||||
// graphData.links.forEach((link: any) => { |
||||
// // console.log(link); |
||||
|
||||
// if (link.source.id === node.id || link.target.id === node.id) { |
||||
// setLabel() |
||||
// // 将与当前点击节点相关联的连接线颜色设置为红色 |
||||
// // link.color = '#FF0000' // 设置连接线颜色为红色 |
||||
// //@ts-ignore |
||||
// Graph.linkColor((item: any): any => { |
||||
// if (item.source.id === node.id || item.target.id === node.id) { |
||||
// return 'red' |
||||
// } else { |
||||
// return '#dd92fd' |
||||
// } |
||||
// }) |
||||
// } else { |
||||
// // Graph.linkColor(() => '#a4c7fe') // 设置连接线颜色为红色 |
||||
// } |
||||
// }) |
||||
|
||||
// // 更新图形数据,以应用颜色变化 |
||||
// //@ts-ignore |
||||
// Graph.graphData(graphData) |
||||
// }) |
||||
// dom.value = document.querySelector('canvas') as any |
||||
// }) |
||||
|
||||
// const setLabel = () => { |
||||
// //@ts-ignore |
||||
// Graph.linkThreeObject((link: any) => { |
||||
// // extend link with text sprite |
||||
// const sprite = new SpriteText(`${link.label}`) |
||||
// sprite.color = '#ccc' |
||||
// sprite.textHeight = 1.5 |
||||
// return sprite |
||||
// }) |
||||
// //@ts-ignore |
||||
// Graph.linkPositionUpdate((sprite, { start, end }) => { |
||||
// //@ts-ignore |
||||
// const middlePos = Object.assign( |
||||
// ...['x', 'y', 'z'].map((c) => ({ |
||||
// //@ts-ignore |
||||
// [c]: start[c] + (end[c] - start[c]) / 2, // calc middle point |
||||
// })), |
||||
// ) |
||||
|
||||
// // Position sprite |
||||
// Object.assign(sprite.position, middlePos) |
||||
// }) |
||||
// //@ts-ignore |
||||
// Graph.d3Force('charge').strength(-120) |
||||
// } |
||||
// // const goToEditAtlas = () => { |
||||
// // console.log(jsonData.value) |
||||
|
||||
// // $router.push({ name: 'EditAtlas', params: { id: 123 } }) |
||||
// // } |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="grid-content knowledge-graph" style="height: 500px"> |
||||
<!-- <div class="graph"> |
||||
<div id="3d-graph"></div> |
||||
</div> --> |
||||
</div> |
||||
</template> |
||||
<style lang="scss" scoped> |
||||
.graph { |
||||
width: 200px; |
||||
height: 400px; |
||||
} |
||||
</style> |
@ -0,0 +1,142 @@ |
||||
<script lang="ts" setup> |
||||
import { ref, onMounted } from 'vue' |
||||
import * as echarts from 'echarts' |
||||
import 'echarts-liquidfill' |
||||
|
||||
const liquidechart1 = ref(null) // 第一个波浪水球图的引用 |
||||
const liquidechart2 = ref(null) // 第二个波浪水球图的引用 |
||||
|
||||
onMounted(() => { |
||||
const myChart1 = echarts.init(liquidechart1.value) // 使用 ref |
||||
myChart1.setOption({ |
||||
title: { |
||||
text: '知识点达成度', |
||||
textStyle: { |
||||
color: '#888', |
||||
fontFamily: 'microsoft yahei', |
||||
fontSize: 24, |
||||
fontWeight: '400', |
||||
align: 'center', |
||||
verticalAlign: 'middle', |
||||
}, |
||||
left: 'center', |
||||
top: '20%', |
||||
}, |
||||
series: [ |
||||
{ |
||||
type: 'liquidFill', |
||||
radius: '95%', |
||||
waveAnimation: true, |
||||
data: [0.5], // 数据值需用数组 |
||||
direction: 'left', |
||||
itemStyle: { |
||||
normal: { |
||||
color: '#1890ff', |
||||
}, |
||||
}, |
||||
outline: { |
||||
borderDistance: 3, |
||||
itemStyle: { |
||||
borderColor: '#4984ff', |
||||
borderWidth: 10, |
||||
}, |
||||
}, |
||||
itemStyle: { |
||||
opacity: 0.9, |
||||
}, |
||||
backgroundStyle: { |
||||
color: '#fff', |
||||
}, |
||||
label: { |
||||
show: true, |
||||
color: '#000', |
||||
insideColor: '#fff', |
||||
fontSize: 24, |
||||
fontWeight: 400, |
||||
align: 'center', |
||||
verticalAlign: 'middle', |
||||
}, |
||||
}, |
||||
], |
||||
}) |
||||
const myChart2 = echarts.init(liquidechart2.value) // 使用 ref |
||||
myChart2.setOption({ |
||||
title: { |
||||
text: '知识点完成度', |
||||
textStyle: { |
||||
color: '#888', |
||||
fontFamily: 'microsoft yahei', |
||||
fontSize: 24, |
||||
fontWeight: '400', |
||||
align: 'center', |
||||
verticalAlign: 'middle', |
||||
}, |
||||
left: 'center', |
||||
top: '20%', |
||||
}, |
||||
series: [ |
||||
{ |
||||
type: 'liquidFill', |
||||
radius: '95%', |
||||
waveAnimation: true, |
||||
data: [0.8], // 数据值需用数组 |
||||
direction: 'left', |
||||
itemStyle: { |
||||
normal: { |
||||
color: '#1890ff', |
||||
}, |
||||
}, |
||||
outline: { |
||||
borderDistance: 1, |
||||
itemStyle: { |
||||
borderColor: '#1890ff', |
||||
borderWidth: 10, |
||||
}, |
||||
}, |
||||
itemStyle: { |
||||
opacity: 0.9, |
||||
}, |
||||
backgroundStyle: { |
||||
color: '#fff', |
||||
}, |
||||
label: { |
||||
show: true, |
||||
color: '#000', |
||||
insideColor: '#fff', |
||||
fontSize: 24, |
||||
fontWeight: 400, |
||||
align: 'center', |
||||
verticalAlign: 'middle', |
||||
}, |
||||
}, |
||||
], |
||||
}) |
||||
}) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="grid-content knowledge-statistic" style="height: 300px"> |
||||
<h1>知识点统计</h1> |
||||
<div class="box"> |
||||
<div style="width: 300px; height: 250px" ref="liquidechart1"></div> |
||||
<div style="width: 300px; height: 250px" ref="liquidechart2"></div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.knowledge-statistic { |
||||
h1 { |
||||
padding-top: 20px; |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 700; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
.box { |
||||
display: flex; |
||||
justify-content: space-around; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,89 @@ |
||||
<script lang="ts" setup> |
||||
import { computed, ref } from 'vue' |
||||
|
||||
interface User { |
||||
chapter: string |
||||
name: string |
||||
type: string |
||||
} |
||||
|
||||
const search = ref('') |
||||
const filterTableData = computed(() => |
||||
tableData.filter( |
||||
(data) => |
||||
!search.value || |
||||
data.type.toLowerCase().includes(search.value.toLowerCase()), |
||||
), |
||||
) |
||||
const handleEdit = (index: number, row: User) => { |
||||
console.log(index, row) |
||||
} |
||||
const handleDelete = (index: number, row: User) => { |
||||
console.log(index, row) |
||||
} |
||||
|
||||
const tableData: User[] = [ |
||||
{ |
||||
chapter: '1.1课程标准', |
||||
type: 'PDF', |
||||
name: '好好学习', |
||||
}, |
||||
{ |
||||
chapter: '离散数学', |
||||
type: 'PPT', |
||||
name: '好好学习', |
||||
}, |
||||
{ |
||||
chapter: '1.1课程标准', |
||||
type: '视频', |
||||
name: '好好学习', |
||||
}, |
||||
{ |
||||
chapter: '1.1课程标准', |
||||
type: 'word', |
||||
name: '好好学习', |
||||
}, |
||||
] |
||||
</script> |
||||
<template> |
||||
<div class="grid-content resource-management" style="height: 500px"> |
||||
<h1>资源管理</h1> |
||||
<el-table :data="filterTableData" style="width: 90%; margin-left: 30px; font-size: 16px"> |
||||
<el-table-column label="相关内容" prop="chapter" /> |
||||
<el-table-column label="文件名称" prop="name" /> |
||||
<el-table-column label="文件类型" prop="type" /> |
||||
|
||||
<!-- <el-table-column label="修改" prop="name" /> |
||||
<el-table-column label="文件类型" prop="name" /> --> |
||||
<el-table-column align="right"> |
||||
<template #header> |
||||
<el-input v-model="search" size="small" placeholder="输入内容进行搜索" /> |
||||
</template> |
||||
<template #default="scope"> |
||||
<el-button size="small" @click="handleEdit(scope.$index, scope.row)"> |
||||
编辑 |
||||
</el-button> |
||||
<el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)"> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</template> |
||||
<style lang="scss" scoped> |
||||
.resource-management { |
||||
h1 { |
||||
// display: block; |
||||
padding: 20px; |
||||
text-align: center; |
||||
font-size: 24px; |
||||
font-weight: 700; |
||||
color: #333333ff; |
||||
} |
||||
|
||||
// el-table { |
||||
// font-size: 20px; |
||||
// } |
||||
} |
||||
</style> |
@ -0,0 +1,23 @@ |
||||
<template> |
||||
<div> |
||||
<button @click="toggle">点击折叠/展开</button> |
||||
<div v-if="isExpanded"> |
||||
<!-- 折叠内容 --> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup> |
||||
export default { |
||||
data() { |
||||
return { |
||||
isExpanded: false, |
||||
} |
||||
}, |
||||
methods: { |
||||
toggle() { |
||||
this.isExpanded = !this.isExpanded |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
Loading…
Reference in new issue