麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 課堂 > 小程序 > 正文

微信小程序生成海報(bào)分享朋友圈的實(shí)現(xiàn)方法

2020-03-21 15:57:42
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

項(xiàng)目需求寫(xiě)完有一段時(shí)間了,但是還是想回過(guò)來(lái)總結(jié)一下,一是對(duì)項(xiàng)目的回顧優(yōu)化等,二是對(duì)坑的地方做個(gè)記錄,避免以后遇到類(lèi)似的問(wèn)題。

需求

利用微信強(qiáng)大的社交能力通過(guò)小程序達(dá)到裂變的目的,拉取新用戶(hù)。

生成的海報(bào)如下

微信小程序,生成海報(bào),分享朋友圈

需求分析

1、利用小程序官方提供的api可以直接分享轉(zhuǎn)發(fā)到微信群打開(kāi)小程序

2、利用小程序生成海報(bào)保存圖片到相冊(cè)分享到朋友圈,用戶(hù)長(zhǎng)按識(shí)別二維碼關(guān)注公眾號(hào)或者打開(kāi)小程序來(lái)達(dá)到裂變的目的

實(shí)現(xiàn)方案

一、分析如何實(shí)現(xiàn)

相信大家應(yīng)該都會(huì)有類(lèi)似的迷惑,就是如何按照產(chǎn)品設(shè)計(jì)的那樣繪制成海報(bào),其實(shí)當(dāng)時(shí)我也是不知道如何下手,認(rèn)真想了下得通過(guò)canvas繪制成圖片,這樣用戶(hù)保存這個(gè)圖片到相冊(cè),就可以分享到朋友圈了。但是要繪制的圖片上面不僅有文字還有數(shù)字、圖片、二維碼等且都是活的,這個(gè)要怎么動(dòng)態(tài)生成呢。認(rèn)真想了下,需要一點(diǎn)一點(diǎn)的將文字和數(shù)字,背景圖繪制到畫(huà)布上去,這樣通過(guò)api最終合成一個(gè)圖片導(dǎo)出到手機(jī)相冊(cè)中。

二、需要解決的問(wèn)題

1、二維碼的動(dòng)態(tài)獲取和繪制(包括如何生成小程序二維碼、公眾號(hào)二維碼、打開(kāi)網(wǎng)頁(yè)二維碼)

2、背景圖如何繪制,獲取圖片信息

3、將繪制完成的圖片保存到本地相冊(cè)

4、處理用戶(hù)是否取消授權(quán)保存到相冊(cè)

三、實(shí)現(xiàn)步驟

這里我具體寫(xiě)下圍繞上面所提出的問(wèn)題,描述大概實(shí)現(xiàn)的過(guò)程

①首先創(chuàng)建canvas畫(huà)布,我把畫(huà)布定位設(shè)成負(fù)的,是為了不讓它顯示在頁(yè)面上,是因?yàn)槲覈L試把canvas通過(guò)判斷條件動(dòng)態(tài)的顯示和隱藏,在繪制的時(shí)候會(huì)出現(xiàn)問(wèn)題,所以采用了這種方法,這里還有一定要設(shè)置畫(huà)布的大小。

<canvas canvas-id="myCanvas" style="width: 690px;height:1085px;position: fixed;top: -10000px;"></canvas>

②創(chuàng)建好畫(huà)布之后,先繪制背景圖,因?yàn)楸尘皥D我是放在本地,所以獲取 <canvas> 組件 canvas-id 屬性,通過(guò) createCanvasContext 創(chuàng)建canvas的繪圖上下文 CanvasContext 對(duì)象。使用 drawImage 繪制圖像到畫(huà)布,第一個(gè)參數(shù)是圖片的本地地址,后面兩個(gè)參數(shù)是圖像相對(duì)畫(huà)布左上角位置的x軸和y軸,最后兩個(gè)參數(shù)是設(shè)置圖像的寬高。 

const ctx = wx.createCanvasContext('myCanvas')

ctx.drawImage('/img/study/shareimg.png', 0, 0, 690, 1085)

③創(chuàng)建好背景圖后,在背景圖上繪制頭像,文字和數(shù)字。通過(guò) getImageInfo 獲取頭像的信息,這里需要注意下在獲取的網(wǎng)絡(luò)圖片要先配置download域名才能生效,具體在小程序后臺(tái)設(shè)置里配置。

獲取頭像地址,首先量取頭像在畫(huà)布中的大小,和x軸Y軸的坐標(biāo),這里的result[0]是我用promise封裝返回的一個(gè)圖片地址

let headImg = new Promise(function (resolve) {  wx.getImageInfo({   src: `${app.globalData.baseUrl2}${that.data.currentChildren.headImg}`,   success: function (res) {   resolve(res.path)   },   fail: function (err) {   console.log(err)   wx.showToast({    title: '網(wǎng)絡(luò)錯(cuò)誤請(qǐng)重試',    icon: 'loading'   })   }  })  })let avatarurl_width = 60, //繪制的頭像寬度 avatarurl_heigth = 60, //繪制的頭像高度 avatarurl_x = 28, //繪制的頭像在畫(huà)布上的位置 avatarurl_y = 36; //繪制的頭像在畫(huà)布上的位置 ctx.save(); // 先保存狀態(tài) 已便于畫(huà)完圓再用 ctx.beginPath(); //開(kāi)始繪制 //先畫(huà)個(gè)圓 前兩個(gè)參數(shù)確定了圓心 (x,y) 坐標(biāo) 第三個(gè)參數(shù)是圓的半徑 四參數(shù)是繪圖方向 默認(rèn)是false,即順時(shí)針 ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false); ctx.clip(); //畫(huà)了圓 再剪切 原始畫(huà)布中剪切任意形狀和尺寸。一旦剪切了某個(gè)區(qū)域,則所有之后的繪圖都會(huì)被限制在被剪切的區(qū)域內(nèi) ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推進(jìn)去圖片

這里舉個(gè)例子說(shuō)下如何繪制文字,比如我要繪制如下這個(gè)“字”,需要?jiǎng)討B(tài)獲取前面字?jǐn)?shù)的總寬度,這樣才能設(shè)置“字”的x軸坐標(biāo),這里我本來(lái)是想通過(guò) measureText 來(lái)測(cè)量字體的寬度,但是在iOS端第一次獲取的寬度值不對(duì),關(guān)于這個(gè)問(wèn)題,我還在微信開(kāi)發(fā)者社區(qū)提了 bug ,所以我想用另一個(gè)方法來(lái)實(shí)現(xiàn),就是先獲取正常情況下一個(gè)字的寬度值,然后乘以總字?jǐn)?shù)就獲得了總寬度,親試是可以的。

微信小程序,生成海報(bào),分享朋友圈

let allReading = 97 / 6 / app.globalData.ratio * wordNumber.toString().length + 325;ctx.font = 'normal normal 30px sans-serif';ctx.setFillStyle('#ffffff')ctx.fillText('字', allReading, 150);

④繪制公眾號(hào)二維碼,和獲取頭像是一樣的,也是先通過(guò)接口返回圖片網(wǎng)絡(luò)地址,然后再通過(guò) getImageInfo 獲取公眾號(hào)二維碼圖片信息

⑤如何繪制小程序碼,具體官網(wǎng)文檔也給出生成無(wú)限 小程序碼接口 ,通過(guò)生成的小程序可以打開(kāi)任意一個(gè)小程序頁(yè)面,并且二維碼永久有效,具體調(diào)用哪個(gè)小程序二維碼接口有不同的應(yīng)用場(chǎng)景,具體可以看下官方文檔怎么說(shuō)的,也就是說(shuō)前端通過(guò)傳遞參數(shù)調(diào)取后端接口返回的小程序碼,然后繪制在畫(huà)布上(和上面寫(xiě)的繪制頭像和公眾號(hào)二維碼一樣的) 
ctx.drawImage('小程序碼的本地地址', x軸, Y軸, 寬, 高)

⑥最終繪制完把canvas畫(huà)布轉(zhuǎn)成圖片并返回圖片地址

wx.canvasToTempFilePath({   canvasId: 'myCanvas',   success: function (res) {    canvasToTempFilePath = res.tempFilePath // 返回的圖片地址保存到一個(gè)全局變量里    that.setData({    showShareImg: true    })    wx.showToast({    title: '繪制成功',    })   },   fail: function () {    wx.showToast({    title: '繪制失敗',    })   },   complete: function () {    wx.hideLoading()    wx.hideToast()   }   })

⑦保存到系統(tǒng)相冊(cè);先判斷用戶(hù)是否開(kāi)啟用戶(hù)授權(quán)相冊(cè),處理不同情況下的結(jié)果。比如用戶(hù)如果按照正常邏輯授權(quán)是沒(méi)問(wèn)題的,但是有的用戶(hù)如果點(diǎn)擊了取消授權(quán)該如何處理,如果不處理會(huì)出現(xiàn)一定的問(wèn)題。所以當(dāng)用戶(hù)點(diǎn)擊取消授權(quán)之后,來(lái)個(gè)彈框提示,當(dāng)它再次點(diǎn)擊的時(shí)候,主動(dòng)跳到設(shè)置引導(dǎo)用戶(hù)去開(kāi)啟授權(quán),從而達(dá)到保存到相冊(cè)分享朋友圈的目的。

// 獲取用戶(hù)是否開(kāi)啟用戶(hù)授權(quán)相冊(cè) if (!openStatus) {  wx.openSetting({  success: (result) => {   if (result) {   if (result.authSetting["scope.writePhotosAlbum"] === true) {    openStatus = true;    wx.saveImageToPhotosAlbum({    filePath: canvasToTempFilePath,    success() {     that.setData({     showShareImg: false     })     wx.showToast({     title: '圖片保存成功,快去分享到朋友圈吧~',     icon: 'none',     duration: 2000     })    },    fail() {     wx.showToast({     title: '保存失敗',     icon: 'none'     })    }    })   }   }  },  fail: () => { },  complete: () => { }  }); } else {  wx.getSetting({  success(res) {   // 如果沒(méi)有則獲取授權(quán)   if (!res.authSetting['scope.writePhotosAlbum']) {   wx.authorize({    scope: 'scope.writePhotosAlbum',    success() {    openStatus = true    wx.saveImageToPhotosAlbum({     filePath: canvasToTempFilePath,     success() {     that.setData({      showShareImg: false     })     wx.showToast({      title: '圖片保存成功,快去分享到朋友圈吧~',      icon: 'none',      duration: 2000     })     },     fail() {     wx.showToast({      title: '保存失敗',      icon: 'none'     })     }    })    },    fail() {    // 如果用戶(hù)拒絕過(guò)或沒(méi)有授權(quán),則再次打開(kāi)授權(quán)窗口    openStatus = false    console.log('請(qǐng)?jiān)O(shè)置允許訪(fǎng)問(wèn)相冊(cè)')    wx.showToast({     title: '請(qǐng)?jiān)O(shè)置允許訪(fǎng)問(wèn)相冊(cè)',     icon: 'none'    })    }   })   } else {   // 有則直接保存   openStatus = true   wx.saveImageToPhotosAlbum({    filePath: canvasToTempFilePath,    success() {    that.setData({     showShareImg: false    })    wx.showToast({     title: '圖片保存成功,快去分享到朋友圈吧~',     icon: 'none',     duration: 2000    })    },    fail() {    wx.showToast({     title: '保存失敗',     icon: 'none'    })    }   })   }  },  fail(err) {   console.log(err)  }  }) }

總結(jié)

至此所有的步驟都已實(shí)現(xiàn),在繪制的時(shí)候會(huì)遇到一些異步請(qǐng)求后臺(tái)返回的數(shù)據(jù),所以我用promise和async和await進(jìn)行了封裝,確保導(dǎo)出的圖片信息是完整的。在繪制的過(guò)程確實(shí)遇到一些坑的地方。比如初開(kāi)始導(dǎo)出的圖片比例大小不對(duì),還有用measureText測(cè)量文字寬度不對(duì),多次繪制(可能受網(wǎng)絡(luò)原因)有時(shí)導(dǎo)出的圖片上的文字顏色會(huì)有誤差等。如果你也遇到一些比較坑的地方可以一起探討下做個(gè)記錄,下面附下完整的代碼

 

import regeneratorRuntime from '../../utils/runtime.js' // 引入模塊const app = getApp(), api = require('../../service/http.js');var ctx = null, // 創(chuàng)建canvas對(duì)象 canvasToTempFilePath = null, // 保存最終生成的導(dǎo)出的圖片地址 openStatus = true; // 聲明一個(gè)全局變量判斷是否授權(quán)保存到相冊(cè)// 獲取微信公眾號(hào)二維碼 getCode: function () { return new Promise(function (resolve, reject) {  api.fetch('/wechat/open/getQRCodeNormal', 'GET').then(res => {  console.log(res, '獲取微信公眾號(hào)二維碼')  if (res.code == 200) {   console.log(res.content, 'codeUrl')   resolve(res.content)  }  }).catch(err => {  console.log(err)  }) }) }, // 生成海報(bào) async createCanvasImage() { let that = this; // 點(diǎn)擊生成海報(bào)數(shù)據(jù)埋點(diǎn) that.setData({  generateId: '點(diǎn)擊生成海報(bào)' }) if (!ctx) {  let codeUrl = await that.getCode()  wx.showLoading({  title: '繪制中...'  })  let code = new Promise(function (resolve) {  wx.getImageInfo({   src: codeUrl,   success: function (res) {   resolve(res.path)   },   fail: function (err) {   console.log(err)   wx.showToast({    title: '網(wǎng)絡(luò)錯(cuò)誤請(qǐng)重試',    icon: 'loading'   })   }  })  })  let headImg = new Promise(function (resolve) {  wx.getImageInfo({   src: `${app.globalData.baseUrl2}${that.data.currentChildren.headImg}`,   success: function (res) {   resolve(res.path)   },   fail: function (err) {   console.log(err)   wx.showToast({    title: '網(wǎng)絡(luò)錯(cuò)誤請(qǐng)重試',    icon: 'loading'   })   }  })  })  Promise.all([headImg, code]).then(function (result) {  const ctx = wx.createCanvasContext('myCanvas')  console.log(ctx, app.globalData.ratio, 'ctx')  let canvasWidthPx = 690 * app.globalData.ratio,   canvasHeightPx = 1085 * app.globalData.ratio,   avatarurl_width = 60, //繪制的頭像寬度   avatarurl_heigth = 60, //繪制的頭像高度   avatarurl_x = 28, //繪制的頭像在畫(huà)布上的位置   avatarurl_y = 36, //繪制的頭像在畫(huà)布上的位置   codeurl_width = 80, //繪制的二維碼寬度   codeurl_heigth = 80, //繪制的二維碼高度   codeurl_x = 588, //繪制的二維碼在畫(huà)布上的位置   codeurl_y = 984, //繪制的二維碼在畫(huà)布上的位置   wordNumber = that.data.wordNumber, // 獲取總閱讀字?jǐn)?shù)   // nameWidth = ctx.measureText(that.data.wordNumber).width, // 獲取總閱讀字?jǐn)?shù)的寬度   // allReading = ((nameWidth + 375) - 325) * 2 + 380;   // allReading = nameWidth / app.globalData.ratio + 325;   allReading = 97 / 6 / app.globalData.ratio * wordNumber.toString().length + 325;  console.log(wordNumber, wordNumber.toString().length, allReading, '獲取總閱讀字?jǐn)?shù)的寬度')  ctx.drawImage('/img/study/shareimg.png', 0, 0, 690, 1085)  ctx.save(); // 先保存狀態(tài) 已便于畫(huà)完圓再用  ctx.beginPath(); //開(kāi)始繪制  //先畫(huà)個(gè)圓 前兩個(gè)參數(shù)確定了圓心 (x,y) 坐標(biāo) 第三個(gè)參數(shù)是圓的半徑 四參數(shù)是繪圖方向 默認(rèn)是false,即順時(shí)針  ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);  ctx.clip(); //畫(huà)了圓 再剪切 原始畫(huà)布中剪切任意形狀和尺寸。一旦剪切了某個(gè)區(qū)域,則所有之后的繪圖都會(huì)被限制在被剪切的區(qū)域內(nèi)  ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推進(jìn)去圖片  ctx.restore(); //恢復(fù)之前保存的繪圖上下文狀態(tài) 可以繼續(xù)繪制  ctx.setFillStyle('#ffffff'); // 文字顏色  ctx.setFontSize(28); // 文字字號(hào)  ctx.fillText(that.data.currentChildren.name, 103, 78); // 繪制文字  ctx.font = 'normal bold 44px sans-serif';  ctx.setFillStyle('#ffffff'); // 文字顏色  ctx.fillText(wordNumber, 325, 153); // 繪制文字  ctx.font = 'normal normal 30px sans-serif';  ctx.setFillStyle('#ffffff')  ctx.fillText('字', allReading, 150);  ctx.font = 'normal normal 24px sans-serif';  ctx.setFillStyle('#ffffff'); // 文字顏色  ctx.fillText('打敗了全國(guó)', 26, 190); // 繪制文字  ctx.font = 'normal normal 24px sans-serif';  ctx.setFillStyle('#faed15'); // 文字顏色  ctx.fillText(that.data.percent, 154, 190); // 繪制孩子百分比  ctx.font = 'normal normal 24px sans-serif';  ctx.setFillStyle('#ffffff'); // 文字顏色  ctx.fillText('的小朋友', 205, 190); // 繪制孩子百分比  ctx.font = 'normal bold 32px sans-serif';  ctx.setFillStyle('#333333'); // 文字顏色  ctx.fillText(that.data.singIn, 50, 290); // 簽到天數(shù)  ctx.fillText(that.data.reading, 280, 290); // 閱讀時(shí)長(zhǎng)  ctx.fillText(that.data.reading, 508, 290); // 聽(tīng)書(shū)時(shí)長(zhǎng)  // 書(shū)籍閱讀結(jié)構(gòu)  ctx.font = 'normal normal 28px sans-serif';  ctx.setFillStyle('#ffffff'); // 文字顏色  ctx.fillText(that.data.bookInfo[0].count, 260, 510);   ctx.fillText(that.data.bookInfo[1].count, 420, 532);   ctx.fillText(that.data.bookInfo[2].count, 520, 594);   ctx.fillText(that.data.bookInfo[3].count, 515, 710);   ctx.fillText(that.data.bookInfo[4].count, 492, 828);   ctx.fillText(that.data.bookInfo[5].count, 348, 858);   ctx.fillText(that.data.bookInfo[6].count, 212, 828);   ctx.fillText(that.data.bookInfo[7].count, 148, 726);   ctx.fillText(that.data.bookInfo[8].count, 158, 600);   ctx.font = 'normal normal 18px sans-serif';  ctx.setFillStyle('#ffffff'); // 文字顏色  ctx.fillText(that.data.bookInfo[0].name, 232, 530);   ctx.fillText(that.data.bookInfo[1].name, 394, 552);   ctx.fillText(that.data.bookInfo[2].name, 496, 614);   ctx.fillText(that.data.bookInfo[3].name, 490, 730);   ctx.fillText(that.data.bookInfo[4].name, 466, 850);   ctx.fillText(that.data.bookInfo[5].name, 323, 878);   ctx.fillText(that.data.bookInfo[6].name, 184, 850);   ctx.fillText(that.data.bookInfo[7].name, 117, 746);   ctx.fillText(that.data.bookInfo[8].name, 130, 621);   ctx.drawImage(result[1], codeurl_x, codeurl_y, codeurl_width, codeurl_heigth); // 繪制頭像  ctx.draw(false, function () {   // canvas畫(huà)布轉(zhuǎn)成圖片并返回圖片地址   wx.canvasToTempFilePath({   canvasId: 'myCanvas',   success: function (res) {    canvasToTempFilePath = res.tempFilePath    that.setData({    showShareImg: true    })    console.log(res.tempFilePath, 'canvasToTempFilePath')    wx.showToast({    title: '繪制成功',    })   },   fail: function () {    wx.showToast({    title: '繪制失敗',    })   },   complete: function () {    wx.hideLoading()    wx.hideToast()   }   })  })  }) } }, // 保存到系統(tǒng)相冊(cè) saveShareImg: function () { let that = this; // 數(shù)據(jù)埋點(diǎn)點(diǎn)擊保存學(xué)情海報(bào) that.setData({  saveId: '保存學(xué)情海報(bào)' }) // 獲取用戶(hù)是否開(kāi)啟用戶(hù)授權(quán)相冊(cè) if (!openStatus) {  wx.openSetting({  success: (result) => {   if (result) {   if (result.authSetting["scope.writePhotosAlbum"] === true) {    openStatus = true;    wx.saveImageToPhotosAlbum({    filePath: canvasToTempFilePath,    success() {     that.setData({     showShareImg: false     })     wx.showToast({     title: '圖片保存成功,快去分享到朋友圈吧~',     icon: 'none',     duration: 2000     })    },    fail() {     wx.showToast({     title: '保存失敗',     icon: 'none'     })    }    })   }   }  },  fail: () => { },  complete: () => { }  }); } else {  wx.getSetting({  success(res) {   // 如果沒(méi)有則獲取授權(quán)   if (!res.authSetting['scope.writePhotosAlbum']) {   wx.authorize({    scope: 'scope.writePhotosAlbum',    success() {    openStatus = true    wx.saveImageToPhotosAlbum({     filePath: canvasToTempFilePath,     success() {     that.setData({      showShareImg: false     })     wx.showToast({      title: '圖片保存成功,快去分享到朋友圈吧~',      icon: 'none',      duration: 2000     })     },     fail() {     wx.showToast({      title: '保存失敗',      icon: 'none'     })     }    })    },    fail() {    // 如果用戶(hù)拒絕過(guò)或沒(méi)有授權(quán),則再次打開(kāi)授權(quán)窗口    openStatus = false    console.log('請(qǐng)?jiān)O(shè)置允許訪(fǎng)問(wèn)相冊(cè)')    wx.showToast({     title: '請(qǐng)?jiān)O(shè)置允許訪(fǎng)問(wèn)相冊(cè)',     icon: 'none'    })    }   })   } else {   // 有則直接保存   openStatus = true   wx.saveImageToPhotosAlbum({    filePath: canvasToTempFilePath,    success() {    that.setData({     showShareImg: false    })    wx.showToast({     title: '圖片保存成功,快去分享到朋友圈吧~',     icon: 'none',     duration: 2000    })    },    fail() {    wx.showToast({     title: '保存失敗',     icon: 'none'    })    }   })   }  },  fail(err) {   console.log(err)  }  }) } },

總結(jié)

以上所述是小編給大家介紹的微信小程序生成海報(bào)分享朋友圈的實(shí)現(xiàn)方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 失禁高潮抽搐喷水h | 成人国产在线视频 | 国产中文一区 | 亚洲欧美aⅴ| 久久免费视频在线 | 97人人草 | 精品一区二区三区日本 | 久久91久久久久麻豆精品 | 欧美三级欧美成人高清www | 亚洲综合视频一区 | 亚洲第一激情 | 午夜在线视频一区二区三区 | 男女视频免费看 | 性毛片视频| 亚洲成年人免费网站 | 久久里面有精品 | 精品二区在线观看 | 九色91视频| 精品在线观看一区二区三区 | 精品久久久久久久久久中文字幕 | 模特三级在线观看 | 黄视频免费在线观看 | 人人做人人看 | 草b视频在线观看 | 国产亚洲精品久久久久久久久久 | www.91操 | 色综合激情 | 成人午夜免费网站 | 少妇一级淫片免费放正片 | 欧美日韩在线免费观看 | 亚洲精品久久久久www | 欧美a视频在线观看 | 国产毛片aaa一区二区三区视频 | 一级大片视频 | 国产一有一级毛片视频 | 欧美性a视频 | 92看片淫黄大片欧美看国产片 | 亚洲国产超高清a毛毛片 | 国产一级在线免费观看 | 免费观看一级黄色片 | 日本a v免费观看 |