提交 5d08f579 authored 作者: lihuihui's avatar lihuihui

开发课程,教案,其他内容

上级 b4673484
...@@ -134,6 +134,7 @@ ...@@ -134,6 +134,7 @@
"useDisplayMedia": true, "useDisplayMedia": true,
"useDocumentVisibility": true, "useDocumentVisibility": true,
"useDraggable": true, "useDraggable": true,
"useDropZone": true,
"useElementBounding": true, "useElementBounding": true,
"useElementByPoint": true, "useElementByPoint": true,
"useElementHover": true, "useElementHover": true,
......
...@@ -135,6 +135,7 @@ declare global { ...@@ -135,6 +135,7 @@ declare global {
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable'] const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover'] const useElementHover: typeof import('@vueuse/core')['useElementHover']
......
...@@ -2,10 +2,8 @@ import { getCategoryList } from '@/api/base' ...@@ -2,10 +2,8 @@ import { getCategoryList } from '@/api/base'
export function useGetCategoryList() { export function useGetCategoryList() {
const list = ref([]) const list = ref([])
onMounted(() => {
getCategoryList({ type: 'tree' }).then((res: any) => { getCategoryList({ type: 'tree' }).then((res: any) => {
list.value = res.data list.value = res.data
}) })
})
return { list } return { list }
} }
\ No newline at end of file
...@@ -3,12 +3,9 @@ import { getProjectList } from '@/api/base' ...@@ -3,12 +3,9 @@ import { getProjectList } from '@/api/base'
export function useProjectList(id?: string) { export function useProjectList(id?: string) {
const list = ref([]) const list = ref([])
const members = ref([]) const members = ref([])
// onMounted(() => {
getProjectList({ organization_id: id || '' }).then((res: any) => { getProjectList({ organization_id: id || '' }).then((res: any) => {
list.value = res.data.departments list.value = res.data.departments
console.log(res.data, 'res.data')
members.value = res.data.members members.value = res.data.members
}) })
// })
return { list, members } return { list, members }
} }
\ No newline at end of file
...@@ -14,25 +14,29 @@ export function getCourseList(params: { ...@@ -14,25 +14,29 @@ export function getCourseList(params: {
// 创建 // 创建
export function createCourse(data: { export function createCourse(data: {
url: string
name: string name: string
source: string source: string
classification: string classification: string
knowledge_points: string knowledge_points?: string
url: string
type: string
size: string
}) { }) {
return httpRequest.post('/api/resource/v1/resource/courseware/create', data) return httpRequest.post('/api/resource/v1/resource/courseware/create', data)
} }
// 更新课件 // 更新课件
export function updateCourse(data: { export function updateCourse(data: {
id: string id: string,
url: string
name: string name: string
source: string source: string
classification: string classification: string
knowledge_points: string knowledge_points?: string
url: string
type: string
size: string
}) { }) {
return httpRequest.post('/v1/resource/courseware/update', data) return httpRequest.post('/api/resource/v1/resource/courseware/update', data)
} }
// 获取课件详情 // 获取课件详情
export function getCourseDetails(params: { id: string }) { export function getCourseDetails(params: { id: string }) {
......
<script setup lang="ts"> <script setup lang="ts">
import { setDepartment, setPlatform, setStatus, setBelong } from '../api' import { setDepartment, setPlatform, setStatus, setBelong } from '../api'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
console.log(store)
const router = useRouter() const router = useRouter()
const route = useRoute()
const props = defineProps(['data']) const props = defineProps(['data'])
const path = router.currentRoute.value.path const path = route.path
console.log(path, 'path')
// 详情id // 详情id
const id = router.currentRoute.value.query.id as string const id = route.query.id as string
// 设置部门共享 // 设置部门共享
const handleDepartment = () => { const handleDepartment = () => {
ElMessageBox.confirm( ElMessageBox.confirm(
......
...@@ -63,7 +63,7 @@ const props = defineProps({ ...@@ -63,7 +63,7 @@ const props = defineProps({
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons" /> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">知识点</div> <div class="name">知识点</div>
<div class="textarea-box"> <div class="textarea-box" style="min-width:500px;">
{{ props.data?.knowledge_points || '暂无' }} {{ props.data?.knowledge_points || '暂无' }}
</div> </div>
</div> </div>
......
<script setup lang="ts"> <script setup lang="ts">
import { getCourseList } 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 } from '@element-plus/icons-vue'
import { useMapStore } from '@/stores/map' import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
const store = useMapStore()
const appList = ref()
// 列表切换
const isCard = ref(true)
// 资源出处 tab触发 const store = useMapStore()
const tabValue = ref('1')
const tabChange = () => {
appList.value.refetch()
}
// 筛选项目列表 // 筛选项目列表
let { list: projectList } = useProjectList() let { list: projectList } = useProjectList()
...@@ -28,27 +19,31 @@ const defaultProps = { ...@@ -28,27 +19,31 @@ const defaultProps = {
value: 'id' value: 'id'
} }
const appList = ref()
// 列表切换
const isCard = ref(true)
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value.refetch()
}
const listOptions = $computed(() => { const listOptions = $computed(() => {
return { return {
remote: { remote: {
httpRequest: getCourseList, httpRequest: getCourseList,
params: { tab: tabValue, title: '', status: '', authorized: '', classification: '' }, params: { tab: tabValue, status: '', authorized: '' }
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
}, },
filters: [ filters: [
{ {
type: 'select', type: 'select',
prop: 'audit_status', prop: 'audit_status',
label: '状态', label: '状态',
options: store.mapList?.filter((item: any) => item.key === 'system_status')[0]?.values options: store.getMapValuesByKey('system_status')
}, },
{ type: 'select', prop: 'authorized', label: '项目', options: projectList.value, labelKey: 'name', valueKey: 'id' }, { type: 'select', prop: 'authorized', label: '项目', options: projectList.value, labelKey: 'name', valueKey: 'id' },
{ prop: 'classification', label: '类别', slots: 'filter-type' }, { prop: 'classification', label: '类别', slots: 'filter-type' }
{ prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
], ],
columns: [ columns: [
{ label: '课件标题', prop: 'name' }, { label: '课件标题', prop: 'name' },
...@@ -82,9 +77,6 @@ const listOptions = $computed(() => { ...@@ -82,9 +77,6 @@ const listOptions = $computed(() => {
</div> </div>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #header-aside></template> <template #header-aside></template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #filter-type="{ params }"> <template #filter-type="{ params }">
<el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" /> <el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" />
</template> </template>
......
<script setup lang="ts"> <script setup lang="ts">
import { createCourse, updateCourse, getCourseDetails } from '../api' import AppUpload from '@/components/base/AppUpload.vue'
import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import UploadAuth from '@/components/base/UploadAuth.vue' import { createCourse, getCourseDetails, updateCourse } from '../api'
import type { FormInstance, FormRules } from 'element-plus'
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
import Operation from '../components/Operation.vue'
// 路由 // 路由
const router = useRouter() const router = useRouter()
const ruleFormRef = ref<FormInstance>() const route = useRoute()
// 判断编辑还是新建
// form表单 const id = route.query.id as string
const form = reactive({
source: '2', // is 编辑 新建
url: 'http://123.pdf', const isUpdate = $computed(() => {
name: '', return !!route.query.id
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) if (isUpdate) {
// 上传视频过程返回值 getCourseDetails({ id: id }).then((res: any) => {
const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' }) form = res.data
// 上传视频回调 form.file = [
const uploadProgress = (res: any) => { {
videoUpload.progress = res name: res.data.name,
} url: res.data.url
const upload = (res: any) => { }
const { code, msg, name } = res ]
videoUpload.code = code })
videoUpload.msg = msg
videoUpload.fileName = name
videoUpload.progress = 0
} }
// 下拉选择tree 视频分类 // 下拉选择tree 视频分类
...@@ -47,17 +38,53 @@ const defaultProps = { ...@@ -47,17 +38,53 @@ const defaultProps = {
value: 'id' value: 'id'
} }
const handleConfirm = async (formEl: FormInstance | undefined) => { // form表单
let form: any = $ref({
file: [],
name: '',
source: '2',
classification: '',
knowledge_points: '',
url: '',
type: '',
size: ''
})
// 表单验证
const rules = {
name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
classification: [{ required: true, message: '请选择分类', trigger: 'change' }],
file: [{ required: true, message: '' }]
}
// 新建编辑表单提交
const ruleFormRef = ref<FormInstance>()
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
await formEl.validate((valid, fields) => { await formEl.validate((valid) => {
if (valid) { if (valid) {
if (!protocol.value) { if (!protocol.value) {
ElMessage('请勾选用户协议') ElMessage('请勾选用户协议')
return return
} }
const id = router.currentRoute.value.query.id as string const { url, type, size } = form.file[0]
if (id !== '' && id) { form.url = url
const params = Object.assign({ id: id }, form) form.type = type
form.size = size
const params = Object.assign({}, form)
delete params.file
if (isUpdate) {
params.id = id
updateResources(params)
} else {
createResources(params)
}
} else {
ElMessage('请完善信息')
}
})
}
// 更新
const updateResources = (params: any) => {
updateCourse(params).then((res: any) => { updateCourse(params).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '更新成功', type: 'success' }) ElMessage({ message: '更新成功', type: 'success' })
...@@ -68,8 +95,11 @@ const handleConfirm = async (formEl: FormInstance | undefined) => { ...@@ -68,8 +95,11 @@ const handleConfirm = async (formEl: FormInstance | undefined) => {
}, 1000) }, 1000)
} }
}) })
} else { }
createCourse(form).then((res: any) => {
// 新建
const createResources = (params: any) => {
createCourse(params).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '创建成功', type: 'success' }) ElMessage({ message: '创建成功', type: 'success' })
setTimeout(() => { setTimeout(() => {
...@@ -79,90 +109,22 @@ const handleConfirm = async (formEl: FormInstance | undefined) => { ...@@ -79,90 +109,22 @@ const handleConfirm = async (formEl: FormInstance | undefined) => {
}, 1000) }, 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
})
} }
// 协议
const protocol = ref(false)
</script> </script>
<template> <template>
<AppCard :title="id ? '编辑课件资源' : '新建课件资源'"> <AppCard :title="isUpdate ? '编辑课件资源' : '新建课件资源'">
<div class="tool-btn-box" v-if="$route.query.id"> <Operation :data="form"></Operation>
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%"> <el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="课件文件:" prop="url"> <el-form-item label="课件文件:" prop="file">
<div> <div>
<div class="upload-video"> <div class="upload-video">
<div class="upload-btn"> <div class="upload-box">
本地文件 <AppUpload :limit="1" v-model="form.file"></AppUpload>
<UploadAuth @progress="uploadProgress" @upload="upload"></UploadAuth> <div class="upload-btn">本地文件</div>
</div>
<div class="demo-progress" v-if="videoUpload.code === 1">
<el-progress :percentage="videoUpload.progress" status="success" />
</div>
<div class="error video-info" v-if="videoUpload.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="videoUpload.code === 0">
<div class="name">{{ videoUpload.fileName }}</div>
<div class="view">查阅</div>
</div> </div>
</div> </div>
<div class="tips">课件支持格式包含:doc docx xls xlsx pdf ppt pptx,大小不超过50M</div> <div class="tips">课件支持格式包含:doc docx xls xlsx pdf ppt pptx,大小不超过50M</div>
...@@ -180,7 +142,7 @@ if (id !== '' && id) { ...@@ -180,7 +142,7 @@ if (id !== '' && id) {
placeholder="请选择课件分类" placeholder="请选择课件分类"
/> />
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;知识点:" prop="knowledge_points"> <el-form-item label="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;知识点:">
<el-input v-model="form.knowledge_points" :rows="2" type="textarea" /> <el-input v-model="form.knowledge_points" :rows="2" type="textarea" />
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -190,12 +152,20 @@ if (id !== '' && id) { ...@@ -190,12 +152,20 @@ if (id !== '' && id) {
</el-checkbox> </el-checkbox>
</div> </div>
<div class="btn-box"> <div class="btn-box">
<div class="confirm" @click="handleConfirm(ruleFormRef)">保存</div> <div class="confirm" @click="submitForm(ruleFormRef)">保存</div>
<div class="cancel">取消</div> <div class="cancel">取消</div>
</div> </div>
</AppCard> </AppCard>
</template> </template>
<style lang="scss" scoped> <style lang="scss">
.upload-box {
position: relative;
.app-upload-btn {
position: relative;
z-index: 99;
opacity: 0.0001 !important;
}
}
.tips { .tips {
font-size: 12px; font-size: 12px;
line-height: 100%; line-height: 100%;
...@@ -330,7 +300,9 @@ if (id !== '' && id) { ...@@ -330,7 +300,9 @@ if (id !== '' && id) {
display: flex; display: flex;
align-items: center; align-items: center;
.upload-btn { .upload-btn {
position: relative; position: absolute;
top: 0;
left: 0;
width: 94px; width: 94px;
line-height: 36px; line-height: 36px;
background: rgba(250, 223, 230, 0.39); background: rgba(250, 223, 230, 0.39);
......
<script setup lang="ts"> <script setup lang="ts">
import TopInfo from '../components/TopInfo.vue' import ViewTop from '../components/ViewTop.vue'
import CenterInfo from '../components/CenterInfo.vue' import ViewCenter from '../components/ViewCenter.vue'
import BottomInfo from '../components/BottomInfo.vue' import ViewBottom from '../components/ViewBottom.vue'
import Operation from '../components/Operation.vue' import Operation from '../components/Operation.vue'
import { getCourseDetails } from '../api' import { getCourseDetails } from '../api'
const router = useRouter()
const route = useRoute()
const id = route.query.id as string
const listOptions = { const listOptions = {
columns: [ columns: [
...@@ -25,27 +26,20 @@ const listOptions = { ...@@ -25,27 +26,20 @@ const listOptions = {
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' } { img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
] ]
} }
const id = router.currentRoute.value.query.id as string
// 获取详情 // 获取详情
let courseDetails: any = ref({}) let courseDetails: any = ref({})
getCourseDetails({ id: id }).then(res => { getCourseDetails({ id: id }).then(res => {
courseDetails.value = res.data courseDetails.value = res.data
console.log(courseDetails, '1111111aaaaaaaaa')
}) })
</script> </script>
<template> <template>
<AppCard title="课件资源信息"> <AppCard title="课件资源信息">
<!-- <div class="btn-box"> <Operation :data="courseDetails"></Operation>
<div class="btn-item">部门共享</div> <ViewTop v-if="Object.keys(courseDetails).length" :data="courseDetails"></ViewTop>
<div class="btn-item">平台共享</div> <ViewCenter v-if="Object.keys(courseDetails).length" :data="courseDetails"></ViewCenter>
<div class="btn-item">资源下线</div> <ViewBottom></ViewBottom>
<div class="btn-item">更改负责人</div>
</div> -->
<Operation :data="courseDetails" style="margin-bottom: 20px"></Operation>
<TopInfo v-if="Object.keys(courseDetails).length" :data="courseDetails"></TopInfo>
<CenterInfo v-if="Object.keys(courseDetails).length" :data="courseDetails"></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard> </AppCard>
<AppCard title="课件资源关联使用课程"> <AppCard title="课件资源关联使用课程">
<AppList v-bind="listOptions" ref="appList" stripe> <AppList v-bind="listOptions" ref="appList" stripe>
......
<script setup lang="ts"> <script setup lang="ts">
import { setDepartment, setPlatform, setStatus, setBelong } from '../api' import { setDepartment, setPlatform, setStatus, setBelong } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
const store = useMapStore()
console.log(store)
const router = useRouter() const router = useRouter()
const route = useRoute()
const props = defineProps(['data']) const props = defineProps(['data'])
const path = router.currentRoute.value.path const path = route.path
console.log(path, 'path')
// 详情id // 详情id
const id = router.currentRoute.value.query.id as string const id = route.query.id as string
// 设置部门共享 // 设置部门共享
const handleDepartment = () => { const handleDepartment = () => {
ElMessageBox.confirm( ElMessageBox.confirm(
......
<script setup lang="ts"> <script setup lang="ts">
const props = defineProps({
data: {
type: Object,
require: true
}
})
</script> </script>
<template> <template>
<div class="center-video-box"> <div class="center-video-box">
<div class="file-box"> <div class="file-box">
<embed width="812" height="433" src="https://vocational-store.oss-cn-beijing.aliyuncs.com/files/20210604/7b1bfdec10354da769461199acf55176.pdf"> <embed width="812" height="433" :src="props.data?.url" />
</div> </div>
<!-- <video width="812" height="433" controls> <!-- <video width="812" height="433" controls>
<source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4"> <source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4">
</video> --> </video> -->
<div class="right-statistics"> <div class="right-statistics">
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.project_count }}<span></span></div>
<div class="tag">使用项目/学校</div> <div class="tag">使用项目/学校</div>
</div> </div>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.course_count }}<span></span></div>
<div class="tag">使用课程</div> <div class="tag">使用课程</div>
</div> </div>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.learn_count }}<span></span></div>
<div class="tag">累计学习人次</div> <div class="tag">累计学习人次</div>
</div> </div>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.learn_time_count }}<span></span></div>
<div class="tag">累计学习时长</div> <div class="tag">累计学习时长</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.center-video-box{ .center-video-box {
padding: 20px 0; padding: 20px 0;
display: flex; display: flex;
.right-statistics{ .right-statistics {
flex: 1; flex: 1;
padding-top: 15px; padding-top: 15px;
.stat-item{ .stat-item {
width: 210px; width: 210px;
height: 85px; height: 85px;
background: #B41E47; background: #b41e47;
border-radius: 6px; border-radius: 6px;
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0 auto 20px; margin: 0 auto 20px;
&:nth-child(even){ &:nth-child(even) {
background: #BF9D6B; background: #bf9d6b;
} }
img{ img {
width: 52px; width: 52px;
height: 52px; height: 52px;
display: block; display: block;
margin-left: 18px; margin-left: 18px;
} }
.content{ .content {
margin-left: 18px; margin-left: 18px;
.unit{ .unit {
font-size: 26px; font-size: 26px;
line-height: 100%; line-height: 100%;
color: #FFFFFF; color: #ffffff;
span{ span {
font-size: 12px; font-size: 12px;
line-height: 100%; line-height: 100%;
} }
} }
.tag{ .tag {
font-size: 14px; font-size: 14px;
line-height: 100%; line-height: 100%;
color: #FFFFFF; color: #ffffff;
margin-top: 10px; margin-top: 10px;
} }
} }
......
<script setup lang="ts"> <script setup lang="ts">
import { Files } from '@element-plus/icons-vue' import { Files } from '@element-plus/icons-vue'
const props = defineProps({
data: {
type: Object,
require: true
}
})
</script> </script>
<template> <template>
...@@ -12,53 +18,53 @@ import { Files } from '@element-plus/icons-vue' ...@@ -12,53 +18,53 @@ import { Files } from '@element-plus/icons-vue'
</div> </div>
<div class="info-items"> <div class="info-items">
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">状态</div> <div class="name">状态</div>
<div class="value active">有效</div> <div class="value active">{{ props.data?.status_name }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">创建者</div> <div class="name">创建者</div>
<div class="value">张三丰</div> <div class="value">{{ props.data?.created_operator_name }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">创建时间</div> <div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div> <div class="value">{{ props.data?.created_time }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">更新时间</div> <div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div> <div class="value">{{ props.data?.updated_time }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">课件名称</div> <div class="name">教案名称</div>
<div class="value">基金产品(中)(初级)</div> <div class="value">{{ props.data?.name }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">课件分类</div> <div class="name">教案分类</div>
<div class="value">金融产品数字化营销-黄老师</div> <div class="value">{{ props.data?.classification_name || '暂无' }}</div>
</div> </div>
</div> </div>
<div class="i-items" style="align-items: flex-start;"> <div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">知识点</div> <div class="name">知识点</div>
<div class="textarea-box"> <div class="textarea-box" style="min-width:500px;">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某 {{ props.data?.knowledge_points || '暂无' }}
</div> </div>
</div> </div>
</div> </div>
...@@ -66,19 +72,19 @@ import { Files } from '@element-plus/icons-vue' ...@@ -66,19 +72,19 @@ import { Files } from '@element-plus/icons-vue'
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-info{ .video-info {
background: #F7F7F7; background: #f7f7f7;
margin-top: 20px; margin-top: 20px;
padding: 20px; padding: 20px;
display: flex; display: flex;
.video-img{ .video-img {
// width: 211px; // width: 211px;
padding: 0 30px; padding: 0 30px;
.item-info-icon{ .item-info-icon {
font-size: 100px; font-size: 100px;
color: #aa1941; color: #aa1941;
} }
.name{ .name {
font-size: 16px; font-size: 16px;
line-height: 100%; line-height: 100%;
color: #666666; color: #666666;
...@@ -86,40 +92,40 @@ import { Files } from '@element-plus/icons-vue' ...@@ -86,40 +92,40 @@ import { Files } from '@element-plus/icons-vue'
text-align: center; text-align: center;
} }
} }
.info-items{ .info-items {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding-left: 12px; padding-left: 12px;
.i-items{ .i-items {
display: flex; display: flex;
align-items: center; align-items: center;
height: fit-content; height: fit-content;
margin-right: 80px; margin-right: 80px;
margin-bottom: 30px; margin-bottom: 30px;
.textarea-box{ .textarea-box {
padding: 18px 18px 51px; padding: 18px 18px 51px;
background: #FFFFFF; background: #ffffff;
border-radius: 4px; border-radius: 4px;
font-size: 16px; font-size: 16px;
line-height: 24px; line-height: 24px;
color: #505050; color: #505050;
margin-top: 14px; margin-top: 14px;
} }
.text-box{ .text-box {
margin-left: 16px; margin-left: 16px;
.name{ .name {
font-size: 14px; font-size: 14px;
line-height: 100%; line-height: 100%;
color: #999999; color: #999999;
} }
.value{ .value {
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
line-height: 100%; line-height: 100%;
color: #333333; color: #333333;
margin-top: 8px; margin-top: 8px;
&.active{ &.active {
color: #1AB226; color: #1ab226;
} }
} }
} }
......
<script setup lang="ts"> <script setup lang="ts">
import { getLessonList } from '../api' import { getLessonList } 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 } from '@element-plus/icons-vue'
import { useMapStore } from '@/stores/map' import { useMapStore } from '@/stores/map'
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
const store = useMapStore() const store = useMapStore()
const appList = ref() const appList = ref()
const isCard = ref(true) const isCard = ref(true)
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value.refetch()
}
// 筛选项目列表 // 筛选项目列表
let { list: projectList } = useProjectList() let { list: projectList } = useProjectList()
// 下拉选择tree 视频分类 // 下拉选择tree 视频分类
...@@ -26,15 +22,17 @@ const defaultProps = { ...@@ -26,15 +22,17 @@ const defaultProps = {
value: 'id' value: 'id'
} }
// 资源出处 tab触发
const tabValue = ref('1')
const tabChange = () => {
appList.value.refetch()
}
const listOptions = $computed(() => { const listOptions = $computed(() => {
return { return {
remote: { remote: {
httpRequest: getLessonList, httpRequest: getLessonList,
params: { tab: tabValue, status: '', authorized: '' }, params: { tab: tabValue, status: '', authorized: '' }
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
}, },
filters: [ filters: [
{ {
...@@ -44,9 +42,7 @@ const listOptions = $computed(() => { ...@@ -44,9 +42,7 @@ const listOptions = $computed(() => {
options: store.getMapValuesByKey('system_status') options: store.getMapValuesByKey('system_status')
}, },
{ type: 'select', prop: 'authorized', label: '项目', options: projectList.value, labelKey: 'name', valueKey: 'id' }, { type: 'select', prop: 'authorized', label: '项目', options: projectList.value, labelKey: 'name', valueKey: 'id' },
{ prop: 'classification', label: '类别', slots: 'filter-type' }, { prop: 'classification', label: '类别', slots: 'filter-type' }
{ prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
], ],
columns: [ columns: [
{ label: '教案标题', prop: 'name' }, { label: '教案标题', prop: 'name' },
...@@ -81,9 +77,6 @@ const listOptions = $computed(() => { ...@@ -81,9 +77,6 @@ const listOptions = $computed(() => {
</div> </div>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #header-aside></template> <template #header-aside></template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #filter-type="{ params }"> <template #filter-type="{ params }">
<el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" /> <el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" />
</template> </template>
......
...@@ -8,8 +8,27 @@ import Operation from '../components/Operation.vue' ...@@ -8,8 +8,27 @@ import Operation from '../components/Operation.vue'
// 路由 // 路由
const router = useRouter() const router = useRouter()
const route = useRoute()
const id = router.currentRoute.value.query.id as string const id = route.query.id as string
// is 编辑 新建
const isUpdate = $computed(() => {
return !!route.query.id
})
// 编辑数据回显
if (isUpdate) {
getLessonDetails({ id: id }).then((res: any) => {
form = res.data
form.file = [
{
name: res.data.name,
url: res.data.url
}
]
})
}
// 下拉选择tree 视频分类 // 下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList() let { list: selectTree } = useGetCategoryList()
...@@ -20,7 +39,7 @@ const defaultProps = { ...@@ -20,7 +39,7 @@ const defaultProps = {
} }
// form表单 // form表单
const form: any = reactive({ let form: any = $ref({
file: [], file: [],
name: '', name: '',
source: '2', source: '2',
...@@ -40,23 +59,32 @@ const rules = { ...@@ -40,23 +59,32 @@ const rules = {
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const submitForm = async (formEl: FormInstance | undefined) => { const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
await formEl.validate((valid, fields) => { await formEl.validate((valid) => {
console.log(valid, 'valid', fields)
if (valid) { if (valid) {
if (!protocol.value) { if (!protocol.value) {
ElMessage('请勾选用户协议') ElMessage('请勾选用户协议')
return return
} }
const id = router.currentRoute.value.query.id as string const { url, type, size } = form.file[0]
const formFile = form.file[0] form.url = url
form.url = formFile.url form.type = type
form.type = formFile.type form.size = size
form.size = formFile.size
const params = Object.assign({}, form) const params = Object.assign({}, form)
delete params.file delete params.file
if (id !== '' && id) { if (isUpdate) {
params.id = id params.id = id
console.log(params, 'paramsparams') updateResources(params)
} else {
createResources(params)
}
} else {
ElMessage('请完善信息')
}
})
}
// 更新
const updateResources = (params: any) => {
updateLessonPlan(params).then((res: any) => { updateLessonPlan(params).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '更新成功', type: 'success' }) ElMessage({ message: '更新成功', type: 'success' })
...@@ -67,7 +95,10 @@ const submitForm = async (formEl: FormInstance | undefined) => { ...@@ -67,7 +95,10 @@ const submitForm = async (formEl: FormInstance | undefined) => {
}, 1000) }, 1000)
} }
}) })
} else { }
// 新建
const createResources = (params: any) => {
createLessonPlan(params).then((res: any) => { createLessonPlan(params).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '创建成功', type: 'success' }) ElMessage({ message: '创建成功', type: 'success' })
...@@ -78,77 +109,15 @@ const submitForm = async (formEl: FormInstance | undefined) => { ...@@ -78,77 +109,15 @@ const submitForm = async (formEl: FormInstance | undefined) => {
}, 1000) }, 1000)
} }
}) })
}
} else {
ElMessage('请完善信息')
console.log('error submit!', fields)
}
})
} }
// 协议 // 协议
const protocol = ref(false) const protocol = ref(false)
// 判断编辑还是新建
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: ''
})
if (id !== '' && id) {
getLessonDetails({ id: id }).then(res => {
const key = ['name', 'classification', 'knowledge_points', 'url', 'size', 'type']
key.forEach(item => {
form[item] = res.data[item]
})
form.file = [
{
name: res.data.name,
url: res.data.url
}
]
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>
<AppCard title="新建教案资源"> <AppCard :title="isUpdate ? '编辑教案资源' : '新建教案资源'">
<Operation :data="statusData" style="margin-bottom: 20px"></Operation> <Operation :data="form"></Operation>
<el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%"> <el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="教案文件:" prop="file"> <el-form-item label="教案文件:" prop="file">
<div> <div>
......
<script setup lang="ts"> <script setup lang="ts">
import TopInfo from '../components/TopInfo.vue' import ViewTop from '../components/ViewTop.vue'
import CenterInfo from '../components/CenterInfo.vue' import ViewCenter from '../components/ViewCenter.vue'
import BottomInfo from '../components/BottomInfo.vue' import ViewBottom from '../components/ViewBottom.vue'
import Operation from '../components/Operation.vue' import Operation from '../components/Operation.vue'
import { getLessonDetails } from '../api' import { getLessonDetails } from '../api'
const router = useRouter()
const route = useRoute()
const listOptions = { const listOptions = {
columns: [ columns: [
...@@ -24,7 +25,7 @@ const listOptions = { ...@@ -24,7 +25,7 @@ const listOptions = {
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' } { img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
] ]
} }
const id = router.currentRoute.value.query.id as string const id = route.query.id as string
// 获取详情 // 获取详情
let lessonDetails: any = ref({}) let lessonDetails: any = ref({})
getLessonDetails({ id: id }).then((res: any) => { getLessonDetails({ id: id }).then((res: any) => {
...@@ -34,17 +35,10 @@ getLessonDetails({ id: id }).then((res: any) => { ...@@ -34,17 +35,10 @@ getLessonDetails({ id: id }).then((res: any) => {
<template> <template>
<AppCard title="课件资源信息"> <AppCard title="课件资源信息">
<!-- <div class="btn-box"> <Operation :data="lessonDetails"></Operation>
<div class="btn-item">部门共享</div> <ViewTop :data="lessonDetails"></ViewTop>
<div class="btn-item">平台共享</div> <ViewCenter v-if="Object.keys(lessonDetails).length" :data="lessonDetails"></ViewCenter>
<div class="btn-item">资源下线</div> <ViewBottom></ViewBottom>
<div class="btn-item">更改负责人</div>
</div> -->
<Operation :data="lessonDetails" style="margin-bottom: 20px"></Operation>
<TopInfo :data="lessonDetails"></TopInfo>
<CenterInfo v-if="Object.keys(lessonDetails).length" :data="lessonDetails"></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard> </AppCard>
<AppCard title="课件资源关联使用课程"> <AppCard title="课件资源关联使用课程">
<AppList v-bind="listOptions" ref="appList" stripe> <AppList v-bind="listOptions" ref="appList" stripe>
......
...@@ -11,6 +11,34 @@ export function getOtherList(params?: { ...@@ -11,6 +11,34 @@ export function getOtherList(params?: {
}) { }) {
return httpRequest.get('/api/resource/v1/resource/other-information/list', { params }) return httpRequest.get('/api/resource/v1/resource/other-information/list', { params })
} }
// 创建教案
export function createOther(data: {
name: string
source: string
classification: string
knowledge_points?: string
url: string
type: string
size: string
}) {
return httpRequest.post('/api/resource/v1/resource/other-information/create', data)
}
// 更新教案
export function updateOther(data: {
id: string,
name: string
source: string
classification: string
knowledge_points?: string
url: string
type: string
size: string
}) {
return httpRequest.post('/api/resource/v1/resource/other-information/update', data)
}
// 获取其他资料详情 // 获取其他资料详情
export function getOtherDetails(params: { id: string }) { export function getOtherDetails(params: { id: string }) {
return httpRequest.get('/api/resource/v1/resource/other-information/view', { params }) return httpRequest.get('/api/resource/v1/resource/other-information/view', { params })
......
<script setup lang="ts"> <script setup lang="ts">
const props = defineProps({
data: {
type: Object,
require: true
}
})
</script> </script>
<template> <template>
<div class="center-video-box"> <div class="center-video-box">
<div class="file-box"> <div class="file-box">
<embed width="812" height="433" src="https://vocational-store.oss-cn-beijing.aliyuncs.com/files/20210604/7b1bfdec10354da769461199acf55176.pdf"> <embed width="812" height="433" :src="props.data?.url" />
</div> </div>
<!-- <video width="812" height="433" controls> <!-- <video width="812" height="433" controls>
<source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4"> <source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4">
</video> --> </video> -->
<div class="right-statistics"> <div class="right-statistics">
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.project_count }}<span></span></div>
<div class="tag">使用项目/学校</div> <div class="tag">使用项目/学校</div>
</div> </div>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.course_count }}<span></span></div>
<div class="tag">使用课程</div> <div class="tag">使用课程</div>
</div> </div>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.learn_count }}<span></span></div>
<div class="tag">累计学习人次</div> <div class="tag">累计学习人次</div>
</div> </div>
</div> </div>
<div class="stat-item"> <div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png" />
<div class="content"> <div class="content">
<div class="unit">758<span></span></div> <div class="unit">{{ props.data?.learn_time_count }}<span></span></div>
<div class="tag">累计学习时长</div> <div class="tag">累计学习时长</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.center-video-box{ .center-video-box {
padding: 20px 0; padding: 20px 0;
display: flex; display: flex;
.right-statistics{ .right-statistics {
flex: 1; flex: 1;
padding-top: 15px; padding-top: 15px;
.stat-item{ .stat-item {
width: 210px; width: 210px;
height: 85px; height: 85px;
background: #B41E47; background: #b41e47;
border-radius: 6px; border-radius: 6px;
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0 auto 20px; margin: 0 auto 20px;
&:nth-child(even){ &:nth-child(even) {
background: #BF9D6B; background: #bf9d6b;
} }
img{ img {
width: 52px; width: 52px;
height: 52px; height: 52px;
display: block; display: block;
margin-left: 18px; margin-left: 18px;
} }
.content{ .content {
margin-left: 18px; margin-left: 18px;
.unit{ .unit {
font-size: 26px; font-size: 26px;
line-height: 100%; line-height: 100%;
color: #FFFFFF; color: #ffffff;
span{ span {
font-size: 12px; font-size: 12px;
line-height: 100%; line-height: 100%;
} }
} }
.tag{ .tag {
font-size: 14px; font-size: 14px;
line-height: 100%; line-height: 100%;
color: #FFFFFF; color: #ffffff;
margin-top: 10px; margin-top: 10px;
} }
} }
......
<script setup lang="ts"> <script setup lang="ts">
import { Files } from '@element-plus/icons-vue' import { Files } from '@element-plus/icons-vue'
const props = defineProps({
data: {
type: Object,
require: true
}
})
</script> </script>
<template> <template>
...@@ -12,53 +18,53 @@ import { Files } from '@element-plus/icons-vue' ...@@ -12,53 +18,53 @@ import { Files } from '@element-plus/icons-vue'
</div> </div>
<div class="info-items"> <div class="info-items">
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">状态</div> <div class="name">状态</div>
<div class="value active">有效</div> <div class="value active">{{ props.data?.status_name }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">创建者</div> <div class="name">创建者</div>
<div class="value">张三丰</div> <div class="value">{{ props.data?.created_operator_name }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">创建时间</div> <div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div> <div class="value">{{ props.data?.created_time }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">更新时间</div> <div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div> <div class="value">{{ props.data?.updated_time }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">课件名称</div> <div class="name">其他名称</div>
<div class="value">基金产品(中)(初级)</div> <div class="value">{{ props.data?.name }}</div>
</div> </div>
</div> </div>
<div class="i-items"> <div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">课件分类</div> <div class="name">其他分类</div>
<div class="value">金融产品数字化营销-黄老师</div> <div class="value">{{ props.data?.classification_name || '暂无' }}</div>
</div> </div>
</div> </div>
<div class="i-items" style="align-items: flex-start;"> <div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons"> <img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons" />
<div class="text-box"> <div class="text-box">
<div class="name">知识点</div> <div class="name">知识点</div>
<div class="textarea-box"> <div class="textarea-box" style="min-width:500px;">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某 {{ props.data?.knowledge_points || '暂无' }}
</div> </div>
</div> </div>
</div> </div>
...@@ -66,19 +72,19 @@ import { Files } from '@element-plus/icons-vue' ...@@ -66,19 +72,19 @@ import { Files } from '@element-plus/icons-vue'
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-info{ .video-info {
background: #F7F7F7; background: #f7f7f7;
margin-top: 20px; margin-top: 20px;
padding: 20px; padding: 20px;
display: flex; display: flex;
.video-img{ .video-img {
// width: 211px; // width: 211px;
padding: 0 30px; padding: 0 30px;
.item-info-icon{ .item-info-icon {
font-size: 100px; font-size: 100px;
color: #aa1941; color: #aa1941;
} }
.name{ .name {
font-size: 16px; font-size: 16px;
line-height: 100%; line-height: 100%;
color: #666666; color: #666666;
...@@ -86,40 +92,40 @@ import { Files } from '@element-plus/icons-vue' ...@@ -86,40 +92,40 @@ import { Files } from '@element-plus/icons-vue'
text-align: center; text-align: center;
} }
} }
.info-items{ .info-items {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding-left: 12px; padding-left: 12px;
.i-items{ .i-items {
display: flex; display: flex;
align-items: center; align-items: center;
height: fit-content; height: fit-content;
margin-right: 80px; margin-right: 80px;
margin-bottom: 30px; margin-bottom: 30px;
.textarea-box{ .textarea-box {
padding: 18px 18px 51px; padding: 18px 18px 51px;
background: #FFFFFF; background: #ffffff;
border-radius: 4px; border-radius: 4px;
font-size: 16px; font-size: 16px;
line-height: 24px; line-height: 24px;
color: #505050; color: #505050;
margin-top: 14px; margin-top: 14px;
} }
.text-box{ .text-box {
margin-left: 16px; margin-left: 16px;
.name{ .name {
font-size: 14px; font-size: 14px;
line-height: 100%; line-height: 100%;
color: #999999; color: #999999;
} }
.value{ .value {
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
line-height: 100%; line-height: 100%;
color: #333333; color: #333333;
margin-top: 8px; margin-top: 8px;
&.active{ &.active {
color: #1AB226; color: #1ab226;
} }
} }
} }
......
<script setup lang="ts"> <script setup lang="ts">
import { getOtherList } from '../api' import { getOtherList } 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 } from '@element-plus/icons-vue'
import { useMapStore } from '@/stores/map' import { useMapStore } from '@/stores/map'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
// 下拉选择tree 视频分类 // 下拉选择tree 视频分类
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
const store = useMapStore() const store = useMapStore()
const appList = ref() const appList = ref()
...@@ -33,23 +34,24 @@ const listOptions = $computed(() => { ...@@ -33,23 +34,24 @@ const listOptions = $computed(() => {
return { return {
remote: { remote: {
httpRequest: getOtherList, httpRequest: getOtherList,
params: { tab: tabValue, title: '', status: '', authorized: '', classification: '' }, params: { tab: tabValue, status: '', authorized: '' }
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
}, },
filters: [ filters: [
{ {
type: 'select', type: 'select',
prop: 'audit_status', prop: 'audit_status',
label: '状态', label: '状态',
options: store.mapList?.filter((item: any) => item.key === 'system_status')[0]?.values options: store.getMapValuesByKey('system_status')
},
{
type: 'select',
prop: 'authorized',
label: '项目',
options: projectList.value,
labelKey: 'name',
valueKey: 'id'
}, },
{ type: 'select', prop: 'authorized', label: '项目', options: projectList.value, labelKey: 'name', valueKey: 'id' }, { prop: 'classification', label: '类别', slots: 'filter-type' }
{ prop: 'classification', label: '类别', slots: 'filter-type' },
{ prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
], ],
columns: [ columns: [
{ label: '课件标题', prop: 'name' }, { label: '课件标题', prop: 'name' },
...@@ -77,24 +79,21 @@ const listOptions = $computed(() => { ...@@ -77,24 +79,21 @@ const listOptions = $computed(() => {
<el-icon class="video-head-icon" @click="isCard = !isCard"><Expand /></el-icon> <el-icon class="video-head-icon" @click="isCard = !isCard"><Expand /></el-icon>
</div> </div>
<div class="video-tool-btn"> <div class="video-tool-btn">
<router-link to="/resource/courseware/update"> <router-link to="/resource/other/update">
<el-button type="primary" round>新建课件资源</el-button> <el-button type="primary" round>新建课件资源</el-button>
</router-link> </router-link>
</div> </div>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #header-aside></template> <template #header-aside></template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #filter-type="{ params }"> <template #filter-type="{ params }">
<el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" /> <el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" />
</template> </template>
<template #table-operate="{ row }"> <template #table-operate="{ row }">
<el-space> <el-space>
<router-link :to="`/resource/courseware/update/?id=${row.id}`"> <router-link :to="`/resource/other/update/?id=${row.id}`">
<el-button plain>编辑</el-button> <el-button plain>编辑</el-button>
</router-link> </router-link>
<router-link :to="`/resource/courseware/view/?id=${row.id}`"> <router-link :to="`/resource/other/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>
......
<script setup lang="ts"> <script setup lang="ts">
import TopInfo from '../components/TopInfo.vue' import ViewTop from '../components/ViewTop.vue'
import CenterInfo from '../components/CenterInfo.vue' import ViewCenter from '../components/ViewCenter.vue'
import BottomInfo from '../components/BottomInfo.vue' import ViewBottom from '../components/ViewBottom.vue'
import Operation from '../components/Operation.vue' import Operation from '../components/Operation.vue'
import { getOtherDetails } from '../api' import { getOtherDetails } from '../api'
const router = useRouter()
const route = useRoute()
const id = route.query.id as string
const listOptions = { const listOptions = {
columns: [ columns: [
...@@ -24,7 +27,7 @@ const listOptions = { ...@@ -24,7 +27,7 @@ const listOptions = {
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' } { img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
] ]
} }
const id = router.currentRoute.value.query.id as string
// 获取详情 // 获取详情
let otherDetails: any = ref({}) let otherDetails: any = ref({})
getOtherDetails({ id: id }).then((res: any) => { getOtherDetails({ id: id }).then((res: any) => {
...@@ -34,17 +37,10 @@ getOtherDetails({ id: id }).then((res: any) => { ...@@ -34,17 +37,10 @@ getOtherDetails({ id: id }).then((res: any) => {
<template> <template>
<AppCard title="课件资源信息"> <AppCard title="课件资源信息">
<!-- <div class="btn-box">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div> -->
<Operation :data="otherDetails" style="margin-bottom: 20px"></Operation> <Operation :data="otherDetails" style="margin-bottom: 20px"></Operation>
<ViewTop :data="otherDetails"></ViewTop>
<TopInfo :data="otherDetails"></TopInfo> <ViewCenter v-if="Object.keys(otherDetails).length" :data="otherDetails"></ViewCenter>
<CenterInfo v-if="Object.keys(otherDetails).length" :data="otherDetails"></CenterInfo> <ViewBottom></ViewBottom>
<BottomInfo></BottomInfo>
</AppCard> </AppCard>
<AppCard title="课件资源关联使用课程"> <AppCard title="课件资源关联使用课程">
<AppList v-bind="listOptions" ref="appList" stripe> <AppList v-bind="listOptions" ref="appList" stripe>
......
<script setup lang="ts"> <script setup lang="ts">
import { setDepartment, setPlatform, setStatus, setBelong } from '../api' import { setDepartment, setPlatform, setStatus, setBelong } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
const store = useMapStore()
console.log(store)
const router = useRouter() const router = useRouter()
const route = useRoute()
const props = defineProps(['data']) const props = defineProps(['data'])
const path = router.currentRoute.value.path const path = route.path
console.log(path, 'path')
// 详情id // 详情id
const id = router.currentRoute.value.query.id as string const id = route.query.id as string
// 设置部门共享 // 设置部门共享
const handleDepartment = () => { const handleDepartment = () => {
ElMessageBox.confirm( ElMessageBox.confirm(
......
<script setup lang="ts">
import { getCreateAuth, updateAuth } from '@/api/base'
/**
* upload 上传状态 {code: -1(待上传)0(成功) 1(开始上传) 2(上传失败), msg: '上传信息'}
* progress 上传进度
**/
interface IUpload {
code: number,
name?: string,
msg?: string,
progress?: number,
videoId?: string
}
let uploadData = $ref<IUpload>({ code: -1 })
const emit = defineEmits(['upload'])
const form:any = reactive({
timeout: '',
partSize: '',
parallel: '',
retryCount: '',
retryDuration: '',
region: 'cn-shanghai',
userId: '1303984639806000',
file: null,
authProgress: 0,
uploader: null,
statusText: ''
})
const fileChange = (e:any) => {
form.file = e.target.files[0]
var userData = '{"Vod":{}}'
if (form.uploader) {
form.uploader.stopUpload()
form.authProgress = 0
form.statusText = ""
}
form.uploader = createUploader()
form.uploader.addFile(form.file, null, null, null, userData)
form.uploader.startUpload()
}
const createUploader:any = () => {
const w = window as any
const uploader = new w.AliyunUpload.Vod({
timeout: form.timeout || 60000,
partSize: form.partSize || 1048576,
parallel: form.parallel || 5,
retryCount: form.retryCount || 3,
retryDuration: form.retryDuration || 2,
region: form.region,
userId: form.userId,
// 开始上传
onUploadstarted: function (uploadInfo:any) {
const fileData = JSON.parse(window.localStorage.fileData || '{}')
// 判断有没有上传过
const isFile = !!fileData.sourceId
if (!isFile) {
// 没上传过请求凭证上传
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then((data: any) => {
window.localStorage.fileData = JSON.stringify({
uploadAuth: data.data.upload_auth,
uploadAddress: data.data.upload_address,
videoId: data.data.source_id,
fileName: uploadInfo.file.name,
fileSize: uploadInfo.file.size
})
uploader.setUploadAuthAndAddress(uploadInfo, data.data.upload_auth, data.data.upload_address, data.data.source_id)
})
} else {
// 上传过判断一下上次上传的文件和本次上传的文件一不一样,一样的话继续上传
if (fileData.fileName === uploadInfo.file.name && fileData.fileSize === uploadInfo.file.size) {
uploader.setUploadAuthAndAddress(uploadInfo, fileData.uploadAuth, fileData.uploadAddress, fileData.videoId)
} else {
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then((data: any) => {
uploader.setUploadAuthAndAddress(uploadInfo, data.data.upload_auth, data.data.upload_address, data.data.source_id)
})
}
}
uploadData = {
code: 1,
name: uploadInfo.file.name,
msg: '开始上传'
}
},
// 文件上传成功
onUploadSucceed: function (uploadInfo:any) {
const fileData = window.localStorage.fileData ? JSON.parse(window.localStorage.fileData) : {}
uploadData = {
code: 0,
name: uploadInfo.file.name,
videoId: fileData.videoId,
msg: '上传成功'
}
emit('upload', fileData.videoId)
},
// 文件上传失败
// code:any, message:any
onUploadFailed: function (uploadInfo:any) {
uploadData = {
code: 2,
name: uploadInfo.file.name,
msg: '文件上传失败'
}
},
// 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上
onUploadProgress: function (uploadInfo:any, totalSize:any, progress:any) {
let progressPercent = Math.ceil(progress * 100)
form.authProgress = progressPercent
uploadData.progress = progressPercent
},
// 上传凭证超时
onUploadTokenExpired: function (uploadInfo:any) {
const fileData = JSON.parse(window.localStorage.fileData || '{}')
updateAuth({ source_id: fileData.videoId }).then(({ data }) => {
let uploadAuth = data.UploadAuth
window.localStorage.fileData = JSON.stringify({
uploadAuth: data.data.upload_auth,
uploadAddress: data.data.upload_address,
videoId: data.data.source_id,
fileName: uploadInfo.file.name,
fileSize: uploadInfo.file.size
})
uploader.resumeUploadWithAuth(uploadAuth)
})
}
// 全部文件上传结束
// onUploadEnd: function (uploadInfo: any) {
// console.log(uploadInfo, '上传完成')
// // console.log("onUploadEnd: uploaded all the files")
// }
})
return uploader
}
</script>
<template>
<div>
<div class="upload-video">
<div class="upload-btn">
本地文件
<input type="file" id="fileUpload" @change="fileChange($event)">
</div>
<div class="demo-progress" v-if="uploadData.code === 1">
<el-progress :percentage="uploadData.progress" status="success" />
</div>
<div class="error video-info" v-if="uploadData.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="uploadData.code === 0">
<div class="name">{{ uploadData.name }}</div>
</div>
</div>
<div class="tips">
推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。
</div>
</div>
</template>
<style lang="scss">
.demo-progress {
width: 350px;
}
#fileUpload{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.00001;
}
.tips {
font-size: 12px;
line-height: 100%;
color: #999999;
margin-top: 8px;
}
.upload-video {
display: flex;
align-items: center;
.upload-btn {
position: relative;
width: 94px;
line-height: 36px;
background: rgba(250, 223, 230, 0.39);
border: 1px solid #aa1941;
border-radius: 20px;
font-size: 14px;
color: #aa1941;
margin-right: 30px;
text-align: center;
}
.video-info {
display: flex;
.name {
color: #333333;
font-size: 16px;
line-height: 100%;
}
.view {
font-size: 16px;
line-height: 100%;
color: #399ee8;
margin-left: 20px;
cursor: pointer;
}
}
}
</style>
\ No newline at end of file
<script setup lang="ts"> <script setup lang="ts">
const props = defineProps(['data']) const props = defineProps(['data'])
console.log(props, 'porps')
</script> </script>
<template> <template>
......
<script setup lang="ts"> <script setup lang="ts">
import TopInfo from '../components/TopInfo.vue' import ViewTop from '../components/ViewTop.vue'
import Upload from '../components/Upload.vue' import UploadImg from '../components/UploadImg.vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getVideoPpt, createPpt, updatePpt, deletePpt } from '../api' import { getVideoPpt, createPpt, updatePpt, deletePpt } from '../api'
...@@ -106,7 +106,6 @@ const deleteUploadList = (index: number, url: string) => { ...@@ -106,7 +106,6 @@ const deleteUploadList = (index: number, url: string) => {
// 修改时间码 // 修改时间码
const uploadTimeCode = (ppt_id: string, name: string, url: string) => { const uploadTimeCode = (ppt_id: string, name: string, url: string) => {
console.log(id)
ElMessageBox.prompt('请输入时间码', '提示', { ElMessageBox.prompt('请输入时间码', '提示', {
confirmButtonText: 'OK', confirmButtonText: 'OK',
cancelButtonText: 'Cancel', cancelButtonText: 'Cancel',
...@@ -149,7 +148,7 @@ const deleteCourseware = (ppt_id: string) => { ...@@ -149,7 +148,7 @@ const deleteCourseware = (ppt_id: string) => {
<template> <template>
<el-dialog v-model="dialogFormVisible"> <el-dialog v-model="dialogFormVisible">
<Upload v-model="covers"></Upload> <UploadImg v-model="covers"></UploadImg>
<AppList v-bind="uploadList"> <AppList v-bind="uploadList">
<template #table-cover="{ row }"> <template #table-cover="{ row }">
<img :src="row.url" style="width:100px;display: block;"> <img :src="row.url" style="width:100px;display: block;">
...@@ -171,7 +170,7 @@ const deleteCourseware = (ppt_id: string) => { ...@@ -171,7 +170,7 @@ const deleteCourseware = (ppt_id: string) => {
</template> </template>
</el-dialog> </el-dialog>
<AppCard title="编辑视频资源"> <AppCard title="编辑视频资源">
<TopInfo :data="videoDetails"></TopInfo> <ViewTop :data="videoDetails"></ViewTop>
</AppCard> </AppCard>
<AppCard> <AppCard>
<el-button @click="dialogFormVisible = true" type="primary">关联课件</el-button> <el-button @click="dialogFormVisible = true" type="primary">关联课件</el-button>
......
<script setup lang="ts"> <script setup lang="ts">
import { getVideoList } from '../api' import { getVideoList } from '../api'
import CardListItem from '../components/CardListItem.vue' import CardListItem from '../components/CardListItem.vue'
import { Expand, Search } from '@element-plus/icons-vue' import { Expand } from '@element-plus/icons-vue'
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
// 筛选项目列表 // 筛选项目列表
let { list: projectList } = useProjectList() let { list: projectList } = useProjectList()
// 筛选下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList()
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
// 资源出处 tab触发 // 资源出处 tab触发
const tabValue = ref('1') const tabValue = ref('1')
...@@ -23,21 +33,14 @@ const listOptions = $computed(() => { ...@@ -23,21 +33,14 @@ const listOptions = $computed(() => {
return { return {
remote: { remote: {
httpRequest: getVideoList, httpRequest: getVideoList,
params: { tab: tabValue, title: '', status: '', authorized: '', classification: '' }, params: { tab: tabValue, status: '', authorized: '' }
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
}, },
filters: [ filters: [
{ {
type: 'select', type: 'select',
prop: 'status', prop: 'status',
label: '状态', label: '状态',
options: [ options: store.getMapValuesByKey('system_status')
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
}, },
{ {
type: 'select', type: 'select',
...@@ -47,8 +50,7 @@ const listOptions = $computed(() => { ...@@ -47,8 +50,7 @@ const listOptions = $computed(() => {
labelKey: 'name', labelKey: 'name',
valueKey: 'id' valueKey: 'id'
}, },
{ prop: 'classification', label: '类别', slots: 'filter-type' }, { prop: 'classification', label: '类别', slots: 'filter-type' }
{ prop: 'title', slots: 'filter-search' }
], ],
columns: [ columns: [
{ label: '视频标题', prop: 'name', align: 'center' }, { label: '视频标题', prop: 'name', align: 'center' },
...@@ -64,14 +66,6 @@ const listOptions = $computed(() => { ...@@ -64,14 +66,6 @@ const listOptions = $computed(() => {
] ]
} }
}) })
// 下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList()
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
</script> </script>
<template> <template>
...@@ -97,9 +91,6 @@ const defaultProps = { ...@@ -97,9 +91,6 @@ const defaultProps = {
<template #filter-type="{ params }"> <template #filter-type="{ params }">
<el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" /> <el-tree-select :props="defaultProps" v-model="params.classification" :data="selectTree" />
</template> </template>
<template #filter-search="{ params }">
<el-input v-model="params.title" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #table-operate="{ row }"> <template #table-operate="{ row }">
<el-space> <el-space>
<router-link :to="`/resource/video/update?id=${row.id}`"> <router-link :to="`/resource/video/update?id=${row.id}`">
......
...@@ -2,14 +2,29 @@ ...@@ -2,14 +2,29 @@
import { PictureFilled, ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue' import { PictureFilled, ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import Upload from '../components/Upload.vue' import UploadImg from '../components/UploadImg.vue'
import Operation from '../components/Operation.vue' import Operation from '../components/Operation.vue'
import UploadAuth from '@/components/base/UploadAuth.vue' import UploadVideo from '../components/UploadVideo.vue'
import { getCoverList, createVideo, getVideoDetails, updateVideo } from '../api' import { getCoverList, createVideo, getVideoDetails, updateVideo } from '../api'
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
// 路由 // 路由
const router = useRouter() const router = useRouter()
const route = useRoute()
const id = route.query.id as string
// is 编辑 新建
const isUpdate = $computed(() => {
return !!route.query.id
})
// 编辑数据回显
if (isUpdate) {
getVideoDetails({ id: id }).then((res: any) => {
form.data = res.data
})
}
// 下拉选择tree 视频分类 // 下拉选择tree 视频分类
let { list: selectTree } = useGetCategoryList() let { list: selectTree } = useGetCategoryList()
...@@ -45,12 +60,13 @@ const swiperChange = (type?: string) => { ...@@ -45,12 +60,13 @@ const swiperChange = (type?: string) => {
type === 'prev' ? swiper.value.prev() : swiper.value.next() type === 'prev' ? swiper.value.prev() : swiper.value.next()
} }
const swiperItemHandle = (url: string) => { const swiperItemHandle = (url: string) => {
form.cover = url form.data.cover = url
console.log(url)
} }
// form表单 提交 // form表单
const form = reactive({ name: '', source: '2', classification: '', knowledge_points: '', cover: '', source_id: '' }) let form = reactive({
data: { name: '', source: '2', classification: '', knowledge_points: '', cover: '', source_id: '' }
})
// 表单验证 // 表单验证
const rules = { const rules = {
name: [{ required: true, message: '请输入标题', trigger: 'blur' }], name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
...@@ -60,15 +76,26 @@ const rules = { ...@@ -60,15 +76,26 @@ const rules = {
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const submitForm = async (formEl: FormInstance | undefined) => { const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
await formEl.validate((valid, fields) => { await formEl.validate(valid => {
if (valid) { if (valid) {
if (!protocol.value) { if (!protocol.value) {
ElMessage('请勾选用户协议') ElMessage('请勾选用户协议')
return return
} }
const id = router.currentRoute.value.query.id as string if (isUpdate) {
if (id !== '' && id) { updateResources()
const params = Object.assign({ id: id }, form) } else {
createResources()
}
} else {
ElMessage('请完善信息')
}
})
}
// 更新
const updateResources = () => {
const params = Object.assign({ id: id }, form.data)
updateVideo(params).then((res: any) => { updateVideo(params).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '更新成功', type: 'success' }) ElMessage({ message: '更新成功', type: 'success' })
...@@ -79,8 +106,11 @@ const submitForm = async (formEl: FormInstance | undefined) => { ...@@ -79,8 +106,11 @@ const submitForm = async (formEl: FormInstance | undefined) => {
}, 1000) }, 1000)
} }
}) })
} else { }
createVideo(form).then((res: any) => {
// 新建
const createResources = () => {
createVideo(form.data).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '创建成功', type: 'success' }) ElMessage({ message: '创建成功', type: 'success' })
setTimeout(() => { setTimeout(() => {
...@@ -90,129 +120,48 @@ const submitForm = async (formEl: FormInstance | undefined) => { ...@@ -90,129 +120,48 @@ const submitForm = async (formEl: FormInstance | undefined) => {
}, 1000) }, 1000)
} }
}) })
}
} else {
ElMessage('请完善信息')
console.log('error submit!', fields)
}
})
} }
// 协议勾选 // 协议勾选
const protocol = ref(false) 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, videoId } = res
videoUpload.code = code
videoUpload.msg = msg
videoUpload.fileName = name
videoUpload.progress = 0
form.source_id = videoId
}
// 判断编辑还是新建 // 上传视频成功
const id = router.currentRoute.value.query.id as string const uploadVideo = (id: string) => {
const statusData = reactive<{ form.data.source_id = id
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: ''
})
if (id !== '' && id) {
getVideoDetails({ 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>
<AppCard title="新建视频资源"> <AppCard title="新建视频资源">
<Operation :data="statusData" style="margin-bottom: 20px"></Operation> <Operation :data="form.data"></Operation>
<el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%"> <el-form ref="ruleFormRef" :model="form.data" :rules="rules" style="width: 70%">
<el-form-item label="视频文件:" prop="source_id" v-if="id == '' || id == undefined"> <el-form-item label="视频文件:" prop="source_id" v-if="!isUpdate">
<div> <UploadVideo @upload="uploadVideo"></UploadVideo>
<div class="upload-video">
<div class="upload-btn">
本地文件
<UploadAuth @progress="uploadProgress" @upload="upload"></UploadAuth>
</div>
<div class="demo-progress" v-if="videoUpload.code === 1">
<el-progress :percentage="videoUpload.progress" status="success" />
</div>
<div class="error video-info" v-if="videoUpload.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="videoUpload.code === 0">
<div class="name">{{ videoUpload.fileName }}</div>
<!-- <div class="view">查阅</div> -->
</div>
</div>
<div class="tips">
推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。
</div>
</div>
</el-form-item> </el-form-item>
<el-form-item label="视频名称:" prop="name"> <el-form-item label="视频名称:" prop="name">
<el-input v-model="form.name" /> <el-input v-model="form.data.name" />
</el-form-item> </el-form-item>
<el-form-item label="视频分类:" prop="classification"> <el-form-item label="视频分类:" prop="classification">
<el-tree-select :props="defaultProps" style="width: 100%" v-model="form.classification" :data="selectTree" /> <el-tree-select
:props="defaultProps"
style="width: 100%"
v-model="form.data.classification"
:data="selectTree"
/>
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;知识点:"> <el-form-item label="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;知识点:">
<el-input v-model="form.knowledge_points" :rows="2" type="textarea" /> <el-input v-model="form.data.knowledge_points" :rows="2" type="textarea" />
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;视频封面:"> <el-form-item label="&nbsp;&nbsp;视频封面:">
<div class="video-cover"> <div class="video-cover">
<div class="img-box"> <div class="img-box">
<el-icon :size="50" color="#ccc" v-if="form.cover == ''"> <el-icon :size="50" color="#ccc" v-if="form.data.cover == ''">
<PictureFilled></PictureFilled> <PictureFilled></PictureFilled>
</el-icon> </el-icon>
<img :src="form.cover" v-else /> <img :src="form.data.cover" v-else />
</div> </div>
<div class="video-cover_right"> <div class="video-cover_right">
<Upload v-model="form.cover"></Upload> <UploadImg v-model="form.data.cover"></UploadImg>
<div class="list"> <div class="list">
<div class="item"> <div class="item">
<img <img
...@@ -276,12 +225,6 @@ if (id !== '' && id) { ...@@ -276,12 +225,6 @@ if (id !== '' && id) {
</AppCard> </AppCard>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.tips {
font-size: 12px;
line-height: 100%;
color: #999999;
margin-top: 8px;
}
.tool-btn-box { .tool-btn-box {
display: flex; display: flex;
justify-content: right; justify-content: right;
...@@ -406,35 +349,4 @@ if (id !== '' && id) { ...@@ -406,35 +349,4 @@ if (id !== '' && id) {
cursor: pointer; cursor: pointer;
} }
} }
.upload-video {
display: flex;
align-items: center;
.upload-btn {
position: relative;
width: 94px;
line-height: 36px;
background: rgba(250, 223, 230, 0.39);
border: 1px solid #aa1941;
border-radius: 20px;
font-size: 14px;
color: #aa1941;
margin-right: 30px;
text-align: center;
}
.video-info {
display: flex;
.name {
color: #333333;
font-size: 16px;
line-height: 100%;
}
.view {
font-size: 16px;
line-height: 100%;
color: #399ee8;
margin-left: 20px;
cursor: pointer;
}
}
}
</style> </style>
<!-- <script setup lang="ts">
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { createVideo, updateVideo, getVideo } from '../api'
const props = defineProps<{ id?: string }>()
const router = useRouter()
const formRef = ref<FormInstance>()
const form = reactive({ course_name: '', type: '', cover_page: '', aliyun_video_id: '', weight: '' })
const rules = {
course_name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
type: [{ required: true, message: '请选择类型', trigger: 'change' }],
cover_page: [{ required: true, message: '请上传视频封面图片', trigger: 'change' }],
aliyun_video_id: [{ required: true, message: '请输入阿里云播放视频ID', trigger: 'blur' }]
}
const typeList = [
{ label: '入学指南', value: '1' },
{ label: '学习地图', value: '2' },
{ label: '考试攻略', value: '3' }
]
// 提交
const onSubmit = () => {
if (!formRef.value) return
formRef.value.validate().then(() => {
props.id ? update() : create()
})
}
// 取消
const onCancel = () => {
router.replace('/video')
}
// 创建
const create = () => {
createVideo(form).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
router.push('/video')
})
}
// 修改
const update = () => {
const params = { ...form, id: props.id as string }
updateVideo(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
router.push('/video')
})
}
onMounted(() => {
props.id &&
getVideo({ id: props.id }).then(res => {
Object.assign(form, res.data)
})
})
</script>
<template>
<AppCard>
<el-form ref="formRef" :model="form" :rules="rules" label-width="140px">
<el-form-item label="标题" prop="course_name">
<el-input v-model="form.course_name" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="form.type">
<el-option v-for="item in typeList" :label="item.label" :value="item.value" :key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="权重" prop="weight">
<el-input type="number" v-model="form.weight" controls-position="right" />
</el-form-item>
<el-form-item label="视频封面" prop="cover_page">
<AppUpload v-model="form.cover_page"></AppUpload>
</el-form-item>
<el-form-item label="阿里云播放视频ID" prop="aliyun_video_id">
<el-input v-model="form.aliyun_video_id" />
</el-form-item>
<el-form-item>
<el-button type="primary" auto-insert-space @click="onSubmit">保存</el-button>
<el-button auto-insert-space @click="onCancel">取消</el-button>
</el-form-item>
</el-form>
</AppCard>
</template> -->
<script setup lang="ts"> <script setup lang="ts">
import TopInfo from '../components/TopInfo.vue' import ViewTop from '../components/ViewTop.vue'
import CenterInfo from '../components/CenterInfo.vue' import ViewCenter from '../components/ViewCenter.vue'
import BottomInfo from '../components/BottomInfo.vue' import ViewBottom from '../components/ViewBottom.vue'
import Operation from '../components/Operation.vue' import Operation from '../components/Operation.vue'
// api
import { getVideoDetails } from '../api' import { getVideoDetails } from '../api'
// 路由 // 路由
const router = useRouter() const route = useRoute()
const id = route.query.id as string
const listOptions = { const listOptions = {
columns: [ columns: [
...@@ -28,9 +28,8 @@ const listOptions = { ...@@ -28,9 +28,8 @@ const listOptions = {
] ]
} }
const id = router.currentRoute.value.query.id as string
// 获取详情 // 获取详情
let videoDetails:any = ref({}) let videoDetails: any = ref({})
getVideoDetails({ id: id }).then(res => { getVideoDetails({ id: id }).then(res => {
videoDetails.value = res.data videoDetails.value = res.data
}) })
...@@ -38,30 +37,17 @@ getVideoDetails({ id: id }).then(res => { ...@@ -38,30 +37,17 @@ getVideoDetails({ id: id }).then(res => {
<template> <template>
<AppCard title="视频资源信息"> <AppCard title="视频资源信息">
<Operation :data="videoDetails" style="margin-bottom: 20px;"></Operation> <Operation :data="videoDetails"></Operation>
<!-- <div class="btn-box"> <ViewTop :data="videoDetails"></ViewTop>
<div class="btn-item">编辑视频信息</div> <ViewCenter v-if="Object.keys(videoDetails).length" :data="videoDetails"></ViewCenter>
<div class="btn-item">编辑视频课件</div> <ViewBottom></ViewBottom>
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div> -->
<TopInfo :data="videoDetails"></TopInfo>
<CenterInfo v-if="Object.keys(videoDetails).length" :data="videoDetails"></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard> </AppCard>
<AppCard title="视频资源信息"> <AppCard title="视频资源信息">
<AppList v-bind="listOptions" ref="appList" stripe> <AppList v-bind="listOptions" ref="appList" stripe>
<template #table-operate="{ row }"> <template #table-operate="{ row }">
<el-space> <el-space>
<router-link :to="`/video/update/${row.id}`"> <router-link :to="`/video/update/${row.id}`">
<el-button <el-button style="color: #399ee8" type="primary" link>查看</el-button>
style="color: #399EE8;"
type="primary"
link
>查看</el-button
>
</router-link> </router-link>
</el-space> </el-space>
</template> </template>
...@@ -69,17 +55,17 @@ getVideoDetails({ id: id }).then(res => { ...@@ -69,17 +55,17 @@ getVideoDetails({ id: id }).then(res => {
</AppCard> </AppCard>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.btn-box{ .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;
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论