├── README.md
├── heartSound V1.dmg
├── heartSound V2.dmg
├── heartSound-master V0 GITHUB.dmg
├── heartSound
├── app.js
├── app.json
├── app.wxss
├── components
│ └── waiting-icon
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
├── images
│ ├── about.png
│ ├── back.png
│ ├── begin.png
│ ├── box_1.png
│ ├── box_2.png
│ ├── button.png
│ ├── dele-blue.png
│ ├── dele-pink.png
│ ├── dele.png
│ ├── enter.png
│ ├── fail.png
│ ├── hbty.png
│ ├── issue.png
│ ├── microphone.png
│ ├── rotate-blue.png
│ ├── rotate-pink.png
│ ├── speak.png
│ ├── stop.png
│ ├── tips.png
│ ├── triangleLeft.png
│ ├── triangleRight.png
│ ├── user_1.png
│ ├── user_2.png
│ ├── xljj.png
│ ├── xxs.png
│ └── zxct.png
├── pages
│ ├── index
│ │ ├── draw
│ │ │ ├── draw.js
│ │ │ ├── draw.json
│ │ │ ├── draw.wxml
│ │ │ └── draw.wxss
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ ├── index.wxss
│ │ ├── longtalk
│ │ │ ├── longtalk.js
│ │ │ ├── longtalk.json
│ │ │ ├── longtalk.wxml
│ │ │ └── longtalk.wxss
│ │ └── talk
│ │ │ ├── talk.js
│ │ │ ├── talk.json
│ │ │ ├── talk.wxml
│ │ │ └── talk.wxss
│ └── user
│ │ ├── about
│ │ ├── about.js
│ │ ├── about.json
│ │ ├── about.wxml
│ │ └── about.wxss
│ │ ├── feedback
│ │ ├── feedback.js
│ │ ├── feedback.json
│ │ ├── feedback.wxml
│ │ └── feedback.wxss
│ │ ├── user.js
│ │ ├── user.json
│ │ ├── user.wxml
│ │ └── user.wxss
├── project.config.json
└── utils
│ └── util.js
└── 项目截图
├── about.jpg
├── code.jpg
├── draw.jpg
├── index.jpg
├── letdraw.jpg
├── longtalk.jpg
├── talk.jpg
└── user.jpg
/README.md:
--------------------------------------------------------------------------------
1 | # heartSound
2 | 心声Lite是一款为听障者服务的微信小程序,提供语音识别、语音合成、画板写字等功能,希望能为他们的生活提供一些便利。本项目使用了“同声传译”插件,希望能和大家一起把这个微信小程序完善地更好,为听障者们带来福音。
3 |
4 | **👏👏如果觉得本项目对你学习小程序插件的使用或其他方面有帮助的话,欢迎右上star支持👏👏**
5 |
6 | ### “微信同声传译”插件使用教程:
7 |
8 | 微信公众平台添加插件
9 |
10 | https://developers.weixin.qq.com/miniprogram/introduction/plugin.html#%E4%BD%BF%E7%94%A8%E6%8F%92%E4%BB%B6
11 |
12 | 浏览插件使用文档
13 |
14 | https://developers.weixin.qq.com/miniprogram/dev/framework/plugin/using.html
15 |
16 | 查看微信同声传译开发文档
17 |
18 | https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx069ba97219f66d99&token=321904791&lang=zh_CN
19 |
20 |
21 | 以上材料是我入门插件使用所看的材料,相信阅读完以后,大家对插件也有一定的了解了。接下来就来看看实战的项目吧。
22 |
23 | 先简单的介绍一下本项目。
24 |
25 | ### 马上体验
26 |
27 |
28 |
29 |
30 | ### 以下是主要功能页面的截图。
31 |
32 |
33 |
34 |

35 |

36 |

37 |
38 |
39 |
40 |
46 |
47 | #### 使用流程
48 |
49 | 一、在后台添加好插件以后
50 |
51 | 二、用你添加了插件的小程序的AppID作为小程序开发者创建项目
52 |
53 | 三、在项目的app.json引入插件
54 | ```
55 | {
56 | "pages": [
57 | ...
58 | ],
59 |
60 | ...
61 |
62 | "plugins": {
63 | "WechatSI": {
64 | "version": "0.1.0",
65 | "provider": "wx069ba97219f66d99"
66 | }
67 | }
68 | }
69 | ```
70 |
71 | 四、在需要用到插件功能的页面引入和使用插件,以下的讲解我都写在注释里啦,认真看注释唷!!!
72 | ```
73 | // pages/talk/talk.js
74 |
75 | // 引入插件
76 | var plugin = requirePlugin("WechatSI")
77 | let manager = plugin.getRecordRecognitionManager()
78 |
79 | Page({
80 |
81 | /**
82 | * 页面的初始数据
83 | */
84 | data: {
85 | showmicro:false,
86 | input:'',
87 | content_up:'',
88 | content_down:'你好,我听力不好,你可以按住底部的按钮,对我说普通话'
89 | },
90 |
91 | //监听字的输入,实时显示在屏幕,并且content_down还会用在文字转语音(语音合成)上。
92 | listenInput: function (e) {
93 | var content = e.detail.value
94 | if (content==''){
95 | content = '你好,我听力不好,你可以按住底部的按钮,对我说普通话'
96 | }
97 | this.setData({
98 | content_down: content
99 | })
100 | },
101 |
102 | // 清空输入框的内容
103 | dele: function (e) {
104 | this.setData({
105 | content_down: '',
106 | input:''
107 | })
108 | },
109 |
110 | // 插件使用重要步骤!!!
111 |
112 | // 手指按下
113 | touchdown_plugin: function () {
114 |
115 | // 开始识别语音,设置最长能录30s(插件默认最长能录60s,我觉得30s够了,反正也显示不完- -。)
116 | manager.start({
117 | duration: 30000, lang: "zh_CN"
118 | })
119 |
120 | //让“正在说话”的遮罩层出现
121 | this.setData({
122 | showmicro:true
123 | })
124 | },
125 |
126 | // 手指松开
127 | touchup_plugin: function () {
128 | var that = this
129 |
130 | // 语音停止识别的时候会调用的函数,这里是把最终识别结果返回的内容呈现在content_up中
131 | manager.onStop = function (res) {
132 | that.setData({
133 | content_up: res.result
134 | })
135 | }
136 |
137 | // 当有新的识别内容返回,就会调用此事件。一般用于想马上得到结果的那种,否则还是onstop用的习惯一些,项目没用到这个,仅作讲解
138 | // manager.onRecognize = function (res) {
139 | // that.setData({
140 | // content_up: res.result
141 | // })
142 | //}
143 |
144 | //语音识别停止(此时就会调用manager.onStop函数)
145 | manager.stop();
146 |
147 | //让“正在说话”的遮罩层消失
148 | this.setData({
149 | showmicro: false,
150 | })
151 | },
152 |
153 | // 文字转语音(语音合成)
154 | wordtospeak: function(e) {
155 |
156 | // 将wxml中传过来的文本内容存起来,用api传给插件
157 | var content = e.currentTarget.dataset.content
158 |
159 | var that = this
160 | plugin.textToSpeech({
161 | lang: "zh_CN",
162 | tts: true,
163 | content: content,
164 | success: function (res) {
165 |
166 | // 插件返回合成好以后的mp3文件,用api自动播放
167 | const innerAudioContext = wx.createInnerAudioContext()
168 | innerAudioContext.autoplay = true
169 | innerAudioContext.src = res.filename
170 | innerAudioContext.onPlay(() => {
171 | console.log('开始播放')
172 | })
173 |
174 | console.log("succ tts", res.filename)
175 | },
176 | fail: function (res) {
177 | console.log("fail tts", res)
178 | }
179 | })
180 | },
181 |
182 | /**
183 | * 用户点击右上角分享
184 | */
185 | onShareAppMessage: function () {
186 | return {
187 | title: '心声Lite,让爱发声',
188 | path: '/pages/index/talk/talk',
189 | imageUrl: '/images/xxs.png'
190 | }
191 | },
192 | })
193 | ```
194 |
195 |
196 | ### 更新日志:
197 |
198 | #### 2018年8月6日 周一
199 | 1.因为“同声传译”插件那边的问题,第一次识别的时候总是没有返回值,所以我只能加一个标签说需要第一次试音之后才能正常使用来提示用户。
200 | 2.当开始识别语音时,加入了一个提示的遮罩层。V0是必须要录够3S,才能结束一次,现在修改成了松开后就停止录音,返回识别,遮罩层消失。
201 | 3.增加了onShareAppMessage的内容
202 |
203 | #### 2018年8月7日 周二
204 | 1.修复了第一次无法识别的问题,其实是我自己的代码问题- -。以后还是要好好看别人的开发手册和别人写的demo呀,然后要学会调试,看错误码。
205 | 2.语音合成并播放的时候增加了一个提示,这样听障用户就知道自己的语音已经在播放了,播放完毕时,这个提示才会消失。
206 | 3.语音合成的按钮修复了可以连续点击的bug,一直点会很鬼畜- -。所以改成了每次点击都会停止前一个语音的播放,然后开启当前的语音播放,保证每次都只有一条语音在播放。
207 | 4.之前还忽略了一个录音授权的bug,如果不写在onload里面的话,当用户点击按钮才会自动调用授权,这样子的话已经按了按钮一次了,有些值就会发生变化,所以现在加上了录音授权的```app.getRecordAuth()```,并且用户可能会按拒绝授权,这时候我也考虑到了,我在没有授权的回调函数里写了个
208 | ```
209 | wx.showToast({
210 | title: '录音授权失败',
211 | image:'/images/fail.png',
212 | duration:1000
213 | })
214 | setTimeout(function () {
215 | wx.openSetting({
216 |
217 | })
218 | }, 1000)
219 | ```
220 | 这样就会toast提示,然后跳转到设置界面,让用户可以点击授权(毕竟不授权录音就肯定没法识别呀)
221 |
222 | #### 2018年8月8日 周三
223 | 1.修复了文字转语音(语音合成)遇到纯字符文本时会出问题的bug。debug过程主要是根据api返回的错误码
224 | 2.从face2face的demo中偷了个component——animation-icon,就是用在正在录音时提示用户的,我觉得还挺好看哈哈,就用上了
225 | 3.增加了坐下长谈的部分,原本想着api限制的manager.start最长只能录制1分钟,但是我发现了听障者使用语音合成功能时,语音识别会自动中断,于是我就在语音合成的按钮点击事件里加上了一个识别停止,然后播放完语音,又开始识别的过程。一般比较少听障者1分钟一直不讲话一直都在听,所以就算比较好的解决这个问题了,在做这个功能模块的过程中也是遇到了不少坑的。
226 | 4.坐下长谈的部分是用了“微信同声传译”中提供的一个方法```manager.onRecognize```有新的识别内容返回,则会调用此事件
227 | ```
228 | manager.onRecognize = function(res) {
229 | console.log("current result", res.result)
230 | }
231 | ```
232 | 然后就是在语音识别的过程中,识别到了什么就返回什么,但是感觉这个AI在断句上还有待提高- -。感觉经常断错句哈哈
233 | 5.为了充分利用布局,并且想加个分享按钮,我把授权登陆的那块换成了,这里有个知识点,就是如果想在其他按钮上出发转发事件(而不是右上角的那个转发),就要给button加上一个```open-type="share"```,这样点击这个按钮就会触发转发事件了。如果有多个按钮想触发不同的转发文本的事件的话可以给button设置传id,然后根据res.target.id来区分
234 |
235 | ```
236 | wxml
237 |
238 |
241 |
242 |
245 | ```
246 |
247 | ```
248 | js
249 |
250 | onShareAppMessage: function () {
251 | return {
252 | title: '心声Lite,用心说话',
253 | desc: '语音识别,语音合成,画板涂鸦,心声Lite — 致力于为听障者服务。',
254 | path: '/pages/index/index',
255 | imageUrl: '/images/xxs.png'
256 | }
257 | },
258 | ```
259 |
260 |
261 | #### 目前待添加功能:
262 | 1.快捷输入,可以将清空input框的那个按钮换成快捷输入的按钮,就是用户可以自己预设,即提前输入一些常用的句子,这样在聊天的过程中可以通过点击这个快捷输入按钮,再点击想要的预设句子,快速的输入想表达的内容。可以将该按钮设置成长按触发的按钮这样。
263 |
--------------------------------------------------------------------------------
/heartSound V1.dmg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound V1.dmg
--------------------------------------------------------------------------------
/heartSound V2.dmg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound V2.dmg
--------------------------------------------------------------------------------
/heartSound-master V0 GITHUB.dmg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound-master V0 GITHUB.dmg
--------------------------------------------------------------------------------
/heartSound/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | // 展示本地存储能力
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 |
9 | // 登录
10 | wx.login({
11 | success: res => {
12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
13 | }
14 | })
15 | // 获取用户信息
16 | wx.getSetting({
17 | success: res => {
18 | if (res.authSetting['scope.userInfo']) {
19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
20 | wx.getUserInfo({
21 | success: res => {
22 | // 可以将 res 发送给后台解码出 unionId
23 | this.globalData.userInfo = res.userInfo
24 |
25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
26 | // 所以此处加入 callback 以防止这种情况
27 | if (this.userInfoReadyCallback) {
28 | this.userInfoReadyCallback(res)
29 | }
30 | }
31 | })
32 | }
33 | }
34 | })
35 | },
36 | // 权限询问
37 | getRecordAuth: function () {
38 | wx.getSetting({
39 | success(res) {
40 | console.log("succ")
41 | console.log(res)
42 | if (!res.authSetting['scope.record']) {
43 | wx.authorize({
44 | scope: 'scope.record',
45 | success() {
46 | // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
47 | console.log("succ auth")
48 | }, fail() {
49 | wx.showToast({
50 | title: '录音授权失败',
51 | image:'/images/fail.png',
52 | duration:1000
53 | })
54 | setTimeout(function () {
55 | wx.openSetting({
56 |
57 | })
58 | }, 1000)
59 | console.log("fail auth")
60 | }
61 | })
62 | } else {
63 | console.log("record has been authed")
64 | }
65 | }, fail(res) {
66 | console.log("fail")
67 | console.log(res)
68 | }
69 | })
70 | },
71 | onHide: function () {
72 | wx.stopBackgroundAudio()
73 | },
74 | globalData: {
75 | userInfo: null
76 | }
77 | })
--------------------------------------------------------------------------------
/heartSound/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/index/draw/draw",
5 | "pages/index/talk/talk",
6 | "pages/index/longtalk/longtalk",
7 | "pages/user/user",
8 | "pages/user/about/about",
9 | "pages/user/feedback/feedback"
10 | ],
11 | "window": {
12 | "backgroundTextStyle": "light",
13 | "navigationBarBackgroundColor": "#f3a09e",
14 | "navigationBarTitleText": "心声Lite",
15 | "navigationBarTextStyle": "fff"
16 | },
17 | "tabBar": {
18 | "color": "#8a8a8a",
19 | "selectedColor": "#f3a09e",
20 | "borderStyle": "#f3a09e",
21 | "list": [
22 | {
23 | "iconPath": "images/box_1.png",
24 | "selectedIconPath": "images/box_2.png",
25 | "pagePath": "pages/index/index",
26 | "text": "工具"
27 | },
28 | {
29 | "iconPath": "images/user_1.png",
30 | "selectedIconPath": "images/user_2.png",
31 | "pagePath": "pages/user/user",
32 | "text": "我的"
33 | }
34 | ]
35 | },
36 | "plugins": {
37 | "WechatSI": {
38 | "version": "0.1.0",
39 | "provider": "wx069ba97219f66d99"
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/heartSound/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | .container {
3 | font-size: 60rpx;
4 | display: flex;
5 | flex-direction: column;
6 | width: 100%;
7 | height: 100%;
8 | background: #f0f0f0;
9 | color: #515151;
10 | position: fixed;
11 | top: 0;
12 | left: 0;
13 | right: 0;
14 | bottom: 0;
15 | }
16 |
17 | .section{
18 | height: 1%;
19 | width: 100%;
20 | background: #999999;
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/heartSound/components/waiting-icon/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Tencent is pleased to support the open source community by making Face-2-Face Translator available.
3 |
4 | Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved.
5 |
6 | Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
7 | http://opensource.org/licenses/MIT
8 |
9 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10 | */
11 |
12 | Component({
13 |
14 | properties: {
15 |
16 | },
17 |
18 | data: {
19 | waiting_animation: {},
20 | waiting_animation_1: {},
21 | },
22 |
23 | ready: function () {
24 | console.log("ready waitting")
25 | this.waiting_animation = wx.createAnimation({
26 | duration: 600
27 | })
28 | this.waiting_animation_1 = wx.createAnimation({
29 | duration: 400
30 | })
31 |
32 | this.setWaitInterval()
33 |
34 | },
35 |
36 | // 组件生命周期函数,在组件实例被从页面节点树移除时执行
37 | detached: function() {
38 | this.clearAnimation()
39 | },
40 |
41 | methods: {
42 |
43 | clearAnimation: function() {
44 | this.endWaitAnimation()
45 | },
46 |
47 | /**
48 | * 清除动画
49 | */
50 | endWaitAnimation: function() {
51 | clearInterval(this.data.waiting_interval)
52 |
53 | this.setData({ waiting_animation : {}})
54 | this.setData({ waiting_animation_1: {} })
55 | },
56 | startWaitAnimation: function () {
57 |
58 | this.waiting_animation.opacity(0).scale(1.2, 1.2).step()
59 | this.waiting_animation.opacity(1).scale(1, 1).step()
60 | this.setData({ waiting_animation: this.waiting_animation.export() })
61 |
62 | this.waiting_animation_1.opacity(0).scale(1.2, 1.2).step()
63 | this.waiting_animation_1.opacity(1).scale(1, 1).step()
64 | this.setData({ waiting_animation_1: this.waiting_animation_1.export() })
65 |
66 | },
67 |
68 | /**
69 | * 设置动画
70 | */
71 | setWaitInterval: function() {
72 | this.endWaitAnimation()
73 |
74 | this.data.waiting_interval = setInterval( ()=>{
75 | this.startWaitAnimation()
76 | },600 )
77 |
78 | },
79 |
80 |
81 | }
82 | });
--------------------------------------------------------------------------------
/heartSound/components/waiting-icon/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
4 |
--------------------------------------------------------------------------------
/heartSound/components/waiting-icon/index.wxml:
--------------------------------------------------------------------------------
1 |
2 | .
3 | .
4 | .
5 |
--------------------------------------------------------------------------------
/heartSound/components/waiting-icon/index.wxss:
--------------------------------------------------------------------------------
1 |
2 | .loading {
3 | position: relative;
4 | display: inline;
5 | }
6 |
7 | .loading-icon {
8 | display: inline;
9 | }
10 |
--------------------------------------------------------------------------------
/heartSound/images/about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/about.png
--------------------------------------------------------------------------------
/heartSound/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/back.png
--------------------------------------------------------------------------------
/heartSound/images/begin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/begin.png
--------------------------------------------------------------------------------
/heartSound/images/box_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/box_1.png
--------------------------------------------------------------------------------
/heartSound/images/box_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/box_2.png
--------------------------------------------------------------------------------
/heartSound/images/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/button.png
--------------------------------------------------------------------------------
/heartSound/images/dele-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/dele-blue.png
--------------------------------------------------------------------------------
/heartSound/images/dele-pink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/dele-pink.png
--------------------------------------------------------------------------------
/heartSound/images/dele.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/dele.png
--------------------------------------------------------------------------------
/heartSound/images/enter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/enter.png
--------------------------------------------------------------------------------
/heartSound/images/fail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/fail.png
--------------------------------------------------------------------------------
/heartSound/images/hbty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/hbty.png
--------------------------------------------------------------------------------
/heartSound/images/issue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/issue.png
--------------------------------------------------------------------------------
/heartSound/images/microphone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/microphone.png
--------------------------------------------------------------------------------
/heartSound/images/rotate-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/rotate-blue.png
--------------------------------------------------------------------------------
/heartSound/images/rotate-pink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/rotate-pink.png
--------------------------------------------------------------------------------
/heartSound/images/speak.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/speak.png
--------------------------------------------------------------------------------
/heartSound/images/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/stop.png
--------------------------------------------------------------------------------
/heartSound/images/tips.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/tips.png
--------------------------------------------------------------------------------
/heartSound/images/triangleLeft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/triangleLeft.png
--------------------------------------------------------------------------------
/heartSound/images/triangleRight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/triangleRight.png
--------------------------------------------------------------------------------
/heartSound/images/user_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/user_1.png
--------------------------------------------------------------------------------
/heartSound/images/user_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/user_2.png
--------------------------------------------------------------------------------
/heartSound/images/xljj.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/xljj.png
--------------------------------------------------------------------------------
/heartSound/images/xxs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/xxs.png
--------------------------------------------------------------------------------
/heartSound/images/zxct.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/heartSound/images/zxct.png
--------------------------------------------------------------------------------
/heartSound/pages/index/draw/draw.js:
--------------------------------------------------------------------------------
1 | let ctx;
2 | Page({
3 | data: {
4 | isrotate:false,
5 | tempFilePath:'',
6 | pen: {
7 | lineWidth: 5,
8 | color: "#2c2c2c"
9 | }
10 | },
11 | onShareAppMessage: function () {
12 | return {
13 | title: '心声Lite,用画笔说话',
14 | path: '/pages/index/draw/draw',
15 | imageUrl: '/images/xxs.png'
16 | }
17 | },
18 | onLoad(options) {
19 | ctx = wx.createCanvasContext('myCanvas');
20 | ctx.setStrokeStyle(this.data.pen.color);
21 | ctx.setLineWidth(this.data.pen.lineWidth);
22 | ctx.setLineCap('round');
23 | ctx.setLineJoin('round');
24 | },
25 | touchstart(e) {
26 | ctx.setStrokeStyle(this.data.pen.color);
27 | ctx.setLineWidth(this.data.pen.lineWidth);
28 | ctx.moveTo(e.touches[0].x, e.touches[0].y);
29 | },
30 | touchmove(e) {
31 | let x = e.touches[0].x;
32 | let y = e.touches[0].y;
33 | ctx.lineTo(x, y)
34 | ctx.stroke();
35 | ctx.draw(true);
36 | ctx.moveTo(x, y)
37 | },
38 | dele: function () {
39 | ctx.setFillStyle('#ffffff')
40 | ctx.fillRect(0, 0, 750, 1000)
41 | ctx.draw()
42 | },
43 | rotate: function () {
44 | wx.showToast({
45 | title: '旋转功能开发中',
46 | image: '/images/fail.png',
47 | duration: 1000,
48 | mask: true,
49 | })
50 | },
51 | })
52 |
--------------------------------------------------------------------------------
/heartSound/pages/index/draw/draw.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "画板涂鸦"
3 | }
--------------------------------------------------------------------------------
/heartSound/pages/index/draw/draw.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/heartSound/pages/index/draw/draw.wxss:
--------------------------------------------------------------------------------
1 |
2 | page{
3 | width: 100%;
4 | height: 100%;
5 | background: #ffffff
6 | }
7 |
8 | .canvas-area{
9 | margin-top: 15%;
10 | width:750rpx;
11 | height: 80%;
12 | background: #ffffff
13 | }
14 | .myCanvas{
15 | width: 100%;
16 | height: 100%;
17 | }
18 | .canvas-tools-you{
19 | position: fixed;
20 | top: 0;
21 | height: 10%;
22 | width: 100%;
23 | display: flex;
24 | justify-content: center;
25 | align-items: center;
26 | }
27 | .canvas-tools-me{
28 | position: fixed;
29 | bottom: 0;
30 | height: 10%;
31 | width: 100%;
32 | display: flex;
33 | justify-content: center;
34 | align-items: center;
35 | }
36 | .icon-box{
37 | width: 350rpx;
38 | }
39 | .icon{
40 | height: 70rpx;
41 | width: 70rpx;
42 | margin-left: 70rpx;
43 | }
--------------------------------------------------------------------------------
/heartSound/pages/index/index.js:
--------------------------------------------------------------------------------
1 | //index.js
2 | //获取应用实例
3 | const app = getApp()
4 |
5 | Page({
6 | data: {
7 |
8 | },
9 | onShareAppMessage: function () {
10 | return {
11 | title: '心声Lite,用心说话',
12 | desc: '语音识别,语音合成,画板涂鸦,心声Lite — 致力于为听障者服务。',
13 | path: '/pages/index/index',
14 | imageUrl:'/images/xxs.png'
15 | }
16 | },
17 | //事件处理函数
18 | gotoSmallTalk: function() {
19 | wx.navigateTo({
20 | url: '/pages/index/talk/talk'
21 | })
22 | },
23 | gotoLongTalk: function () {
24 | wx.navigateTo({
25 | url: '/pages/index/longtalk/longtalk'
26 | })
27 | },
28 | gotoDraw: function () {
29 | wx.navigateTo({
30 | url: '/pages/index/draw/draw'
31 | })
32 | },
33 | onLoad(){
34 | }
35 | })
36 |
--------------------------------------------------------------------------------
/heartSound/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
--------------------------------------------------------------------------------
/heartSound/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/heartSound/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | /**index.wxss**/
2 |
3 | .box{
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | height: 50%;
8 | width: 100%;
9 | }
10 |
11 | .icon-button{
12 | height: 300rpx;
13 | width: 300rpx;
14 | }
--------------------------------------------------------------------------------
/heartSound/pages/index/longtalk/longtalk.js:
--------------------------------------------------------------------------------
1 | const app = getApp()
2 |
3 | var plugin = requirePlugin("WechatSI")
4 | let manager = plugin.getRecordRecognitionManager()
5 | const innerAudioContext = wx.createInnerAudioContext()
6 |
7 | Page({
8 | data: {
9 | recording:false,
10 | scrollTop: 10000,
11 | content:[
12 | {
13 | 'content':'可用于和别人较长时间的交谈,请对方戴上耳机交谈会更加方便,识别也更加清晰。',
14 | 'person':'me'
15 | }
16 | ],
17 | ison:false,
18 | now:'me',
19 | content_now:'',
20 | content_temp:'',
21 | addinput: '',//清楚input框的值
22 | },
23 | initRecord: function () {
24 | var that = this
25 |
26 | manager.onStart = (res) => {
27 |
28 | }
29 |
30 | manager.onRecognize = (res) => {
31 | var content_temp = that.data.content_temp
32 | if (content_temp == res.result){
33 |
34 | }else{
35 | var array = []
36 | array = that.data.content
37 | console.log(array)
38 |
39 | var a = content_temp
40 | var b = res.result
41 | var text = b.slice(a.length, b.length)
42 |
43 | var temp = {
44 | 'content': text,
45 | 'person': 'you'
46 | }
47 | array.push(temp)
48 | console.log(array)
49 | that.setData({
50 | content: array,
51 | content_temp: res.result,
52 | scrollTop: that.data.scrollTop + 100
53 | })
54 | }
55 | }
56 |
57 | // 识别结束事件
58 | manager.onStop = (res) => {
59 |
60 | }
61 | },
62 |
63 | onLoad: function (options) {
64 | this.initRecord()
65 | app.getRecordAuth()
66 | },
67 |
68 | touchdown_plugin: function() {
69 | var that = this
70 | if(that.data.recording){
71 | manager.stop()
72 |
73 | wx.showToast({
74 | title: '停止识别',
75 | image: '/images/stop.png',
76 | duration: 800
77 | })
78 |
79 | that.setData({
80 | recording: false
81 | })
82 |
83 | }else{
84 | wx.stopBackgroundAudio();
85 |
86 | manager.start({
87 | lang: "zh_CN"
88 | })
89 | wx.showToast({
90 | title: '开始识别',
91 | image:'/images/begin.png',
92 | duration:800
93 | })
94 | that.setData({
95 | recording: true
96 | })
97 | }
98 | },
99 |
100 | listenInput: function (e) {
101 | var content = e.detail.value
102 | this.setData({
103 | content_now: content
104 | })
105 | console.log(e.detail.value)
106 | },
107 |
108 | // 清空输入框的内容
109 | dele: function (e) {
110 | this.setData({
111 | content_down: '',
112 | input: ''
113 | })
114 | },
115 |
116 | // 文字转语音(语音合成)
117 | wordtospeak: function (e) {
118 | let flag = 0
119 | if (this.data.recording){
120 | manager.stop
121 | flag = 1
122 | }
123 |
124 | if (e.currentTarget.dataset.content == '') {
125 | wx.showToast({
126 | title: '请勿发空消息',
127 | image: '/images/fail.png',
128 | })
129 | } else if (/[@\/'\\"#$%&\^*]/.test(e.currentTarget.dataset.content)){
130 | wx.showToast({
131 | title:'有非法字符',
132 | image:'/images/fail.png'
133 | })
134 | }else{
135 | // 将wxml中传过来的文本内容存起来,用api传给插件
136 | var content = e.currentTarget.dataset.content
137 |
138 | var that = this
139 |
140 | plugin.textToSpeech({
141 | lang: "zh_CN",
142 | tts: true,
143 | content: content,
144 | success: function (res) {
145 | console.log(" tts", res)
146 | innerAudioContext.autoplay = true
147 | innerAudioContext.src = res.filename
148 | innerAudioContext.onPlay(() => {
149 | console.log('开始播放')
150 | })
151 |
152 | wx.showLoading({
153 | title: '正在播放',
154 | })
155 |
156 | innerAudioContext.onError((res) => {
157 | if(res){
158 | wx.hideLoading(),
159 | wx.showToast({
160 | title: '文本格式错误',
161 | image: '/images/fail.png',
162 | })
163 | }
164 | })
165 |
166 | innerAudioContext.onEnded(function () {
167 | wx.stopBackgroundAudio();
168 |
169 | manager.start({
170 | lang: "zh_CN"
171 | })
172 |
173 | setTimeout(function () {
174 | wx.hideLoading()
175 | }, 300)
176 |
177 | that.setData({
178 | content_temp: ''
179 | })
180 | })
181 | },
182 | fail: function (res) {
183 | console.log("fail tts", res)
184 |
185 | }
186 | })
187 |
188 | var array = []
189 | array = this.data.content
190 | var temp = {
191 | 'content': e.currentTarget.dataset.content,
192 | 'person' : 'me'
193 | }
194 | array.push(temp)
195 | console.log(array)
196 | that.setData({
197 | content:array,
198 | scrollTop:that.data.scrollTop + 100
199 | })
200 | }
201 | },
202 |
203 | onUnload: function () {
204 | manager.stop()
205 | },
206 | })
--------------------------------------------------------------------------------
/heartSound/pages/index/longtalk/longtalk.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "坐下长谈",
3 | "usingComponents": {
4 | "waiting-icon": "/components/waiting-icon/index"
5 | }
6 | }
--------------------------------------------------------------------------------
/heartSound/pages/index/longtalk/longtalk.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 开始识别
7 |
8 |
9 | 正在识别
10 |
11 |
12 |
13 |
33 |
34 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/heartSound/pages/index/longtalk/longtalk.wxss:
--------------------------------------------------------------------------------
1 | /* pages/commom/personChat/personChat.wxss */
2 | .top-bar{
3 | height: 100rpx;
4 | background: #515151;
5 | width: 100%;
6 | display: flex;
7 | align-items: center;
8 | justify-content: center;
9 | }
10 | .start-button{
11 | font-size: 40rpx;
12 | color: #fff;
13 | }
14 | .waiting-icon{
15 | position: relative;
16 | left: 10rpx;
17 | bottom: 10rpx;
18 | }
19 |
20 | .container{
21 | background: #ffffff;
22 | color: #fff;
23 | font-size: 55rpx;
24 | padding-bottom: 20%;
25 | }
26 | .container {
27 | height: 100%;
28 | width: 100%;
29 | flex-direction: column;
30 | }
31 | .container {
32 | display: flex;
33 | display:-webkit-flex;
34 | box-sizing: border-box;
35 | }
36 | .placeholder{
37 | color: #999;
38 | }
39 | /*聊天盒子*/
40 | .scrollwechat {
41 | flex: 1;
42 | display: flex;
43 | flex-direction: column;
44 | overflow: hidden;
45 | height: 100%;
46 | padding-top: 10rpx;
47 | }
48 | .scrollview{
49 | height: 100%;
50 |
51 | }
52 | .scrollwechat li {
53 | width: 100%;
54 | display: flex;
55 | margin-top: 20rpx;
56 | }
57 |
58 | .container .user {
59 | flex-direction: row;
60 | }
61 |
62 | .container .sys{
63 | flex-direction: row-reverse;
64 | }
65 |
66 | .input-layer{
67 | height: 10%;
68 | width: 100%;
69 | position: fixed;
70 | bottom: 0;
71 | background: blue;
72 | }
73 | .input-panel {
74 | height: 100%;
75 | padding: 0 15rpx 0 15rpx;
76 | background: #f0f0f0;
77 | box-sizing: border-box;
78 | display: flex;
79 | align-items: center;
80 | }
81 | input{
82 | color: #515151;
83 | }
84 | .send-input {
85 | font-size: 38rpx;
86 | flex: 1;
87 | height: 95rpx;
88 | background: #fff;
89 | border:#ddd 1rpx solid;
90 | border-radius: 10rpx;
91 | box-sizing: border-box;
92 | padding: 0 10rpx;
93 | }
94 | .send-btn {
95 | display: flex;
96 | justify-content: center;
97 | align-items: center;
98 | width: 120rpx;
99 | height: 80rpx;
100 | line-height: 75rpx;
101 | background-color: #474646;
102 | font-size: 32rpx;
103 | color:#fff;
104 | border-radius: 10rpx;
105 | margin-left: 15rpx;
106 | }
107 | .send-btn:active{
108 | opacity: .7;
109 | }
110 | .icon{
111 | height: 40rpx;
112 | width: 40rpx;
113 | }
114 |
115 | .me-box{
116 | margin: 20rpx;
117 | margin-left: 180rpx;
118 | }
119 | .me{
120 | padding: 20rpx;
121 | border: 5rpx solid #7aa0cb;
122 | }
123 | .you{
124 | padding: 20rpx;
125 | margin: 20rpx;
126 | margin-left: 180rpx;
127 | border: 5rpx solid #7aa0cb;
128 | }
129 |
130 |
131 | .triangle image{
132 | width: 20rpx;
133 | height: 80rpx;
134 | }
135 | .textview1 {
136 | width:70%;
137 | border-radius: 10rpx;
138 | background: #7aa0cb;
139 | padding: 20rpx;
140 | }
141 | .textview2 {
142 | width:70%;
143 | background: #f3a09e;
144 | border-radius: 10rpx;
145 | padding: 20rpx;
146 | }
147 | .link{
148 | height: 150rpx;
149 | }
150 |
--------------------------------------------------------------------------------
/heartSound/pages/index/talk/talk.js:
--------------------------------------------------------------------------------
1 | // pages/talk/talk.js
2 |
3 | // 引入插件
4 | const app = getApp()
5 |
6 | var plugin = requirePlugin("WechatSI")
7 | let manager = plugin.getRecordRecognitionManager()
8 | const innerAudioContext = wx.createInnerAudioContext()
9 |
10 | Page({
11 |
12 | /**
13 | * 页面的初始数据
14 | */
15 | data: {
16 | shownull:false,
17 | showmicro: false,
18 | input: '',
19 | content_up: '',
20 | content_down: '你好,我听力不好,你可以按住底部的按钮,对我说普通话'
21 | },
22 |
23 | initRecord: function () {
24 | var that = this
25 | manager.onStart = (res) => {
26 | that.setData({
27 | showmicro:true
28 | })
29 | }
30 |
31 | // 识别结束事件
32 | manager.onStop = (res) => {
33 | var that = this
34 | let text = res.result
35 |
36 | if (text == '') {
37 | this.setData({
38 | shownull: true
39 | })
40 | setTimeout(function () {
41 | that.setData({
42 | shownull: false
43 | })
44 | }, 500)
45 | }
46 |
47 | this.setData({
48 | content_up: text,
49 | showmicro: false
50 | })
51 | }
52 |
53 | },
54 | //监听字的输入,实时显示在屏幕,并且content_down还会用在文字转语音(语音合成)上。
55 | listenInput: function (e) {
56 | var content = e.detail.value
57 | if (content == '') {
58 | content = '你好,我听力不好,你可以按住底部的按钮,对我说普通话'
59 | }
60 | this.setData({
61 | content_down: content
62 | })
63 | },
64 |
65 | // 清空输入框的内容
66 | dele: function (e) {
67 | this.setData({
68 | content_down: '',
69 | input: ''
70 | })
71 | },
72 |
73 | // 插件使用重要步骤!!
74 |
75 | //手指按下
76 | touchdown_plugin: function (e) {
77 | wx.stopBackgroundAudio();
78 |
79 | manager.start({
80 | lang: "zh_CN"
81 | })
82 | },
83 | //手指松开
84 | touchup_plugin: function () {
85 |
86 | manager.stop();
87 | },
88 |
89 | // 文字转语音(语音合成)
90 | wordtospeak: function (e) {
91 | var that = this
92 |
93 | var content = e.currentTarget.dataset.content
94 |
95 | if (content==''){
96 | wx.showToast({
97 | title: '请输入文字',
98 | image: '/images/fail.png',
99 | })
100 | }
101 |
102 | plugin.textToSpeech({
103 | lang: "zh_CN",
104 | tts: true,
105 | content: content,
106 | success: function (res) {
107 | innerAudioContext.autoplay = true
108 | innerAudioContext.src = res.filename
109 | innerAudioContext.onPlay(() => {
110 | console.log('开始播放')
111 | })
112 |
113 | wx.showLoading({
114 | title: '正在播放',
115 | })
116 |
117 | innerAudioContext.onError((res) => {
118 | if (res) {
119 | wx.hideLoading(),
120 | wx.showToast({
121 | title: '文本格式错误',
122 | image: '/images/fail.png',
123 | })
124 | }
125 | })
126 |
127 | innerAudioContext.onEnded(function(){
128 | wx.hideLoading()
129 | })
130 | console.log("succ tts", res.filename)
131 | },
132 | fail: function (res) {
133 | console.log("fail tts", res)
134 | },
135 | })
136 | },
137 |
138 |
139 | /**
140 | * 用户点击右上角分享
141 | */
142 | onShareAppMessage: function () {
143 | return {
144 | title: '心声Lite,让爱发声',
145 | path: '/pages/index/talk/talk',
146 | imageUrl: '/images/xxs.png'
147 | }
148 | },
149 | onLoad: function (){
150 | this.initRecord()
151 | app.getRecordAuth()
152 | },
153 | })
--------------------------------------------------------------------------------
/heartSound/pages/index/talk/talk.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "小聊几句",
3 | "usingComponents": {
4 | "waiting-icon": "/components/waiting-icon/index"
5 | }
6 | }
--------------------------------------------------------------------------------
/heartSound/pages/index/talk/talk.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{content_up}}
9 |
10 |
11 |
12 |
13 | {{content_down}}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 | 正在识别
34 |
35 |
36 |
37 |
38 | 请说话
39 |
40 |
--------------------------------------------------------------------------------
/heartSound/pages/index/talk/talk.wxss:
--------------------------------------------------------------------------------
1 | /* pages/talk/talk.wxss */
2 |
3 | .button-layer{
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | padding-top: 15rpx;
8 | height: 20%;
9 | width: 100%;
10 | background: #f0f0f0;
11 | }
12 | .showme-layer{
13 | height: 35%;
14 | width: 100%;
15 | background: #ffffff;
16 | }
17 | .content-box-showme{
18 | height: 100%;
19 | line-height: 1.5;
20 | padding: 20rpx 20rpx 0 30rpx;
21 | box-sizing: border-box;
22 | border-bottom: 1px solid #e5e5e5;
23 | }
24 | .content-box-showyou{
25 | height: 100%;
26 | line-height: 1.5;
27 | padding: 20rpx 20rpx 0 30rpx;
28 | box-sizing: border-box;
29 | border-bottom: 1px solid #e5e5e5;
30 | transform: scaleY(-1);
31 | }
32 | .showyou-layer{
33 | height: 35%;
34 | width: 100%;
35 | background: #ffffff;
36 | transform: scaleX(-1);
37 | }
38 | .input-layer{
39 | height: 10%;
40 | width: 100%;
41 | position: fixed;
42 | bottom: 0;
43 | background: blue;
44 | }
45 |
46 | .speak-button{
47 | height: 220rpx;
48 | width: 220rpx;
49 | margin-bottom: 20rpx;
50 | }
51 | .speak-button:active{
52 | opacity: .7;
53 | }
54 | .tips{
55 | position: absolute;
56 | width: 400rpx;
57 | height: 200rpx;
58 | left: 175rpx;
59 | top: 320rpx;
60 | }
61 | .input-panel {
62 | height: 100%;
63 | padding: 0 15rpx 0 15rpx;
64 | background: #f0f0f0;
65 | box-sizing: border-box;
66 | display: flex;
67 | align-items: center;
68 | }
69 | .send-input {
70 | font-size: 38rpx;
71 | flex: 1;
72 | height: 95rpx;
73 | background: #fff;
74 | border:#ddd 1rpx solid;
75 | border-radius: 10rpx;
76 | box-sizing: border-box;
77 | padding: 0 10rpx;
78 | }
79 | .send-btn {
80 | display: flex;
81 | justify-content: center;
82 | align-items: center;
83 | width: 120rpx;
84 | height: 80rpx;
85 | line-height: 75rpx;
86 | background-color: #474646;
87 | font-size: 32rpx;
88 | color:#fff;
89 | border-radius: 10rpx;
90 | margin-left: 15rpx;
91 | }
92 | .send-btn:active{
93 | opacity: .7;
94 | }
95 | .icon{
96 | height: 40rpx;
97 | width: 40rpx;
98 | }
99 |
100 | .toast{
101 | background: rgba(0,0,0, 0.7);
102 | color: #fff;
103 | display: flex;
104 | align-items: center;
105 | height: 130rpx;
106 | width: 300rpx;
107 | padding: 20rpx;
108 | border-radius: 20rpx;
109 | position: fixed;
110 | top: 340rpx;
111 | left: 225rpx;
112 | }
113 | .toast text{
114 | font-size: 36rpx;
115 | }
116 | .waiting-icon{
117 | position: relative;
118 | left: 10rpx;
119 | bottom: 15rpx;
120 | }
121 | .microphone{
122 | height: 80rpx;
123 | width: 80rpx;
124 | }
125 | .warning{
126 | height: 80rpx;
127 | width: 80rpx;
128 | margin-left: 20rpx;
129 | }
130 | .warning-text{
131 | margin-left: 20rpx;
132 | }
--------------------------------------------------------------------------------
/heartSound/pages/user/about/about.js:
--------------------------------------------------------------------------------
1 | //about.js
2 | //获取应用实例
3 | var app = getApp();
4 | Page({
5 | data: {
6 |
7 | },
8 | onLoad: function () {
9 |
10 | },
11 | });
--------------------------------------------------------------------------------
/heartSound/pages/user/about/about.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "关于",
3 | "enablePullDownRefresh": false
4 | }
--------------------------------------------------------------------------------
/heartSound/pages/user/about/about.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 心声Lite
7 | 公益项目
8 |
9 |
10 |
11 | 简介
12 |
13 |
14 |
15 |
16 | 简介
17 | 我们的身边有很多听障者,他们或许来到这个世界就未曾听到过任何欢声笑语。或者被忽然降临的疾病夺去了本该属于他们的平凡人的生活。
18 | 心声Lite是一款帮助听障者与普通人交流的微信小程序,希望能用微薄的力量,给予他们一点便利。
19 | 语音识别,使得街头路人可以告诉他们车站在何方
20 | 语音合成,可以帮他们向爸爸妈妈说一声“爸妈,让你们受累了”。
21 | 心声Lite,只为让世界多一点温暖
22 |
23 |
24 | 心声Lite诚挚的欢迎各大公众号关联小程序,并期待与您的合作。AppID:wxfb65ccf6436cd4f6
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/heartSound/pages/user/about/about.wxss:
--------------------------------------------------------------------------------
1 | /**about.wxss**/
2 | /* pages/user/feedback/feedback.wxss */
3 |
4 | .version{
5 | height: 100rpx;
6 | background: #fff;
7 | display: flex;
8 | align-items: center;
9 | padding: 0 45rpx;
10 | box-sizing: border-box;
11 | font-size: 13pt;
12 | color: #666;
13 | border-bottom: 1px #e5e5e5 solid;
14 | }
15 | .version-title{
16 | flex: 1;
17 | display: flex;
18 | align-items: center;
19 | }
20 | .title-name{
21 | padding-right: 10rpx;
22 | }
23 | .version-text{
24 | font-size: 10pt;
25 | line-height: 100%;
26 | color: #7acfa6;
27 | border: 1px solid #7acfa6;
28 | padding: 5rpx 10rpx;
29 | border-radius: 5rpx;
30 | margin-left: 10rpx;
31 | text-align: center;
32 | }
33 | .version-log-link{
34 | position: relative;
35 | font-size: 12pt;
36 | color: #7acfa6;
37 | }
38 | .version-log-link:active{
39 | opacity: .8;
40 | }
41 | .update-log::after{
42 | content: '';
43 | position: absolute;
44 | right: -3px;
45 | top: -1px;
46 | width: 5px;
47 | height: 5px;
48 | border-radius: 50%;
49 | background: #e55c5c;
50 | }
51 |
52 | .container{
53 | background: #f4f4f4;
54 | padding: 0;
55 | font-size: 11pt;
56 | }
57 | .header{
58 | position: relative;
59 | width: 100%;
60 | height: 400rpx;
61 | text-align: center;
62 | box-sizing: border-box;
63 | overflow: hidden;
64 | display: flex;
65 | align-items: center;
66 | justify-content: center;
67 | }
68 | .header .title{
69 | position: relative;
70 | width: 600rpx;
71 | height: 200rpx;
72 | z-index: 3;
73 | opacity: .95;
74 | }
75 | .black-cover{
76 | position: absolute;
77 | z-index: 2;
78 | top:0;
79 | left: 0;
80 | width: 100%;
81 | height: 100%;
82 | background: #888;
83 | opacity: .18;
84 | }
85 | .logo{
86 | position: absolute;
87 | top:0;
88 | left: 0;
89 | z-index: 1;
90 | width: 100%;
91 | height: 750rpx;
92 | border-radius: 10rpx;
93 | margin-top: -175rpx;
94 | filter: blur(15px);
95 | }
96 | .content{
97 | height: 80%;
98 | flex: 1;
99 | }
100 | .version{
101 | height: 100rpx;
102 | background: #fff;
103 | display: flex;
104 | align-items: center;
105 | padding: 0 45rpx;
106 | box-sizing: border-box;
107 | font-size: 13pt;
108 | color: #666;
109 | border-bottom: 1px #e5e5e5 solid;
110 | }
111 | .version-title{
112 | flex: 1;
113 | display: flex;
114 | align-items: center;
115 | }
116 | .title-name{
117 | padding-right: 10rpx;
118 | }
119 | .version-text{
120 | font-size: 10pt;
121 | line-height: 100%;
122 | color: #7acfa6;
123 | border: 1px solid #7acfa6;
124 | padding: 5rpx 10rpx;
125 | border-radius: 5rpx;
126 | margin-left: 10rpx;
127 | text-align: center;
128 | }
129 | .version-log-link{
130 | position: relative;
131 | font-size: 12pt;
132 | color: #7acfa6;
133 | }
134 | .version-log-link:active{
135 | opacity: .8;
136 | }
137 | .update-log::after{
138 | content: '';
139 | position: absolute;
140 | right: -3px;
141 | top: -1px;
142 | width: 5px;
143 | height: 5px;
144 | border-radius: 50%;
145 | background: #e55c5c;
146 | }
147 | .log-list{
148 | display: flex;
149 | flex-direction: column;
150 | align-items: stretch;
151 | }
152 | .describe{
153 | width: 100%;
154 | box-sizing: border-box;
155 | padding: 20rpx 45rpx 30rpx;
156 | display: flex;
157 | flex-flow: column wrap;
158 | color: #545454;
159 | line-height: 175%;
160 | background: #fff;
161 | margin-top: 15rpx;
162 | border-top: 1px #e5e5e5 solid;
163 | border-bottom: 1px #e5e5e5 solid;
164 | }
165 | .desc-title{
166 | display: flex;
167 | font-size: 13pt;
168 | line-height: 200%;
169 | margin-bottom: 15rpx;
170 | }
171 | .desc-v{
172 | flex: 1;
173 | }
174 | .desc-time{
175 | font-size: 11pt;
176 | color: #888;
177 | }
178 | .desc-list{
179 | display: flex;
180 | flex-direction: column;
181 | border-left: 8rpx solid #ddd;
182 | padding-left: 15rpx;
183 | color: #777;
184 | margin-bottom: 15rpx;
185 | font-size: 30rpx;
186 | }
187 |
188 | .desc-content{
189 | padding-bottom: 15rpx;
190 | }
191 | .footer{
192 | display: flex;
193 | flex-direction: column;
194 | font-size: 9pt;
195 | line-height: 150%;
196 | text-align: center;
197 | padding: 100rpx 0 15rpx;
198 | color: #c2c2c2;
199 | }
200 | .footer-lanshan{
201 | font-size: 10pt;
202 | height: 10pt;
203 | line-height: 10pt;
204 | display: flex;
205 | align-items: center;
206 | justify-content: center;
207 | margin-bottom: 8rpx;
208 | }
209 | .footer-lanshan image{
210 | width: 10pt;
211 | height: 10pt;
212 | margin-right: 5rpx;
213 | }
214 |
--------------------------------------------------------------------------------
/heartSound/pages/user/feedback/feedback.js:
--------------------------------------------------------------------------------
1 | // pages/user/feedback/feedback.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/heartSound/pages/user/feedback/feedback.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/heartSound/pages/user/feedback/feedback.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 反馈邮箱
5 |
6 |
7 | 535073920@qq.com
8 | 简介
9 |
10 |
--------------------------------------------------------------------------------
/heartSound/pages/user/feedback/feedback.wxss:
--------------------------------------------------------------------------------
1 | /* pages/user/feedback/feedback.wxss */
2 | .version{
3 | height: 100rpx;
4 | background: #fff;
5 | display: flex;
6 | align-items: center;
7 | padding: 0 45rpx;
8 | box-sizing: border-box;
9 | font-size: 13pt;
10 | color: #666;
11 | border-bottom: 1px #e5e5e5 solid;
12 | }
13 | .version-title{
14 | flex: 1;
15 | display: flex;
16 | align-items: center;
17 | }
18 | .title-name{
19 | padding-right: 10rpx;
20 | }
21 | .version-text{
22 | font-size: 10pt;
23 | line-height: 100%;
24 | color: #7acfa6;
25 | border: 1px solid #7acfa6;
26 | padding: 5rpx 10rpx;
27 | border-radius: 5rpx;
28 | margin-left: 10rpx;
29 | text-align: center;
30 | }
31 | .version-log-link{
32 | position: relative;
33 | font-size: 12pt;
34 | color: #7acfa6;
35 | }
36 | .version-log-link:active{
37 | opacity: .8;
38 | }
39 | .update-log::after{
40 | content: '';
41 | position: absolute;
42 | right: -3px;
43 | top: -1px;
44 | width: 5px;
45 | height: 5px;
46 | border-radius: 50%;
47 | background: #e55c5c;
48 | }
--------------------------------------------------------------------------------
/heartSound/pages/user/user.js:
--------------------------------------------------------------------------------
1 | //index.js
2 | //获取应用实例
3 | const app = getApp()
4 |
5 | Page({
6 | data: {
7 | motto: 'Hello World',
8 | userInfo: {},
9 | hasUserInfo: false,
10 | canIUse: wx.canIUse('button.open-type.getUserInfo')
11 | },
12 | //事件处理函数
13 | gotoAbout: function () {
14 | wx.navigateTo({
15 | url: '/pages/user/about/about'
16 | })
17 | },
18 | gotoFeedback: function () {
19 | wx.navigateTo({
20 | url: '/pages/user/feedback/feedback'
21 | })
22 | },
23 | gotoShare: function () {
24 | this.onShareAppMessage()
25 | },
26 | onLoad: function () {
27 | if (app.globalData.userInfo) {
28 | this.setData({
29 | userInfo: app.globalData.userInfo,
30 | hasUserInfo: true
31 | })
32 | } else if (this.data.canIUse) {
33 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
34 | // 所以此处加入 callback 以防止这种情况
35 | app.userInfoReadyCallback = res => {
36 | this.setData({
37 | userInfo: res.userInfo,
38 | hasUserInfo: true
39 | })
40 | }
41 | } else {
42 | // 在没有 open-type=getUserInfo 版本的兼容处理
43 | wx.getUserInfo({
44 | success: res => {
45 | app.globalData.userInfo = res.userInfo
46 | this.setData({
47 | userInfo: res.userInfo,
48 | hasUserInfo: true
49 | })
50 | }
51 | })
52 | }
53 | },
54 | getUserInfo: function (e) {
55 | console.log(e)
56 | app.globalData.userInfo = e.detail.userInfo
57 | this.setData({
58 | userInfo: e.detail.userInfo,
59 | hasUserInfo: true
60 | })
61 | },
62 | onShareAppMessage: function () {
63 | return {
64 | title: '心声Lite,用心说话',
65 | desc: '语音识别,语音合成,画板涂鸦,心声Lite — 致力于为听障者服务。',
66 | path: '/pages/index/index',
67 | imageUrl: '/images/xxs.png'
68 | }
69 | },
70 | })
71 |
--------------------------------------------------------------------------------
/heartSound/pages/user/user.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/heartSound/pages/user/user.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{userInfo.nickName}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 反馈
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 关于
26 |
27 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/heartSound/pages/user/user.wxss:
--------------------------------------------------------------------------------
1 |
2 | .user-wechat-info {
3 | display: flex;
4 | flex-wrap: wrap;
5 | justify-content: center;
6 | width: 95%;
7 | margin: 25rpx auto;
8 | height: 280rpx;
9 | border-radius: 30rpx;
10 | box-shadow: 0px 2px 2px 1px #cccccc;
11 | background-color: #f3a09e;
12 | overflow: hidden;
13 | }
14 | .avatar image {
15 | width: 150rpx;
16 | height: 150rpx;
17 | border-radius: 50%;
18 | margin-top: 30rpx;
19 | display: block;
20 | }
21 | .nick-name {
22 | display: flex;
23 | justify-content: center;
24 | color: #ffffff;
25 | font-size: 34rpx;
26 | position: absolute;
27 | top: 225rpx;
28 | }
29 | .nav-item-box{
30 | display: flex;
31 | flex-wrap: wrap;
32 | }
33 | .nav-item{
34 | margin-top: 60rpx;
35 | display: block;
36 | height: 125rpx;
37 | width: 125rpx;
38 | }
39 | .append{
40 | display: flex;
41 | justify-content: center;
42 | }
43 |
44 | /**more.wxss**/
45 | .container{
46 | background-color: #f6f6f6;
47 | }
48 | .user-info, .more-btn {
49 | display: flex;
50 | background-color: #fff;
51 | min-height: 85rpx;
52 | border-top: 1px solid #e5e5e5;
53 | border-bottom: 1px solid #e5e5e5;
54 | }
55 | /**user-info**/
56 | .user-info-box{
57 | margin-bottom: 40rpx;
58 | }
59 | .user-info {
60 | flex-direction: column;
61 | margin: 30rpx 0 -1px;
62 | padding: 25rpx 30rpx 20rpx;
63 | }
64 | .info-hd {
65 | display: flex;
66 | align-items: center;
67 | }
68 | .bind-btn {
69 | color: #aaa;
70 | }
71 | .user-avatar {
72 | width: 120rpx;
73 | height: 120rpx;
74 | border-radius: 5px;
75 | }
76 | .user-title {
77 | flex: 1;
78 | display: flex;
79 | flex-direction: column;
80 | padding-left: 25rpx;
81 | }
82 | .time-box {
83 | display: flex;
84 | flex-direction: column;
85 | align-items: center;
86 | font-size: 10pt;
87 | line-height: 140%;
88 | color: #aaa;
89 | }
90 | .user-name {
91 | font-size: 16pt;
92 | line-height: 160%;
93 | letter-spacing: 1px;
94 | }
95 | .user-id {
96 | font-size: 11pt;
97 | color: #8b8b8b;
98 | }
99 | .info-bd {
100 | display: flex;
101 | justify-content: space-between;
102 | padding: 25rpx 15rpx 0 5rpx;
103 | font-size: 11pt;
104 | line-height: 150%;
105 | color: #8b8b8b;
106 | }
107 | .info-bd-left, .info-bd-right {
108 | display: flex;
109 | flex-direction: column;
110 | }
111 | .info-bd-left{
112 | flex-shrink: 0;
113 | padding-right: 30rpx;
114 | }
115 | /**more-list**/
116 | .more-list {
117 | flex: 1;
118 | display: flex;
119 | flex-direction: column;
120 | }
121 | .more-btn {
122 | align-items: center;
123 | font-size: 13pt;
124 | padding: 0 30rpx;
125 | margin-top: 20rpx;
126 | }
127 | .issue-link, .about-link {
128 | margin-bottom: 20rpx;
129 | }
130 | .btn-icon {
131 | width: 55rpx;
132 | height: 55rpx;
133 | margin-right: 15rpx;
134 | }
135 | .btn-text {
136 | flex: 1;
137 | font-size: 36rpx;
138 | color: #515151;
139 | }
140 | .btn-open {
141 | display: flex;
142 | align-items: center;
143 | justify-content: flex-end;
144 | margin-left: 10rpx;
145 | }
146 | .btn-enter {
147 | width: 18rpx;
148 | height: 27rpx;
149 | }
150 | .login-btn {
151 | font-size: 13pt;
152 | line-height: 85rpx;
153 | height: 85rpx;
154 | background: #7aa0cb;
155 | color: #fff;
156 | text-align: center;
157 | border-radius: 5px;
158 | margin: 40rpx 3%;
159 | }
--------------------------------------------------------------------------------
/heartSound/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件。",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": true,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true
12 | },
13 | "compileType": "miniprogram",
14 | "libVersion": "2.2.2",
15 | "appid": "wxfb65ccf6436cd4f6",
16 | "projectname": "heartSound%20latest",
17 | "isGameTourist": false,
18 | "condition": {
19 | "search": {
20 | "current": -1,
21 | "list": []
22 | },
23 | "conversation": {
24 | "current": -1,
25 | "list": []
26 | },
27 | "game": {
28 | "currentL": -1,
29 | "list": []
30 | },
31 | "miniprogram": {
32 | "current": -1,
33 | "list": []
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/heartSound/utils/util.js:
--------------------------------------------------------------------------------
1 | const formatTime = date => {
2 | const year = date.getFullYear()
3 | const month = date.getMonth() + 1
4 | const day = date.getDate()
5 | const hour = date.getHours()
6 | const minute = date.getMinutes()
7 | const second = date.getSeconds()
8 |
9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
10 | }
11 |
12 | const formatNumber = n => {
13 | n = n.toString()
14 | return n[1] ? n : '0' + n
15 | }
16 |
17 | module.exports = {
18 | formatTime: formatTime
19 | }
20 |
--------------------------------------------------------------------------------
/项目截图/about.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/about.jpg
--------------------------------------------------------------------------------
/项目截图/code.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/code.jpg
--------------------------------------------------------------------------------
/项目截图/draw.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/draw.jpg
--------------------------------------------------------------------------------
/项目截图/index.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/index.jpg
--------------------------------------------------------------------------------
/项目截图/letdraw.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/letdraw.jpg
--------------------------------------------------------------------------------
/项目截图/longtalk.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/longtalk.jpg
--------------------------------------------------------------------------------
/项目截图/talk.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/talk.jpg
--------------------------------------------------------------------------------
/项目截图/user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonLam0990/HeartSound/2dd0cbcd1772c929088ca565cff9d04065cb3a4c/项目截图/user.jpg
--------------------------------------------------------------------------------