当前位置:网站首页>Wechat applet training | Chinese dictation tool based on cloud database
Wechat applet training | Chinese dictation tool based on cloud database
2022-07-18 14:00:00 【TiAmo zhang】

This training project combines cloud database developed by cloud and “ Wechat simultaneous interpretation ” plug-in unit , Make a real Chinese dictation tool for primary school students , The page effect is as shown in the figure 1 Shown .

▍ chart 1 “ Dictation assistant ” page
Wechat applets developed based on cloud have many advantages , The cloud development model really liberates developers , It greatly improves the development efficiency , The small program development and delivery process under its mode is also more convenient ; Cloud development has established a shortcut from applet side to Tencent cloud and applet side to wechat , It also provides a shortcut to connect more Tencent cloud resources , You can also get through cloud to cloud 、 End to end boundaries , Its computing resource billing is more reasonable , Lower cost .
In the era of rapid development of small program Internet , The educational scene has been reshaped , Educational applets are booming .2020 The COVID-19 in brought new vitality to online education , Driving the demand of users for online education . therefore , Based on the needs of online education, our team developed “ Listen and write assistant ” This little app .
“ Listen and write assistant ” It is a language centered , Take wechat applet as the window , A full phonetic teaching platform for students and their parents .“ Listen and write assistant ” Set voice dictation 、 Error analysis 、 Ten words a day 、 Review reminder 、 Personalized customization 、 Review six functions in one stage , Adopt voice broadcast mode , Reduce students' eyes , It greatly improves students' learning efficiency , At the same time, it also reduces the pressure on parents to tutor their children's dictation homework .
This case is based on cloud database developed by cloud , Make a wechat applet for primary school Chinese dictation .
01、 Development content
In order to achieve “ Dictation assistant ” Voice playback function , You need to add plug-ins “ Wechat simultaneous interpretation ”, The specific steps are: : Log in to wechat platform , choice “ Set up ”→“ Third party settings ”→“ Plug-in management ”→“ Search plug-ins ” And finish adding . Open after adding the plug-in “ Console ”→“ database ”, Import the database file into the database , Thus, the storage of all words after six years of primary school is completed . Finally, in order to interact with front and back-end users, we need to use cloud functions to operate , To do this, you need to complete the synchronization of the cloud function list and upload and deploy getContent and getUserCollectList Cloud function operation , Recompile and choose the book in the first volume of grade one , Dictation function can be realized . Similarly, importing the remaining database collection can realize the dictation function of all books .
Dictate the fields contained in each record in a single set of data , Pictured 2 Shown .

▍ chart 2 rn_11 Collection import complete
This case development mainly includes adding plug-ins 、 Database page 、 There are three steps to upload and deploy cloud functions .
1、 Add the plug-in
Listen, the code of the written assistant uses the plug-in of wechat simultaneous interpretation , This is because a good dictation assistant needs to convert the text stored in the database into speech , Let the code run normally , You need to log in to wechat public platform , stay “ Set up ”→“ Third party settings ”→“ Plug-in management ” in , Add the plug-in “ Wechat simultaneous interpretation ”, After adding plug-ins , Pictured 3 Shown .

▍ chart 3 Add the plug-in “ Wechat simultaneous interpretation ”
2、 Page database
Recompile after adding the plug-in , You will find that there are errors , The reason is that there is no data record corresponding to the textbook in the cloud development database , Therefore, you need to import the database . The database file is shown in Figure 4 . among ,rn_11 Corresponding to the dictation data in Volume 1 of grade 1 ,rn_12 Corresponding to the dictation data in Volume II of grade one , And so on .

▍ chart 4 Database files
3、 Upload and deploy cloud functions
Right click cloudfunctions, choice “ Synchronize cloud function list ”, Complete the synchronization of cloud function list and upload and deploy getContent and getUserCollectList Cloud function operation , Recompile and choose the book in the first volume of grade one , Dictation function can be realized . Similarly, importing the remaining database collection can realize the dictation function of all books , Pictured 5 Shown .

▍ chart 5 Synchronize cloud function list
02、 Project code
pages/chooseBook/chooseBook.wxml The code for is as follows :
<view id="chooseBook">
<button
class='toCollect'
bindtap='toCollect'
> Wrong questions </button>
<button class='button' open-type="feedback">
<icon type="info_circle" color='rgba(255, 0, 0, 0.6)' size="16" style='margin-right:2px;'></icon>
<text class='button_title'> Feedback suggestions </text>
</button>
<view class='tab'>
<scroll-view scroll-x="true" class='tab-nav' scroll-left='{
{scrollLeft}}' scroll-with-animation="true">
<view wx:for="{
{navlist}}" wx:key="unique" class='{
{current==index?"on":""}}' data-current="{
{index}}" bindtap='tab'>{
{item}}</view>
</scroll-view>
<swiper class='tab-box'zz current="{
{current}}" bindchange="eventchange">
<swiper-item wx:for="{
{conlist}}" wx:key="unique">
<view class='tip'> Slide left and right to switch </view>
<view class="module-container">
<view class="box-wrapper" wx:for="{
{item.moudles}}" wx:key="index">
<navigator url="{
{item.url}}" hover-class="none">
<view class="servicebox">
<image src="{
{item.src}}" class="box-img"/>
<text style='font-size: 35rpx;'>{
{item.text}}</text>
</view>
</navigator>
</view>
</view>
</swiper-item>
</swiper>
</view>
</view>pages/chooseBook/chooseBook.js The code for is as follows :
const app = getApp()
Page({
data: {
current: 0,// The current slider index
navlist: [" Grade one or two ", " Third and fourth grade ", " Fifth and sixth grade "],
// Textbook list
conlist: []
},
//tab Switch
tab: function (event) {
this.setData({ current: event.target.dataset.current })
// Anchor handling
},
// Sliding events
eventchange: function (event) {
this.setData({ current: event.detail.current })
// Anchor handling
},
// Life cycle function -- Monitor page loading
onLoad: function (options) {
this.setData({
conlist: [
{
moudles: [
{
url: './chooseLesson/chooseLesson?book=rn_11',
src: '/img/book/ch_rn_11.jpg',
text: ' The first volume of grade one edited by the Ministry '
},
{
url: './chooseLesson/chooseLesson?book=rn_12',
src: '/img/book/ch_rn_12.jpg',
text: ' The second volume of grade one edited by the Ministry '
},
{
url: './chooseLesson/chooseLesson?book=rn_21',
src: '/img/book/ch_rn_21.jpg',
text: ' Department edition second grade volume 1 '
},
{
url: './chooseLesson/chooseLesson?book=rn_22',
src: '/img/book/ch_rn_22.jpg',
text: ' Department edition second grade volume II '
}
]
},
{
moudles: [
{
url: './chooseLesson/chooseLesson?book=rn_31',
src: '/img/book/ch_rn_31.jpg',
text: ' Department edition third grade volume 1 '
},
{
url: './chooseLesson/chooseLesson?book=rn_32',
src: '/img/book/ch_rn_32.jpg',
text: ' Department edition third grade volume II '
},
{
url: './chooseLesson/chooseLesson?book=rn_41',
src: '/img/book/ch_rn_41.jpg',
text: ' PEP fourth grade volume 1 '
},
{
url: './chooseLesson/chooseLesson?book=rn_42',
src: '/img/book/ch_rn_42.jpg',
text: ' PEP fourth grade volume II '
}
]
},
{
moudles: [
{
url: './chooseLesson/chooseLesson?book=rn_51',
src: '/img/book/ch_rn_51.jpg',
text: ' People's Education Edition fifth grade volume 1 '
},
{
url: './chooseLesson/chooseLesson?book=rn_52',
src: '/img/book/ch_rn_52.jpg',
text: ' People's Education Edition fifth grade volume II '
},
{
url: './chooseLesson/chooseLesson?book=rn_61',
src: '/img/book/ch_rn_61.jpg',
text: ' PEP sixth grade volume 1 '
},
{
url: './chooseLesson/chooseLesson?book=rn_62',
src: '/img/book/ch_rn_62.jpg',
text: ' PEP sixth grade volume II '
}
]
},
],
})
},
toCollect: function () {
wx.navigateTo({
url: "../user/collectList/collectList",
})
},
onReady: function () {},
onShow: function () {},
onHide: function () {},
onUnload: function () {},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {}
})pages/chooseBook/chooseBook.wxss The code for is as follows :
.button {
position: fixed;
left: 20rpx;
bottom: 30rpx;
background: #FAF0E6;
border: none;
text-align: left;
margin: 0px;
line-height: 1.6;
border-radius: 0;
}
.button::after {
border: none;
border-radius: 0;
}
.button_title {
font-size: 12px;
color: rgb(114, 112, 112);
}
.toCollect {
position: fixed;
bottom: 100rpx;
right: 40rpx;
font-size: 40rpx;
height: 70rpx;
line-height: 70rpx;
background-color: rgba(255, 213, 124, 0.925);
z-index: 999;
box-shadow: 2px 2px 2px #bbb;
}
/* tab Switching effect */
swiper {
height: 1000rpx;
}
.tab{ padding: 20rpx 0;}
.tab-nav{
height: 80rpx;
line-height: 80rpx;
}
.tab-nav view{
float: left;
height: 80rpx;
line-height: 80rpx;
background: #FAF0E6;
width: 33.33%;
font-size: 30rpx;
text-align: center;
color: #000;
}
.tab-nav view.on{
background: #FAF0E6;
color: rgb(255, 201, 18);
position: relative;
}
.tab-nav view.on:after{
content: "";
display: block;
height: 6rpx;
width: 26px;
background: rgb(243, 189, 10);
position: absolute;
bottom: 2px;
left: calc(50% - 12px);
border-radius: 16rpx;
}
.tip {
color: #aaa;
text-align: center;
font-size: 35rpx;
margin-top: 20rpx;
}
/* Book Options */
#chooseBook .module-container {
width: 100%;
display: flex;
flex-wrap:wrap;
box-sizing: border-box;
flex-direction:row;
justify-content: center;
margin-top: 55rpx;
}
#chooseBook .module-container .box-wrapper{
height: 300rpx;
width: 200rpx;
margin: 0 70rpx;
margin-bottom: 95rpx;
}
/* Service options */
#chooseBook .module-container .box-wrapper .servicebox{
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
text-align: center;
}
#chooseBook .module-container .box-wrapper .servicebox .box-img{
height:250rpx;
width: 100%;
margin-bottom: 10rpx;
box-shadow: 2px 2px 3px #aaa;
}Code explanation
chooseBook.js Of onLoad() Function is conlist Each element in the list sets the corresponding url、src and text Content , In order to bind these data in chooseBook.wxml in , Run the program to render and display .
pages/chooseBook/chooseLesson/chooseLesson.wxml The code for is as follows :
<view id="listen">
<view class='tab'>
<scroll-view scroll-x="true" class='tab-nav' scroll-left='{
{scrollLeft}}' scroll-with-animation="true">
<view class='tab-nav-c' style='width:{
{conlist.length*90}}px'>
<view wx:for="{
{conlist}}" wx:key="unit" class='{
{current==index?"on":""}}' data-current="{
{index}}" bindtap='tab'> The first {
{index==0?' One ':index==1?' Two ':index==2?' 3、 ... and ':index==3?' Four ':index==4?' 5、 ... and ':index==5?' 6、 ... and ':index==6?' 7、 ... and ':index==7?' 8、 ... and ':index==8?' Nine ':index==9?' Ten ':''}} unit </view>
</view>
</scroll-view>
</view>
<view class='swiper-box'>
<swiper class='swiper' style='height:{
{conlist[current].length*150+135}}rpx;' current="{
{current}}" bindchange="eventchange">
<swiper-item wx:for="{
{conlist}}" wx:key="unit">
<view class='tip'> Slide left and right to switch </view>
<view class="module-container">
<view class="box-wrapper" wx:for="{
{item}}" wx:key="index">
<view class="text-box">
<text>{
{item.title}}</text>
</view>
<view class="img-box" data-content='{
{item}}' bindtap='toDetail'>
<image src='/img/listen2.png' mode="widthFix"></image>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</view>pages/chooseBook/chooseLesson/chooseLesson.js The code for is as follows :
const db = wx.cloud.database();
const _ = db.command;
let plugin = requirePlugin("WechatSI");
let manager = plugin.getRecordRecognitionManager();
const innerAudioContext = wx.createInnerAudioContext();
let that;
let book;
Page({
data: {
current: 0,// The current slider index
scrollLeft: -90,// Scroll bar position , The width of a tab is 90( Customize from css), In proportion 90*n Set location
conlist: [],
},
//tab Switch
tab: function (event) {
// console.log(event.target.dataset.current);
this.setData({ current: event.target.dataset.current })
// Anchor handling
this.setData({
scrollLeft: event.target.dataset.current * 90 - 90,
})
},
// Sliding events
eventchange: function (event) {
console.log(event.detail.current)
this.setData({ current: event.detail.current })
// Anchor handling
this.setData({
scrollLeft: event.detail.current * 90 - 90,
})
},
toDetail: function (e) {
let content = '';
let speak = '';
for (let word of e.currentTarget.dataset.content.content) {
content = content + word + '/';
}
if (e.currentTarget.dataset.content.speak) {
for (let word of e.currentTarget.dataset.content.speak) {
speak = speak + word + '/';
}
}
wx.navigateTo({
url: './detail/detail?content=' + content + '&speak=' + speak + '&book=' + book,
})
},
onLoad: function (options) {
wx.showLoading({
title: ' Loading ',
});
book = options.book;
that = this;
// setNavigationBarTitle
let bookName = ' Chinese language and literature ';
let bookLevel = {
"11": " First grade volume 1 ",
"12": " Grade one volume two ",
"21": " Second grade volume one ",
"22": " Second grade volume two ",
"31": " Third grade volume one ",
"32": " Third grade volume two ",
"41": " Fourth grade volume one ",
"42": " Fourth grade volume two ",
"51": " Grade five volume one ",
"52": " Grade 5 Volume 2 ",
"61": " Sixth grade volume one ",
"62": " Sixth grade volume two ",
}
if (book.search("su") != -1) { bookName += ' Jiangsu Education Press ' } else if (book.search("zh") != -1) { bookName += ' Zhejiang Education Edition ' } else if (book.search("rn") != -1 && (book.search("4") != -1 || book.search("5") != -1 || book.search("6") != -1)) { bookName += ' People's education ' } else { bookName += ' Department Edition ' }
for (let key in bookLevel) {
if (book.search(key) != -1) {
bookName += bookLevel[key]
}
}
wx.setNavigationBarTitle({
title: bookName
})
let dbBook = book;
let conlist = [];
// Use cloud functions , Able to read 100 strip
wx.cloud.callFunction({
name: 'getContent',
data: {
dbBook: dbBook
}
}).then(res => {
that.setData({
conlist: res.result
});
wx.hideLoading();
})
},
onReady: function () {
},
onShow: function () {
},
onHide: function () {
},
onUnload: function () {
innerAudioContext.offPlay();
},
onPullDownRefresh: function () {
},
onReachBottom: function () {},
onShareAppMessage: function () {
}
})pages/chooseBook/chooseLesson/chooseLesson.wxss The code for is as follows :
page {
background-color: #fff;
}
/* tab Switching effect */
.swiper-box {
/* overflow-y: scroll; */
height: 90%;
position: absolute;
width: 100%;
}
.swiper {
min-height: 100%;
width: 100%;
height: 100%;
}
.tip {
color: #888;
/* border-bottom: 1px solid #f2f2f2; */
text-align: center;
font-size: 35rpx;
line-height: 35rpx;
padding: 30rpx;
}
scroll-view{
width: 100%;
height: 100%;/* Dynamic height */
overflow-y: scroll;
}
/* Top tab */
.tab{
height: 80rpx;
box-shadow: 0px 2px 3px #888888;
}
.tab-nav{
height: 80rpx;
line-height: 80rpx;
width: 100%;
background-color: #FAF0E6;
}
.tab-nav .tab-nav-c view{
height: 80rpx;
line-height: 80rpx;
float: left;
width: 90px;
font-size: 30rpx;
text-align: center;
color: #000;
}
.tab-nav view.on{
background: #FAF0E6;
color: rgb(255, 201, 18);
position: relative;
}
.tab-nav view.on:after{
content: "";
display: block;
height: 6rpx;
width: 26px;
background: rgb(243, 189, 10);
position: absolute;
bottom: 2px;
left: 32px;
border-radius: 16rpx;
}
/* words */
#listen .module-container {
width: 100%;
display: flex;
flex-wrap:nowrap;
flex-direction:column;
justify-content: center;
align-items: center;
}
#listen .module-container .box-wrapper{
background-color: #f2f2f2;
border-bottom: 1px solid #c2c2c2;
display: flex;
flex-direction: row;
align-items: center;
flex-wrap:nowrap;
width: 100%;
height: 150rpx;
justify-content: center;
}
#listen .module-container .box-wrapper .text-box{
display: flex;
width: 70%;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
#listen .module-container .box-wrapper .text-box text{
font-size: 40rpx;
text-align: center;
line-height: 60rpx;
}
#listen .module-container .box-wrapper .img-box {
width: 20%;
}
#listen .module-container .box-wrapper .img-box image {
width: 100%;
}
/* Service options */
#listen .module-container .box-wrapper .servicebox{
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
text-align: center;
}
#listen .module-container .box-wrapper .servicebox .box-img{
height:250rpx;
width: 100%;
margin-bottom: 5rpx;
}
Code explanation
chooseLesson .js Of onLoad() Function automatically executes the query operation of cloud database , Get the data of textbooks in the cloud database , And assign it to “book”, Then through data binding in chooseLesson.wxml Rendering display .
pages/chooseBook/chooseLesson/detail/detail.wxml The code for is as follows :
<view id='detail'>
<van-transition name="fade" duration='1000' show="{
{show}}" style="{
{i==sum?'display:none':''}}">
<view style="width:80%;margin:0 auto;position:relitive;top:-80rpx;">
<van-steps
steps="{
{ steps }}"
active="{
{ active }}"
/>
</view>
<view class="page__bd">
<view class="icon-box" bindtap='preWord'>
<image
class='icon'
style=' width: 150rpx;height: 150rpx;'
src="/img/pre.png"
> the previous </image>
<view class="icon-box__ctn">
<view class="icon-box__title"> the previous </view>
</view>
</view>
<view class="icon-box" bindtap='nextWord'>
<image
class='icon'
src="/img/{
{(i==-1?'start':i==sum-1?'end':'next')}}.png"
> next </image>
<view class="icon-box__ctn">
<view class="icon-box__title"> next </view>
</view>
</view>
<view class="icon-box" style='margin-bottom: 0;' bindtap='again'>
<image
class='icon'
style=' width: 150rpx;height: 150rpx;'
src="/img/again.png"
> Read it again </image>
<view class="icon-box__ctn">
<view class="icon-box__title"> Read it again </view>
</view>
</view>
</view>
</van-transition>
<view style="{
{i<sum?'display:none':''}}">
<view class="weui-cells__title" style="font-size:16px;color:#000;margin-bottom:40rpx;"> Please proofread :</view>
<view class="weui-cells weui-cells_after-title">
<checkbox-group bindchange="checkboxChange">
<label class="weui-cell weui-check__label" wx:for="{
{content}}" wx:key="index">
<checkbox class="weui-check" value="{
{item.value}}" checked="{
{item.checked}}"/>
<view class="weui-cell__hd weui-check__hd_in-checkbox">
<icon class="weui-icon-checkbox_circle" type="circle" size="23" wx:if="{
{!item.checked}}"></icon>
<icon class="weui-icon-checkbox_success" type="cancel" size="23" wx:if="{
{item.checked}}"></icon>
</view>
<view class="weui-cell__bd">{
{item.name}}</view>
</label>
</checkbox-group>
</view>
<view class="weui-btn-area">
<button class="weui-btn" style='background-color:#fff' plain="" type="default" bindtap="submit" disabled='{
{submit}}'> Submit the wrong question </button>
<button class="weui-btn weui_btn_primary" style='color:#fff;background-color:#33CC99' plain="" type="default" bindtap="submitAndAgain" disabled='{
{submit}}'> Listen again </button>
</view>
</view>
</view>pages/chooseBook/chooseLesson/detail/detail.js The code for is as follows :
const db = wx.cloud.database();
const _ = db.command;
let plugin = requirePlugin("WechatSI");
let manager = plugin.getRecordRecognitionManager();
const innerAudioContext = wx.createInnerAudioContext();
let that;
let i;
let active;
let oriSpeak;
let oriContent;
let book;
Page({
data: {
i: -1,
sum: 99,
userCollect: [],
content: [],
speak: [],
steps: [],
active: -1,
show: true,
submit: false
},
// Text to speech ( speech synthesis )
wordToSpeak: function (word) {
let that = this;
plugin.textToSpeech({
lang: "zh_CN",
tts: true,
content: word,
success: function (res) {
console.log(" tts", res)
innerAudioContext.autoplay = true
innerAudioContext.src = res.filename
wx.showLoading({
// Uncomment when submitting
mask: true,
title: ' Playing ',
})
},
fail: function (res) {
console.log("fail tts", res)
}
})
},
// next
nextWord: function (e) {
active = this.data.active;
i = this.data.i;
this.setData({
active: ++active,
i: i+1
});
that.wordToSpeak(this.data.speak[i+1]);
},
// the previous
preWord: function (e) {
i = this.data.i;
i = this.data.i;
if (i > 0) {
this.setData({
active: --active,
i: i - 1
});
that.wordToSpeak(this.data.speak[i-1]);
} else {
wx.showToast({
icon: 'none',
title: ' There's no last one !',
})
}
},
// repeat
again: function (e) {
i = this.data.i;
if (i > -1) {
that.wordToSpeak(this.data.speak[i]);
} else {
wx.showToast({
icon: 'none',
title: ' Please start first !',
})
}
},
onLoad: function (options) {
oriSpeak = options.speak;
oriContent = options.content;
book = options.book;
let content = [];
let speak = [];
let contentTemp = [];
console.log(options);
that = this;
speak = options.speak.split('/');
speak.pop();
content = options.content.split('/');
content.pop();
this.setData({
sum: content.length,
speak: (speak.length == 0 ? content : speak),
steps: content
})
for (let name of content) {
let o = {};
o['name'] = name;
o['value'] = name;
contentTemp.push(o);
}
that.setData({
content: contentTemp
})
innerAudioContext.onPlay(() => {
console.log(' Start playing ')
})
innerAudioContext.onError((res) => {
if (res) {
console.log(res)
wx.hideLoading(),
wx.showToast({
title: ' Text format error ',
image: '/images/fail.png',
})
}
})
innerAudioContext.onEnded(function () {
manager.start({
lang: "zh_CN"
})
wx.hideLoading()
})
},
checkboxChange: function (e) {
console.log('checkbox happen change event , carry value The value is :', e.detail.value);
var checkboxItems = this.data.content, values = e.detail.value;
for (var i = 0, lenI = checkboxItems.length; i < lenI; ++i) {
checkboxItems[i].checked = false;
for (var j = 0, lenJ = values.length; j < lenJ; ++j) {
if (checkboxItems[i].value == values[j]) {
checkboxItems[i].checked = true;
break;
}
}
}
this.setData({
content: checkboxItems,
userCollect: e.detail.value
});
},
submit: function () {
this.setData({
submit: true
})
wx.showLoading({
title: ' In submission ...',
mask:true
})
let userCollectID;
if (that.data.userCollect) {
db.collection('userCollectList').add({
data: {
collect: that.data.userCollect,
book: book,
createTime: db.serverDate()
},
success(res) {
wx.hideLoading();
wx.showToast({
title: ' Submit successfully !',
duration: 3000,
mask: true
})
setTimeout(() => {
wx.navigateBack({
})
}, 1000)
}
})
} else {
wx.hideLoading();
wx.showToast({
title: ' Submit successfully !',
duration: 3000,
mask: true
})
setTimeout(() => {
wx.navigateBack({
})
},1000)
}
},
submitAndAgain: function () {
this.setData({
submit: true
})
wx.showLoading({
title: ' In submission ...',
mask: true
})
let userCollectID;
if (that.data.userCollect) {
db.collection('userCollectList').add({
data: {
collect: that.data.userCollect,
book: book,
createTime: db.serverDate()
},
success(res) {
wx.hideLoading();
wx.showToast({
title: ' Submit successfully !',
duration: 3000,
mask: true
})
setTimeout(() => {
wx.redirectTo({
url: './detail?content=' + oriContent + '&speak=' + oriSpeak
})
}, 300)
}
})
} else {
wx.hideLoading();
wx.showToast({
title: ' Submit successfully !',
duration: 3000,
mask: true
})
setTimeout(() => {
wx.redirectTo({
url:'./detail?content=' + oriContent + '&speak=' + oriSpeak
})
}, 800)
}
},
onReady: function () {},
onShow: function () {},
onHide: function () {},
onUnload: function () {
innerAudioContext.offPlay();
innerAudioContext.offEnded();
innerAudioContext.offError();
innerAudioContext.stop();
wx.stopBackgroundAudio();
manager.start({
lang: "zh_CN"
})
wx.hideLoading()
},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {}
})pages/chooseBook/chooseLesson/detail/detail.wxss The code for is as follows :
#detail {
position: relative;
}
.weui-cell {
width: 40%;
}
checkbox-group {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.weui-cell__bd {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#detail .content-box {
width: 80%;
margin: 0 auto;
margin-top: 220rpx;
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
}
#detail .content-box .content {
font-size: 60rpx;
margin: 0 20rpx;
display: line-block;
}
.page__bd {
margin-top: 90rpx;
padding: 0 30px;
text-align: left;
}
.icon-box{
margin-bottom: 80rpx;
display: flex;
align-items: center;
border: 2px solid #FF9933;
border-radius: 80rpx;
box-shadow: 4px 4px 4px #ddd;
background-color: rgba(255, 224, 51, 0.329);
padding: 30rpx 20rpx;
justify-content: center;
}
.icon-box__ctn{
flex-shrink: 100;
}
.icon-box__title{
font-size: 20px;
}
.icon {
width: 250rpx;
height: 250rpx;
margin-right: 30rpx
}
Code explanation
detail.js Get chooseLesson.js Incoming book data , Use the functions provided by wechat simultaneous interpretation plug-in , call wordToSpeak() Function to convert text to speech , And the function of switching up and down and repeating playback is realized on this page .
边栏推荐
- ES2022 Array.at( )
- SimpleDateFormat 的线程安全问题与解决方案
- 微信小程序实训|基于云数据库的语文听写工具
- The open and closed interval of the mean value theorem of higher numbers | integrals, the first mean value theorem of integrals and its generalization
- Opencv: convert video into continuous image frames
- T100debug operation record
- 文旅夜游:城市经济复苏增长新机遇
- Esp8266+blinker+web distribution network
- Literature learning (part99) -- fast unfolding of communities in large networks
- Box model, document flow, positioning, layout and responsive design
猜你喜欢

MySQL window function running average

文旅夜游项目助力夜间经济发展

用过useEffect,useLayoutEffect吗

The digital transformation forum for small and medium-sized enterprises in Shandong Province was successfully held, and Jiuzhou cloud empowers small and medium-sized enterprises to upgrade their digit

数字孪生工厂丨智慧工厂孪生驾驶舱,实现智能化精益生产管理

2.4_ 9 MySQL by separator, row to column

base64编码解码原理和C语言实现

Workplace essentials | 123 pages Huawei internal project management ppt

XML文件删除掉注释

微信小程序实训|基于云数据库的语文听写工具
随机推荐
Iptables mask access to a port of IP
2018年江苏省信息与未来程序设计小能手比赛试题--(新)鸡兔同笼
Reading true questions | reading true questions record 2
数字孪生工厂丨智慧工厂孪生驾驶舱,实现智能化精益生产管理
2018 Jiangsu Provincial Information and future programming expert competition test question -- (New) chicken and rabbit in the same cage standard schedule
Quarkus practice 2: develop rest ful services to realize simple curd functions
【深度学习-学习笔记01】
Les employés de Tencent postent pour trouver des objets, ce qui indique une préférence pour les programmeurs! Les commentaires sont en feu... 丨 Black Horse Headlines
PMP每日一练 | 考试不迷路-7.14
联盛德W801-如何提高采集多路ADC效率
騰訊員工發帖找對象,錶示偏愛程序員!評論火了......丨黑馬頭條
T100excel import writing template
AB controller l36erm_ Communication between two processors
Tencent employees post to find objects, indicating that they prefer programmers! Comments are hot Dark horse headlines
Ubuntu 18.04 install mysql5.7.35 with tar package
PMP practice once a day | don't get lost in the exam -7.15
Binary tree, traversal
阅读真题 | 真题阅读 做题记录 二
Interview problem: how to close an order without using a scheduled task?
【品牌专场】跨越 X 突破,音视频聚力新机遇