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

添加课程第二步开发

上级 4664be91
......@@ -13,10 +13,10 @@ const props = withDefaults(
remote?: IRemoteProps
filters?: any[]
moreFilters?: any[]
columns: any[]
columns?: any[]
data?: any[]
hasPagination?: boolean
limit?: number
limit?: number,
}>(),
{
hasPagination: true,
......
......@@ -15,28 +15,68 @@ export function getCourseList(params: {
export function getCourseStatistics() {
return httpRequest.get('/api/resource/v1/course/course/statistics')
}
// 创建视频
export function createVideo(data: {
name: string
source: string
classification: string
knowledge_points: string
cover: string
source_id: string
// 获取课件列表
export function getCourseList(params: {
tab: string
status?: string
authorized?: string
classification?: string
page?: number
['per-page']?: number
}) {
return httpRequest.post('/api/resource/v1/resource/video/create', data)
return httpRequest.get('/api/resource/v1/resource/courseware/list', { params })
}
// 获取封面列表
export function getCoverList() {
return httpRequest.get('/api/resource/v1/util/get-cover-list')
// 获取教案列表
export function getLessonList(params?: {
tab: string
status?: string
authorized?: string
classification?: string
page?: number
['per-page']?: number
}) {
return httpRequest.get('/api/resource/v1/resource/lesson-plan/list', { params })
}
// 获取其他资料列表
export function getOtherList(params?: {
tab: string
status?: string
authorized?: string
classification?: string
page?: number
['per-page']?: number
}) {
return httpRequest.get('/api/resource/v1/resource/other-information/list', { params })
}
// 试卷搜索
export function gatExamList(data: {
nonce: string
timestamp: string
signature: string
paper_title: string
limit: string
is_all: number
project_prefix: string
}) {
return httpRequest.post('/api/qbs/api/v1/question-papers/search', data)
}
// 获取视频详情
export function getVideoDetails(params: { id: string }) {
return httpRequest.get('/api/resource/v1/resource/video/view', { params })
}
// 获取课件详情
export function getCourseDetails(params: { id: string }) {
return httpRequest.get('/api/resource/v1/resource/courseware/view', { params })
}
// 获取教案详情
export function getLessonDetails(params: { id: string }) {
return httpRequest.get('/api/resource/v1/resource/lesson-plan/view', { params })
}
// 章节结构调整
export function dragChapterList(data: { course_id: string; id: string; brother_id: string; type: string }) {
return httpRequest.post('/api/resource/v1/course/course/drag', data)
}
// 更新视频
export function updateVideo(data: {
......@@ -98,8 +138,8 @@ export function createCharacter(data: {
course_id: string
resource_type: string
name: string
parent_id: string
resource_id: string
parent_id?: string
resource_id?: string
}) {
return httpRequest.post('/api/resource/v1/course/course/create-chapter', data)
}
......
<script setup lang="ts">
import { getCourseList, createCharacter } from '../api'
import CardListItem from './CardListItem.vue'
import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList'
const store = useMapStore()
const appList = ref()
// const page = reactive({ total: 0, size: 10, currentPage: 1 })
const emit = defineEmits<Emits>()
const props = defineProps({
isShowCourseDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowCourseDialog', isShowCourseDialog: boolean): void
(e: 'create'): void
}
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value?.refetch()
}
const handleCancel = () => {
emit('update:isShowCourseDialog', false)
}
const handleSave = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '课件')[0]?.value
console.log(tableData.list)
const name = tableData.list.filter((item: any) => item.auth_department === true)[0].name
const resource_id = tableData.list.filter((item: any) => item.auth_department === true)[0].id
// console.log(resource_id, '1111', name)
const params: any = {
name: name,
course_id: props.course_id,
resource_type: type,
parent_id: props.chapterID,
resource_id: resource_id
}
createCharacter(params).then(() => {
emit('update:isShowCourseDialog', false)
emit('create')
})
}
let tableData: any = reactive({
list: [],
title: '',
total: ''
})
const listOptions = {
remote: {
httpRequest: getCourseList,
callback(data: any) {
tableData = data
return data
},
params: { tab: tabValue, status: '', authorized: '', name: '' }
},
filters: [
{ prop: 'classification', label: '类别:', slots: 'filter-type' },
{ type: 'input', prop: 'name', label: '标题:' }
],
columns: [],
data: tableData
}
// 筛选下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList()
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
const typeFilter = () => {
appList.value.refetch()
}
</script>
<template>
<el-drawer :model-value="isShowCourseDialog" draggable :before-close="handleCancel" size="60%" title="添加课件">
<div class="video-head">
<el-tabs @tab-change="tabChange" v-model="tabValue">
<el-tab-pane label="我的资源" name="1"></el-tab-pane>
<el-tab-pane label="部门资源" name="2"></el-tab-pane>
<el-tab-pane label="公开资源" name="3"></el-tab-pane>
</el-tabs>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #filter-type="{ params }">
<el-tree-select
@change="typeFilter"
clearable
:props="defaultProps"
v-model="params.classification"
:data="selectTree"
/>
</template>
<template #body="{ data }">
<div class="card-list" v-if="data.length">
<div class="card-list-con">
<div style="position: relative" v-for="(item, index) in data" :key="index">
<el-checkbox
v-model="item.auth_department"
style="position: absolute; right: 40px; bottom: 22px"
></el-checkbox>
<CardListItem :tabIndex="tabValue" :data="item"> </CardListItem>
</div>
</div>
</div>
<el-empty v-else description="暂无数据" />
</template>
</AppList>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-drawer>
</template>
<style lang="scss">
.card-list {
display: flex;
flex-direction: column;
}
.card-list-con {
background: #fafafa;
padding: 20px;
display: flex;
flex-wrap: wrap;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
import { gatExamList, createCharacter } from '../api'
import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList'
const store = useMapStore()
const appList = ref()
let { list: selectTree } = useGetCategoryList()
const tabValue = ref('1')
const multipleSelection: any = ref([])
const emit = defineEmits<Emits>()
const props = defineProps({
isShowExamDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowExamDialog', isShowExamDialog: boolean): void
(e: 'create'): void
}
const listOptions = {
remote: {
httpRequest: gatExamList,
callback(data: any) {
return { list: data.data }
},
params: {
tab: tabValue,
paper_title: '',
is_all: 1,
project_prefix: 'x1',
signature: 'UG7wBenexQhiuD2wpCwuxkU0jqcj006d',
timestamp: '32322323',
nonce: '3232'
}
},
filters: [
{ prop: 'classification', label: '类别:', slots: 'filter-type' },
{ type: 'input', prop: 'paper_category.name', label: '标题:' }
],
columns: [
{ type: 'selection', fixed: 'left' },
{ type: 'index', label: '序号', fixed: 'left' },
{
label: '组卷模式',
prop: 'paper_type',
computed: (row: any) => {
return row.row.paper_type === 1 ? '选题组卷' : '自动组卷'
}
},
{
label: '试卷用途',
prop: 'paper_uses',
computed: (row: any) => {
const map = { 1: '考试', 2: '课后作业', 3: '课程测试' }
return map[row.row.paper_uses] || row.row.paper_uses
}
},
{ label: '试卷分类', prop: 'paper_category.name', minWidth: 200 },
{ label: '试卷名称', prop: 'paper_title', minWidth: 200 },
{ label: '总分', prop: 'paper_total_score' },
{ label: '及格分数', prop: 'pass_score' },
{ label: '更新时间', prop: 'updated_at' }
]
}
// 资源出处 tab触发
const tabChange = () => {
appList.value?.refetch()
}
const handleCancel = () => {
emit('update:isShowExamDialog', false)
}
// 保存
const handleSave = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '视频')[0]?.value
console.log(multipleSelection)
const name = multipleSelection.value.map((item: any) => item.paper_category.name)[0]
const resource_id = multipleSelection.value.map((item: any) => item.id)[0]
const params: any = {
name: name,
course_id: props.course_id,
resource_type: type,
parent_id: props.chapterID,
resource_id: resource_id
}
createCharacter(params).then(() => {
emit('update:isShowExamDialog', false)
emit('create')
})
}
// 筛选下拉选择tree 视频分类
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
// 刷新
const typeFilter = () => {
appList.value.refetch()
}
const handleSelectionChange = (val: any) => {
multipleSelection.value = val
}
</script>
<template>
<el-drawer :model-value="isShowExamDialog" draggable :before-close="handleCancel" size="60%" title="添加考试/作业">
<div class="video-head">
<el-tabs @tab-change="tabChange" v-model="tabValue">
<el-tab-pane label="我的资源" name="1"></el-tab-pane>
<el-tab-pane label="部门资源" name="2"></el-tab-pane>
<el-tab-pane label="公开资源" name="3"></el-tab-pane>
</el-tabs>
</div>
<AppList v-bind="listOptions" ref="appList" @selection-change="handleSelectionChange">
<template #filter-type="{ params }">
<el-tree-select
@change="typeFilter"
clearable
:props="defaultProps"
v-model="params.paper_categories"
:data="selectTree"
/>
</template>
</AppList>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-drawer>
</template>
<style lang="scss">
.card-list {
display: flex;
flex-direction: column;
}
.card-list-con {
background: #fafafa;
padding: 20px;
display: flex;
flex-wrap: wrap;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
import { getLessonList, createCharacter } from '../api'
import CardListItem from './CardListItem.vue'
import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList'
const store = useMapStore()
const appList = ref()
// const page = reactive({ total: 0, size: 10, currentPage: 1 })
const emit = defineEmits<Emits>()
const props = defineProps({
isShowLessonDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowLessonDialog', isShowLessonDialog: boolean): void
(e: 'create'): void
}
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value?.refetch()
}
const handleCancel = () => {
emit('update:isShowLessonDialog', false)
}
const handleSave = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '视频')[0]?.value
console.log(tableData.list)
const name = tableData.list.filter((item: any) => item.auth_department === true)[0].name
const resource_id = tableData.list.filter((item: any) => item.auth_department === true)[0].id
// console.log(resource_id, '1111', name)
const params: any = {
name: name,
course_id: props.course_id,
resource_type: type,
parent_id: props.chapterID,
resource_id: resource_id
}
createCharacter(params).then(() => {
emit('update:isShowLessonDialog', false)
emit('create')
})
}
let tableData: any = reactive({
list: [],
title: '',
total: ''
})
const listOptions = {
remote: {
httpRequest: getLessonList,
callback(data: any) {
tableData = data
return data
},
params: { tab: tabValue, status: '', authorized: '', name: '' }
},
filters: [
{ prop: 'classification', label: '类别:', slots: 'filter-type' },
{ type: 'input', prop: 'name', label: '标题:' }
],
columns: [],
data: tableData
}
// 筛选下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList()
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
const typeFilter = () => {
appList.value.refetch()
}
</script>
<template>
<el-drawer :model-value="isShowLessonDialog" draggable :before-close="handleCancel" size="60%" title="添加教案">
<div class="video-head">
<el-tabs @tab-change="tabChange" v-model="tabValue">
<el-tab-pane label="我的资源" name="1"></el-tab-pane>
<el-tab-pane label="部门资源" name="2"></el-tab-pane>
<el-tab-pane label="公开资源" name="3"></el-tab-pane>
</el-tabs>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #filter-type="{ params }">
<el-tree-select
@change="typeFilter"
clearable
:props="defaultProps"
v-model="params.classification"
:data="selectTree"
/>
</template>
<template #body="{ data }">
<div class="card-list" v-if="data.length">
<div class="card-list-con">
<div style="position: relative" v-for="(item, index) in data" :key="index">
<el-checkbox
v-model="item.auth_department"
style="position: absolute; right: 40px; bottom: 22px"
></el-checkbox>
<CardListItem :tabIndex="tabValue" :data="item"> </CardListItem>
</div>
</div>
</div>
<el-empty v-else description="暂无数据" />
</template>
</AppList>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-drawer>
</template>
<style lang="scss">
.card-list {
display: flex;
flex-direction: column;
}
.card-list-con {
background: #fafafa;
padding: 20px;
display: flex;
flex-wrap: wrap;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
......@@ -20,8 +20,7 @@ let liveList = ref<IliveList[]>([])
// 封面状态
const form = reactive({
name: '',
resource_id: ''
name: ''
})
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入直播名称', trigger: 'change' }]
......@@ -35,7 +34,6 @@ const props = defineProps({
type: String,
required: true
},
chapterName: {
type: String,
required: true
......@@ -59,36 +57,63 @@ 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)
const params: any = Object.assign(
{
course_id: props.course_id,
resource_type: type,
parent_id: props.chapterID,
resource_id: lecturerValue.value[0]
},
form
)
createCharacter(params).then(() => {
emit('update:isShowLiveDialog', false)
emit('create')
})
}
const handleLiveList = () => {
const params = {
name: '',
page: 1,
'per-page': 100
const loading = ref(false)
// 直播选中的值
const lecturerValue = ref([])
// 所有被搜索出来的值
const allLecturers: any = ref([])
const handleLiveList = (query: string) => {
if (query) {
loading.value = true
getLiveList({ name: query }).then((res: any) => {
loading.value = false
liveList.value = res.data.list.filter((item: any) => {
return !lecturerValue.value.find((id: string) => id === item.id)
})
liveList.value.forEach((item: any) => {
const findItem = allLecturers.value.find((cItem: any) => cItem.id === item.id)
if (!findItem) {
allLecturers.value.push(item)
}
})
})
} else {
liveList.value = []
}
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-dialog :model-value="isShowLiveDialog" draggable :before-close="handleCancel" width="30%" title="添加直播">
<el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="120px">
<el-form-item props="resource_id" label="直播名称:">
<el-select
v-model="lecturerValue"
filterable
remote
reserve-keyword
placeholder="请输入直播名称"
:remote-method="handleLiveList"
:loading="loading"
>
<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-form-item label="章节名称" props="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
......
<script setup lang="ts">
import { getOtherList, createCharacter } from '../api'
import CardListItem from './CardListItem.vue'
import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList'
const store = useMapStore()
const appList = ref()
// const page = reactive({ total: 0, size: 10, currentPage: 1 })
const emit = defineEmits<Emits>()
const props = defineProps({
isShowOtherDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowOtherDialog', isShowOtherDialog: boolean): void
(e: 'create'): void
}
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value?.refetch()
}
const handleCancel = () => {
emit('update:isShowOtherDialog', false)
}
const handleSave = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '视频')[0]?.value
console.log(tableData.list)
const name = tableData.list.filter((item: any) => item.auth_department === true)[0].name
const resource_id = tableData.list.filter((item: any) => item.auth_department === true)[0].id
// console.log(resource_id, '1111', name)
const params: any = {
name: name,
course_id: props.course_id,
resource_type: type,
parent_id: props.chapterID,
resource_id: resource_id
}
createCharacter(params).then(() => {
emit('update:isShowOtherDialog', false)
emit('create')
})
}
let tableData: any = reactive({
list: [],
title: '',
total: ''
})
const listOptions = {
remote: {
httpRequest: getOtherList,
callback(data: any) {
tableData = data
return data
},
params: { tab: tabValue, status: '', authorized: '', name: '' }
},
filters: [
{ prop: 'classification', label: '类别:', slots: 'filter-type' },
{ type: 'input', prop: 'name', label: '标题:' }
],
columns: [],
data: tableData
}
// 筛选下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList()
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
const typeFilter = () => {
appList.value.refetch()
}
</script>
<template>
<el-drawer :model-value="isShowOtherDialog" draggable :before-close="handleCancel" size="60%" title="添加其他资料">
<div class="video-head">
<el-tabs @tab-change="tabChange" v-model="tabValue">
<el-tab-pane label="我的资源" name="1"></el-tab-pane>
<el-tab-pane label="部门资源" name="2"></el-tab-pane>
<el-tab-pane label="公开资源" name="3"></el-tab-pane>
</el-tabs>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #filter-type="{ params }">
<el-tree-select
@change="typeFilter"
clearable
:props="defaultProps"
v-model="params.classification"
:data="selectTree"
/>
</template>
<template #body="{ data }">
<div class="card-list" v-if="data.length">
<div class="card-list-con">
<div style="position: relative" v-for="(item, index) in data" :key="index">
<el-checkbox
v-model="item.auth_department"
style="position: absolute; right: 40px; bottom: 22px"
></el-checkbox>
<CardListItem :tabIndex="tabValue" :data="item"> </CardListItem>
</div>
</div>
</div>
<el-empty v-else description="暂无数据" />
</template>
</AppList>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-drawer>
</template>
<style lang="scss">
.card-list {
display: flex;
flex-direction: column;
}
.card-list-con {
background: #fafafa;
padding: 20px;
display: flex;
flex-wrap: wrap;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
import { getVideoList, createCharacter } from '../api'
import CardListItem from './CardListItem.vue'
import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList'
const store = useMapStore()
const appList = ref()
// const page = reactive({ total: 0, size: 10, currentPage: 1 })
const emit = defineEmits<Emits>()
const props = defineProps({
isShowVideoDialog: {
type: Boolean,
required: true
},
course_id: {
type: String,
required: true
},
chapterName: {
type: String,
required: true
},
chapterID: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowVideoDialog', isShowVideoDialog: boolean): void
(e: 'create'): void
}
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value?.refetch()
}
const handleCancel = () => {
emit('update:isShowVideoDialog', false)
}
const handleSave = () => {
const type = store.mapList
.filter(item => item.key === 'system_chapter_resource_type')[0]
?.values.filter(it => it.label === '视频')[0]?.value
console.log(tableData.list)
const name = tableData.list.filter((item: any) => item.auth_department === true)[0].name
const resource_id = tableData.list.filter((item: any) => item.auth_department === true)[0].id
// console.log(resource_id, '1111', name)
const params: any = {
name: name,
course_id: props.course_id,
resource_type: type,
parent_id: props.chapterID,
resource_id: resource_id
}
createCharacter(params).then(() => {
emit('update:isShowVideoDialog', false)
emit('create')
})
}
let tableData: any = reactive({
list: [],
title: '',
total: ''
})
const listOptions = {
remote: {
httpRequest: getVideoList,
callback(data: any) {
tableData = data
return data
},
params: { tab: tabValue, status: '', authorized: '', name: '' }
},
filters: [
{ prop: 'classification', label: '类别:', slots: 'filter-type' },
{ type: 'input', prop: 'name', label: '标题:' }
],
columns: [],
data: tableData
}
// 筛选下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList()
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
const typeFilter = () => {
appList.value.refetch()
}
</script>
<template>
<el-drawer :model-value="isShowVideoDialog" draggable :before-close="handleCancel" size="60%" title="添加视频">
<div class="video-head">
<el-tabs @tab-change="tabChange" v-model="tabValue">
<el-tab-pane label="我的资源" name="1"></el-tab-pane>
<el-tab-pane label="部门资源" name="2"></el-tab-pane>
<el-tab-pane label="公开资源" name="3"></el-tab-pane>
</el-tabs>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #filter-type="{ params }">
<el-tree-select
@change="typeFilter"
clearable
:props="defaultProps"
v-model="params.classification"
:data="selectTree"
/>
</template>
<template #body="{ data }">
<div class="card-list" v-if="data.length">
<div class="card-list-con">
<div style="position: relative" v-for="(item, index) in data" :key="index">
<el-checkbox
v-model="item.auth_department"
style="position: absolute; right: 40px; bottom: 22px"
></el-checkbox>
<CardListItem :tabIndex="tabValue" :data="item"> </CardListItem>
</div>
</div>
</div>
<el-empty v-else description="暂无数据" />
</template>
</AppList>
<el-button type="primary" @click="handleSave">保存</el-button>
</el-drawer>
</template>
<style lang="scss">
.card-list {
display: flex;
flex-direction: column;
}
.card-list-con {
background: #fafafa;
padding: 20px;
display: flex;
flex-wrap: wrap;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
const props:any = defineProps<{ data: object, tabIndex: string }>()
const props: any = defineProps<{ data: object; tabIndex: string }>()
</script>
<template>
<!-- <div>{{ props.data }}</div> -->
......@@ -9,12 +9,12 @@ const props:any = defineProps<{ data: object, tabIndex: string }>()
<!-- <img :src="props.data.cover" /> -->
<div class="cover-img" :style="`background-image:url(${props.data.cover})`"></div>
<div class="tool-pop-btn">
<div style="min-width:100%">
<div style="min-width: 100%">
<router-link v-if="props.data.auth_edit" :to="`/resource/video/update?id=${props.data.id}`">
<div class="edit-btn">编辑</div>
</router-link>
</div>
<div style="min-width:100%">
<div style="min-width: 100%">
<router-link v-if="props.data.auth_view" :to="`/resource/video/view?id=${props.data.id}`">
<div class="view-btn">查看</div>
</router-link>
......@@ -65,12 +65,12 @@ const props:any = defineProps<{ data: object, tabIndex: string }>()
color: #ffffff;
padding-left: 16px;
box-sizing: border-box;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tool-pop-btn {
transition: all .5s;
transition: all 0.5s;
position: absolute;
top: 0;
left: 0;
......@@ -80,75 +80,75 @@ const props:any = defineProps<{ data: object, tabIndex: string }>()
opacity: 0;
padding-top: 52px;
box-sizing: border-box;
.edit-btn{
.edit-btn {
width: 113px;
line-height: 32px;
border: 1px solid #D3D3D3;
border: 1px solid #d3d3d3;
border-radius: 18px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
color: #ffffff;
margin: 0 auto 12px;
cursor: pointer;
}
.view-btn{
.view-btn {
width: 113px;
line-height: 32px;
background: #AA1941;
background: #aa1941;
border-radius: 18px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
color: #ffffff;
margin: 0 auto;
cursor: pointer;
}
}
}
}
.card-item-bottom{
.card-item-bottom {
background: #fff;
padding: 20px 16px 30px;
.item-t{
.item-t {
display: flex;
align-items: center;
justify-content: space-between;
.text{
.text {
width: 150px;
font-size: 16px;
line-height: 100%;
color: #666666;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tag{
.tag {
width: 48px;
line-height: 22px;
background: #AA1941;
background: #aa1941;
border-radius: 11px;
font-size: 14px;
color: #fff;
text-align: center;
&.green{
background: #1AB226;
&.green {
background: #1ab226;
}
}
}
.item-b{
.item-b {
margin-top: 18px;
display: flex;
align-items: center;
justify-content: space-between;
.time{
.time {
font-size: 14px;
line-height: 100%;
color: #999999;
}
.tag{
.tag {
font-size: 16px;
line-height: 100%;
color: #999999;
}
}
}
</style>
\ No newline at end of file
</style>
<script lang="ts" setup>
import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue'
const emit = defineEmits<Emits>()
const props = defineProps({
isShowVideoPlayDialog: {
type: Boolean,
required: true
},
videoOptions: {
type: String,
required: true
}
})
interface Emits {
(e: 'update:isShowVideoPlayDialog', isShowVideoPlayDialog: boolean): void
}
// 取消
const handleCancel = () => {
emit('update:isShowVideoPlayDialog', false)
}
</script>
<template>
<el-dialog :model-value="isShowVideoPlayDialog" draggable :before-close="handleCancel" width="35%">
<AppVideoPlayer :options="{sources:[{src:props.videoOptions}]}"></AppVideoPlayer>
</el-dialog>
</template>
......@@ -3,14 +3,33 @@
import AddChapterDialog from '../components/AddChapterDialog.vue'
import AddSectionDialog from '../components/AddSectionDialog.vue'
import AddLiveDialog from '../components/AddLiveDialog.vue'
import AddVideoDialog from '../components/AddVideoDialog.vue'
import AddCoursewareDialog from '../components/AddCoursewareDialog.vue'
import AddLessonPlanDialog from '../components/AddLessonPlanDialog.vue'
import AddOtherDialog from '../components/AddOtherDialog.vue'
import AddExamDialog from '../components/AddExamDialog.vue'
import VideoPlayDialog from '../components/VideoPlayDialog.vue'
import { Plus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { getCharacter, delCharacter } from '../api'
import {
getCharacter,
delCharacter,
getVideoDetails,
getCourseDetails,
getLessonDetails,
dragChapterList
} from '../api'
const dataSource = ref([])
const isShowDialog = ref(false)
const isShowSectionDialog = ref(false)
const isShowLiveDialog = ref(false)
const isShowVideoDialog = ref(false)
const isShowCourseDialog = ref(false)
const isShowLessonDialog = ref(false)
const isShowOtherDialog = ref(false)
const isShowExamDialog = ref(false)
const isShowVideoPlayDialog = ref(false)
const chapterName = ref('')
const chapterID = ref('')
const isEdit = ref(false)
......@@ -67,13 +86,106 @@ const handleDel = (node: any) => {
handleFresh()
})
}
// 添加直播
const handleAddLive = (node: any) => {
chapterID.value = node.key
isEdit.value = true
chapterName.value = node.label
chapterID.value = node.key
isShowLiveDialog.value = true
}
// 添加视频
const handleAddVideo = (node: any) => {
chapterID.value = node.key
chapterName.value = node.label
chapterID.value = node.key
isShowVideoDialog.value = true
}
// 添加课件
const handleAddCourse = (node: any) => {
chapterID.value = node.key
chapterName.value = node.label
chapterID.value = node.key
isShowCourseDialog.value = true
}
// 添加教案
const handleAddLessonPlan = (node: any) => {
chapterID.value = node.key
chapterName.value = node.label
chapterID.value = node.key
isShowLessonDialog.value = true
}
// 添加其他资料
const handleAddOther = (node: any) => {
chapterID.value = node.key
chapterName.value = node.label
chapterID.value = node.key
isShowOtherDialog.value = true
}
// 添加考试
const handleAddExam = (node: any) => {
chapterID.value = node.key
chapterName.value = node.label
chapterID.value = node.key
isShowExamDialog.value = true
}
//查阅
const videoUrl = ref('')
const courseUrl = ref('')
const lessonPlanUrl = ref('')
const handleConsult = (node: any) => {
console.log(node.data.resource_type, '000')
// 视频
if (node.data.resource_type === '2') {
getVideoDetails({ id: node.data.resource_id }).then(res => {
videoUrl.value = res.data.play_auth.play_info_list.filter((item: any) => item.Definition === 'SD')[0].PlayURL
console.log(videoUrl, '000111')
isShowVideoPlayDialog.value = true
})
} else if (node.data.resource_type === '4') {
// 其他资源
}
}
// 下载
const handleDownload = (node: any) => {
if (node.data.resource_type === '10') {
// 课件
getCourseDetails({ id: node.data.resource_id }).then(res => {
courseUrl.value = res.data.url
window.open(courseUrl.value)
})
} else if (node.data.resource_type === '11') {
//教案
getLessonDetails({ id: node.data.resource_id }).then(res => {
lessonPlanUrl.value = res.data.url
window.open(lessonPlanUrl.value)
})
}
}
const allowDrop = (draggingNode: any, dropNode: any, type: any) => {
console.log(draggingNode.data, dropNode, type)
if (draggingNode.data.depth === dropNode.data.depth) {
if (draggingNode.data.parentId === dropNode.data.parentId) {
return type === 'prev' || type === 'next'
} else {
return false
}
} else {
// 不同级进行处理
return false
}
}
const handleDrop = (startNode: any, endNode: any, position: any, event: any) => {
console.log(startNode, endNode, position, event)
const params = {
course_id: '6947482745467568128',
id: startNode.data.id,
brother_id: endNode.data.id,
type: startNode.data.id < endNode.data.id ? 'before' : 'after'
}
dragChapterList(params).then(() => {
handleChapterList()
})
}
</script>
<template>
<AppCard title="新建课程">
......@@ -83,38 +195,57 @@ const handleAddLive = (node: any) => {
温馨提示:先建“章”,后建“小节”;课程资源关联到小节;能够关联的资源包含:视频、作业、考试、直播、其他资料、教案、课件。
</div>
</el-row>
<el-tree :data="dataSource" node-key="id" default-expand-all :expand-on-click-node="false" :props="defaultProps">
<el-tree
draggable
:data="dataSource"
node-key="id"
default-expand-all
:expand-on-click-node="false"
:props="defaultProps"
:allow-drop="allowDrop"
@node-drop="handleDrop"
>
<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
class="btn_edit"
v-if="data.depth === '3' && node.data.resource_type === '2'"
@click="handleConsult(node)"
>查阅</el-link
>
<el-link
class="btn_edit"
v-if="data.depth === '3' && node.data.resource_type !== '2' && node.data.resource_type !== '6'"
@click="handleDownload(node)"
>下载</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-button class="btn_operate" v-if="data.depth === '2'" @click="handleAddVideo(node)">
<el-icon><Plus /></el-icon>
视频
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-button class="btn_operate" v-if="data.depth === '2'" @click="handleAddCourse(node)">
<el-icon><Plus /></el-icon>
课件
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-button class="btn_operate" v-if="data.depth === '2'" @click="handleAddLessonPlan(node)">
<el-icon><Plus /></el-icon>
资料
教案
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-button class="btn_operate" v-if="data.depth === '2'" @click="handleAddOther(node)">
<el-icon><Plus /></el-icon>
作业
资料
</el-button>
<el-button class="btn_operate" v-if="data.depth === '2'">
<el-button class="btn_operate" v-if="data.depth === '2'" @click="handleAddExam(node)">
<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>
......@@ -154,6 +285,58 @@ const handleAddLive = (node: any) => {
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
<!-- 添加视频 -->
<AddVideoDialog
v-if="isShowVideoDialog === true"
v-model:isShowVideoDialog="isShowVideoDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
<!-- 添加课件 -->
<AddCoursewareDialog
v-if="isShowCourseDialog === true"
v-model:isShowCourseDialog="isShowCourseDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
<!-- 添加教案 -->
<AddLessonPlanDialog
v-if="isShowLessonDialog === true"
v-model:isShowLessonDialog="isShowLessonDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
<!-- 添加其他资源 -->
<AddOtherDialog
v-if="isShowOtherDialog === true"
v-model:isShowOtherDialog="isShowOtherDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
<!-- 添加考试 -->
<AddExamDialog
v-if="isShowExamDialog === true"
v-model:isShowExamDialog="isShowExamDialog"
@create="handleFresh"
:chapterName="chapterName"
:chapterID="chapterID"
:course_id="'6947482745467568128'"
/>
<!-- 视频查阅弹框 -->
<VideoPlayDialog
v-if="isShowVideoPlayDialog === true"
v-model:isShowVideoPlayDialog="isShowVideoPlayDialog"
:videoOptions="videoUrl"
/>
<!-- 课件下载 -->
</template>
<style>
......
<script setup lang="ts">
const props:any = defineProps<{ data: object, tabIndex: string }>()
const props: any = defineProps<{ data: object; tabIndex: string }>()
</script>
<template>
<!-- <div>{{ props.data }}</div> -->
<div>{{ props.data }}</div>
<div class="card-item">
<div class="card-item-top">
<div class="title">{{ props.data.name }}</div>
<!-- <img :src="props.data.cover" /> -->
<div class="cover-img" :style="`background-image:url(${props.data.cover})`"></div>
<div class="tool-pop-btn">
<div style="min-width:100%">
<router-link v-if="props.data.auth_edit" :to="`/resource/video/update?id=${props.data.id}`">
<div class="edit-btn">编辑</div>
</router-link>
</div>
<div style="min-width:100%">
<div style="min-width: 100%">
<router-link v-if="props.data.auth_view" :to="`/resource/video/view?id=${props.data.id}`">
<div class="view-btn">查看</div>
</router-link>
</div>
<div style="min-width: 100%">
<!-- <router-link v-if="props.data.auth_view" :to="`/resource/video/view?id=${props.data.id}`"> -->
<div class="view-btn">选择</div>
<!-- </router-link> -->
</div>
</div>
</div>
<div class="card-item-bottom">
......@@ -65,12 +65,12 @@ const props:any = defineProps<{ data: object, tabIndex: string }>()
color: #ffffff;
padding-left: 16px;
box-sizing: border-box;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tool-pop-btn {
transition: all .5s;
transition: all 0.5s;
position: absolute;
top: 0;
left: 0;
......@@ -80,75 +80,75 @@ const props:any = defineProps<{ data: object, tabIndex: string }>()
opacity: 0;
padding-top: 52px;
box-sizing: border-box;
.edit-btn{
.edit-btn {
width: 113px;
line-height: 32px;
border: 1px solid #D3D3D3;
border: 1px solid #d3d3d3;
border-radius: 18px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
color: #ffffff;
margin: 0 auto 12px;
cursor: pointer;
}
.view-btn{
.view-btn {
width: 113px;
line-height: 32px;
background: #AA1941;
background: #aa1941;
border-radius: 18px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
color: #ffffff;
margin: 0 auto;
cursor: pointer;
}
}
}
}
.card-item-bottom{
.card-item-bottom {
background: #fff;
padding: 20px 16px 30px;
.item-t{
.item-t {
display: flex;
align-items: center;
justify-content: space-between;
.text{
.text {
width: 150px;
font-size: 16px;
line-height: 100%;
color: #666666;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tag{
.tag {
width: 48px;
line-height: 22px;
background: #AA1941;
background: #aa1941;
border-radius: 11px;
font-size: 14px;
color: #fff;
text-align: center;
&.green{
background: #1AB226;
&.green {
background: #1ab226;
}
}
}
.item-b{
.item-b {
margin-top: 18px;
display: flex;
align-items: center;
justify-content: space-between;
.time{
.time {
font-size: 14px;
line-height: 100%;
color: #999999;
}
.tag{
.tag {
font-size: 16px;
line-height: 100%;
color: #999999;
}
}
}
</style>
\ No newline at end of file
</style>
// json to array
export const json2Array = function (data, isValueToNumber = true) {
return Object.keys(data).map(value => ({ label: data[value], value: isValueToNumber ? parseInt(value) : value }))
}
// 组卷模式
export const paperType = {
1: '选题组卷',
2: '自动组卷',
3: '自由组卷'
}
// 组卷模式列表
export const paperTypeList = json2Array(paperType)
// 试题类型
export const questionType = {
1: '单选题',
2: '多选题',
3: '问答题',
5: '案例题',
6: '判断题',
7: '实操题',
8: '情景题'
}
// 试题类型列表
export const questionTypeList = json2Array(questionType, false)
// 试题难度
export const questionDifficulty = {
1: '易',
2: '中',
3: '难',
0: '无'
}
// 试题难度列表
export const questionDifficultyList = json2Array(questionDifficulty, false)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论