提交 c695eeb9 authored 作者: matian's avatar matian

新增章节

上级 a5393832
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取视频列表 // 获取视频列表
export function getVideoList(params: { tab: string; status?: string; authorized?: string; classification?: string; page?: number; page_size?: number }) { export function getVideoList(params: {
tab: string
status?: string
authorized?: string
classification?: string
page?: number
page_size?: number
}) {
return httpRequest.get('/api/resource/v1/resource/video/list', { params }) return httpRequest.get('/api/resource/v1/resource/video/list', { params })
} }
// 创建视频 // 创建视频
export function createVideo(data: { name: string; source: string; classification: string; knowledge_points: string; cover: string; source_id: string }) { export function createVideo(data: {
name: string
source: string
classification: string
knowledge_points: string
cover: string
source_id: string
}) {
return httpRequest.post('/api/resource/v1/resource/video/create', data) return httpRequest.post('/api/resource/v1/resource/video/create', data)
} }
...@@ -21,7 +35,13 @@ export function getVideoDetails(params: { id: string }) { ...@@ -21,7 +35,13 @@ export function getVideoDetails(params: { id: string }) {
} }
// 更新视频 // 更新视频
export function updateVideo(data: { id: string; name: string; classification: string; knowledge_points?: string; cover?: string }) { export function updateVideo(data: {
id: string
name: string
classification: string
knowledge_points?: string
cover?: string
}) {
return httpRequest.post('/api/resource/v1/resource/video/update', data) return httpRequest.post('/api/resource/v1/resource/video/update', data)
} }
...@@ -56,11 +76,38 @@ export function createPpt(data: { id: string; ppts: string }) { ...@@ -56,11 +76,38 @@ export function createPpt(data: { id: string; ppts: string }) {
} }
// 编辑课件 // 编辑课件
export function updatePpt(data: { id: string; ppt_id: string, name: string, point: string, url: string }) { export function updatePpt(data: { id: string; ppt_id: string; name: string; point: string; url: string }) {
return httpRequest.post('/api/resource/v1/resource/video/update-ppt', data) return httpRequest.post('/api/resource/v1/resource/video/update-ppt', data)
} }
// 编辑课件 // 获取章节
export function deletePpt(data: { id: string; ppt_id: string }) { export function deletePpt(data: { course_id: string; type: string }) {
return httpRequest.post('/api/resource/v1/resource/video/delete-ppt', data) return httpRequest.post('/api/resource/v1/resource/video/delete-ppt', data)
} }
// 获取章节
export function getCharacter(params: { course_id: string; type: string }) {
return httpRequest.get('/api/resource/v1/course/course/chapters', { params })
}
// 新建章节
export function createCharacter(data: {
course_id: string
resource_type: string
name: string
parent_id: string
resource_id: string
}) {
return httpRequest.post('/api/resource/v1/course/course/create-chapter', data)
}
// 章节修改
export function editCharacter(data: { id: string; course_id: string; name: string; resource_id: string }) {
return httpRequest.post('/api/resource/v1/course/course/update-chapter', data)
}
// 章节删除
export function delCharacter(data: { id: string; course_id: string }) {
return httpRequest.post('/api/resource/v1/course/course/delete-chapter', data)
}
// 直播列表
export function getLiveList(params: { name: string; page?: number; ['page_size']?: number }) {
return httpRequest.get('/api/resource/v1/course/course/search-live', { params })
}
<script lang="ts" setup>
import { createCharacter, editCharacter } from '../api'
import type { FormInstance, FormRules } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const emit = defineEmits<Emits>()
const ruleFormRef = ref<FormInstance>()
// 封面状态
const form = reactive({
name: '',
parent_id: '',
resource_id: ''
})
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入章名称', trigger: 'blur' }]
})
const props = defineProps({
isShowDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
isEdit: {
type: Boolean,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowDialog', isShowDialog: boolean): void
(e: 'create'): void
}
// 取消
const handleCancel = () => {
emit('update:isShowDialog', false)
}
// 确定
const handleConfirm = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '章节')[0]?.value
if (props.isEdit) {
const params = Object.assign({ id: props.chapterID, course_id: props.course_id }, form)
editCharacter(params).then(() => {
emit('update:isShowDialog', false)
emit('create')
})
} else {
const params = Object.assign({ course_id: props.course_id, resource_type: type }, form)
createCharacter(params).then(() => {
emit('update:isShowDialog', false)
emit('create')
})
}
}
onMounted(() => {
if (props.isEdit) {
form.name = props.chapterName
}
})
</script>
<template>
<el-dialog
:model-value="isShowDialog"
draggable
:before-close="handleCancel"
width="25%"
:title="isEdit ? '编辑:章' : '新增:章'"
>
<el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="80px">
<el-form-item label="章-名称:" prop="type">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { createCharacter, getLiveList } from '../api'
import type { FormInstance, FormRules } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const emit = defineEmits<Emits>()
const ruleFormRef = ref<FormInstance>()
interface IliveList {
id: string
meeting_id: string
meeting_code: string
subject: string
start_time: string
end_time: string
meeting_type: number
status: string
}
let liveList = ref<IliveList[]>([])
// 封面状态
const form = reactive({
name: '',
resource_id: ''
})
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入直播名称', trigger: 'change' }]
})
const props = defineProps({
isShowLiveDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowLiveDialog', isShowLiveDialog: boolean): void
(e: 'create'): void
}
// 取消
const handleCancel = () => {
emit('update:isShowLiveDialog', false)
}
// 确定
const handleConfirm = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '腾讯会议')[0]?.value
const params = Object.assign({ course_id: props.course_id, resource_type: type, parent_id: props.chapterID }, form)
createCharacter(params).then(() => {
emit('update:isShowLiveDialog', false)
emit('create')
})
}
const handleLiveList = () => {
const params = {
name: '',
page: 1,
'per-page': 100
}
getLiveList(params).then(res => {
console.log(res.data)
liveList.value = res.data.list
})
}
onMounted(() => {
handleLiveList()
})
</script>
<template>
<el-dialog :model-value="isShowLiveDialog" draggable :before-close="handleCancel" width="25%" title="添加直播">
<el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="80px">
<el-form-item props="resource_id" label="直播名称">
<el-select clearable v-model="form.resource_id" placeholder="请选择直播">
<el-option v-for="item in liveList" :key="item.id" :label="item.subject" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="章节名称" props="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { createCharacter, editCharacter } from '../api'
import type { FormInstance, FormRules } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const emit = defineEmits<Emits>()
const ruleFormRef = ref<FormInstance>()
// 封面状态
const form = reactive({
name: '',
resource_id: ''
})
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入节名称', trigger: 'blur' }]
})
const props = defineProps({
isShowSectionDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
},
isEdit: {
type: Boolean,
required: true
}
})
interface Emits {
(e: 'update:isShowSectionDialog', isShowSectionDialog: boolean): void
(e: 'create'): void
}
// 取消
const handleCancel = () => {
emit('update:isShowSectionDialog', false)
}
// 确定
const handleConfirm = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '章节')[0]?.value
if (props.isEdit) {
const params = Object.assign({ id: props.chapterID, course_id: props.course_id }, form)
editCharacter(params).then(() => {
emit('update:isShowSectionDialog', false)
emit('create')
})
} else {
const params = Object.assign({ course_id: props.course_id, resource_type: type, parent_id: props.chapterID }, form)
createCharacter(params).then(() => {
emit('update:isShowSectionDialog', false)
emit('create')
})
}
}
onMounted(() => {
if (props.isEdit) {
form.name = props.chapterName
}
})
</script>
<template>
<el-dialog
:model-value="isShowSectionDialog"
draggable
:before-close="handleCancel"
width="25%"
:title="props.isEdit ? '编辑:节' : '新增:节'"
>
<el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="80px">
<el-form-item label="所属章:" prop="type">
<p>{{ chapterName }}</p>
</el-form-item>
<el-form-item label="节-名称:" prop="type">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</span>
</template>
</el-dialog>
</template>
...@@ -6,7 +6,8 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -6,7 +6,8 @@ export const routes: Array<RouteRecordRaw> = [
path: '/course/my', path: '/course/my',
component: AppLayout, component: AppLayout,
children: [ children: [
{ path: '', component: () => import('./views/List.vue') } { path: '', component: () => import('./views/List.vue') },
{ path: '/course/my/StepTwo', component: () => import('./views/StepTwo.vue') }
] ]
} }
] ]
...@@ -118,12 +118,7 @@ const statisticsData = [ ...@@ -118,12 +118,7 @@ const statisticsData = [
<el-icon class="video-head-icon" @click="changeCard"><Expand /></el-icon> <el-icon class="video-head-icon" @click="changeCard"><Expand /></el-icon>
</div> </div>
<div class="video-tool-btn"> <div class="video-tool-btn">
<router-link <router-link v-if="tabValue === '1'" to="/course/my/StepTwo" target="_blank">
v-if="tabValue === '1'"
to="/resource/video/update"
target="_blank"
v-permission="'v1-resource-video-create'"
>
<el-button type="primary" round>新建视频资源</el-button> <el-button type="primary" round>新建视频资源</el-button>
</router-link> </router-link>
</div> </div>
......
<script lang="ts" setup>
// import type Node from 'element-plus/es/components/tree/src/model/node'
import AddChapterDialog from '../components/AddChapterDialog.vue'
import AddSectionDialog from '../components/AddSectionDialog.vue'
import AddLiveDialog from '../components/AddLiveDialog.vue'
import { Plus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getCharacter, delCharacter } from '../api'
const dataSource = ref([])
const isShowDialog = ref(false)
const isShowSectionDialog = ref(false)
const isShowLiveDialog = ref(false)
const chapterName = ref('')
const chapterID = ref('')
const isEdit = ref(false)
const defaultProps = {
children: 'children',
label: 'name'
}
// 获取章节列表
onMounted(() => {
handleChapterList()
})
const handleChapterList = () => {
getCharacter({ course_id: '6947482745467568128', type: 'tree' }).then((res: any) => {
dataSource.value = res.data[0].children
})
}
// 新增章节
const handleAddChapter = () => {
isShowDialog.value = true
isEdit.value = false
}
// 页面刷新
const handleFresh = () => {
handleChapterList()
}
// 添加小节
const handleAddSection = (node: any) => {
console.log(node, 'oooo')
chapterName.value = node.label
chapterID.value = node.key
console.log(isShowSectionDialog.value)
isShowSectionDialog.value = true
}
//编辑章节
const handleEdit = (node: any) => {
console.log(node)
chapterID.value = node.key
isEdit.value = true
chapterName.value = node.label
chapterID.value = node.key
if (node.level === 1) {
isShowDialog.value = true
} else {
isShowSectionDialog.value = true
}
}
// 删除章节
const handleDel = (node: any) => {
const params = { id: node.key, course_id: '6947482745467568128' }
delCharacter(params).then(() => {
ElMessage.success('删除成功')
handleFresh()
})
}
const handleAddLive = (node: any) => {
chapterID.value = node.key
isEdit.value = true
chapterName.value = node.label
chapterID.value = node.key
isShowLiveDialog.value = true
}
</script>
<template>
<AppCard title="新建课程">
<el-row>
<el-button type="primary" round style="margin-bottom: 20px" @click="handleAddChapter">添加章</el-button>
<div class="course_tip">
温馨提示:先建“章”,后建“小节”;课程资源关联到小节;能够关联的资源包含:视频、作业、考试、直播、其他资料、教案、课件。
</div>
</el-row>
<el-tree :data="dataSource" node-key="id" default-expand-all :expand-on-click-node="false" :props="defaultProps">
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ node.label }}</span>
<span>
<el-link class="btn_edit" v-if="data.depth !== '3'" @click="handleEdit(node)">编辑</el-link>
<el-link class="btn_edit" v-if="data.depth === '3'">查阅</el-link>
<el-link class="btn_edit" v-if="data.depth === '3'">下载</el-link>
<el-link type="info" @click="handleDel(node)">删除</el-link>
<el-button class="btn_operate" v-if="data.depth === '1'" @click="handleAddSection(node)">
<el-icon><Plus /></el-icon>
&nbsp; 添加小节
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-icon><Plus /></el-icon>
视频
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-icon><Plus /></el-icon>
课件
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-icon><Plus /></el-icon>
资料
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-icon><Plus /></el-icon>
作业
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-icon><Plus /></el-icon>
考试
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'" @click="handleAddLive(node)">
<el-icon><Plus /></el-icon>
直播
</el-button>
</span>
</span>
</template>
</el-tree>
</AppCard>
<!-- 添加章 -->
<AddChapterDialog
v-if="isShowDialog === true"
v-model:isShowDialog="isShowDialog"
@create="handleFresh"
:course_id="'6947482745467568128'"
:isEdit="isEdit"
:chapterID="chapterID"
:chapterName="chapterName"
/>
<!-- 添加小节 -->
<AddSectionDialog
v-if="isShowSectionDialog === true"
v-model:isShowSectionDialog="isShowSectionDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
:isEdit="isEdit"
/>
<!-- 添加直播 -->
<AddLiveDialog
v-if="isShowLiveDialog === true"
v-model:isShowLiveDialog="isShowLiveDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
</template>
<style>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.course_tip {
font-size: 12px;
font-weight: 400;
color: #999999;
margin-left: 16px;
line-height: 36px;
height: 36px;
}
.el-tree-node__content {
height: 42px;
margin-bottom: 15px;
background: #f4f4f4;
}
.btn_operate {
background-color: rgba(248, 241, 229, 0.39);
font-weight: 400;
color: #b2833d;
border: none;
border-radius: 16px;
margin: 8px;
}
.btn_edit {
color: #b2833d;
margin-right: 10px;
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论