Compare commits

...

4 Commits

  1. 14
      .env.development
  2. 6
      src/api/user/chapter.js
  3. 6
      src/api/user/object.js
  4. 6
      src/layout/menu/index.vue
  5. 10
      src/router/routers.ts
  6. 63
      src/views/course/basicCourseInformation.vue
  7. 37
      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. 70
      src/views/course/components/courseEdit.vue
  11. 193
      src/views/course/components/knowledge-statistic.vue

@ -1,15 +1,5 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development' NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台' VITE_APP_TITLE = '无糖运营平台'
<<<<<<< HEAD VITE_APP_BASE_API = 'http://127.0.0.1:8080'
# 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://39.106.16.162:8080'
<<<<<<< HEAD
=======
http://localhost:5173/#/courseResourcesManagement/courseResources
>>>>>>> b0c11f6676b1ee245db7ea30ff02485e14c91a32
=======
# VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_BASE_API = 'http://39.106.16.162:8080'
http://localhost:5173/#/courseResourcesManagement/courseResources
>>>>>>> 72be77b12b37cb07a7dd807572ca24163c368ce0

@ -1,11 +1,11 @@
import request from '@/utils/request' import request from '@/utils/request'
// 获取课程章节列表 // 获取课程章节列表
export const getChaptersListApi = (params) => { 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) => { 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' 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) => { export const updateContents = (params) => {
return request.put(`/api/objective_contents/update`, params) return request.put(`/api/objective_contents/update`, params)

@ -1,10 +1,6 @@
<template> <template>
<template v-for="(item, index) in menuList[0].children" :key="item.path"> <template v-for="(item, index) in menuList[0].children" :key="item.path">
<el-menu-item <el-menu-item v-if="!item.meta.hidden" :index="item.path" @click="goToRoute">
v-if="!item.meta.hidden"
:index="item.path"
@click="goToRoute"
>
<el-icon> <el-icon>
<component :is="item.meta.icon"></component> <component :is="item.meta.icon"></component>
</el-icon> </el-icon>

@ -57,7 +57,7 @@ export const constantRoute: any = [
name: 'CourseDetails', name: 'CourseDetails',
meta: { meta: {
title: '课程详情', title: '课程详情',
hidden: false, hidden: true,
icon: 'Notebook', icon: 'Notebook',
}, },
}, },
@ -67,7 +67,7 @@ export const constantRoute: any = [
name: 'CourseObjectives', name: 'CourseObjectives',
meta: { meta: {
title: '课程目标', title: '课程目标',
hidden: false, hidden: true,
icon: 'Notebook', icon: 'Notebook',
}, },
}, },
@ -77,7 +77,7 @@ export const constantRoute: any = [
name: 'CourseChapters', name: 'CourseChapters',
meta: { meta: {
title: '课程章节', title: '课程章节',
hidden: false, hidden: true,
icon: 'Notebook', icon: 'Notebook',
}, },
}, },
@ -87,7 +87,7 @@ export const constantRoute: any = [
name: 'KnowledgePoints', // name 要与权限一致 name: 'KnowledgePoints', // name 要与权限一致
meta: { meta: {
title: '知识点', title: '知识点',
hidden: false, hidden: true,
icon: 'Notebook', icon: 'Notebook',
}, },
}, },
@ -97,7 +97,7 @@ export const constantRoute: any = [
name: 'CurriculumMap', // name 要与权限一致 name: 'CurriculumMap', // name 要与权限一致
meta: { meta: {
title: '课程图谱', title: '课程图谱',
hidden: false, hidden: true,
icon: 'Notebook', icon: 'Notebook',
}, },
}, },

@ -52,6 +52,7 @@ const getCourseList = async () => {
const res = await getCourseListApi(params.value) const res = await getCourseListApi(params.value)
courseList.value = res.data.list courseList.value = res.data.list
total.value = res.data.total total.value = res.data.total
console.log(res, 'courseres')
console.log(courseList.value, 'courseList.value') console.log(courseList.value, 'courseList.value')
loading.value = false loading.value = false
// console.log(userStore.userName, '1111') // console.log(userStore.userName, '1111')
@ -209,11 +210,7 @@ const CloseCouresNameChangeEvent = () => {
</el-form> </el-form>
<div class="course"> <div class="course">
<ul class="course_list"> <ul class="course_list">
<li <li v-if="userStore.userInfo.roleId[0] === '1'" @click="onAddCourse()" class="add_course">
v-if="userStore.userInfo.roleId[0] === '1'"
@click="onAddCourse()"
class="add_course"
>
<div class="plus"> <div class="plus">
<el-icon class="avatar-uploader-icon"> <el-icon class="avatar-uploader-icon">
<Plus /> <Plus />
@ -222,17 +219,8 @@ const CloseCouresNameChangeEvent = () => {
<h2 class="course_name">{{ course_name }}</h2> <h2 class="course_name">{{ course_name }}</h2>
</li> </li>
<li v-for="item in courseList" :key="item.id"> <li v-for="item in courseList" :key="item.id">
<img <img title="点击查看课程详情" :src="item.img" alt="" @click="onGetCourseObject(item.id)" />
title="点击查看课程详情" <h2 title="点击查看课程基本信息" class="course_name">
:src="item.img"
alt=""
@click="onGetCourseObject(item.id)"
/>
<h2
title="点击查看课程基本信息"
class="course_name"
@click="onEditCourse(item)"
>
{{ item.name }} {{ item.name }}
</h2> </h2>
<p class="teacher_name">讲师{{ item.teacher }}</p> <p class="teacher_name">讲师{{ item.teacher }}</p>
@ -245,36 +233,22 @@ const CloseCouresNameChangeEvent = () => {
<el-icon class="del" @click="onDeleteCourse(item.id)"> <el-icon class="del" @click="onDeleteCourse(item.id)">
<Delete /> <Delete />
</el-icon> </el-icon>
<el-button <el-button class="object" round plain @click="onGetCourseObject(item.id)">
class="object" 详情
round </el-button>
plain <el-button class="object1" round plain @click="onEditCourse(item)">
@click="onGetCourseObject(item.id)" 编辑
>
查看课程详情
</el-button> </el-button>
</li> </li>
</ul> </ul>
</div> </div>
<el-pagination <el-pagination v-model:current-page="params.pageNo" v-model:page-size="params.pageSize"
v-model:current-page="params.pageNo" :page-sizes="[2, 5, 7, 10]" :background="true" layout="jumper,total, sizes, prev, pager, next " :total="total"
v-model:page-size="params.pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"
:page-sizes="[2, 5, 7, 10]" style="margin-top: 10px; justify-content: center" />
:background="true"
layout="jumper,total, sizes, prev, pager, next "
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
style="margin-top: 10px; justify-content: center"
/>
</div> </div>
<course-edit <course-edit ref="drawer" @success="onSuccess" @couresNameChange="couresNameChangeEvent"
ref="drawer" @CloseCouresNameChange="CloseCouresNameChangeEvent" :flog="flog"></course-edit>
@success="onSuccess"
@couresNameChange="couresNameChangeEvent"
@CloseCouresNameChange="CloseCouresNameChangeEvent"
:flog="flog"
></course-edit>
</div> </div>
</div> </div>
</template> </template>
@ -320,6 +294,7 @@ const CloseCouresNameChangeEvent = () => {
} }
.course { .course {
// display: flex; // display: flex;
// flex: 0 0 25%; // flex: 0 0 25%;
// justify-content: space-between; // justify-content: space-between;
@ -399,6 +374,12 @@ const CloseCouresNameChangeEvent = () => {
margin-left: 180px; margin-left: 180px;
margin-top: -29px; margin-top: -29px;
} }
.object1 {
position: absolute;
margin-left: 250px;
margin-top: -29px;
}
} }
.plus { .plus {

@ -26,20 +26,23 @@ onMounted(() => {
</script> </script>
<template> <template>
<div class="grid-content course-brief" style="height: 350px"> <div class="grid-content course-brief" style="height: 350px">
<h1 style="text-align:">课程基本信息</h1> <h1 style="text-align:">
{{ courseDetails.name }}
<span>主讲教师{{ courseDetails.teacher }}</span>
</h1>
<div class="box"> <div class="box">
<div class="image"> <div class="image">
<img :src="courseDetails.img" alt="" /> <img :src="courseDetails.img" alt="" />
</div> </div>
<div class="text"> <div class="text">
<h2 class="title"> <!-- <h2 class="title">
{{ courseDetails.name }} {{ courseDetails.name }}
<span>主讲教师{{ courseDetails.teacher }}</span> <span>主讲教师{{ courseDetails.teacher }}</span>
</h2> </h2> -->
<div> <div>
<h3> <h3>
课程简介: 课程简介:
<el-scrollbar height="70px"> <el-scrollbar height="143px">
<p class="pp">{{ courseDetails.description }}</p> <p class="pp">{{ courseDetails.description }}</p>
</el-scrollbar> </el-scrollbar>
<!-- <textarea name="" id=""></textarea> --> <!-- <textarea name="" id=""></textarea> -->
@ -87,9 +90,16 @@ onMounted(() => {
// display: block; // display: block;
padding-top: 20px; padding-top: 20px;
text-align: center; text-align: center;
font-size: 24px; font-size: 26px;
font-weight: 700; font-weight: 700;
color: #333333ff; color: #333333ff;
span {
margin-left: 40px;
font-size: 18px;
line-height: 30px;
color: #8a8b99;
}
} }
.box { .box {
@ -135,13 +145,6 @@ onMounted(() => {
margin-bottom: 20px; margin-bottom: 20px;
font-family: Inter, Inter; font-family: Inter, Inter;
color: #333333ff; color: #333333ff;
span {
margin-left: 40px;
font-size: 18px;
line-height: 30px;
color: #8a8b99;
}
} }
h3 { h3 {
@ -161,23 +164,27 @@ onMounted(() => {
.brief { .brief {
border-radius: 4px; border-radius: 4px;
width: 100%; width: 100%;
height: 50%; height: 80%;
.ull { .ull {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin-top: 10px; margin-top: 10px;
align-content: space-around;
justify-content: space-between;
} }
li { li {
// margin-top: 10px; // margin-top: 10px;
// padding-left: 10px;
margin-right: 80px; margin-right: 80px;
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
margin-bottom: 15px; margin-bottom: 10px;
p { p {
margin-top: 10px; margin-top: 6px;
font-size: 16px; font-size: 16px;
} }

@ -9,14 +9,15 @@ import {
delChaptersApi, delChaptersApi,
} from '@/api/user/chapter' } from '@/api/user/chapter'
import { onMounted } from 'vue' import { onMounted } from 'vue'
// const route = useRoute() const route = useRoute()
// const router = useRouter() // const router = useRouter()
// const courseId = ref() const courseId = ref()
const courseId = '719f91586a64413898253c5b7d046fd8' // const courseId = '719f91586a64413898253c5b7d046fd8'
onMounted(() => { onMounted(() => {
// courseId.value = route.query.id courseId.value = route.query.id
// courseId.value = '719f91586a64413898253c5b7d046fd8' console.log(courseId.value, 'route.query.id');
// courseId.value = '719f91586a64413898253c5b7d046fd8'
getChaptersList() getChaptersList()
}) })
@ -106,7 +107,7 @@ const remove = async (node: Node, data: Tree) => {
}) })
} }
// //
const getDetails = (id: any) => {} const getDetails = (id: any) => { }
const dataSource = ref<Tree[]>([ const dataSource = ref<Tree[]>([
{ {
id, id,
@ -134,36 +135,18 @@ const dataSource = ref<Tree[]>([
<h1>课程章节</h1> <h1>课程章节</h1>
<!-- <button @click="getChaptersList">获取</button> --> <!-- <button @click="getChaptersList">获取</button> -->
<div class="custom-tree-container"> <div class="custom-tree-container">
<el-tree <el-tree style="max-width: 600px" :data="dataSource" node-key="id" default-expand-all
style="max-width: 600px" :expand-on-click-node="false" empty-text="暂无章节">
:data="dataSource"
node-key="id"
default-expand-all
:expand-on-click-node="false"
empty-text="暂无章节"
>
<template #default="{ node, data }"> <template #default="{ node, data }">
<span class="custom-tree-node"> <span class="custom-tree-node">
<span @click="getDetails(data.id)">{{ data.name }}</span> <span @click="getDetails(data.id)">{{ data.name }}</span>
<span> <span>
<el-button <el-button @click="append(data)" circle size="small" type="primary" plain>
@click="append(data)"
circle
size="small"
type="primary"
plain
>
<el-icon :size="15"> <el-icon :size="15">
<Plus /> <Plus />
</el-icon> </el-icon>
</el-button> </el-button>
<el-button <el-button @click="remove(node, data)" circle size="small" type="danger" plain>
@click="remove(node, data)"
circle
size="small"
type="danger"
plain
>
<el-icon :size="15"> <el-icon :size="15">
<Delete /> <Delete />
</el-icon> </el-icon>

@ -8,54 +8,67 @@ import {
delObjectContents, delObjectContents,
addObjectContents, addObjectContents,
getObjectContent, getObjectContent,
getObjectType,
} from '@/api/user/object' } from '@/api/user/object'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { ITEM_RENDER_EVT } from 'element-plus/es/components/virtual-list/src/defaults.mjs'
const route = useRoute() const route = useRoute()
// const router = useRouter() // const router = useRouter()
const courseId = ref(0) const courseId = ref()
// //
const data = ref({}) const data = ref({})
// //
const params = ref({ const params = ref({
content: '', content: '请添加整体目标',
id: '', id: '',
objectiveId: '', objectiveId: '',
}) })
// //
const list = ref([])
const getObject = async () => { const getObject = async () => {
const res = await getObjectList({ id: courseId.value }) const res = await getObjectList({ id: courseId.value })
console.log(res, 'objectres') console.log(res, 'objectres')
data.value = res.data[0].courseObjectivesTrees data.value = res.data[0].courseObjectivesTrees
params.value = res.data[0].contents[0] console.log(data, 'data');
console.log(params.value, 'params.value')
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 // content.value = res.data[0].contents[0].content
} // console.log(content.value, 'content.value')
}
// //
// const type = ref({ const type = ref({
// id: '', id: '',
// typeName: '', name: '',
// }) })
// const getType = async () => { const getType = async () => {
// const res = await getObjectType() console.log(courseId, 'typecourse')
// type.value = res.data.slice(1, 5) const res = await getObjectType(courseId.value)
// console.log(type.value, 'typeres')
// } type.value = res.data
console.log(res, 'typeres')
}
onMounted(() => { onMounted(() => {
courseId.value = route.query.id courseId.value = route.query.id
console.log(courseId.value, 'courseid.vlue') console.log(courseId.value, 'courseid.vlue')
getObject() getObject()
getType()
}) })
// //
const isEditing = ref(false) const isEditing = ref(false)
const content = ref('')
const updateContent = () => { const updateContent = () => {
isEditing.value = true isEditing.value = true
content.value = params.value.content content.value = params.value.content
} }
const content = ref('')
// //
const saveContent = async () => { const saveContent = async () => {
console.log(params.value.content, ' params.value.content') console.log(params.value.content, ' params.value.content')
@ -73,6 +86,9 @@ const saveContent = async () => {
}) })
.then(async () => { .then(async () => {
params.value.content = content.value params.value.content = content.value
const res = await updateContents({ const res = await updateContents({
id: params.value.id, id: params.value.id,
objectiveId: params.value.objectiveId, objectiveId: params.value.objectiveId,
@ -81,8 +97,10 @@ const saveContent = async () => {
console.log(res, 'res') console.log(res, 'res')
ElMessage.success('保存成功!') ElMessage.success('保存成功!')
isEditing.value = false isEditing.value = false
})
.catch(() => {
}, () => {
// //
ElMessage.info('您已取消操作') ElMessage.info('您已取消操作')
}) })
@ -101,6 +119,9 @@ const delObject = async (id: any) => {
await delObjectContents(id).then(() => { await delObjectContents(id).then(() => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
getObject() 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) => { const addObject = (item: any) => {
// console.log(id, 'id') // console.log(id, 'id')
dialogVisible.value = true dialogVisible.value = true
flog.value = false flog.value = false
type.value.name = ''
formData.value.description = '' formData.value.description = ''
// updateDisabledStatus() // updateDisabledStatus()
objectiveIds.value = item.id objectiveIds.value = item.id
@ -157,6 +180,7 @@ const submit = async () => {
} else { } else {
console.log(objectiveIds, 'objectiveIds') console.log(objectiveIds, 'objectiveIds')
await addObjectContents({ await addObjectContents({
// id: type.value.id,
objectiveId: objectiveIds.value, objectiveId: objectiveIds.value,
content: formData.value.description, content: formData.value.description,
}) })
@ -181,13 +205,7 @@ const submit = async () => {
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span>整体目标</span> <span>整体目标</span>
<el-button <el-button type="primary" :icon="Edit" circle plain @click="updateContent"></el-button>
type="primary"
:icon="Edit"
circle
plain
@click="updateContent"
></el-button>
</div> </div>
</template> </template>
<div class="el-card__body" style=""> <div class="el-card__body" style="">
@ -204,7 +222,7 @@ const submit = async () => {
</div> </div>
</div> </div>
<div class="typeObject"> <div class="typeObject">
<ul v-for="item in data" :key="item.id"> <!-- <ul v-for="item in data" :key="item.id">
<li> <li>
<div class="all"> <div class="all">
<div class="left"> <div class="left">
@ -243,24 +261,36 @@ const submit = async () => {
</div> </div>
<el-divider style="margin: 0; width: 100%" /> <el-divider style="margin: 0; width: 100%" />
</li> </li>
</ul> </ul> -->
<el-dialog <el-scrollbar>
v-if="dialogVisible" <li v-for="(obj, i) in list" :key="obj.id">
v-model="dialogVisible" <span>目标{{ i + 1 }}{{ obj.content }}</span>
:title="flog ? '编辑' : '新增'" <div class="icon">
width="500" <el-button type="primary" :icon="Edit" circle size="small" plain @click="updateObjectContent(obj.id)" />
:before-close="handleClose" <el-button type="danger" :icon="Delete" circle size="small" plain @click="delObject(obj.id)" />
> <span>{{ data.name }}</span>
<el-form </div>
:model="formData"
label-width="auto" </li>
style="max-width: 600px" </el-scrollbar>
> <el-button @click="addObject" circle size="small" type="primary" plain class="addbutton">
<el-form-item label="内容" prop="description"> <el-icon :size="15">
<el-input <Plus />
v-model="formData.description" </el-icon>
placeholder="请输入内容" </el-button>
></el-input> <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-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -268,6 +298,7 @@ const submit = async () => {
<el-button @click="close">取消</el-button> <el-button @click="close">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button> <el-button type="primary" @click="submit">确定</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
@ -275,6 +306,10 @@ const submit = async () => {
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
li {
list-style-type: none; //
}
.el-tabs__item { .el-tabs__item {
padding: 0 50px; padding: 0 50px;
} }
@ -367,65 +402,81 @@ const submit = async () => {
} }
.typeObject { .typeObject {
width: 70%; width: 60%;
// height: 80%; height: 80%;
text-align: center; // text-align: center;
// align-items: center;
ul:nth-child(-n + 3) {
border-bottom: none;
}
ul {
width: 90%;
border: 1px solid #dcdfe6; border: 1px solid #dcdfe6;
margin-right: 35px;
padding: 20px;
position: relative;
// box-shadow: 1px -5px 6px rgba(153, 150, 150, 0.5); .icon {
margin-left: 700px;
// display: inline-block;
// position: absolute;
} }
.all { .addbutton {
display: flex; position: absolute;
width: 100%; right: 20px;
// box-shadow: 1px 1px 6px rgba(153, 150, 150, 0.5); bottom: 20px;
// align-content: center; }
.left { // align-items: center;
width: 20%; // ul:nth-child(-n + 3) {
display: flex; // border-bottom: none;
justify-content: center; // }
border-right: 1px solid #dcdfe6;
flex-wrap: wrap;
align-content: center;
letter-spacing: 1px;
.icon { // ul {
margin-left: 10px; // width: 90%;
} // border: 1px solid #dcdfe6;
.icon:hover { // // box-shadow: 1px -5px 6px rgba(153, 150, 150, 0.5);
cursor: pointer; // }
color: red;
}
}
.objectdetails { // .all {
padding-right: 20px; // display: flex;
width: 100%; // width: 100%;
// border: 1px solid #8a8b99; // // box-shadow: 1px 1px 6px rgba(153, 150, 150, 0.5);
// // align-content: center;
li { // .left {
width: 100%; // width: 20%;
display: flex; // display: flex;
justify-content: space-between; // justify-content: center;
flex-wrap: wrap; // border-right: 1px solid #dcdfe6;
// flex-wrap: wrap;
// align-content: center; // align-content: center;
align-items: center; // letter-spacing: 1px;
line-height: 1;
margin-top: 2px; // .icon {
letter-spacing: 1px; // 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, teacher: userStore.data.id,
img: '', img: '',
name: '', name: '',
category: ref(0), category: '',
nature: ref(0), nature: '',
code: '', code: '',
credit: '', credit: '',
classhours: '', classhours: '',
assessmenttype: ref(0), assessmenttype: '',
assessmentway: ref(0), assessmentway: '',
teachermethod: '', teachermethod: '',
teacherway: '', teacherway: '',
description: '', description: '',
@ -127,6 +127,14 @@ const rules = {
trigger: 'change', trigger: 'change',
}, },
], ],
description: [
{
required: true,
message: '请输入课程简介',
trigger: 'blur',
},
{ max: 500, message: '不能超过500个字符', trigger: 'blur' }
]
} }
// //
@ -243,20 +251,11 @@ const upload = async (option: any) => {
</script> </script>
<template> <template>
<el-drawer <el-drawer :before-close="handleClose" v-model="visibleDrawer" direction="rtl"
:before-close="handleClose" :title="formModel.id ? '编辑课程' : '添加课程'">
v-model="visibleDrawer"
direction="rtl"
:title="formModel.id ? '编辑课程' : '添加课程'"
>
<el-form :model="formModel" :rules="rules" ref="formRef"> <el-form :model="formModel" :rules="rules" ref="formRef">
<el-form-item label="课程封面" prop="img"> <el-form-item label="课程封面" prop="img">
<el-upload <el-upload v-model="formModel.img" class="avatar-uploader" :http-request="upload" :show-file-list="false">
v-model="formModel.img"
class="avatar-uploader"
:http-request="upload"
:show-file-list="false"
>
<img v-if="imgUrl" :src="imgUrl" class="avatar" /> <img v-if="imgUrl" :src="imgUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"> <el-icon v-else class="avatar-uploader-icon">
<Plus /> <Plus />
@ -295,12 +294,8 @@ const upload = async (option: any) => {
</el-upload> --> </el-upload> -->
</el-form-item> </el-form-item>
<el-form-item label="课程名称" prop="name"> <el-form-item label="课程名称" prop="name">
<el-input <el-input :disabled="nameDisabled" style="width: 200px" v-model="formModel.name"
:disabled="nameDisabled" @input="courseNameInput"></el-input>
style="width: 200px"
v-model="formModel.name"
@input="courseNameInput"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="课程类别" prop="category"> <el-form-item label="课程类别" prop="category">
<el-radio-group v-model="formModel.category"> <el-radio-group v-model="formModel.category">
@ -316,25 +311,18 @@ const upload = async (option: any) => {
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="课程编码" prop="code"> <el-form-item label="课程编码" prop="code">
<el-input <el-input style="width: 200px" v-model="formModel.code" :disabled="codeDisabled"></el-input>
style="width: 200px"
v-model="formModel.code"
:disabled="codeDisabled"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="课程学分" prop="credit"> <el-form-item label="课程学分" prop="credit">
<el-input style="width: 200px" v-model="formModel.credit"></el-input> <el-input style="width: 200px" v-model="formModel.credit"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="课程学时" prop="classhours"> <el-form-item label="课程学时" prop="classhours">
<el-input <el-input style="width: 200px" v-model="formModel.classhours"></el-input>
style="width: 200px"
v-model="formModel.classhours"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="考核类型" prop="assessmenttype"> <el-form-item label="考核类型" prop="assessmenttype">
<el-radio-group v-model="formModel.assessmenttype"> <el-radio-group v-model="formModel.assessmenttype">
<el-radio value="1">考试</el-radio> <el-radio value="1">考试</el-radio>
<el-radio value="2"></el-radio> <el-radio value="2"></el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="考核方式" prop="assessmentway"> <el-form-item label="考核方式" prop="assessmentway">
@ -344,14 +332,15 @@ const upload = async (option: any) => {
<el-radio value="3">其他</el-radio> <el-radio value="3">其他</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="教学方法" prop="teachermethod"> <!-- <el-form-item label="教学方法" prop="teachermethod">
<el-input type="textarea" v-model="formModel.teachermethod" /> <el-input type="textarea" v-model="formModel.teachermethod" />
</el-form-item> </el-form-item>
<el-form-item label="教学方式" prop="teacherway"> <el-form-item label="教学方式" prop="teacherway">
<el-input type="textarea" v-model="formModel.teacherway" /> <el-input type="textarea" v-model="formModel.teacherway" />
</el-form-item> </el-form-item> -->
<el-form-item label="课程简介" prop="description"> <el-form-item label="课程简介" prop="description">
<el-input type="textarea" v-model="formModel.description" /> <textarea name="" id="" v-model="formModel.description"></textarea>
<!-- <el-input class="brief_text" type="textarea" /> -->
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -367,6 +356,17 @@ const upload = async (option: any) => {
</el-drawer> </el-drawer>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
textarea {
width: 400px;
height: 180px;
resize: none;
border: 1px solid #dcdfe6;
color: #606266;
line-height: 1.3;
letter-spacing: 1px;
border-radius: 6px;
}
.avatar-uploader { .avatar-uploader {
:deep() { :deep() {
.avatar { .avatar {

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

Loading…
Cancel
Save