Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gs10
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
template admin
gs10
Commits
21c8f1f9
Commit
21c8f1f9
authored
Feb 20, 2025
by
liujiangnan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 表单
parent
9d944887
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
445 additions
and
29 deletions
+445
-29
index.css
form/index.css
+149
-1
index.html
form/index.html
+56
-4
index.js
form/index.js
+240
-24
No files found.
form/index.css
View file @
21c8f1f9
.edit-data
{
.edit-data
{
padding
:
10px
;
padding
:
10px
;
}
}
.el-card
{
display
:
inline-block
;
margin
:
3px
;
}
.data-card
{
position
:
relative
;
width
:
90%
;
vertical-align
:
top
;
}
.data-card
.el-card__body
{
padding
:
15px
20px
0px
;
}
.audio-uploader
{
text-align
:
left
;
margin-bottom
:
10px
;
}
audio
{
margin
:
10px
0
;
}
.el-form-item
{
margin-bottom
:
15px
;
}
.delete-btn-wrapper
{
position
:
absolute
;
bottom
:
10px
;
left
:
0
;
right
:
0
;
text-align
:
center
;
}
/* 音频信息显示样式 */
.audio-info
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
margin-top
:
10px
;
padding
:
8px
12px
;
background
:
#f5f7fa
;
border-radius
:
4px
;
}
.audio-file-info
{
flex
:
1
;
overflow
:
hidden
;
margin-right
:
10px
;
}
.audio-file-info
.filename
{
display
:
block
;
font-size
:
14px
;
color
:
#606266
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.audio-file-info
.file-meta
{
font-size
:
12px
;
color
:
#909399
;
}
.audio-play-btn
{
font-size
:
30px
;
color
:
#409EFF
;
cursor
:
pointer
;
transition
:
all
0.3s
;
}
.audio-play-btn
:hover
{
color
:
#66b1ff
;
}
/* 图片上传区域样式 */
.image-uploader
{
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
border
:
1px
dashed
#d9d9d9
;
border-radius
:
6px
;
cursor
:
pointer
;
position
:
relative
;
overflow
:
hidden
;
}
.image-uploader
.el-upload
{
width
:
120px
;
height
:
120px
;
}
.image-uploader
:hover
{
border-color
:
#409EFF
;
}
.upload-icon
{
font-size
:
28px
;
color
:
#8c939d
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.image-preview
{
width
:
100%
;
height
:
100%
;
position
:
relative
;
}
.uploaded-image
{
width
:
100%
;
height
:
100%
;
object-fit
:
cover
;
}
.image-actions
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
100%
;
background
:
rgba
(
0
,
0
,
0
,
0.5
);
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
opacity
:
0
;
transition
:
opacity
0.3s
;
}
.image-preview
:hover
.image-actions
{
opacity
:
1
;
}
.image-actions
i
{
color
:
#fff
;
font-size
:
20px
;
margin
:
0
10px
;
cursor
:
pointer
;
}
.image-actions
i
:hover
{
transform
:
scale
(
1.2
);
}
\ No newline at end of file
form/index.html
View file @
21c8f1f9
...
@@ -16,9 +16,61 @@
...
@@ -16,9 +16,61 @@
</head>
</head>
<body>
<body>
<div
class=
"edit-data"
>
<div
class=
"edit-data"
>
<!-- 简单的例子,一个输入框+一个按钮,保存输入框的信息 -->
<el-card
class=
"data-card"
v-for=
"item, index in data"
:key=
"index"
>
test:
<input
type=
"text"
name=
"test"
/>
<div
slot=
"header"
class=
"clearfix"
>
<input
id=
"save"
type=
"button"
value=
"保存"
>
<span>
短句{{index + 1}}
</span>
<el-button
style=
"float: right; padding: 3px 0"
type=
"text"
@
click=
"deleteConf(index)"
>
删除
</el-button>
</div>
<div>
<el-form
label-width=
"90px"
>
<el-form-item
label=
"短句图片"
>
<div
class=
"image-uploader"
>
<el-upload
:action=
"uploadUrl"
:data=
"uploadData"
:show-file-list=
"false"
:on-success=
"(res, file) => handleImageSuccess(res, file, index)"
:before-upload=
"beforeImageUpload"
>
<div
v-if=
"data[index].image_url"
class=
"image-preview"
>
<img
:src=
"data[index].image_url"
class=
"uploaded-image"
>
<div
class=
"image-actions"
>
<i
class=
"el-icon-zoom-in"
@
click
.
stop=
"previewImage(data[index].image_url)"
></i>
<i
class=
"el-icon-delete"
@
click
.
stop=
"removeImage(index)"
></i>
</div>
</div>
<i
v-else
class=
"el-icon-plus upload-icon"
></i>
</el-upload>
</div>
</el-form-item>
<el-form-item
label=
"短句"
>
<el-input
type=
"textarea"
v-model=
"data[index].question"
placeholder=
"请输入短句英文"
@
change=
"save"
></el-input>
</el-form-item>
<!-- 新增音频上传和预览部分 -->
<el-form-item
label=
"短句音频"
>
<div
class=
"audio-uploader"
>
<el-upload
:action=
"uploadUrl"
:data=
"uploadData"
:on-success=
"(res, file) => handleAudioSuccess(res, file, index)"
:before-upload=
"beforeAudioUpload"
:show-file-list=
"false"
>
<el-button
size=
"small"
type=
"primary"
>
{{ data[index].audio_url ? '重新上传' : '上传' }}
</el-button>
<span
v-if=
"data[index].audio_url"
class=
"filename"
@
click
.
stop=
"togglePlay(index)"
>
{{ data[index].audio_name }}(点击播放)
</span>
<audio
:ref=
"'audio' + index"
:src=
"data[index].audio_url"
@
ended
.
stop=
"audioEnded(index)"
style=
"display: none;"
></audio>
</el-upload>
</div>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card
shadow=
"hover"
class=
"data-card"
>
<div
style=
"cursor: pointer; display: flex; justify-content: center; align-items: center; height: 80px;"
@
click=
"addConfig"
>
<el-button
class=
"btn"
type=
"text"
size=
"mini"
icon=
"el-icon-plus"
>
新加
</el-button>
</div>
</el-card>
</div>
</div>
</body>
</body>
<script
src=
"./index.js"
></script>
<script
src=
"./index.js"
></script>
...
...
form/index.js
View file @
21c8f1f9
/*
/*
window.courseware.getData(callback,key); //用于获取数据
window.courseware.getData(callback,key); //用于获取数据
...
@@ -10,26 +8,244 @@ var uploadData = window.courseware.uploadData(); //上传文件必须要的参
...
@@ -10,26 +8,244 @@ var uploadData = window.courseware.uploadData(); //上传文件必须要的参
*/
*/
//对应模板的名称,这个可以不写,但是最好是能写上,同时开发多个模板的情况下如果不写这个,本地缓存可能会存在混乱
//对应模板的名称,这个可以不写,但是最好是能写上,同时开发多个模板的情况下如果不写这个,本地缓存可能会存在混乱
var
key
=
"
h5_test
"
;
var
key
=
"
gs10
"
;
new
Vue
({
el
:
'
.edit-data
'
,
created
()
{
window
.
courseware
.
getData
((
data
)
=>
{
this
.
data
=
data
||
[];
},
key
);
window
[
'
air
'
].
getUploadCallback
=
(
url
,
data
)
=>
{
this
.
uploadUrl
=
url
;
this
.
uploadData
=
data
;
};
},
data
()
{
return
{
data
:
[],
uploadUrl
:
window
.
courseware
.
uploadUrl
(),
uploadData
:
window
.
courseware
.
uploadData
(),
}
},
methods
:
{
handleAudioSuccess
(
res
,
file
,
index
)
{
// 假设上传接口返回的音频URL在 res.url 中
this
.
data
[
index
].
audio_url
=
res
.
url
;
this
.
data
[
index
].
audio_name
=
file
.
name
;
// 计算文件大小
const
size
=
file
.
size
;
if
(
size
<
1024
)
{
this
.
data
[
index
].
audio_size
=
size
+
'
B
'
;
}
else
if
(
size
<
1024
*
1024
)
{
this
.
data
[
index
].
audio_size
=
(
size
/
1024
).
toFixed
(
2
)
+
'
KB
'
;
}
else
{
this
.
data
[
index
].
audio_size
=
(
size
/
(
1024
*
1024
)).
toFixed
(
2
)
+
'
MB
'
;
}
$
(
function
(){
// 获取音频时长
window
.
courseware
.
getData
(
function
(
data
){
const
audio
=
new
Audio
(
res
.
url
);
//数据加载完,才算页面加载完成
audio
.
addEventListener
(
'
loadedmetadata
'
,
()
=>
{
//获取数据
const
duration
=
audio
.
duration
;
if
(
data
&&
data
.
test
){
const
minutes
=
Math
.
floor
(
duration
/
60
);
$
(
"
[name='test']
"
).
val
(
data
.
test
);
const
seconds
=
Math
.
floor
(
duration
%
60
);
this
.
data
[
index
].
audio_duration
=
`
${
minutes
}
:
${
seconds
.
toString
().
padStart
(
2
,
'
0
'
)}
`
;
});
this
.
save
();
},
handleOptionAudioSuccess
(
res
,
file
,
index
,
optionIndex
)
{
this
.
data
[
index
].
options
[
optionIndex
].
audio_url
=
res
.
url
;
this
.
data
[
index
].
options
[
optionIndex
].
audio_name
=
file
.
name
;
// 计算文件大小
const
size
=
file
.
size
;
if
(
size
<
1024
)
{
this
.
data
[
index
].
options
[
optionIndex
].
audio_size
=
size
+
'
B
'
;
}
else
if
(
size
<
1024
*
1024
)
{
this
.
data
[
index
].
options
[
optionIndex
].
audio_size
=
(
size
/
1024
).
toFixed
(
2
)
+
'
KB
'
;
}
else
{
this
.
data
[
index
].
options
[
optionIndex
].
audio_size
=
(
size
/
(
1024
*
1024
)).
toFixed
(
2
)
+
'
MB
'
;
}
// 获取音频时长
const
audio
=
new
Audio
(
res
.
url
);
audio
.
addEventListener
(
'
loadedmetadata
'
,
()
=>
{
const
duration
=
audio
.
duration
;
const
minutes
=
Math
.
floor
(
duration
/
60
);
const
seconds
=
Math
.
floor
(
duration
%
60
);
this
.
data
[
index
].
options
[
optionIndex
].
audio_duration
=
`
${
minutes
}
:
${
seconds
.
toString
().
padStart
(
2
,
'
0
'
)}
`
;
});
this
.
save
();
},
pauseAudios
()
{
// 停止全部音频的播放
this
.
data
.
forEach
((
item
,
i
)
=>
{
const
otherAudio
=
this
.
$refs
[
'
audio
'
+
i
][
0
];
if
(
otherAudio
)
{
otherAudio
.
pause
();
item
.
isPlaying
=
false
;
}
item
.
options
.
forEach
((
option
,
optionIndex
)
=>
{
const
optionAudio
=
this
.
$refs
[
'
audio
'
+
i
+
'
-
'
+
optionIndex
][
0
];
if
(
optionAudio
)
{
optionAudio
.
pause
();
option
.
isPlaying
=
false
;
}
}
});
});
},
//绑定点击事件
// 播放/暂停音频
$
(
'
#save
'
).
on
(
'
click
'
,
function
(){
togglePlay
(
index
)
{
var
test
=
$
(
"
[name='test']
"
).
val
();
const
audio
=
this
.
$refs
[
'
audio
'
+
index
][
0
];
this
.
pauseAudios
();
audio
.
play
();
this
.
data
[
index
].
isPlaying
=
true
;
},
//保存新增或修改的数据
toggleOptionAudioPlay
(
index
,
optionIndex
)
{
window
.
courseware
.
setData
({
test
:
test
},
function
(){
const
audio
=
this
.
$refs
[
'
audio
'
+
index
+
'
-
'
+
optionIndex
][
0
];
this
.
pauseAudios
();
audio
.
play
();
this
.
data
[
index
].
options
[
optionIndex
].
isPlaying
=
true
;
},
// 音频播放结束
audioEnded
(
index
)
{
this
.
data
[
index
].
isPlaying
=
false
;
},
audioOptionEnded
(
index
,
optionIndex
)
{
this
.
data
[
index
].
options
[
optionIndex
].
isPlaying
=
false
;
},
beforeAudioUpload
(
file
)
{
const
isAudio
=
file
.
type
.
startsWith
(
'
audio/
'
);
const
isLt20M
=
file
.
size
/
1024
/
1024
<
20
;
if
(
!
isAudio
)
{
this
.
$message
.
error
(
'
只能上传音频文件!
'
);
return
false
;
}
if
(
!
isLt20M
)
{
this
.
$message
.
error
(
'
音频大小不能超过 20MB!
'
);
return
false
;
}
return
true
;
},
save
()
{
// 保存新增或修改的数据
window
.
courseware
.
setData
(
this
.
data
,
()
=>
{
//保存数据也是异步的
//保存数据也是异步的
alert
(
"
保存成功!
"
);
this
.
$message
.
success
(
"
实时保存成功
"
);
},
key
);
},
key
);
},
deleteConf
(
index
)
{
this
.
data
.
splice
(
index
,
1
);
this
.
save
();
},
addConfig
()
{
this
.
data
.
push
({
question
:
''
,
audio_url
:
''
,
image_url
:
''
,
audio_name
:
''
,
audio_size
:
''
,
audio_duration
:
''
,
isPlaying
:
false
,
options
:
[{
image_url
:
''
,
audio_url
:
''
,
audio_name
:
''
,
audio_size
:
''
,
audio_duration
:
''
,
isPlaying
:
false
,
text
:
''
,
is_correct
:
false
,
}],
});
this
.
save
();
},
addOption
(
index
)
{
this
.
data
[
index
].
options
.
push
({
image_url
:
''
,
audio_url
:
''
,
audio_name
:
''
,
audio_size
:
''
,
audio_duration
:
''
,
isPlaying
:
false
,
text
:
''
,
is_correct
:
false
,
});
this
.
save
();
},
deleteOption
(
index
,
optionIndex
)
{
this
.
data
[
index
].
options
.
splice
(
optionIndex
,
1
);
this
.
save
();
},
// 图片上传成功的回调
handleImageSuccess
(
res
,
file
,
index
)
{
// 假设上传接口返回的图片URL在 res.url 中
console
.
log
(
res
,
file
,
index
);
this
.
data
[
index
].
image_url
=
res
.
url
;
this
.
save
();
},
handleOptionImageSuccess
(
res
,
file
,
index
,
optionIndex
)
{
this
.
data
[
index
].
options
[
optionIndex
].
image_url
=
res
.
url
;
this
.
save
();
},
// 图片上传前的验证
beforeImageUpload
(
file
)
{
const
isImage
=
file
.
type
.
startsWith
(
'
image/
'
);
const
isLt2M
=
file
.
size
/
1024
/
1024
<
5
;
})
if
(
!
isImage
)
{
},
key
);
this
.
$message
.
error
(
'
只能上传图片文件!
'
);
})
return
false
;
\ No newline at end of file
}
if
(
!
isLt2M
)
{
this
.
$message
.
error
(
'
图片大小不能超过 2MB!
'
);
return
false
;
}
return
true
;
},
// 预览图片
previewImage
(
url
)
{
// 使用 Element UI 的 Image 组件预览
const
h
=
this
.
$createElement
;
this
.
$msgbox
({
title
:
'
图片预览
'
,
message
:
h
(
'
img
'
,
{
attrs
:
{
src
:
url
,
style
:
'
max-width: 100%; max-height: 500px;
'
}
}),
showCancelButton
:
false
,
confirmButtonText
:
'
关闭
'
});
},
removeImage
(
index
)
{
this
.
$confirm
(
'
确定要删除这张图片吗?
'
,
'
提示
'
,
{
confirmButtonText
:
'
确定
'
,
cancelButtonText
:
'
取消
'
,
type
:
'
warning
'
}).
then
(()
=>
{
this
.
data
[
index
].
image_url
=
''
;
this
.
save
();
this
.
$message
({
type
:
'
success
'
,
message
:
'
删除成功!
'
});
}).
catch
(()
=>
{
});
},
removeOptionImage
(
index
,
optionIndex
)
{
this
.
data
[
index
].
options
[
optionIndex
].
image_url
=
''
;
this
.
save
();
}
},
computed
:
{
}
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment