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

课件资源部分开发

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