lijiaqi 3 months ago
parent 63efc9bce9
commit 74aabb14e2
  1. 4
      .env.development
  2. 6
      src/api/user/chapter.js
  3. 6
      src/api/user/object.js
  4. 4
      src/layout/menu/index.vue
  5. 36
      src/router/routers.ts
  6. 1
      src/views/course/basicCourseInformation.vue
  7. 4
      src/views/course/components/course-brief.vue
  8. 39
      src/views/course/components/course-chapters.vue
  9. 239
      src/views/course/components/course-object.vue
  10. 9
      src/views/course/components/courseEdit.vue
  11. 199
      src/views/course/components/knowledge-statistic.vue

@ -1,5 +1,5 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台'
# VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_BASE_API = 'http://39.106.16.162:8080'
VITE_APP_BASE_API = 'http://127.0.0.1:8080'
# VITE_APP_BASE_API = 'http://39.106.16.162:8080'

@ -1,11 +1,11 @@
import request from '@/utils/request'
// 获取课程章节列表
export const getChaptersListApi = (params) => {
return request.get(`/chapter2/chapter?courseId=${params.id}`)
return request.get(`api/chapter2/chapter?courseId=${params.id}`)
}
// 添加课程章节
export const addChaptersApi = (params) => request.post('/chapter2/add', params)
export const addChaptersApi = (params) => request.post('api/chapter2/add', params)
// 删除课程章节
export const delChaptersApi = (id) => {
return request.delete(`/chapter2/delete/${id}`)
return request.delete(`api/chapter2/delete/${id}`)
}

@ -1,6 +1,8 @@
import request from '@/utils/request'
// 获取目标类型
export const getObjectType = () => request.get(`/api/objectives_type/list`)
// 添加显示目标类型
export const getObjectType = (id) => {
return request.get(`/api/course_objectives/objectiveslist/${id}`)
}
// 修改目标内容
export const updateContents = (params) => {
return request.put(`/api/objective_contents/update`, params)

@ -20,7 +20,7 @@
</el-menu-item>
</template>
<!-- 有子路由但是只有一个子路由 -->
<template v-if="item.children && item.children.length === 1">
<template v-if="item.children && (item.children.length === 1||item.children.filter(o=>!o.meta.hidden).length==1)">
<el-menu-item
v-if="!item.children[0].meta.hidden"
:index="item.children[0].path"
@ -37,7 +37,7 @@
<!-- 有子路由且有多个 -->
<el-sub-menu
:index="item.path"
v-if="item.children && item.children.length > 1"
v-if="item.children && item.children.length > 1&&item.children.filter(o=>!o.meta.hidden).length!=1"
>
<template #title>
<el-icon>

@ -77,7 +77,7 @@ export const constantRoute: any = [
name: 'CurriculumCenter',
meta: {
title: '课程',
hidden: false,
hidden: true,
icon: 'HomeFilled', // 菜单图标
},
children: [
@ -97,7 +97,7 @@ export const constantRoute: any = [
name: 'CourseDetails',
meta: {
title: '课程详情',
hidden: false,
hidden: true,
icon: 'Notebook',
},
},
@ -107,7 +107,7 @@ export const constantRoute: any = [
name: 'CourseObjectives',
meta: {
title: '课程目标',
hidden: false,
hidden: true,
icon: 'Notebook',
},
},
@ -117,7 +117,7 @@ export const constantRoute: any = [
name: 'CourseChapters',
meta: {
title: '课程章节',
hidden: false,
hidden: true,
icon: 'Notebook',
},
},
@ -127,7 +127,7 @@ export const constantRoute: any = [
name: 'KnowledgePoints', // name 要与权限一致
meta: {
title: '知识点',
hidden: false,
hidden: true,
icon: 'Notebook',
},
},
@ -137,7 +137,7 @@ export const constantRoute: any = [
name: 'CurriculumMap', // name 要与权限一致
meta: {
title: '课程图谱',
hidden: false,
hidden: true,
icon: 'Notebook',
},
},
@ -188,8 +188,8 @@ export const constantRoute: any = [
},
{
path: '/messageManagement/sendMessage',
component: ()=>import('@/views/message/components/sendMessage.vue'),
name:'SendMessage',
component: () => import('@/views/message/components/sendMessage.vue'),
name: 'SendMessage',
meta: {
title: '个人发出',
hidden: true,
@ -198,8 +198,8 @@ export const constantRoute: any = [
},
{
path: '/messageContentList',
component:()=>import('@/views/message/components/indexContentList.vue'),
name:'MessageContentList',
component: () => import('@/views/message/components/indexContentList.vue'),
name: 'MessageContentList',
meta: {
title: '收到信息详情',
hidden: true,
@ -208,8 +208,8 @@ export const constantRoute: any = [
},
{
path: '/sendMessageList',
component:()=>import('@/views/message/components/sendMessageList.vue'),
name:'SendMessageList',
component: () => import('@/views/message/components/sendMessageList.vue'),
name: 'SendMessageList',
meta: {
title: '发送信息详情',
hidden: true,
@ -222,7 +222,7 @@ export const constantRoute: any = [
path: '/messageContent',
component: () => import('@/views/message/components/messageContent.vue'),
name: 'MessageContent',
meta:{
meta: {
title: '写栈内信函',
hidden: true,
icon: 'EditPen',
@ -231,7 +231,7 @@ export const constantRoute: any = [
{
path: '/news',
component: () => import('@/layout/index.vue'),
name:'NewsManagement',
name: 'NewsManagement',
meta: {
title: '资讯',
hidden: false,
@ -240,8 +240,8 @@ export const constantRoute: any = [
children: [
{
path: '/news/newsContent',
component:()=>import('@/views/news/index.vue'),
name:'NewsContent',
component: () => import('@/views/news/index.vue'),
name: 'NewsContent',
meta: {
title: '资讯管理',
hidden: false,
@ -250,8 +250,8 @@ export const constantRoute: any = [
},
{
path: '/newsDetails',
component:()=>import('@/views/news/components/newsContent.vue'),
name:'NewsDetails',
component: () => import('@/views/news/components/newsContent.vue'),
name: 'NewsDetails',
meta: {
title: '新闻详情',
hidden: true,

@ -52,6 +52,7 @@ const getCourseList = async () => {
const res = await getCourseListApi(params.value)
courseList.value = res.data.list
total.value = res.data.total
console.log(res, 'courseres')
console.log(courseList.value, 'courseList.value')
loading.value = false
// console.log(userStore.userName, '1111')

@ -27,10 +27,8 @@ onMounted(() => {
<template>
<div class="grid-content course-brief" style="height: 350px">
<h1 style="text-align:">
{{ courseDetails.name }}
<span>主讲教师{{ courseDetails.teacher }}</span>
</h1>
<div class="box">
<div class="image">
@ -147,8 +145,6 @@ onMounted(() => {
margin-bottom: 20px;
font-family: Inter, Inter;
color: #333333ff;
}
h3 {

@ -9,14 +9,15 @@ import {
delChaptersApi,
} from '@/api/user/chapter'
import { onMounted } from 'vue'
// const route = useRoute()
const route = useRoute()
// const router = useRouter()
// const courseId = ref()
const courseId = '719f91586a64413898253c5b7d046fd8'
const courseId = ref()
// const courseId = '719f91586a64413898253c5b7d046fd8'
onMounted(() => {
// courseId.value = route.query.id
// courseId.value = '719f91586a64413898253c5b7d046fd8'
courseId.value = route.query.id
console.log(courseId.value, 'route.query.id');
// courseId.value = '719f91586a64413898253c5b7d046fd8'
getChaptersList()
})
@ -106,7 +107,7 @@ const remove = async (node: Node, data: Tree) => {
})
}
//
const getDetails = (id: any) => {}
const getDetails = (id: any) => { }
const dataSource = ref<Tree[]>([
{
id,
@ -134,36 +135,18 @@ const dataSource = ref<Tree[]>([
<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="暂无章节"
>
<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 @click="getDetails(data.id)">{{ data.name }}</span>
<span>
<el-button
@click="append(data)"
circle
size="small"
type="primary"
plain
>
<el-button @click="append(data)" circle size="small" type="primary" plain>
<el-icon :size="15">
<Plus />
</el-icon>
</el-button>
<el-button
@click="remove(node, data)"
circle
size="small"
type="danger"
plain
>
<el-button @click="remove(node, data)" circle size="small" type="danger" plain>
<el-icon :size="15">
<Delete />
</el-icon>

@ -8,9 +8,9 @@ import {
delObjectContents,
addObjectContents,
getObjectContent,
getObjectType,
} from '@/api/user/object'
import { useRoute } from 'vue-router'
// import { ITEM_RENDER_EVT } from 'element-plus/es/components/virtual-list/src/defaults.mjs'
const route = useRoute()
// const router = useRouter()
const courseId = ref()
@ -23,39 +23,52 @@ const params = ref({
objectiveId: '',
})
//
const list = ref([])
const getObject = async () => {
const res = await getObjectList({ id: courseId.value })
console.log(res, 'objectres')
data.value = res.data[0].courseObjectivesTrees
params.value = res.data[0].contents[0]
console.log(params.value, 'params.value')
console.log(data, 'data');
console.log(res.data, 'res.data[0].contents[0]');
Object.assign(params.value, res.data[0].contents[0])
// params.value = res.data[0].contents[0]
list.value = data.value.map(item => item.contents).flat()
console.log(list.value, 'list.value ');
console.log(data.value, 'data.value')
// content.value = res.data[0].contents[0].content
}
// console.log(content.value, 'content.value')
}
//
// const type = ref({
// id: '',
// typeName: '',
// })
// const getType = async () => {
// const res = await getObjectType()
// type.value = res.data.slice(1, 5)
// console.log(type.value, 'typeres')
// }
const type = ref({
id: '',
name: '',
})
const getType = async () => {
console.log(courseId, 'typecourse')
const res = await getObjectType(courseId.value)
type.value = res.data
console.log(res, 'typeres')
}
onMounted(() => {
courseId.value = route.query.id
console.log(courseId.value, 'courseid.vlue')
getObject()
getType()
})
//
const isEditing = ref(false)
const content = ref('')
const updateContent = () => {
isEditing.value = true
content.value = params.value.content
}
const content = ref('')
//
const saveContent = async () => {
console.log(params.value.content, ' params.value.content')
@ -73,6 +86,9 @@ const saveContent = async () => {
})
.then(async () => {
params.value.content = content.value
const res = await updateContents({
id: params.value.id,
objectiveId: params.value.objectiveId,
@ -81,8 +97,10 @@ const saveContent = async () => {
console.log(res, 'res')
ElMessage.success('保存成功!')
isEditing.value = false
})
.catch(() => {
}, () => {
//
ElMessage.info('您已取消操作')
})
@ -101,6 +119,9 @@ const delObject = async (id: any) => {
await delObjectContents(id).then(() => {
ElMessage.success('删除成功')
getObject()
}).catch((err: any) => {
// console.log(id, 'id')
ElMessage.error(err.response.data.message)
})
}
//
@ -126,7 +147,9 @@ const objectiveIds = ref(0)
const addObject = (item: any) => {
// console.log(id, 'id')
dialogVisible.value = true
flog.value = false
type.value.name = ''
formData.value.description = ''
// updateDisabledStatus()
objectiveIds.value = item.id
@ -157,6 +180,7 @@ const submit = async () => {
} else {
console.log(objectiveIds, 'objectiveIds')
await addObjectContents({
// id: type.value.id,
objectiveId: objectiveIds.value,
content: formData.value.description,
})
@ -181,13 +205,7 @@ const submit = async () => {
<template #header>
<div class="card-header">
<span>整体目标</span>
<el-button
type="primary"
:icon="Edit"
circle
plain
@click="updateContent"
></el-button>
<el-button type="primary" :icon="Edit" circle plain @click="updateContent"></el-button>
</div>
</template>
<div class="el-card__body" style="">
@ -204,7 +222,7 @@ const submit = async () => {
</div>
</div>
<div class="typeObject">
<ul v-for="item in data" :key="item.id">
<!-- <ul v-for="item in data" :key="item.id">
<li>
<div class="all">
<div class="left">
@ -243,24 +261,36 @@ const submit = async () => {
</div>
<el-divider style="margin: 0; width: 100%" />
</li>
</ul>
<el-dialog
v-if="dialogVisible"
v-model="dialogVisible"
:title="flog ? '编辑' : '新增'"
width="500"
:before-close="handleClose"
>
<el-form
:model="formData"
label-width="auto"
style="max-width: 600px"
>
<el-form-item label="内容" prop="description">
<el-input
v-model="formData.description"
placeholder="请输入内容"
></el-input>
</ul> -->
<el-scrollbar>
<li v-for="(obj, i) in list" :key="obj.id">
<span>目标{{ i + 1 }}{{ obj.content }}</span>
<div class="icon">
<el-button type="primary" :icon="Edit" circle size="small" plain @click="updateObjectContent(obj.id)" />
<el-button type="danger" :icon="Delete" circle size="small" plain @click="delObject(obj.id)" />
<span>{{ data.name }}</span>
</div>
</li>
</el-scrollbar>
<el-button @click="addObject" circle size="small" type="primary" plain class="addbutton">
<el-icon :size="15">
<Plus />
</el-icon>
</el-button>
<el-dialog v-if="dialogVisible" v-model="dialogVisible" :title="flog ? '编辑' : '新增'" width="500"
:before-close="handleClose">
<el-form :model="type">
<el-form-item label="目标类别">
<el-select v-model="type.name" placeholder="请选择目标类别">
<el-option v-for="item in type" :key="item.id" :label="item.name" :value="item.name"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-form :model="formData" label-width="auto" style="max-width: 600px">
<el-form-item label="目标内容" prop="description">
<el-input v-model="formData.description" placeholder="请输入内容"></el-input>
</el-form-item>
</el-form>
<template #footer>
@ -268,6 +298,7 @@ const submit = async () => {
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</div>
</template>
</el-dialog>
</div>
@ -275,6 +306,10 @@ const submit = async () => {
</div>
</template>
<style lang="scss" scoped>
li {
list-style-type: none; //
}
.el-tabs__item {
padding: 0 50px;
}
@ -367,65 +402,81 @@ const submit = async () => {
}
.typeObject {
width: 70%;
// height: 80%;
text-align: center;
width: 60%;
height: 80%;
// text-align: center;
border: 1px solid #dcdfe6;
margin-right: 35px;
padding: 20px;
position: relative;
// align-items: center;
ul:nth-child(-n + 3) {
border-bottom: none;
.icon {
margin-left: 700px;
// display: inline-block;
// position: absolute;
}
ul {
width: 90%;
border: 1px solid #dcdfe6;
// box-shadow: 1px -5px 6px rgba(153, 150, 150, 0.5);
.addbutton {
position: absolute;
right: 20px;
bottom: 20px;
}
.all {
display: flex;
width: 100%;
// box-shadow: 1px 1px 6px rgba(153, 150, 150, 0.5);
// align-content: center;
.left {
width: 20%;
display: flex;
justify-content: center;
border-right: 1px solid #dcdfe6;
flex-wrap: wrap;
align-content: center;
letter-spacing: 1px;
// align-items: center;
// ul:nth-child(-n + 3) {
// border-bottom: none;
// }
.icon {
margin-left: 10px;
}
// ul {
// width: 90%;
// border: 1px solid #dcdfe6;
.icon:hover {
cursor: pointer;
color: red;
}
}
// // box-shadow: 1px -5px 6px rgba(153, 150, 150, 0.5);
// }
.objectdetails {
padding-right: 20px;
width: 100%;
// border: 1px solid #8a8b99;
li {
width: 100%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
// align-content: center;
align-items: center;
line-height: 1;
margin-top: 2px;
letter-spacing: 1px;
}
}
}
// .all {
// display: flex;
// width: 100%;
// // box-shadow: 1px 1px 6px rgba(153, 150, 150, 0.5);
// // align-content: center;
// .left {
// width: 20%;
// display: flex;
// justify-content: center;
// border-right: 1px solid #dcdfe6;
// flex-wrap: wrap;
// align-content: center;
// letter-spacing: 1px;
// .icon {
// margin-left: 10px;
// }
// .icon:hover {
// cursor: pointer;
// color: red;
// }
// }
// .objectdetails {
// padding-right: 20px;
// width: 100%;
// // border: 1px solid #8a8b99;
// li {
// width: 100%;
// display: flex;
// justify-content: space-between;
// flex-wrap: wrap;
// // align-content: center;
// align-items: center;
// line-height: 1;
// margin-top: 2px;
// letter-spacing: 1px;
// }
// }
// }
}
}
}

@ -28,13 +28,13 @@ const defaultForm = {
teacher: userStore.data.id,
img: '',
name: '',
category: ref(0),
nature: ref(0),
category: '',
nature: '',
code: '',
credit: '',
classhours: '',
assessmenttype: ref(0),
assessmentway: ref(0),
assessmenttype: '',
assessmentway: '',
teachermethod: '',
teacherway: '',
description: '',
@ -133,6 +133,7 @@ const rules = {
message: '请输入课程简介',
trigger: 'blur',
},
{ max: 500, message: '不能超过500个字符', trigger: 'blur' }
]
}

@ -2,63 +2,174 @@
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import 'echarts-liquidfill'
const liquidechart3 = ref(null) //
const liquidechart1 = ref(null) //
const liquidechart2 = ref(null) //
onMounted(() => {
const myChart3 = echarts.init(liquidechart3.value) // 使 ref
myChart3.setOption({
title: {
text: '目标完成度',
textStyle: {
color: '#888',
fontFamily: 'microsoft yahei',
fontSize: 24,
fontWeight: '400',
align: 'center',
verticalAlign: 'middle',
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 线线 线
},
},
},
left: 'center',
top: '20%',
},
series: [
{
type: 'liquidFill',
radius: '95%',
waveAnimation: true,
data: [0.3], //
direction: 'left',
itemStyle: {
normal: {
color: '#1890ff',
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,
},
outline: {
borderDistance: 3,
itemStyle: {
borderColor: '#4984ff',
borderWidth: 10,
axisLine: {
show: false,
},
name: {
formatter: '{value}',
textStyle: {
color: 'rgba(0,0,0,0.4)',
fontSize: 16,
},
},
itemStyle: {
opacity: 0.9,
splitLine: {
lineStyle: {
color: '#6093FF',
type: 'solid',
width: 8,
},
},
backgroundStyle: {
color: '#fff',
},
],
series: [
{
type: 'radar',
emphasis: {
lineStyle: {
width: 20,
},
},
label: {
show: true,
color: '#000',
insideColor: '#fff',
fontSize: 24,
fontWeight: 400,
align: 'center',
verticalAlign: 'middle',
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)
const myChart1 = echarts.init(liquidechart1.value) // 使 ref
myChart1.setOption({
title: {
@ -170,7 +281,7 @@ onMounted(() => {
<div class="grid-content knowledge-statistic" style="height: 300px">
<!-- <h1>知识点统计</h1> -->
<div class="box">
<div style="width: 300px; height: 250px" ref="liquidechart3"></div>
<div style="width: 300px; height: 250px" id="main" class="radarmap"></div>
<div style="width: 300px; height: 250px" ref="liquidechart1"></div>
<div style="width: 300px; height: 250px" ref="liquidechart2"></div>
</div>
@ -181,6 +292,8 @@ onMounted(() => {
.knowledge-statistic {
display: flex;
align-content: center;
flex-direction: column;
align-items: center;
.box {
margin-top: 20px;

Loading…
Cancel
Save