zdppy_api+vue3实现前后端分离的登录功能

实现思路

1、准备zdppy的开发环境
2、使用amauth提供的低代码接口,直接生成login登录接口
3、使用之前开发的登录模板渲染登录界面
4、给登录按钮绑定点击事件
5、给用户名和密码的输入框双向绑定数据
6、使用axios在登录按钮点击的时候,携带用户数据发送POST登录请求
7、处理登录接口的响应

完整代码

后端代码

.env
ZDPPY_MCRUD_HOST=127.0.0.1
ZDPPY_MCRUD_PORT=3306
ZDPPY_MCRUD_USERNAME=root
ZDPPY_MCRUD_PASSWORD=zhangdapeng520
ZDPPY_MCRUD_DATABASE=zdppy_demo
main.py
import contextlibimport api
import mcrud
import amauth
import envenv.load(".env")
db = mcrud.new_env()amauth.data.init(db, is_init_role=True, is_init_auth=True)@contextlib.asynccontextmanager
async def lifespan(app):yield {"db": db}app = api.Api(routes=[api.resp.post("/login", amauth.user.login),],middleware=[api.middleware.cors(),],lifespan=lifespan,
)if __name__ == '__main__':app.run()

前端代码

package.json
{"name": "tailwindcss_demo","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite","build": "vite build","preview": "vite preview"},"dependencies": {"@ant-design/icons-vue": "^7.0.1","ant-design-vue": "^4.2.3","axios": "^1.7.2","dayjs": "^1.11.11","vue": "^3.4.29","vue-router": "^4.4.0"},"devDependencies": {"@vitejs/plugin-vue": "^5.0.5","autoprefixer": "^10.4.19","postcss": "^8.4.38","tailwindcss": "^3.4.4","vite": "^5.3.1"}
}
vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],
})
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {content: ["./src/**/*.{html,js,vue}"],theme: {extend: {},},plugins: [],
}
postcss.config.js
export default {plugins: {tailwindcss: {},autoprefixer: {},}}
index.html
<!doctype html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/vite.svg" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Vite + Vue</title></head><body><div id="app"></div><script type="module" src="/src/main.js"></script></body>
</html>
src/main.js
import {createApp} from 'vue'
import './style.css'
import 'ant-design-vue/dist/reset.css';import Antd from 'ant-design-vue';
import App from './App.vue';const app = createApp(App)
app.use(Antd)
app.mount('#app')
src/style.css
@tailwind base;
@tailwind components;
@tailwind utilities;
src/App.vue
<script setup>
import {message} from "ant-design-vue";
import {ref} from "vue";
import axios from "axios";const username = ref("")
const password = ref("")const onLoginButtonClick = () => {axios.post('http://127.0.0.1:8888/login', {username: username.value,password: password.value}).then(function (response) {message.success("login success")console.log("response=", response)const data = response.data.dataconsole.log("data=", data)console.log("token=", data.token)}).catch(function (error) {console.log(error);message.error(error)});
}
</script>
<template><section><span v-for="i in 297" :key="i"></span><div class="signin"><div class="content"><h2>用户登录</h2><div class="form"><div class="inputBox"><input type="text" v-model="username"> <i>账号</i></div><div class="inputBox"><input type="password" v-model="password"> <i>密码</i></div><div class="links"><a href="#">忘记密码</a><a href="#">注册</a></div><div class="inputBox"><input type="submit" value="立即登录" @click.prevent="onLoginButtonClick"></div></div></div></div></section>
</template>
<style scoped>
* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Quicksand', sans-serif;
}body {display: flex;justify-content: center;align-items: center;min-height: 100vh;background: #000;
}section {position: absolute;width: 100vw;height: 100vh;display: flex;justify-content: center;align-items: center;gap: 2px;flex-wrap: wrap;overflow: hidden;
}section::before {content: '';position: absolute;width: 100%;height: 100%;background: linear-gradient(#000, #0f0, #000);animation: animate 5s linear infinite;
}@keyframes animate {0% {transform: translateY(-100%);}100% {transform: translateY(100%);}
}section span {position: relative;display: block;width: calc(6.25vw - 2px);height: calc(6.25vw - 2px);background: #181818;z-index: 2;transition: 1.5s;
}section span:hover {background: #0f0;transition: 0s;
}section .signin {position: absolute;width: 400px;background: #222;z-index: 1000;display: flex;justify-content: center;align-items: center;padding: 40px;border-radius: 4px;box-shadow: 0 15px 35px rgba(0, 0, 0, 9);
}section .signin .content {position: relative;width: 100%;display: flex;justify-content: center;align-items: center;flex-direction: column;gap: 40px;
}section .signin .content h2 {font-size: 2em;color: #0f0;text-transform: uppercase;
}section .signin .content .form {width: 100%;display: flex;flex-direction: column;gap: 25px;
}section .signin .content .form .inputBox {position: relative;width: 100%;
}section .signin .content .form .inputBox input {position: relative;width: 100%;background: #333;border: none;outline: none;padding: 25px 10px 7.5px;border-radius: 4px;color: #fff;font-weight: 500;font-size: 1em;
}section .signin .content .form .inputBox i {position: absolute;left: 0;padding: 15px 10px;font-style: normal;color: #aaa;transition: 0.5s;pointer-events: none;
}.signin .content .form .inputBox input:focus ~ i,
.signin .content .form .inputBox input:valid ~ i {transform: translateY(-7.5px);font-size: 0.8em;color: #fff;
}.signin .content .form .links {position: relative;width: 100%;display: flex;justify-content: space-between;
}.signin .content .form .links a {color: #fff;text-decoration: none;
}.signin .content .form .links a:nth-child(2) {color: #0f0;font-weight: 600;
}.signin .content .form .inputBox input[type="submit"] {padding: 10px;background: #0f0;color: #000;font-weight: 600;font-size: 1.35em;letter-spacing: 0.05em;cursor: pointer;
}input[type="submit"]:active {opacity: 0.6;
}@media (max-width: 900px) {section span {width: calc(10vw - 2px);height: calc(10vw - 2px);}
}@media (max-width: 600px) {section span {width: calc(20vw - 2px);height: calc(20vw - 2px);}
}
</style>
<script setup lang="ts">
</script>

效果预览

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/38442.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PySide(PyQt)与OpenCV图像格式的相互转换

PySide和OpenCV在图像格式上的区别&#xff1a; 主要表现在图像数据的存储方式和使用场景上。以下是一些关键区别&#xff1a; 1. 数据结构 PySide: QImage 和 QPixmap 是 PySide 中常用的图像表示形式。 QImage&#xff1a;用于直接访问图像的像素数据&#xff0c;适合需要…

C++ | Leetcode C++题解之第207题课程表

题目&#xff1a; 题解&#xff1a; class Solution { private:vector<vector<int>> edges;vector<int> indeg;public:bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {edges.resize(numCourses);indeg.resize(numCo…

MyBatis(15)MyBatis 的延迟加载是如何实现

MyBatis 的延迟加载&#xff08;懒加载&#xff09;特性允许在需要使用关联对象数据时才进行加载&#xff0c;而不是在执行主查询时就加载所有相关数据。这种机制可以提高应用程序的性能&#xff0c;特别是当关联数据庞大或关联层次较深时。我们将通过以下几个方面来深入了解My…

昇思25天学习打卡营第13天|MindNLP ChatGLM-6B StreamChat

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) MindNLP ChatGLM-6B StreamChat 本案例基于MindNLP和ChatGLM-6B实现一个聊天应用。 1 环境配置 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspo…

[知识点篇]《计算机组成原理》之数据信息的表示

1、数据表示的作用 &#xff08;1&#xff09;定义&#xff1a;将数据按照某种方式组织&#xff0c;以便机器硬件能直接识别和使用。现代计算机采用二进制进行数据表示。 &#xff08;2&#xff09;数据表示考虑因素&#xff1a; 数据的类型&#xff1a; 数值/非数值、小数、…

读AI新生:破解人机共存密码笔记17不确定性和概率

1. 前向搜索 1.1. 通过前向搜索&#xff0c;通过考虑各种可能的动作序列的结果&#xff0c;来选择动作&#xff0c;是智能系统的基本能力 1.2. 如果一家卡车运输公司想要优化其100辆卡车在美国的运输&#xff0c;那么该公司可能需要考虑的状态数量将是10^700个 1.3. 几乎所有…

Linux之masscan工具安装和使用

一、masscan简介 Masscan是一款快速、高效且开源的端口扫描工具,被广泛用于网络安全领域。它的设计目标是实现极高的扫描速度,使其能够在极短的时间内扫描整个互联网的IPv4地址空间。以下是masscan的主要特性和功能: 极高的扫描速度:Masscan的设计目标是快速和灵活,它能够…

网络爬虫的特点

网络爬虫的特点 网络爬虫的特点在于其高度的自动化、灵活性和可扩展性。这些特点使得网络爬虫在互联网信息的获取、处理和分析中发挥着举足轻重的作用。 首先&#xff0c;网络爬虫的高度自动化是其最为显著的特点之一。一旦设置好爬取的目标和规则&#xff0c;爬虫便可以自动…

vue3记个坑关于router的特点

我的问题有一下几点 1. router-view 在使用name进行命名 这个命名&#xff0c;我再三确定没有命名错误的情况下。我的组件死活出不来。仔细排查了之后&#xff0c;也反复看了官方文档。终于发现 <router-view name"login"></router-view>这个是路由上的…

数据赋能(134)——开发:数据转换——技术方法、主要工具

数据类型转换&#xff1a; 数据类型转换包括自动类型转换、强制类型转换和包装类转换。自动类型转换发生在两种类型兼容且目标类型大于源类型时&#xff0c;如将整数转换为浮点数。强制类型转换则需要将范围大的数据类型转换为范围小的数据类型&#xff0c;如将浮点数转换为整数…

el-form表单中的el-upload的文件表单验证

el-form表单中的el-upload的文件表单验证 常规el-form中的表单验证&#xff1a; el-form的el-form-item中&#xff1a; <el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"100px" class"demo-ruleForm"…

uni-app的来龙去脉,技术要点及技术难点,语法结构及应用场景,其实前端也很难,顶级的前端比后端都重要,感觉第一,理性第二

Uni-App 的来龙去脉 Uni-App 是由 DCloud 推出的一款跨平台前端框架&#xff0c;用于开发一次性代码并可以同时在 iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、字节跳动小程序和 QQ 小程序等多个平台上运行的应用。Uni-App 的出现应对了移动互联网时代多平台应用…

解决Install/Remove of the Service Denied报错

1、问题概述&#xff1f; 在Windows系统中安装MySQL5.7.43的时候&#xff0c;运行mysqld install命令提示报错&#xff1a;Install/Remove of the Service Denied 意思是&#xff1a;安装/删除服务被拒绝 问题原因所在&#xff1a;就是你当前的权限不够&#xff0c;以管理员…

Linux【环境 CenOS7】部分软件安装链接整理

优质博文&#xff1a;IT-BLOG-CN 一、开启网络 【问题】&#xff1a; 刚安装完CentOS&#xff0c;当ping www.baidu.com时&#xff0c;ping不通&#xff1b; 【解决】&#xff1a; 进入cd /etc/sysconfig/network-scripts/我这里修改的是ifcfg-ens33文件&#xff0c;将ONBOOT…

p2p、分布式,区块链笔记:试用ZeroTier组网

ZeroTier 是一种用于创建和管理虚拟局域网&#xff08;Virtual Local Area Network&#xff0c;VLAN&#xff09;的软件定义网络&#xff08;SDN&#xff09;解决方案。它可以通过互联网将多个设备安全地连接在一起&#xff0c;就像它们在同一个本地网络上一样。主要开发语言为…

hadoop 3.X 分布式HA集成Kerbos(保姆级教程)

前提&#xff1a;先安装Kerbos 1、创建keytab目录 在每台机器上上提前创建好对应的kertab目录 [hadooptv3-hadoop-01 ~]$ sudo mkdir -p /BigData/run/hadoop/keytab/ [hadooptv3-hadoop-01 ~]$ sudo mkdir -p /opt/security/ [hadooptv3-hadoop-01 ~]$ sudo chown hadoop:had…

【Python从入门到进阶】59、Pandas库中Series对象的操作(二)

接上篇《58、Pandas库中Series对象的操作(一)》 上一篇我们讲解了Pandas库中Series对象的基本概念、对象创建和操作&#xff0c;本篇我们来继续学习Series对象的运算、函数应用、时间序列操作&#xff0c;以及Series的案例实践。 一、Series对象的运算 1. 数值型数据的算术运…

1、音视频解封装流程---解复用

对于一个视频文件(mp4格式/flv格式)&#xff0c;audio_pkt或者video_pkt是其最基本的数据单元&#xff0c;即视频文件是由独立的视频编码包或者音频编码包组成的。 解复用就是从视频文件中把视频包/音频包单独读取出来保存成独立文件&#xff0c;那么如何得知packet是视频包还是…

指针赋值与引用传递:C语言的基础知识与实践技巧

指针赋值与引用传递&#xff1a;C语言的基础知识与实践技巧 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; **1. **引言 在C语言中&#xff0c;指针是一种强…

Vue CLI VS Vite

Vue CLI与Vite区别&#xff1a; Vue CLI与Vite之间存在明显的区别&#xff0c;这些区别主要体现在实现原理、优化策略、开发环境速度、构建速度、依赖关系分析和插件系统等方面。以下是关于Vue CLI和Vite区别的详细分析&#xff1a; 实现原理&#xff1a; Vue CLI&#xff1a…