index.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. import {
  2. getActivityInfo,
  3. saveActivity
  4. } from '~/api/activity'
  5. /*微信录音*/
  6. let recorderManager = wx.getRecorderManager();
  7. let dsq
  8. Page({
  9. /**
  10. * 页面的初始数据
  11. */
  12. data: {
  13. // 'before录制前, process 录制中,after录制后'
  14. state: 'before',
  15. tens: 3,
  16. bits: 0,
  17. fromWidth: 100,
  18. toWidth: 100,
  19. configure: {},
  20. avatar: '',
  21. percent: 0,
  22. // 本地录音地址
  23. tempFilePath: '',
  24. // 线上录音地址
  25. audioPath: '',
  26. uploadState: false,
  27. // 此id保存模板使用
  28. id: '',
  29. greeting: [],
  30. // 是否更改过头像
  31. changeAvatarFlag: false,
  32. greetingCard: null,
  33. userAudioState: false
  34. },
  35. async onLoad(options) {
  36. let configure = await getActivityInfo(options.id)
  37. this.setData({
  38. configure,
  39. avatar: configure.photoText,
  40. toWidth: '',
  41. fromWidth: configure.fromText.length * configure.fromFontSize,
  42. toWidth: configure.toText.length * configure.toFontSize,
  43. id: options.id,
  44. greeting: configure.greeting.split('\r'),
  45. tens: configure.bgMusicLength[0],
  46. bits: configure.bgMusicLength[1]
  47. })
  48. },
  49. setInput({
  50. currentTarget
  51. }) {
  52. console.log(currentTarget.dataset.info);
  53. },
  54. async changeAvatar(e) {
  55. const {
  56. avatarUrl
  57. } = e.detail
  58. let res = await this.uploadFile(avatarUrl)
  59. this.setData({
  60. changeAvatarFlag: true,
  61. avatar: res
  62. })
  63. },
  64. play() {
  65. if (this.data.state == 'before') {
  66. this.innerAudioContext = wx.createInnerAudioContext();
  67. this.innerAudioContext.src = this.data.configure.bgMusic; // 这里可以是录音的临时路径
  68. this.innerAudioContext.play();
  69. this.innerAudioContext.onEnded((res) => {
  70. console.log('音频播放完毕');
  71. this.setData({
  72. userAudioState: false
  73. })
  74. });
  75. this.setData({
  76. state: 'process'
  77. })
  78. let countDown = Number(this.data.configure.bgMusicLength)
  79. // 倒计时
  80. this.dsq = setInterval(item => {
  81. // 倒计时结束
  82. if (countDown == 1) {
  83. this.stopRecording()
  84. }
  85. if (countDown % 10 == 0) {
  86. this.setData({
  87. tens: --this.data.tens,
  88. bits: 9
  89. })
  90. } else {
  91. this.setData({
  92. bits: --this.data.bits
  93. })
  94. }
  95. --countDown
  96. }, 1000)
  97. const options = {
  98. sampleRate: 44100, //采样率
  99. numberOfChannels: 1, //录音通道数
  100. encodeBitRate: 192000, //编码码率
  101. format: 'mp3', //音频格式,有效值aac/mp3
  102. frameSize: 50 //指定帧大小,单位 KB
  103. };
  104. //开始录音,在开始录音回调中feed音频片
  105. recorderManager.start(options);
  106. //监听录音结束事件
  107. recorderManager.onStop((res) => {
  108. console.log('录音结束', res);
  109. this.setData({
  110. tempFilePath: res.tempFilePath,
  111. });
  112. this.uploadAudio(res.tempFilePath)
  113. });
  114. } else {
  115. this.stopRecording()
  116. }
  117. },
  118. stopRecording() {
  119. clearInterval(dsq)
  120. this.innerAudioContext.stop();
  121. recorderManager.stop();
  122. this.setData({
  123. state: 'after',
  124. tens: this.data.configure.bgMusicLength[0],
  125. bits: this.data.configure.bgMusicLength[1]
  126. })
  127. },
  128. uploadAudio(recordSource) {
  129. this.setData({
  130. uploadState: true
  131. });
  132. const uploadTask = wx.uploadFile({
  133. url: 'https://reader-api.ai160.com//file/upload',
  134. filePath: recordSource,
  135. name: '朗读录音',
  136. header: {
  137. uid: wx.getStorageSync('uid')
  138. },
  139. success: (res) => {
  140. const formateRes = JSON.parse(res.data);
  141. let audioPath = formateRes.data;
  142. this.setData({
  143. audioPath
  144. })
  145. this.uploadActivity()
  146. },
  147. })
  148. uploadTask.onProgressUpdate((res) => {
  149. this.setData({
  150. percent: res.progress
  151. })
  152. })
  153. },
  154. // 上传贺卡
  155. async uploadActivity() {
  156. this.createActivityImg('upload').then(async res => {
  157. let cardUrl = await this.uploadFile(res)
  158. let data = {
  159. audioPath: this.data.audioPath,
  160. // 生成贺卡图片地址
  161. cardUrl,
  162. templateId: this.data.id
  163. }
  164. console.log(data, 'data');
  165. let greetingCard = await saveActivity(data)
  166. console.log('贺卡生成', greetingCard);
  167. this.setData({
  168. greetingCard,
  169. uploadState: false
  170. })
  171. })
  172. },
  173. playUserAudio() {
  174. if (!this.innerAudioContext) {
  175. this.innerAudioContext = wx.createInnerAudioContext();
  176. }
  177. if (this.data.userAudioState) {
  178. this.innerAudioContext.stop();
  179. this.setData({
  180. userAudioState: false
  181. })
  182. } else {
  183. this.innerAudioContext.src = this.data.tempFilePath;
  184. this.innerAudioContext.play();
  185. this.setData({
  186. userAudioState: true
  187. })
  188. }
  189. },
  190. bindKeyInput(e) {
  191. if (e.currentTarget.dataset.type == 'from') {
  192. this.setData({
  193. fromWidth: e.detail.cursor * this.data.configure.fromFontSize,
  194. 'configure.fromText': e.detail.value
  195. })
  196. } else if (e.currentTarget.dataset.type == 'to') {
  197. this.setData({
  198. toWidth: e.detail.cursor * this.data.configure.toFontSize,
  199. 'configure.toText': e.detail.value
  200. })
  201. }
  202. },
  203. // 上传图片
  204. uploadFile(filePath) {
  205. return new Promise((resolve, reject) => {
  206. wx.uploadFile({
  207. url: 'https://reader-api.ai160.com/file/upload',
  208. filePath,
  209. name: '头像',
  210. header: {
  211. uid: wx.getStorageSync('uid')
  212. },
  213. success: (res) => {
  214. const result = JSON.parse(res.data).data;
  215. resolve(result)
  216. }
  217. })
  218. })
  219. },
  220. // 生成活动图片
  221. createActivityImg(createType = 'share') {
  222. return new Promise((resolve, reject) => {
  223. let cardUrl = !this.data.greetingCard ? '' : this.data.greetingCard.cardUrl
  224. if (cardUrl) {
  225. resolve({
  226. title: '请欣赏我的课文朗读作品,点赞+评论。',
  227. path: `/pages/index/index`,
  228. imageUrl: cardUrl
  229. })
  230. }
  231. let context = wx.createSelectorQuery();
  232. context
  233. .select('#share')
  234. .fields({
  235. node: true,
  236. size: true
  237. }).exec((res) => {
  238. const canvas = res[0].node;
  239. const ctx = canvas.getContext('2d');
  240. const dpr = wx.getSystemInfoSync().pixelRatio;
  241. canvas.width = res[0].width * dpr;
  242. canvas.height = res[0].height * dpr;
  243. ctx.scale(dpr, dpr);
  244. let avatar = canvas.createImage();
  245. avatar.src = this.data.avatar
  246. avatar.onload = () => {
  247. ctx.drawImage(avatar, this.data.configure.templateBase.photoLeft / 2, this.data.configure.templateBase.photoTop / 2, this.data.configure.templateBase.photoWidth / 2, this.data.configure.templateBase.photoHeight / 2);
  248. let bgImg = canvas.createImage();
  249. bgImg.src = this.data.configure.bgImg
  250. bgImg.onload = () => {
  251. ctx.drawImage(bgImg, 0, 0, 375, 300);
  252. ctx.font = `${this.data.configure.fromFontSize/2}px PingFang`;
  253. ctx.fillText(this.data.configure.toText, this.data.configure.templateBase.toLeft / 2, this.data.configure.templateBase.toTop / 2 + this.data.configure.fromFontSize / 2)
  254. ctx.fillText(this.data.configure.fromText, this.data.configure.templateBase.fromLeft / 2, this.data.configure.templateBase.fromTop / 2 + this.data.configure.toFontSize / 2)
  255. console.log(this.data.configure.toText, this.data.configure.templateBase.toLeft / 2, this.data.configure.templateBase.toTop / 2);
  256. console.log(this.data.configure.fromText, this.data.configure.templateBase.fromLeft / 2, this.data.configure.templateBase.fromTop / 2);
  257. setTimeout(() => {
  258. wx.canvasToTempFilePath({
  259. canvas: canvas,
  260. success(res) {
  261. console.log('9');
  262. if (createType == 'share') {
  263. resolve({
  264. title: '请欣赏我的课文朗读作品,点赞+评论。',
  265. path: `/pages/index/index`,
  266. imageUrl: res.tempFilePath
  267. })
  268. } else {
  269. resolve(res.tempFilePath)
  270. }
  271. },
  272. fail(res) {
  273. reject()
  274. }
  275. }, this)
  276. }, 1000)
  277. }
  278. }
  279. })
  280. })
  281. },
  282. onShareAppMessage({
  283. from,
  284. }) {
  285. if (from == 'button') {
  286. const promise = new Promise(resolve => {
  287. this.createActivityImg().then(res => {
  288. resolve(res)
  289. })
  290. })
  291. return {
  292. title: '请欣赏我的课文朗读作品,点赞+评论。',
  293. path: `/pages/index/index?readId`,
  294. imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png',
  295. promise
  296. }
  297. } else {
  298. return {
  299. title: '课文朗读,从未如此有趣。',
  300. path: `/pages/index/index?&uid=${wx.getStorageSync('uid')}`,
  301. imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png'
  302. }
  303. }
  304. }
  305. })