最近受疫情的影响,一直呆在家中进行网课学习。由于我们有一定的JS、CSS以及后端开发的基础,所以老师只给了七天的时间学习智能微信小程序的项目开发。在线上听课的同时,抽空也将一些重点记了下来,在此上传至CSDN下作以保留。这里所写的代码,基本都是固定格式,在开发其他功能的小程序中同样适用。
注意事项:
一:需要一个微信账号
二:将微信账号升级为开发者账号(操作步骤如下)
三:使用各大厂商的AI接口提供的功能,开发自己的产品(各种厂商的AI网站可在参考资料下自行获取使用)
微信开发工具使用方法:
第一步:打开微信开发工具
第二步:选择项目目录,可以选择默认,也可选择其他目录
第三步:appid填入上一步获取的appid或者选择测试
1、app开头的几个文件是整个小程序的入口
2、在app.json文件中,pages数组中代表的是页面路径,所有的小程序页面都必须在这里进行注册,放在数组第一个的就是小程序的入口页面,也就是第一个加载出来的页面
3、pages文件夹中代表的就是该小程序的所有页面
注意:在创建页面的时候,文件夹的名字最好和页面名字相同
4、页面由4个文件组成
.js文件:主要实现用户交互和跟后端的交互
.wxss文件:决定了页面上的控件的外观(如:宽高背景颜色字体大小等270多个效果)例如:
.myname{
width:200px;
color:red;
}
.wxml文件:用来写标签,决定页面上展示哪些控件和内容
标签名称 | 功能 |
---|---|
view | 用来排版的模块标签,可以在它里面放很多控件 |
text | 放文字的标签 |
image | 显示图片,在src属性里面放图片的网址或路径 |
其他标签不再展示,可在微信开发文档查看。
样式名称 | 介绍 |
---|---|
宽(width) | 设置宽度 |
高(height) | 设置高度 |
背景颜色(color) | 设置背景颜色 |
圆角度(border-radius) | 设置圆角度 |
文字、大小、颜色(font-xxx) | 例如:font-size:30px; |
线条粗度(font-wight) | 设置线条粗度 |
间隔(leter-space) | 设置间隔距离 |
行高(line-height) | 设置行高 |
页面背景(background-image:url(“放入图片地址或图片路径”)) | 设置页面背景 |
调整界面居中(text-align:center) | 设置界面布局方式为居中 |
调整字体大小(font-size:) | 例如:font-size:25px; |
字体加粗(font-weight:bold;) | 设置字体加粗 |
其他不再赘述,只展示最常用的样式,其余样式可在CSS文档下查看使用。
1、元素内部的控件之间的弹性布局技术
代码格式:
.xxx{
display: flex; /*弹性布局*/
justify-content:flex-start; /*居左对齐 flex-end space-round space-beteawn*/
flex-wrap: wrap; /*内容模块超出了自动换行*/
}
最小宽度:内容比元素窄
最大宽度:内容比元素宽
.xxx{
min-width:20px; /*最小20px*/
max-width:200px; /*最宽200px*/
}
写一个微信聊天的页面(不需要实现功能,只展示静态效果)
写一个商品页面的商品排版
icon图标库:阿里矢量图标库网址 https://www.iconfont.cn/
图标显示的开发步骤:
1、在程序的app.json文件中输入tabBar,即可创建单个或多个跳转按钮
2、tabBar属性中的"iconPath":放入图片icon路径,“selectedIconPath”:放入单击后的图片路径。
1、微信中开发时,对于变量的取法:在wxml文件中,通常在标签中使用双大括号来对变量取值。
例如:
<view>{{……}}view>
注意:
1、在使用image标签对数据进行取值时,图片文件要放在src中。
例如:
<image src="{{……}}">image>
2、在js文件中,存放自定义数据的元素要放在data中,通常数据有以下几种格式。
1、对象格式,如:
obj:{name:"zhangsan",age:"22"}
2、元素定义赋值,如:
title:"hello word"
3、数组格式,如:
arr["123","456","789"]
4、对象+数组格式,如:
users[{name:"marry",age:11},{name:"xiaomin",age:22},{name:"kares",age:33}]
3、在wxml中调用js中保存的数据
通常使用双大括号的格式调用,如:
<text>{{users[0].name}}text>
1、在wxml中for语句的使用方法,如:
<view wx:for="{{arr}}">{{item}}view>
<view wx:for="{{users}}">{{item.name}}view>
2、企业级数据的获取及使用
通过不同的平台获取页面的json或Ajax数据,粘贴复制到js文件中的data中,然后在onLoad中写入函数,例如:
onLoad: function (options){console.log(this.data.weibo)}
3、Ajax中的数据可通过搜索查找相应的数据对应。
4、数据导入完成后,即可通过for循环,将其展示在页面上。
1、使用格式:
<view wx:if="{{判断条件}}">view>
2、for循环和if语句可嵌套使用。
1、文本框(input)属性
value的值是文本框中所显示的内容。例如:
<input>
value="{{inp1}}"
input>
bindinput=“函数名”,文本框的自定义函数,在js中定义此函数。
定义格式如下:
函数名:function(e){“这里写入该函数的方法”}
常用函数 | 作用 |
---|---|
console.log(this.……) | 控制台输出括号中this调用的数据 |
console.log(e.detail.value) | 在文本框函数中使用时,会在控制台输出此时文本框所调用的数据 |
this.setData({inp1:e.detail.value}) | 设置此时inp1的值为文本框中输入的值 |
2、按钮(button) 属性
bindtap=“函数名”,按钮自定义函数,在js中定义此函数。定义方法同文本框自定义函数类似。
声明变量时,使用let来声明变量。例如:
let last=this.data.count
实例:通过点击按钮实现数字的加减,并把运算后的结果输出到屏幕上。
方法:这时可通过使用let声明变量,setData设置变量等。(代码如下)
data:{count:1} /*存放的数据*/
test.function()
{
let newData=this.data.count+1 /*变量new存放新的数据*/
this.setData({count:newData}) /*设置变量(赋值)*/
}
1、在js文件中的onLoad:function(options)中写入如下代码:
wx:wx.getUserInfo({
success(res) {console.log(JSON.parse(res.rawData))}
})/*可查看当前用户的一些微信数据*/
2、获取当前用户的头像,在js文件中的onLoad:function(options)中写入如下代码:
//获取当前用户的头像
let that=this
wx:wx.getUserInfo({
success(res) {
let userinfo=JSON.parse(res.rawData)
console.log(userinfo)
that.setData({ userimg: userinfo.avatarUrl})
}
})
1、JS代码如下:
console.log(this.data.chatInputValue)
//获取数据
let arr2=this.data.arr
//给数组添加数据
arr2.push({ flag: 0, img: this.data.userimg, text: this.data.chatInputValue})
//把新数组添加到data中,让界面显示
this.setData({arr:arr2})
//设置滚动条,使得每次的新数据都能展示在最下方而不必滑动页面
this.setData({scrolltop:10000000000})
2、各种功能学习在微信开发者文档中。
名称 | 用法 |
---|---|
外边距 | margin- |
内边距 | padding- |
相对定位 | position: relative |
绝对定位 | position: absolute |
微调圆角度 | border- |
关于相对定位:若在某个元素中设置了相对定位,它不会影响此元素,如果它的子元素设置了绝对定位后,它的子元素就可以设置x、y的值。
关于绝对定位:position: absolute (left: top bottom right),可选择其他的值来进行绝对定位。
关于圆角度的微调:可对该元素的不同位置的圆角度进行细小的调整,例如:
border-bottom-left-radius: 9px; //左下方的圆角度设置
border-top-left-radius: 9px; //左上方的圆角度设置
1、安装时全部选择默认,安装路径可以装在C盘下或其他盘下。
2、配置环境变量PATH
注意:egg框架要在node.js安装完成后进行
1、打开vscode,创建文件夹后,右键单击文件夹,选择在终端中打开,之后使用如下命令下载egg框架。
npm init egg --type=simple
2、在终端中输入 npm i
,安装必要的文件(项目的依赖模块,会自动生成一个node_mudules文件夹)
3、等待安装成功后,输入npm run dev
启动egg服务框架
4、启动成功后,在浏览器中可以访问服务器(localhost:7001或服务器本机IP:7001)
注意事项:
1、app文件夹是存放项目源代码的地方
2、controller文件夹里面就是处理不同业务的控制文件
ctx.boy=“js中的所有数据类型都可以发送给前端” ,例如
async mycar() {
const { ctx } = this;
ctx.body = '6666';//发送到前端的数据
}
3、service文件夹中的方法专门给controller中的方法使用(新建.js文件后,在空文件后输入egg service会有提示)
数据传输过程示例代码(controller文件中):
//在controller中调用如下方法
let data1=await ctx.service.car.findCarName() //await等待,等待异步操作完成
ctx.body = data1; //向前端发送数据
//这里相当于调用了service文件夹中的car文件中的findCarName方法
在service文件夹中car.js中的代码示例:
async find(uid) {
return {EnName:"BMW",ZhName:'宝马'};
}
router.js文件中的接口
router.get('/learndata', controller.learn.learndata); //三层调用
注意:生成egg service代码片段后,const后跟的命名不能和class后跟的命名相同,否则会报错。
4、public文件夹放静态资源,前端可以直接访问 http://localhost:7001/public/ 这个网址,相当于服务器的public文件夹。
文件说明:
文件类型 | 说明 |
---|---|
config文件夹 | 放项目的配置文件 |
config.default.js | 配置文件 |
plugin.js | 插件配置 |
5、router.js中的module.exports = app => {router.get(“通过编写get方法实现在浏览器中输入不同的网址呈现不同的页面”) }
如:
router.get('/learn', controller.learn.learn); //在浏览器中输入localhost:7001/learn即可查看learn页面
因为egg框架比较新,它的一些代码辅助工具没有完善,所以这里需要自定义用户代码片段,来构造一个代码提示工具。
做法步骤:
1、vscode的扩展按钮单击后输入eggjs选择eggjs 0.3.1版本下载
2、选择这个插件,部分代码会没有提示,此时可完善提示功能,步骤:文件–>首选项–>用户代码片段–>回车(新建一个文件),新建完成后全选删除页面的所有文件,把下面的代码粘贴进去并保存
补全代码提示功能的代码片段:
{
// 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服务代码提示
"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": [
""
],
"description": "axios cdn"
},
//jquery cdn
"scr-jquery": {
"scope": "html,typescript",
"prefix": "scr-jquery",
"body": [
""
],
"description": "jquery cdn"
}
}
1、在微信开发者工具中创建一个按钮,方法名自定义,在js文件中定义此方法,方法体如下:
/*获取后端的数据*/
let that=this //在微信开发者工具中this未定义,此时要使用一个声明了的变量that定义this
//网络请求
wx.request({
//前端要访问的页面,如果要展示给他人使用,这里的localhost要改为服务器IP地址
url: 'localhost:7001/learndata',
success(res){
console.log(res) //网址后端发送给我们的数据
// console.log(that)
that.setData({user:res.data}) //将后端的网页数据传入前端的user中,并放入data中
}
})
此时在wxml中可使用{{user.name}}将获取后的数据打印在界面上
2、将前端的数据发送到后端
在vscode中创建一个方法,用该方法获取前端传来的数据,代码如下:
async getdata() {
const { ctx } = this;
//获取前端的数据
console.log(ctx.request.query);
ctx.body="已收到数据";
}
3、向后端传入参数
在浏览器网址后输入要传入的参数,如:localhost:7001/learn?name=tom&pwd=123
浏览器接收数据的两种方式:
get方式, 如:router.get(’/’, controller.home.index);
post方式,如:router.post(’/getfile’, controller.home.getfile);
在router.js页面使用post方法编写接口,在getfile所在的js文件中写入getfile方法。代码如下:
async getfile() {
const { ctx } = this;
//获取前端传来的文件
console.log(ctx.request.files)
ctx.body = "文件已收到";
}
注意:若要接收传过来的文件并使用post方式写接口,必须在config文件夹中的config.default.js文件中进行配置。方法如下:
在此文件(config.default.js)中找config,找到后将下面的代码粘到const config = exports = {};之后。代码如下:
config.security = {
csrf: {
enable: false //使用post请求要将安全协议关闭
}
}
config.multipart = {
mode: "file" //开启文件模式
}
在微信开发者工具中的js文件中写入如下代码:
//向后端传入图片或拍照上传
//按钮的事件
sendfile() {
//图片的获取:图片/拍照
wx.chooseImage({
success: function(res) {
//上传文件
wx.uploadFile({
url: 'http://localhost:7001/getfile',
filePath: res.tempFiles[0].path, //用户选择的图片的路径:相册/拍照
name: 'myfile',
success(res) {console.log(res)} //控制台打印传入成功后的结果
})
}
})
}
注意:传文件或图片时要用post请求
文件传完之后,如果想保留到服务器,需要在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,()=>{})
注意:如果上传的文件和项目文件不在同一磁盘下,此方法移动文件会失败,这时要使用其他方法来移动文件。
微信端(前端)实现方法如下:
sendrecord() {
//实现开关按钮
this.data.flag = !this.data.flag
console.log(this.data.flag)
if (this.data.flag) {
console.log("录音开始")
let myrecord = wx.getRecorderManager() //获取录音的工具
this.setData({ //将录音工具保存在data中
myrecord: myrecord
})
myrecord.start({ //开始录音
format: "mp3"
})
//监听录音工具停止录音的事件,录音停止将调用函数
myrecord.onStop((res)=>{
console.log(res)//获取录音文件的信息,
//向后端发送录音文件
wx.uploadFile({
url: 'http://localhost:7001/getrecord',
filePath: res.tempFilePath,
name: 'mymp3',
})
})
}
else {
console.log("结束录音,获取录音文件")
this.data.myrecord.stop() //停止录音
}
}
这时在后端的.js文件中要补全接口代码和函数代码,后端获取前端发送的录音文件代码与获取图片的代码大致相同。
根据今天的内容,将第四天的任务项目中添加如下功能的实现,排版问题请自行实现
1、前端要点
查看用户输入的信息数据的组成格式
console.log(this.data.chatMsg)
获取用户输入的信息,并保存在data中
this.setData({chatMsg: e.detail.value})
清空输入框
this.setData({chatMsg:""})
将数据发送到后端
wx.request({url: 'localhost:7001/chatMsg',
data: {msg: this.data.chatMsg},
success(res) {
console.log(res) //控制台打印后端传入前端的数据的组成结构
that.setData({tencentChat:res.data.data})//获取后端返回的结果并保存
}
})
注意:在进行网络请求时,不能直接使用this,需要在wx.request函数体之外,声明并保存this,如:
let that=this
2、后端对接各大厂商AI接口的要点(如:腾讯智能闲聊API)
代码如下:
console.log(714, ctx.request.query) //获取前端传来的数据,第一个参数可省略,这里只是为了精确定位
//将获取到的数据发送给AI处理(三步)
//第一步:得到原始数据
let obj = {
app_id: "填入个人的appid",//appid
time_stamp: Math.round(new Date().valueOf() / 1000),//时间戳
nonce_str: Math.round(new Date().valueOf() / 1000),//随机数
session: "before",//为了记住上一次的聊天用户的唯一标志
question: ctx.request.query.msg, //用户的聊天信息
sign: "" //签名
}
//第二步:对原始数据进行签名
obj.sign = await this.ctx.service.sign.getReqSign(obj) //调用service目录下的sign文件中的getReqSign方法,并将此时的obj传入方法中
let url = "https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat" //对接AI接口API
//第三步:向腾讯AI接口发送网络请求
let result = await this.app.curl(url, {
method: "GET",//请求方式
dataType: "json",//希望腾讯返回的数据的格式,若不写默认返回的就是二进制数据包
data: obj,//给腾讯发送的数据(签名后的数据)
})
console.log(result.data)//控制台打印腾讯API返回的数据的组成结构
ctx.body = result.data;//将关键数据发送给前端
}
3、调用service目录下的sign文件中的getReqSign方法,进行签名转换机制
代码如下:
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]];
}
//第二步:转queryString
let str = '';
for (const k in params) {
if (params.hasOwnProperty(k) && params[k]) {
str += k + '=' + encodeURIComponent(params[k]) + '&';
}
}
//第三步:末尾拼接Appkey
str += 'app_key=' + appKey(申请应用时所分配的);
//第四步:md5加密
return md5(str).toUpperCase();
//return newObj;
}
1、申请AI应用: https://ai.qq.com/ ,获取App_ID 和 App_Key
注意:签名算法的计算步骤
2、接口鉴权(详解)
将
将列表N中的参数对,按URL键值对的格式拼接成字符串,得到字符串T(如:key1=value1&key2=value2),URL键值拼接过程value部分需要URL编码,URL编码算法用大写字母。(例如:%E8,而不是小写%e8)
将应用密钥以app_key为键名,组成URL键值拼接到字符串T末尾,得到字符串S(如:key1=value1&key2=value2&app_key=密钥)
对字符串S进行MD5运算,将得到的MD5值所有字符转换成大写,得到接口并请求签名。
注意:所有接口调用前,都要先接入能力再调用接口。
3、AI智能对话
请求url:https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat
请求方式:GET或POST
响应格式:统一采用JSON格式
接口鉴权:签名机制,参考接口鉴权(详解)
参数 | 解释 |
---|---|
app_id | 应用标识(AppId) |
time_stamp | 请求时间戳(秒级) |
nonce_str | 随机字符串 |
session | 会话标识(任意值,作用:通过标识记住你的对话,应用内唯一) |
question | 用户输入的聊天内容 |
sign | 签名信息,参考接口鉴权(详解) |
代码示例:
async chat() {
const obj = {
app_id: appId,//申请应用时分配的
session: '7888',
question: ctx.request.query.message.toUpperCase(),//用户会话信息
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发送网络请求
const result = await this.app.curl(url, {
method: 'GET',
dataType: 'json',
data: obj
});
console.log(result.data);
}
1、智能聊天的后端请求可以是GET/POST,智能语音的后端请求为POST
2、CSS样式:z-index的含义:z-index 属性设置元素的堆叠顺序。拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。
参数 | 解释 |
---|---|
app_id | 应用标识(AppId) |
time_stamp | 请求时间戳(秒级) |
nonce_str | 随机字符串 |
sign | 签名信息,详见接口鉴权(详解) |
image | 原始图片的base64编码数据(原图大小上限1MB,支持JPG、PNG、BMP格式) |
mode | 检测模式,0-正常,1-大脸模式(默认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);//两个路径必须在一个盘下
//图片转base64编码
let imgData = fs.readFileSync(newpath);
let imgBase64 = Buffer.from(imgData).toString("base64");
在配置文件中修改相关参数
代码如下:
//关闭安全威胁csrf的防范
config.security={
csrf:{
enable:false
}
}
//打开文件上传模式
config.multipart={
mode:"file"
}
//常用的字段可以保存到config中,便于统一管理使用
config.ai={
app_id:"xxxx",
app_key:"xxx"
}
调用保存的字段
this.app.config.ai.app_id
请求url:https://api.ai.qq.com/fcgi-bin/aai/aai_asr
传输方式:HTTPS
请求方法:POST
语音参数:必须符合16k或8K采样率、16bit采样位数、单声道
语音格式:PCM、WAV、AMR、 SILK
字符编码:统一采用UTF-8编码
响应格式:统一采用JSON格式
接口鉴权:签名机制,详见接口鉴权(详解)
参数 | 解释 |
---|---|
app_id | 应用标识(AppId) |
time_stamp | 请求时间戳(秒级) |
nonce_str | 随机字符串 |
sign | 签名信息,详见接口鉴权 |
format | 语音压缩格式编码 |
speech | 语音数据的Base64编码,非空且长度上限8MB,待识别语音(时长上限15s) |
rate | 语音采样率编码,默认即16KHz |
函数名 | 返回值类型 | 返回值含义 |
---|---|---|
ret | int | 0表示成功,非0表示失败 |
msg | string | ret非0时表示出错 |
data | object | ret为0时有意义 |
format | int | API请求中的格式编码 |
rate | int | API请求中的采样率编码 |
text | string | 语音识别结果(UTF-8编码) |
网址:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/api.html
腾讯AI开放平台:https://ai.qq.com/
百度AI开放平台:https://ai.baidu.com/
阿里AI开放平台:https://www.aligenie.com/
网易AI平台:https://openai.163.com/
讯飞开放平台:https://www.xfyun.cn/
相关的开放平台还有很多,比如华为、小米(小爱)、京东以及适合学习机器学习、深度学习的亚马逊、英特尔等,这里不再详述。
关于我个人开发的微信小程序,因为部分功能没有完善、且未向服务器发布,这里就不展示了。