环境和脚手架搭建
- 安装合适版本的node.js 目前使用的是18.20.2 Node.js — Download Node.js®
- 安装解释器vscode和插件:Vue - Official、vue3-snippets-for-vscode、WindiCSS(可替换为Tailwind CSS) IntelliSense、等
- 创建vue3项目 快速上手 | Vue.js ;创建时 Vue Router 选Y
- 安装elementplus Vite安装 | Element Plus ,快速开始 | Element Plus 。推荐自动导入
- 删除项目中 .src/App.vue 原本的样式和js;引入一个elementplus 组件
<script> </script> <template> <div class="mb-4"> <el-button>Default</el-button> <el-button type="primary">Primary</el-button> <el-button type="success">Success</el-button> <el-button type="info">Info</el-button> <el-button type="warning">Warning</el-button> <el-button type="danger">Danger</el-button> </div> </template>
- 运行项目查看组件是否成功引入
- Vite 集成 | Windi CSS
- 路由配置:由于创建项目时加入了Vue Router;所以不需要手动配置了,后续有需要修改的地方可以在 src\router\index.js 中修改。
//src\router\index.js
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
//需要引入相关目录的 vue文件
component: index
},
]
})
// src\App.vue中加入路由
<template>
<router-view></router-view>
</template>
创建页面
404页面
自定义一个404页面,然后配置路由。使用带参数的动态路由匹配 | Vue Router 捕获所有路由或 404 Not found 路由
登录页面
在其他渠道抄了一段代码,忘记出处了。如有雷同请联系删除
<template>
<el-row class="min-h-screen">
<el-col :lg="16" class="left">
<div>
<div>禽兽之家</div>
<div>www.禽兽是混蛋.com</div>
</div>
</el-col>
<el-col :lg="8" class="right">
<h2 class="zftitle">欢迎回家</h2>
<div>
<span class="line"></span>
<span>账号密码登录</span>
<span class="line"></span>
</div>
<div>
<el-form :model="form" label-width="auto" style="max-width: 600px">
<el-form-item>
<el-input prefix-icon="User" v-model="form.username" placeholder="请输入账号" />
</el-form-item>
<el-form-item>
<el-input v-model="form.password" placeholder="请输入密码">
<template #prefix>
<el-icon><Lock /></el-icon>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button class="w-[300px]" round color="##337ecc" type="primary" @click="onSubmit">登 录</el-button>
</el-form-item>
</el-form>
</div>
</el-col>
</el-row>
</template>
<style>
.left {
@apply flex items-center flex-col justify-center;
background-image: url('https://p3.itc.cn/images01/20220818/69f3539c5c7a4f8591e19eee0256f7ca.jpeg');
/* 这里替换为你的图片路径 */
background-size: cover;
/* 使图片覆盖整个元素 */
background-position: center;
/* 使图片在元素中居中 */
}
/* left下级的div里的第一个div */
.left>div>div:first-child {
@apply font-extrabold text-red-100 text-5xl;
}
.left>div>div:nth-child(2){
@apply font-extrabold text-red-100;
}
.right {
@apply bg-indigo-500 flex items-center flex-col justify-center;
}
.right .zftitle {
@apply text-4xl text-red-100 font-extrabold;
}
.right>div {
@apply flex items-center justify-center my-5 text-red-100 space-x-6;
}
.right .line {
@apply h-[1px] w-17 bg-indigo-400;
}
</style>
<script setup>
import { reactive } from 'vue'
// import {Lock, User} from '@element-plus/icons-vue'
// do not use same name with ref
const form = reactive({
username: "",
password: "",
})
const onSubmit = () => {
console.log('submit!')
}
</script>
注意点:
-
@apply
指令是 Tailwind CSS 的一个功能,不使用 Tailwind CSS,你需要将@apply
替换为实际的 CSS 属性。 -
使用了elementUI,其中有Layout 布局 | Element Plus Form 表单 | Element Plus 等
-
script setup 是组合式 API 的入口,响应式 API:核心 | Vue.js
表单校验
在饿了么中找到表单校验组件,根据项目需要进行配置
注意点:
- <el-form> 组件中加入 :relus属性;form-Item 的
prop
属性设置为需要验证的特殊键值
"rules"对象的定义参考饿了么。reactive中字段最好和表单中的名字对应
<script setup>
const rules = reactive({
username: [
{ required: true, message: '请输入用户名!', trigger: 'blur' },
],
password: [
{ required: true, message: '请输入密码!', trigger: 'blur' },
{ min: 3, max: 10, message: '长度需要在3到10之间', trigger: 'blur' },
],
})
</script>
el-form-Item 中prop
需要和"rules"定义的对象一致
- 最后我希望点击登录按钮时也校验表单,那么先需要在el-form 中加上 ref 属性,然后使用ref响应式api处理
const ruleFormRef = ref(null) //使用响应式api
const onSubmit = () => {
ruleFormRef.value.validate((valid) => {
if (!valid) {
return false
}
else {
console.log("校验通过")
}
})
}
ruleFormRef.value
是 ruleFormRef
响应式引用的当前值。validate
是用 ruleFormRef.value
上的一个方法,该方法用于表单校验。
- 密码隐藏/展示插件 Input 输入框 | Element Plus
登录接口联调
后端
后端使用python fastapi写一个简单的登录接口。需要在main文件里注册路由create_login_route(app)
# E:\fastapi_tools\login.py
from fastapi import HTTPException, FastAPI
from pydantic import BaseModel
# 创建一个请求体的模型,FastAPI将期望请求体包含一个JSON对象
class LoginRequest(BaseModel):
username: str
password: str
# 创建一个简单的用户数据库(在实际应用中,你可能使用数据库查询)
users_db = {"user2": "password2"}
# 创建一个简单的依赖,用于验证用户
def authenticate_user(username: str, password: str):
if username in users_db and users_db[username] == password:
return True
else:
return False
# 定义一个函数,它接受app作为参数,并添加路由
def create_login_route(app: FastAPI):
@app.post("/login")
async def login(login_request: LoginRequest):
# 使用依赖来验证用户
if authenticate_user(login_request.username, login_request.password):
return {"message": "登录成功"}
else:
# 如果认证失败,抛出一个HTTP异常
raise HTTPException(status_code=401, detail="用户名或密码错误")
return login
前端
axios中文文档|axios中文网 | axios
先创建对象配置axios的基本参数
//src\axios.js 创建
import axios from "axios"
const service = axios.create({
baseURL:"http://127.0.0.1:8000/" // 后端接口的域名或ip端口
})
export default service
使用axios请求接口,为方便管理在src中专门创建一个api文件夹存放请求接口
// scr/api/manage.js
import axios from "../axios" //引入本地定义的axios
export function login(username, password) {
return axios.post("/longin", { username, password })
}
登录按钮中请求接口
const onSubmit = () => {
ruleFormRef.value.validate((valid) => {
if (!valid) {
return false
}
else {
login(form.username, form.password)
.then(response => { // 获取响应数据
if (response.data.message === "登录成功") {
ElMessage({
message: response.data.message,
type: 'success',
})
router.push("/"); // 内部导航
window.open('https://blog.csdn.net/weixin_51959864?spm=1000.2115.3001.5343'); // 浏览器跳外部页面
} else {
ElMessage({
message: response.data.message,
type: 'error',
})
}
})
.catch(error => { // 状态码非200时
console.log(error)
ElMessage({
message: "请求失败,请稍后再试。",
type: 'error',
})
})
}
})
}
配置 Vite | Vite,在vite.config.js的defineConfig方法中加入
// 仅作用于dev环境,主要解决跨域问题
server: {
proxy: {
// 选项写法
'/api': {
target: 'http://127.0.0.1:8000', // 后端服务器IP端口
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
}
}
最后根据接口返回信息toast用户
const onSubmit = () => {
ruleFormRef.value.validate((valid) => {
if (!valid) {
return false
}
else {
login(form.username, form.password)
.then(succ => { //获取成功的信息
console.log(succ.data.message)
ElMessage({
message: succ.data.message,
type: 'success',
})
})
.catch(erro => { //获取失败的信息
ElMessage({
message: erro.response.data.detail,
type: 'error',
})
})
}
})
}
部署
vue部署用vite打包后放到服务器上
npm run build
这里使用的是docker compose构建的容器,因为有其他项目使用所以监听了80、81两个端口
services:
nginx:
image: nginx:latest
container_name: auto_test_platform-nginx
# depends_on:
# - auto_test_plt
# ★注意:先建立目录,复制nginx.conf
volumes:
- ./django-automatic-test-platform/static:/static
- /opt/linchihome/test-tools:/test-tools
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./logs/nginx:/var/log/nginx
ports:
- 80:80
- 81:81
networks:
- default
云服务器上开放端口
nginx配置
server {
listen 81;
server_name localhost; # 域名或 IP 地址
location / {
root /test-tools; # 确保这是你的 Vue3 项目构建后的目录
try_files $uri /index.html;
}
}
前端部署完成