ww 4 months ago
commit a570de2a2f
  1. 4
      .env.development
  2. 8491
      pnpm-lock.yaml
  3. 18
      src/api/courseChaptersApi.ts
  4. 174
      src/api/sectionApi.ts
  5. 2
      src/store/modules/user.ts
  6. 213
      src/views/course/components/KnowledgeGraphUi/AddOrEdit copy.vue
  7. 155
      src/views/course/components/KnowledgeGraphUi/FoldAdd.vue
  8. 155
      src/views/course/components/KnowledgeGraphUi/FoldEdit.vue
  9. 196
      src/views/course/components/KnowledgeGraphUi/foldInfoUi.vue
  10. 2
      src/views/course/components/KnowledgeGraphUi/index.ts
  11. 306
      src/views/course/courseChapters.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:8008'
VITE_APP_BASE_API = 'http://39.106.16.162:8080'

File diff suppressed because it is too large Load Diff

@ -96,8 +96,20 @@ export const deleteCourse = (params: any) => {
// 获取详情
export const getCourseInfo = (params: any) => {
return request({
url: 'api/objective_contents/' + params.id,
method: "get",
// params
// <<<<<<< HEAD
url: '/objective_contents/' + params.id,
method: 'get',
// // params
// =======
// <<<<<<< HEAD
// url: '/api/objective_contents/' + params.id,
// method: 'get',
// params,
// =======
// url: '/objective_contents/' + params.id,
// method: "get",
// // params
// >>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
// >>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
})
}

@ -0,0 +1,174 @@
import request from '@/utils/request'
/**
* linkedlist
* @param {string} courseid courseid
* @returns
* 2fa0fd63262230639d2c45a3acd9045c
*/
export function getChapterApi(courseid: string) {
return request.get(`/chapter/aaa/${courseid}`);
}
// 响应接口
export interface DeleteRes {
code: number;
data: boolean;
message: string;
}
/**
*
* @param {string} id id
* @returns
*/
export function deleteSectionApi(id: string): Promise<DeleteRes> {
return request.delete(`/chapter/${id}`);
}
// 响应接口
export interface GetByIdCourseVoRes {
code: number;
data: {
classhours: number;
credit: number;
description: string;
id: string;
img: string;
name: string;
objectContent: string;
teacher: string;
totalAssignHours: number;
totalHours: number;
totalKnow: number;
totalNotAssignHours: number;
totalchapter: number;
};
message: string;
}
/**
* id查询课程Vo版
* @param {string} id id
* @returns
*/
export function getByIdCourseVoApi(id: string): Promise<GetByIdCourseVoRes> {
return request.get(`/api/coursesteacher/getById/${id}`);
}
// 参数接口
export interface AddChapterParams {
content?: string;
courseid?: string;
courseobjectivesid?: string;
createBy?: string;
createTime?: Record<string, unknown>;
id?: string;
name?: string;
num?: number;
numshow?: string;
onlinclasshours?: string;
pid?: string;
requirement?: string;
sysOrgCode?: string;
totalclasshours?: string;
updateBy?: string;
updateTime?: Record<string, unknown>;
zc?: string;
ziyuan?: string;
zywj?: string;
}
// 响应接口
export interface AddChapterRes {
code: number;
data: boolean;
message: string;
}
/**
*
* @param {object} params chapter
* @param {string} params.content
* @param {string} params.courseid
* @param {string} params.courseobjectivesid
* @param {string} params.createBy
* @param {object} params.createTime
* @param {string} params.id
* @param {string} params.name
* @param {number} params.num
* @param {string} params.numshow
* @param {string} params.onlinclasshours 线
* @param {string} params.pid
* @param {string} params.requirement
* @param {string} params.sysOrgCode
* @param {string} params.totalclasshours
* @param {string} params.updateBy
* @param {object} params.updateTime
* @param {string} params.zc
* @param {string} params.ziyuan
* @param {string} params.zywj
* @returns
*/
export function addChapterApi(params: AddChapterParams): Promise<AddChapterRes> {
return request.post(`/chapter/add`, params);
}
// 参数接口
export interface UpdateChapterParams {
content?: string;
courseid?: string;
courseobjectivesid?: string;
createBy?: string;
createTime?: Record<string, unknown>;
id?: string;
name?: string;
num?: number;
numshow?: string;
onlinclasshours?: string;
pid?: string;
requirement?: string;
sysOrgCode?: string;
totalclasshours?: string;
updateBy?: string;
updateTime?: Record<string, unknown>;
zc?: string;
ziyuan?: string;
zywj?: string;
}
// 响应接口
export interface UpdateChapterRes {
code: number;
data: boolean;
message: string;
}
/**
*
* @param {object} params chapter
* @param {string} params.content
* @param {string} params.courseid
* @param {string} params.courseobjectivesid
* @param {string} params.createBy
* @param {object} params.createTime
* @param {string} params.id
* @param {string} params.name
* @param {number} params.num
* @param {string} params.numshow
* @param {string} params.onlinclasshours 线
* @param {string} params.pid
* @param {string} params.requirement
* @param {string} params.sysOrgCode
* @param {string} params.totalclasshours
* @param {string} params.updateBy
* @param {object} params.updateTime
* @param {string} params.zc
* @param {string} params.ziyuan
* @param {string} params.zywj
* @returns
*/
export function updateChapterApi(params: UpdateChapterParams): Promise<UpdateChapterRes> {
return request.put(`/chapter`, params);
}

@ -114,6 +114,8 @@ const useUserStore = defineStore(
this.userName = result.data.username
// this.avatar = result.data.checkUser.avatar
// @ts-expect-error
this.routes = result.data.permissions
return {
result,

@ -0,0 +1,213 @@
<template>
<div class="add-or-edit">
<el-drawer v-model="isDrawer" title="新增章节" direction="rtl" size="50%">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto"
class="demo-ruleForm" :size="formSize" status-icon>
<el-form-item label="章节" prop="pid">
<el-cascader v-model="activePidArr" :options="options" :props="CascaderProps"
:show-all-levels="false" clearable />
</el-form-item>
<el-form-item label="章节名" prop="name">
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" />
</el-form-item>
<el-form-item label="总学时" prop="totalclasshours">
<el-input v-model="ruleForm.totalclasshours" style="width: 240px" placeholder="请输入总学时" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)">
Create
</el-button>
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
function comNum(n: number | undefined) {
if (n === undefined) return 1
return n + 1
}
import { ref, reactive, watch, computed, nextTick } from 'vue'
const props = defineProps(['isD', 'data', 'loading'])
const emits = defineEmits(['update:isD', 'submit'])
const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal)
watch(() => isDrawer.value, newVal => emits('update:isD', newVal))
const type = false
const options = computed(() => {
if (type) {
const arr = props.data.map((item: any, i: number) => {
const obj = { ...item }
if (item.chapterSection) obj.chapterSection = item.chapterSection.map((chap: any) => ({ ...chap, disabled: true }))
else obj.chapterSection = []
obj.chapterSection.push({ name: `${i + 1}章第${comNum(item.chapterSection?.length)}`, pid: item.id })
return obj
})
arr.push({ name: `${arr.length + 1}`, pid: '' })
return arr
}
return props.data
})
const CascaderProps = {
checkStrictly: !type,
label: 'name',
value: type ? 'pid' : 'id',
children: 'chapterSection'
}
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
interface RuleForm {
content: string
courseid: string
courseobjectivesid: string
createBy: string
createTime: string
id: string
name: string
num: number
numshow: string
onlinclasshours: string
pid: string | undefined
requirement: string
sysOrgCode: string
totalclasshours: string
updateBy: string
updateTime: string
zc: string
ziyuan: string
zywj: string
}
const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>()
let o
if (type) {
o = {
"content": "",
"courseid": "",
"courseobjectivesid": "",
"createBy": "",
"createTime": "",
"id": "",
"name": "",
"num": 0,
"numshow": "",
"onlinclasshours": "",
"pid": undefined,
"requirement": "",
"sysOrgCode": "",
"totalclasshours": "",
"updateBy": "",
"updateTime": "",
"zc": "",
"ziyuan": "",
"zywj": ""
}
}else{
o = {
"content": "",
"courseid": "",
"courseobjectivesid": "",
"createBy": "",
"createTime": "",
"id": undefined,
"name": "111",
"num": 0,
"numshow": "",
"onlinclasshours": "",
"pid": "",
"requirement": "",
"sysOrgCode": "",
"totalclasshours": "",
"updateBy": "",
"updateTime": "",
"zc": "",
"ziyuan": "",
"zywj": ""
}
}
let pxObj
if (type) pxObj = o
else {
pxObj = new Proxy(o, {
get(target, key) {
if (key === 'pid') return target.id
// @ts-ignore
return target[key];
},
set: function (obj, prop, value) {
if (prop === 'pid') {
obj.id = value
return true
}
// @ts-ignore
obj[prop] = value
return true;
}
})
}
// @ts-ignore
const ruleForm = reactive<RuleForm>(pxObj)
// @ts-ignore
const validateChapterOrSection = (rule, value, callback) => {
nextTick(() => {
const value = ruleForm.pid
if (!value && value !== '') {
if (type) callback(new Error('请选择新增的章或节'))
else callback(new Error('请选择编辑的章或节'))
}
else callback()
})
};
//
const rules = reactive<FormRules<RuleForm>>({
pid: [
{ required: true, validator: validateChapterOrSection, trigger: 'change' },
]
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log(options.value, '1')
console.log(ruleForm);
// emits('submit', ruleForm)
} else {
console.log('error submit!', fields)
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
activePidArr.value = undefined
}
const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => {
if (newVal === undefined) placeholder.value = '请输入章节名'
else if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名'
})
const activePidArr = ref<string[] | undefined>([])
watch(() => activePidArr.value, newVal => {// pid
if (newVal === undefined) {
ruleForm.pid = undefined
return
}
ruleForm.pid = newVal.slice(-1)[0]
})
</script>
<style lang="scss"></style>

@ -0,0 +1,155 @@
<template>
<div class="add-or-edit">
<el-drawer v-model="isDrawer" title="新增章节" direction="rtl" size="50%">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto"
class="demo-ruleForm" :size="formSize" status-icon>
<el-form-item label="章节" prop="pid">
<el-cascader v-model="activePidArr" :options="options1" :props="CascaderProps"
:show-all-levels="false" clearable />
</el-form-item>
<el-form-item label="章节名" prop="name">
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" />
</el-form-item>
<el-form-item label="总学时" prop="totalclasshours">
<el-input v-model="ruleForm.totalclasshours" style="width: 240px" placeholder="请输入总学时" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)">
提交
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
function comNum(n: number | undefined) {
if (n === undefined) return 1
return n + 1
}
import { ref, reactive, watch, computed, nextTick } from 'vue'
const props = defineProps(['isD', 'data'])
const emits = defineEmits(['update:isD','submit'])
const loading = ref(false)
const updLoading = (boo:boolean) => loading.value = boo
const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal)
watch(()=>isDrawer.value,newVal=>emits('update:isD',newVal))
const options1 = computed(() => {
const arr = props.data.map((item: any, i: number) => {
const obj = { ...item }
if (item.chapterSection) obj.chapterSection = item.chapterSection.map((chap: any) => ({ ...chap, disabled: true }))
else obj.chapterSection = []
obj.chapterSection.push({ name: `${i + 1}章第${comNum(item.chapterSection?.length)}`, pid: item.id })
return obj
})
arr.push({ name: `${arr.length + 1}`, pid: '' })
return arr
})
const CascaderProps = {
label: 'name',
value: 'pid',
children: 'chapterSection'
}
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
interface RuleForm {
content: string
courseid: string
courseobjectivesid: string
createBy: string
createTime: string
id: string
name: string
num: number
numshow: string
onlinclasshours: string
pid: string | undefined
requirement: string
sysOrgCode: string
totalclasshours: string
updateBy: string
updateTime: string
zc: string
ziyuan: string
zywj: string
}
const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
"content": "",
"courseid": "2fa0fd63262230639d2c45a3acd9045c",
"courseobjectivesid": "",
"createBy": "",
"createTime": "",
"id": "",
"name": "",
"num": 0,
"numshow": "",
"onlinclasshours": "",
"pid": undefined,
"requirement": "",
"sysOrgCode": "",
"totalclasshours": "",
"updateBy": "",
"updateTime": "",
"zc": "",
"ziyuan": "",
"zywj": ""
})
// @ts-ignore
const validateChapterOrSection = (rule, value, callback) => {
nextTick(()=>{
const value =ruleForm.pid
if (!value && value !== '') callback(new Error('请选择新增的章或节'))
else callback()
})
};
//
const rules = reactive<FormRules<RuleForm>>({
pid: [
{ required: true, validator: validateChapterOrSection, trigger: 'change' },
]
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
emits('submit',ruleForm,updLoading)
} else {
console.log('error submit!', fields)
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
activePidArr.value = undefined
}
const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => {
if (newVal === undefined) placeholder.value = '请输入章节名'
else if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名'
})
const activePidArr = ref<string[] | undefined>([])
watch(() => activePidArr.value, newVal => {// pid
if (newVal === undefined) {
ruleForm.pid = undefined
return
}
ruleForm.pid = newVal.slice(-1)[0]
})
</script>
<style lang="scss"></style>

@ -0,0 +1,155 @@
<template>
<div class="add-or-edit">
<el-drawer v-model="isDrawer" title="编辑章节" direction="rtl" size="50%">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto"
class="demo-ruleForm" :size="formSize" status-icon>
<el-form-item label="章节" prop="id">
<el-cascader v-model="activeIdArr" :options="options1" :props="CascaderProps"
:show-all-levels="false" clearable />
</el-form-item>
<el-form-item label="章节名" prop="name">
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" />
</el-form-item>
<el-form-item label="总学时" prop="totalclasshours">
<el-input v-model="ruleForm.totalclasshours" style="width: 240px" placeholder="请输入总学时" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)">
提交
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, watch, computed } from 'vue'
const props = defineProps(['isD', 'data', 'editData'])
const emits = defineEmits(['update:isD', 'submit'])
const loading = ref(false)
const updLoading = (boo:boolean) => loading.value = boo
const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal)
watch(() => isDrawer.value, newVal => emits('update:isD', newVal))
const options1 = computed(() => props.data)
const CascaderProps = {
checkStrictly: true,
label: 'name',
value: 'id',
children: 'chapterSection'
}
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
import { isArray } from 'element-plus/es/utils/types.mjs';
interface RuleForm {
content: string
courseid: string
courseobjectivesid: string
createBy: string
createTime: string
id: string | undefined
name: string
num: number
numshow: string
onlinclasshours: string
pid: string
requirement: string
sysOrgCode: string
totalclasshours: string
updateBy: string
updateTime: string
zc: string
ziyuan: string
zywj: string
}
const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({ ...props.editData })
//
const rules = reactive<FormRules<RuleForm>>({
id: [
{ required: true, message: '请选择要更新的章节', trigger: 'change' },
]
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
emits('submit', ruleForm,updLoading)
} else {
console.log('error submit!', fields)
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
activeIdArr.value = getCheckedChapter(options1.value)
}
watch(() => ruleForm.id, newVal => {
const obj =getCheckedChapterObj(options1.value,newVal)
// const arr = getCheckedChapter(options1.value)
// let obj
// if (arr.length === 1) obj = options1.value.find((item: any) => item.id === arr[0])
// else if (arr.length === 2) obj = options1.value.find((item: any) => item.id === arr[0]).value.find((item: any) => item.id === arr[1])
if (obj) Object.assign(ruleForm, obj)
})
const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => {
if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名'
},{immediate:true})
// id
function getCheckedChapter(array: any) {
let i = 0, arr: any[] = [], f: any
(function fn(array: any) {
if (!isArray(array)) return
const ch = array.find((item: any) => item.id === ruleForm.id)
if (ch === undefined && i < array.length) {
f = array[i].id
fn(array[i++].chapterSection)
}
if (ch === undefined) return
if (f) arr.push(f)
arr.push(ch.id)
}(array))
return arr
}
//
function getCheckedChapterObj(array: any,id:any) {
let i = 0, arr: any[] = [];
(function fn(array: any) {
if (!isArray(array)) return
const ch = array.find((item: any) => item.id === id)
if (ch === undefined && i < array.length) {
fn(array[i++].chapterSection)
}
if (ch === undefined) return
arr.push(ch)
}(array))
return arr[0]
}
const activeIdArr = ref<string[] | undefined>(getCheckedChapter(options1.value))
watch(() => activeIdArr.value, newVal => {// id
if (newVal === undefined) {
ruleForm.id = undefined
return
}
ruleForm.id = newVal.slice(-1)[0]
})
</script>
<style lang="scss"></style>

@ -1,42 +1,47 @@
<template>
<div class="fold-info-ui">
<div class="demo-collapse">
<el-collapse
class="collapse"
v-model="activeNames"
@change="handleChange"
>
<el-collapse-item v-for="item in 3" :key="item" :name="item">
<el-collapse class="collapse">
<button class="my-button" style="position: absolute;left: 0;top: 0;" @click.stop="emits('add')">新增</button>
<el-collapse-item v-for="item in foldInfoData" :key="item.id">
<template #title>
<div class="title">
<div class="icon">
<img src="@/assets/images/minus-circle-filled.png" alt="" />
<img src="@/assets/images/minus-circle-filled.png" alt="">
</div>
<div class="index">01 /</div>
<div class="text">基本概念</div>
<div class="index" v-if="String(item.numshow).length == 1"> 0{{ item.numshow }} /</div>
<div class="index" v-else>{{ item.numshow }} /</div>
<div class="text">{{ item.name }}</div>
<div class="title-tag-box">
<div class="my-tag" type="warning">32学时</div>
<div class="my-tag" type="warning">{{ item.totalclasshours }}学时</div>
<div class="my-tag">本章资源</div>
</div>
<button class="my-button" @click.stop="emits('edit', item)" style="margin-right: 10px;">编辑</button>
<el-button type="danger" class="is-el-button" :loading="loading&&item.id===activeData.id" @click.stop="hanDel(item)" style="margin-right: 10px;">删除</el-button>
</div>
</template>
<template #default>
<div class="titile-box-knowledge chapter-knowledge">
<div class="my-tag">知识点1</div>
<div class="my-tag">知识点1</div>
</div>
<div class="main-box">
<div class="left"></div>
<div class="right">
<div class="structure-item">
<div
class="structure-item-titile-box"
v-for="item in 3"
:key="item"
>
<div class="structure-item-titile-box" v-for="obj, ind in item.chapterSection" :key="item.id">
<div class="titile-box-titile">
<div class="sequence">5</div>
<div class="sequence">{{ ind + 1 }}</div>
<div class="tit-box">
<div class="tit-box-left">1.1 基本概念1</div>
<div class="tit-box-left">{{ obj.numshow }} {{ obj.name }}</div>
<div class="tit-box-right my-tag">资源</div>
<div class="title-tag-box">
<div class="my-tag" type="warning">{{ obj.totalclasshours }}学时</div>
</div>
<div class="tit-box-edit">
<button class="my-button">编辑</button>
<button class="my-button" @click.stop="emits('edit', obj)" style="margin-right: 10px;">编辑</button>
<el-button type="danger" class="is-el-button" :loading="loading&&obj.id==activeData.id" my-type="error" @click.stop="hanDel(obj)">删除</el-button>
</div>
</div>
</div>
@ -49,6 +54,7 @@
</div>
</div>
</template>
</el-collapse-item>
</el-collapse>
</div>
@ -57,14 +63,16 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps(['foldInfoData'])
console.log(props.foldInfoData, '可折叠基本概念接口数据')
const activeNames = ref([1])
const handleChange = (val: string[]) => {
console.log(val)
defineProps(['foldInfoData','loading'])
const emits = defineEmits(['add', 'del', 'edit'])
const activeData = ref({id:undefined})
function hanDel(o:any){
activeData.value = o
emits('del', o.id)
}
</script>
<style lang="scss" scoped>
::v-deep .collapse {
border-top: none;
@ -80,12 +88,15 @@ const handleChange = (val: string[]) => {
padding-top: 27px;
padding-left: 61px;
background: #fff;
position: relative;
.demo-collapse {
$title-icon-width: 15px;
$title--icon-m-r: 34px;
$title-index-width: 60px;
.title {
display: flex;
height: 22px;
@ -101,6 +112,7 @@ const handleChange = (val: string[]) => {
& img {
width: 100%;
height: 100%;
}
}
@ -126,17 +138,17 @@ const handleChange = (val: string[]) => {
display: flex;
column-gap: 16px;
}
}
.main-box {
width: 100%;
display: flex;
$line: 1px dashed #d9d9d9;
$line: 1px dashed #D9D9D9;
.left {
width: calc(
$title-icon-width + $title--icon-m-r + $title-index-width / 2
);
width: calc($title-icon-width + $title--icon-m-r + $title-index-width / 2);
border-right: $line;
}
@ -147,7 +159,7 @@ const handleChange = (val: string[]) => {
width: 100%;
.structure-item-titile-box {
& > * {
&>* {
padding-left: 42px;
}
@ -178,7 +190,7 @@ const handleChange = (val: string[]) => {
top: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
background: #ffb21e;
background: #FFB21E;
text-align: center;
line-height: $height;
font-weight: 400;
@ -206,83 +218,95 @@ const handleChange = (val: string[]) => {
}
}
.titile-box-knowledge {
display: flex;
margin-left: 33px;
& > * {
margin-left: 38px;
border: 1px solid #0052d9;
font-weight: bold;
font-size: 12px;
color: #0052d9;
&:first-child {
margin-left: 0;
}
}
}
}
}
}
}
}
.titile-box-knowledge {
display: flex;
margin-left: 33px;
gap: 38px;
flex-wrap: wrap;
&>* {
border: 1px solid #0052D9;
font-weight: bold;
font-size: 12px;
color: #0052D9;
}
}
.chapter-knowledge {
margin-bottom: 10px;
margin-left: calc(79px - 33px / 2);
}
// ===================
.my-tag {
padding: 2px 8px;
font-weight: 400;
font-size: 12px;
color: #0052d9;
color: #0052D9;
line-height: 20px;
background: #f2f3ff;
background: #F2F3FF;
cursor: pointer;
border-radius: 3px;
}
[type='warning'].my-tag {
color: #e37318;
background: #fff1e9;
* {
white-space: nowrap;
}
.my-button {
all: initial;
$color-start: #52a1ff;
$color-end: #4255ff;
padding: 8px 24px;
background: linear-gradient(128deg, $color-start 0%, $color-end 100%);
box-shadow: 0px 4px 7px 0px rgba(0, 82, 255, 0.27);
border-radius: 20px;
font-weight: bold;
font-size: 16px;
color: rgba(255, 255, 255, 0.9);
line-height: 24px;
text-align: center;
cursor: pointer;
[type=warning].my-tag {
color: #E37318;
background: #FFF1E9;
}
&:hover {
background: linear-gradient(
128deg,
lighten($color-start, 5%) 0%,
lighten($color-end, 5%) 100%
);
}
}
&:active {
background: linear-gradient(
128deg,
darken($color-start, 10%) 0%,
darken($color-end, 10%) 100%
);
}
.my-button {
all: initial;
$color-start: #52A1FF;
$color-end: #4255FF;
padding: 8px 24px;
background: linear-gradient(128deg, $color-start 0%, $color-end 100%);
box-shadow: 0px 4px 7px 0px rgba(0, 82, 255, 0.27);
border-radius: 20px;
font-weight: bold;
font-size: 16px;
color: rgba(255, 255, 255, 0.9);
line-height: 24px;
text-align: center;
cursor: pointer;
&:hover {
background: linear-gradient(128deg, lighten($color-start, 5%) 0%, lighten($color-end, 5%) 100%);
}
&:disabled {
background: linear-gradient(
128deg,
lighten($color-start, 20%) 0%,
lighten($color-end, 20%) 100%
);
}
&:active {
background: linear-gradient(128deg, darken($color-start, 10%) 0%, darken($color-end, 10%) 100%);
}
&:disabled {
background: linear-gradient(128deg, lighten($color-start, 20%) 0%, lighten($color-end, 20%) 100%);
}
}
</style>
.is-el-button {
width: 80px;
height: 40px;
box-shadow: 0px 4px 7px 0px rgba(0, 82, 255, 0.27);
border-radius: 20px;
font-weight: bold;
font-size: 16px !important;
color: rgba(255, 255, 255, 0.9);
line-height: 24px;
text-align: center;
cursor: pointer;
}
</style>

@ -3,3 +3,5 @@ export { default as objectiveUi } from './objectiveUi.vue'
export { default as atlasUi } from '../atlasUi.vue'
export { default as lookResourceUi } from './lookResourceUi.vue'
export { default as foldInfoUi } from './foldInfoUi.vue'
export { default as FoldAdd } from './FoldAdd.vue'
export { default as FoldEdit } from './FoldEdit.vue'

@ -1,51 +1,51 @@
<template>
<div class="course-chapters">
<div class="flex-layout">
<div class="flex-left">
<div class="left" ref="atlasCon">
<!-- 知识图谱 -->
<atlas-ui @hadRouter="handle" />
<div class="course-chapters">
<div class="flex-layout">
<div class="flex-left">
<div class="left" ref="atlasCon">
<!-- 知识图谱 -->
<atlas-ui @hadRouter="handle" />
</div>
<div class="right-top radius-10 vertical-line">
<!-- 计算机导论 -->
<theory-ui :learnInfo="learnInfo" />
</div>
<div class="right-bottom radius-10 vertical-line">
<!-- 课程目标 -->
<objective-ui :orogramObjective="orogramObjective" />
</div>
<div class="bottom">
<!-- 可折叠基本概念 -->
<fold-info-ui :foldInfoData="foldInfoData" @add="showHide = true" @edit="hanEdit" @del="flodDel"
:loading="foldDelLoading" />
<FoldAdd v-model:is-d="showHide" v-if="showHide" :data="foldInfoData" @submit="foldAddSubmit" />
<FoldEdit v-model:is-d="showHide1" v-if="showHide1" :editData="activeEditData" :data="foldInfoData"
@submit="foldEditSubmit" />
</div>
</div>
<div class="flex_right">
<div class="top-container">
<img src="" alt="">
</div>
<div class="bottom-container radius-10">
<!-- 查看资源 -->
<look-resource-ui :lookResource="lookResource" />
</div>
</div>
</div>
<div class="right-top radius-10 vertical-line">
<!-- 计算机导论 -->
<theory-ui :learnInfo="learnInfo" />
</div>
<div class="right-bottom radius-10 vertical-line">
<!-- 课程目标 -->
<objective-ui :orogramObjective="orogramObjective" />
</div>
<div class="bottom">
<!-- 可折叠基本概念 -->
<fold-info-ui :foldInfoData="foldInfoData" />
</div>
</div>
<div class="flex_right">
<div class="top-container">
<img src="" alt="" />
</div>
<div class="bottom-container radius-10">
<!-- 查看资源 -->
<look-resource-ui :lookResource="lookResource" />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {
getLearnInfoApi,
getOrogramObjectiveApi,
} from '@/api/courseChaptersApi'
import {
theoryUi,
objectiveUi,
atlasUi,
lookResourceUi,
foldInfoUi,
} from './components/KnowledgeGraphUi/index'
import { reactive } from 'vue'
<script lang='ts' setup>
import { getLearnInfoApi, getOrogramObjectiveApi } from '@/api/courseChaptersApi'
import { getChapterApi, deleteSectionApi, addChapterApi, updateChapterApi } from '@/api/sectionApi'
import { theoryUi, objectiveUi, atlasUi, lookResourceUi, foldInfoUi, FoldAdd, FoldEdit } from './components/KnowledgeGraphUi/index'
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus';
const $router = useRouter()
// atlas-ui
@ -53,104 +53,170 @@ const handle = () => $router.push('/knowledgeAtlas')
// theory-ui
const learnInfo: object[] = reactive([])
getLearnInfoApi().then((res) => learnInfo.push(...(res as object[])))
getLearnInfoApi().then(res => learnInfo.push(...res as object[]))
// getByIdCourseVoApi('2fa0fd63262230639d2c45a3acd9045c')
// objective-ui
const orogramObjective: any = reactive({})
getOrogramObjectiveApi().then((res) => Object.assign(orogramObjective, res))
getOrogramObjectiveApi().then(res => Object.assign(orogramObjective, res))
// look-resource-ui
const lookResource: any = reactive({})
// fold-info-ui
const foldInfoData: any = reactive({})
const foldInfoData: any = reactive([])
function getFold() {
getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then(res => {
foldInfoData.length = 0
foldInfoData.push(...res.data)
})
}
getFold()
//
const showHide = ref(false)
function foldAddSubmit(data: any, updLoading: Function) {
updLoading(true)
addChapterApi(data).then(() => {
ElMessage({
message: `添加${data.pid === '' ? '章' : '节'}成功`,
type: 'success'
})
showHide.value = false
getFold()
}).catch(() => {
ElMessage({
message: `添加${data.pid === '' ? '章' : '节'}失败`,
type: 'error'
})
}).finally(() => updLoading(false))
}
//
const foldDelLoading = ref(false)
function flodDel(id: string) {
foldDelLoading.value = true
deleteSectionApi(id).then(() => {
ElMessage({
message: `删除成功`,
type: 'success'
})
getFold()
}).catch(() => {
ElMessage({
message: `删除失败`,
type: 'error'
})
}).finally(() => foldDelLoading.value = false)
}
//
const showHide1 = ref(false)
const activeEditData = ref()
function hanEdit(data: any) {
activeEditData.value = data
showHide1.value = true
}
function foldEditSubmit(data: any, updLoading: Function) {
updLoading(true)
updateChapterApi(data).then(() => {
ElMessage({
message: `更新${data.pid === '' ? '章' : '节'}成功`,
type: 'success'
})
showHide1.value = false
getFold()
}).catch(() => {
ElMessage({
message: `更新${data.pid === '' ? '章' : '节'}失败`,
type: 'error'
})
}).finally(() => updLoading(false))
}
</script>
<style lang="scss" scoped>
<style lang='scss' scoped>
.course-chapters {
width: 100%;
height: 100%;
position: relative;
background: #f2f7fb;
width: 100%;
height: 100%;
position: relative;
background: #F2F7FB;
&,
* {
box-sizing: border-box;
}
&,
* {
box-sizing: border-box;
}
$right-box-width: 555px;
.radius-10 {
border-radius: 10px;
overflow: hidden;
}
.radius-10 {
border-radius: 10px;
overflow: hidden;
}
.vertical-line {
position: relative;
.vertical-line {
position: relative;
&::before {
content: '';
display: block;
position: absolute;
height: 100%;
width: 12px;
background-color: #2147fb;
}
}
.flex-layout {
display: flex;
justify-content: space-between;
align-items: flex-start;
.flex-left {
display: grid;
grid-template-columns: repeat(2, auto);
width: 1243px;
.left {
grid-row: 1/3;
width: 664px;
height: 424px;
}
.right-top {
justify-self: end;
width: $right-box-width;
height: 243px;
}
.right-bottom {
justify-self: end;
align-self: end;
width: $right-box-width;
height: 168px;
}
.bottom {
margin-top: 15px;
grid-column: 1/3;
width: 100%;
min-height: 521px;
}
&::before {
content: '';
display: block;
position: absolute;
height: 100%;
width: 12px;
background-color: #2147FB;
}
}
.flex_right {
width: 355px;
.top-container {
height: 231px;
margin-bottom: 23px;
img {
width: 100%;
height: 100%;
.flex-layout {
display: flex;
justify-content: space-between;
align-items: flex-start;
.flex-left {
display: grid;
grid-template-columns: 664px 555px;
justify-content: space-between;
width: 1243px;
.left {
grid-row: 1/3;
height: 424px;
}
.right-top {
width: 100%;
height: 243px;
}
.right-bottom {
align-self: end;
width: 100%;
height: 168px;
}
.bottom {
margin-top: 15px;
grid-column: 1/3;
width: 100%;
min-width: 100%;
min-height: 521px;
}
}
}
.bottom-container {
min-height: 945px;
}
.flex_right {
width: 355px;
.top-container {
height: 231px;
margin-bottom: 23px;
img {
width: 100%;
height: 100%;
}
}
.bottom-container {
min-height: 945px;
}
}
}
}
}
</style>

Loading…
Cancel
Save