提交 2e3c599e authored 作者: matian's avatar matian

课件资源部分开发

上级 35190c86
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取视频列表 // 获取课件列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) { export function getCourseList(params: {
return httpRequest.get('/api/psp/backend/video/index', { params }) tab: string
status?: string
authorized?: string
classification?: string
page?: number
['per-page']?: number
}) {
return httpRequest.get('/api/resource/v1/resource/courseware/list', { params })
} }
// 创建视频 // 创建
export function createVideo(data: { course_name: string; cover_page: string; type: string; weight?: string }) { export function createCourse(data: {
return httpRequest.post('/api/psp/backend/video/create', data) url: string
name: string
source: string
classification: string
knowledge_points: string
}) {
return httpRequest.post('/api/resource/v1/resource/courseware/create', data)
} }
// 更新视频 // 获取分类列表
export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) { export function getCategoryList(params: { type: string; category_name?: string }) {
return httpRequest.post('/api/psp/backend/video/update', data) return httpRequest.get('/api/resource/v1/backend/category/list', { params })
} }
// 获取视频详情 // 更新课件
export function getVideo(params: { id: string }) { export function updateCourse(data: {
return httpRequest.get('/api/psp/backend/video/view', { params }) id: string
url: string
name: string
source: string
classification: string
knowledge_points: string
}) {
return httpRequest.post('/v1/resource/courseware/update', data)
}
// 获取课件详情
export function getCourseDetails(params: { id: string }) {
return httpRequest.get('/api/resource/v1/resource/courseware/view', { params })
} }
...@@ -7,8 +7,8 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -7,8 +7,8 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout, component: AppLayout,
children: [ children: [
{ path: '', component: () => import('./views/List.vue') }, { path: '', component: () => import('./views/List.vue') },
{ path: 'update', component: () => import('./views/Update.vue') }, { path: '/resource/courseware/update', component: () => import('./views/Update.vue') },
{ path: 'view', component: () => import('./views/View.vue') } { path: '/resource/courseware/view', component: () => import('./views/View.vue') }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true } // { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
] ]
} }
......
<script setup lang="ts"> <script setup lang="ts">
// import { getVideoList } from '../api' import { getCourseList } from '../api'
import CardListItem from '@/components/base/CardListItem.vue' import CardListItem from '@/components/base/CardListItem.vue'
import { Expand, Search } from '@element-plus/icons-vue' import { Expand, Search } from '@element-plus/icons-vue'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const appList = ref() const appList = ref()
// 列表切换
const isCard = ref(true) const isCard = ref(true)
const listOptions = { // 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value.refetch()
}
const listOptions = $computed(() => {
return {
remote: { remote: {
// httpRequest: getVideoList, httpRequest: getCourseList,
params: { type: '' }, params: { tab: tabValue, title: '', status: '', authorized: '', classification: '' },
beforeRequest(params: any) { beforeRequest(params: any) {
// params.type = 选项卡类型 // params.type = 选项卡类型
return params return params
} }
}, },
filters: [ filters: [
{ type: 'select', prop: 'type', label: '状态' }, {
type: 'select',
prop: 'type',
label: '状态',
options: store.mapList?.filter((item: any) => item.key === 'system_status')[0]?.values
},
{ type: 'select', prop: 'project_id', label: '项目' }, { type: 'select', prop: 'project_id', label: '项目' },
{ type: 'select', prop: 'category_id', label: '类别' }, { type: 'select', prop: 'category_id', label: '类别' },
{ prop: 'search', slots: 'filter-search' } { prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' } // { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
], ],
columns: [ columns: [
{ label: '视频标题', prop: 'title' }, { label: '课件标题', prop: 'name' },
{ label: '视频分类', prop: 'type' }, { label: '课件分类', prop: 'classification_name' },
{ label: '知识点', prop: 'zsd' }, { label: '知识点', prop: 'knowledge_points' },
{ label: '封面', slots: 'table-cover', width: 100 }, { label: '资源状态', prop: 'status_name' },
{ label: '资源状态', prop: 'state' }, { label: '审核状态', prop: 'audit_status_name' },
{ label: '审核状态', prop: 'state2' }, { label: '更新人', prop: 'updated_operator_name' },
{ label: '更新人', prop: 'update' }, { label: '更新人部门', prop: 'organ_id_name' },
{ label: '更新人部门', prop: 'updatebm' }, { label: '更新日期', prop: 'updated_time' },
{ label: '更新日期', prop: 'update_time' },
{ label: '操作', slots: 'table-operate', align: 'right' } { label: '操作', slots: 'table-operate', align: 'right' }
],
data: [
{ id: 1, title: '视频标题', type: '视频分类' },
{ id: 2, title: '视频标题', type: '视频分类' }
] ]
} }
})
</script> </script>
<template> <template>
<AppCard> <AppCard>
<!-- <el-switch v-model="isCard"></el-switch> -->
<div class="video-head"> <div class="video-head">
<el-tabs> <el-tabs @tab-change="tabChange" v-model="tabValue">
<el-tab-pane label="我的资源"></el-tab-pane> <el-tab-pane label="我的资源"></el-tab-pane>
<el-tab-pane label="部门资源"></el-tab-pane> <el-tab-pane label="部门资源"></el-tab-pane>
<el-tab-pane label="公开资源"></el-tab-pane> <el-tab-pane label="公开资源"></el-tab-pane>
...@@ -65,10 +73,10 @@ const listOptions = { ...@@ -65,10 +73,10 @@ const listOptions = {
</template> </template>
<template #table-operate="{ row }"> <template #table-operate="{ row }">
<el-space> <el-space>
<router-link :to="`/video/update/${row.id}`"> <router-link :to="`/resource/courseware/update/?id=${row.id}`">
<el-button plain>编辑</el-button> <el-button plain>编辑</el-button>
</router-link> </router-link>
<router-link :to="`/video/view/${row.id}`"> <router-link :to="`/resource/courseware/view/?id=${row.id}`">
<el-button type="primary" plain>查看</el-button> <el-button type="primary" plain>查看</el-button>
</router-link> </router-link>
</el-space> </el-space>
...@@ -76,17 +84,17 @@ const listOptions = { ...@@ -76,17 +84,17 @@ const listOptions = {
<!-- 卡片 --> <!-- 卡片 -->
<template #body="{ data }" v-if="isCard"> <template #body="{ data }" v-if="isCard">
<div class="card-list"> <div class="card-list" v-if="data.length">
<CardListItem v-for="(item, index) in data" :data="item" :key="index"></CardListItem> <CardListItem v-for="(item, index) in data" :data="item" :key="index"></CardListItem>
</div> </div>
<!-- <div class="resource-video-item" v-for="item in data" :key="item.id">{{ item.title }}</div> --> <el-empty v-else description="description" />
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
</template> </template>
<style lang="scss"> <style lang="scss">
.card-list{ .card-list {
background: #FAFAFA; background: #fafafa;
padding: 20px; padding: 20px;
display: flex; display: flex;
} }
......
<script setup lang="ts"> <script setup lang="ts">
import UploadAuth from '@/components/base/UploadAuth.vue' import { createCourse, updateCourse, getCategoryList, getCourseDetails } from '../api'
import { ElMessage } from 'element-plus'
import UploadAuth from '@/components/base/UploadAuth.vue'
import type { FormInstance, FormRules } from 'element-plus'
// 路由
const router = useRouter()
const ruleFormRef = ref<FormInstance>()
// 判断编辑还是新建
// form表单 // form表单
const form = reactive({ videoFile: '', videoName: '', videoType: '', zsd: '', aliyun_video_id: '', weight: '' }) const form = reactive({
const rules = {} source: '2',
const data = [ url: 'http://123.pdf',
{ name: '',
value: '1', classification: '',
label: 'Level one 1', knowledge_points: ''
children: [ })
{ const rules = reactive<FormRules>({
value: '1-1', url: [{ required: true, message: '请选择课件文件', trigger: 'change' }],
label: 'Level two 1-1', name: [{ required: true, message: '请输入课件名称', trigger: 'blur' }],
children: [ classification: [{ required: true, message: '请选择课件分类', trigger: 'change' }]
{ })
value: '1-1-1',
label: 'Level three 1-1-1', // 协议
}, const protocol = ref(false)
], // 上传视频过程返回值
}, const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' })
], // 上传视频回调
}, const uploadProgress = (res: any) => {
{
value: '2',
label: 'Level one 2',
children: [
{
value: '2-1',
label: 'Level two 2-1',
children: [
{
value: '2-1-1',
label: 'Level three 2-1-1',
},
],
},
{
value: '2-2',
label: 'Level two 2-2',
children: [
{
value: '2-2-1',
label: 'Level three 2-2-1',
},
],
},
],
},
{
value: '3',
label: 'Level one 3',
children: [
{
value: '3-1',
label: 'Level two 3-1',
children: [
{
value: '3-1-1',
label: 'Level three 3-1-1',
},
],
},
{
value: '3-2',
label: 'Level two 3-2',
children: [
{
value: '3-2-1',
label: 'Level three 3-2-1',
},
],
},
],
},
]
// 协议
const protocol = ref(false)
// 上传视频过程返回值
const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' })
// 上传视频回调
const uploadProgress = (res: any) => {
videoUpload.progress = res videoUpload.progress = res
} }
const upload = (res: any) => { const upload = (res: any) => {
const { code, msg, name } = res const { code, msg, name } = res
videoUpload.code = code videoUpload.code = code
videoUpload.msg = msg videoUpload.msg = msg
videoUpload.fileName = name videoUpload.fileName = name
videoUpload.progress = 0 videoUpload.progress = 0
}
// 下拉选择tree 课件分类
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
let selectTree = $ref([])
getCategoryList({ type: 'tree' }).then(res => {
selectTree = res.data
})
const handleConfirm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
if (!protocol.value) {
ElMessage('请勾选用户协议')
return
}
const id = router.currentRoute.value.query.id as string
if (id !== '' && id) {
const params = Object.assign({ id: id }, form)
updateCourse(params).then((res: any) => {
if (res.code === 0) {
ElMessage({ message: '更新成功', type: 'success' })
setTimeout(() => {
router.push({
path: '/resource/courseware'
})
}, 1000)
} }
})
} else {
createCourse(form).then((res: any) => {
if (res.code === 0) {
ElMessage({ message: '创建成功', type: 'success' })
setTimeout(() => {
router.push({
path: '/resource/courseware'
})
}, 1000)
}
})
}
} else {
ElMessage('请完善信息')
console.log('error submit!', fields)
}
})
}
const statusData = reactive<{
department_public: string
platform_public: string
status: string
organ_id_name: string
organ_id: string
created_operator_name: string
belong_operator_name: string
created_time: string
updated_time: string
}>({
department_public: '0',
platform_public: '0',
status: '0',
organ_id_name: '',
organ_id: '',
created_operator_name: '',
belong_operator_name: '',
created_time: '',
updated_time: ''
})
const id = router.currentRoute.value.query.id as string
if (id !== '' && id) {
getCourseDetails({ id: id }).then(res => {
const key = ['name', 'classification', 'knowledge_points', 'cover', 'source_id']
key.forEach(item => {
form[item] = res.data[item]
})
const {
department_public,
platform_public,
status,
organ_id_name,
organ_id,
created_operator_name,
belong_operator_name,
created_time,
updated_time
} = res.data
statusData.department_public = department_public
statusData.platform_public = platform_public
statusData.status = status
statusData.organ_id_name = organ_id_name
statusData.organ_id = organ_id
statusData.created_operator_name = created_operator_name
statusData.belong_operator_name = belong_operator_name
statusData.created_time = created_time
statusData.updated_time = updated_time
})
}
</script> </script>
<template> <template>
...@@ -99,8 +148,8 @@ ...@@ -99,8 +148,8 @@
<div class="btn-item">资源下线</div> <div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div> <div class="btn-item">更改负责人</div>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" style="width: 70%"> <el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="课件文件:" prop="course_name"> <el-form-item label="课件文件:" prop="url">
<div> <div>
<div class="upload-video"> <div class="upload-video">
<div class="upload-btn"> <div class="upload-btn">
...@@ -121,19 +170,21 @@ ...@@ -121,19 +170,21 @@
<div class="tips">课件支持格式包含:doc docx xls xlsx pdf ppt pptx,大小不超过50M</div> <div class="tips">课件支持格式包含:doc docx xls xlsx pdf ppt pptx,大小不超过50M</div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="课件名称:" prop="course_name"> <el-form-item label="课件名称:" prop="name">
<el-input v-model="form.videoName" /> <el-input v-model="form.name" />
</el-form-item>
<el-form-item label="课件分类:" prop="course_name">
<el-tree-select style="width:100%" v-model="form.videoType" :data="data" />
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;知识点:" prop="course_name"> <el-form-item label="课件分类:" prop="classification">
<el-input <el-tree-select
v-model="form.zsd" style="width: 100%"
:rows="2" :props="defaultProps"
type="textarea" v-model="form.classification"
:data="selectTree"
placeholder="请选择课件分类"
/> />
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;知识点:" prop="knowledge_points">
<el-input v-model="form.knowledge_points" :rows="2" type="textarea" />
</el-form-item>
</el-form> </el-form>
<div class="protocol-box"> <div class="protocol-box">
<el-checkbox v-model="protocol" size="large"> <el-checkbox v-model="protocol" size="large">
...@@ -141,65 +192,65 @@ ...@@ -141,65 +192,65 @@
</el-checkbox> </el-checkbox>
</div> </div>
<div class="btn-box"> <div class="btn-box">
<div class="confirm">保存</div> <div class="confirm" @click="handleConfirm(ruleFormRef)">保存</div>
<div class="cancel">取消</div> <div class="cancel">取消</div>
</div> </div>
</AppCard> </AppCard>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.tips{ .tips {
font-size: 12px; font-size: 12px;
line-height: 100%; line-height: 100%;
color: #999999; color: #999999;
margin-top: 8px; margin-top: 8px;
} }
.tool-btn-box{ .tool-btn-box {
display: flex; display: flex;
justify-content: right; justify-content: right;
.btn-item{ .btn-item {
width: 127px; width: 127px;
line-height: 36px; line-height: 36px;
background: #AA1941; background: #aa1941;
border-radius: 20px; border-radius: 20px;
margin-right: 10px; margin-right: 10px;
font-size: 14px; font-size: 14px;
color: #FFFFFF; color: #ffffff;
text-align: center; text-align: center;
} }
} }
.demo-progress{ .demo-progress {
width: 350px; width: 350px;
} }
.video-cover{ .video-cover {
display: flex; display: flex;
.img-box{ .img-box {
width: 208px; width: 208px;
height: 130px; height: 130px;
border-radius: 4px; border-radius: 4px;
background: #F7F7F7; background: #f7f7f7;
font-size: 20px; font-size: 20px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
img{ img {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;
} }
} }
.video-cover_right{ .video-cover_right {
margin-left: 20px; margin-left: 20px;
.list{ .list {
.item{ .item {
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 12px; margin-top: 12px;
img{ img {
width: 9px; width: 9px;
display: block; display: block;
margin-right: 5px; margin-right: 5px;
} }
.text{ .text {
font-size: 12px; font-size: 12px;
color: #999999; color: #999999;
line-height: 100%; line-height: 100%;
...@@ -208,29 +259,29 @@ ...@@ -208,29 +259,29 @@
} }
} }
} }
.swiper-box{ .swiper-box {
min-width: 660px; min-width: 660px;
margin-top: 20px; margin-top: 20px;
padding: 0 40px; padding: 0 40px;
position: relative; position: relative;
.arrow{ .arrow {
position: absolute; position: absolute;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
font-size: 30px; font-size: 30px;
color: #D5D5D5; color: #d5d5d5;
cursor: pointer; cursor: pointer;
&.left{ &.left {
left: 0; left: 0;
} }
&.right{ &.right {
right: 10px; right: 10px;
} }
} }
.cover-list{ .cover-list {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
.cover-list_item{ .cover-list_item {
display: block; display: block;
width: 155px; width: 155px;
height: 96px; height: 96px;
...@@ -240,26 +291,26 @@ ...@@ -240,26 +291,26 @@
} }
} }
} }
:deep(.el-carousel__indicators--horizontal){ :deep(.el-carousel__indicators--horizontal) {
display: none; display: none;
} }
.protocol-box{ .protocol-box {
font-size: 14px; font-size: 14px;
line-height: 24px; line-height: 24px;
padding-left: 90px; padding-left: 90px;
padding-top: 20px; padding-top: 20px;
color: #666666; color: #666666;
span{ span {
color: #AA1941; color: #aa1941;
} }
} }
.btn-box{ .btn-box {
display: flex; display: flex;
margin-top: 20px; margin-top: 20px;
margin-left: 90px; margin-left: 90px;
.confirm{ .confirm {
width: 94px; width: 94px;
background: #AA1941; background: #aa1941;
border-radius: 20px; border-radius: 20px;
text-align: center; text-align: center;
line-height: 36px; line-height: 36px;
...@@ -267,42 +318,42 @@ ...@@ -267,42 +318,42 @@
margin-right: 26px; margin-right: 26px;
cursor: pointer; cursor: pointer;
} }
.cancel{ .cancel {
width: 94px; width: 94px;
line-height: 36px; line-height: 36px;
border: 1px solid #AA1941; border: 1px solid #aa1941;
border-radius: 20px; border-radius: 20px;
text-align: center; text-align: center;
color: #AA1941; color: #aa1941;
cursor: pointer; cursor: pointer;
} }
} }
.upload-video{ .upload-video {
display: flex; display: flex;
align-items: center; align-items: center;
.upload-btn{ .upload-btn {
position: relative; position: relative;
width: 94px; width: 94px;
line-height: 36px; line-height: 36px;
background: rgba(250, 223, 230, 0.39); background: rgba(250, 223, 230, 0.39);
border: 1px solid #AA1941; border: 1px solid #aa1941;
border-radius: 20px; border-radius: 20px;
font-size: 14px; font-size: 14px;
color: #AA1941; color: #aa1941;
margin-right: 30px; margin-right: 30px;
text-align: center; text-align: center;
} }
.video-info{ .video-info {
display: flex; display: flex;
.name{ .name {
color: #333333; color: #333333;
font-size: 16px; font-size: 16px;
line-height: 100%; line-height: 100%;
} }
.view{ .view {
font-size: 16px; font-size: 16px;
line-height: 100%; line-height: 100%;
color: #399EE8; color: #399ee8;
margin-left: 20px; margin-left: 20px;
cursor: pointer; cursor: pointer;
} }
......
...@@ -7,8 +7,8 @@ export function getVideoList(params?: { type?: string; page?: number; page_size? ...@@ -7,8 +7,8 @@ export function getVideoList(params?: { type?: string; page?: number; page_size?
// 获取字典列表 // 获取字典列表
export function getDictionaryList(params?: { export function getDictionaryList(params?: {
name?: string name?: string
key?: number key?: string
status?: boolean status?: string
created_time_start?: string created_time_start?: string
created_time_end?: string created_time_end?: string
page?: number page?: number
......
...@@ -18,6 +18,7 @@ const listOptions = $computed(() => { ...@@ -18,6 +18,7 @@ const listOptions = $computed(() => {
remote: { remote: {
httpRequest: getDictionaryList, httpRequest: getDictionaryList,
params: { params: {
status: '',
type: '', type: '',
created_time_start: '', created_time_start: '',
created_time_end: '' created_time_end: ''
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论