Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
3241135a
提交
3241135a
authored
7月 07, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 添加删除功能,支持删除实验指导书、案例原文和操作视频
上级
00476186
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
94 行增加
和
64 行删除
+94
-64
api.ts
src/modules/admin/lab/book/api.ts
+5
-0
FormDialog.vue
src/modules/admin/lab/book/components/FormDialog.vue
+5
-15
types.ts
src/modules/admin/lab/book/types.ts
+3
-1
Index.vue
src/modules/admin/lab/book/views/Index.vue
+18
-3
api.ts
src/modules/admin/lab/case/api.ts
+5
-0
FormDialog.vue
src/modules/admin/lab/case/components/FormDialog.vue
+5
-22
types.ts
src/modules/admin/lab/case/types.ts
+0
-1
Index.vue
src/modules/admin/lab/case/views/Index.vue
+20
-3
api.ts
src/modules/admin/lab/video/api.ts
+5
-0
FormDialog.vue
src/modules/admin/lab/video/components/FormDialog.vue
+5
-15
types.ts
src/modules/admin/lab/video/types.ts
+3
-1
Index.vue
src/modules/admin/lab/video/views/Index.vue
+20
-3
没有找到文件。
src/modules/admin/lab/book/api.ts
浏览文件 @
3241135a
...
@@ -27,3 +27,8 @@ export function createBook(data: BookCreateItem) {
...
@@ -27,3 +27,8 @@ export function createBook(data: BookCreateItem) {
export
function
updateBook
(
data
:
BookCreateItem
)
{
export
function
updateBook
(
data
:
BookCreateItem
)
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/book/update'
,
data
)
return
httpRequest
.
post
(
'/api/lab/v1/teacher/book/update'
,
data
)
}
}
// 删除指导书
export
function
deleteBook
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/book/delete'
,
data
)
}
src/modules/admin/lab/book/components/FormDialog.vue
浏览文件 @
3241135a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
BookItem
,
BookCreateItem
}
from
'../types'
import
type
{
Book
FormData
,
Book
Item
,
BookCreateItem
}
from
'../types'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
{
createBook
,
updateBook
}
from
'../api'
import
{
createBook
,
updateBook
}
from
'../api'
import
{
useGetCourseList
}
from
'../composables/useGetCourseList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
...
@@ -19,32 +18,29 @@ const emit = defineEmits<{
...
@@ -19,32 +18,29 @@ const emit = defineEmits<{
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
}
>
()
}
>
()
// 课程列表
const
{
courses
}
=
useGetCourseList
()
// 数据状态
// 数据状态
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
// 实验列表
// 实验列表
const
{
experiments
,
updateExperiments
}
=
useGetExperimentList
()
const
{
experiments
,
updateExperiments
}
=
useGetExperimentList
()
const
formRef
=
$ref
<
FormInstance
>
()
const
formRef
=
$ref
<
FormInstance
>
()
const
form
=
reactive
<
Book
CreateItem
>
({
const
form
=
reactive
<
Book
FormData
>
({
name
:
''
,
name
:
''
,
course_id
:
''
,
experiment_id
:
''
,
experiment_id
:
''
,
status
:
'1'
,
status
:
'1'
,
url
:
''
,
url
:
''
,
type
:
''
,
type
:
''
,
size
:
''
,
size
:
''
,
files
:
[],
files
:
[],
protocol
:
fals
e
protocol
:
tru
e
})
})
watchEffect
(()
=>
{
watchEffect
(()
=>
{
if
(
!
props
.
data
)
return
if
(
!
props
.
data
)
return
form
.
files
=
[{
name
:
props
.
data
.
name
,
url
:
props
.
data
.
url
,
type
:
props
.
data
.
type
}]
form
.
files
=
[{
name
:
props
.
data
.
name
,
url
:
props
.
data
.
url
,
type
:
props
.
data
.
type
}]
Object
.
assign
(
form
,
{
protocol
:
true
},
props
.
data
)
Object
.
assign
(
form
,
{
protocol
:
true
},
props
.
data
)
})
})
watchEffect
(()
=>
{
onMounted
(()
=>
{
updateExperiments
(
form
.
course_id
)
updateExperiments
()
})
})
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
if
(
!
value
)
{
if
(
!
value
)
{
...
@@ -56,7 +52,6 @@ const checkProtocol = (rule: any, value: any, callback: any) => {
...
@@ -56,7 +52,6 @@ const checkProtocol = (rule: any, value: any, callback: any) => {
const
rules
=
ref
<
FormRules
>
({
const
rules
=
ref
<
FormRules
>
({
files
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请上传实验指导书'
}],
files
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请上传实验指导书'
}],
name
:
[{
required
:
true
,
message
:
'请输入实验指导书名称'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'请输入实验指导书名称'
,
trigger
:
'blur'
}],
course_id
:
[{
required
:
true
,
message
:
'请选择关联实验课程'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联实验'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联实验'
,
trigger
:
'change'
}],
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
})
})
...
@@ -121,11 +116,6 @@ function handleUpdate(params: BookCreateItem) {
...
@@ -121,11 +116,6 @@ function handleUpdate(params: BookCreateItem) {
<el-input
v-model=
"form.name"
></el-input>
<el-input
v-model=
"form.name"
></el-input>
<p
class=
"form-tips"
>
实验指导书名称自动取值于文件名称,可以进行二次修改。
</p>
<p
class=
"form-tips"
>
实验指导书名称自动取值于文件名称,可以进行二次修改。
</p>
</el-form-item>
</el-form-item>
<el-form-item
label=
"关联实验课程"
prop=
"course_id"
>
<el-select
v-model=
"form.course_id"
filterable
style=
"width: 100%"
@
change=
"form.experiment_id = ''"
>
<el-option
v-for=
"item in courses"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"关联实验"
prop=
"experiment_id"
>
<el-form-item
label=
"关联实验"
prop=
"experiment_id"
>
<el-select
v-model=
"form.experiment_id"
filterable
style=
"width: 100%"
>
<el-select
v-model=
"form.experiment_id"
filterable
style=
"width: 100%"
>
<el-option
v-for=
"item in experiments"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
<el-option
v-for=
"item in experiments"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
...
...
src/modules/admin/lab/book/types.ts
浏览文件 @
3241135a
...
@@ -24,12 +24,14 @@ export interface BookItem {
...
@@ -24,12 +24,14 @@ export interface BookItem {
export
interface
BookCreateItem
{
export
interface
BookCreateItem
{
id
?:
string
id
?:
string
experiment_id
:
string
experiment_id
:
string
course_id
:
string
status
:
string
status
:
string
name
:
string
name
:
string
type
:
string
type
:
string
url
:
string
url
:
string
size
:
string
size
:
string
}
export
interface
BookFormData
extends
BookCreateItem
{
protocol
:
boolean
protocol
:
boolean
files
:
FileItem
[]
files
:
FileItem
[]
}
}
...
...
src/modules/admin/lab/book/views/Index.vue
浏览文件 @
3241135a
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
import
type
{
BookItem
}
from
'../types'
import
type
{
BookItem
}
from
'../types'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
useLocalStorage
}
from
'@vueuse/core'
import
{
useLocalStorage
}
from
'@vueuse/core'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
AppList
from
'@/components/base/AppList.vue'
import
AppList
from
'@/components/base/AppList.vue'
import
ListItem
from
'../components/ListItem.vue'
import
ListItem
from
'../components/ListItem.vue'
import
{
getBookList
}
from
'../api'
import
{
deleteBook
,
getBookList
}
from
'../api'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
...
@@ -63,7 +64,7 @@ const listOptions = $computed(() => {
...
@@ -63,7 +64,7 @@ const listOptions = $computed(() => {
{
label
:
'创建人'
,
prop
:
'created_operator_name'
,
width
:
120
},
{
label
:
'创建人'
,
prop
:
'created_operator_name'
,
width
:
120
},
{
label
:
'创建时间'
,
prop
:
'created_time'
,
width
:
180
},
{
label
:
'创建时间'
,
prop
:
'created_time'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
width
:
180
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
1
60
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
2
60
},
],
],
}
}
})
})
...
@@ -81,6 +82,14 @@ function handleUpdate(row: BookItem) {
...
@@ -81,6 +82,14 @@ function handleUpdate(row: BookItem) {
dialogVisible
=
true
dialogVisible
=
true
}
}
async
function
handleDelete
(
row
:
BookItem
)
{
ElMessageBox
.
confirm
(
`确定要删除实验指导书“
${
row
.
name
}
”吗?`
,
'提示'
).
then
(
async
()
=>
{
await
deleteBook
({
id
:
row
.
id
})
ElMessage
.
success
(
'删除成功'
)
appList
?.
refetch
()
})
}
function
onUpdateSuccess
()
{
function
onUpdateSuccess
()
{
appList
?.
refetch
()
appList
?.
refetch
()
}
}
...
@@ -118,7 +127,12 @@ function onUpdateSuccess() {
...
@@ -118,7 +127,12 @@ function onUpdateSuccess() {
</
template
>
</
template
>
<
template
#
body=
"{ data }"
v-if=
"viewMode === 'card'"
>
<
template
#
body=
"{ data }"
v-if=
"viewMode === 'card'"
>
<div
class=
"list-card"
v-if=
"data.length"
>
<div
class=
"list-card"
v-if=
"data.length"
>
<ListItem
v-for=
"item in data"
:data=
"item"
:key=
"item.id"
@
clickEdit=
"handleUpdate(item)"
></ListItem>
<ListItem
v-for=
"item in data"
:data=
"item"
:key=
"item.id"
@
clickEdit=
"handleUpdate(item)"
@
clickDelete=
"handleDelete(item)"
></ListItem>
</div>
</div>
<el-empty
description=
"暂无数据"
v-else
/>
<el-empty
description=
"暂无数据"
v-else
/>
</
template
>
</
template
>
...
@@ -129,6 +143,7 @@ function onUpdateSuccess() {
...
@@ -129,6 +143,7 @@ function onUpdateSuccess() {
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'v1-teacher-book-update'"
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'v1-teacher-book-update'"
>
编辑
</el-button
>
编辑
</el-button
>
>
<el-button
type=
"danger"
round
@
click=
"handleDelete(row)"
v-permission=
"'v1-teacher-book-delete'"
>
删除
</el-button>
</
template
>
</
template
>
<
template
#
table-status=
"{ row }: { row: BookItem }"
>
<
template
#
table-status=
"{ row }: { row: BookItem }"
>
<span
:class=
"isActiveStatus(row.status) ? 'status-active' : 'status-inactive'"
>
{{
row
.
status_name
}}
</span>
<span
:class=
"isActiveStatus(row.status) ? 'status-active' : 'status-inactive'"
>
{{
row
.
status_name
}}
</span>
...
...
src/modules/admin/lab/case/api.ts
浏览文件 @
3241135a
...
@@ -27,3 +27,8 @@ export function createCase(data: CaseCreateItem) {
...
@@ -27,3 +27,8 @@ export function createCase(data: CaseCreateItem) {
export
function
updateCase
(
data
:
CaseCreateItem
)
{
export
function
updateCase
(
data
:
CaseCreateItem
)
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/experiment-cases/update'
,
data
)
return
httpRequest
.
post
(
'/api/lab/v1/teacher/experiment-cases/update'
,
data
)
}
}
// 删除案例原文
export
function
deleteCase
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/experiment-cases/delete'
,
data
)
}
src/modules/admin/lab/case/components/FormDialog.vue
浏览文件 @
3241135a
...
@@ -5,7 +5,6 @@ import { ElMessageBox, ElMessage } from 'element-plus'
...
@@ -5,7 +5,6 @@ import { ElMessageBox, ElMessage } from 'element-plus'
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
{
createCase
,
updateCase
}
from
'../api'
import
{
createCase
,
updateCase
}
from
'../api'
import
{
useGetCourseList
}
from
'../composables/useGetCourseList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
...
@@ -19,8 +18,6 @@ const emit = defineEmits<{
...
@@ -19,8 +18,6 @@ const emit = defineEmits<{
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
}
>
()
}
>
()
// 课程列表
const
{
courses
}
=
useGetCourseList
()
// 数据状态
// 数据状态
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
// 实验列表
// 实验列表
...
@@ -29,22 +26,21 @@ const { experiments, updateExperiments } = useGetExperimentList()
...
@@ -29,22 +26,21 @@ const { experiments, updateExperiments } = useGetExperimentList()
const
formRef
=
$ref
<
FormInstance
>
()
const
formRef
=
$ref
<
FormInstance
>
()
const
form
=
reactive
<
CaseFormData
>
({
const
form
=
reactive
<
CaseFormData
>
({
name
:
''
,
name
:
''
,
course_id
:
''
,
experiment_id
:
''
,
experiment_id
:
''
,
status
:
'1'
,
status
:
'1'
,
url
:
''
,
url
:
''
,
type
:
''
,
type
:
''
,
size
:
''
,
size
:
''
,
files
:
[],
files
:
[],
protocol
:
fals
e
protocol
:
tru
e
})
})
watchEffect
(()
=>
{
watchEffect
(()
=>
{
if
(
!
props
.
data
)
return
if
(
!
props
.
data
)
return
form
.
files
=
[{
name
:
props
.
data
.
name
,
url
:
props
.
data
.
url
,
type
:
props
.
data
.
type
}]
form
.
files
=
[{
name
:
props
.
data
.
name
,
url
:
props
.
data
.
url
,
type
:
props
.
data
.
type
}]
Object
.
assign
(
form
,
{
protocol
:
true
,
course_id
:
props
.
data
.
course
.
id
},
props
.
data
)
Object
.
assign
(
form
,
{
protocol
:
true
},
props
.
data
)
})
})
watchEffect
(()
=>
{
onMounted
(()
=>
{
updateExperiments
(
form
.
course_id
)
updateExperiments
()
})
})
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
if
(
!
value
)
{
if
(
!
value
)
{
...
@@ -56,7 +52,6 @@ const checkProtocol = (rule: any, value: any, callback: any) => {
...
@@ -56,7 +52,6 @@ const checkProtocol = (rule: any, value: any, callback: any) => {
const
rules
=
ref
<
FormRules
>
({
const
rules
=
ref
<
FormRules
>
({
files
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请上传案例原文'
}],
files
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请上传案例原文'
}],
name
:
[{
required
:
true
,
message
:
'请输入案例原文名称'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'请输入案例原文名称'
,
trigger
:
'blur'
}],
course_id
:
[{
required
:
true
,
message
:
'请选择关联实验课程'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联实验'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联实验'
,
trigger
:
'change'
}],
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
})
})
...
@@ -66,13 +61,6 @@ const isUpdate = $computed(() => {
...
@@ -66,13 +61,6 @@ const isUpdate = $computed(() => {
const
title
=
$computed
(()
=>
{
const
title
=
$computed
(()
=>
{
return
isUpdate
?
'编辑案例原文'
:
'新增案例原文'
return
isUpdate
?
'编辑案例原文'
:
'新增案例原文'
})
})
// 实验列表
const
experimentList
=
$computed
(()
=>
{
if
(
!
props
.
data
)
return
experiments
.
value
return
isUpdate
&&
props
.
data
.
course
.
id
===
form
.
course_id
?
[{
id
:
props
.
data
.
experiment_id
,
name
:
props
.
data
.
experiment
.
name
},
...
experiments
.
value
]
:
experiments
.
value
})
function
handleBeforeUpload
()
{
function
handleBeforeUpload
()
{
if
(
form
.
files
.
length
)
{
if
(
form
.
files
.
length
)
{
...
@@ -128,14 +116,9 @@ function handleUpdate(params: CaseUpdateItem) {
...
@@ -128,14 +116,9 @@ function handleUpdate(params: CaseUpdateItem) {
<el-input
v-model=
"form.name"
></el-input>
<el-input
v-model=
"form.name"
></el-input>
<p
class=
"form-tips"
>
案例原文名称自动取值于文件名称,可以进行二次修改。
</p>
<p
class=
"form-tips"
>
案例原文名称自动取值于文件名称,可以进行二次修改。
</p>
</el-form-item>
</el-form-item>
<el-form-item
label=
"关联实验课程"
prop=
"course_id"
>
<el-select
v-model=
"form.course_id"
filterable
style=
"width: 100%"
@
change=
"form.experiment_id = ''"
>
<el-option
v-for=
"item in courses"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"关联实验"
prop=
"experiment_id"
>
<el-form-item
label=
"关联实验"
prop=
"experiment_id"
>
<el-select
v-model=
"form.experiment_id"
filterable
style=
"width: 100%"
>
<el-select
v-model=
"form.experiment_id"
filterable
style=
"width: 100%"
>
<el-option
v-for=
"item in experiment
List
"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
<el-option
v-for=
"item in experiment
s
"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"有效状态"
prop=
"status"
>
<el-form-item
label=
"有效状态"
prop=
"status"
>
...
...
src/modules/admin/lab/case/types.ts
浏览文件 @
3241135a
...
@@ -33,7 +33,6 @@ export interface CaseOperator {
...
@@ -33,7 +33,6 @@ export interface CaseOperator {
export
interface
CaseFormData
{
export
interface
CaseFormData
{
id
?:
string
id
?:
string
experiment_id
:
string
experiment_id
:
string
course_id
:
string
status
:
string
status
:
string
name
:
string
name
:
string
type
:
string
type
:
string
...
...
src/modules/admin/lab/case/views/Index.vue
浏览文件 @
3241135a
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
import
type
{
CaseItem
}
from
'../types'
import
type
{
CaseItem
}
from
'../types'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
useLocalStorage
}
from
'@vueuse/core'
import
{
useLocalStorage
}
from
'@vueuse/core'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
AppList
from
'@/components/base/AppList.vue'
import
AppList
from
'@/components/base/AppList.vue'
import
ListItem
from
'../components/ListItem.vue'
import
ListItem
from
'../components/ListItem.vue'
import
{
getCaseList
}
from
'../api'
import
{
deleteCase
,
getCaseList
}
from
'../api'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
...
@@ -95,7 +96,7 @@ const listOptions = $computed(() => {
...
@@ -95,7 +96,7 @@ const listOptions = $computed(() => {
{
label
:
'创建人'
,
prop
:
'created_operator_name'
,
width
:
120
},
{
label
:
'创建人'
,
prop
:
'created_operator_name'
,
width
:
120
},
{
label
:
'创建时间'
,
prop
:
'created_time'
,
width
:
180
},
{
label
:
'创建时间'
,
prop
:
'created_time'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
width
:
180
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
1
60
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
2
60
},
],
],
}
}
})
})
...
@@ -113,6 +114,14 @@ function handleUpdate(row: CaseItem) {
...
@@ -113,6 +114,14 @@ function handleUpdate(row: CaseItem) {
dialogVisible
=
true
dialogVisible
=
true
}
}
async
function
handleDelete
(
row
:
CaseItem
)
{
ElMessageBox
.
confirm
(
`确定要删除案例原文“
${
row
.
name
}
”吗?`
,
'提示'
).
then
(
async
()
=>
{
await
deleteCase
({
id
:
row
.
id
})
ElMessage
.
success
(
'删除成功'
)
appList
?.
refetch
()
})
}
function
onUpdateSuccess
()
{
function
onUpdateSuccess
()
{
appList
?.
refetch
()
appList
?.
refetch
()
}
}
...
@@ -150,7 +159,12 @@ function onUpdateSuccess() {
...
@@ -150,7 +159,12 @@ function onUpdateSuccess() {
</
template
>
</
template
>
<
template
#
body=
"{ data }: { data: CaseListRow[] }"
v-if=
"viewMode === 'card'"
>
<
template
#
body=
"{ data }: { data: CaseListRow[] }"
v-if=
"viewMode === 'card'"
>
<div
class=
"list-card"
v-if=
"viewMode === 'card' && data.length"
>
<div
class=
"list-card"
v-if=
"viewMode === 'card' && data.length"
>
<ListItem
v-for=
"item in data"
:data=
"item"
:key=
"item.id"
@
clickEdit=
"handleUpdate(item)"
></ListItem>
<ListItem
v-for=
"item in data"
:data=
"item"
:key=
"item.id"
@
clickEdit=
"handleUpdate(item)"
@
clickDelete=
"handleDelete(item)"
></ListItem>
</div>
</div>
<el-empty
description=
"暂无数据"
v-else
/>
<el-empty
description=
"暂无数据"
v-else
/>
</
template
>
</
template
>
...
@@ -161,6 +175,9 @@ function onUpdateSuccess() {
...
@@ -161,6 +175,9 @@ function onUpdateSuccess() {
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'teacher-experiment-cases-update'"
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'teacher-experiment-cases-update'"
>
编辑
</el-button
>
编辑
</el-button
>
>
<el-button
type=
"danger"
round
@
click=
"handleDelete(row)"
v-permission=
"'teacher-experiment-cases-delete'"
>
删除
</el-button
>
</
template
>
</
template
>
<
template
#
table-status=
"{ row }: { row: CaseListRow }"
>
<
template
#
table-status=
"{ row }: { row: CaseListRow }"
>
<span
:class=
"isActiveStatus(row.status) ? 'status-active' : 'status-inactive'"
>
{{
row
.
status_name
}}
</span>
<span
:class=
"isActiveStatus(row.status) ? 'status-active' : 'status-inactive'"
>
{{
row
.
status_name
}}
</span>
...
...
src/modules/admin/lab/video/api.ts
浏览文件 @
3241135a
...
@@ -27,3 +27,8 @@ export function createVideo(data: VideoCreateItem) {
...
@@ -27,3 +27,8 @@ export function createVideo(data: VideoCreateItem) {
export
function
updateVideo
(
data
:
VideoCreateItem
)
{
export
function
updateVideo
(
data
:
VideoCreateItem
)
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/video/update'
,
data
)
return
httpRequest
.
post
(
'/api/lab/v1/teacher/video/update'
,
data
)
}
}
// 删除操作视频
export
function
deleteVideo
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/video/delete'
,
data
)
}
src/modules/admin/lab/video/components/FormDialog.vue
浏览文件 @
3241135a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
VideoItem
,
VideoCreateItem
}
from
'../types'
import
type
{
Video
FormData
,
Video
Item
,
VideoCreateItem
}
from
'../types'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
UploadVideo
from
'@/components/UploadVideo.vue'
import
UploadVideo
from
'@/components/UploadVideo.vue'
import
{
createVideo
,
updateVideo
}
from
'../api'
import
{
createVideo
,
updateVideo
}
from
'../api'
import
{
useGetCourseList
}
from
'../composables/useGetCourseList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
...
@@ -19,28 +18,25 @@ const emit = defineEmits<{
...
@@ -19,28 +18,25 @@ const emit = defineEmits<{
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
}
>
()
}
>
()
// 课程列表
const
{
courses
}
=
useGetCourseList
()
// 数据状态
// 数据状态
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
// 实验列表
// 实验列表
const
{
experiments
,
updateExperiments
}
=
useGetExperimentList
()
const
{
experiments
,
updateExperiments
}
=
useGetExperimentList
()
const
formRef
=
$ref
<
FormInstance
>
()
const
formRef
=
$ref
<
FormInstance
>
()
const
form
=
reactive
<
Video
CreateItem
>
({
const
form
=
reactive
<
Video
FormData
>
({
name
:
''
,
name
:
''
,
course_id
:
''
,
experiment_id
:
''
,
experiment_id
:
''
,
status
:
'1'
,
status
:
'1'
,
source_id
:
''
,
source_id
:
''
,
protocol
:
fals
e
protocol
:
tru
e
})
})
watchEffect
(()
=>
{
watchEffect
(()
=>
{
if
(
!
props
.
data
)
return
if
(
!
props
.
data
)
return
Object
.
assign
(
form
,
{
protocol
:
true
},
props
.
data
)
Object
.
assign
(
form
,
{
protocol
:
true
},
props
.
data
)
})
})
watchEffect
(()
=>
{
onMounted
(()
=>
{
updateExperiments
(
form
.
course_id
)
updateExperiments
()
})
})
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
if
(
!
value
)
{
if
(
!
value
)
{
...
@@ -52,7 +48,6 @@ const checkProtocol = (rule: any, value: any, callback: any) => {
...
@@ -52,7 +48,6 @@ const checkProtocol = (rule: any, value: any, callback: any) => {
const
rules
=
ref
<
FormRules
>
({
const
rules
=
ref
<
FormRules
>
({
source_id
:
[{
required
:
true
,
message
:
'请上传实验操作视频'
}],
source_id
:
[{
required
:
true
,
message
:
'请上传实验操作视频'
}],
name
:
[{
required
:
true
,
message
:
'请输入实验操作视频名称'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'请输入实验操作视频名称'
,
trigger
:
'blur'
}],
course_id
:
[{
required
:
true
,
message
:
'请选择关联实验课程'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联实验'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联实验'
,
trigger
:
'change'
}],
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
})
})
...
@@ -110,11 +105,6 @@ function handleUpdate(params: VideoCreateItem) {
...
@@ -110,11 +105,6 @@ function handleUpdate(params: VideoCreateItem) {
<el-input
v-model=
"form.name"
></el-input>
<el-input
v-model=
"form.name"
></el-input>
<p
class=
"form-tips"
>
操作视频名称自动取值于文件名称,可以进行二次修改。
</p>
<p
class=
"form-tips"
>
操作视频名称自动取值于文件名称,可以进行二次修改。
</p>
</el-form-item>
</el-form-item>
<el-form-item
label=
"关联实验课程"
prop=
"course_id"
>
<el-select
v-model=
"form.course_id"
filterable
style=
"width: 100%"
@
change=
"form.experiment_id = ''"
>
<el-option
v-for=
"item in courses"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"关联实验"
prop=
"experiment_id"
>
<el-form-item
label=
"关联实验"
prop=
"experiment_id"
>
<el-select
v-model=
"form.experiment_id"
filterable
style=
"width: 100%"
>
<el-select
v-model=
"form.experiment_id"
filterable
style=
"width: 100%"
>
<el-option
v-for=
"item in experiments"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
<el-option
v-for=
"item in experiments"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
...
...
src/modules/admin/lab/video/types.ts
浏览文件 @
3241135a
...
@@ -24,9 +24,11 @@ export interface VideoItem {
...
@@ -24,9 +24,11 @@ export interface VideoItem {
export
interface
VideoCreateItem
{
export
interface
VideoCreateItem
{
id
?:
string
id
?:
string
experiment_id
:
string
experiment_id
:
string
course_id
:
string
status
:
string
status
:
string
name
:
string
name
:
string
source_id
:
string
source_id
:
string
}
export
interface
VideoFormData
extends
VideoCreateItem
{
protocol
:
boolean
protocol
:
boolean
}
}
src/modules/admin/lab/video/views/Index.vue
浏览文件 @
3241135a
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
import
type
{
VideoItem
}
from
'../types'
import
type
{
VideoItem
}
from
'../types'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
useLocalStorage
}
from
'@vueuse/core'
import
{
useLocalStorage
}
from
'@vueuse/core'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
AppList
from
'@/components/base/AppList.vue'
import
AppList
from
'@/components/base/AppList.vue'
import
ListItem
from
'../components/ListItem.vue'
import
ListItem
from
'../components/ListItem.vue'
import
{
getVideoList
}
from
'../api'
import
{
deleteVideo
,
getVideoList
}
from
'../api'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useGetExperimentList
}
from
'../composables/useGetExperimentList'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
...
@@ -63,7 +64,7 @@ const listOptions = $computed(() => {
...
@@ -63,7 +64,7 @@ const listOptions = $computed(() => {
{
label
:
'创建人'
,
prop
:
'created_operator_name'
,
width
:
120
},
{
label
:
'创建人'
,
prop
:
'created_operator_name'
,
width
:
120
},
{
label
:
'创建时间'
,
prop
:
'created_time'
,
width
:
180
},
{
label
:
'创建时间'
,
prop
:
'created_time'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updated_time'
,
width
:
180
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
1
60
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
2
60
},
],
],
}
}
})
})
...
@@ -81,6 +82,14 @@ function handleUpdate(row: VideoItem) {
...
@@ -81,6 +82,14 @@ function handleUpdate(row: VideoItem) {
dialogVisible
=
true
dialogVisible
=
true
}
}
async
function
handleDelete
(
row
:
VideoItem
)
{
ElMessageBox
.
confirm
(
`确定要删除实验操作视频“
${
row
.
name
}
”吗?`
,
'提示'
).
then
(
async
()
=>
{
await
deleteVideo
({
id
:
row
.
id
})
ElMessage
.
success
(
'删除成功'
)
appList
?.
refetch
()
})
}
function
onUpdateSuccess
()
{
function
onUpdateSuccess
()
{
appList
?.
refetch
()
appList
?.
refetch
()
}
}
...
@@ -118,7 +127,12 @@ function onUpdateSuccess() {
...
@@ -118,7 +127,12 @@ function onUpdateSuccess() {
</
template
>
</
template
>
<
template
#
body=
"{ data }"
v-if=
"viewMode === 'card'"
>
<
template
#
body=
"{ data }"
v-if=
"viewMode === 'card'"
>
<div
class=
"list-card"
v-if=
"data.length"
>
<div
class=
"list-card"
v-if=
"data.length"
>
<ListItem
v-for=
"item in data"
:data=
"item"
:key=
"item.id"
@
clickEdit=
"handleUpdate(item)"
></ListItem>
<ListItem
v-for=
"item in data"
:data=
"item"
:key=
"item.id"
@
clickEdit=
"handleUpdate(item)"
@
clickDelete=
"handleDelete(item)"
></ListItem>
</div>
</div>
<el-empty
description=
"暂无数据"
v-else
/>
<el-empty
description=
"暂无数据"
v-else
/>
</
template
>
</
template
>
...
@@ -129,6 +143,9 @@ function onUpdateSuccess() {
...
@@ -129,6 +143,9 @@ function onUpdateSuccess() {
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'v1-teacher-video-update'"
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'v1-teacher-video-update'"
>
编辑
</el-button
>
编辑
</el-button
>
>
<el-button
type=
"danger"
round
@
click=
"handleDelete(row)"
v-permission=
"'v1-teacher-video-delete'"
>
删除
</el-button
>
</
template
>
</
template
>
<
template
#
table-status=
"{ row }: { row: VideoItem }"
>
<
template
#
table-status=
"{ row }: { row: VideoItem }"
>
<span
:class=
"isActiveStatus(row.status) ? 'status-active' : 'status-inactive'"
>
{{
row
.
status_name
}}
</span>
<span
:class=
"isActiveStatus(row.status) ? 'status-active' : 'status-inactive'"
>
{{
row
.
status_name
}}
</span>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论