课程章节:新增、编辑、删除

develoop
significative 5 months ago
parent 00d1c46e62
commit b618c5e0b7
  1. 5
      .env.development
  2. 8198
      pnpm-lock.yaml
  3. 26
      src/api/courseChaptersApi.ts
  4. 174
      src/api/sectionApi.ts
  5. 4
      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. 146
      src/views/course/components/KnowledgeGraphUi/foldInfoUi.vue
  10. 2
      src/views/course/components/KnowledgeGraphUi/index.ts
  11. 122
      src/views/course/courseChapters.vue

@ -1,8 +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:8008'
VITE_APP_BASE_API = 'http://127.0.0.1:8008'
=======
VITE_APP_BASE_API = 'http://39.106.16.162:8080' VITE_APP_BASE_API = 'http://39.106.16.162:8080'
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a

File diff suppressed because it is too large Load Diff

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

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

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

@ -16,12 +16,17 @@
</div> </div>
<div class="bottom"> <div class="bottom">
<!-- 可折叠基本概念 --> <!-- 可折叠基本概念 -->
<fold-info-ui :foldInfoData="foldInfoData" /> <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> </div>
<div class="flex_right"> <div class="flex_right">
<div class="top-container"> <div class="top-container">
<img src="" alt="" /> <img src="" alt="">
</div> </div>
<div class="bottom-container radius-10"> <div class="bottom-container radius-10">
<!-- 查看资源 --> <!-- 查看资源 -->
@ -30,22 +35,17 @@
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang='ts' setup>
import { import { getLearnInfoApi, getOrogramObjectiveApi } from '@/api/courseChaptersApi'
getLearnInfoApi, import { getChapterApi, deleteSectionApi, addChapterApi, updateChapterApi } from '@/api/sectionApi'
getOrogramObjectiveApi, import { theoryUi, objectiveUi, atlasUi, lookResourceUi, foldInfoUi, FoldAdd, FoldEdit } from './components/KnowledgeGraphUi/index'
} from '@/api/courseChaptersApi' import { ref, reactive } from 'vue'
import {
theoryUi,
objectiveUi,
atlasUi,
lookResourceUi,
foldInfoUi,
} from './components/KnowledgeGraphUi/index'
import { reactive } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus';
const $router = useRouter() const $router = useRouter()
// atlas-ui // atlas-ui
@ -53,32 +53,97 @@ const handle = () => $router.push('/knowledgeAtlas')
// theory-ui // theory-ui
const learnInfo: object[] = reactive([]) const learnInfo: object[] = reactive([])
getLearnInfoApi().then((res) => learnInfo.push(...(res as object[]))) getLearnInfoApi().then(res => learnInfo.push(...res as object[]))
// getByIdCourseVoApi('2fa0fd63262230639d2c45a3acd9045c')
// objective-ui // objective-ui
const orogramObjective: any = reactive({}) const orogramObjective: any = reactive({})
getOrogramObjectiveApi().then((res) => Object.assign(orogramObjective, res)) getOrogramObjectiveApi().then(res => Object.assign(orogramObjective, res))
// look-resource-ui // look-resource-ui
const lookResource: any = reactive({}) const lookResource: any = reactive({})
// fold-info-ui // 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> </script>
<style lang="scss" scoped> <style lang='scss' scoped>
.course-chapters { .course-chapters {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative; position: relative;
background: #f2f7fb; background: #F2F7FB;
&, &,
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
$right-box-width: 555px;
.radius-10 { .radius-10 {
border-radius: 10px; border-radius: 10px;
@ -94,7 +159,7 @@ const foldInfoData: any = reactive({})
position: absolute; position: absolute;
height: 100%; height: 100%;
width: 12px; width: 12px;
background-color: #2147fb; background-color: #2147FB;
} }
} }
@ -105,25 +170,23 @@ const foldInfoData: any = reactive({})
.flex-left { .flex-left {
display: grid; display: grid;
grid-template-columns: repeat(2, auto); grid-template-columns: 664px 555px;
justify-content: space-between;
width: 1243px; width: 1243px;
.left { .left {
grid-row: 1/3; grid-row: 1/3;
width: 664px;
height: 424px; height: 424px;
} }
.right-top { .right-top {
justify-self: end; width: 100%;
width: $right-box-width;
height: 243px; height: 243px;
} }
.right-bottom { .right-bottom {
justify-self: end;
align-self: end; align-self: end;
width: $right-box-width; width: 100%;
height: 168px; height: 168px;
} }
@ -131,6 +194,7 @@ const foldInfoData: any = reactive({})
margin-top: 15px; margin-top: 15px;
grid-column: 1/3; grid-column: 1/3;
width: 100%; width: 100%;
min-width: 100%;
min-height: 521px; min-height: 521px;
} }
} }
@ -141,6 +205,7 @@ const foldInfoData: any = reactive({})
.top-container { .top-container {
height: 231px; height: 231px;
margin-bottom: 23px; margin-bottom: 23px;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -152,5 +217,6 @@ const foldInfoData: any = reactive({})
} }
} }
} }
} }
</style> </style>

Loading…
Cancel
Save