Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
center-resource
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
center-resource
Commits
a1956e7e
提交
a1956e7e
authored
11月 14, 2023
作者:
lhh
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update
上级
6eb32f0e
显示空白字符变更
内嵌
并排
正在显示
17 个修改的文件
包含
1570 行增加
和
31 行删除
+1570
-31
menus.ts
src/assets/menus.ts
+8
-1
Header.vue
src/components/layout/Header.vue
+8
-3
AddStaff.vue
src/modules/admin/staff/components/AddStaff.vue
+36
-1
AddStudent.vue
src/modules/admin/student/components/AddStudent.vue
+18
-1
api.ts
src/modules/resource/dashboard/api.ts
+0
-6
Index.vue
src/modules/resource/dashboard/views/Index.vue
+65
-7
api.ts
src/modules/resource/timetable/api.ts
+46
-0
CardListItem.vue
src/modules/resource/timetable/components/CardListItem.vue
+167
-0
Operation.vue
src/modules/resource/timetable/components/Operation.vue
+205
-0
VideoDetail.vue
src/modules/resource/timetable/components/VideoDetail.vue
+89
-0
ViewCenter.vue
src/modules/resource/timetable/components/ViewCenter.vue
+103
-0
ViewTop.vue
src/modules/resource/timetable/components/ViewTop.vue
+162
-0
index.ts
src/modules/resource/timetable/index.ts
+14
-0
List.vue
src/modules/resource/timetable/views/List.vue
+215
-0
Update.vue
src/modules/resource/timetable/views/Update.vue
+394
-0
View.vue
src/modules/resource/timetable/views/View.vue
+28
-0
index.ts
src/router/index.ts
+12
-12
没有找到文件。
src/assets/menus.ts
浏览文件 @
a1956e7e
...
@@ -20,7 +20,8 @@ import {
...
@@ -20,7 +20,8 @@ import {
QuestionFilled
,
QuestionFilled
,
EditPen
,
EditPen
,
DataAnalysis
,
DataAnalysis
,
ChatDotRound
ChatDotRound
,
Calendar
}
from
'@element-plus/icons-vue'
}
from
'@element-plus/icons-vue'
export
const
menus
:
IMenuItem
[]
=
[
export
const
menus
:
IMenuItem
[]
=
[
{
{
...
@@ -28,6 +29,12 @@ export const menus: IMenuItem[] = [
...
@@ -28,6 +29,12 @@ export const menus: IMenuItem[] = [
name
:
'资源管理'
,
name
:
'资源管理'
,
path
:
'/resource'
,
path
:
'/resource'
,
children
:
[
children
:
[
{
// tag: 'v1-resource-video-list',
icon
:
Calendar
,
name
:
'课程表'
,
path
:
'/resource/timetable'
},
{
{
tag
:
'v1-resource-video-list'
,
tag
:
'v1-resource-video-list'
,
icon
:
VideoCamera
,
icon
:
VideoCamera
,
...
...
src/components/layout/Header.vue
浏览文件 @
a1956e7e
...
@@ -30,11 +30,16 @@ function genNavClassName(data: IMenuItem) {
...
@@ -30,11 +30,16 @@ function genNavClassName(data: IMenuItem) {
<header
class=
"app-header"
>
<header
class=
"app-header"
>
<div
class=
"app-header-left"
>
<div
class=
"app-header-left"
>
<div
class=
"logo"
>
<div
class=
"logo"
>
<router-link
to=
"/"
><img
src=
"https://zws-imgs-pub.ezijing.com/pc/base/ezijing-logo-white.svg"
/></router-link>
<router-link
to=
"/"
><img
style=
"height: 60px;"
src=
"https://zws-imgs-pub.oss-cn-beijing.aliyuncs.com/pc/base/logo%E5%89%AF%E6%9C%AC2.png"
/></router-link>
</div>
</div>
<h1
class=
"app-name"
>
统一资源管理平台
</h1>
<h1
class=
"app-name"
>
运维管理系统
</h1>
</div>
</div>
<div
class=
"app-header-nav"
>
<div
class=
"app-header-nav"
>
<div
class=
"app-header-nav-item"
>
<a
href=
"https://xjjt.obe.ezjing.com"
target=
"_blank"
>
人才培养
</a>
</div>
<div
<div
class=
"app-header-nav-item"
class=
"app-header-nav-item"
v-for=
"(item, index) in menus"
v-for=
"(item, index) in menus"
...
@@ -84,7 +89,7 @@ function genNavClassName(data: IMenuItem) {
...
@@ -84,7 +89,7 @@ function genNavClassName(data: IMenuItem) {
background-color
:
var
(
--
main-color
);
background-color
:
var
(
--
main-color
);
color
:
#fff
;
color
:
#fff
;
.logo
{
.logo
{
width
:
120px
;
//
width: 120px;
}
}
}
}
.app-header-left
{
.app-header-left
{
...
...
src/modules/admin/staff/components/AddStaff.vue
浏览文件 @
a1956e7e
...
@@ -40,7 +40,11 @@ const form: any = reactive({
...
@@ -40,7 +40,11 @@ const form: any = reactive({
mobile
:
''
,
mobile
:
''
,
role
:
[],
role
:
[],
email
:
''
,
email
:
''
,
status
:
'1'
status
:
'1'
,
age
:
''
,
education
:
''
,
title
:
''
,
work_experience
:
''
})
})
const
rules
=
reactive
<
FormRules
>
({
const
rules
=
reactive
<
FormRules
>
({
...
@@ -130,6 +134,34 @@ if (props.isEdit === '2' || props.isEdit === '1') {
...
@@ -130,6 +134,34 @@ if (props.isEdit === '2' || props.isEdit === '1') {
<el-radio
v-for=
"(item, index) in sexList"
:key=
"index"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
<el-radio
v-for=
"(item, index) in sexList"
:key=
"index"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
</el-radio-group>
</el-radio-group>
</el-form-item>
</el-form-item>
<el-form-item
label=
"年龄"
>
<el-input
v-model=
"form.age"
:disabled=
"props.isEdit === '2' || props.isEdit === '1'"
></el-input>
</el-form-item>
<el-form-item
label=
"学历"
>
<el-select
style=
"width: 100%"
v-model=
"form.education"
placeholder=
"请选择"
:disabled=
"props.isEdit === '2' || props.isEdit === '1'"
>
<el-option
key=
"博士"
label=
"博士"
value=
"博士"
/>
<el-option
key=
"硕士"
label=
"硕士"
value=
"硕士"
/>
<el-option
key=
"本科"
label=
"本科"
value=
"本科"
/>
<el-option
key=
"专科"
label=
"专科"
value=
"专科"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"职称"
>
<el-select
style=
"width: 100%"
v-model=
"form.title"
placeholder=
"请选择"
:disabled=
"props.isEdit === '2' || props.isEdit === '1'"
>
<el-option
key=
"初级"
label=
"初级"
value=
"初级"
/>
<el-option
key=
"中级"
label=
"中级"
value=
"中级"
/>
<el-option
key=
"高级"
label=
"高级"
value=
"高级"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"手机号"
prop=
"mobile"
>
<el-form-item
label=
"手机号"
prop=
"mobile"
>
<el-input
v-model=
"form.mobile"
:disabled=
"props.isEdit === '2' || props.isEdit === '1'"
></el-input>
<el-input
v-model=
"form.mobile"
:disabled=
"props.isEdit === '2' || props.isEdit === '1'"
></el-input>
</el-form-item>
</el-form-item>
...
@@ -141,6 +173,9 @@ if (props.isEdit === '2' || props.isEdit === '1') {
...
@@ -141,6 +173,9 @@ if (props.isEdit === '2' || props.isEdit === '1') {
<el-form-item
label=
"邮箱"
prop=
"email"
>
<el-form-item
label=
"邮箱"
prop=
"email"
>
<el-input
v-model=
"form.email"
:disabled=
"props.isEdit === '2'"
/>
<el-input
v-model=
"form.email"
:disabled=
"props.isEdit === '2'"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"工作经历"
>
<el-input
type=
"textarea"
v-model=
"form.work_experience"
:disabled=
"props.isEdit === '2'"
/>
</el-form-item>
<el-form-item
label=
"生效状态"
prop=
"status"
>
<el-form-item
label=
"生效状态"
prop=
"status"
>
<el-radio-group
v-model=
"form.status"
:disabled=
"props.isEdit === '2'"
>
<el-radio-group
v-model=
"form.status"
:disabled=
"props.isEdit === '2'"
>
<el-radio
v-for=
"(item, index) in statusList"
:key=
"index"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
<el-radio
v-for=
"(item, index) in statusList"
:key=
"index"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
...
...
src/modules/admin/student/components/AddStudent.vue
浏览文件 @
a1956e7e
...
@@ -27,7 +27,9 @@ const form: any = reactive({
...
@@ -27,7 +27,9 @@ const form: any = reactive({
organ_id
:
''
,
organ_id
:
''
,
specialty_id
:
''
,
specialty_id
:
''
,
class_id
:
''
,
class_id
:
''
,
status
:
'1'
status
:
'1'
,
address
:
''
,
join_time
:
''
})
})
const
rules
=
reactive
<
FormRules
>
({
const
rules
=
reactive
<
FormRules
>
({
sno_number
:
[{
required
:
true
,
message
:
'请输入学号'
,
trigger
:
'blur'
}],
sno_number
:
[{
required
:
true
,
message
:
'请输入学号'
,
trigger
:
'blur'
}],
...
@@ -196,6 +198,21 @@ if (props.isEdit === '2' || props.isEdit === '1') {
...
@@ -196,6 +198,21 @@ if (props.isEdit === '2' || props.isEdit === '1') {
<el-form-item
label=
"证件号码"
prop=
"id_number"
>
<el-form-item
label=
"证件号码"
prop=
"id_number"
>
<el-input
v-model=
"form.id_number"
:disabled=
"props.isEdit === '2'"
/>
<el-input
v-model=
"form.id_number"
:disabled=
"props.isEdit === '2'"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"家庭住址"
>
<el-input
v-model=
"form.address"
:disabled=
"props.isEdit === '2'"
/>
</el-form-item>
<el-form-item
label=
"入学时间"
>
<!--
<el-input
v-model=
"form.join_time"
:disabled=
"props.isEdit === '2'"
/>
-->
<el-date-picker
style=
"width: 100%"
v-model=
"form.join_time"
type=
"month"
format=
"YYYY/MM"
placeholder=
"请选择"
:disabled=
"props.isEdit === '2'"
/>
<!--
<el-date-picker
v-model=
"form.join_time"
type=
"datetime"
:disabled=
"props.isEdit === '2'"
placeholder=
"请选择"
format=
"YYYY/MM/DD HH:mm:ss"
/>
-->
</el-form-item>
<el-form-item
label=
"所属部门/学校"
prop=
"organ_id"
>
<el-form-item
label=
"所属部门/学校"
prop=
"organ_id"
>
<el-select
<el-select
clearable
clearable
...
...
src/modules/resource/dashboard/api.ts
浏览文件 @
a1956e7e
...
@@ -4,8 +4,3 @@ import httpRequest from '@/utils/axios'
...
@@ -4,8 +4,3 @@ import httpRequest from '@/utils/axios'
export
function
getUtilData
()
{
export
function
getUtilData
()
{
return
httpRequest
.
get
(
'/api/resource/v1/util/index'
)
return
httpRequest
.
get
(
'/api/resource/v1/util/index'
)
}
}
export
function
aa
()
{
return
httpRequest
.
get
(
'/api/otn/leftTicket/queryZ?leftTicketDTO.train_date=2023-04-28&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=DTV&purpose_codes=ADULT'
)
}
// https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2023-04-28&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=DTV&purpose_codes=ADULT
\ No newline at end of file
src/modules/resource/dashboard/views/Index.vue
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
aa
}
from
'../api'
import
Statistics
from
'../components/Statistics.vue'
aa
().
then
(
res
=>
{
import
Newest
from
'../components/Newest.vue'
console
.
log
(
res
,
'res'
)
import
Hottest
from
'../components/Hottest.vue'
import
RecentLearning
from
'../components/RecentLearning.vue'
import
{
getUtilData
}
from
'../api'
let
flag
=
$ref
(
false
)
const
data
=
reactive
<
{
statistics
:
object
[];
latest
:
object
[];
hot
:
object
[];
learn
:
object
[]
}
>
({
statistics
:
[],
latest
:
[],
hot
:
[],
learn
:
[]
})
// 所有数据
getUtilData
().
then
(
res
=>
{
flag
=
true
let
{
latest
=
[],
hot
=
[],
learn
=
[]
}:
{
latest
:
object
[];
hot
:
object
[];
learn
:
object
[]
}
=
res
.
data
if
(
learn
===
null
)
learn
=
[]
// 统计资源数据整合
const
statisticsData
=
[
{
key
:
'video_count'
,
unit
:
'个'
,
number
:
0
,
text
:
'视频资源'
},
{
key
:
'courseware_count'
,
unit
:
'个'
,
number
:
0
,
text
:
'课件资源'
},
{
key
:
'other_information_count'
,
unit
:
'个'
,
number
:
0
,
text
:
'其他资料'
},
{
key
:
'question_count'
,
unit
:
'个'
,
number
:
0
,
text
:
'题库资源'
},
{
key
:
'paper_count'
,
unit
:
'套'
,
number
:
0
,
text
:
'试卷资源'
},
{
key
:
'memory_size'
,
unit
:
''
,
number
:
0
,
text
:
'资源总体量'
},
{
key
:
'length'
,
unit
:
'小时'
,
number
:
0
,
text
:
'资源总时长'
},
{
key
:
'learn_times'
,
unit
:
'人次'
,
number
:
0
,
text
:
'总学习人次'
},
{
key
:
'learn_time_length'
,
unit
:
'小时'
,
number
:
0
,
text
:
'总学习时长'
}
]
data
.
statistics
=
statisticsData
.
map
((
item
:
any
)
=>
{
item
.
number
=
res
.
data
[
item
.
key
]
||
0
return
item
})
// 最近数据
data
.
latest
=
latest
.
map
((
item
:
any
,
index
:
number
)
=>
{
item
.
index
=
index
+
1
return
item
})
||
[]
// 最热资源
data
.
hot
=
hot
.
map
((
item
:
any
,
index
:
number
)
=>
{
item
.
index
=
index
+
1
return
item
})
||
[]
data
.
learn
=
learn
.
map
((
item
:
any
,
index
:
number
)
=>
{
item
.
index
=
index
+
1
return
item
})
||
[]
})
})
// aa().then(res => {
// console.log(res, 'res')
// })
</
script
>
</
script
>
<
template
>
<
template
>
<div>
111
</div>
<div
v-if=
"flag"
>
<AppCard
title=
"资源统计"
>
<Statistics
:data=
"data.statistics"
></Statistics>
</AppCard>
<AppCard
title=
"最新资源"
>
<Newest
:data=
"data.latest"
></Newest>
</AppCard>
<AppCard
:data=
"data.hot"
title=
"最热资源"
>
<Hottest
:data=
"data.hot"
></Hottest>
</AppCard>
<AppCard
title=
"最近学习"
>
<RecentLearning
:data=
"data.learn"
></RecentLearning>
</AppCard>
</div>
</
template
>
</
template
>
src/modules/resource/timetable/api.ts
0 → 100644
浏览文件 @
a1956e7e
import
httpRequest
from
'@/utils/axios'
// 获取课程表列表
export
function
getTimetableList
(
params
:
{
tab
:
string
;
status
?:
string
;
authorized
?:
string
;
classification
?:
string
;
page
?:
number
;
page_size
?:
number
})
{
return
httpRequest
.
get
(
'/api/resource/v1/resource/school-timetable/list'
,
{
params
})
}
// 创建课程表
export
function
createTimetable
(
data
:
any
)
{
return
httpRequest
.
post
(
'/api/resource/v1/resource/school-timetable/create'
,
data
)
}
// 获取学期
export
function
getSemestersList
()
{
return
httpRequest
.
get
(
'/api/resource/v1/resource/school-timetable/semesters'
)
}
// 获取课程表详情
export
function
getTimetableDetails
(
params
:
{
id
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/resource/school-timetable/view'
,
{
params
})
}
// 更新课程表
export
function
updateTimetable
(
data
:
{
id
:
string
;
name
:
string
;
classification
:
string
;
knowledge_points
?:
string
;
cover
?:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/resource/school-timetable/update'
,
data
)
}
// 部门共享
export
function
setDepartment
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/resource/school-timetable/set-department'
,
data
)
}
// 平台共享
export
function
setPlatform
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/resource/school-timetable/set-platform'
,
data
)
}
// 上下线
export
function
setStatus
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/resource/school-timetable/set-status'
,
data
)
}
// 更改负责人
export
function
setBelong
(
data
:
{
id
:
string
;
belong_operator
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/resource/school-timetable/set-belong'
,
data
)
}
src/modules/resource/timetable/components/CardListItem.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
const
props
:
any
=
defineProps
<
{
data
:
object
;
tabIndex
:
string
}
>
()
</
script
>
<
template
>
<div
class=
"card-item"
>
<div
class=
"card-item-top"
>
<div
class=
"title"
>
{{
props
.
data
.
name
}}
</div>
<!--
<img
:src=
"props.data.cover"
/>
-->
<div
class=
"cover-img"
:style=
"`background-image:url($
{props.data.url})`">
</div>
<div
class=
"tool-pop-btn"
>
<div
style=
"min-width: 100%"
>
<router-link
v-if=
"props.data.auth_edit"
:to=
"`/resource/timetable/update?id=$
{props.data.id}`">
<div
class=
"edit-btn btn"
>
编辑
</div>
</router-link>
</div>
<div
style=
"min-width: 100%"
>
<router-link
v-if=
"props.data.auth_view"
:to=
"`/resource/timetable/view?id=$
{props.data.id}`">
<div
class=
"view-btn btn"
>
查看
</div>
</router-link>
</div>
</div>
</div>
<div
class=
"card-item-bottom"
>
<div
class=
"item-t"
>
<el-popover
trigger=
"hover"
placement=
"right"
>
<div
v-html=
"props.data.created_operator_name + '/' + props.data.organ_id_name"
></div>
<template
#
reference
>
<div
class=
"text"
>
{{
props
.
data
.
created_operator_name
}}
/
{{
props
.
data
.
organ_id_name
}}
</div>
</
template
>
</el-popover>
<div
:class=
"props.data.status == 1 ? 'tag green' : 'tag'"
>
{{ props.data.status_name }}
</div>
</div>
<div
class=
"item-b"
>
<div
class=
"time"
>
{{ props.data.updated_time }}
</div>
<div
class=
"tag1"
v-if=
"tabIndex === '2'"
>
{{ props.data.department_public === '0' ? '未共享' : '已共享' }}
</div>
<div
class=
"tag1"
v-if=
"tabIndex === '3'"
>
{{ props.data.platform_public === '0' ? '未共享' : '已共享' }}
</div>
</div>
</div>
</div>
</template>
<
style
lang=
"scss"
scoped
>
.card-item
{
width
:
18%
;
border-radius
:
6px
;
overflow
:
hidden
;
margin-right
:
10px
;
margin-bottom
:
20px
;
.card-item-top
{
height
:
170px
;
position
:
relative
;
&
:hover
{
.tool-pop-btn
{
opacity
:
1
;
}
}
.cover-img
{
width
:
100%
;
height
:
100%
;
background-size
:
cover
;
}
.title
{
position
:
absolute
;
bottom
:
0
;
left
:
0
;
width
:
100%
;
line-height
:
37px
;
background
:
rgba
(
0
,
0
,
0
,
0
.4
);
font-size
:
18px
;
color
:
#ffffff
;
padding-left
:
16px
;
box-sizing
:
border-box
;
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
.tool-pop-btn
{
transition
:
all
0
.5s
;
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
100%
;
background
:
rgba
(
0
,
0
,
0
,
0
.6
);
opacity
:
0
;
padding-top
:
52px
;
box-sizing
:
border-box
;
.edit-btn
{
width
:
113px
;
line-height
:
32px
;
background
:
#aa1941
;
border-radius
:
18px
;
text-align
:
center
;
font-size
:
14px
;
color
:
#ffffff
;
margin
:
0
auto
12px
;
cursor
:
pointer
;
}
.btn
:hover
{
background
:
none
;
border
:
1px
solid
#d3d3d3
;
}
.view-btn
{
width
:
113px
;
line-height
:
32px
;
background
:
#aa1941
;
border-radius
:
18px
;
text-align
:
center
;
font-size
:
14px
;
color
:
#ffffff
;
margin
:
0
auto
;
cursor
:
pointer
;
}
}
}
}
.card-item-bottom
{
background
:
#fff
;
padding
:
20px
16px
30px
;
.item-t
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
.text
{
width
:
150px
;
font-size
:
16px
;
line-height
:
100%
;
color
:
#666666
;
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
.tag
{
width
:
48px
;
line-height
:
22px
;
background
:
#aa1941
;
border-radius
:
11px
;
font-size
:
14px
;
color
:
#fff
;
text-align
:
center
;
&
.green
{
background
:
#1ab226
;
}
}
}
.item-b
{
margin-top
:
18px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
.time
{
font-size
:
14px
;
line-height
:
100%
;
color
:
#999999
;
}
.tag1
{
font-size
:
16px
;
line-height
:
100%
;
color
:
#999999
;
word-break
:
keep-all
;
}
}
}
</
style
>
src/modules/resource/timetable/components/Operation.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
import
{
setDepartment
,
setPlatform
,
setStatus
,
setBelong
}
from
'../api'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
useProjectList
}
from
'@/composables/useGetProjectList'
const
router
=
useRouter
()
const
route
=
useRoute
()
const
props
=
defineProps
([
'data'
])
// 详情id
const
id
=
route
.
query
.
id
as
string
// 设置部门共享
const
handleDepartment
=
()
=>
{
ElMessageBox
.
confirm
(
`
${
parseInt
(
props
.
data
.
department_public
)
===
0
?
`该操作将会使本课程表资源在您所在的部门“
${
props
.
data
.
organ_id_name
}
”内部共享,管理者不变,其余人员只能共享使用该资源,确认部门共享吗?`
:
`该操作将会取消本课程表资源在您所在的部门“
${
props
.
data
.
organ_id_name
}
”内部共享,部门其余人员将不能再看到该共享资源,确认取消部门共享吗?`
}
`
,
'提示'
,
{
confirmButtonText
:
'确认'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}
).
then
(()
=>
{
setDepartment
({
id
:
id
}).
then
((
res
:
any
)
=>
{
if
(
res
.
code
===
0
)
{
ElMessage
({
message
:
'更改成功'
,
type
:
'success'
})
setTimeout
(()
=>
{
router
.
go
(
0
)
},
500
)
}
})
})
}
// 设置平台共享
const
handlePlatform
=
()
=>
{
ElMessageBox
.
confirm
(
`
${
parseInt
(
props
.
data
.
platform_public
)
===
0
?
'该操作将会使本课程表资源在e-SaaS平台中公开共享供所有老师使用,资源的管理者不变,其余人员只能共享使用该资源,确认公开该资源吗?'
:
'该操作将会取消本课程表资源在e-SaaS平台中公开共享,平台所有人员将不能再看到该共享资源,确认取消平台共享吗?'
}
`
,
'提示'
,
{
confirmButtonText
:
'确认'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}
).
then
(()
=>
{
setPlatform
({
id
:
id
}).
then
((
res
:
any
)
=>
{
if
(
res
.
code
===
0
)
{
ElMessage
({
message
:
'更改成功'
,
type
:
'success'
})
setTimeout
(()
=>
{
router
.
go
(
0
)
},
500
)
}
})
})
}
// 上下线设置
const
handleStatus
=
()
=>
{
ElMessageBox
.
confirm
(
`
${
parseInt
(
props
.
data
.
status
)
===
1
?
'已下线的资源将不能被关联到课程使用,确认下线该资源吗?'
:
'确认再次上线该资源吗?'
}
`
,
'提示'
,
{
confirmButtonText
:
'确认'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}
).
then
(()
=>
{
setStatus
({
id
:
id
}).
then
((
res
:
any
)
=>
{
if
(
res
.
code
===
0
)
{
ElMessage
({
message
:
'更改成功'
,
type
:
'success'
})
setTimeout
(()
=>
{
router
.
go
(
0
)
},
500
)
}
})
})
}
// 更该负责人
const
form
=
reactive
({
members
:
''
})
const
dialogFormVisible
=
ref
(
false
)
// 人员列表
let
members
:
any
=
ref
([])
// 点击更改负责人按钮弹窗
const
handleMembers
=
()
=>
{
dialogFormVisible
.
value
=
true
members
.
value
=
useProjectList
(
props
.
data
.
organ_id
).
members
}
// 更改负责人确定
const
handlesetBelong
=
()
=>
{
setBelong
({
id
:
id
,
belong_operator
:
form
.
members
}).
then
((
res
:
any
)
=>
{
if
(
res
.
code
===
0
)
{
ElMessage
({
message
:
'更改成功'
,
type
:
'success'
})
setTimeout
(()
=>
{
dialogFormVisible
.
value
=
false
},
500
)
}
})
}
</
script
>
<
template
>
<div
class=
"tool-btn-box"
v-if=
"$route.query.id"
style=
"margin-bottom: 20px"
>
<template
v-if=
"props.data.auth_edit"
>
<router-link
:to=
"`/resource/timetable/update?id=$
{id}`">
<div
class=
"btn-item"
>
编辑课程表信息
</div>
</router-link>
<!--
<router-link
:to=
"`/resource/video/edit-courseware?id=$
{id}`">
<div
class=
"btn-item"
>
编辑课程表课件
</div>
</router-link>
-->
</
template
>
<div
v-if=
"props.data.auth_department"
class=
"btn-item"
@
click=
"handleDepartment"
>
{{ props.data.department_public == 0 ? '部门共享' : '取消部门共享' }}
</div>
<div
v-if=
"props.data.auth_platform"
class=
"btn-item"
@
click=
"handlePlatform"
>
{{ props.data.platform_public == 0 ? '平台共享' : '取消平台共享' }}
</div>
<div
v-if=
"props.data.auth_status"
v-permission=
"'v1-resource-video-set-status'"
class=
"btn-item"
@
click=
"handleStatus"
>
{{ props.data.status == 0 ? '资源上线' : '资源下线' }}
</div>
<div
v-if=
"props.data.auth_belong"
class=
"btn-item"
@
click=
"handleMembers"
>
更改负责人
</div>
</div>
<el-dialog
v-model=
"dialogFormVisible"
title=
"更改负责人"
center
>
<el-form
:model=
"form"
>
<el-form-item>
<div
style=
"width: 500px"
>
<el-row>
<el-col
:span=
"12"
><div
class=
"grid-content ep-bg-purple"
/>
资源创建人: {{ props.data.created_operator_name }}
</el-col>
<el-col
:span=
"12"
><div
class=
"grid-content ep-bg-purple-light"
/>
创建时间: {{ props.data.created_time }}
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
><div
class=
"grid-content ep-bg-purple"
/>
资源负责人: {{ props.data.belong_operator_name }}
</el-col>
<el-col
:span=
"12"
><div
class=
"grid-content ep-bg-purple-light"
/>
更新时间: {{ props.data.updated_time }}
</el-col>
</el-row>
</div>
<el-select
style=
"width: 500px; margin-top: 20px"
v-model=
"form.members"
placeholder=
"请选择新的资源负责人"
>
<el-option
v-for=
"item in members.value"
:label=
"item.name"
:value=
"item.id"
:key=
"item.id"
/>
</el-select>
</el-form-item>
</el-form>
<
template
#
footer
>
<span
class=
"dialog-footer"
>
<el-button
@
click=
"dialogFormVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"handlesetBelong"
>
确认
</el-button>
</span>
</
template
>
</el-dialog>
</template>
<
style
lang=
"scss"
scoped
>
.tool-btn-box
{
display
:
flex
;
justify-content
:
right
;
.btn-item
{
width
:
127px
;
line-height
:
36px
;
background
:
#aa1941
;
border-radius
:
20px
;
margin-right
:
10px
;
font-size
:
14px
;
color
:
#ffffff
;
text-align
:
center
;
cursor
:
pointer
;
}
}
</
style
>
src/modules/resource/timetable/components/VideoDetail.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
lang=
"ts"
setup
>
interface
UploadInfo
{
bucket
:
string
checkpoint
:
{
file
:
File
;
name
:
string
;
fileSize
:
number
;
partSize
:
number
;
uploadId
:
string
}
endpoint
:
string
file
:
File
fileHash
:
string
isImage
:
boolean
loaded
:
number
object
:
string
region
:
string
retry
:
boolean
ri
:
string
state
:
string
userData
:
string
videoId
:
string
videoInfo
:
any
progress
:
number
}
interface
Props
{
videoList
:
UploadInfo
[]
modelValue
:
boolean
}
interface
Emits
{
(
e
:
'update:modelValue'
,
modelValue
:
boolean
):
void
}
const
props
=
defineProps
<
Props
>
()
const
emit
=
defineEmits
<
Emits
>
()
const
currentPage
=
ref
(
1
)
const
page
=
reactive
({
size
:
10
,
currentPage
:
1
})
const
handleCancel
=
function
()
{
emit
(
'update:modelValue'
,
false
)
}
const
handleSizeChange
=
(
val
:
any
)
=>
{
page
.
size
=
val
}
const
handleCurrentChange
=
(
val
:
any
)
=>
{
page
.
currentPage
=
val
}
function
percentage
(
value
:
number
)
{
return
parseFloat
((
value
?
value
*
100
:
0
).
toFixed
(
2
))
}
</
script
>
<
template
>
<el-dialog
:model-value=
"props.modelValue"
title=
"更多视频文件"
:before-close=
"handleCancel"
width=
"30vw"
>
<div
v-for=
"(item, index) in props.videoList.slice((page.currentPage - 1) * page.size, page.currentPage * page.size)"
:key=
"index"
>
<div
class=
"video-info"
>
<span
class=
"name"
>
{{
item
.
file
?.
name
}}
</span>
<el-progress
style=
"width: 200px"
:percentage=
"percentage(item.loaded)"
class=
"view"
/>
</div>
</div>
<el-pagination
v-model:currentPage=
"currentPage"
:page-size=
"page.size"
layout=
"total, sizes, prev, pager, next, jumper"
:page-sizes=
"[5, 10, 20, 30, 50]"
:total=
"props.videoList.length"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
>
</el-pagination>
</el-dialog>
</
template
>
<
style
lang=
"scss"
scoped
>
.video-info
{
display
:
flex
;
margin-top
:
10px
;
.name
{
color
:
#333333
;
font-size
:
14px
;
line-height
:
1
.5
;
}
.view
{
font-size
:
16px
;
line-height
:
100%
;
margin-left
:
20px
;
cursor
:
pointer
;
}
}
:deep
(
.el-pagination
)
{
margin-top
:
20px
;
}
</
style
>
src/modules/resource/timetable/components/ViewCenter.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
import
AppVideoPlayer
from
'@/components/base/AppVideoPlayer.vue'
const
props
=
defineProps
([
'data'
])
const
videoOptions
=
$computed
(()
=>
{
return
{
sources
:
[
{
src
:
props
.
data
.
play_auth
.
play_info_list
.
find
((
item
:
any
)
=>
{
return
item
.
Definition
===
'SD'
}).
PlayURL
}
]
}
})
</
script
>
<
template
>
<div
class=
"center-video-box"
>
<div
class=
"right-statistics"
>
<div
class=
"stat-item"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/view-vicon1.png"
/>
<div
class=
"content"
>
<div
class=
"unit"
>
{{
data
.
project_count
}}
<span>
个
</span></div>
<div
class=
"tag"
>
使用项目/学校
</div>
</div>
</div>
<div
class=
"stat-item"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/view-vicon2.png"
/>
<div
class=
"content"
>
<div
class=
"unit"
>
{{
data
.
course_count
}}
<span>
门
</span></div>
<div
class=
"tag"
>
使用课程
</div>
</div>
</div>
<div
class=
"stat-item"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/view-vicon3.png"
/>
<div
class=
"content"
>
<div
class=
"unit"
>
{{
data
.
learn_count
}}
<span>
人次
</span></div>
<div
class=
"tag"
>
累计学习人次
</div>
</div>
</div>
<div
class=
"stat-item"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/view-vicon4.png"
/>
<div
class=
"content"
>
<div
class=
"unit"
>
{{
data
.
learn_time_count
}}
<span>
分钟
</span></div>
<div
class=
"tag"
>
累计学习时长
</div>
</div>
</div>
</div>
<div
style=
"width: 100%; background: #000"
>
<div
style=
"margin: 0 auto; width: 80%"
>
<img
:src=
"data?.url"
style=
"width: 100%;"
>
<!--
<AppVideoPlayer
:isAdd=
"true"
:options=
"videoOptions"
></AppVideoPlayer>
-->
</div>
</div>
</div>
</
template
>
<
style
lang=
"scss"
scoped
>
.center-video-box
{
padding
:
20px
0
;
.right-statistics
{
margin
:
0
auto
;
display
:
flex
;
padding-top
:
15px
;
justify-content
:
space-between
;
.stat-item
{
width
:
24%
;
height
:
85px
;
background
:
#b41e47
;
border-radius
:
6px
;
display
:
flex
;
align-items
:
center
;
// margin: 0 auto 20px;
margin-bottom
:
20px
;
&
:nth-child
(
even
)
{
background
:
#bf9d6b
;
}
img
{
width
:
52px
;
height
:
52px
;
display
:
block
;
margin-left
:
18px
;
}
.content
{
margin-left
:
18px
;
.unit
{
font-size
:
26px
;
line-height
:
100%
;
color
:
#ffffff
;
span
{
font-size
:
12px
;
line-height
:
100%
;
}
}
.tag
{
font-size
:
14px
;
line-height
:
100%
;
color
:
#ffffff
;
margin-top
:
10px
;
}
}
}
}
}
</
style
>
src/modules/resource/timetable/components/ViewTop.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
import
{
PictureFilled
}
from
'@element-plus/icons-vue'
const
props
=
defineProps
([
'data'
])
</
script
>
<
template
>
<div
class=
"video-info"
>
<div
class=
"video-img"
>
<div
v-if=
"props.data.url"
class=
"img"
:style=
"`width: 210px;height: 140px;background-size: cover;background-image: url($
{props.data.url});`"
>
</div>
<el-icon
v-else
:size=
"200"
color=
"#ccc"
>
<PictureFilled></PictureFilled>
</el-icon>
<!--
<img
:src=
"props.data.cover"
>
-->
<!--
<div
class=
"name"
>
视频封面
</div>
-->
</div>
<div
class=
"info-items"
>
<div
class=
"flex-box"
>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon5.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
课程表名称
</div>
<div
class=
"value"
>
{{
props
.
data
.
name
}}
</div>
</div>
</div>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon7.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
课程表分类
</div>
<div
class=
"value"
>
{{
props
.
data
.
classification_name
||
'暂无'
}}
</div>
</div>
</div>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon1.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
状态
</div>
<div
:class=
"props.data.status == '1' ? 'value active' : 'value inactive'"
>
{{
props
.
data
.
status_name
}}
</div>
</div>
</div>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon3.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
创建时间
</div>
<div
class=
"value"
>
{{
props
.
data
.
created_time
}}
</div>
</div>
</div>
</div>
<div
class=
"flex-box"
>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon12.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
创建者
</div>
<div
class=
"value"
>
{{
props
.
data
.
created_operator_name
}}
</div>
</div>
</div>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/course-view-icon13.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
负责人
</div>
<div
class=
"value"
>
{{
props
.
data
.
belong_operator_name
}}
</div>
</div>
</div>
<div
class=
"i-items"
style=
"align-items: flex-start"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon8.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
知识点
</div>
<div
class=
"value"
>
{{
props
.
data
?.
knowledge_points
||
'暂无'
}}
</div>
</div>
</div>
<div
class=
"i-items"
>
<img
src=
"https://webapp-pub.ezijing.com/center_resource/video-view-icon4.png"
class=
"icons"
/>
<div
class=
"text-box"
>
<div
class=
"name"
>
更新时间
</div>
<div
class=
"value"
>
{{
props
.
data
.
updated_time
}}
</div>
</div>
</div>
</div>
</div>
</div>
</
template
>
<
style
lang=
"scss"
scoped
>
.video-info
{
background
:
#f7f7f7
;
margin-top
:
20px
;
padding
:
20px
;
display
:
flex
;
.video-img
{
width
:
211px
;
text-align
:
center
;
img
{
width
:
211px
;
display
:
block
;
}
.name
{
font-size
:
16px
;
line-height
:
100%
;
color
:
#666666
;
margin-top
:
12px
;
text-align
:
center
;
}
}
.info-items
{
display
:
flex
;
flex-direction
:
column
;
flex
:
1
;
padding
:
12px
0
;
.flex-box
{
display
:
flex
;
justify-content
:
space-around
;
}
.i-items
:not
(
:last-child
)
{
border-right
:
1px
dashed
rgb
(
191
,
191
,
191
);
}
.i-items
{
width
:
25%
;
display
:
flex
;
align-items
:
center
;
height
:
fit-content
;
margin-bottom
:
30px
;
padding-left
:
5%
;
.textarea-box
{
padding
:
18px
18px
51px
;
background
:
#ffffff
;
border-radius
:
4px
;
font-size
:
16px
;
line-height
:
24px
;
color
:
#505050
;
margin-top
:
14px
;
min-width
:
500px
;
}
.text-box
{
margin-left
:
16px
;
.name
{
font-size
:
14px
;
line-height
:
100%
;
color
:
#999
;
}
.value
{
font-size
:
14px
;
line-height
:
100%
;
color
:
#333
;
font-family
:
Source
Han
Sans
CN
;
margin-top
:
8px
;
word-break
:
break-all
;
&
.active
{
color
:
#1ab226
;
}
&
.inactive
{
color
:
#aa1941
;
}
}
}
}
}
}
</
style
>
src/modules/resource/timetable/index.ts
0 → 100644
浏览文件 @
a1956e7e
import
type
{
RouteRecordRaw
}
from
'vue-router'
import
AppLayout
from
'@/components/layout/Index.vue'
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
{
path
:
'/resource/timetable'
,
component
:
AppLayout
,
children
:
[
{
path
:
''
,
component
:
()
=>
import
(
'./views/List.vue'
)
},
{
path
:
'update'
,
component
:
()
=>
import
(
'./views/Update.vue'
)
},
{
path
:
'view'
,
component
:
()
=>
import
(
'./views/View.vue'
)
}
]
}
]
src/modules/resource/timetable/views/List.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
import
{
getTimetableList
,
getSemestersList
}
from
'../api'
import
CardListItem
from
'../components/CardListItem.vue'
import
{
PictureFilled
}
from
'@element-plus/icons-vue'
import
{
useGetCategoryList
}
from
'@/composables/useGetCategoryList'
import
{
useProjectList
}
from
'@/composables/useGetProjectList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useUserStore
}
from
'@/stores/user'
// import BatchImportVideo from '../components/BatchImportVideo.vue'
// 学期
let
semestersList
:
any
=
$ref
([])
getSemestersList
().
then
((
res
:
any
)
=>
{
semestersList
=
res
.
data
})
// 判断当前用户是不是超级管理员
const
user
=
useUserStore
().
roles
const
isAdmin
=
!!
user
.
find
((
item
:
any
)
=>
item
.
name
===
'超级管理员'
)
const
store
=
useMapStore
()
// const router = useRouter()
// 筛选部门列表
const
departmentList
:
any
=
useProjectList
(
''
,
'79806610719731712'
).
departmentList
// 筛选下拉选择tree 视频分类
let
{
list
:
selectTree
}:
any
=
useGetCategoryList
()
const
defaultProps
=
{
children
:
'children'
,
label
:
'category_name'
,
value
:
'id'
}
// 资源出处 tab触发
const
tabValue
=
ref
(
'1'
)
const
appList
=
ref
()
// const isShowBatchImport = ref(false)
const
tabChange
=
()
=>
{
appList
.
value
.
refetch
()
}
// 列表切换
let
isCard
=
$ref
(
true
)
// table 数据
const
listOptions
=
$computed
(()
=>
{
const
columns
=
[
{
label
:
'课程表标题'
,
prop
:
'name'
,
align
:
'center'
,
computed
({
row
}:
any
)
{
return
row
.
name
?.
length
>
10
?
`
${
row
.
name
.
slice
(
0
,
10
)}
...`
:
row
.
name
}
},
{
label
:
'课程表分类'
,
prop
:
'classification_name'
,
align
:
'center'
},
{
label
:
'知识点'
,
prop
:
'knowledge_points'
,
align
:
'center'
},
// { label: '封面', slots: 'table-cover', width: 150, align: 'center' },
{
label
:
'资源状态'
,
prop
:
'status_name'
,
align
:
'center'
},
{
label
:
'审核状态'
,
prop
:
'audit_status_name'
,
align
:
'center'
},
{
label
:
'更新人'
,
prop
:
'updated_operator_name'
,
align
:
'center'
},
{
label
:
'更新人部门'
,
prop
:
'organ_id_name'
,
align
:
'center'
},
{
label
:
'更新日期'
,
prop
:
'updated_time'
,
align
:
'center'
},
{
label
:
'操作'
,
slots
:
'table-operate'
,
align
:
'center'
,
width
:
200
,
fixed
:
'right'
}
]
if
(
tabValue
.
value
===
'2'
)
{
columns
.
splice
(
2
,
0
,
{
label
:
'部门共享'
,
prop
:
'department_public_name'
,
align
:
'center'
})
}
if
(
tabValue
.
value
===
'3'
)
{
columns
.
splice
(
2
,
0
,
{
label
:
'平台共享'
,
prop
:
'platform_public_name'
,
align
:
'center'
})
}
return
{
remote
:
{
httpRequest
:
getTimetableList
,
params
:
{
tab
:
tabValue
,
status
:
''
,
authorized
:
''
,
name
:
''
,
semesters_id
:
''
}
},
filters
:
[
{
type
:
'select'
,
prop
:
'status'
,
label
:
'状态:'
,
options
:
store
.
getMapValuesByKey
(
'system_status'
)
},
{
prop
:
'classification'
,
label
:
'类别:'
,
slots
:
'filter-type'
},
{
type
:
'input'
,
prop
:
'name'
,
label
:
'标题:'
},
{
type
:
'select'
,
prop
:
'semesters_id'
,
label
:
'学期:'
,
options
:
semestersList
,
valueKey
:
'id'
,
labelKey
:
'name'
},
{
prop
:
'authorized'
,
slots
:
'filter-department'
}
],
columns
}
})
const
typeFilter
=
()
=>
{
appList
.
value
.
refetch
()
}
const
changeCard
=
()
=>
{
isCard
=
!
isCard
}
// 批量上传
const
handleBatchImport
=
()
=>
{
window
.
open
(
'/resource/video/upload'
)
// router.push('/resource/video/upload')
// isShowBatchImport.value = true
}
</
script
>
<
template
>
<AppCard>
<div
class=
"video-head"
>
<el-tabs
@
tab-change=
"tabChange"
v-model=
"tabValue"
>
<el-tab-pane
label=
"我的资源"
name=
"1"
></el-tab-pane>
<el-tab-pane
label=
"部门资源"
name=
"2"
></el-tab-pane>
<el-tab-pane
label=
"公开资源"
name=
"3"
></el-tab-pane>
</el-tabs>
<div
class=
"video-head-icon"
@
click=
"changeCard"
>
<img
v-if=
"!isCard"
src=
"https://webapp-pub.ezijing.com/center_resource/change_card.png"
alt=
""
/>
<img
v-else
src=
"https://webapp-pub.ezijing.com/center_resource/change_list.png"
alt=
""
/>
</div>
</div>
<div
class=
"video-tool-btn"
>
<router-link
v-if=
"tabValue === '1'"
to=
"/resource/timetable/update"
>
<el-button
type=
"primary"
round
>
新建课程表资源
</el-button>
</router-link>
<!--
<el-button
v-if=
"tabValue === '1'"
type=
"primary"
round
@
click=
"handleBatchImport"
style=
"margin-left: 20px"
>
批量上传
</el-button
>
-->
</div>
<AppList
v-bind=
"listOptions"
ref=
"appList"
>
<template
#
header-aside
></
template
>
<
template
#
table-cover=
"{ row }"
>
<div
style=
"background: #ccc"
>
<el-icon
:size=
"50"
color=
"#fff"
v-if=
"row.cover == ''"
>
<PictureFilled></PictureFilled>
</el-icon>
<div
v-else
:style=
"`width: 150px;
display: block;
height: 83px;
background-size: cover;
background-image: url($
{row.cover});`"
>
</div>
</div>
</
template
>
<
template
#
filter-type=
"{ params }"
>
<el-tree-select
node-key=
"id"
@
change=
"typeFilter"
clearable
:props=
"defaultProps"
v-model=
"params.classification"
:data=
"selectTree"
:default-expanded-keys=
"selectTree.length ? [selectTree[0]?.id] : []"
/>
</
template
>
<
template
v-if=
"tabValue == '3' && isAdmin"
#
filter-department=
"{ params }"
>
<div
class=
"name"
style=
"font-size: 14px; color: #606266; padding-right: 12px"
>
部门:
</div>
<el-select
@
change=
"typeFilter"
clearable
v-model=
"params.authorized"
>
<el-option
v-for=
"item in departmentList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
template
#
table-operate=
"{ row }"
>
<el-space>
<router-link
v-if=
"row.auth_edit"
:to=
"`/resource/timetable/update?id=$
{row.id}`">
<el-button
plain
>
编辑
</el-button>
</router-link>
<router-link
:to=
"`/resource/timetable/view?id=$
{row.id}`">
<el-button
type=
"primary"
plain
>
查看
</el-button>
</router-link>
</el-space>
</
template
>
<!-- 卡片 -->
<
template
#
body=
"{ data }"
v-if=
"isCard"
>
<div
class=
"card-list"
v-if=
"data.length"
>
<CardListItem
:tabIndex=
"tabValue"
v-for=
"(item, index) in data"
:data=
"item"
:key=
"index"
></CardListItem>
</div>
<!--
<el-empty
v-else
description=
"暂无数据"
/>
-->
</
template
>
</AppList>
</AppCard>
<!-- <BatchImportVideo v-model="isShowBatchImport" v-if="isShowBatchImport === true" @update="typeFilter" /> -->
</template>
<
style
lang=
"scss"
scoped
>
.card-list
{
background
:
#fafafa
;
display
:
flex
;
flex-wrap
:
wrap
;
padding
:
20px
0
;
}
.video-head
{
position
:
relative
;
.video-head-icon
{
position
:
absolute
;
top
:
0
;
right
:
0
;
font-size
:
30px
;
color
:
#666
;
cursor
:
pointer
;
}
}
.video-tool-btn
{
padding
:
10px
0
30px
0
;
}
</
style
>
src/modules/resource/timetable/views/Update.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
type
{
FormInstance
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
createTimetable
,
getTimetableDetails
,
updateTimetable
,
getSemestersList
}
from
'../api'
import
{
useGetCategoryList
}
from
'@/composables/useGetCategoryList'
import
Protocol
from
'@/components/base/Protocol.vue'
// 路由
const
router
=
useRouter
()
const
route
=
useRoute
()
const
id
=
route
.
query
.
id
as
string
// is 编辑 新建
const
isUpdate
=
$computed
(()
=>
{
return
!!
route
.
query
.
id
})
// 编辑数据回显
if
(
isUpdate
)
{
getTimetableDetails
({
id
:
id
}).
then
((
res
:
any
)
=>
{
form
=
res
.
data
form
.
file
=
[
{
name
:
res
.
data
.
name
,
url
:
res
.
data
.
url
}
]
})
}
// 下拉选择tree 视频分类
let
{
list
:
selectTree
}:
any
=
useGetCategoryList
()
const
defaultProps
=
{
children
:
'children'
,
label
:
'category_name'
,
value
:
'id'
}
// form表单
let
form
:
any
=
$ref
({
file
:
[],
name
:
''
,
source
:
'2'
,
classification
:
''
,
knowledge_points
:
''
,
url
:
''
,
type
:
''
,
size
:
''
,
semesters_id
:
[]
})
// 监听文件上传
watch
(
()
=>
form
.
file
,
value
=>
{
if
(
value
[
0
]?.
name
.
indexOf
(
'.'
)
!=
-
1
)
{
form
.
name
=
value
[
0
]?.
name
.
slice
(
0
,
value
[
0
]?.
name
.
lastIndexOf
(
'.'
))
||
''
}
}
)
// 表单验证
const
rules
=
{
name
:
[{
required
:
true
,
message
:
'请输入标题'
,
trigger
:
'blur'
}],
semesters_id
:
[{
required
:
true
,
message
:
'请选择学期'
,
trigger
:
'change'
}],
classification
:
[{
required
:
true
,
message
:
'请选择分类'
,
trigger
:
'change'
}],
file
:
[{
required
:
true
,
message
:
''
}]
}
// 新建编辑表单提交
const
ruleFormRef
=
ref
<
FormInstance
>
()
let
submitFlag
=
true
const
submitForm
=
async
(
formEl
:
FormInstance
|
undefined
)
=>
{
if
(
!
formEl
)
return
if
(
!
submitFlag
)
return
submitFlag
=
false
await
formEl
.
validate
(
valid
=>
{
if
(
valid
)
{
if
(
!
protocol
.
value
)
{
submitFlag
=
true
ElMessage
(
'请勾选用户协议'
)
return
}
const
{
url
,
size
}
=
form
.
file
[
0
]
const
findString
=
url
.
lastIndexOf
(
'.'
)
+
1
form
.
url
=
url
form
.
type
=
url
.
substring
(
findString
,
url
.
length
)
form
.
size
=
size
form
.
semesters_id
=
form
.
semesters_id
.
toString
()
const
params
=
Object
.
assign
({},
form
)
delete
params
.
file
if
(
isUpdate
)
{
params
.
id
=
id
updateResources
(
params
)
}
else
{
createResources
(
params
)
}
}
else
{
submitFlag
=
true
ElMessage
(
'请完善信息'
)
}
})
}
// 更新
const
updateResources
=
(
params
:
any
)
=>
{
updateTimetable
(
params
)
.
then
((
res
:
any
)
=>
{
if
(
res
.
code
===
0
)
{
ElMessage
({
message
:
'更新成功'
,
type
:
'success'
})
setTimeout
(()
=>
{
router
.
push
({
path
:
'/resource/timetable'
})
},
1000
)
}
else
{
submitFlag
=
true
}
})
.
catch
(()
=>
{
submitFlag
=
true
})
}
// 新建
const
createResources
=
(
params
:
any
)
=>
{
createTimetable
(
params
)
.
then
((
res
:
any
)
=>
{
if
(
res
.
code
===
0
)
{
ElMessage
({
message
:
'创建成功'
,
type
:
'success'
})
setTimeout
(()
=>
{
router
.
push
({
path
:
'/resource/timetable'
})
},
1000
)
}
else
{
submitFlag
=
true
}
})
.
catch
(()
=>
{
submitFlag
=
true
})
}
// 协议
const
protocol
=
ref
(
false
)
const
changeProtocol
=
(
data
:
any
)
=>
{
protocol
.
value
=
data
.
value
}
let
semestersList
:
any
=
$ref
([])
getSemestersList
().
then
((
res
:
any
)
=>
{
semestersList
=
res
.
data
})
</
script
>
<
template
>
<AppCard
:title=
"isUpdate ? '编辑课程表资源' : '新建课程表资源'"
>
<el-form
ref=
"ruleFormRef"
:model=
"form"
:rules=
"rules"
style=
"width: 70%"
>
<el-form-item
label=
"课程表文件:"
prop=
"file"
>
<div>
<div
class=
"upload-video"
>
<div
class=
"upload-box"
>
<AppUpload
accept=
".png,.jpeg,.jpg"
:limit=
"1"
v-model=
"form.file"
></AppUpload>
<div
class=
"upload-btn"
>
本地文件
</div>
</div>
</div>
<div
class=
"tips"
>
课程表支持格式包含:png jpeg jpg,大小不超过50M
</div>
</div>
</el-form-item>
<el-form-item
label=
"课程表名称:"
prop=
"name"
>
<el-input
maxlength=
"40"
v-model=
"form.name"
/>
<div
class=
"tips"
>
课程表名称自动取值于文件名称,可以进行二次修改。
</div>
</el-form-item>
<el-form-item
label=
"课程表分类:"
prop=
"classification"
>
<el-tree-select
:render-after-expand=
"false"
style=
"width: 100%"
:props=
"defaultProps"
v-model=
"form.classification"
:data=
"selectTree"
placeholder=
"请选择课程表分类"
node-key=
"id"
:default-expanded-keys=
"selectTree.length ? [selectTree[0]?.id] : []"
/>
</el-form-item>
<el-form-item
label-width=
"105px"
label=
"学期:"
prop=
"semesters_id"
>
<el-select
style=
"width: 100%"
v-model=
"form.semesters_id"
multiple
placeholder=
"请选择学期"
>
<el-option
v-for=
"item in semestersList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label-width=
"105px"
label=
"知识点:"
>
<el-input
placeholder=
"请输入该课程表相关知识点,多个知识点请使用“,”分隔"
maxlength=
"100"
v-model=
"form.knowledge_points"
:rows=
"2"
type=
"textarea"
/>
</el-form-item>
</el-form>
<div
class=
"protocol-box"
>
<Protocol
@
change=
"changeProtocol"
></Protocol>
</div>
<div
class=
"btn-box"
>
<div
class=
"confirm"
@
click=
"submitForm(ruleFormRef)"
>
保存
</div>
<div
class=
"cancel"
@
click=
"router.go(-1)"
>
取消
</div>
</div>
</AppCard>
</
template
>
<
style
lang=
"scss"
>
.tips
{
font-size
:
12px
;
line-height
:
100%
;
color
:
#999999
;
margin-top
:
8px
;
}
.upload-box
{
// min-width: 400px;
.el-progress__text
{
transform
:
translate
(
20px
,
-5px
);
}
position
:
relative
;
.app-upload-btn
{
position
:
relative
;
z-index
:
99
;
opacity
:
0
.0001
!
important
;
}
}
.tips
{
font-size
:
12px
;
line-height
:
100%
;
color
:
#999999
;
margin-top
:
8px
;
}
.tool-btn-box
{
display
:
flex
;
justify-content
:
right
;
.btn-item
{
width
:
127px
;
line-height
:
36px
;
background
:
#aa1941
;
border-radius
:
20px
;
margin-right
:
10px
;
font-size
:
14px
;
color
:
#ffffff
;
text-align
:
center
;
}
}
.demo-progress
{
width
:
350px
;
}
.video-cover
{
display
:
flex
;
.img-box
{
width
:
208px
;
height
:
130px
;
border-radius
:
4px
;
background
:
#f7f7f7
;
font-size
:
20px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
img
{
width
:
100%
;
height
:
100%
;
display
:
block
;
}
}
.video-cover_right
{
margin-left
:
20px
;
.list
{
.item
{
display
:
flex
;
align-items
:
center
;
margin-top
:
12px
;
img
{
width
:
9px
;
display
:
block
;
margin-right
:
5px
;
}
.text
{
font-size
:
12px
;
color
:
#999999
;
line-height
:
100%
;
}
}
}
}
}
.swiper-box
{
min-width
:
660px
;
margin-top
:
20px
;
padding
:
0
40px
;
position
:
relative
;
.arrow
{
position
:
absolute
;
top
:
50%
;
transform
:
translateY
(
-50%
);
font-size
:
30px
;
color
:
#d5d5d5
;
cursor
:
pointer
;
&
.left
{
left
:
0
;
}
&
.right
{
right
:
10px
;
}
}
.cover-list
{
display
:
flex
;
flex-wrap
:
wrap
;
.cover-list_item
{
display
:
block
;
width
:
155px
;
height
:
96px
;
margin
:
0
10px
10px
0
;
border-radius
:
4px
;
cursor
:
pointer
;
}
}
}
:deep
(
.el-carousel__indicators--horizontal
)
{
display
:
none
;
}
.protocol-box
{
font-size
:
14px
;
line-height
:
24px
;
padding-left
:
90px
;
padding-top
:
20px
;
color
:
#666666
;
}
.btn-box
{
display
:
flex
;
margin-top
:
20px
;
margin-left
:
90px
;
.confirm
{
width
:
94px
;
background
:
#aa1941
;
border-radius
:
20px
;
text-align
:
center
;
line-height
:
36px
;
color
:
#fff
;
margin-right
:
26px
;
cursor
:
pointer
;
}
.cancel
{
width
:
94px
;
line-height
:
36px
;
border
:
1px
solid
#aa1941
;
border-radius
:
20px
;
text-align
:
center
;
color
:
#aa1941
;
cursor
:
pointer
;
}
}
.upload-video
{
width
:
500px
;
display
:
flex
;
align-items
:
center
;
.upload-btn
{
position
:
absolute
;
top
:
0
;
left
:
0
;
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
>
src/modules/resource/timetable/views/View.vue
0 → 100644
浏览文件 @
a1956e7e
<
script
setup
lang=
"ts"
>
import
ViewTop
from
'../components/ViewTop.vue'
import
ViewCenter
from
'../components/ViewCenter.vue'
import
Operation
from
'../components/Operation.vue'
import
ResourceCourseList
from
'@/components/ResourceCourseList.vue'
import
DataAccess
from
'@/components/DataAccess.vue'
import
{
getTimetableDetails
}
from
'../api'
// 路由
const
route
=
useRoute
()
const
id
=
route
.
query
.
id
as
string
let
videoDetails
:
any
=
ref
({})
// 获取详情
getTimetableDetails
({
id
:
id
}).
then
(
res
=>
{
videoDetails
.
value
=
res
.
data
})
</
script
>
<
template
>
<AppCard
title=
"课程表资源信息"
>
<Operation
v-if=
"Object.keys(videoDetails).length"
:data=
"videoDetails"
></Operation>
<ViewTop
v-if=
"Object.keys(videoDetails).length"
:data=
"videoDetails"
></ViewTop>
<ViewCenter
v-if=
"Object.keys(videoDetails).length"
:data=
"videoDetails"
></ViewCenter>
<!--
<DataAccess
v-if=
"Object.keys(videoDetails).length"
:data=
"videoDetails"
></DataAccess>
-->
</AppCard>
<ResourceCourseList
title=
"课程表资源关联使用课程"
:list=
"videoDetails.course_list"
></ResourceCourseList>
</
template
>
src/router/index.ts
浏览文件 @
a1956e7e
import
{
createRouter
,
createWebHistory
}
from
'vue-router'
import
{
createRouter
,
createWebHistory
}
from
'vue-router'
//
import { useUserStore } from '@/stores/user'
import
{
useUserStore
}
from
'@/stores/user'
const
router
=
createRouter
({
const
router
=
createRouter
({
history
:
createWebHistory
(),
history
:
createWebHistory
(),
...
@@ -7,17 +7,17 @@ const router = createRouter({
...
@@ -7,17 +7,17 @@ const router = createRouter({
})
})
router
.
beforeEach
(
async
(
to
,
from
,
next
)
=>
{
router
.
beforeEach
(
async
(
to
,
from
,
next
)
=>
{
//
const whiteList = ['/401']
const
whiteList
=
[
'/401'
]
//
const user = useUserStore()
const
user
=
useUserStore
()
//
if (!user.isLogin && !whiteList.includes(to.path)) {
if
(
!
user
.
isLogin
&&
!
whiteList
.
includes
(
to
.
path
))
{
//
try {
try
{
//
await user.getUser()
await
user
.
getUser
()
//
} catch (e) {
}
catch
(
e
)
{
//
console.error(e)
console
.
error
(
e
)
//
}
}
//
user.isLogin ? next() : next('/401')
user
.
isLogin
?
next
()
:
next
(
'/401'
)
//
return
return
//
}
}
next
()
next
()
})
})
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论