前言
老样子,我的风格,直接上项目做,大家学到这里都是具备了一定的前端知识和编程基础的,本学期的课程我将引导你自己来设计一款属于你自己的独特的手机APP。
但是在此之前,你啥也不会,我先带你做一个简单的应用程序,我把它叫做商贸树洞,树洞的意思就是大家吐露心声的地方,这是一种新型的社区,针对的是现在压力过大,且比较孤独的年轻人群,在大学中非常常见。
其实说简单一点就是一个具备匿名功能的留言板,当然,这种社区如果再加上匹配功能就演变成soul等软件,然后通过付费匹配获取盈利,这个不扯远了,跟着做就完事了,做完再说。
一、创建项目
前端还是选择使用uni-app的框架。
打开HBuilder X,点左上角的文件,新建一个项目,选择uniapp中的默认模板即可,项目名称随便取一个好了。
二、注册页面
1.前端(signup.vue)
<template>
<view>
<!-- 图片区域 -->
<div class="image_section flex_column">
<image style="width: 100px;height: 100px;" src="../../static/iloli.gif" mode=""></image>
<h4>Hi~请注册</h4>
</div>
<!-- 输入区域 -->
<div class="input_section flex_column">
<!-- 用户名及用户名输入框 -->
<div class="flex_row">
<p>用户名</p>
<input type="text" placeholder="请输入用户名"/>
</div>
<!-- 密码及密码输入框 -->
<div class="flex_row">
<p>密码</p>
<input type="password" placeholder="请输入密码"/>
</div>
<!-- 确认密码及确认密码输入框 -->
<div class="flex_row">
<p>确认密码</p>
<input type="password" placeholder="请输入确认密码"/>
</div>
</div>
<!-- 按钮区域 -->
<div class="button_section flex_row">
<button @click="zhuce()" class="blue_button">注册</button>
</div>
<!-- 导航区域 -->
<div class="nav_section">
<navigator url=""></navigator>
</div>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
// 注册按钮
zhuce(){
// 发送请求
uni.request({
// 请求的地址
url:'http://localhost:7777/1.php',
// 请求的方法
method:'GET',
// 请求携带的参数
data:{
username:'张三',
password:'123456'
},
// 请求成功后的回调函数
success: (res) => {
// 打印后端给我们的回答
console.log(res)
}
})
}
}
}
</script>
<style>
.image_section{
width: 100vw;
height: 20vh;
background-color: antiquewhite;
}
.input_section{
width: 100vw;
height: 30vh;
background-color: cadetblue;
}
.button_section{
width: 100vw;
height: 20vh;
background-color: chartreuse;
}
.nav_section{
width: 100vw;
height: 30vh;
background-color: chocolate;
}
/* 弹性盒子横着排 */
.flex_row{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: row;/*排列方向:横向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
/* 弹性盒子竖着排 */
.flex_column{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: column;/*排列方向:纵向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
input{
border: 1px solid black;
margin: 10px;
padding: 10px;
}
.blue_button{
background-color: #ecf5ff;
width: 100px;
border: 1px solid #409eff;
color: #409eff;
font-weight: bold;
}
</style>
2.后端(Signup.php)
后端我用的是php语言来写,相对java的后端会简单不少。
后端其实就是接收来自前端的请求,然后发送到数据库,比如前端发来一个请求,表示想注册,后端就把前端传过来的用户名和密码添加到数据库就行了。
有同学可能会疑惑,前端直接把数据添加到数据库不就行了吗?这样多省事,为什么非得经过后端,但是如果前端都能直接操作数据库的话,你不觉得太危险了吗?因为前端代码会发送给用户的浏览器,也就意味着前端代码对用户是完全可见的,用户甚至可以随意修改前端的代码,这样的做法叫做JS绕过,如果有机会的话,我会设计一些网站安全相关的案例带大家去做,我如果就这样说,什么是JS绕过,不管讲得再精彩,你肯定也理解不了,还得得通过实际的案例来说明。
总之就是后端代码存在于服务器上,对用户是不可见的,前端可以很轻易的绕过,后端要攻破就不是那么容易了,我们先写好基础的逻辑,之后讨论安全相关的内容。
准备工作:
- 打开小皮面板、在首页启动apache服务器
- 打开vscode
- 新建Signup.php
由于是第一次讲后端,我把分析的过程一步步给大家展示出来,之后的页面我就直接写完整代码了。
<?php
echo '你好';
?>
在上面这段代码中,<?php ?>
是 PHP 代码的开放和关闭标签,就是说写在中间的内容就会被当作php的代码来执行,不然不认识。
echo
的中文翻译是回声的意思,其实就是咱们不是发了一个请求给后端吗?后端收到请求是不是得给咱们一个回应啊,上面这段代码就是回答了我们一声,说了一句“你好”。
前端对这个接口发请求,看看能不能收到一句“你好”呢?如果收到了,表示前后端成功对话了。
还记得注册页面是不是得传三个参数,也就是前端得告诉我们需要注册账号的用户名,以及还输入了两次密码,这些参数我们都需要后端接收,并保存到数据库,如果接收呢?
<?php
// 定义变量$username,用于接收get请求获取的字段
$username = $_GET['username'];
echo $username;
?>
上述代码接收了来自前端get请求发送的字段username,并保存在$username
变量里,我们用echo回答给前端,表示我们收到了,很简单。
<?php
// 定义变量$username,用于接收get请求获取的字段
$username = $_GET['username'];
$password = $_GET['password'];
echo $username;
echo $password;
?>
但是这样做有一个问题,就是如果要接收两个参数的话,返回数据的时候就出问题,通俗来说,你发现这两个数据是“粘”在一起的,要用的话还得想办法给他们分开,根本分不开的好吧。
这个时候需要定义一个数组类型的变量,用于保存多个数据。
但是注意,我们之前学过python的数组类型,不就是定义一个[],然后往这里面装东西不就行了吗?使用上比较简单,但是php的数组是一种关联数组,是用键值对的形式来存储的,硬要比较的话,和python中的字典类型很像。
<?php
// 定义变量$username,用于接收get请求获取的字段
$username = $_GET['username'];
$password = $_GET['password'];
$a = array(); // 定义一个空数组
$a['username'] = $username;
$a['password'] = $password;
// 返回之前要先将数组转换为json格式
echo json_encode($a);
?>
注意:
- 返回之前要先将数组转换为json格式
- 在网络中传播的数据基本上都是json格式
- 原因是,虽然都是数组,但是php的数组和python的数组在结构上完全不一样
- 这就导致不同语言之间的数据在传输的时候互相不认识
- 大家就规定了一种通用的格式,就是json,他就是一种简单的键值对类型,一个键对应一个值
- 所以只要是键值对类型的数据几乎都可以转换为json格式,相当于一种通用的货币
3.数据库
- 启动小皮面板首页的MYSQL
- 在数据库选项卡中创建数据库(我已经帮你们创建好了)
- 在软件管理中的第四个网站程序,第一个就是,phpMyadmin,点击管理进入管理页面,这里需要输入数据库的密码。
- 新建数据表users
- 新建字段
字段名 | 类型 | 默认值 | 含义 |
---|---|---|---|
id | int10 | 无 | 用户的唯一标识 |
username | varchar100 | 无 | 用户名 |
password | varchar100 | 无 | 密码 |
admin | int10 | 0 | 管理权限 |
数据库连接文件(conn.php)
<?php
// 连接数据库服务器(用户名、密码、数据库名)
$conn = mysqli_connect("localhost","admin","123456","web");
if(!$conn){
die('连接数据库失败');
}
// 设置字符集
mysqli_query($conn,"set names utf8");
4.完善后端(Signup.php)
数据库建好了之后,我们再来写注册页面的后端
<?php
// 连接数据库
include_once "conn.php";
// 定义变量$username,用于接收get请求获取的字段
$username = $_GET['username'];
$password = $_GET['password'];
$a = array(); // 定义一个空数组[]
// 新增一条数据
$sql = "INSERT INTO `users`(`username`,`password`) VALUES ('$username','$password')";
// 执行sql语句
$result = mysqli_query($conn,$sql);
// 如果执行成功,$result就为true,反之为false
if($result){
$a['error'] = 0;
$a['msg'] = '请求成功';
}else{
$a['error'] = 1;
$a['msg'] = '请求失败';
}
// 返回之前要先将数组转换为json格式
echo json_encode($a);
exit;
?>
现在可以通过添加数据到数据库,但是还是有一点问题,因为产品是需要结合具体的使用场景的,如果注册了两个同名的用户,那么登录的时候就出问题了,到底应该是登录谁的账号,所以按理来说应该是一个账号对应一个用户名,我们不能允许用户注册相同的用户名。
也就是说,用户在注册的时候,程序需要先校验,当前数据库是否已经存在相同的用户名了。
// 先判断是否已经存在相同的用户名
$sql = "SELECT * FROM `users` WHERE `username` = '$username'";
// 对于SELECT查询,由于它们产生一个结果集
$result = mysqli_query($conn,$sql);
// 需要通过mysqli_fetch_row()函数来从结果集中逐行获取数据
$info = mysqli_fetch_array($result);
// 还可以通过mysqli_num_rows()函数获取数量
$num = mysqli_num_rows($result);
if($num){
$a['error'] = 1;
$a['msg'] = '该用户名已存在';
echo json_encode($a);
exit;
}
5.完善前端(signup.vue)
再回过头来完善一下前端代码
<template>
<!-- 网页主体 -->
<body class="flex_column">
<!-- 标题区域 -->
<div class="title_section flex_row" style="justify-content: space-around;">
<h3>用户注册</h3>
<h3>X</h3>
</div>
<!-- 图片区域 -->
<div class="image_section flex_column">
<image style="width: 100px;height: 100px;" src="../../static/logo.png" mode=""></image>
<h4>Hi、请注册</h4>
</div>
<!-- 用户输入区域 -->
<div class="input_secition flex_column">
<div class="flex_row">
<p>用户名:</p>
<input v-model="username" type="text" placeholder="请输入账号"/>
</div>
<div class="flex_row">
<p>密码:</p>
<input v-model="password" type="password" placeholder="请输入密码"/>
</div>
<div class="flex_row">
<p>确认密码:</p>
<input v-model="cpassword" type="password" placeholder="请再次输入密码"/>
</div>
</div>
<!-- 按钮区域 -->
<div class="button_section flex_row">
<button @click="signup()" class="login_button">注册</button>
</div>
</body>
</template>
<script>
export default {
data() {
return {
username: "",
password: "",
cpassword: "",
}
},
onLoad() {
},
methods: {
// 注册
signup(){
// 非空校验
if(!this.username || !this.password || !this.cpassword){
uni.showToast({
title:'用户名、密码、确认密码、反正有一个没输入',
duration:2000
})
return false
}
// 密码的长度不能小于6位
if(this.password.length < 6 || this.password.length > 18){
uni.showToast({
title:'前端:密码不能小于6位、或者不能大于18位',
duration:3000,
icon:'error'
})
return false
}
// 密码不一致校验
if(this.password != this.cpassword){
uni.showToast({
title:'两次输入的密码不一致'
})
return false
}
// 发送请求
uni.request({
url: "http://localhost:7777/Signup.php",
data: {
username: this.username,
password: this.password,
cpassword: this.cpassword
},
success: (res) => {
console.log(res);
if(res.data.error==1){
uni.showToast({
title:res.data.msg,
duration:3000,
icon:'error'
})
}else{
uni.showToast({
title:res.data.msg,
duration:3000,
icon:'success'
})
}
}
});
}
}
}
</script>
<style>
.login_button{
width: 50vw;
font-weight: bold;
}
.login_button:hover{
background-color: aquamarine;
}
input{
border: 1px solid black;
margin: 10px;
padding: 10px;
}
.title_section{
width: 100vw;
height: 10vh;
background-color: antiquewhite;
}
.image_section{
width: 100vw;
height: 25vh;
background-color: darkgray;
}
.input_secition{
width: 100vw;
height: 30vh;
background-color: darkseagreen;
}
.button_section{
width: 100vw;
height: 20vh;
background-color: pink;
}
/* 弹性盒子横着排 */
.flex_row{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: row;/*排列方向:横向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
/* 弹性盒子竖着排 */
.flex_column{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: column;/*排列方向:纵向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
</style>
6.完善后端校验(Signup.php)
<?php
include_once 'conn.php';
$a = array(); // 定义一个空数组
// 定义变量$username,用于接收get请求获取的字段
$username = trim($_GET['username']);
$password = trim($_GET['password']);
$cpassword = trim($_GET['cpassword']);
// 非空校验
if(!strlen($username) || !strlen($password) || !strlen($cpassword)){
$a['error'] = 1;
$a['msg'] = '用户名、密码、确认密码、反正有一个没输入';
echo json_encode($a);
exit;
}
// 密码不能低于6位、或者密码不能大于18位
if(strlen($password) < 6 || strlen($password) > 18){
$a['error'] = 1;
$a['msg'] = '后端:密码不能低于6位、或者密码不能大于18位';
echo json_encode($a);
exit; // 终止程序往下运行
}
// 密码不一致校验
if($password <> $cpassword){
$a['error'] = 1;
$a['msg'] = '两次输入的密码不一致';
echo json_encode($a);
exit;
}
// 不能注册同名账号
$sql = "SELECT * FROM `users` WHERE `username` = '$username'";
$result = mysqli_query($conn,$sql);
$num = mysqli_num_rows($result);
if($num){
$a['error'] = 1;
$a['msg'] = '该用户名已经注册了';
echo json_encode($a);
exit;
}
// 插入一条数据
$sql = "INSERT INTO `users`(`username`, `password`) VALUES ('$username','$password')";
$result = mysqli_query($conn,$sql);
if($result){
$a['error'] = 0;
$a['msg'] = '注册成功';
}else{
$a['error'] = 1;
$a['msg'] = '注册失败';
}
// 返回之前要先将数组转换为json格式
echo json_encode($a);
?>
7.注册僵尸账号(了解)
先去这个网站弄个密码字典,https://www.bugku.com/mima/
import requests
file = open('./password_hanhan.txt','r',encoding='utf-8')
content_list =file.readlines()
for content in content_list:
username = content.strip()
password = content.strip()
url = 'http://localhost:7777/Signup.php'
params = {
'username':username,
'password':password,
'cpassword':password,
}
res = requests.get(url,params=params)
res.encoding = 'utf-8'
print(res.text)
8.后端的接口文档
请求地址 | 请求方式 |
---|---|
http://localhost:7777/Signup.php | GET |
字段名称 | 类型和长度 | 是否必须 | 默认值 |
---|---|---|---|
username | varchar(100) | 是 | 无 |
password | varchar(100) | 是 | 无 |
cpassword | varchar(100) | 是 | 无 |
返回参数 | 字段 |
---|---|
error | error为1表示有错误、error为0表示没有错误 |
msg | 错误的具体内容 |
三、登录页面
后端
<?php
// 链接上数据库
include_once 'conn.php';
// 接收前端传过来的用户名和密码
$username = $_GET['username'];
$password = $_GET['password'];
// 定义一个空数组、用于存放返回的数据
$a = array();
// 用户名、密码不能为空 0:false 非0:true
if(!strlen($username) || !strlen($password)){
$a['error'] = 1;
$a['msg'] = '后端:用户名、密码,反正你有一个没填';
echo json_encode($a);
exit; // 终止程序往下运行
}
// 密码不能低于6位、或者密码不能大于18位
if(strlen($password) < 6 || strlen($password) > 18){
$a['error'] = 1;
$a['msg'] = '后端:密码不能低于6位、或者密码不能大于18位';
echo json_encode($a);
exit; // 终止程序往下运行
}
// 去数据库查询,有没有这样一条数据,用户名和密码都等于前端输入的用户名和密码
$sql = "SELECT * FROM `users` WHERE `username` = '$username' and `password` = '$password'";
// 执行上面的sql查询语句,得到一个结果集
$result = mysqli_query($conn,$sql);
// 数一下结果集里有多少条数据
$num = mysqli_num_rows($result);
// 如果查出来有1条以上,就为true(登录成功),否者为false(登录失败)
if($num){
$a['error'] = 0;
$a['msg'] = '登录成功';
echo json_encode($a);
exit;
}else{
$a['error'] = 1;
$a['msg'] = '用户名或密码错误';
echo json_encode($a);
exit;
}
?>
后端接口文档
请求的地址 | 请求的方式 |
---|---|
http://localhost:7777/Login.php | get |
携带的参数 | 类型 | 是否必须 | 默认值 |
---|---|---|---|
username | varcher(100) | 是 | 无 |
password | varcher(100) | 是 | 无 |
返回参数 | 字段 |
---|---|
error | error为1表示有错误、error为0表示没有错误 |
msg | 错误的具体内容 |
前端
<template>
<view>
<!-- 图片区域 -->
<div class="image_section flex_column">
<image src="../../static/angry.gif" style="height: 100px;width: 100px;" mode=""></image>
<h4>Hi~请登陆</h4>
</div>
<!-- 输入区域 -->
<div class="input_section flex_column">
<!-- 用户名及用户名输入框 -->
<div class="flex_row">
<p>用户名</p>
<input type="text" placeholder="请输入用户名" v-model="username"/>
</div>
<!-- 密码及密码输入框 -->
<div class="flex_row">
<p>密码</p>
<input type="password" placeholder="请输入密码" v-model="password"/>
</div>
</div>
<!-- 按钮区域 -->
<div class="button_section flex_row">
<button @click="login()" class="blue_button">登陆</button>
</div>
<!-- 导航区域 -->
<div class="nav_section flex_row">
<navigator url="/pages/signup/signup">
<button class="blue_button" style="width: 70vw;">没有账号、立即注册</button>
</navigator>
</div>
</view>
</template>
<script>
export default {
data() {
return {
username:'',
password:''
}
},
methods: {
// 登陆按钮
login(){
// 输入框的空校验
if(!this.username || !this.password){
uni.showToast({
title:'前端:用户名、密码,反正有一个没填',
duration:3000,
icon:'error'
})
return false
}
// 密码的长度不能小于6位
if(this.password.length < 6 || this.password.length > 18){
uni.showToast({
title:'前端:密码不能小于6位、或者不能大于18位',
duration:3000,
icon:'error'
})
return false
}
// 发送登录请求
uni.request({
url:'http://localhost:7777/Login.php',
method:'GET',
data:{
username:this.username,
password:this.password
},
// 如果请求成功
success: (res) => {
console.log(res)
// 用户登录成功
if(res.data.error == 0){
uni.showToast({
title:res.data.msg,
icon:'success'
})
// 登录成功之后,将用户名保存在缓存里
uni.setStorageSync('username',this.username)
// const username = uni.getStorageSync('username')
// console.log(username)
}else{
uni.showToast({
title:res.data.msg,
icon:'error'
})
}
}
})
}
}
}
</script>
<style>
.image_section{
width: 100vw;
height: 20vh;
background-color: antiquewhite;
}
.input_section{
width: 100vw;
height: 30vh;
background-color: cadetblue;
}
.button_section{
width: 100vw;
height: 20vh;
background-color: chartreuse;
}
.nav_section{
width: 100vw;
height: 30vh;
background-color: chocolate;
}
/* 弹性盒子横着排 */
.flex_row{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: row;/*排列方向:横向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
/* 弹性盒子竖着排 */
.flex_column{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: column;/*排列方向:纵向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
input{
border: 1px solid black;
margin: 10px;
padding: 10px;
}
.blue_button{
background-color: #ecf5ff;
width: 100px;
border: 1px solid #409eff;
color: #409eff;
font-weight: bold;
}
</style>
密码爆破
import requests
url = 'http://localhost:7777/Login.php'
file = open('./password.txt','r',encoding='utf-8')
rows = file.readlines()
for row in rows:
username = row.strip()
password = row.strip()
params = {
'username' : username,
'password' : password
}
res = requests.get(url,params)
if r'\u767b\u5f55\u6210\u529f' in res.text:
print(password)
break
四、制作底部导航栏
官方的代码示例:
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/component/index",
"iconPath": "static/image/icon_component.png",
"selectedIconPath": "static/image/icon_component_HL.png",
"text": "组件"
}, {
"pagePath": "pages/API/index",
"iconPath": "static/image/icon_API.png",
"selectedIconPath": "static/image/icon_API_HL.png",
"text": "接口"
}]
}
我写的代码:(pages.json)
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "树洞"
}
},
{
"path" : "pages/mine/mine",
"style" :
{
"navigationBarTitleText" : "个人中心",
"enablePullDownRefresh" : false
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#00aaff",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/home.png",
"selectedIconPath": "static/home-active.png",
"text": "首页"
}, {
"pagePath": "pages/mine/mine",
"iconPath": "static/mine.png",
"selectedIconPath": "static/mine-active.png",
"text": "我的"
}]
}
}
这里我是顺便把标题栏的名字也改了。
五、个人中心页面(mine.vue)
<template>
<body>
<!-- 用户信息区域 -->
<div class="flex_row" style="width: 100vw;height: 18vh;background-color: cornflowerblue;">
<!-- 左边的头像区域 -->
<div class="flex_row" style="width: 30%;height: 100%;">
<image style="width: 80px;height: 80px;" src="../../static/头像/ikun_7.jpg" mode=""></image>
</div>
<!-- 右边的用户名区域 -->
<div class="flex_column" style="width: 70%;height: 100%;justify-content: space-evenly;">
<h3 style="color: white;">{{username}}</h3>
<!-- 登录注册按钮 -->
<navigator v-if="username=='未登录'" url="/pages/login/login">
<button style="width: 100px; font-weight: bold;background-color: antiquewhite;font-size: medium;">登陆注册</button>
</navigator>
</div>
</div>
<!-- 菜单项(我的树洞) -->
<div class="flex_row" style="border-bottom: 1px solid gray; padding: 10px;box-sizing: border-box; width: 100vw;height: 8vh;background-color: white;margin-top: 20px;">
<div class="flex_row" style="justify-content: flex-start; width: 50%;height: 100%;">
<image class="mid_icon" src="../../static/contact.png" mode=""></image>
<p>我的树洞</p>
</div>
<div class="flex_row" style="justify-content: flex-end; width: 50%;height: 100%;">
<image src="../../static/right_arrow.png" class="mid_icon" mode=""></image>
</div>
</div>
<!-- 菜单项(修改密码) -->
<navigator v-if="username!='未登录'" url="/pages/mod_password/mod_password">
<div class="flex_row" style="border-bottom: 1px solid gray;padding: 10px;box-sizing: border-box; width: 100vw;height: 8vh;background-color: white;">
<div class="flex_row" style="justify-content: flex-start; width: 50%;height: 100%;">
<image class="mid_icon" src="../../static/contact.png" mode=""></image>
<p>修改密码</p>
</div>
<div class="flex_row" style="justify-content: flex-end; width: 50%;height: 100%;">
<image src="../../static/right_arrow.png" class="mid_icon" mode=""></image>
</div>
</div>
</navigator>
<!-- 菜单项(退出登录) -->
<div @click="exit()" class="flex_row" style="border-bottom: 1px solid gray;padding: 10px;box-sizing: border-box; width: 100vw;height: 8vh;background-color: white;">
<div class="flex_row" style="justify-content: flex-start; width: 50%;height: 100%;">
<image class="mid_icon" src="../../static/contact.png" mode=""></image>
<p>退出登录</p>
</div>
<div class="flex_row" style="justify-content: flex-end; width: 50%;height: 100%;">
<image src="../../static/right_arrow.png" class="mid_icon" mode=""></image>
</div>
</div>
</body>
</template>
<script>
export default {
data() {
return {
username:'未登录'
}
},
// 定义网页的相关方法
methods: {
// 退出登录
exit(){
// 清除缓存中的用户名
uni.removeStorageSync('username')
// 更新页面上的数据为未登录
this.username = '未登录'
// 弹框提醒用户
uni.showToast({
title:'退出成功'
})
}
},
// 生命周期函数(当页面显示出来的时候自动调用)
onShow(){
// 如果缓存里有用户名,再去替换,否则不要替换
if(uni.getStorageSync('username')){ //''为False,否则都是True
// 读取缓存中存放的用户名,并且更新到页面
const username = uni.getStorageSync('username')
this.username = username
}
}
}
</script>
<style>
.samll_icon{
width: 20px;
height: 20px;
}
.mid_icon{
width: 30px;
height: 30px;
}
.big_icon{
width: 40px;
height: 40px;
}
body{
background-color: #efefef;
width: 100vw;
height: 100vh;
}
/* 弹性盒子横着排 */
.flex_row{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: row;/*排列方向:横向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
/* 弹性盒子竖着排 */
.flex_column{
display: flex; /* 排列方式:弹性盒子 */
flex-direction: column;/*排列方向:纵向*/
justify-content: center;/*主轴居中*/
align-items: center;/*副轴居中*/
}
</style>
六、发布树洞页面
<template>
<view>
<!-- 输入区域 -->
<div class="input_section">
<textarea v-model="content" style="height: 60%;" maxlength="50"/>
<p>字数提示:{{content.length}}/50</p>
</div>
<!-- 按钮区域 -->
<div class="button_section">
<button @click="commit()" class="commit_button">发布</button>
</div>
</view>
</template>
<script>
export default {
data() {
return {
content:'' // 用户输入的内容
}
},
methods: {
// 发布按钮
commit(){
// 前端空校验
if(this.content == ''){
alert('请输入内容')
return
}
// 从缓存里去取用户名
const username = uni.getStorageSync('username')
// 发请求到后端
uni.request({
url:'http://localhost:7777/Commit.php',
method:'GET',
data:{
content: this.content,
username: username
},
// 发送请求成功
success: (res) => {
console.log(res)
// 如果发布成功
if (res.data.error == 0) {
uni.showToast({
title:res.data.msg
})
// 跳转到广场页面
uni.switchTab({
url:'/pages/index/index'
})
this.content = ''
}else{
uni.showToast({
title:res.data.msg,
icon:'error'
})
}
}
})
}
},
// 当页面自动显示的时候,自动执行一次
onShow: () => {
// 从缓存里去取用户名
const username = uni.getStorageSync('username')
console.log(username);
// 如果没有用户名
if (!username){ // ''为false,否则就是true
// 弹一个登录的对话框
uni.showModal({
title: '提示',
content: '请先登录',
success: function (res) {
// 如果点击确定的话
if (res.confirm) {
// 跳转到登录页面
uni.navigateTo({
url:'/pages/login/login'
})
// 如果用户点击了取消
} else if (res.cancel) {
// 跳转到登录页面
uni.navigateTo({
url:'/pages/login/login'
})
}
}
});
}
}
}
</script>
<style>
textarea{
border: 1px solid gray;
padding: 10px;
margin: 10px;
}
.input_section{
width: 100vw;
height: 40vh;
background-color: antiquewhite;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.button_section{
width: 100vw;
height: 20vh;
background-color: aquamarine;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.commit_button{
width: 30%;
border: 1px saddlebrown solid;
background-color: lightblue;
color: darkblue;
font-weight: bold;
}
</style>
<?php
// 连接数据库
include_once 'conn.php';
// 定义一个数组a,用于存放返回的数据
$a = array();
// 接收前端发过来的内容
$content = $_GET['content'];
$username = $_GET['username'];
// 插入一条数据
$sql = "INSERT INTO `shudong`(`username`, `content`) VALUES ('$username','$content')";
// 执行sql语句 (返回一个结果,如果执行成功,返回true,否则返回false)
$result = mysqli_query($conn,$sql);
if($result){
$a['error'] = 0;
$a['msg'] = '执行成功';
}else{
$a['error'] = 1;
$a['msg'] = '执行失败';
}
echo json_encode($a);
?>