微信小程序開(kāi)發(fā)實(shí)戰(zhàn)學(xué)習(xí)筆記
前言
最近受疫情的影響,一直呆在家中進(jìn)行網(wǎng)課學(xué)習(xí)。由于我們有一定的JS、CSS以及后端開(kāi)發(fā)的基礎(chǔ),所以老師只給了七天的時(shí)間學(xué)習(xí)智能微信小程序的項(xiàng)目開(kāi)發(fā)。在線上聽(tīng)課的同時(shí),抽空也將一些重點(diǎn)記了下來(lái),在此上傳至CSDN下作以保留。這里所寫(xiě)的代碼,基本都是固定格式,在開(kāi)發(fā)其他功能的小程序中同樣適用。
目標(biāo)
- 前端 —— 掌握微信開(kāi)發(fā)技術(shù)
- 后端 —— 掌握node.js的egg框架
- AI技術(shù) —— 掌握各大平臺(tái)的AI接口使用方法(如:騰訊AI、阿里AI、百度AI等)
- 最終目標(biāo) —— 開(kāi)發(fā)一個(gè)AI產(chǎn)品
第一天 —— 前端配置和編寫(xiě)
微信開(kāi)發(fā)
注意事項(xiàng):
一:需要一個(gè)微信賬號(hào)
-
二:將微信賬號(hào)升級(jí)為開(kāi)發(fā)者賬號(hào)(操作步驟如下)
- 第一步:打開(kāi)此網(wǎng)址 https://mp.weixin.qq.com
- 第二步:選擇個(gè)人開(kāi)發(fā)
- 第三步:申請(qǐng)開(kāi)發(fā)必要的appkey和appid,在開(kāi)發(fā)設(shè)置里面有appkey,可在本地電腦上保存這兩個(gè)數(shù)據(jù)
三:使用各大廠商的AI接口提供的功能,開(kāi)發(fā)自己的產(chǎn)品(各種廠商的AI網(wǎng)站可在資源下自行獲取使用)
微信開(kāi)發(fā)者工具使用方法:
? 第一步:打開(kāi)微信開(kāi)發(fā)工具
? 第二步:選擇項(xiàng)目目錄,可以選擇默認(rèn),也可選擇其他目錄
? 第三步:appid填入上一步獲取的appid或者選擇測(cè)試
微信小程序的代碼結(jié)構(gòu)
1、app開(kāi)頭的幾個(gè)文件是整個(gè)小程序的入口
2、在app.json文件中,pages數(shù)組中代表的是頁(yè)面路徑,所有的小程序頁(yè)面都必須在這里進(jìn)行注冊(cè),放在數(shù)組第一個(gè)的就是小程序的入口頁(yè)面,也就是第一個(gè)加載出來(lái)的頁(yè)面
3、pages文件夾中代表的就是該小程序的所有頁(yè)面
注意:在創(chuàng)建頁(yè)面的時(shí)候,文件夾的名字最好和頁(yè)面名字相同
4、頁(yè)面由4個(gè)文件組成
.js文件:(重點(diǎn))主要實(shí)現(xiàn)用戶交互和跟后端的交互
.wxss文件:決定了頁(yè)面上的控件的外觀(如:寬高背景顏色字體大小等270多個(gè)效果)例如:
.myname{
width:200px;
color:red;
}
.wxml文件:用來(lái)寫(xiě)標(biāo)簽,決定頁(yè)面上展示哪些控件和內(nèi)容
常用標(biāo)簽(wxml)
| 標(biāo)簽名稱 | 功能 |
|---|---|
| <view></view> | 用來(lái)排版的模塊標(biāo)簽,可以在它里面放很多控件 |
| <text></text> | 放文字的標(biāo)簽 |
| <image></image> | 顯示圖片,在src屬性里面放圖片的網(wǎng)址或路徑 |
其他標(biāo)簽不再展示,可在微信開(kāi)發(fā)文檔查看。
常用樣式(wxss)
| 樣式名稱 | 介紹 |
|---|---|
| 寬(width) | 設(shè)置寬度 |
| 高(height) | 設(shè)置高度 |
| 背景顏色(color) | 設(shè)置背景顏色 |
| 圓角度(border-radius) | 設(shè)置圓角度 |
| 文字、大小、顏色(font-xxx) | 例如:font-size:30px; |
| 線條粗度(font-wight) | 設(shè)置線條粗度 |
| 間隔(leter-space) | 設(shè)置間隔距離 |
| 行高(line-height) | 設(shè)置行高 |
| 頁(yè)面背景(background-image:url("放入圖片地址或圖片路徑")) | 設(shè)置頁(yè)面背景 |
| 調(diào)整界面居中(text-align:center) | 設(shè)置界面布局方式為居中 |
| 調(diào)整字體大小(font-size:) | 例如:font-size:25px; |
| 字體加粗(font-weight:bold;) | 設(shè)置字體加粗 |
| "color": "#bfbfbf" | 默認(rèn)文本樣式 |
| "selectedColor": "#333333" | 選中文本樣式 |
其他不再贅述,只展示最常用的樣式,其余樣式可在CSS文檔下查看使用。
界面布局的技術(shù)
1、元素內(nèi)部的控件之間的彈性布局技術(shù)
代碼格式:
.xxx{
display: flex; /*彈性布局*/
justify-content:flex-start; /*居左對(duì)齊 flex-end space-round space-beteawn*/
flex-wrap: wrap; /*內(nèi)容模塊超出了自動(dòng)換行*/
}
最小寬度:內(nèi)容比元素窄
最大寬度:內(nèi)容比元素寬
.xxx{
min-width:20px; /*最小20px*/
max-width:200px; /*最寬200px*/
}
任務(wù)
寫(xiě)一個(gè)微信聊天的頁(yè)面(不需要實(shí)現(xiàn)功能,只展示靜態(tài)效果)
寫(xiě)一個(gè)商品頁(yè)面的商品排版
第二天 —— 深度學(xué)習(xí)微信前端編寫(xiě)(一)
程序底部圖標(biāo)
icon圖標(biāo)庫(kù):阿里矢量圖網(wǎng)址 https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2
圖標(biāo)顯示的開(kāi)發(fā)步驟:
1、在程序的app.json文件中輸入tabBar,即可創(chuàng)建單個(gè)或多個(gè)跳轉(zhuǎn)按鈕
2、tabBar屬性中的"iconPath":放入圖片icon路徑,"selectedIconPath":放入單擊后的圖片路徑。
頁(yè)面數(shù)據(jù)
1、微信中開(kāi)發(fā)時(shí),對(duì)于變量的取法:在wxml文件中,通常在標(biāo)簽中使用雙大括號(hào)來(lái)對(duì)變量取值。
例如:
<view>{{……}}</view>
注意:
1、在使用image標(biāo)簽對(duì)數(shù)據(jù)進(jìn)行取值時(shí),圖片文件要放在src中。
例如:
<image src="{{……}}">
2、在js文件中,存放自定義數(shù)據(jù)的元素要放在data中,通常數(shù)據(jù)有以下幾種格式。
-
1、對(duì)象格式,如:
obj:{name:"zhangsan",age:"22"} -
2、元素定義賦值,如:
title:"hello word" -
3、數(shù)組格式,如:
arr["123","456","789"] -
4、對(duì)象+數(shù)組格式,如:
users[{name:"marry",age:11},{name:"xiaomin",age:22},{name:"kares",age:33}]
3、在wxml中調(diào)用js中保存的數(shù)據(jù)
通常使用雙大括號(hào)的格式調(diào)用,如:
<text>{{users[0].name}}</text>
for循環(huán)
1、在wxml中for語(yǔ)句的使用方法,如:
<view wx:for="{{arr}}">{{item}}</view> <!--此時(shí)程序會(huì)自動(dòng)遍歷數(shù)組中所有的元素,并顯示在頁(yè)面上。-->
<view wx:for="{{users}}">{{item.name}}</view> <!--使用此方式可以對(duì)對(duì)象數(shù)組或復(fù)雜數(shù)據(jù)進(jìn)行調(diào)用。-->
2、企業(yè)級(jí)數(shù)據(jù)的獲取及使用
通過(guò)不同的平臺(tái)獲取頁(yè)面的json或Ajax數(shù)據(jù),粘貼復(fù)制到j(luò)s文件中的data中,然后在onLoad中寫(xiě)入函數(shù),例如:
onLoad: function (options){console.log(this.data.weibo)}
3、Ajax中的數(shù)據(jù)可通過(guò)搜索查找相應(yīng)的數(shù)據(jù)對(duì)應(yīng)。
4、數(shù)據(jù)導(dǎo)入完成后,即可通過(guò)for循環(huán),將其展示在頁(yè)面上。
if語(yǔ)句
1、使用格式:
<view wx:if="{{判斷條件}}"></view>
2、for循環(huán)和if語(yǔ)句可嵌套使用。
任務(wù)
- 制作一個(gè)可以跳轉(zhuǎn)的界面,并在一個(gè)頁(yè)面上顯示獲取到的相應(yīng)的數(shù)據(jù)(理解json/ajax的數(shù)據(jù)處理)
第三天 —— 深度學(xué)習(xí)微信前端編寫(xiě) (二)
文本框和按鈕的事件
1、文本框(input)屬性
-
value的值是文本框中所顯示的內(nèi)容。例如:
<input> value="{{inp1}}" <!--這時(shí)inp1所在的js頁(yè)面中所寫(xiě)的數(shù)據(jù)將被調(diào)用 --> </input> -
bindinput="函數(shù)名",文本框的自定義函數(shù),在js中定義此函數(shù)。
定義格式如下:
函數(shù)名:function(e){"這里寫(xiě)入該函數(shù)的方法"}
常用函數(shù) 作用 console.log(this.……) 控制臺(tái)輸出括號(hào)中this調(diào)用的數(shù)據(jù) console.log(e.detail.value) 在文本框函數(shù)中使用時(shí),會(huì)在控制臺(tái)輸出此時(shí)文本框所調(diào)用的數(shù)據(jù) this.setData({inp1:e.detail.value}) 設(shè)置此時(shí)inp1的值為文本框中輸入的值
2、按鈕(button) 屬性
bindtap="函數(shù)名",按鈕自定義函數(shù),在js中定義此函數(shù)。定義方法同文本框自定義函數(shù)類似。
-
聲明變量時(shí),使用let來(lái)聲明變量。例如:
let last=this.data.count實(shí)例:通過(guò)點(diǎn)擊按鈕實(shí)現(xiàn)數(shù)字的加減,并把運(yùn)算后的結(jié)果輸出到屏幕上。
方法:這時(shí)可通過(guò)使用let聲明變量,setData設(shè)置變量等。(代碼如下)
data:{count:1} /*存放的數(shù)據(jù)*/ test.function() { let newData=this.data.count+1 /*變量new存放新的數(shù)據(jù)*/ this.setData({count:newData}) /*設(shè)置變量(賦值)*/ }
獲取用戶信息
1、在js文件中的onLoad:function(options)中寫(xiě)入如下代碼:
wx:wx.getUserInfo({
success(res) {console.log(JSON.parse(res.rawData))}
})/*可查看當(dāng)前用戶的一些微信數(shù)據(jù)*/
2、獲取當(dāng)前用戶的頭像,在js文件中的onLoad:function(options)中寫(xiě)入如下代碼:
//獲取當(dāng)前用戶的頭像
let that=this
wx:wx.getUserInfo({
success(res) {
let userinfo=JSON.parse(res.rawData)
console.log(userinfo)
that.setData({ userimg: userinfo.avatarUrl})
}
})
點(diǎn)擊按鈕發(fā)送消息
1、JS代碼如下:
console.log(this.data.chatInputValue)
//獲取數(shù)據(jù)
let arr2=this.data.arr
//給數(shù)組添加數(shù)據(jù)
arr2.push({ flag: 0, img: this.data.userimg, text: this.data.chatInputValue})
//把新數(shù)組添加到data中,讓界面顯示
this.setData({arr:arr2})
//設(shè)置滾動(dòng)條,使得每次的新數(shù)據(jù)都能展示在最下方而不必滑動(dòng)頁(yè)面
this.setData({scrolltop:10000000000})
2、各種功能學(xué)習(xí)在微信開(kāi)發(fā)者文檔中。
關(guān)于微信前端樣式的補(bǔ)充
| 名稱 | 用法 |
|---|---|
| 外邊距 | margin- |
| 內(nèi)邊距 | padding- |
| 相對(duì)定位 | position: relative |
| 絕對(duì)定位 | position: absolute |
| 微調(diào)圓角度 | border- |
關(guān)于相對(duì)定位:若在某個(gè)元素中設(shè)置了相對(duì)定位,它不會(huì)影響此元素,如果它的子元素設(shè)置了絕對(duì)定位后,它的子元素就可以設(shè)置x、y的值。
關(guān)于絕對(duì)定位:position: absolute (left: top bottom right),可選擇其他的值來(lái)進(jìn)行絕對(duì)定位。
關(guān)于圓角度的微調(diào):可對(duì)該元素的不同位置的圓角度進(jìn)行細(xì)小的調(diào)整,例如:
border-bottom-left-radius: 9px; //左下方的圓角度設(shè)置
border-top-left-radius: 9px; //左上方的圓角度設(shè)置
任務(wù)
- 將第一天和第二天的內(nèi)容結(jié)合起來(lái),加入第三天的內(nèi)容,編寫(xiě)一個(gè)靜態(tài)的小程序界面
第四天 —— 后端環(huán)境配置和編寫(xiě)
node.js的安裝方法
1、安裝時(shí)全部選擇默認(rèn),安裝路徑可以裝在C盤(pán)下或其他盤(pán)下。
- 安裝在C盤(pán)下,可以避免不少的配置步驟和項(xiàng)目后期出現(xiàn)的一些BUG。
- 安裝在其他盤(pán)下需要對(duì)系統(tǒng)環(huán)境變量和用戶環(huán)境變量進(jìn)行配置。(具體方法可在百度中進(jìn)行搜索)
2、配置環(huán)境變量PATH
egg框架的安裝方法
注意:egg框架要在node.js安裝完成后進(jìn)行
1、打開(kāi)vscode,創(chuàng)建文件夾后,右鍵單擊文件夾,選擇在終端中打開(kāi),之后使用如下命令下載egg框架。
npm init egg --type=simple
2、在終端中輸入 npm i ,安裝必要的文件(項(xiàng)目的依賴模塊,會(huì)自動(dòng)生成一個(gè)node_mudules文件夾)
3、等待安裝成功后,輸入npm run dev 啟動(dòng)egg服務(wù)框架
4、啟動(dòng)成功后,在瀏覽器中可以訪問(wèn)服務(wù)器(localhost:7001或服務(wù)器本機(jī)IP:7001)
egg的使用方法
注意事項(xiàng):
1、app文件夾是存放項(xiàng)目源代碼的地方
2、controller文件夾里面就是處理不同業(yè)務(wù)的控制文件
ctx.boy="js中的所有數(shù)據(jù)類型都可以發(fā)送給前端" ,例如
async mycar() {
const { ctx } = this;
ctx.body = '6666';//發(fā)送到前端的數(shù)據(jù)
}
3、service文件夾中的方法專門(mén)給controller中的方法使用(新建.js文件后,在空文件后輸入egg service會(huì)有提示)
數(shù)據(jù)傳輸過(guò)程示例代碼(controller文件中):
//在controller中調(diào)用如下方法
let data1=await ctx.service.car.findCarName() //await等待,等待異步操作完成
ctx.body = data1; //向前端發(fā)送數(shù)據(jù)
//這里相當(dāng)于調(diào)用了service文件夾中的car文件中的findCarName方法
在service文件夾中car.js中的代碼示例:
async find(uid) {
return {EnName:"BMW",ZhName:'寶馬'};
}
router.js文件中的接口
router.get('/learndata', controller.learn.learndata); //三層調(diào)用
注意:生成egg service代碼片段后,const后跟的命名不能和class后跟的命名相同,否則會(huì)報(bào)錯(cuò)。
4、public文件夾放靜態(tài)資源,前端可以直接訪問(wèn) http://localhost:7001/public/ 這個(gè)網(wǎng)址,相當(dāng)于服務(wù)器的public文件夾。
文件說(shuō)明:
| 文件類型 | 說(shuō)明 |
|---|---|
| config文件夾 | 放項(xiàng)目的配置文件 |
| config.default.js | 配置文件 |
| plugin.js | 插件配置 |
5、router.js中的module.exports = app => {router.get("通過(guò)編寫(xiě)get方法實(shí)現(xiàn)在瀏覽器中輸入不同的網(wǎng)址呈現(xiàn)不同的頁(yè)面") }
如:
router.get('/learn', controller.learn.learn); //在瀏覽器中輸入localhost:7001/learn即可查看learn頁(yè)面
egg代碼提示工具
因?yàn)閑gg框架比較新,它的一些代碼輔助工具沒(méi)有完善,所以這里需要自定義用戶代碼片段,來(lái)構(gòu)造一個(gè)代碼提示工具。
做法步驟:
1、vscode的擴(kuò)展按鈕單擊后輸入eggjs選擇eggjs 0.3.1版本下載
2、選擇這個(gè)插件,部分代碼會(huì)沒(méi)有提示,此時(shí)可完善提示功能,步驟:文件-->首選項(xiàng)-->用戶代碼片段-->回車(新建一個(gè)文件),新建完成后全選刪除頁(yè)面的所有文件,把下面的代碼粘貼進(jìn)去并保存
補(bǔ)全代碼提示功能的代碼片段:
{
// Place your 全局 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
//egg控制器代碼提示
"egg-controller": {
"scope": "javascript,typescript",
"prefix": "egg controller",
"body": [
"'use strict';",
"const Controller = require('egg').Controller;",
"class $1Controller extends Controller {",
" async index() {",
" const { ctx } = this;",
" ctx.body = '$2';",
" }",
"}",
"module.exports = $1Controller;",
],
"description": "egg 控制器的代碼提示"
},
//egg服務(wù)代碼提示
"egg-service": {
"scope": "javascript,typescript",
"prefix": "egg service",
"body": [
"const Service = require('egg').Service;",
"class $1Service extends Service {",
" async find(uid) {",
" const sql=``",
" const data = await this.app.mysql.query(sql);",
" return data;",
" }",
"}",
"module.exports = $1Service;",
],
"description": "egg 控制器的代碼提示"
},
//axios cdn
"scr-axios": {
"scope": "html,typescript",
"prefix": "scr-axios",
"body": [
"<script src='https://unpkg.com/axios/dist/axios.min.js'></script>"
],
"description": "axios cdn"
},
//jquery cdn
"scr-jquery": {
"scope": "html,typescript",
"prefix": "scr-jquery",
"body": [
"<script src='https://code.jquery.com/jquery-3.4.1.slim.min.js'></script>"
],
"description": "jquery cdn"
}
}
任務(wù)
- 根據(jù)前面所學(xué)習(xí)的內(nèi)容,結(jié)合第三天自己做的靜態(tài)小程序界面,編寫(xiě)好后端文件代碼。
第五天 —— 前后端交互的簡(jiǎn)單學(xué)習(xí)
前后端交互的方法及注意事項(xiàng)
1、在微信開(kāi)發(fā)者工具中創(chuàng)建一個(gè)按鈕,方法名自定義,在js文件中定義此方法,方法體如下:
/*獲取后端的數(shù)據(jù)*/
let that=this //在微信開(kāi)發(fā)者工具中this未定義,此時(shí)要使用一個(gè)聲明了的變量that定義this
//網(wǎng)絡(luò)請(qǐng)求
wx.request({
//前端要訪問(wèn)的頁(yè)面,如果要展示給他人使用,這里的localhost要改為服務(wù)器IP地址
url: 'localhost:7001/learndata',
success(res){
console.log(res) //網(wǎng)址后端發(fā)送給我們的數(shù)據(jù)
// console.log(that)
that.setData({user:res.data}) //將后端的網(wǎng)頁(yè)數(shù)據(jù)傳入前端的user中,并放入data中
}
})
此時(shí)在wxml中可使用{{user.name}}將獲取后的數(shù)據(jù)打印在界面上
2、將前端的數(shù)據(jù)發(fā)送到后端
在vscode中創(chuàng)建一個(gè)方法,用該方法獲取前端傳來(lái)的數(shù)據(jù),代碼如下:
async getdata() {
const { ctx } = this;
//獲取前端的數(shù)據(jù)
console.log(ctx.request.query);
ctx.body="已收到數(shù)據(jù)";
}
3、向后端傳入?yún)?shù)
在瀏覽器網(wǎng)址后輸入要傳入的參數(shù),如:localhost:7001/learn?name=tom&pwd=123
瀏覽器接收數(shù)據(jù)的兩種方式:
? get方式, 如:router.get('/', controller.home.index);
? post方式,如:router.post('/getfile', controller.home.getfile);
后端獲取前端傳來(lái)的文件
在router.js頁(yè)面使用post方法編寫(xiě)接口,在getfile所在的js文件中寫(xiě)入getfile方法。代碼如下:
async getfile() {
const { ctx } = this;
//獲取前端傳來(lái)的文件
console.log(ctx.request.files)
ctx.body = "文件已收到";
}
注意:若要接收傳過(guò)來(lái)的文件并使用post方式寫(xiě)接口,必須在config文件夾中的config.default.js文件中進(jìn)行配置。方法如下:
? 在此文件(config.default.js)中找config,找到后將下面的代碼粘到const config = exports = {};之后。代碼如下:
config.security = {
csrf: {
enable: false //使用post請(qǐng)求要將安全協(xié)議關(guān)閉
}
}
config.multipart = {
mode: "file" //開(kāi)啟文件模式
}
向后端傳入圖片或拍照上傳
在微信開(kāi)發(fā)者工具中的js文件中寫(xiě)入如下代碼:
//向后端傳入圖片或拍照上傳
//按鈕的事件
sendfile() {
//圖片的獲取:圖片/拍照
wx.chooseImage({
success: function(res) {
//上傳文件
wx.uploadFile({
url: 'http://localhost:7001/getfile',
filePath: res.tempFiles[0].path, //用戶選擇的圖片的路徑:相冊(cè)/拍照
name: 'myfile',
success(res) {console.log(res)} //控制臺(tái)打印傳入成功后的結(jié)果
})
}
})
}
注意:傳文件或圖片時(shí)要用post請(qǐng)求
文件傳完之后,如果想保留到服務(wù)器,需要在vscode中的getfile方法中添加如下代碼:
//例如:oldpath:"C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\egg-multipart-tmp\\taobao\\2020\\03\\28\\16\\ba295b87-26f4-47ca-aa53-5a319bbba281.jpg"
//newpath:"c:/xx/x/x/x/public/wx616a91aed6a26640.o6zAJs4731Mrs5ZaKUNC6Aotfkso.mYezV3Q3EFMv128753d0885c888f9b4cd8746717b19e.jpg"
let oldpath=ctx.request.files[0].filepath
let newpath=__dirname+"/../public/"+ctx.request.files[0].filename
fs.rename(oldpath,newpath,()=>{})
注意:如果上傳的文件和項(xiàng)目文件不在同一磁盤(pán)下,此方法移動(dòng)文件會(huì)失敗,這時(shí)要使用其他方法來(lái)移動(dòng)文件。
向后端傳入錄音文件
微信端(前端)實(shí)現(xiàn)方法如下:
sendrecord() {
//實(shí)現(xiàn)開(kāi)關(guān)按鈕
this.data.flag = !this.data.flag
console.log(this.data.flag)
if (this.data.flag) {
console.log("錄音開(kāi)始")
let myrecord = wx.getRecorderManager() //獲取錄音的工具
this.setData({ //將錄音工具保存在data中
myrecord: myrecord
})
myrecord.start({ //開(kāi)始錄音
format: "mp3"
})
//監(jiān)聽(tīng)錄音工具停止錄音的事件,錄音停止將調(diào)用函數(shù)
myrecord.onStop((res)=>{
console.log(res)//獲取錄音文件的信息,
//向后端發(fā)送錄音文件
wx.uploadFile({
url: 'http://localhost:7001/getrecord',
filePath: res.tempFilePath,
name: 'mymp3',
})
})
}
else {
console.log("結(jié)束錄音,獲取錄音文件")
this.data.myrecord.stop() //停止錄音
}
}
這時(shí)在后端的.js文件中要補(bǔ)全接口代碼和函數(shù)代碼,后端獲取前端發(fā)送的錄音文件代碼與獲取圖片的代碼大致相同。
任務(wù)
根據(jù)今天的內(nèi)容,將第四天的任務(wù)項(xiàng)目中添加如下功能的實(shí)現(xiàn),排版問(wèn)題請(qǐng)自行實(shí)現(xiàn)
- 加入上傳文件的功能,并保存在服務(wù)器端的 public/file 文件夾中
- 加入上傳圖片和拍照上傳的功能,并保存在服務(wù)器端的 public/photo 文件夾中
- 加入上傳錄音的功能,保存在服務(wù)器端的 public/record 文件夾中
第六天 —— 動(dòng)態(tài)界面的實(shí)現(xiàn)
前端向后端發(fā)送文字
1、前端要點(diǎn)
-
查看用戶輸入的信息數(shù)據(jù)的組成格式
console.log(this.data.chatMsg) -
獲取用戶輸入的信息,并保存在data中
this.setData({chatMsg: e.detail.value}) -
清空輸入框
this.setData({chatMsg:""}) -
將數(shù)據(jù)發(fā)送到后端
wx.request({url: 'localhost:7001/chatMsg', data: {msg: this.data.chatMsg}, success(res) { console.log(res) //控制臺(tái)打印后端傳入前端的數(shù)據(jù)的組成結(jié)構(gòu) that.setData({tencentChat:res.data.data})//獲取后端返回的結(jié)果并保存 } })注意:在進(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí),不能直接使用this,需要在wx.request函數(shù)體之外,聲明并保存this,如:
let that=this
2、后端對(duì)接各大廠商AI接口的要點(diǎn)(如:騰訊智能閑聊API)
代碼如下:
console.log(714, ctx.request.query) //獲取前端傳來(lái)的數(shù)據(jù),第一個(gè)參數(shù)可省略,這里只是為了精確定位
//將獲取到的數(shù)據(jù)發(fā)送給AI處理(三步)
//第一步:得到原始數(shù)據(jù)
let obj = {
app_id: "填入個(gè)人的appid",//appid
time_stamp: Math.round(new Date().valueOf() / 1000),//時(shí)間戳
nonce_str: Math.round(new Date().valueOf() / 1000),//隨機(jī)數(shù)
session: "before",//為了記住上一次的聊天用戶的唯一標(biāo)志
question: ctx.request.query.msg, //用戶的聊天信息
sign: "" //簽名
}
//第二步:對(duì)原始數(shù)據(jù)進(jìn)行簽名
obj.sign = await this.ctx.service.sign.getReqSign(obj) //調(diào)用service目錄下的sign文件中的getReqSign方法,并將此時(shí)的obj傳入方法中
let url = "https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat" //對(duì)接AI接口API
//第三步:向騰訊AI接口發(fā)送網(wǎng)絡(luò)請(qǐng)求
let result = await this.app.curl(url, {
method: "GET",//請(qǐng)求方式
dataType: "json",//希望騰訊返回的數(shù)據(jù)的格式,若不寫(xiě)默認(rèn)返回的就是二進(jìn)制數(shù)據(jù)包
data: obj,//給騰訊發(fā)送的數(shù)據(jù)(簽名后的數(shù)據(jù))
})
console.log(result.data)//控制臺(tái)打印騰訊API返回的數(shù)據(jù)的組成結(jié)構(gòu)
ctx.body = result.data;//將關(guān)鍵數(shù)據(jù)發(fā)送給前端
}
3、調(diào)用service目錄下的sign文件中的getReqSign方法,進(jìn)行簽名轉(zhuǎn)換機(jī)制
代碼如下:
async getReqSign(obj) {
//第一步:key排序
const newkey = Object.keys(obj).sort();
var params = {};
for (var i = 0; i < newkey.length; i++) {
params[newkey[i]] = obj[newkey[i]];
}
//第二步:轉(zhuǎn)queryString
let str = '';
for (const k in params) {
if (params.hasOwnProperty(k) && params[k]) {
str += k + '=' + encodeURIComponent(params[k]) + '&';
}
}
//第三步:末尾拼接Appkey
str += 'app_key=' + appKey(申請(qǐng)應(yīng)用時(shí)所分配的);
//第四步:md5加密
return md5(str).toUpperCase();
//return newObj;
}
微信AI(騰訊)小程序開(kāi)發(fā)
1、申請(qǐng)AI應(yīng)用: https://ai.qq.com/ ,獲取App_ID 和 App_Key
注意:簽名算法的計(jì)算步驟
2、接口鑒權(quán)(詳解)
將<key, value>請(qǐng)求參數(shù)對(duì)按key進(jìn)行字典升序排序,得到有序的參數(shù)對(duì)列表N
將列表N中的參數(shù)對(duì),按URL鍵值對(duì)的格式拼接成字符串,得到字符串T(如:key1=value1&key2=value2),URL鍵值拼接過(guò)程value部分需要URL編碼,URL編碼算法用大寫(xiě)字母。(例如:%E8,而不是小寫(xiě)%e8)
將應(yīng)用密鑰以app_key為鍵名,組成URL鍵值拼接到字符串T末尾,得到字符串S(如:key1=value1&key2=value2&app_key=密鑰)
-
對(duì)字符串S進(jìn)行MD5運(yùn)算,將得到的MD5值所有字符轉(zhuǎn)換成大寫(xiě),得到接口并請(qǐng)求簽名。
注意:所有接口調(diào)用前,都要先接入能力再調(diào)用接口。
3、AI智能對(duì)話
? 請(qǐng)求url:https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat
? 請(qǐng)求方式:GET或POST
? 響應(yīng)格式:統(tǒng)一采用JSON格式
? 接口鑒權(quán):簽名機(jī)制,參考接口鑒權(quán)(詳解)
| 參數(shù) | 解釋 |
|---|---|
| app_id | 應(yīng)用標(biāo)識(shí)(AppId) |
| time_stamp | 請(qǐng)求時(shí)間戳(秒級(jí)) |
| nonce_str | 隨機(jī)字符串 |
| session | 會(huì)話標(biāo)識(shí)(任意值,作用:通過(guò)標(biāo)識(shí)記住你的對(duì)話,應(yīng)用內(nèi)唯一) |
| question | 用戶輸入的聊天內(nèi)容 |
| sign | 簽名信息,參考接口鑒權(quán)(詳解) |
代碼示例:
async chat() {
const obj = {
app_id: appId,//申請(qǐng)應(yīng)用時(shí)分配的
session: '7888',
question: ctx.request.query.message.toUpperCase(),//用戶會(huì)話信息
time_stamp: Math.floor(new Date().valueOf() / 1000),
nonce_str: Math.random().toString().substr(2, 18),
sign: ''
};
obj.sign = await getReqSign(obj);
let url = 'https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat';
//egg發(fā)送網(wǎng)絡(luò)請(qǐng)求
const result = await this.app.curl(url, {
method: 'GET',
dataType: 'json',
data: obj
});
console.log(result.data);
}
智能聊天、智能語(yǔ)音、人臉識(shí)別等
1、智能聊天的后端請(qǐng)求可以是GET/POST,智能語(yǔ)音的后端請(qǐng)求為POST
2、CSS樣式:z-index的含義:z-index 屬性設(shè)置元素的堆疊順序。擁有更高堆疊順序的元素總是會(huì)處于堆疊順序較低的元素的前面。
人臉檢測(cè)
| 參數(shù) | 解釋 |
|---|---|
| app_id | 應(yīng)用標(biāo)識(shí)(AppId) |
| time_stamp | 請(qǐng)求時(shí)間戳(秒級(jí)) |
| nonce_str | 隨機(jī)字符串 |
| sign | 簽名信息,詳見(jiàn)接口鑒權(quán)(詳解) |
| image | 原始圖片的base64編碼數(shù)據(jù)(原圖大小上限1MB,支持JPG、PNG、BMP格式) |
| mode | 檢測(cè)模式,0-正常,1-大臉模式(默認(rèn)1) |
代碼示例:
//將上傳的圖片保存
let oldpath = this.ctx.request.files[0].filepath;
let newpath = __dirname + "/../public/upload/" + this.ctx.request.files[0].filename;
fs.renameSync(oldpath, newpath, err => err);//兩個(gè)路徑必須在一個(gè)盤(pán)下
//圖片轉(zhuǎn)base64編碼
let imgData = fs.readFileSync(newpath);
let imgBase64 = Buffer.from(imgData).toString("base64");
在配置文件中修改相關(guān)參數(shù)
代碼如下:
//關(guān)閉安全威脅csrf的防范
config.security={
csrf:{
enable:false
}
}
//打開(kāi)文件上傳模式
config.multipart={
mode:"file"
}
//常用的字段可以保存到config中,便于統(tǒng)一管理使用
config.ai={
app_id:"xxxx",
app_key:"xxx"
}
調(diào)用保存的字段
this.app.config.ai.app_id
語(yǔ)音識(shí)別
請(qǐng)求url:https://api.ai.qq.com/fcgi-bin/aai/aai_asr
傳輸方式:HTTPS
請(qǐng)求方法:POST
語(yǔ)音參數(shù):必須符合16k或8K采樣率、16bit采樣位數(shù)、單聲道
語(yǔ)音格式:PCM、WAV、AMR、 SILK
字符編碼:統(tǒng)一采用UTF-8編碼
響應(yīng)格式:統(tǒng)一采用JSON格式
接口鑒權(quán):簽名機(jī)制,詳見(jiàn)接口鑒權(quán)(詳解)
| 參數(shù) | 解釋 |
|---|---|
| app_id | 應(yīng)用標(biāo)識(shí)(AppId) |
| time_stamp | 請(qǐng)求時(shí)間戳(秒級(jí)) |
| nonce_str | 隨機(jī)字符串 |
| sign | 簽名信息,詳見(jiàn)接口鑒權(quán) |
| format | 語(yǔ)音壓縮格式編碼 |
| speech | 語(yǔ)音數(shù)據(jù)的Base64編碼,非空且長(zhǎng)度上限8MB,待識(shí)別語(yǔ)音(時(shí)長(zhǎng)上限15s) |
| rate | 語(yǔ)音采樣率編碼,默認(rèn)即16KHz |
| 函數(shù)名 | 返回值類型 | 返回值含義 |
|---|---|---|
| ret | int | 0表示成功,非0表示失敗 |
| msg | string | ret非0時(shí)表示出錯(cuò) |
| data | object | ret為0時(shí)有意義 |
| format | int | API請(qǐng)求中的格式編碼 |
| rate | int | API請(qǐng)求中的采樣率編碼 |
| text | string | 語(yǔ)音識(shí)別結(jié)果(UTF-8編碼) |
任務(wù)
- 結(jié)合第五天的任務(wù),在自己的小程序中加入智能聊天、語(yǔ)言識(shí)別、人臉識(shí)別的功能。
第七天 —— 自主學(xué)習(xí)
目標(biāo)
- 補(bǔ)充關(guān)于微信小程序開(kāi)發(fā)的基礎(chǔ)知識(shí)
- 熟練應(yīng)用egg框架
- 掌握AI接口的使用方法
- 復(fù)習(xí)鞏固近六天的知識(shí)
任務(wù)
- 選定題材,開(kāi)發(fā)一套屬于自己的微信小程序
參考資料
微信開(kāi)放文檔
網(wǎng)址:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/api.html
各大公司AI接口
騰訊AI開(kāi)放平臺(tái):https://ai.qq.com/
百度AI開(kāi)放平臺(tái):https://ai.baidu.com/
阿里AI開(kāi)放平臺(tái):https://www.aligenie.com/
網(wǎng)易AI平臺(tái):https://openai.163.com/
-
訊飛開(kāi)放平臺(tái):https://www.xfyun.cn/
相關(guān)的開(kāi)放平臺(tái)還有很多,比如華為、小米(小愛(ài))、京東以及適合學(xué)習(xí)機(jī)器學(xué)習(xí)、深度學(xué)習(xí)的亞馬遜、英特爾等,這里不再詳述。
關(guān)于我個(gè)人開(kāi)發(fā)的微信小程序,因?yàn)椴糠止δ軟](méi)有完善、且未向服務(wù)器發(fā)布,這里就不展示了。