设计登录界面,输入账号、密码(测试账号:admin 密码:123456)后调用服务端Api接口进行身份验证验证。登录成功记录所返回的身份令牌,登录失败给出相应反馈提示。
<template>
<div>
<div class="container">
<h1>登录</h1><br><br>
<label for="username">用户名</label>
<input type="text" id="username" name="username" required v-model="username"><br><br>
<label for="password">密码</label>
<input type="password" id="password" name="password" required v-model="password"><br><br>
<button @click="login">登录</button>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Login',
data() {
return {
username: "",
password: ""
}
},
methods: {
login() {
axios.post('http://114.67.241.121:8088/user/login',null,{
params:{
username:this.username,
password:this.password
}
}).then((res)=>{
console.log(res);
if(res.data.code==200){
alert("登录成功")
localStorage.setItem("webTestToken",res.data.data.token)
this.$router.push("/info")
}else{
alert(res.data.msg)
}
}).catch((res)=>{
alert(res)
})
}
}
}
</script>
<style lang='less' scoped>
.container {
width: 400px;
// margin: 0 auto;
padding: 20px;
padding-bottom: 70px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
h1 {
margin-bottom: 20px;
text-align: center;
color: #7bd900;
}
label {
display: block;
margin-bottom: 10px;
color: #333;
font-weight: bold;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 10px;
background-color: 7bd900;
border: none;
color: #fff;
font-size: 16px;
font-weight: bold;
text-align: center;
text-decoration: none;
display: block;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #7bd900;
}
</style>
登录成功进入学生管理界面,调用Api接口获取所有学生信息,并设计界面加载显示数据。
- 接口地址:http:// 114.67.241.121:8088/stu/list
- 请求方式:get
- 请求头:
header请求头携带变量:Authorization
header请求头携带变量的值:登录成功所记录下的token身份令牌
- 接口参数:无
- 返回数据
请求头未携带登录成功所返回的token
点击“添加”按钮进入添加界面,完成相关信息输入后,调用Api接口保存数据信息。
- 接口地址:http:// 114.67.241.121:8088/stu/add
- 请求方式:post
- 请求头
header请求头携带变量:Authorization
header请求头携带变量的值:登录成功所记录下的token身份令牌
点击“修改”按钮进入修改界面,读取当前学生信息,输入修改后数据后保存完成数据信息更新。
点击“删除”按钮请求服务端删除数据接口,在服务端数据成功删除后,移除表格中数据行。
<template>
<div class="box">
<button @click="handleAdd" style="margin-bottom: 20px;margin-left: 700px;">添加</button>
<div class="input-wrapper" style="width:200px">
<div class="bar"></div>
</div>
<table class="table">
<tr>
<th>ID</th>
<th>学号</th>
<th>姓名</th>
<th>专业</th>
<th>性别</th>
<th>年级</th>
<th>手机号</th>
<th>地址</th>
<th>出生地</th>
<th>操作</th>
</tr>
<tr v-for="(item, index) in tableData" :key="index">
<td>{{ item.stuid }}</td>
<td>{{ item.stuno }}</td>
<td>{{ item.stuname }}</td>
<td>{{ item.stumajor }}</td>
<td>{{ item.stugender }}</td>
<td>{{ item.stugrade }}</td>
<td>{{ item.stuphone }}</td>
<td>{{ item.stuaddess }}</td>
<td>{{ item.stunative }}</td>
<td><button @click="handleDelete(item.stuid)" style="background-color: orange;">删除</button><button
@click="handleEdit(item)" style="margin-left: 10px;">编辑</button></td>
</tr>
</table>
//编辑用户
<transition name="fade" mode="">
<div class="dialog-mask" v-if="dialogVisiable" @click="handleMask">
<div class="dialog">
<div class="dialog-header">
<h3>编辑用户</h3>
<span class="dialog-close" @click="dialogVisiable = false">×</span>
</div>
<div class="dialog-body">
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuno" />
<label class="label">学号</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuname" />
<label class="label">姓名</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stumajor" />
<label class="label">专业</label>
<div class="bar"></div>
</div>
<div style="position: relative;padding-top: 10px;">
<span
style="font-size: 18px; color: #7bd900; position: absolute; top: -20px; left: 0;">性别</span>
<input type="radio" name="sex" id="male" v-model="form.stugender" value="男"> <label
for="male">男</label>
<input type="radio" name="sex" id="female" v-model="form.stugender" value="女"> <label
for="female">女</label>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stugrade" />
<label class="label">年级</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuphone" />
<label class="label">手机号</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuaddess" />
<label class="label">地址</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stunative" />
<label class="label">出生地</label>
<div class="bar"></div>
</div>
</div>
<div class="dialog-footer">
<button style="margin-right: 10px;" @click="edit">确定</button>
<button @click="dialogVisiable = false">取消</button>
</div>
</div>
</div>
</transition>
//添加用户
<transition name="fade" mode="">
<div class="dialog-mask" v-if="dialogAddVisiable" @click="handleMask">
<div class="dialog">
<div class="dialog-header">
<h3>添加用户</h3>
<span class="dialog-close" @click="dialogAddVisiable = false">×</span>
</div>
<div class="dialog-body">
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuno" />
<label class="label">学号</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuname" />
<label class="label">姓名</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stumajor" />
<label class="label">专业</label>
<div class="bar"></div>
</div>
<div style="position: relative;padding-top: 10px;">
<span
style="font-size: 18px; color: #7bd900; position: absolute; top: -20px; left: 0;">性别</span>
<input type="radio" name="sex" id="male" v-model="form.stugender" value="男"> <label
for="male">男</label>
<input type="radio" name="sex" id="female" v-model="form.stugender" value="女"> <label
for="female">女</label>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stugrade" />
<label class="label">年级</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuphone" />
<label class="label">手机号</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stuaddess" />
<label class="label">地址</label>
<div class="bar"></div>
</div>
<div class="input-wrapper">
<input type="text" class="input" required v-model="form.stunative" />
<label class="label">出生地</label>
<div class="bar"></div>
</div>
</div>
<div class="dialog-footer">
<button @click="add" style="margin-right: 10px;">确定</button>
<button @click="dialogAddVisiable = false">取消</button>
</div>
</div>
</div>
</transition>
//删除用户
<transition name="fade" mode="">
<div class="dialog-mask" v-if="dialogDeleteVisiable" @click="handleMask">
<div class="dialog" ref="deleteDialog">
<div class="dialog-header">
<h3>删除用户</h3>
<span class="dialog-close" @click="dialogDeleteVisiable = false">×</span>
</div>
<div class="dialog-body">
确定要删除吗?
</div>
<div class="dialog-footer">
<button @click="deleteRow" style="margin-right: 10px;">确定</button>
<button @click="dialogDeleteVisiable = false">取消</button>
</div>
</div>
</div>
</transition>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Info',
data() {
return {
tableData: [],
form: {
stuaddess: "",
stugender: "男",
stugrade: "",
stuid: null,
stumajor: "",
stuname: "",
stunative: "",
stuno: "",
stuphone: ""
},
dialogVisiable: false,
dialogAddVisiable: false,
dialogDeleteVisiable: false,
currentRow: {},
stuid: "",
count: 1
}
},
mounted() {
this.getList()
},
methods: {
deleteRow() {
axios.post("http://114.67.241.121:8088/stu/del", null, {
params: {
stuid: this.stuid
},
headers: {
'Authorization': localStorage.getItem("webTestToken")
}
}).then((res) => {
if (res.data.code == 200) {
// alert("删除成功")
this.dialogDeleteVisiable = false
this.getList()
} else {
alert(res.data.msg)
}
}).catch((res) => {
alert(res)
})
},
handleDelete(stuid) {
this.stuid = stuid
this.dialogDeleteVisiable = true
},
getList() {
axios.get("http://114.67.241.121:8088/stu/list", {
headers: {
'Authorization': localStorage.getItem("webTestToken")
}
}).then((res) => {
this.tableData = res.data.data
})
},
add() {
axios.post("http://114.67.241.121:8088/stu/add", {
...this.form
}, {
headers: {
'Authorization': localStorage.getItem("webTestToken")
}
}).then((response) => {
if (response.data.code == 200) {
this.dialogAddVisiable = false
this.getList()
} else {
console.log(response.data.msg);
}
}).catch((response) => {
console.log(response);
})
},
handleAdd() {
this.dialogAddVisiable = true
},
handleEdit(item) {
this.dialogVisiable = true
this.currentRow = JSON.parse(JSON.stringify(item))
this.form = this.currentRow
console.log(this.currentRow);
},
edit() {
axios.post("http://114.67.241.121:8088/stu/edit", {
...this.form
}, {
headers: {
'Authorization': localStorage.getItem("webTestToken")
}
}).then((res) => {
if (res.data.code == 200) {
this.dialogVisiable = false,
this.getList()
}
}).catch((res) => {
alert(res)
})
},
handleMask(e) {
if (e.srcElement.className == "dialog-mask") {
this.dialogAddVisiable = false
this.dialogVisiable = false
this.dialogDeleteVisiable = false
}
}
},
watch: {
dialogAddVisiable(newValue, oldValue) {
if (!newValue) {
this.currentRow = {},
this.form = {}
}
},
dialogVisiable(newValue, oldValue) {
if (!newValue) {
this.currentRow = {},
this.form = {}
}
},
}
}
</script>
<style lang='less' scoped>
.box{
background-color: #fff;
}
.table {
width: 100%;
min-width: 1200px;
border-collapse: collapse;
border-spacing: 0;
}
.table th,
.table td {
padding: 10px;
text-align: center;
border: 1px solid #ccc;
}
.table th {
font-weight: bold;
background-color: #7bd900;
color: #fff;
}
.table tr:nth-child(even) {
background-color: #f0f0f0;
}
.table td {
font-size: 16px;
}
.table td:first-child {
font-weight: bold;
color: #7bd900;
}
button {
padding: 10px 20px;
background-color: #7bd900;
color: #fff;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #7bd900;
}
.dialog-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
// z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
transition: all .3s ease;
}
.dialog {
width: 600px;
background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
border-radius: 5px;
}
.dialog-header {
padding: 15px;
font-size: 18px;
font-weight: bold;
border-bottom: 1px solid #ccc;
display: flex;
justify-content: space-between;
align-items: center;
}
.dialog-close {
font-size: 20px;
cursor: pointer;
}
.dialog-body {
padding: 20px;
line-height: 1.5;
}
.dialog-footer {
padding: 15px;
text-align: right;
border-top: 1px solid #ccc;
}
/* input框容器 */
.input-wrapper {
position: relative;
margin: 30px 0;
}
/* 输入框 */
.input {
font-size: 16px;
width: 100%;
border: none;
border-bottom: 1px solid #ccc;
padding: 10px 0;
background-color: transparent;
transition: border-color 0.3s, box-shadow 0.3s;
}
/* 输入框获得焦点时 */
.input:focus {
border-color: #7bd900;
box-shadow: 0 2px 0 0 #7bd900;
outline: none;
}
/* 输入框有值时 */
.input:not(:placeholder-shown)+.label,
.input:focus+.label {
top: -20px;
font-size: 12px;
color: #7bd900;
}
/* label */
.input-wrapper .label {
position: absolute;
top: 10px;
left: 0;
font-size: 18px !important;
color: #999;
transition: top 0.3s, font-size 0.3s, color 0.3s;
}
/* 底部的动画条 */
.bar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px;
background-color: #ccc;
transition: background-color 0.3s;
}
/* 输入框获得焦点时底部的动画条 */
.input:focus+.bar {
background-color: #7bd900;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease-in-out;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>