- 宝宝闪卡小程序 - 跟读评测设计
做单词类的小程序,跟读评测是绕不过去的一个功能,但是本身又不具备AI能力,就想这个功能是不是可以往后放放,但是发现如果不做评测,后续的练习就只能有听音选图一种形式,而练习应该是从听,读上进行全面的考察,而且没有孩子方面的输出,也很难看到学习成果,索性抽个时间做了,这里记录下实现的思路。 首先是状态,针对跟读应该分为以下几种状态: 播放标准音频未录音状态录音中状态录音完毕,播放录音音频打分完毕针对上面的不同状态,为了更方便用户理解,要设计不同的引导方案及展示效果,对此我的设计如下 [图片] 虽然相对来说还是比较简陋,但是目前来看至少可以清楚的分开当前进行中的每一种状态,其中在到达最后一个状态时,同步会有星星的展示以及TTS播放。下面简单描述一下每个状态的要点。 1.播放标准音频过程 当打开跟读的悬浮窗时,音频同步播放,在此状态下,按钮不可点击,音频播放完毕状态过度为[2],再次点击黑板,则重复当前状态。 2.未播音状态 在未播音状态下,此时innerAudioContext与recordManager均已就绪,用户点击则调用start开启录音,也可以再次播放标准音频。 3.录音中状态 录音状态下再次点击应调用stop停止录音,此时可以获取到用户录音临时文件。 4.发音播放中 利用 innerAudioContext 播放录制的临时文件,同时应该在音频的播放过程中开启调用三方api进行评测,并在评测的回调中同步保存孩子发音音频文件以及数据库中插入本次跟读的成绩记录,评测完成后会有相应的星星展示以及音频播放,这里为了更直观的展示孩子的发音效果,将分数转化为了星星进行展示,但是数据中存入的数据仍旧为原始分数,这样可以更好的契合不同的展示场景。 5.打分完毕 此时应该重置一切状态,出文案外,与状态1相同。 上面是整个过程的流转,具体的代码不做赘述,但是在开发的过程中还是遇到了一些小问题。 首先是利用innerAudio播放云文件时,会报文件错误,在多次尝试及查阅资料无果后,增加了一步用云文件id换取临时https链接,这样解决了问题, 第二个问题是兼容问题,在iphone12真机测试下,recorder初次初始化需要一定时间,大概在前一秒是录不上任何声音的,后续再次调用无问题,安卓机下也无此问题。由于录音需要向用户申请权限,所以没有办法提前初始化,在尝试了多款小程序后,均发现有此问题,鉴于影响较小,后续没有做其他处理,如果有哪位有解决方案,还望不吝赐教。 [图片]
2021-11-26 - 关于补充小程序、插件用户隐私保护指引说明
为进一步规范开发者的用户个人信息处理行为,保障用户合法权益,小程序、插件中涉及处理用户个人信息的开发者,无论是通过调用涉及用户个人信息的相关接口,还是自行收集用户个人信息,在提交代码版本前,均需补充相应用户隐私保护指引,具体如下: 一、 如小程序、插件有涉及收集用户个人信息(包含通过接口形式收集、通过非接口的形式收集)开发者需在【小程序管理后台-设置-功能设置-用户隐私保护指引】(如果是第三方开发者代开发小程序可通过接口进行配置)/【小程序管理后台-功能-小程序插件-基本设置-用户隐私保护说明】针对具体使用目的与用途进行说明填写,并补充完整隐私指引内容。 二、针对隐私指引说明内容,有如下要求: 1、隐私指引说明内容需与代码包内引用相关接口一致; 2、隐私指引说明内容文字表述需清晰、完整、告知用户处理相应信息的目的与用途; 3、在代码提审环节将对以上要求进行核验,如未满足相应要求,则无法通过代码版本审核,将影响开发者后续版本提审。 平台预计于11月1日对相关接口进行隐私指引说明审核,请开发者及时补充完善隐私指引说明,避免影响相关服务及用户体验。 微信团队 2021年10月29日
2023-09-26 - 跌宕起伏的小程序之登录组件
缘起🧐 开始的开始,简单粗暴。在微信小程序里,一行wx.getUserInfo即可弹窗用户授权登陆。大部分小程序图省事,直接在打开小程序的时候就调这个方法。所以那时候一个印象就是随便打开一个小程序,进去就是弹窗让我登陆,想拿我的微信信息,给人一种不安全的感觉。 当时的代码长这样: [代码]<script> wx.getUserInfo({ success(res) { // res.userInfo 用户信息 } }) </script> [代码] 如果要与业务结合起来,通常会是这样(以下代码示例均使用wepy框架): [代码]<template> <!-- 下面这个操作需要用户登陆 --> <view @tap="clickA">需要登陆操作A</view> <view @tap="clickB">需要登陆操作B</view> </template> <script> { methods = { clickA () { await getUserInfo() // wx.getUserInfo 封装在这里面 // 接着写A的业务逻辑 } clickB () { await getUserInfo() // 接着写B的业务逻辑 } } } </script> [代码] 变数😩 为了防止滥用,微信后来决定调整这个交互,改变了授权登陆流程。于是就发布了一个公告,很突然的,就是直接调wx.getUserInfo不再弹窗询问用户是否授权。而是需要使用原生button组件,用户实际操作点击了屏幕才能触发。 [图片] 此时的代码变成了这个熊样: [代码]<template> <button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo"> 点击授权登陆 </button> </template> <script> { methods = { bindGetUserInfo (e) { // e.detail.userInfo 用户信息 } } } </script> [代码] 看上去问题不大,其实已经原地爆炸。现在如果和业务结合起来就会有很多赘余代码: [代码]<template> <view> <button class="auth-btn" open-type="getUserInfo" bindgetuserinfo="clickA"></button> 需要登陆操作A </view> <view> <button class="auth-btn" open-type="getUserInfo" bindgetuserinfo="clickB"></button> 需要登陆操作B </view> </template> <script> { methods = { clickA (e) { if (e.detail.errMsg === 'getUserInfo:ok') { // 接着写A的业务逻辑 } } clickB (e) { if (e.detail.errMsg === 'getUserInfo:ok') { // 接着写B的业务逻辑 } } } } </script> <style lang="less"> .auth-btn { // 使其cover在父容器上并透明 } </style> [代码] 之前接手过一个遗留项目,里面密密麻麻充斥着这种代码,我看5分钟吐了3次🤮。DRY!DRY!DRY!有代码洁癖加重度强迫症的我完全不能忍。 归途😎 作为一个有追求的追风少年,思虑良久,得想个辙🤔,不然之后的开发生涯就充斥着难受。wepy是一个组件化的小程序框架,可以像写vue组件一样去写小程序的自定义组件。于是就有了一个很自然的想法。把登陆按钮封装起来,使其足够方便。 最后的最后,组件化后的代码长这样🚀: [代码]<template> <view> <LoginButton1 @tap.user="clickA"></LoginButton1> 需要登陆操作A </view> <view> <LoginButton2 @tap.user="clickB"></LoginButton2> 需要登陆操作B </view> </template> <script> import LoginButton from '@/components/LoginButton' { components = { LoginButton1: LoginButton, LoginButton2: LoginButton, } methods = { clickA () { // 直接写A的业务逻辑 } clickB () { // 直接写B的业务逻辑 } } </script> [代码] [代码]{ LoginButton1: LoginButton, LoginButton2: LoginButton }[代码]这个诡异的写法主要是因为wepy的组件是静态组件(其实就是编译时代码复制),导致每实例化一个都要分配一个id😐。据说wepy即将发布2.0版本,会解决这个问题,甚是期待。 这可能不是最优方案,但确实方便了许多。 临末,送大家个福利😘 [图片]
2019-03-29