Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jj_learn_word
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
jj_learn_word
Commits
68086014
Commit
68086014
authored
May 07, 2025
by
chunsen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 更新表单组件,添加思考问题功能及音频生成,优化数据结构
parent
f023b993
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
471 additions
and
32 deletions
+471
-32
.DS_Store
.DS_Store
+0
-0
form.component.html
form/src/app/form/form.component.html
+88
-10
form.component.ts
form/src/app/form/form.component.ts
+383
-22
No files found.
.DS_Store
View file @
68086014
No preview for this file type
form/src/app/form/form.component.html
View file @
68086014
...
@@ -23,16 +23,20 @@
...
@@ -23,16 +23,20 @@
<div>
<div>
<!-- 单词 -->
<!-- 单词 -->
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<span
style=
"width: 120px; text-align: right;"
>
单词:
</span>
<span
style=
"width: 120px; text-align: right;"
>
<input
type=
"text"
nz-input
[(
ngModel
)]="
word
.
word
"
(
blur
)="
save
()"
style=
"width: 250px;"
>
<span
style=
"color: #ff4d4f; margin-right: 4px;"
>
*
</span>
单词:
</span>
<input
type=
"text"
nz-input
[(
ngModel
)]="
word
.
word
"
(
blur
)="
save
()"
style=
"width: 250px;"
placeholder=
"请输入单词"
>
</div>
</div>
<!-- 词性 -->
<!-- 词性 -->
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<span
style=
"width: 120px; text-align: right;"
>
词性:
</span>
<span
style=
"width: 120px; text-align: right;"
>
<span
style=
"color: #ff4d4f; margin-right: 4px;"
>
*
</span>
词性:
</span>
<div
style=
"width: 250px;"
>
<div
style=
"width: 250px;"
>
<a
nz-dropdown
[
nzDropdownMenu
]="
menu
"
>
<a
nz-dropdown
[
nzDropdownMenu
]="
menu
"
>
{{word.partOfSpeech || '
无
'}}
{{word.partOfSpeech || '
请选择词性
'}}
<i
nz-icon
nzType=
"down"
></i>
<i
nz-icon
nzType=
"down"
></i>
</a>
</a>
<button
style=
"margin-left: 10px;"
nz-button
(
click
)="
word
.
partOfSpeech =
''
;
save
()"
>
<button
style=
"margin-left: 10px;"
nz-button
(
click
)="
word
.
partOfSpeech =
''
;
save
()"
>
...
@@ -55,6 +59,9 @@
...
@@ -55,6 +59,9 @@
<app-audio-recorder
[
audioUrl
]="
word
.
wordAudioUrl
"
<app-audio-recorder
[
audioUrl
]="
word
.
wordAudioUrl
"
(
audioUploaded
)="
onItemAudioUploadSuccess
($
event
,
word
,
'
wordAudioUrl
')"
>
(
audioUploaded
)="
onItemAudioUploadSuccess
($
event
,
word
,
'
wordAudioUrl
')"
>
</app-audio-recorder>
</app-audio-recorder>
<button
nz-button
style=
"margin-left: 10px;"
(
click
)="
generateWordAudio
(
word
)"
[
disabled
]="!
word
.
word
"
>
<i
nz-icon
nzType=
"sound"
></i>
生成音频
</button>
</div>
</div>
<!-- 翻译 -->
<!-- 翻译 -->
...
@@ -66,16 +73,15 @@
...
@@ -66,16 +73,15 @@
<div
style=
"margin-top: 20px; border-top: 1px dashed #eee; padding-top: 15px;"
>
<div
style=
"margin-top: 20px; border-top: 1px dashed #eee; padding-top: 15px;"
>
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<span
style=
"width: 120px; text-align: right;"
>
显示类型:
</span>
<span
style=
"width: 120px; text-align: right;"
>
<span
style=
"color: #ff4d4f; margin-right: 4px;"
>
*
</span>
显示类型:
</span>
<div
style=
"width: auto; display: flex; align-items: center;"
>
<div
style=
"width: auto; display: flex; align-items: center;"
>
<label
style=
"margin-right: 10px; font-size: 14px;"
>
<label
style=
"margin-right: 10px; font-size: 14px;"
>
<input
type=
"radio"
[(
ngModel
)]="
word
.
displayType
"
[
value
]="
1
"
(
change
)="
save
()"
>
高亮
<input
type=
"radio"
[(
ngModel
)]="
word
.
displayType
"
[
value
]="
1
"
(
change
)="
save
()"
>
词卡单词
</label>
<label
style=
"margin-right: 10px; font-size: 14px;"
>
<input
type=
"radio"
[(
ngModel
)]="
word
.
displayType
"
[
value
]="
2
"
(
change
)="
save
()"
>
单词卡
</label>
</label>
<label
style=
"font-size: 14px;"
>
<label
style=
"font-size: 14px;"
>
<input
type=
"radio"
[(
ngModel
)]="
word
.
displayType
"
[
value
]="
3
"
(
change
)="
save
()"
checked
>
高亮
&
单词卡
<input
type=
"radio"
[(
ngModel
)]="
word
.
displayType
"
[
value
]="
3
"
(
change
)="
save
()"
>
核心单词
</label>
</label>
</div>
</div>
</div>
</div>
...
@@ -96,6 +102,9 @@
...
@@ -96,6 +102,9 @@
<app-audio-recorder
[
audioUrl
]="
word
.
exampleSentenceAudioUrl
"
<app-audio-recorder
[
audioUrl
]="
word
.
exampleSentenceAudioUrl
"
(
audioUploaded
)="
onItemAudioUploadSuccess
($
event
,
word
,
'
exampleSentenceAudioUrl
')"
>
(
audioUploaded
)="
onItemAudioUploadSuccess
($
event
,
word
,
'
exampleSentenceAudioUrl
')"
>
</app-audio-recorder>
</app-audio-recorder>
<button
nz-button
style=
"margin-left: 10px;"
(
click
)="
generateExampleAudio
(
word
)"
[
disabled
]="!
word
.
exampleSentence
"
>
<i
nz-icon
nzType=
"sound"
></i>
生成音频
</button>
</div>
</div>
<!-- 图片 -->
<!-- 图片 -->
...
@@ -139,6 +148,75 @@
...
@@ -139,6 +148,75 @@
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 思考问题部分 -->
<div
style=
"margin-top: 20px; border-top: 1px solid #ddd; padding-top: 20px;"
>
<div
style=
"display: flex; align-items: center; margin-bottom: 15px;"
>
<h4
style=
"margin: 0; margin-right: 20px;"
>
思考问题
</h4>
</div>
<!-- 问题内容 -->
<div
style=
"margin-bottom: 15px; display: flex; align-items: flex-start;"
>
<span
style=
"width: 120px; text-align: right; margin-top: 5px;"
>
题目:
</span>
<div
style=
"flex: 1; max-width: 800px;"
>
<textarea
nz-input
[(
ngModel
)]="
getBackContent
(
word
).
content
"
(
blur
)="
save
()"
style=
"width: 400px; min-height: 50px;"
></textarea>
<div
style=
"margin-top: 10px; display: flex;"
>
<app-audio-recorder
[
audioUrl
]="
getBackContent
(
word
).
audioUrl
"
(
audioUploaded
)="
onBackContentAudioUploaded
($
event
,
word
)"
>
</app-audio-recorder>
<button
nz-button
style=
"margin-left: 10px;"
(
click
)="
generateQuestionAudio
(
word
)"
[
disabled
]="!
getBackContent
(
word
).
content
"
>
<i
nz-icon
nzType=
"sound"
></i>
生成音频
</button>
</div>
</div>
</div>
<!-- 选项列表 -->
<div
*
ngFor=
"let option of getBackContent(word).answer; let i = index"
style=
"margin-bottom: 20px; border: 1px solid #eee; padding: 15px; border-radius: 5px; background-color: #f9f9f9;"
>
<div
style=
"display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;"
>
<h5
style=
"margin: 0;"
>
选项 {{i+1}}
</h5>
<button
nz-button
nzType=
"danger"
(
click
)="
deleteOption
(
word
,
i
)"
>
<i
nz-icon
nzType=
"delete"
></i>
删除
</button>
</div>
<div
style=
"margin-bottom: 10px; display: flex; align-items: flex-start;"
>
<span
style=
"width: 120px; text-align: right; margin-top: 5px;"
>
答案内容:
</span>
<div
style=
"flex: 1; max-width: 600px;"
>
<textarea
nz-input
[(
ngModel
)]="
option
.
answer
"
(
blur
)="
save
()"
style=
"width: 400px; min-height: 50px;"
></textarea>
<div
style=
"margin-top: 10px; display: flex;"
>
<app-audio-recorder
[
audioUrl
]="
option
.
audioUrl
"
(
audioUploaded
)="
onOptionAudioUploaded
($
event
,
option
,
word
)"
>
</app-audio-recorder>
<button
nz-button
style=
"margin-left: 10px;"
(
click
)="
generateOptionAudio
(
option
,
word
)"
[
disabled
]="!
option
.
answer
"
>
<i
nz-icon
nzType=
"sound"
></i>
生成音频
</button>
</div>
</div>
</div>
<div
style=
"margin-bottom: 10px; display: flex; align-items: center;"
>
<span
style=
"width: 120px; text-align: right;"
>
正确答案:
</span>
<nz-switch
[(
ngModel
)]="
option
.
isCorrect
"
(
ngModelChange
)="
save
()"
></nz-switch>
</div>
</div>
<!-- 添加选项按钮 -->
<div
style=
"text-align: center; margin: 20px 0;"
>
<button
nz-button
nzType=
"primary"
(
click
)="
addOption
(
word
)"
>
<i
nz-icon
nzType=
"plus"
></i>
添加选项
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
form/src/app/form/form.component.ts
View file @
68086014
import
{
Component
,
EventEmitter
,
Input
,
OnDestroy
,
OnChanges
,
OnInit
,
Output
,
ApplicationRef
,
ChangeDetectorRef
}
from
'
@angular/core
'
;
import
{
Component
,
EventEmitter
,
Input
,
OnDestroy
,
OnChanges
,
OnInit
,
Output
,
ApplicationRef
,
ChangeDetectorRef
}
from
'
@angular/core
'
;
import
{
JsonPipe
}
from
'
@angular/common
'
;
import
{
JsonPipe
}
from
'
@angular/common
'
;
import
{
NzMessageService
}
from
'
ng-zorro-antd/message
'
;
import
{
NzMessageService
}
from
'
ng-zorro-antd/message
'
;
declare
function
commonPostMessageWithCallback
(
params
:
any
,
callback
:
(
res
:
any
)
=>
void
):
void
;
@
Component
({
@
Component
({
selector
:
'
app-form
'
,
selector
:
'
app-form
'
,
...
@@ -11,7 +14,7 @@ import { NzMessageService } from 'ng-zorro-antd/message';
...
@@ -11,7 +14,7 @@ import { NzMessageService } from 'ng-zorro-antd/message';
export
class
FormComponent
implements
OnInit
,
OnChanges
,
OnDestroy
{
export
class
FormComponent
implements
OnInit
,
OnChanges
,
OnDestroy
{
// 储存数据用
// 储存数据用
saveKey
=
"
learn_word
"
;
saveKey
=
"
jj_
learn_word
"
;
// 储存对象
// 储存对象
item
;
item
;
...
@@ -40,10 +43,31 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -40,10 +43,31 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
}
// 从父窗口URL获取参数
getParentUrlParam
(
param
:
string
):
string
|
null
{
try
{
// 获取父窗口的URL
const
parentUrl
=
window
.
parent
.
location
.
href
;
// 创建URL对象来解析参数
const
url
=
new
URL
(
parentUrl
);
// 获取指定的参数值
return
url
.
searchParams
.
get
(
param
);
}
catch
(
e
)
{
// 处理可能的跨域安全错误
console
.
error
(
"
无法访问父窗口URL,可能是由于跨域限制:
"
,
e
);
return
null
;
}
}
ngOnInit
()
{
ngOnInit
()
{
this
.
item
=
{};
this
.
item
=
{};
// 获取父窗口URL中的courseId参数作为pictureBookId
const
courseId
=
this
.
getParentUrlParam
(
'
courseId
'
);
if
(
courseId
)
{
console
.
log
(
'
从父窗口URL获取到courseId:
'
,
courseId
);
}
// 获取存储的数据
// 获取存储的数据
(
<
any
>
window
).
courseware
.
getData
((
data
)
=>
{
(
<
any
>
window
).
courseware
.
getData
((
data
)
=>
{
if
(
data
)
{
if
(
data
)
{
...
@@ -56,6 +80,15 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -56,6 +80,15 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}
}
this
.
initItem
();
this
.
initItem
();
// 确保pictureBookId存在
if
(
courseId
&&
(
!
this
.
item
.
pictureBookId
||
this
.
item
.
pictureBookId
===
''
))
{
this
.
item
.
pictureBookId
=
courseId
;
}
// 确保每个单词都有ID
this
.
ensureWordIds
();
console
.
log
(
"
this.item:
"
,
JSON
.
stringify
(
this
.
item
));
console
.
log
(
"
this.item:
"
,
JSON
.
stringify
(
this
.
item
));
this
.
init
();
this
.
init
();
...
@@ -72,6 +105,46 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -72,6 +105,46 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this
.
item
.
data
=
[];
this
.
item
.
data
=
[];
}
}
// 确保pictureBookId存在
if
(
!
this
.
item
.
pictureBookId
)
{
this
.
item
.
pictureBookId
=
''
;
}
// 确保每个单词都有正确的backContent结构
if
(
this
.
item
.
data
&&
this
.
item
.
data
.
length
>
0
)
{
this
.
item
.
data
.
forEach
(
word
=>
{
// 初始化backContent
if
(
!
word
.
backContent
)
{
word
.
backContent
=
{
content
:
''
,
audioUrl
:
''
,
answer
:
[]
};
}
else
if
(
!
word
.
backContent
.
answer
)
{
// 确保answer数组存在
word
.
backContent
.
answer
=
[];
}
});
}
}
// 确保每个单词都有ID
ensureWordIds
()
{
if
(
!
this
.
item
.
data
||
this
.
item
.
data
.
length
===
0
)
{
return
;
}
const
pictureBookId
=
this
.
item
.
pictureBookId
||
''
;
// 为每个没有id的单词生成id
this
.
item
.
data
.
forEach
((
word
,
index
)
=>
{
if
(
!
word
.
id
||
word
.
id
.
trim
()
===
''
)
{
// 使用pictureBookId + 索引生成单词ID
word
.
id
=
`
${
pictureBookId
}${
index
+
1
}
`
;
}
// 更新pictureBookId
word
.
pictureBookId
=
pictureBookId
;
});
}
}
init
()
{
init
()
{
...
@@ -86,9 +159,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -86,9 +159,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this
.
item
.
data
.
push
({
this
.
item
.
data
.
push
({
id
:
''
,
id
:
''
,
pictureBookId
:
''
,
pictureBookId
:
this
.
item
.
pictureBookId
||
''
,
word
:
''
,
word
:
''
,
displayType
:
'
'
,
displayType
:
'
3
'
,
// 默认为"核心单词"
partOfSpeech
:
''
,
partOfSpeech
:
''
,
exampleSentence
:
''
,
exampleSentence
:
''
,
wordAudioUrl
:
''
,
wordAudioUrl
:
''
,
...
@@ -99,7 +172,11 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -99,7 +172,11 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
britishPhonetic
:
''
,
britishPhonetic
:
''
,
americanPhonetic
:
''
,
americanPhonetic
:
''
,
englishDefinition
:
''
,
englishDefinition
:
''
,
backContent
:
{},
backContent
:
{
content
:
''
,
audioUrl
:
''
,
answer
:
[]
},
createdTime
:
new
Date
().
toISOString
()
createdTime
:
new
Date
().
toISOString
()
});
});
}
}
...
@@ -141,23 +218,34 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -141,23 +218,34 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存数据
* 储存数据
*/
*/
save
()
{
save
()
{
// 更新data中的时间戳
// 验证必填字段
// if (this.item.data && this.item.data.length > 0) {
let
hasError
=
false
;
// const now = new Date().toISOString();
if
(
this
.
item
.
data
&&
this
.
item
.
data
.
length
>
0
)
{
// this.item.data.forEach(item => {
this
.
item
.
data
.
forEach
((
word
,
index
)
=>
{
// if (!item.createdTime) {
if
(
!
word
.
word
||
word
.
word
.
trim
()
===
''
)
{
// item.createdTime = now;
this
.
message
.
warning
(
`第
${
index
+
1
}
个单词的"单词"不能为空`
);
// }
hasError
=
true
;
// });
}
// }
if
(
!
word
.
partOfSpeech
||
word
.
partOfSpeech
.
trim
()
===
''
)
{
this
.
message
.
warning
(
`第
${
index
+
1
}
个单词的"词性"不能为空`
);
hasError
=
true
;
}
if
(
!
word
.
displayType
)
{
this
.
message
.
warning
(
`第
${
index
+
1
}
个单词的"显示类型"不能为空`
);
hasError
=
true
;
}
});
}
// 删除item中可能存在的quesArr属性
// 如果有错误,不保存
// if (this.item.quesArr) {
if
(
hasError
)
{
// delete this.item.quesArr;
return
;
// }
}
// 确保所有单词都有ID
this
.
ensureWordIds
();
const
newItem
=
this
.
getNewSortItem
();
const
newItem
=
this
.
getNewSortItem
();
(
<
any
>
window
).
courseware
.
setData
(
newItem
,
null
,
this
.
saveKey
);
(
<
any
>
window
).
courseware
.
setData
(
newItem
,
null
,
this
.
saveKey
);
...
@@ -180,9 +268,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -180,9 +268,9 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
addNewWord
()
{
addNewWord
()
{
this
.
item
.
data
.
push
({
this
.
item
.
data
.
push
({
id
:
''
,
id
:
''
,
pictureBookId
:
''
,
pictureBookId
:
this
.
item
.
pictureBookId
||
''
,
word
:
''
,
word
:
''
,
displayType
:
'
'
,
displayType
:
'
3
'
,
// 默认为"核心单词"
partOfSpeech
:
''
,
partOfSpeech
:
''
,
exampleSentence
:
''
,
exampleSentence
:
''
,
wordAudioUrl
:
''
,
wordAudioUrl
:
''
,
...
@@ -193,9 +281,17 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -193,9 +281,17 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
britishPhonetic
:
''
,
britishPhonetic
:
''
,
americanPhonetic
:
''
,
americanPhonetic
:
''
,
englishDefinition
:
''
,
englishDefinition
:
''
,
backContent
:
{},
backContent
:
{
content
:
''
,
audioUrl
:
''
,
answer
:
[]
},
createdTime
:
new
Date
().
toISOString
()
createdTime
:
new
Date
().
toISOString
()
});
});
// 确保所有单词都有ID
this
.
ensureWordIds
();
this
.
save
();
this
.
save
();
}
}
...
@@ -205,4 +301,269 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
...
@@ -205,4 +301,269 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this
.
save
();
this
.
save
();
}
}
// 生成单词音频
generateWordAudio
(
word
)
{
if
(
!
word
.
word
||
word
.
word
.
trim
()
===
''
)
{
this
.
message
.
error
(
'
请先输入单词
'
);
return
;
}
const
call_back
=
(
res
)
=>
{
console
.
log
(
"
gennerateQuestionAudio res:
"
,
res
);
try
{
const
resData
=
JSON
.
parse
(
res
);
if
(
resData
.
msg
==
"
success
"
)
{
if
(
resData
.
data
&&
word
.
word
)
{
// 确保音频URL正确赋值
word
.
wordAudioUrl
=
resData
.
data
;
this
.
save
();
// 保存更改
this
.
message
.
create
(
"
success
"
,
"
题目音频生成成功
"
);
}
else
{
this
.
message
.
create
(
"
warning
"
,
"
生成的音频数据为空
"
);
}
}
else
{
this
.
message
.
create
(
"
error
"
,
"
音频生成失败
"
);
}
}
catch
(
e
)
{
console
.
error
(
"
解析音频生成响应出错:
"
,
e
);
this
.
message
.
create
(
"
error
"
,
"
音频生成响应解析失败
"
);
}
};
// 检查方法是否存在
const
checkAndCall
=
(
word
:
any
)
=>
{
if
(
typeof
commonPostMessageWithCallback
===
"
function
"
)
{
commonPostMessageWithCallback
(
{
action
:
"
generateTTS
"
,
data
:
word
,
},
call_back
);
}
else
{
// setTimeout(checkAndCall, 100);
this
.
message
.
create
(
"
error
"
,
"
通信方法不可用
"
);
}
};
checkAndCall
(
word
.
word
);
this
.
message
.
info
(
`准备为单词"
${
word
.
word
}
"生成音频`
);
}
// 生成例句音频
generateExampleAudio
(
word
)
{
if
(
!
word
.
exampleSentence
||
word
.
exampleSentence
.
trim
()
===
''
)
{
this
.
message
.
error
(
'
请先输入例句
'
);
return
;
}
const
call_back
=
(
res
)
=>
{
console
.
log
(
"
generateExampleAudio res:
"
,
res
);
try
{
const
resData
=
JSON
.
parse
(
res
);
if
(
resData
.
msg
==
"
success
"
)
{
if
(
resData
.
data
&&
word
.
exampleSentence
)
{
// 确保音频URL正确赋值
word
.
exampleSentenceAudioUrl
=
resData
.
data
;
this
.
save
();
// 保存更改
this
.
message
.
create
(
"
success
"
,
"
例句音频生成成功
"
);
}
else
{
this
.
message
.
create
(
"
warning
"
,
"
生成的音频数据为空
"
);
}
}
else
{
this
.
message
.
create
(
"
error
"
,
"
音频生成失败
"
);
}
}
catch
(
e
)
{
console
.
error
(
"
解析音频生成响应出错:
"
,
e
);
this
.
message
.
create
(
"
error
"
,
"
音频生成响应解析失败
"
);
}
};
// 检查方法是否存在
const
checkAndCall
=
(
sentence
:
any
)
=>
{
if
(
typeof
commonPostMessageWithCallback
===
"
function
"
)
{
commonPostMessageWithCallback
(
{
action
:
"
generateTTS
"
,
data
:
sentence
,
},
call_back
);
}
else
{
this
.
message
.
create
(
"
error
"
,
"
通信方法不可用
"
);
}
};
checkAndCall
(
word
.
exampleSentence
);
this
.
message
.
info
(
`准备为例句生成音频`
);
}
// 获取或初始化backContent
getBackContent
(
word
)
{
if
(
!
word
.
backContent
)
{
word
.
backContent
=
{
content
:
''
,
audioUrl
:
''
,
answer
:
[]
};
}
// 确保answer数组存在
if
(
!
word
.
backContent
.
answer
)
{
word
.
backContent
.
answer
=
[];
}
return
word
.
backContent
;
}
// 添加新选项
addOption
(
word
)
{
// 确保backContent及其answer数组存在
const
backContent
=
this
.
getBackContent
(
word
);
try
{
// 添加新选项
backContent
.
answer
.
push
({
answer
:
''
,
audioUrl
:
''
,
isCorrect
:
false
});
this
.
save
();
}
catch
(
error
)
{
console
.
error
(
'
添加选项失败:
'
,
error
);
this
.
message
.
error
(
'
添加选项失败,请刷新页面后重试
'
);
}
}
// 删除选项
deleteOption
(
word
,
index
)
{
try
{
const
backContent
=
this
.
getBackContent
(
word
);
// 检查索引是否有效
if
(
backContent
.
answer
&&
Array
.
isArray
(
backContent
.
answer
)
&&
index
>=
0
&&
index
<
backContent
.
answer
.
length
)
{
backContent
.
answer
.
splice
(
index
,
1
);
this
.
save
();
}
else
{
console
.
warn
(
'
尝试删除不存在的选项索引:
'
,
index
);
}
}
catch
(
error
)
{
console
.
error
(
'
删除选项失败:
'
,
error
);
this
.
message
.
error
(
'
删除选项失败,请刷新页面后重试
'
);
}
}
// 思考问题音频上传成功回调
onBackContentAudioUploaded
(
e
,
word
)
{
const
backContent
=
this
.
getBackContent
(
word
);
backContent
.
audioUrl
=
e
.
url
;
this
.
save
();
}
// 选项音频上传成功回调
onOptionAudioUploaded
(
e
,
option
,
word
)
{
option
.
audioUrl
=
e
.
url
;
this
.
save
();
}
// 生成思考问题音频
generateQuestionAudio
(
word
)
{
const
backContent
=
this
.
getBackContent
(
word
);
if
(
!
backContent
.
content
||
backContent
.
content
.
trim
()
===
''
)
{
this
.
message
.
error
(
'
请先输入题目内容
'
);
return
;
}
const
call_back
=
(
res
)
=>
{
console
.
log
(
"
generateQuestionAudio res:
"
,
res
);
try
{
const
resData
=
JSON
.
parse
(
res
);
if
(
resData
.
msg
==
"
success
"
)
{
if
(
resData
.
data
&&
backContent
.
content
)
{
backContent
.
audioUrl
=
resData
.
data
;
this
.
save
();
this
.
message
.
create
(
"
success
"
,
"
题目音频生成成功
"
);
}
else
{
this
.
message
.
create
(
"
warning
"
,
"
生成的音频数据为空
"
);
}
}
else
{
this
.
message
.
create
(
"
error
"
,
"
音频生成失败
"
);
}
}
catch
(
e
)
{
console
.
error
(
"
解析音频生成响应出错:
"
,
e
);
this
.
message
.
create
(
"
error
"
,
"
音频生成响应解析失败
"
);
}
};
const
checkAndCall
=
(
content
)
=>
{
if
(
typeof
commonPostMessageWithCallback
===
"
function
"
)
{
commonPostMessageWithCallback
(
{
action
:
"
generateTTS
"
,
data
:
content
,
},
call_back
);
}
else
{
this
.
message
.
create
(
"
error
"
,
"
通信方法不可用
"
);
}
};
checkAndCall
(
backContent
.
content
);
this
.
message
.
info
(
`准备为题目生成音频`
);
}
// 生成选项音频
generateOptionAudio
(
option
,
word
)
{
if
(
!
option
.
answer
||
option
.
answer
.
trim
()
===
''
)
{
this
.
message
.
error
(
'
请先输入选项内容
'
);
return
;
}
const
call_back
=
(
res
)
=>
{
console
.
log
(
"
generateOptionAudio res:
"
,
res
);
try
{
const
resData
=
JSON
.
parse
(
res
);
if
(
resData
.
msg
==
"
success
"
)
{
if
(
resData
.
data
&&
option
.
answer
)
{
option
.
audioUrl
=
resData
.
data
;
this
.
save
();
this
.
message
.
create
(
"
success
"
,
"
选项音频生成成功
"
);
}
else
{
this
.
message
.
create
(
"
warning
"
,
"
生成的音频数据为空
"
);
}
}
else
{
this
.
message
.
create
(
"
error
"
,
"
音频生成失败
"
);
}
}
catch
(
e
)
{
console
.
error
(
"
解析音频生成响应出错:
"
,
e
);
this
.
message
.
create
(
"
error
"
,
"
音频生成响应解析失败
"
);
}
};
const
checkAndCall
=
(
content
)
=>
{
if
(
typeof
commonPostMessageWithCallback
===
"
function
"
)
{
commonPostMessageWithCallback
(
{
action
:
"
generateTTS
"
,
data
:
content
,
},
call_back
);
}
else
{
this
.
message
.
create
(
"
error
"
,
"
通信方法不可用
"
);
}
};
checkAndCall
(
option
.
answer
);
this
.
message
.
info
(
`准备为选项生成音频`
);
}
}
}
\ No newline at end of file
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