【景途无忧微信小程序】——零基础手把手带你实现,既能连接数据库,又能实现多项功能的前后端交互的微信小程序设计(上)
🎼个人主页:【Y小夜】
😎作者简介:一位双非学校的大三学生,编程爱好者,
专注于基础和实战分享,欢迎私信咨询!
🎆入门专栏:🎇【MySQL,Java基础,Rust】
🎈热门专栏:🎊【Python,Javaweb,Springboot】
感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持!❤️
目录
🎈项目背景
🎊需求分析
🎊性能需求
🎊功能需求
🎈登录功能
🎊创建数据库
🎊后台服务端
🎄初始化服务端
🎄功能实现
🎁utils文件夹
🎁routers文件夹
🎁app.js文件
🎄测试功能
🎊前台微信小程序
🎄功能实现
🎁index.html
🎁index.js
🎄 页面展示
🎈注册功能
🎊后台服务端
🎊前端服务端
🎄功能实现
🎁regist.js
🎁regist.wxml
🎄页面展示
🎈项目背景
🎊需求分析
在当今这个快节奏、高互联的时代,旅游已不仅仅是简单的出行,它更是一种生活方式的探索与体验。随着科技的进步和人们生活品质的提升,现代旅行者对旅游服务的需求日益多元化和个性化。他们渴望在旅途中不仅能够享受到便捷的预订服务,还希望能获得深度的文化体验、实时的信息更新以及社交互动的乐趣。因此,设计一款集景区展示、购票服务、景点推荐、AI答疑等功能于一体的微信小程序“景途无忧”,显得尤为迫切和必要。
🎊性能需求
- 正确性需求
管理员应能够进行有关的旅游信息准确地添加到数据库中。系统用户登录后,系统应能正确地读取用户个人信息。系统的操作结果与预期的结果应该是一致。
- 安全性需求
无重大安全漏洞,用户数据得到妥善保护。
- 及时性需求
即时可见:对旅游信息的处理(包括添加、删除、修改)将立即在后台数据库中进行更新,达到“即时操作、即时生效”的功能
- 稳定性需求
系统部署后,在硬件条件和支持软件条件没有变化的情况下,能够一直保持运行状态,直到系统被升级或代替。
- 扩展性需求
系统应该支持功能扩展与支持环境的扩展。功能扩展就是在现有的功能模块的基础上可以添加信息的功能模块。
- 故障处理能力需求
系统可能遇到的软件故障是数据库与应用程序服务器。为了满足信息处理的需求,可以采取数据恢复来解决。
🎊功能需求
- 运行景途无忧小程序后,进入登录/注册页面,用户如已有账号,可以直接输入账号和密码进行登录,若无账号,可以先进行注册,然后再进行登录操作。
- 首页对数据库中的景点数据进行展示,并且用户可以根据景点名称对感兴趣的景点进行搜索,用户也可以对景点的门票进行购买,加入订单中。
- 小助手页面是调用智能云平台创建的旅游小助手智能体,用于对用户提出的关于旅游的问题进行回答。
- 订单页面可以查看自己购买的门票,并且可以对订单进行取消操作。
- 我的页面用户可以进行查看个人信息、快速注册、退出登录或查看关于我们的界面
🎈登录功能
🎊创建数据库
先自己创建一个MySQL的tour数据库
🎊后台服务端
🎄初始化服务端
先自己创建一个文件夹,用于存放服务端代码
然后开始搭建服务器
- 下载Node.js(https://nodejs.org),选择长期支持版下载。
- 安装Node.js,双击下载的安装包安装即可,安装选项全部使用默认值。
- “用户登录”文件夹下创建文件夹“服务器端”来存放小程序项目对应的服务器端文件。
- “服务器端”文件夹下进入DOS命令界面。
- 初始化服务器端项目,将会自动创建package.json配置文件。 npm init -y
- 安装Express框架,用于快速搭建HTTP服务器。 npm install express --save
- 安装request模块。npm install request --save
- 安装nodemon监控代码修改。 npm install nodemon -g
安装完之后再在根目录下创建一个app.js文件,如下图
最后使用vscode将自己创建的文件加打开
🎄功能实现
🎁utils文件夹
首先,在根目录下创建utils文件夹
在utils文件夹下创建BaseDB.js文件用于导入MySQL的模块
//导入mysql的模块const mysql=require(\"mysql\")//创建数据库连接const db=mysql.createConnection({ //数据库的主机地址 host:\"localhost\", //数据库账号 user:\"root\", //数据库密码 password:\"密码\", //操作的目标数据库 database:\"数据库名\"})//导出数据库连接对象module.exports=db
在utils文件夹下创建Result.js文件用于封装结果类
//定义Result结果封装类class Result{ //返回成功的对象的方法 static success(data){ //返回结果 return{ code:0, msg:\"成功\", data:data } } //返回失败时的对象的方法 static fail(data){ return{ code:1, msg:\"失败\", data:data } }}module.exports=Result
🎁routers文件夹
在routers文件下创建userRouter.js文件,开始编写用户登陆的功能
//导入express用模块const express=require(\"express\")//导入获得路由实例const router=express.Router()//导入数据库连接对象const db=require(\"../utils/BaseDB\")//导入结果封装类const Result=require(\"../utils/Result\")//用户登录router.post(\'/user/login\',(req,resp)=>{ //获取用户名和密码 let username=req.body.username let password=req.body.password //定义sql语句 let sql=` select * from user where username=? and password=? ` //定义参数 let params=[username,password] //查询数据库 db.query(sql,params,(err,res)=>{ //错误 if(err){ resp.send(Result.fail(err)) }else{ //成功 resp.send(Result.success(res)) } })})//进行导出module.exports=router
🎁app.js文件
在app.js文件中编写代码,将路由引入
//导入express模块const express = require(\'express\')//创建express的实例const app=express()//解析提交的json数据app.use(express.json())//解析提交表单的的数据app.use(express.urlencoded({extended:true}))//导入用户模块const userRouter=require(\'./routers/userRouter\')//配置路由app.use(userRouter)// 监听3000端口app.listen(3000,()=>{ console.log(\"服务端启动成功.....\")})
🎄测试功能
先打开终端,再根目录下使用node app 命令运行程序,但是不出意外的话这里要出意外了,请看下图报错
这里是意思是指没有引入mysql模块,我们查看一下node_modules文件夹,发现确实没有mysql
这时我们可以在终端使用 npm install mysql 命令下载mysql模块
下载完毕后,再次运行,发现运行成功。
但是使用node命令运行,当代码发生改变时,页面并不会自动刷新。所以我们可以使用nodemon,nodemon可以实现对代码的监控,使得当代码更新时,不需要重启服务器,就可以自动更新代码。
使用npm install -g nodemon
然后我们使用nodemon app运行,这时候可能还会出现一种错误,如下图
解决方案:
先使用管理员身份登录vscode
- 在终端运行:get-ExecutionPolicy,显示Restricted(表示状态是禁止的)
- 在终端执行,set-ExecutionPolicy RemoteSigned
- 在终端运行:get-ExecutionPolicy,显示RemoteSigned
- 再次运行nodemon app就可不会报错了
接下来使用apifox进行登录测试
请求:
响应:
到此我们的登录接口测试成功。
🎊前台微信小程序
🎄功能实现
🎁index.html
景途无忧 账号 密码 <input password=\"{{true}}\" bind:blur=\"pwdBlur\" placeholder=\"请输入密码\"/> <button type=\"primary\" bind:tap=\"login\" disabled=\"{{disabled}}\">登陆 在这里,我们致力于为您提供一个无忧无虑的旅行体验。无论您是想要探索美丽的自然风光,还是体验丰富的文化之旅,景途无忧都能满足您的需求。我们深知旅行中的每一个细节都至关重要,因此,从购票、规划行程到应对突发情况,我们都为您提供全方位的保障和支持。选择景途无忧,让我们一起开启一段美好的旅程吧!
🎁index.js
// 登录界面的js//获取全局的app对象const app = getApp()Page({ data: { disabled:true, username:\"\", password:\"\" }, //账号文本框输入事件 usernameInput(e){ //获取当前输入的账号 let username = e.detail.value if(username){ //让登陆按钮处于启用状态 this.setData({ disabled:false, username:username }) }else{ this.setData({ disabled:true, username:username }) } }, //绑定密码的失焦函数 pwdBlur(e){ //将密码框中的数据,设置到data.password上 this.setData({ password:e.detail.value }) }, //点击登陆按钮 login(e){ let that=this //判断是否输入密码 if(!this.data.password){ wx.showToast({ title: \'请输入密码\', icon:\"error\" }) return } //发起服务端请求,进行登陆操作 wx.request({ //请求地址 url:app.globalData.baseUrl+\'/user/login\', //请求方法 method:\"POST\", //提交到后端的数据 data:{ \"username\":this.data.username, \"password\":this.data.password }, success:(res)=>{ //请求成功之后,获取后端响应的结果 if(res.data.code==0 && res.data.data.length>0){ wx.showToast({title: \'登陆成功\',icon:\"success\" }) //设置全局用户名 app.globalData.username=that.data.username //登陆成功,将用户数据,存储到本地 //跳转到商品首页 setTimeout(()=>{wx.switchTab({ url: \'/pages/home/home\',}) },200) }else{ wx.showToast({ title: \'登陆失败\', icon:\"error\" }) } } }) }, //注册事件 // 导航到注册 regist(e){ wx.navigateTo({ url: \'/pages/regist/regist\', }) }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, /** * 生命周期函数--监听页面显示 */ onShow() { }, /** * 生命周期函数--监听页面隐藏 */ onHide() { }, /** * 生命周期函数--监听页面卸载 */ onUnload() { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { }, /** * 用户点击右上角分享 */ onShareAppMessage() { }})
🎄 页面展示
🎈注册功能
🎊后台服务端
// 用户注册router.post(\'/user/regist\', (req, resp) => { console.log(req.body); //获取获取一系列信息 const { username, password, phone, address } = req.body; //定义sql语句 let sql = ` insert into user(username,password,phone,address) values(?,?,?,?) `; //定义参数 let params = [username, password, phone, address]; //执行sql语句 db.query(sql, params, (err, res) => { //错误 if (err) { resp.send(result.fail(err)); } //成功 else { resp.send(result.success(res)); } });});
🎊前端服务端
🎄功能实现
🎁regist.js
// pages/regist/regist.jsconst app=getApp();Page({ /** * 页面的初始数据 */ data: { username: \"\", password: \"\", phone: \"\", address: \"\", region: [\'河南省\', \'洛阳市\', \'涧西区\'], customItem: \'全部\' }, // 绑定账号输入 bindUsernameInput: function(e) { this.setData({ username: e.detail.value }); }, // 绑定密码输入 bindPasswordInput: function(e) { this.setData({ password: e.detail.value }); }, // 绑定电话输入 bindPhoneInput: function(e) { this.setData({ phone: e.detail.value }); }, // 改变地区 bindRegionChange: function(e) { this.setData({ region: e.detail.value // 更新地址为选中的地区 }); }, regist(e) { const { username, password, phone, region } = this.data; // 由于picker组件的值是数组,我们需要将其转换为字符串 const address = region.join(\'\'); // 查看表格是否为空 if (!username || !password || !phone || !address) { wx.showToast({ title: \'请填写完整信息\', icon: \'error\' }); return; } // 提交数据 wx.request({ url: app.globalData.baseUrl + \"/user/regist\", method: \"POST\", data:{ \"username\":username, \"password\":password, \"phone\":phone, \"address\":address }, success: (res) => { if ((res.data.code==0)) { wx.showToast({ title: \'注册成功\', icon: \"success\", }); setTimeout(() => { wx.redirectTo({ url: \'/pages/index/index\', }); }, 100); // 0.1秒后跳转 } else { wx.showToast({ title: \'注册失败\', icon: \'error\' }); } } }); }});
🎁regist.wxml
账号 密码 <input password=\"{{true}}\" name=\"password\" placeholder=\"请输入密码\" bindinput=\"bindPasswordInput\"/> 电话 地址 <picker mode=\"region\" bindchange=\"bindRegionChange\" value=\"{{region}}\" custom-item=\"{{customItem}}\"> {{region[0]}},{{region[1]}},{{region[2]}}
🎄页面展示
今天的讲解就到这里,预知后续如何,请看下篇文章!