Vue3前端 .NET 后端接口【前后端分离】 觉得不错就点个赞吧
文章目录
1.前端创建Vue3项目👷
1.Win+R cmd Enter 选择一个创建一个存放项目的文件夹使用npm命令创建项目进行配置
npm create vue@latest
2.项目依赖:
Vue3+Vite+TypeScript+JSX+Vue-Router+Pinia+Vitest+Cypress+Eslint+Prettier+Vue DevTools
3.命令如图依次执行
完成时窗口显示 看见成功的显示心情也很愉快把!😀😀😀
引入[Element-plus](快速开始 | Element Plus (element-plus.org)) 前端框架
npm install element-puls
//在main.ts中import Element from'element-plus'import'element-plus/dist/index.css'
app.use(Element)
删除App.Vue 前端HTML页面代码 打开[Element-plus](快速开始 | Element Plus (element-plus.org)) 使用组件查看页面效果
<template>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
status-icon
:rules="rules"
label-width="auto"
class="demo-ruleForm"
>
<el-form-item label="Password" prop="pass">
<el-input v-model="ruleForm.pass" type="password" autocomplete="off" />
</el-form-item>
<el-form-item label="Confirm" prop="checkPass">
<el-input v-model="ruleForm.checkPass" type="password" autocomplete="off" />
</el-form-item>
<el-form-item label="Age" prop="age">
<el-input v-model.number="ruleForm.age" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(ruleFormRef)">Submit</el-button>
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
</el-form-item>
</el-form>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
const ruleFormRef = ref<FormInstance>()
const checkAge = (rule: any, value: any, callback: any) => {
if (!value) {
return callback(new Error('Please input the age'))
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('Please input digits'))
} else {
if (value < 18) {
callback(new Error('Age must be greater than 18'))
} else {
callback()
}
}
}, 1000)
}
const validatePass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('Please input the password'))
} else {
if (ruleForm.checkPass !== '') {
if (!ruleFormRef.value) return
ruleFormRef.value.validateField('checkPass', () => null)
}
callback()
}
}
const validatePass2 = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('Please input the password again'))
} else if (value !== ruleForm.pass) {
callback(new Error("Two inputs don't match!"))
} else {
callback()
}
}
const ruleForm = reactive({
pass: '',
checkPass: '',
age: ''
})
const rules = reactive<FormRules<typeof ruleForm>>({
pass: [{ validator: validatePass, trigger: 'blur' }],
checkPass: [{ validator: validatePass2, trigger: 'blur' }],
age: [{ validator: checkAge, trigger: 'blur' }]
})
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!')
return false
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
}
</script>
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
nav {
width: 100%;
font-size: 12px;
text-align: center;
margin-top: 2rem;
}
nav a.router-link-exact-active {
color: var(--color-text);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
}
nav a {
display: inline-block;
padding: 0 1rem;
border-left: 1px solid var(--color-border);
}
nav a:first-of-type {
border: 0;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
}
</style>
ok👌**我们可以配置自己的模板用于生成Vue基础代码 ** 设置 ->使用代码片段->创建自己的代码配置文件粘贴代码
{"vue-template3":{"prefix":"vue3","body":[// "<!--",// " *@author [前端_XXX]", // 作者名称// " *@date $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND",//当前时间// "!-->","<template>"," <div>",""," </div>","</template>","<script>","import {ref, reactive, defineComponent, Ref, onMounted} from 'vue';","export default defineComponent({"," name:'',"," setup(){"," onMounted(() => {",""," });"," return{",""," };"," }"," })","</script>","<style scoped>","","</style>"],"description":"vue-template3"},"vue-templateSetup3":{"prefix":"setup","body":["<!-- eslint-disable vue/multi-word-component-names ="," *@author [前端_XXX]",// 作者名称" *@date $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND",//当前时间"!-->","<template>"," <div></div>","</template>","<script setup lang='ts'>","import { onMounted } from 'vue';","onMounted(() => { });","</script>","<style scoped></style>"],"description":"vue-template3"},"vue-template2":{"prefix":"vue2","body":[// "<!--",// " *@author [前端_XXX]", // 作者名称// " *@date $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND",//当前时间// "!-->","<template>"," <div>",""," </div>","</template>","<script>","export default {"," data () {"," return {",""," }"," }","}","</script>","<style lang=\"scss\" scoped>","","</style>"],"description":"vue-template2"},}
使用setup+tab tab生成语法糖模板
<!-- eslint-disable vue/multi-word-component-names =
*@author [前端_XXX]
*@date 2024/04/06 19:41:20
!-->
<template>
<div></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => {})
</script>
<style scoped></style>
配置.eslintrc.cjs代码检查规则,避免代码爆红
rules:{// 去掉函数()前面的空格'space-before-function-paren':'off','no-console': process.env.NODE_ENV==='production'?'warn':'off','no-debugger': process.env.NODE_ENV==='production'?'warn':'off',// 关闭驼峰命名规则'vue/multi-word-component-names':0}
2.后端.NET 创建ASP.NET Core WebApi项目👷
Win+r cmd Enter 选择一个工作磁盘
mkdir Api
------------
cd Api
------------
dotnet new webapi -n Api //Api是项目名
------------
cd Api
------------
dotnet run
下图为Vistual Studio创建好的Api项目,注意作者这里没有取消勾选https的 不使用https 请注释掉此行****注意dotnet版本为.NET8
访问你的项目地址 http://loaclhost端口号/swaager+Enter
**在文件夹下新建解决方案文件 **
dotnet new sln -n 解决方案名称
将创建的项目加入到该解决方案当中
dotnet sln add 项目文件夹路径
3.MySql 数据库创建库与表
ok👌 下面打开MySql服务 创建数据库连接数据库
Win+R cmd Enter
--------------
net start mysql80 mysql80 为mysql服务名
-------------
mysql -u 用户名 -p
-------------
下图为登录成功
打开可视化工具 作者使用 DataGrip 进行创建表进行测试 数据库自行创建 可以手动或者代码形式
DataGrip2022破解
//创建表代码use test_db;createtable T_user(
t_Id VARCHAR(50)notnullprimarykeyCOMMENT'用户id',
t_Act VARCHAR(50)NOTNULLCOMMENT'用户账户',
t_Pwd VARCHAR(50)NOTNULLCOMMENT'用户密码',
t_IsDel smallintNOTNULLCOMMENT'是否删除',
t_State smallintNOTNULLCOMMENT'用户状态',
t_Code VARCHAR(50)NOTNULLCOMMENT'登录凭证',
t_CeTime DatetimeNOTNULLCOMMENT'创建时间',
t_Uptime DatetimeNOTNULLCOMMENT'修改时间');createtable T_user_info(
t_Id VARCHAR(50)notnullprimarykeyCOMMENT'用户信息id',
t_Uid VARCHAR(50)notnullCOMMENT'用户id,外键',
t_Name VARCHAR(50)NOTNULLCOMMENT'用户名',
t_Nick VARCHAR(50)NOTNULLCOMMENT'昵称',
t_Sex VARCHAR(50)NOTNULLCOMMENT'性别',
t_Age VARCHAR(50)NOTNULLCOMMENT'年龄',
t_Phone VARCHAR(50)NOTNULLCOMMENT'电话',
t_Address VARCHAR(50)NOTNULLCOMMENT'地址',
t_Email smallintNOTNULLCOMMENT'邮箱',
t_Birth smallintNOTNULLCOMMENT'生日',
t_Card VARCHAR(50)NOTNULLCOMMENT'身份',
t_CeTime DatetimeNOTNULLCOMMENT'创建时间',
t_Uptime DatetimeNOTNULLCOMMENT'修改时间',FOREIGNKEY(t_Uid)references T_user(t_Id))
下图为DataGrip 连接MySql 新建查询窗口 创建表代码图片
ok👌 下面咱们可以新建后台项目层级结构 编写底层创建接口,配置数据库连接,进行接口测试了
**搭建后端ASP.NET Core WebApi项目架构 **
cmd 命令
F: 跳转到磁盘 cd /work 目录 mkdir TApi 创建存放项目目录 dotnet new sln -n TApi 创建TApi解决方案 mkdir {Web,Data,Model,Common,Services,IServices,Business,IBusiness} 创建多个同级目录 在各级目录下创建对应项目 dotnet new classlib -n UI -o F:/work/TApi/Web/ dotnet new classlib -n DB -o F:/work/TApi/Data/ dotnet new classlib -n Entity -oF:/work/TApi/Model/ dotnet new classlib -n Utils -o F:/work/TApi/Common/ dotnet new classlib -n DomainCome -o F:/work/TApi/Services/ dotnet new classlib -n Domain -o F:/work/TApi/IServices/ dotnet new classlib -n LogicHandle -o F:/work/TApi/Business/ dotnet new classlib -n ILogicHandle -o F:/work/TApi/IBusiness/ 添加到解决方案 dotnet sln add F:/work/TApi/Web/UI dotnet sln add F:/work/TApi/Data/DB dotnet sln add F:/work/TApi/Model/Entity dotnet sln add F:/work/TApi/Common/Utils dotnet sln add F:/work/TApi/Services/DomainCome dotnet sln add F:/work/TApi/IServices/Domain dotnet sln add F:/work/TApi/Business/LogicHandle dotnet sln add F:/work/TApi/IBusiness/ILogicHandle 在解决方案目录下运行打开Visutal Studio devenv /run TApi.sln
运行完结构如下
添加项目之间引用关系
|- Data 添加 Common,Model引用
dotnet add ./Data/DB/DB.csproj reference ./Common/Utils/Utils.csproj ./Model/Entity/Entity.csproj
|- Services 添加 Common,Model ,IServices引用
dotnet add ./Services/DomainCome/DomainCome.csproj reference ./Common/Utils/Utils.csproj ./Model/Entity/Entity.csproj ./IServices/Domain/Domain.csproj
|- IServices 添加 Data引用
dotnet add ./IServices/Domain/Domain.csproj reference ./Data/DB/DB.csproj
|- IBusiness 添加Common,Model, Services 引用
dotnet add ./IBusiness/ILogicHandle/ILogicHandle.csproj reference ./Common/Utils/Utils.csproj ./Model/Entity/Entity.csproj ./Services/DomainCome/DomainCome.csproj
|- Business 添加IBusiness 引用
dotnet add ./Business/LogicHandle/LogicHandle.csproj reference ./IBusiness/ILogicHandle/ILogicHandle.csproj
|- UI 添加 Common,Model,Business 引用
dotnet add ./Web/UI/UI.csproj reference ./Common/Utils/Utils.csproj ./Model/Entity/Entity.csproj ./Business /LogicHandle/LogicHandle.csproj
下一步 安装EFCore,Nuget包 根据连接字符串生成实体模型到Model层
SqlServer
Microsoft.EntityFrameworkCore
Micorsoft.EntityFrameworkCore.SqlServer
Micorsoft.EntityFrameworkCore.Tools
MySQl
Microsoft.EntityFrameworkCore.Tools
MySql.EntityFrameworkCore
Pomelo.EntityFrameworkCore.MySql
Oracle
Microsoft.EntityFrameworkCore
Oracle.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
4.后端编写CURD 接口 测试
在数据层创建DbContext对象 引入EFCore资源包 重写OnConfiguring方法配置好连接字符串
编写底层类CURD方法 与 实现
IBaseServices.cs
public interface IBaseServices
{
T Find<T>(params T[] key) where T : class;
void UpdateCome<T>(T t,EntityState state) where T : class;
void UpdateCome<T>(List<T> t, EntityState state) where T : class;
void UpdateComeAsync<T>(T t, EntityState state) where T : class;
void UpdateComeAsync<T>(List<T> t, EntityState state) where T : class;
IQueryable<T> QueryCome<T>(in Expression<Func<T, bool>>[]? whereExp = null) where T : class;
IQueryable<T> QueryCome<T>(int page = 1, int limit = 10, params Expression<Func<T, bool>>[]? whereExp) where T : class;
IQueryable<T> QueryCome<T>(out int total, int page = 1, int limit = 10, params Expression<Func<T, bool>>[]? whereExp ) where T : class;
List<T> QueryCome<T, TOrder>(out int total, int page = 1, int limit = 10,bool isAsc=false, Expression<Func<T,TOrder>>? isOrder=null, params Expression<Func<T, bool>>[]? whereExp) where T : class;
}
BaseServices.cs
public class BaseServices(IServiceProvider dbContext) : IBaseServices
{
private readonly Test_dbContext _dbContext = dbContext.CreateScope().ServiceProvider.GetRequiredService<Test_dbContext>();
public T Find<T>(params T[] key) where T : class
{
throw new NotImplementedException();
}
public IQueryable<T> QueryCome<T>(in Expression<Func<T, bool>>[]? whereExp = null) where T : class
{
IQueryable<T> data= _dbContext.Set<T>();
if (whereExp != null && whereExp.Length!=0)
{
foreach (Expression<Func<T, bool>> item in whereExp)
{
data.Where(item);
}
}
return data;
}
public IQueryable<T> QueryCome<T>(int page = 1, int limit = 10, params Expression<Func<T, bool>>[]? whereExp) where T : class
{
IQueryable<T>? data = QueryCome(in whereExp);
if (page == 0 && limit == 0)
{
return data;
}
page = (page - 1) * limit;
return data.Skip(page).Take(limit);
}
public IQueryable<T> QueryCome<T>(out int total,int page = 1, int limit = 10, params Expression<Func<T, bool>>[]? whereExp) where T : class
{
IQueryable<T>? data = QueryCome(page, limit,whereExp);
total = data.Count();
return data;
}
public List<T> QueryCome<T, TOrder>(out int total, int page = 1, int limit = 10, bool isAsc = false, Expression<Func<T, TOrder>>? isOrder = null, params Expression<Func<T, bool>>[]? whereExp) where T : class
{
IQueryable<T>? data = QueryCome(out total, page, limit, whereExp);
if (isOrder != null)
{
data = isAsc == true ? data.OrderBy(isOrder) : data.OrderByDescending(isOrder);
}
return [.. data];
}
public void UpdateCome<T>(T t, EntityState state) where T : class
{
try
{
switch (state)
{
case EntityState.Added:
_dbContext.Add(t);
break;
case EntityState.Deleted:
_dbContext.Remove(t);
break;
case EntityState.Modified:
_dbContext.Update(t);
break;
default:
break;
}
_dbContext.SaveChanges();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void UpdateCome<T>(List<T> t, EntityState state) where T : class
{
try
{
switch (state)
{
case EntityState.Added:
_dbContext.AddRange(t);
break;
case EntityState.Deleted:
_dbContext.RemoveRange(t);
break;
case EntityState.Modified:
_dbContext.UpdateRange(t);
break;
default:
break;
}
_dbContext.SaveChanges();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void UpdateComeAsync<T>(T t, EntityState state) where T : class
{
try
{
switch (state)
{
case EntityState.Added:
_dbContext.AddAsync(t);
break;
case EntityState.Deleted:
_dbContext.Remove(t);
break;
case EntityState.Modified:
_dbContext.Update(t);
break;
default:
break;
}
_dbContext.SaveChanges();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void UpdateComeAsync<T>(List<T> t, EntityState state) where T : class
{
try
{
switch (state)
{
case EntityState.Added:
_dbContext.AddRangeAsync(t);
break;
case EntityState.Deleted:
_dbContext.RemoveRange(t);
break;
case EntityState.Modified:
_dbContext.UpdateRange(t);
break;
default:
break;
}
_dbContext.SaveChanges();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}
It_userServices.cs
public interface It_userServices
{
void AddUser(t_user t_User);
int AddUserlist(List<t_user> res);
List<t_user> QueryUserlist(int page = 1, int limit = 10, int total=0, bool isAsc = false);
}
t_userServices.cs
public class t_userServices : It_userServices
{
private readonly IBaseServices _baseServices;
public t_userServices(IBaseServices baseServices) {
_baseServices=baseServices;
}
public void AddUser(t_user t_User)
{
_baseServices.UpdateCome(t_User,EntityState.Added);
}
public int AddUserlist(List<t_user> res)
{
_baseServices.UpdateCome(res,EntityState.Added);
return 0;
}
public List<t_user>? QueryUserlist(int page=1, int limit=10, int total=0, bool isAsc = false)
{
List<t_user>? res = _baseServices.QueryCome<t_user, DateTime>(out total, page, limit, isAsc, d=>d.t_Uptime);
return res;
}
}
在工具层写返回接口结果的抽象类以及用于生成随机数据测试的工具类
随机数据工具类 太长了 给个外链
ApiResult.cs
public abstract class ApiResult<T>
{
public int? Code { get; set; }
public T? Data { get; set; }
public string? Message { get; set; }
public abstract ApiResult<T>? Out(T? Data, int? Code,string? msg);
}
Result.cs
public class Result<T> : ApiResult<T>
{
private Result() { }
public static readonly Result<T> result = ResultCome.Instance;
public class ResultCome {
static ResultCome()
{
}
public static Result<T> Instance
{
get {
if(result==null)
return new Result<T>();
else return result;
}
}
}
public override Result<T> Out(T? Data, int? Code=200, string? msg="")
{
switch (Code)
{
case 500:
result.Code = Code;
result.Data = Data;
result.Message = msg==""? "请求失败" : msg;
return result;
case 501:
result.Code = Code;
result.Data = Data;
result.Message = msg == "" ? "您没有权限" : msg;
return result;
default:
result.Code = Code;
result.Data = Data;
result.Message = msg == "" ? "请求成功" : msg;
return result;
}
}
}
QueryParams.cs
public class QueryParams
{
static QueryParams()
{
}
public static QueryParams queryParams=new QueryParams();
public static int Page { get; set; }
public static int Limit { get; set; }
}
由EF 生成的实体 Model 层下的t_user表映射
public class t_user
{
[Key]
public string? t_Id { get; set; }
public string? t_Act { get; set; }
public string? t_Pwd { get; set; }
public int t_IsDel { get; set; }
public int t_State { get; set; }
public string? t_Code { get; set; }
public DateTime t_CeTime { get; set; }
public DateTime t_Uptime { get; set; }
}
在Business业务层编写登录逻辑
It_userLogic.cs
public interface It_userLogic
{
Result<t_user>? Login(string username, string password);
Result<int>? AddUserList(List<t_user> t_User);
Result<List<t_user>>? QueryList(QueryParams query);
}
t_userLogic.cs
public class t_userLogic : It_userLogic
{
private readonly It_userServices _services;
public t_userLogic(It_userServices services)
{
_services = services;
}
public Result<int>? AddUserList(List<t_user> t_User)
{ if (t_User == null) {
return Result<int>.result.Out(0, 500, "请求失败");
}
_services.AddUserlist(t_User);
return Result<int>.result.Out(1);
}
/// <summary>
/// 用户登录方法
/// </summary>
/// <param name="username">用户账户</param>
/// <param name="password">用户密码</param>
/// <returns></returns>
public Result<t_user>? Login(string username, string password)
{
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) {
bool isAny = _services.QueryUserlist().Count != 0;
if (isAny) {
t_user? data = _services.QueryUserlist().Where(d => d.t_Act == username && d.t_Pwd == password).SingleOrDefault();
if (data != null) {
return Result<t_user>.result.Out(data, 200, "登录成功!");
}
return Result<t_user>.result.Out(data, 500, "账号或密码错误! 请重新填写");
}
}
return Result<t_user>.result.Out(null,500, "账号密码不能为空!s");
}
public Result<List<t_user>> QueryList(QueryParams query)
{
bool isAny = _services.QueryUserlist(QueryParams.Page, QueryParams.Limit).Count != 0;
if (isAny)
{
List<t_user>? data= _services.QueryUserlist(QueryParams.Page, QueryParams.Limit).ToList();
return Result<List<t_user>>.result.Out(data, 200);
}
return Result<List<t_user>>.result.Out(null, 500, "请求失败");
}
}
最后在页面层新建用户控制器 接受前端参数进行逻辑处理
UserController.cs
[Route("api/[controller]")]
[ApiController]
[EnableCors("Any")]
public class UserController : ControllerBase
{
private readonly It_userLogic _UserLogic;
public UserController(It_userLogic it_UserLogic)
{
_UserLogic= it_UserLogic;
}
[HttpPost("Add")]
public ActionResult Add([FromQuery] int nums)
{
List<t_user>? res = RandomTools<t_user>.RdObj(new t_user { }, nums);
Result<int>? data= _UserLogic.AddUserList(res);
return Ok(data);
}
[HttpGet("Query")]
public ActionResult Query([FromQuery] int page,int limit)
{
QueryParams.Limit = limit;
QueryParams.Page = page;
ApiResult<List<t_user>>? data = _UserLogic.QueryList(QueryParams.queryParams);
return Ok(data);
}
[HttpGet("Login")]
public ActionResult Login([FromQuery] string act,string pwd)
{
ApiResult<t_user>? data= _UserLogic.Login(act,pwd);
return Ok(data);
}
}
这里login登录接受的参数为接口路径后的参数 [FromQuery] 也就是 https://xx/xx/api?xx&xx
现在把写好的api项目接口开始执行
5.前端请求,路由,接口基础配置
用Vscode 打开之前创建好的项目 新建以下文件夹
分别 为 接口配置文件夹,测试数据mock文件夹
request请求配置文件夹,router路由配置文件夹,
store Vuex状态配置文件夹 utils工具文件夹
- 配置http
- 配置路由router
- 配置store
- 配置interface
- 配置api请求
- 配置utils
- 配置view页面
request文件夹下
http.ts 这里的请求路径为后端接口的路径
import axios from'axios'const requestInstance=axios.create({//请求路径 baseURL:"https://localhost:7243/api",//超时时间 timeout:80000})//请求头 requestInstance.defaults.headers["Content-Type"]="application/json;charset=UTF-8";//请求拦截 requestInstance.interceptors.request.use((res)=>{//做一些处理//const headers=res.headers.get('Authorization')//路由前置守卫 设置传递一些参数returnPromise.resolve(res)},(err:any)=>{returnPromise.reject(err)})//响应拦截 requestInstance.interceptors.response.use((res)=>{//做一些状态码判断returnPromise.reject(res.data)},(err:any)=>{returnPromise.reject(err)})exportdefault requestInstance
methods.ts
import requestInstance from"./http";//封装方法 路径,参数//GET 请求exportconstGET=async(url:string,params:any)=>{try{returnawait requestInstance.get(url, params).then((res)=>{return res }).catch((err)=>{return err });}catch(err){return err }}//POST 请求exportconstPOST=async(url:string,data:any)=>{try{returnawait requestInstance.post(url, data).then((res)=>{return res }).catch((err)=>{return err });;}catch(err){return err }}//PUT 请求exportconstPUT=async(url:string,data:any)=>{try{returnawait requestInstance.put(url, data).then((res)=>{return res }).catch((err)=>{return err });}catch(err){return err }}//DELETE 请求exportconstDEL=async(url:string,data:any)=>{try{returnawait requestInstance.delete(url, data).then((res)=>{return res }).catch((err)=>{return err });}catch(err){return err }}
router文件夹下
路由 index.ts
import{ createRouter, createWebHistory }from"vue-router";const router=createRouter({ history:createWebHistory(), routes:[{ path:"/", name:"home",component:()=>import("@/view/home/index.vue")},{ path:"/Login", name:"Login",component:()=>import("@/view/user/login.vue")},]})exportdefault router
routers.ts
import{ RouteRecordRaw }from'vue-router'exportconst routes:RouteRecordRaw[]=[{ path:"/", name:"home",component:()=>import("@/view/home/index.vue"), meta:{ isChecked:false, icon:""}, children:[{ path:"home/manage", name:"manage",component:()=>import("@/view/home/manage.vue"),}]},{ path:"/Login", name:"Login",component:()=>import("@/view/user/login.vue"),},{ path:"/attr", name:"attr",component:()=>import("@/view/attr/index.vue"), children:[{ path:"attr/config", name:"config",component:()=>import("@/view/attr/config.vue"),}]},]
interface文件夹下
user/userformDto.ts
typeuser_loginform={ act:string|any, pwd:string|any}typeuser_dto={ unick:string, uname:string, usex:string, uage:number, ustate:number, ucode:string, uaddress:string, ucreatetime:Date, uupdatetime:Date }exportconst user_formdata:user_loginform={ act:"", pwd:"",}exportconst user_dto:user_dto={ unick:"", uname:"", usex:"", uage:0, ustate:0, ucode:"", uaddress:"", ucreatetime:newDate(), uupdatetime:newDate()}
api接口文件夹下
user/api.ts
import{GET,POST}from"@/request/methods"//用户请求接口//登录//创建对应的接口数据 后台Entity 前台DTO对象exportconstlogin=(url:string,params?:any)=>{returnGET(url,params)}//获取用户信息exportconstGetUserInfo=(url:string,params?:any)=>{returnPOST(url,params)}//获取用户列表exportconstGetUserList=(url:string,params?:any)=>{returnGET(url,params)}
store文件夹下
index.ts
import{ createStore }from'vuex'const defaultState ={ count:0}// Create a new store instance.exportdefaultcreateStore({state(){return defaultState }, mutations:{increment(state:typeof defaultState){ state.count++}}, actions:{increment(context){ context.commit('increment')}}, getters:{double(state:typeof defaultState){return2* state.count }}})
utils文件夹下
handlerCache.ts
exportconstGetCookie=()=>{return}exportconstSetCookie=()=>{return}exportconstSetSession=()=>{return}exportconstGetSession=()=>{return}exportconstGetLocalStorage=()=>{return}exportconstSetLocalStorage=()=>{return}exportconstGetToken=()=>{return}exportconstSetToken=()=>{return}
tools.cs 这里用于生成随机数据作测试 这里给个链接
将view页面根据路由创建好后
编写简单的登录页面
login.vue
<template> <div class="Login_box"> <el-card class="Login_FormContent" shadow="hover"> <h3>Login in</h3> <div class="flex gap-4"> <div class="Combox_act"> <el-autocomplete v-model="state1" :fetch-suggestions="querySearch" clearable class="inline-input w-50" placeholder="账号:" @select="handleSelect" /> </div> <div class="Combox_pwd"> <el-autocomplete v-model="state2" :fetch-suggestions="querySearch" :trigger-on-focus="false" clearable class="inline-input w-50" placeholder=" 密码:" @select="handleSelect" /> </div> <el-button type="primary" plain @click="LoginIn">登录</el-button> </div> </el-card> </div> </template> <script type="module" lang="ts" setup> import { onMounted, ref } from 'vue' import {login} from "@/api/user/api" import { ElMessage } from 'element-plus'; interface RestaurantItem { value: string link: string } const state1 = ref('') const state2 = ref('') const restaurants = ref<RestaurantItem[]>([]) const querySearch = (queryString: string, cb: any) => { const results = queryString ? restaurants.value.filter(createFilter(queryString)) : restaurants.value // call callback function to return suggestions cb(results) } const createFilter = (queryString: string) => { return (restaurant: RestaurantItem) => { return ( restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ) } } const loadAll = () => { return [ { value: 'vue', link: 'https://github.com/vuejs/vue' }, { value: 'element', link: 'https://github.com/ElemeFE/element' }, { value: 'cooking', link: 'https://github.com/ElemeFE/cooking' }, { value: 'mint-ui', link: 'https://github.com/ElemeFE/mint-ui' }, { value: 'vuex', link: 'https://github.com/vuejs/vuex' }, { value: 'vue-router', link: 'https://github.com/vuejs/vue-router' }, { value: 'babel', link: 'https://github.com/babel/babel' }, ] } const handleSelect = (item: RestaurantItem) => { console.log(item) } //全局引入资源包 // const tools = import.meta.glob("http://sb075u42m.sabkt.gdipper.com/MyTools.ts") const LoginIn=()=>{ login("/user/login?act="+state1.value+"&pwd="+state2.value+"", { }).then((res: any)=>{ ElMessage({ type:"success", message:"操作成功!" }) console.log("数据请求:",res) }).catch((err: any)=>{ ElMessage({ type:"error", message:err }) }) // GetUserList("/user/query",{page:10,limit:5}).then((res: any)=>{ // ElMessage({ // type:"success", // message:"操作成功!" // }) // console.log("数据请求:",res) // }).catch((err: any)=>{ // ElMessage({ // type:"error", // message:err // }) // }) } onMounted(() => { restaurants.value = loadAll() }) </script> <style> .Login_box { display: flex; justify-content: center; align-items: center; } .Login_FormContent { margin: auto; height: auto; width: 280px; background-color: rgba(238, 242, 249, 0.826); } .Combox_act { margin: 15px; } .Combox_pwd { margin: 15px; } </style>
6.前端页面请求调用 后端接口Api
打开网址 根据之前配置好的打开为首页
切换地址到登录页面
输入错误密码请求f12进入页面查看控制台返回数据
断点请求调试视频如下
前后端分离请求登录断点视频
在后端接口项目挂入断点进行F5调试
打开数据库复制正确的账号密码进行请求
输入正确密码进行请求
欧克 简单的登录就实现啦 觉得对您有帮助的话就点个赞吧
版权归原作者 Awzh Circulate 所有, 如有侵权,请联系我们删除。