Commit 906191f76e79e942ac6ebd27dcb32d247588d059

Authored by xwenliang
1 parent fbe86a2d

feat: add entry

README.md
1 # 微信小程序 - 语音助手 1 # 微信小程序 - 语音助手
2 2
3 -## todo 3 +### todo
4 4
5 -1. 历史记录  
6 \ No newline at end of file 5 \ No newline at end of file
  6 +- [x] 内容安全问题处理
  7 +
  8 +- [x] 下载音频需求
  9 + - 无直接下载接口,可通过 webview 间接实现
  10 + - 个人类小程序不支持 web-view
  11 + - wx.shareFileMessage 可以直接分享文件
1 //app.js 1 //app.js
2 App({ 2 App({
3 - onLaunch: function() { 3 + onLaunch () {
4 4
5 }, 5 },
6 - getUserInfo: function(cb) {  
7 - var that = this  
8 - if (this.globalData.userInfo) {  
9 - typeof cb == "function" && cb(this.globalData.userInfo)  
10 - } else {  
11 - //调用登录接口  
12 - wx.login({  
13 - success: function() {  
14 - wx.getUserInfo({  
15 - success: function(res) {  
16 - that.globalData.userInfo = res.userInfo  
17 - typeof cb == "function" && cb(that.globalData.userInfo)  
18 - }  
19 - }) 6 + globalData: {
  7 + getTypeList(){
  8 + return [
  9 + {
  10 + desc: '男声一',
  11 + createUrl(text){
  12 + return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=1`
  13 + }
  14 + },
  15 + {
  16 + desc: '男声二',
  17 + createUrl(text){
  18 + return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=4`
  19 + }
  20 + },
  21 + {
  22 + desc: '女声一',
  23 + createUrl(text){
  24 + return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=2`
  25 + }
  26 + },
  27 + {
  28 + desc: '女声二',
  29 + createUrl(text){
  30 + return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=3`
  31 + }
  32 + },
  33 + {
  34 + desc: '女声三',
  35 + createUrl(text){
  36 + return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=5`
  37 + }
  38 + },
  39 + {
  40 + desc: '女声四',
  41 + createUrl(text){
  42 + return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=6`
  43 + }
  44 + },
  45 + {
  46 + desc: '女声五',
  47 + createUrl(text){
  48 + return `https://tts.youdao.com/fanyivoice?word=${text}&le=zh&keyfrom=speaker-target`
  49 + }
20 } 50 }
21 - }) 51 + ];
  52 + },
  53 + getSelectedTypeIndex(){
  54 + const storageKey = 'audioTypeselectedIndex';
  55 + return wx.getStorageSync(storageKey);
  56 + },
  57 + setSelectedTypeIndex(index){
  58 + const storageKey = 'audioTypeselectedIndex';
  59 + wx.setStorageSync(storageKey, index);
  60 + return index;
  61 + },
  62 + getAudioList(){
  63 + const storageKey = 'audioList';
  64 + return wx.getStorageSync(storageKey) || [];
  65 + },
  66 + /**
  67 + * @param {(add|delete)} action - 增或删
  68 + * @param {object|number} [param] - 增加时是 audio 描述,删除时是索引
  69 + */
  70 + setAudioList(action, param){
  71 + const storageKey = 'audioList';
  72 + const list = this.getAudioList() || [];
  73 + if(action === 'add' && param.constructor === Object){
  74 + list.push(param);
  75 + wx.setStorageSync(storageKey, list);
  76 + }
  77 + if(action === 'delete' && String(param)){
  78 + list.splice(param, 1);
  79 + wx.setStorageSync(storageKey, list);
  80 + }
  81 + return list;
22 } 82 }
23 - },  
24 - globalData: {  
25 - userInfo: null  
26 } 83 }
27 }); 84 });
pages/index/index.js
1 //index.js 1 //index.js
2 //获取应用实例 2 //获取应用实例
3 const app = getApp(); 3 const app = getApp();
4 -const storageKey = 'audioTypeselectedIndex';  
5 -const selectedIndex = wx.getStorageSync(storageKey);  
6 -const type = [  
7 - {  
8 - desc: '男声一',  
9 - createUrl(text){  
10 - return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=1`  
11 - }  
12 - },  
13 - {  
14 - desc: '男声二',  
15 - createUrl(text){  
16 - return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=4`  
17 - }  
18 - },  
19 - {  
20 - desc: '女声一',  
21 - createUrl(text){  
22 - return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=2`  
23 - }  
24 - },  
25 - {  
26 - desc: '女声二',  
27 - createUrl(text){  
28 - return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=3`  
29 - }  
30 - },  
31 - {  
32 - desc: '女声三',  
33 - createUrl(text){  
34 - return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=5`  
35 - }  
36 - },  
37 - {  
38 - desc: '女声四',  
39 - createUrl(text){  
40 - return `https://fanyi.sogou.com/reventondc/synthesis?text=${text}&speed=1&lang=zh-CHS&from=translateweb&speaker=6`  
41 - }  
42 - },  
43 - {  
44 - desc: '女声五',  
45 - createUrl(text){  
46 - return `https://tts.youdao.com/fanyivoice?word=${text}&le=zh&keyfrom=speaker-target`  
47 - }  
48 - }  
49 -]; 4 +const selectedIndex = app.globalData.getSelectedTypeIndex();
  5 +const type = app.globalData.getTypeList();
50 6
51 let audio = null; 7 let audio = null;
52 8
@@ -65,10 +21,34 @@ Page({ @@ -65,10 +21,34 @@ Page({
65 }, 21 },
66 play(){ 22 play(){
67 const text = this.data.text || this.data.placeholder; 23 const text = this.data.text || this.data.placeholder;
  24 + const url = this.data.type[this.data.selectedIndex].createUrl(text);
68 this.resetAudio(); 25 this.resetAudio();
69 audio = wx.createInnerAudioContext({useWebAudioImplement: true}); 26 audio = wx.createInnerAudioContext({useWebAudioImplement: true});
70 audio.autoplay = true; 27 audio.autoplay = true;
71 - audio.src = this.data.type[this.data.selectedIndex].createUrl(text); 28 + // 检查是否播放过
  29 + const audioList = app.globalData.getAudioList();
  30 + const playedIndex = audioList.findIndex(v => v.url === url);
  31 + // 播放过,使用本地文件减少请求
  32 + if(playedIndex > -1){
  33 + return audio.src = audioList[playedIndex].path;
  34 + }
  35 + // 未播放过,先下载再播放
  36 + wx.downloadFile({
  37 + url,
  38 + success (res) {
  39 + audio.src = res.tempFilePath;
  40 + app.globalData.setAudioList('add', {
  41 + // 音频文本
  42 + text,
  43 + // 音频网络地址
  44 + url,
  45 + // 音频本地地址
  46 + path: res.tempFilePath,
  47 + // 音频创建时间
  48 + time: Date.now()
  49 + });
  50 + }
  51 + });
72 }, 52 },
73 clear(){ 53 clear(){
74 this.resetAudio(); 54 this.resetAudio();
@@ -89,6 +69,11 @@ Page({ @@ -89,6 +69,11 @@ Page({
89 }, () => { 69 }, () => {
90 this.play(); 70 this.play();
91 }); 71 });
92 - wx.setStorageSync(storageKey, index); 72 + app.globalData.setSelectedTypeIndex(index);
  73 + },
  74 + gotoAudioList(){
  75 + wx.navigateTo({
  76 + url: '/pages/result/result'
  77 + });
93 } 78 }
94 }); 79 });
pages/index/index.wxml
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 </view> 13 </view>
14 <view class="button-view"> 14 <view class="button-view">
15 <button bindtap="play" class="button" type="primary" size="mini"> 播放 </button> 15 <button bindtap="play" class="button" type="primary" size="mini"> 播放 </button>
  16 + <button bindtap="gotoAudioList" class="goto-audio-list" type="primary" size="mini"> 下载 </button>
16 <button bindtap="clear" class="button" type="default" size="mini"> 清空 </button> 17 <button bindtap="clear" class="button" type="default" size="mini"> 清空 </button>
17 </view> 18 </view>
18 <view class="type-view"> 19 <view class="type-view">
pages/result/result.js
@@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
2 import { convertDate } from '../../utils/util.js'; 2 import { convertDate } from '../../utils/util.js';
3 //获取应用实例 3 //获取应用实例
4 const app = getApp(); 4 const app = getApp();
5 -const audioList = app.globalData.getAudioList();  
6 const type = app.globalData.getTypeList(); 5 const type = app.globalData.getTypeList();
7 6
8 let audio = null; 7 let audio = null;
@@ -17,10 +16,12 @@ let formateDate = function (audioList) { @@ -17,10 +16,12 @@ let formateDate = function (audioList) {
17 16
18 Page({ 17 Page({
19 data: { 18 data: {
20 - audioList: formateDate(audioList) 19 + audioList: formateDate(app.globalData.getAudioList())
21 }, 20 },
22 onLoad (options) { 21 onLoad (options) {
23 - 22 + this.setData({
  23 + audioList: formateDate(app.globalData.getAudioList())
  24 + });
24 }, 25 },
25 play(e){ 26 play(e){
26 const { index } = e.target.dataset; 27 const { index } = e.target.dataset;