Spring Boot 3 + Vue 3实战:实现用户登录功能

这篇具有很好参考价值的文章主要介绍了Spring Boot 3 + Vue 3实战:实现用户登录功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实战概述

  • 该实战教程旨在指导开发者通过前后端分离的方式,搭建一个结合Vue.js前端框架和Spring Boot后端框架的登录系统。首先,从创建前端项目开始,利用Vue CLI快速生成项目结构,安装axios以实现HTTP请求功能,vue-router处理路由导航,less与less-loader用于样式预处理增强前端开发体验。完成基础设置后,开发者在IDEA中打开并继续构建前端页面,分别创建登录组件、首页组件以及配置路由视图。编写应用根组件,并设置主入口脚本,同时为解决跨域问题设置了反向代理。

  • 接着进行后端项目的搭建,创建Spring Boot应用,配置服务器运行端口号,并启动服务确保能访问到后端首页。然后,为后端设计数据模型,创建用户实体类和结果实体类,以便于业务逻辑处理。最后,开发登录控制器以对接前端发送的登录请求。

  • 整合测试阶段,分别启动前端login-vue项目和后端LoginDemo项目,前端调用后端接口进行登录验证,确保用户登录功能正常运作。此实战涵盖了项目初始化、模块安装、组件开发、路由配置、实体类设计、控制器编写及跨域解决方案等关键环节,有助于开发者理解和实践前后端交互开发流程。

二、实战步骤​

(一)创建前端项目 - login-vue

  • 查看Node和npm版本
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
  • 安装vue脚手架,执行命令:nmp install -g @vue/cli
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

1、创建Vue项目

  • 在命令行窗口里执行命令:vue create login-vue,选择Default ([Vue 3] babel, eslint)
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

2、安装axios模块

  • Axios 是一款基于Promise的JavaScript库,主要用于浏览器和Node.js环境,提供了一种简单、高效的方式来处理前端与后端API之间的HTTP通信。它支持创建和发送GET、POST等多种HTTP请求,可处理JSON数据自动转换,并具有拦截请求/响应、取消请求、设置超时等功能。 Axios遵循Promise API设计,易于理解和使用,广泛应用于现代Web项目中进行异步数据交互。
  • 进入login-vue目录,执行命令:npm install axios --save
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

3、安装vue-router模块

  • Vue Router是Vue.js官方的路由管理器,它通过将SPA(单页应用)的页面切分成多个组件,并实现了URL与组件间的映射关系。在Vue项目中,通过定义路由规则和嵌套路由,Vue Router能够实现视图与URL的同步切换,提供前端路由功能,支持动态路由、导航守卫等功能,为构建复杂单页应用提供了便捷的支持。
  • 执行命令:npm install vue-router@4 --save
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

4、安装less和less-loader模块

  • Less是一种CSS预处理器,通过扩展CSS语法提供变量、嵌套规则、混合、函数等高级特性,使得样式编写更高效、模块化和易于维护。less-loader则是Webpack的一个加载器,用于将Less文件编译成浏览器可识别的CSS代码。在Vue项目中安装并配置less和less-loader后,即可在.vue文件或独立.less文件中编写Less代码,并在构建过程中自动转化为CSS样式。
  • 执行命令:npm install --save-dev less less-loader
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

5、运行Vue项目

  • 执行命令:npm run serve
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
  • 给出访问应用的网址
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

6、在浏览器里访问首页

  • 访问http://local:8080
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

7、在IDEA里打开Vue项目

  • 打开Vue项目 - login-vue
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

8、创建登录Vue组件

  • src/components目录里,删除HelloWorld.vue组件,创建LoginView.vue组件
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
<template>
  <table class="login-table" border="0" cellpadding="10">
    <tr>
      <td align="center">用户名</td>
      <td><input id='username' type="text" v-model="username" placeholder="请输入用户名"/></td>
    </tr>
    <tr>
      <td align="center">&nbsp;&nbsp;&nbsp;&nbsp;</td>
      <td><input id='password' type="password" v-model="password" placeholder="请输入密码"/></td>
    </tr>
    <tr align="center">
      <td colspan="2">
        <button @click="handleLogin">登录</button>
      </td>
    </tr>
  </table>
</template>

<script setup>
import {ref} from 'vue';
import {useRouter} from 'vue-router';
import axios from "axios";

const router = useRouter();
const username = ref('');
const password = ref('');

async function handleLogin() {
  try {
    const response = await axios.post('/api/login', {username: username.value, password: password.value});
    console.log(response.data.code)
    if (response.data.code === 200) {
      router.replace('/index'); // 使用后端返回的路径
    } else if (response.data.code === 400) {
      alert('用户名或密码错误!请重新登录!');
      username.value = '';
      password.value = '';
      document.getElementById('username').focus();
    }
  } catch (error) {
    console.error("Error during login:", error.message); // 添加错误处理,打印错误信息
  }
}
</script>

<style lang="less" scoped>
/* 重置table样式 */
.login-table {
  width: 100%;
  max-width: 300px;
  margin: 50px auto;
  border-collapse: collapse;
  border-spacing: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.login-table td {
  padding-bottom: 16px;
  padding-top: 16px;
  padding-right: 0px;
  padding-right: 8px;
  vertical-align: middle;
  text-align: left;
  border-bottom: 1px solid #ddd;
}

.login-table input[type="text"],
.login-table input[type="password"] {
  width: 100%;
  padding: 8px;
  border: 1px solid #ccc;
  border-radius: 4px;
  outline: none;
  box-sizing: border-box;
}

.login-table button {
  display: block;
  width: 100%;
  padding: 12px;
  background-color: #007bff;
  color: white;
  font-size: 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  text-align: center;
  transition: all 0.3s ease;

  &:hover,
  &:focus {
    background-color: #0056b3;
  }
}
</style>
  • 代码创建了一个登录表单,使用Vue响应式数据绑定用户输入,并在点击登录按钮时通过axios发送POST请求。根据后端返回的code进行判断:200则跳转至/index页面,400则提示错误并清空密码重置焦点。同时定义了简洁的登录界面样式。

9、创建首页Vue组件

  • src/components里创建IndexView.vue组件
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
<template>
  <div class="welcome-container">
    Welcome to Vue 3 World~
  </div>
</template>

<script>
export default {
  name: "IndexView"
}
</script>

<style scoped>
.welcome-container {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 5px;
  background-color: #f5f5f5;
  text-align: center;
  max-width: 400px;
  margin: 0 auto;
  color: red;
  font-weight: bold;
  font-size: 30px;
}
</style>
  • 该代码定义了一个Vue组件IndexView,渲染一个居中显示的欢迎信息框,样式包括内边距、边框、背景色等,并通过CSS设置了自动水平居中布局及字体样式。

10、创建路由视图

  • src里创建router目录,在router目录里创建index.js脚本
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
// 引入Vue3以及新的vue-router
import { createRouter, createWebHistory } from 'vue-router';
import Login from '@/components/LoginView.vue';
import Index from "@/components/IndexView.vue";

// 定义路由
const routes = [
  {
    path: '/login',
    name: 'LoginView',
    component: Login
  },
  {
    path: '/index',
    name: 'IndexView',
    component: Index
  }
];

// 创建路由器实例
const router = createRouter({
  history: createWebHistory(),
  routes,
});

// 导出全局注册
export default router;
  • 该代码引入Vue Router并定义了登录和首页两个路由,使用createRouter创建路由器实例,配置history模式,并导出用于全局注册。

11、编写应用根组件

  • 应用Vue组件 - App.vue是 Vue.js 应用程序的根组件,负责整个应用的布局与整体结构,所有其他组件在其内部组织和渲染。
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <router-view />
  </div>
</template>

<script>
</script>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>
  • 此代码为Vue应用的根组件(App.vue),包含一个logo图片和动态路由视图(<router-view/>)。样式设置字体、抗锯齿及居中对齐。

12、编写主入口脚本

  • main.js是Vue应用的主入口脚本,负责初始化Vue应用实例、注册全局组件与插件(如路由、状态管理等),并挂载到DOM指定元素。
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
// 导入Vue3的核心API,用于创建Vue应用实例
import {createApp} from 'vue';

// 导入根组件App.vue,它是整个应用程序的主视图模板
import App from './App.vue';

// 导入已配置好的路由模块(index.js或router.ts等),它管理着应用内的页面跳转逻辑
import router from "@/router";

// 使用createApp方法创建一个Vue应用实例,并注册全局路由配置
const app = createApp(App).use(router);

// 将Vue应用挂载到HTML文档中id为'app'的元素上
// 这将把整个应用程序渲染到这个DOM元素内部
app.mount('#app');
  • 该代码导入Vue3核心API创建应用实例,引入根组件与路由配置,通过createApp初始化应用并注册路由,最后将整个应用挂载到DOM中id为’app’的元素上。

13、设置反向代理和跨域支持

  • 修改vue.config.js代码,设置反向代理和跨域支持
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
module.exports = {
  // 设置在保存文件时禁用ESLint自动检查
  lintOnSave: false,

  // 配置Vue开发服务器相关选项
  devServer: {
    // 配置HTTP代理,以便在开发过程中将特定请求转发到其他服务器
    proxy: {
      // 当请求以 '/api' 开头时进行代理
      '/api': {
        // 指定目标服务器地址(例如后台API接口)
        target: 'http://localhost:8888',
        
        // 设置为true,允许跨域请求时重写源信息(Origin header)
        changeOrigin: true,

        // 路径重写规则,将前端应用中'/api'前缀去掉,映射到后端服务器的实际路径上
        pathRewrite: { '^/api': '' },
      }
    }
  }
}
  • 这段代码配置了Vue项目在开发环境下的行为:禁用了文件保存时的ESLint检查,并设置了一个开发服务器的代理服务。当开发环境中前端应用发起对/api开头的请求时,该请求会被代理至http://localhost:8888服务器,并通过pathRewrite规则进行路径重写,解决前后端分离开发中的跨域问题。

14、访问登录页面

  • 启动Vue项目,访问http://localhost:8080/login
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

(二)创建后端项目 - LoginDemo

1、创建Spring Boot项目

  • 设置项目名称 LoginDemo、保存位置、语言、类型、组标识、构件名、包名、JDK版本、Java语言级、打包类型
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 单击【Next】按钮,在弹出的对话框里选择Spring Boot版本,添加项目相关依赖
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 单击【Create】按钮,得到初始化项目
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

2、配置服务器端口号

  • 在前端项目里配置了目标服务器地址,端口是8888
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 在应用属性文件application.properties里配置服务器端口号
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

3、启动应用,访问首页

  • resources目录里创建首页index.html
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <h3 style="text-align: center; color: red">Welcome to Spring Boot World~</h3>
</body>
</html>
  • 修改入口程序LoginDemoApplication代码
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
  • 启动应用程序,在浏览器里访问http://localhost:8888,查看结果
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

4、创建用户实体类

  • 创建bean子包,在子包里创建User
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
package net.huawei.login.bean;

/**
 * 功能:用户实体类
 * 作者:华卫
 * 日期:2024年01月14日
 */
public class User {
    private int id;
    private String username;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

5、创建结果实体类

  • 创建result子包,在子包里创建Result类,封装响应码
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
package net.huawei.login.result;

/**
 * 功能:结果实体类
 * 作者:华卫
 * 日期:2024年01月14日
 */
public class Result {
    private int code;

    public Result(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}
  • 该Java类为结果实体,包含一个表示状态码的整型变量code,通过构造函数初始化,并提供getter/setter方法,用于处理服务端响应的状态信息。

6、创建登录控制器

  • 创建controller子包,在子包里创建LoginController
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录
package net.huawei.login.controller;

import net.huawei.login.bean.User;
import net.huawei.login.result.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;

/**
 * 功能:登录控制器
 * 作者:华卫
 * 日期:2024年01月14日
 */
@Controller
public class LoginController {
    @CrossOrigin
    @PostMapping(value = "api/login")
    @ResponseBody
    public Result login(@RequestBody User requestUser) {
        // 获取用户名和密码
        String username = requestUser.getUsername();
        String password = requestUser.getPassword();
        // 对html标签进行转义,防止XSS攻击
        username = HtmlUtils.htmlEscape(username);
        // 判断登录是否成功
        if (username.equals("无心剑") && password.equals("903213")) {
            return new Result(200);
        } else {
            System.out.println("用户名或密码有误!");
            return new Result(400);
        }
    }
}
  • 该Java控制器处理登录请求,接收并校验用户提交的用户名密码,进行XSS防护,并根据预设数据判断登录是否成功,返回包含状态码的结果实体。

(三)前后端整合测试

1、启动前端项目 - login-vue

  • 在前端项目的目录里执行命令:npm run serve
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

2、启动后端项目 - LoginDemo

  • 启动入口类LoginDemoApplication
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

3、测试用户登录功能

  • 访问http://localhost:8080/login登录页面
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 如果输入的用户名或密码有误,弹出消息框提示用户
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 输入正确的用户名或密码(无心剑 :903213)
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 单击【登录】按钮,跳转到首页
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录

  • 操作录屏演示
    Spring Boot 3 + Vue 3实战:实现用户登录功能,Spring Boot + Vue,spring boot,vue.js,用户登录文章来源地址https://www.toymoban.com/news/detail-795758.html

三、实战总结

  • 该实战通过前后端分离方式,构建基于Vue.js与Spring Boot的登录系统。前端完成项目创建、页面组件开发和路由配置;后端搭建Spring Boot服务,设计实体类并实现登录控制器。整合阶段测试用户登录功能,确保前后端交互正常。

到了这里,关于Spring Boot 3 + Vue 3实战:实现用户登录功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring boot3登录开发-微信小程序用户登录设计与实现

      ⛰️个人主页:     蒾酒 🔥系列专栏:《spring boot实战》 🌊山高路远,行路漫漫,终有归途 目录 写在前面 登录流程 流程解析 具体实现 相关代码 说明 服务端 小程序端 写在最后 本文介绍了springboot开发微信小程序后端服务中,用户登录功能的设计与实现,坚持看完相信

    2024年03月18日
    浏览(46)
  • Android前端+Spring Boot后端 登录功能实现

    创建项目后,自己添加包,框架如下   userController里的一些内容,只供参考,代码不全,无法实现 数据库是直接在社区版IDEA里连接Mysql,在控制台端创建的数据库和user表,用于数据交互。 Activity包里是Activity Java类,主要响应layout包里activity_login.xml等页面布局内的按钮响应 a

    2024年02月12日
    浏览(53)
  • 【项目实战】一、Spring boot整合JWT、Vue案例展示用户鉴权

    【项目实战】Spring boot整合JWT、Vue案例展示用户鉴权 【微服务实战】JWT

    2024年02月09日
    浏览(36)
  • Spring Boot 实现审核功能,实战来了!

    1、普通 方案 :经办时入A表,审核后从A表读取数据,然后操作目标B表; 优势 :思路简单 劣势 :对后端功能实行高度的嵌入;审核功能数据操作不统一 2、弹框式 方案 :前台实现,操作时判断是否需要权限控制,如果需要,则弹出框,由审核人员进行审核,审核通过后,

    2024年02月08日
    浏览(32)
  • spring boot中常用的安全框架 Security框架 利用Security框架实现用户登录验证token和用户授权(接口权限控制)

    spring boot中常用的安全框架 Security 和 Shiro 框架 Security 两大核心功能 认证 和 授权 重量级 Shiro 轻量级框架 不限于web 开发 在不使用安全框架的时候 一般我们利用过滤器和 aop自己实现 权限验证 用户登录 Security 实现逻辑 输入用户名和密码 提交 把提交用户名和密码封装对象

    2024年02月06日
    浏览(39)
  • Spring Boot + Vue的网上商城之springsecurity+jwt+redis实现用户权限认证实现

    在网上商城项目中,用户的安全性是非常重要的。为了实现用户权限认证和安全校验,我们可以使用Spring Security、JWT和Redis来实现。本篇博客将详细介绍后端和前台的实现过程,并提供相应的代码案例。 当用户点击登录按钮时,前端发送一个POST请求到后端的登录接口,传递用

    2024年02月07日
    浏览(41)
  • Spring Boot + Vue的网上商城之基于用户的协同过滤的商品推荐实现

    协同过滤算法设计思路 构建用户-商品评分矩阵:将用户的购买行为和评价记录转化为一个用户-商品评分矩阵,矩阵中的每个元素表示用户对商品的评分。 计算用户之间的相似度:通过计算用户之间的相似度,找出与目标用户相似的其他用户。 预测目标用户对未购买商品的

    2024年02月08日
    浏览(31)
  • 【Spring Boot】社交网站中验证用户登录的checkUser方法

    这段代码是UserService类中的checkUser方法,用于验证用户登录。具体解释如下: 方法签名:public boolean checkUser(User user) 参数:User user,表示用户实体对象,包含用户名和密码 返回值:boolean类型,表示验证结果,true表示验证通过,false表示验证失败 逻辑:首先根据用户输入的用

    2024年02月11日
    浏览(29)
  • Redis实战 | 使用Redis 的有序集合(Sorted Set)实现排行榜功能,和Spring Boot集成

    专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https://blog.csdn.net/superdangbo/category_9271502.html tensorflow专栏:https://blog.csdn.net/superdangbo/category_869

    2024年02月05日
    浏览(40)
  • Spring Boot快速搭建一个简易商城项目【完成登录功能且优化】

    未优化做简单的判断: 优化:返回的是json的格式 GlobalExceptionHandler 这里为啥要写这两个类: 理解:编写 GlobalExceptionHandler 类可以集中处理应用程序中的各种异常,提高代码的可维护性,同时简化了代码 实体:使用注解 抛一个异常: 报错信息: 这个是时候错误已经该变:

    2024年01月22日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包