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

updates

上级 036980b3
...@@ -55,7 +55,7 @@ export function getCategoryList(params: { type: string; category_name?: string } ...@@ -55,7 +55,7 @@ export function getCategoryList(params: { type: string; category_name?: string }
} }
// 获取项目列表 // 获取项目列表
export function getProjectList(params: { organization_id?: string; project_id?: string }) { export function getProjectList(params: { organization_id?: string; project_id?: string; semester?: number }) {
return httpRequest.get('/api/resource/v1/util/members', { params }) return httpRequest.get('/api/resource/v1/util/members', { params })
} }
// 获取试题分类 // 获取试题分类
......
...@@ -199,11 +199,7 @@ export const menus: IMenuItem[] = [ ...@@ -199,11 +199,7 @@ export const menus: IMenuItem[] = [
path: 'http://114.242.229.132:18080/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!5b66!!4e60!!884c!!4e3a!!753b!!50cf!.db&platform=PC&browserType=chrome' path: 'http://114.242.229.132:18080/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!5b66!!4e60!!884c!!4e3a!!753b!!50cf!.db&platform=PC&browserType=chrome'
}, },
{ {
<<<<<<< HEAD
tag: '', tag: '',
=======
tag: 'v1-backend-lecturer-list',
>>>>>>> master
icon: DataAnalysis, icon: DataAnalysis,
name: '生源地分布', name: '生源地分布',
path: 'http://114.242.229.132:18080/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!751f!!6e90!!5730!!5206!!5e03!.db&platform=PC&browserType=chrome' path: 'http://114.242.229.132:18080/bi/?proc=1&action=viewer&hback=true&isInPreview=true&db=!7d2b!!8346!!6559!!80b2!e-SaaS!2f!!751f!!6e90!!5730!!5206!!5e03!.db&platform=PC&browserType=chrome'
......
...@@ -4,7 +4,7 @@ export function useProjectList(id?: string, projectId?: string) { ...@@ -4,7 +4,7 @@ export function useProjectList(id?: string, projectId?: string) {
const list = ref([]) const list = ref([])
const members = ref([]) const members = ref([])
const departmentList = ref([]) const departmentList = ref([])
getProjectList({ organization_id: id, project_id: projectId }).then((res: any) => { getProjectList({ organization_id: id, project_id: projectId, semester: 1 }).then((res: any) => {
list.value = res.data.departments list.value = res.data.departments
members.value = res.data.members members.value = res.data.members
departmentList.value = res.data.departments.reduce((a: any, b: any) => { departmentList.value = res.data.departments.reduce((a: any, b: any) => {
......
...@@ -41,10 +41,10 @@ const listOptions = $computed(() => { ...@@ -41,10 +41,10 @@ const listOptions = $computed(() => {
columns: [ columns: [
{ type: 'selection' }, { type: 'selection' },
{ label: '序号', type: 'index', align: 'center' }, { label: '序号', type: 'index', align: 'center' },
{ label: '课程名称', prop: 'name', align: 'center' }, { label: '课程名称/别名', prop: 'name', align: 'center', width: '200' },
{ label: '课程类型', prop: 'online_type_name', align: 'center' }, { label: '课程类型', prop: 'online_type_name', align: 'center', width: '200' },
{ label: '选课类型', prop: 'elective_type_name', align: 'center' }, { label: '选课类型', prop: 'elective_type_name', align: 'center' },
{ label: '课程分类', prop: 'classification_name', align: 'center' }, { label: '课程分类', prop: 'classification_name', align: 'center', width: '310' },
{ label: '课程学分', prop: 'credit', align: 'center' }, { label: '课程学分', prop: 'credit', align: 'center' },
{ {
label: '讲师', label: '讲师',
...@@ -54,9 +54,10 @@ const listOptions = $computed(() => { ...@@ -54,9 +54,10 @@ const listOptions = $computed(() => {
if (row.row.lecturers_name.length) { if (row.row.lecturers_name.length) {
return row.row.lecturers_name.toString() return row.row.lecturers_name.toString()
} }
} },
width: '200'
}, },
{ label: '更新时间', prop: 'updated_time', align: 'center' }, { label: '更新时间', prop: 'updated_time', align: 'center', width: '200' },
{ label: '操作', slots: 'table-operate', align: 'center', minWidth: '200', fixed: 'right' } { label: '操作', slots: 'table-operate', align: 'center', minWidth: '200', fixed: 'right' }
] ]
} }
...@@ -85,7 +86,7 @@ const handleFresh = () => { ...@@ -85,7 +86,7 @@ const handleFresh = () => {
} }
</script> </script>
<template> <template>
<el-dialog :model-value="isShowCourse" draggable title="关联选择课程" width="50%" :before-close="handleCancel"> <el-dialog :model-value="isShowCourse" draggable title="添加学期课程" width="50%" :before-close="handleCancel">
<div style="overflow-y: auto; height: 70vh"> <div style="overflow-y: auto; height: 70vh">
<el-descriptions> <el-descriptions>
<el-descriptions-item label="学期名称:">{{ semInfo.name }}</el-descriptions-item> <el-descriptions-item label="学期名称:">{{ semInfo.name }}</el-descriptions-item>
......
...@@ -189,11 +189,18 @@ export function createCharacter(data: { ...@@ -189,11 +189,18 @@ export function createCharacter(data: {
name: string name: string
parent_id?: string parent_id?: string
resource_id?: string resource_id?: string
can_download?: number
}) { }) {
return httpRequest.post('/api/resource/v1/course/course/create-chapter', data) return httpRequest.post('/api/resource/v1/course/course/create-chapter', data)
} }
// 章节修改 // 章节修改
export function editCharacter(data: { id: string; course_id: string; name: string; resource_id: string }) { export function editCharacter(data: {
id: string
course_id: string
name: string
resource_id?: string
can_download?: string
}) {
return httpRequest.post('/api/resource/v1/course/course/update-chapter', data) return httpRequest.post('/api/resource/v1/course/course/update-chapter', data)
} }
// 章节删除 // 章节删除
...@@ -208,4 +215,21 @@ export function getLiveList(params: { name: string; page?: number; ['per-page']? ...@@ -208,4 +215,21 @@ export function getLiveList(params: { name: string; page?: number; ['per-page']?
export function getMajorList(params: { name: string; page?: number; ['per-page']?: string }) { export function getMajorList(params: { name: string; page?: number; ['per-page']?: string }) {
return httpRequest.get('/api/resource/v1/course/course/search-specialty', { params }) return httpRequest.get('/api/resource/v1/course/course/search-specialty', { params })
} }
// 设置章节开放规则
export function setOpenRules(data: {
course_id: string
chapter_id: string
type: string
progress?: string
score?: string
start_time?: string
end_time?: string
open?: string
}) {
return httpRequest.post('/api/resource/v1/course/course/set-chapter-rules', data)
}
// 控制资料能否下载
export function setDownload(data: { course_id: string; information_id: string; can_download: string }) {
return httpRequest.post('/api/resource/v1/course/course/set-course-information-can-download ', data)
}
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { setOpenRules } from '../../api'
const emit = defineEmits<Emits>()
const form = reactive({
type: '0',
progress: '',
score: '',
open: '1',
start_time: '',
end_time: ''
})
const props = defineProps({
isShowOpenRules: {
type: Boolean
},
chapterName: {
type: String
},
sectionName: {
type: String
},
chapterID: {
type: String
},
course_id: {
type: String
}
})
interface Emits {
(e: 'update:isShowOpenRules', isShowOpenRules: boolean): void
(e: 'create'): void
}
const handleCancel = () => {
emit('update:isShowOpenRules', false)
}
const handleConfirm = () => {
const params: any = Object.assign({ course_id: props.course_id, chapter_id: props.chapterID }, form)
setOpenRules(params).then(() => {
emit('update:isShowOpenRules', false)
emit('create')
ElMessage.success('章节开放规则设置成功')
})
}
</script>
<template>
<el-dialog :model-value="isShowOpenRules" :before-close="handleCancel" title="章节开放规则">
<el-form :model="form" laebl-suffix=":" label-width="100px">
<el-form-item label="章名称:" prop="chapter">{{ props.chapterName }}</el-form-item>
<el-form-item label="小节名称:" prop="section">{{ props.sectionName || '无' }}</el-form-item>
<el-form-item label="开放规则:" prop="rules">
<el-radio-group
v-model="form.type"
style="display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start"
>
<el-radio label="0">无条件</el-radio>
<el-radio label="1">
前一章/前一节完成度达到之后开放 <el-input v-model="form.progress" style="width: 50px"></el-input>%
</el-radio>
<el-radio label="2">
完成前一章/前一节考试,且考试成绩达到<el-input v-model="form.score" style="width: 50px"></el-input
>分以上</el-radio
>
<el-radio label="3">
时间范围:
<el-date-picker v-model="form.start_time" type="date"> </el-date-picker>
~
<el-date-picker v-model="form.end_time" type="date"> </el-date-picker>
</el-radio>
<el-radio label="4">
手工开放:<el-switch
v-model="form.open"
size="large"
active-value="1"
inactive-value="0"
inline-prompt
style="--el-switch-on-color: #aa1941"
></el-switch
></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts"> <script setup lang="ts">
import { createCourse, getCourseDetails, updateCourse, getMajorList } from '../api' import { createCourse, getCourseDetails, updateCourse, getMajorList } from '../api'
//
// setStatus // setStatus
import { useGetCategoryList } from '@/composables/useGetCategoryList' import { useGetCategoryList } from '@/composables/useGetCategoryList'
import { useMapStore } from '@/stores/map' import { useMapStore } from '@/stores/map'
......
<script lang="ts" setup> <script lang="ts" setup>
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getCharacter, delCharacter, getVideoDetails, dragChapterList } from '../api' import { getCharacter, delCharacter, getVideoDetails, dragChapterList, createCharacter, editCharacter } from '../api'
import AddSectionDialog from '../components/stepTwoComponents/AddSectionDialog.vue' import AddSectionDialog from '../components/stepTwoComponents/AddSectionDialog.vue'
import AddLiveDialog from '../components/stepTwoComponents/AddLiveDialog.vue' import AddLiveDialog from '../components/stepTwoComponents/AddLiveDialog.vue'
import AddVideoDialog from '../components/stepTwoComponents/AddVideoDialog.vue' import AddVideoDialog from '../components/stepTwoComponents/AddVideoDialog.vue'
import AddExamDialog from '../components/stepTwoComponents/AddExamDialog.vue' import AddExamDialog from '../components/stepTwoComponents/AddExamDialog.vue'
import VideoPlayDialog from '../components/stepTwoComponents/VideoPlayDialog.vue' import VideoPlayDialog from '../components/stepTwoComponents/VideoPlayDialog.vue'
import AddChapterDialog from '../components/stepTwoComponents/AddChapterDialog.vue' import AddChapterDialog from '../components/stepTwoComponents/AddChapterDialog.vue'
import OpenRules from '../components/stepTwoComponents/OpenRules.vue'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const isEditCourse = route.query.isEditCourse as string const isEditCourse = route.query.isEditCourse as string
const id = route.query.id as string const id = route.query.id as string
const dataSource: any = ref([]) const dataSource: any = ref([])
const isShowOpenRules = ref(false)
const isShowDialog = ref(false) const isShowDialog = ref(false)
const isShowSectionDialog = ref(false) const isShowSectionDialog = ref(false)
const isShowLiveDialog = ref(false) const isShowLiveDialog = ref(false)
...@@ -79,8 +81,10 @@ const handleChapterList = () => { ...@@ -79,8 +81,10 @@ const handleChapterList = () => {
}) })
} }
}) })
console.log(dataSource, 'dataSource')
}) })
} }
console.log(dataSource, 'dataSource')
// 新增章节 // 新增章节
const handleAddChapter = () => { const handleAddChapter = () => {
...@@ -258,13 +262,52 @@ const nodeType = (node: any) => { ...@@ -258,13 +262,52 @@ const nodeType = (node: any) => {
} }
const handleNodeExpand = (data: any) => { const handleNodeExpand = (data: any) => {
flag.value = true flag.value = true
defaultExpandedKeys.value = [data.id] defaultExpandedKeys.value = [data.id]
} }
const handleNodeCollapse = () => { const handleNodeCollapse = () => {
flag.value = false flag.value = false
defaultExpandedKeys.value = [] defaultExpandedKeys.value = []
} }
// 设置开放规则
const handleOpenRules = (node: any, data: any) => {
if (node.level === 1) {
chapterName.value = node.label
sectionName.value = '无'
chapterID.value = node.key
} else {
chapterName.value = data.parent_name
chapterID.value = data.parent_id
sectionName.value = node.label
}
isShowOpenRules.value = true
}
// 控制学生能否下载
const handleChangeStatus = (node: any, data: any) => {
if (isEditCourse !== '1') {
console.log(node, data)
const params: any = {
course_id: id,
resource_type: node.data.resource_type,
name: node.label,
resource_id: node.key,
can_download: node.can_download
}
createCharacter(params).then(() => {
ElMessage.success('设置下载控制成功')
})
} else {
const params: any = {
course_id: id,
id: '',
name: node.label,
resource_id: node.key,
can_download: node.can_download
}
editCharacter(params).then(() => {
ElMessage.success('设置下载控制成功')
})
}
}
</script> </script>
<template> <template>
<AppCard :title="isEditCourse === '1' ? '编辑课程' : '新建课程'"> <AppCard :title="isEditCourse === '1' ? '编辑课程' : '新建课程'">
...@@ -318,12 +361,48 @@ const handleNodeCollapse = () => { ...@@ -318,12 +361,48 @@ const handleNodeCollapse = () => {
style="margin-left: 35px" style="margin-left: 35px"
>下载</el-link >下载</el-link
> >
<span
v-if="
data.depth === '3' &&
node.data.resource_type !== '2' &&
node.data.resource_type !== '6' &&
node.data.resource_type !== '3' &&
node.data.resource_type !== '9'
"
>学生下载控制:</span
>
<el-switch
class="btn_edit"
v-if="
data.depth === '3' &&
node.data.resource_type !== '2' &&
node.data.resource_type !== '6' &&
node.data.resource_type !== '3' &&
node.data.resource_type !== '9'
"
v-model="node.data.information_can_download"
size="large"
active-value="1"
inactive-value="0"
inline-prompt
style="--el-switch-on-color: #aa1941"
@change="handleChangeStatus(node, data)"
></el-switch>
<el-link class="btn_edit" v-if="data.depth !== '3'" @click="handleEdit(node)" style="margin-left: 35px" <el-link class="btn_edit" v-if="data.depth !== '3'" @click="handleEdit(node)" style="margin-left: 35px"
>编辑</el-link >编辑</el-link
> >
<el-link type="info" @click="handleDel(node)" style="margin-left: 25px">删除</el-link></span <el-link type="info" @click="handleDel(node)" style="margin-left: 25px">删除</el-link></span
> >
<span> <span>
<el-button
class="btn_operate"
v-if="data.depth === '1' || data.depth === '2'"
@click="handleOpenRules(node, data)"
>
<el-icon><Plus /></el-icon>
&nbsp; 开放规则
</el-button>
<el-button class="btn_operate" v-if="data.depth === '1'" @click="handleAddSection(node)"> <el-button class="btn_operate" v-if="data.depth === '1'" @click="handleAddSection(node)">
<el-icon><Plus /></el-icon> <el-icon><Plus /></el-icon>
&nbsp; 添加小节 &nbsp; 添加小节
...@@ -409,6 +488,15 @@ const handleNodeCollapse = () => { ...@@ -409,6 +488,15 @@ const handleNodeCollapse = () => {
v-model:isShowVideoPlayDialog="isShowVideoPlayDialog" v-model:isShowVideoPlayDialog="isShowVideoPlayDialog"
:videoOptions="videoUrl" :videoOptions="videoUrl"
/> />
<OpenRules
v-model:isShowOpenRules="isShowOpenRules"
v-if="isShowOpenRules === true"
:chapterName="chapterName"
:sectionName="sectionName"
:chapterID="chapterID"
:course_id="id"
@create="handleFresh"
/>
</template> </template>
<style> <style>
......
...@@ -2,20 +2,18 @@ ...@@ -2,20 +2,18 @@
import { courseCopy, setDepartment, setPlatform, setStatus, setBelong, courseAuthorization } from '../api' import { courseCopy, setDepartment, setPlatform, setStatus, setBelong, courseAuthorization } from '../api'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
// 筛选部门 // 筛选部门
const departmentList: any = useProjectList('', '79806610719731712').departmentList let departmentList: any = useProjectList('', '79806610719731712').departmentList
console.log()
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const props = defineProps(['data']) const props = defineProps(['data'])
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
}>() }>()
// 详情id // 详情id
const id = route.query.id as string const id = route.query.id as string
// 设置部门共享 // 设置部门共享
const handleDepartment = () => { const handleDepartment = () => {
ElMessageBox.confirm( ElMessageBox.confirm(
...@@ -133,10 +131,20 @@ const handlesetBelong = () => { ...@@ -133,10 +131,20 @@ const handlesetBelong = () => {
// 授权 // 授权
const dialogVisibleAuthorize = ref(false) const dialogVisibleAuthorize = ref(false)
const authorizeCheck = ref([]) const authorizeCheck: any = ref([])
const courseAuthorizeConfirm = () => { const courseAuthorizeConfirm = () => {
const organIds = authorizeCheck.value.toString() const list: any = ref([])
courseAuthorization({ id: id, organ_ids: organIds }).then((res: any) => { const newList = JSON.parse(JSON.stringify(departmentList.value))
newList.map((item: any) => {
authorizeCheck.value.map((it: any) => {
delete item.semesters
if (item.id === it) {
list.value.push(item)
return item
}
})
})
courseAuthorization({ id: id, organ_ids: JSON.stringify(list.value) }).then((res: any) => {
if (res.code === 0) { if (res.code === 0) {
ElMessage({ message: '授权成功', type: 'success' }) ElMessage({ message: '授权成功', type: 'success' })
dialogVisibleAuthorize.value = false dialogVisibleAuthorize.value = false
...@@ -219,10 +227,36 @@ const copyCourse = () => { ...@@ -219,10 +227,36 @@ const copyCourse = () => {
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="dialogVisibleAuthorize" title="项目/学校" width="30%"> <el-dialog v-model="dialogVisibleAuthorize" title="项目/学校" width="85vw">
<el-checkbox-group v-model="authorizeCheck"> <el-checkbox-group v-model="authorizeCheck" style="display: flex; flex-direction: column">
<el-checkbox :label="item.id" v-for="item in departmentList" :key="item.id">{{ item.name }}</el-checkbox> <el-checkbox :label="item.id" v-for="item in departmentList" :key="item.id">
{{ item.name }}
<span v-if="authorizeCheck.filter((it:any)=>it === item.id).length >0">
<el-radio-group v-model="item.auth_type">
<el-radio label="1">长期有效:</el-radio>
<el-radio label="2">学期有效:</el-radio>
<el-select v-model="item.auth_semester_id">
<el-option v-for="(it, id) in item.semesters" :key="id" :label="it.name" :value="it.id"></el-option>
</el-select>
<el-radio label="3">时间范围:</el-radio>
<el-date-picker
v-model="item.auth_start_time"
type="datetime"
style="width: 150px"
value-format="YYYY-MM-DD HH:mm:ss"
/>
~
<el-date-picker
v-model="item.auth_end_time"
type="datetime"
style="width: 150px"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-radio-group>
</span>
</el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="dialogVisibleAuthorize = false">取消</el-button> <el-button @click="dialogVisibleAuthorize = false">取消</el-button>
...@@ -247,4 +281,10 @@ const copyCourse = () => { ...@@ -247,4 +281,10 @@ const copyCourse = () => {
cursor: pointer; cursor: pointer;
} }
} }
:deep(.el-checkbox) {
margin-top: 20px;
}
:deep(.el-radio) {
margin-left: 20px;
}
</style> </style>
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import { useGetCategoryList } from '@/composables/useGetCategoryList'
import { createVideo } from '../api'
import UploadVideo from './UploadVideo.vue'
const emit = defineEmits<Emits>()
let { list: selectTree }: any = useGetCategoryList()
const defaultProps = { children: 'children', label: 'category_name', value: 'id' }
const form = reactive({
source_id: '',
name: '0',
classification: ''
})
defineProps({
isShowBatchImport: {
type: Boolean
}
})
interface Emits {
(e: 'update:isShowBatchImport', isShowBatchImport: boolean): void
(e: 'update'): void
}
const handleConfirm = () => {
emit('update:isShowBatchImport', false)
emit('update')
}
const handleCancel = () => {
emit('update:isShowBatchImport', false)
}
// 上传视频成功
const uploadVideo = (data: any) => {
console.log(data)
const params = {
name: data.name.slice(0, data.name.lastIndexOf('.')),
source: '2',
classification: form.classification,
knowledge_points: '',
source_id: data.videoId,
cover: ''
}
createVideo(params).then(() => {
ElMessage.success('视频上传成功')
})
}
</script>
<template>
<el-dialog :model-value="isShowBatchImport" title="批量导入视频" :before-close="handleCancel">
<el-form :model="form" label-suffix=":">
<el-form-item label="视频分类" prop="classification">
<el-tree-select
node-key="id"
:render-after-expand="false"
:props="defaultProps"
v-model="form.classification"
:data="selectTree"
clearable
placeholder="视频分类"
:default-expanded-keys="selectTree.length ? [selectTree[0]?.id] : []"
/>
</el-form-item>
<el-form-item label="视频文件" prop="source_id" v-if="form.classification !== ''">
<UploadVideo @upload="uploadVideo" />
</el-form-item>
<el-form-item label="视频名称" prop="name">
<el-radio-group v-model="form.name">
<el-radio label="0">源自文件名称</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="handleConfirm">保存</el-button>
<el-button @click="handleCancel">取消</el-button>
</span>
</template>
</el-dialog>
</template>
<style></style>
<script setup lang="ts"> <script setup lang="ts">
import { getCreateAuth, updateAuth } from '@/api/base' import { getCreateAuth, updateAuth } from '@/api/base'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
const props = defineProps({
createFlag: {
type: Number
}
})
/** /**
* upload 上传状态 {code: -1(待上传)0(成功) 1(开始上传) 2(上传失败), msg: '上传信息'} * upload 上传状态 {code: -1(待上传)0(成功) 1(开始上传) 2(上传失败), msg: '上传信息'}
* progress 上传进度 * progress 上传进度
**/ **/
interface IUpload { interface IUpload {
id?: number
code: number code: number
name?: string name?: string
msg?: string msg?: string
...@@ -13,6 +19,7 @@ interface IUpload { ...@@ -13,6 +19,7 @@ interface IUpload {
videoId?: string videoId?: string
} }
let uploadData = $ref<IUpload>({ code: -1 }) let uploadData = $ref<IUpload>({ code: -1 })
let uploadData1 = $ref<IUpload[]>([])
const emit = defineEmits(['upload']) const emit = defineEmits(['upload'])
const form: any = reactive({ const form: any = reactive({
...@@ -29,24 +36,48 @@ const form: any = reactive({ ...@@ -29,24 +36,48 @@ const form: any = reactive({
statusText: '' statusText: ''
}) })
const fileChange = (e: any) => { const fileChange = (e: any) => {
form.file = e.target.files[0] if (props.createFlag === 1) {
if (form.file.name.indexOf('.mp4') === -1) { form.file = e.target.files[0]
ElMessage('请上传mp4格式视频') if (form.file.name.indexOf('.mp4') === -1) {
return ElMessage.warning('请上传mp4格式视频')
} return
var userData = '{"Vod":{}}' }
if (form.uploader) { var userData = '{"Vod":{}}'
form.uploader.stopUpload() if (form.uploader) {
form.authProgress = 0 form.uploader.stopUpload()
form.statusText = '' form.authProgress = 0
form.statusText = ''
}
form.uploader = createUploader()
form.uploader.addFile(form.file, null, null, null, userData)
form.uploader.startUpload()
} else {
form.file = e.target.files
console.log(form.file, '123')
form.file.forEach((item: any) => {
if (item.name.indexOf('.mp4') === -1) {
ElMessage('请上传mp4格式视频')
} else {
var userData = '{"Vod":{}}'
if (form.uploader) {
form.uploader.stopUpload()
form.authProgress = 0
form.statusText = ''
}
setTimeout(() => {
form.uploader = createUploader()
form.uploader.addFile(item, null, null, null, userData)
form.uploader.startUpload()
}, 1000)
}
})
} }
form.uploader = createUploader()
form.uploader.addFile(form.file, null, null, null, userData)
form.uploader.startUpload()
} }
let id = ref(0)
const createUploader: any = () => { const createUploader: any = () => {
console.log('000000')
const w = window as any const w = window as any
// for
const uploader = new w.AliyunUpload.Vod({ const uploader = new w.AliyunUpload.Vod({
timeout: form.timeout || 60000, timeout: form.timeout || 60000,
partSize: form.partSize || 1048576, partSize: form.partSize || 1048576,
...@@ -92,37 +123,70 @@ const createUploader: any = () => { ...@@ -92,37 +123,70 @@ const createUploader: any = () => {
}) })
} }
} }
uploadData = { if (props.createFlag === 1) {
code: 1, uploadData = {
name: uploadInfo.file.name, code: 1,
msg: '开始上传' name: uploadInfo.file.name,
msg: '开始上传'
}
} else {
// id.value = id.value + 1
uploadData1.push({
code: 1,
name: uploadInfo.file.name,
msg: '开始上传'
})
} }
}, },
// 文件上传成功 // 文件上传成功
onUploadSucceed: function (uploadInfo: any) { onUploadSucceed: function (uploadInfo: any) {
const fileData = window.localStorage.fileData ? JSON.parse(window.localStorage.fileData) : {} const fileData = window.localStorage.fileData ? JSON.parse(window.localStorage.fileData) : {}
uploadData = { if (props.createFlag === 1) {
code: 0, uploadData = {
name: uploadInfo.file.name, code: 0,
videoId: fileData.videoId, name: uploadInfo.file.name,
msg: '上传成功' videoId: fileData.videoId,
msg: '上传成功'
}
} else {
const findIndex = uploadData1.findIndex(item => item.name === uploadInfo.file.name)
uploadData1[findIndex] = {
code: 0,
name: uploadInfo.file.name,
videoId: fileData.videoId,
msg: '上传成功'
}
} }
emit('upload', { videoId: fileData.videoId, name: uploadInfo.file.name }) emit('upload', { videoId: fileData.videoId, name: uploadInfo.file.name })
}, },
// 文件上传失败 // 文件上传失败
// code:any, message:any // code:any, message:any
onUploadFailed: function (uploadInfo: any) { onUploadFailed: function (uploadInfo: any) {
uploadData = { if (props.createFlag === 1) {
code: 2, uploadData = {
name: uploadInfo.file.name, code: 2,
msg: '文件上传失败' name: uploadInfo.file.name,
msg: '文件上传失败'
}
} else {
const findIndex = uploadData1.findIndex(item => item.id === id.value)
uploadData1[findIndex] = {
id: id.value,
code: 2,
name: uploadInfo.file.name,
msg: '文件上传失败'
}
} }
}, },
// 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上 // 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上
onUploadProgress: function (uploadInfo: any, totalSize: any, progress: any) { onUploadProgress: function (uploadInfo: any, totalSize: any, progress: any) {
let progressPercent = Math.ceil(progress * 100) let progressPercent = Math.ceil(progress * 100)
form.authProgress = progressPercent form.authProgress = progressPercent
uploadData.progress = progressPercent if (props.createFlag === 1) {
uploadData.progress = progressPercent
} else {
uploadData1.map((item: any) => (item.progress = progressPercent))
}
}, },
// 上传凭证超时 // 上传凭证超时
onUploadTokenExpired: function (uploadInfo: any) { onUploadTokenExpired: function (uploadInfo: any) {
...@@ -144,7 +208,7 @@ const createUploader: any = () => { ...@@ -144,7 +208,7 @@ const createUploader: any = () => {
} }
</script> </script>
<template> <template>
<div> <div v-if="props.createFlag === 1">
<div class="upload-video"> <div class="upload-video">
<div class="upload-btn"> <div class="upload-btn">
本地文件 本地文件
...@@ -153,7 +217,6 @@ const createUploader: any = () => { ...@@ -153,7 +217,6 @@ const createUploader: any = () => {
</div> </div>
<div class="demo-progress" v-if="uploadData.code === 1"> <div class="demo-progress" v-if="uploadData.code === 1">
<el-progress style="width: 340px" :percentage="uploadData.progress" /> <el-progress style="width: 340px" :percentage="uploadData.progress" />
<!-- <span> {{ uploadData.progress }}% </span> -->
</div> </div>
<div class="error video-info" v-if="uploadData.code === 2"> <div class="error video-info" v-if="uploadData.code === 2">
<div class="name">上传失败(请重新选择文件进行上传)</div> <div class="name">上传失败(请重新选择文件进行上传)</div>
...@@ -164,10 +227,32 @@ const createUploader: any = () => { ...@@ -164,10 +227,32 @@ const createUploader: any = () => {
</div> </div>
<div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div> <div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div>
</div> </div>
<div v-else>
<div class="upload-video" style="display: flex; flex-direction: column; align-items: flex-start">
<div class="upload-btn">
本地文件
<input accept=".mp4" type="file" id="fileUpload" @change="fileChange($event)" multiple />
</div>
<div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div>
<div v-for="(item, index) in uploadData1" :key="index" style="display: flex; flex-direction: column">
<div class="demo-progress" v-if="item.code === 1">
<span style="min-width: 340px">{{ item.name }}</span>
<el-progress style="width: 200px" :percentage="item.progress" />
</div>
<div class="error video-info" v-if="item.code === 2">
<div class="name">上传失败(请重新选择文件进行上传)</div>
</div>
<div class="video-info" v-if="item.code === 0">
<div class="name">{{ item.name }}</div>
</div>
</div>
</div>
</div>
</template> </template>
<style lang="scss"> <style lang="scss">
.demo-progress { .demo-progress {
width: 350px; min-width: 350px;
display: flex; display: flex;
span { span {
color: #999999; color: #999999;
......
...@@ -6,6 +6,7 @@ import { useGetCategoryList } from '@/composables/useGetCategoryList' ...@@ -6,6 +6,7 @@ import { useGetCategoryList } from '@/composables/useGetCategoryList'
import { useProjectList } from '@/composables/useGetProjectList' import { useProjectList } from '@/composables/useGetProjectList'
import { useMapStore } from '@/stores/map' import { useMapStore } from '@/stores/map'
import { useUserStore } from '@/stores/user' import { useUserStore } from '@/stores/user'
import BatchImportVideo from '../components/BatchImportVideo.vue'
// 判断当前用户是不是超级管理员 // 判断当前用户是不是超级管理员
const user = useUserStore().roles const user = useUserStore().roles
...@@ -26,13 +27,12 @@ const defaultProps = { ...@@ -26,13 +27,12 @@ const defaultProps = {
// 资源出处 tab触发 // 资源出处 tab触发
const tabValue = ref('1') const tabValue = ref('1')
const appList = ref() const appList = ref()
const isShowBatchImport = ref(false)
const tabChange = () => { const tabChange = () => {
appList.value.refetch() appList.value.refetch()
} }
// 列表切换 // 列表切换
let isCard = $ref(true) let isCard = $ref(true)
// table 数据 // table 数据
const listOptions = $computed(() => { const listOptions = $computed(() => {
const columns = [ const columns = [
...@@ -90,6 +90,10 @@ const typeFilter = () => { ...@@ -90,6 +90,10 @@ const typeFilter = () => {
const changeCard = () => { const changeCard = () => {
isCard = !isCard isCard = !isCard
} }
// 批量上传
const handleBatchImport = () => {
isShowBatchImport.value = true
}
</script> </script>
<template> <template>
...@@ -118,6 +122,9 @@ const changeCard = () => { ...@@ -118,6 +122,9 @@ const changeCard = () => {
> >
<el-button type="primary" round>新建视频资源</el-button> <el-button type="primary" round>新建视频资源</el-button>
</router-link> </router-link>
<el-button v-if="tabValue === '1'" type="primary" round @click="handleBatchImport" style="margin-left: 20px"
>批量上传</el-button
>
</div> </div>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #header-aside></template> <template #header-aside></template>
...@@ -173,6 +180,11 @@ const changeCard = () => { ...@@ -173,6 +180,11 @@ const changeCard = () => {
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
<BatchImportVideo
v-model:isShowBatchImport="isShowBatchImport"
v-if="isShowBatchImport === true"
@update="typeFilter"
/>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.card-list { .card-list {
......
...@@ -162,7 +162,7 @@ const changeProtocol = (data: any) => { ...@@ -162,7 +162,7 @@ const changeProtocol = (data: any) => {
<AppCard :title="isUpdate ? '编辑视频资源' : '新建视频资源'"> <AppCard :title="isUpdate ? '编辑视频资源' : '新建视频资源'">
<el-form ref="ruleFormRef" :model="form.data" :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="!isUpdate"> <el-form-item label="视频文件:" prop="source_id" v-if="!isUpdate">
<UploadVideo @upload="uploadVideo"></UploadVideo> <UploadVideo @upload="uploadVideo" :createFlag="1"></UploadVideo>
</el-form-item> </el-form-item>
<el-form-item label="视频名称:" prop="name"> <el-form-item label="视频名称:" prop="name">
<el-input v-model="form.data.name" maxlength="40" /> <el-input v-model="form.data.name" maxlength="40" />
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论