Umi3与Antd-Pro5中后台全栈项目实战(2)

简介: 6、弹窗表单组件pages/ListTableList/components/HandleForm.d.ts

6、弹窗表单组件

pages/ListTableList/components/HandleForm.d.ts
import React from 'react';
import { Modal } from 'antd';
import ProForm, { ProFormText, ProFormRadio } from '@ant-design/pro-form';
import { TableListItem } from '../data';
export interface FormValueType extends Partial<TableListItem> {
  username?: string;
  password?: string;
  type?: string;
  time?: string;
  frequency?: string;
}
export interface CreateFormProps {
  onCancel: (flag?: boolean, formVals?: FormValueType) => void;
  onSubmit: (values?: FormValueType) => Promise<void>;
  modalVisible: boolean;
  values: Partial<TableListItem> | null;
  isDetail?: boolean;
}
const CreateForm: React.FC<CreateFormProps> = ({
  isDetail,
  onCancel,
  modalVisible,
  values,
  onSubmit,
}) => {
  if (values?.password) values.password = '******';
  return (
    <Modal
      destroyOnClose
      title={!values ? '新建用户' : isDetail ? '用户详情' : '更新用户'}
      visible={modalVisible}
      onCancel={() => onCancel()}
      footer={null}
      width={840}
    >
      <ProForm
        initialValues={values as TableListItem}
        onFinish={async (values: Partial<TableListItem>) => {
          !isDetail && onSubmit(values);
        }}
        {...(isDetail && { submitter: false })}
      >
        <ProFormText
          rules={[{ required: true, message: '请输入用户名!' }]}
          disabled={isDetail}
          label="用户名"
          name="username"
        />
        <ProFormText
          rules={[{ required: true, message: '请输入密码!' }]}
          disabled={isDetail}
          label="密码"
          name="password"
        />
        <ProFormText
          rules={[{ required: true, message: '请输入邮箱!' }]}
          disabled={isDetail}
          label="邮箱"
          name="email"
        />
        <ProFormRadio.Group
          name="access"
          disabled={isDetail}
          label="角色"
          rules={[{ required: true, message: '请选择角色!' }]}
          options={[
            {
              label: '管理员',
              value: 'admin',
            },
            {
              label: '用户',
              value: 'user',
            },
          ]}
        />
        <ProFormText
          // rules={[{ required: true, message: '请填写头像!' }]}
          disabled={isDetail}
          label="头像"
          name="avatar"
        />
      </ProForm>
    </Modal>
  );
};
export default CreateForm;

7、登录和用户信息services

pages/services/login.ts

import { request } from 'umi';
export interface LoginParamsType {
  username: string;
  password: string;
  mobile: string;
  captcha: string;
  type: string;
}
export async function fakeAccountLogin(params: LoginParamsType) {
  return request<API.LoginStateType>('/api/user/login', {
    method: 'POST',
    data: params
  });
}
export async function getFakeCaptcha(mobile: string) {
  return request(`/api/login/captcha?mobile=${mobile}`);
}
export async function outLogin() {
  return request('/api/login/outLogin');
}

pages/services/user.ts

import { request } from 'umi';
export async function query() {
  return request<API.CurrentUser[]>('/api/users');
}
export async function queryCurrent() {
  return request<API.CurrentUser>('/api/currentUser', {
    headers: { 
      Authorization :  'Bearer ' + `${localStorage.getItem('token')}`
    }
  });
}
export async function queryNotices(): Promise<any> {
  return request<{ data: API.NoticeIconData[] }>('/api/notices');
}

2、初始化server端项目

参考链接 实现链接数据库的例子˘

0、实现的功能

  • 处理post请求(body-parser)
  • 处理跨域 (cors)
  • 处理cookie (cookie-parser)
  • 打印日志 (morgan)
  • 设置token信息,解析token信息 (jsonwebtoken)
  • 全局验证jwt  (express-jwt)
  • 实现登录返回token,全局验证token
  • 实现注册密码加密 (md5)
npm i express mongoose body-parser jsonwebtoken http-status-codes -S

1、入口文件 app.js

var createError = require("http-errors");
let express = require("express");
let bodyParser = require("body-parser");
let app = express();
var cors = require("cors");
var logger = require("morgan");
var cookieParser = require("cookie-parser");
const expressJWT = require("express-jwt");
const config = require("./config");
let { userRouter } = require("./routes/index");
// 处理post请求
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// 打印日志
app.use(logger("dev"));
// 处理跨域
app.use(cors());
// 日志
app.use(logger("dev"));
// 使用cookie
app.use(cookieParser());
// 校验token,获取headers⾥里里的Authorization的token,要写在路由加载之前,静态资源之后
app.use(
  expressJWT({
    secret: config.Secret,
    algorithms: ["HS256"],
    credentialsRequired: true,
  }).unless({
    path: ["/api/user/register", "/api/login", "/api/user/account"], //⽩白名单,除了了这⾥里里写的地址,其他的URL都需要验证
  })
);
app.use("/api", userRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
  if (err.name === "UnauthorizedError") {
    // 这个需要根据⾃自⼰己的业务逻辑来处理理
    res.status(401).send({ code: -1, msg: "token验证失败" });
  } else {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get("env") === "development" ? err : {};
    // render the error page
    res.status(err.status || 500);
    res.render("error");
  }
});
app.listen(3000, function () {
  console.log("服务在3000启动了");
});

2、开启mongodb数据库

// 没有/data/db需要创建
cd /usr/local/mongodb/bin
sudo ./mongod  -dbpath /data/db/

3、配置config.js

module.exports={
    dbUrl:'mongodb://localhost:27017/pro5App',
    screct:'pro5',
    EXPIRESD:60*60*24
}

4、路由 routes

routes/index.js

const { userRouter } = require("./user");
module.exports = {
  userRouter,
};

routers/user.js

let express = require("express");
let userRouter = express.Router();
const { UserModel } = require("../model/index");
let jwt = require("jsonwebtoken");
let config = require("../config");
const { SuccessModel, ErrorModel } = require("../utils/resModule");
// 用户注册接口
userRouter.post("/user/register", async function (req, res) {
  await UserModel.create(req.body);
  res.json(new SuccessModel("注册成功"));
});
// 登录接口
userRouter.post("/user/login", async function (req, res) {
  let { username, password } = req.body;
  let query = { username, password };
  try {
    let result = await UserModel.findOne(query);
    let resultJSON = result.toJSON();
    let token = jwt.sign(resultJSON, config.Secret,{expiresIn:config.EXPIRESD});
    res.json(new SuccessModel(token));
  } catch (error) {
    res.json(new ErrorModel("登录失败"));
  }
});
// 查询当前用户信息接口
userRouter.get("/user/currentInfo", async function (req, res) {
  let authorization = req.headers["authorization"];
  let token = authorization.split(" ")[1];
  let result = jwt.verify(token, config.Secret);
  res.json(new SuccessModel(result, "注册成功"));
});
// 查询所有用户信息
userRouter.get("/user/account", async function (req, res) {
  try {
    let result = await UserModel.find();
    res.json(new SuccessModel(result, "查询成功"));
  } catch (error) {
    res.json(new ErrorModel(error));
  }
});
// 删除用户信息
userRouter.delete("/user/account", async function (req, res) {
  let hasRes = await UserModel.findOne(req.body);
  if (hasRes) {
    let { deletedCount } = await UserModel.remove(req.body);
    if (deletedCount) {
      res.json(new SuccessModel("删除成功"));
    }
  } else {
    res.json(new ErrorModel("删除失败"));
  }
});
// 修改用户信息
userRouter.put("/user/account", async function (req, res) {
  let { nModified } = await UserModel.update(
    req.query,
    { $set: req.body },
    { multi: true }
  );
  if (nModified) {
    res.json(new SuccessModel("修改成功"));
  } else {
    res.json(new ErrorModel("修改失败"));
  }
});
module.exports = {
  userRouter,
};

5、模型model

model/index.js

const mongoose = require("mongoose");
const config = require("../config");
const { UserSchema } = require("./user");
// 注册
let connection = mongoose.createConnection(config.dbUrl, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});
// 连接数据库
const UserModel = connection.model("User", UserSchema);
module.exports = {
  UserModel,
};

model/user.js

let mongoose = require("mongoose");
const Schema = mongoose.Schema;
// 定义数据结构
let UserSchema = new Schema({
  username: { type: String },
  email: { type: String },
  password: { type: String },
  avatar: { type: String },
  access: { type: String },
});
module.exports = {
    UserSchema
};

6、工具函数utils

utils/resModule.js

class BaseModel {
    constructor(data,message) {
        if(typeof data === 'string') {
            this.message = data
            data = null
            message = null
        }
        if(data){
            this.data = data
        }
        if(message){
            this.message = message
        }
    }
}
class SuccessModel extends BaseModel {
    constructor(data,message){
        super(data,message)
        this.errno = 0
        this.code = 200
        this.type = "success"
    }
}
class ErrorModel extends BaseModel {
    constructor(data,message,code){
        super(data,message)
        this.errno = -1
        this.type = "error"
        this.code = code
    }
}
module.exports = {
    SuccessModel,
    ErrorModel
}

3、项目地址与参考链接

前端地址:rockshang.coding.net/public/reac…服务端地址:rockshang.coding.net/public/reac…umi 官网pro5参考文档:procomponents.ant.design/components/…

相关文章
|
26天前
|
前端开发 JavaScript 关系型数据库
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
这篇文章介绍了一个名为Vue3Admin的全栈后台应用,前端基于SoybeanAdmin二次开发,后端基于Nest.js。主要使用了Vue3.5、AntDesignVue、UnoCSS、Pinia等前端技术栈,以及Nest.js、PostgreSQL、Prisma等后端技术栈。文章详细描述了系统的功能设计,包括动态国际化语言配置、登录用户操作日志、用户和角色权限映射、动态路由菜单、消息公告发布及前端业务功能等。同时,也提供了项目运行所需的环境和依赖,以及如何拉取代码、安装依赖和启动项目的方法。最后,文章展示了项目的演示图,并对项目进行了总结,指出项目未经严格测试,仅供学习交流使用。
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
|
14天前
|
JavaScript 前端开发 索引
Vue3 + Vite项目实战:常见问题与解决方案全解析
Vue3 + Vite项目实战:常见问题与解决方案全解析
34 0
|
6月前
|
前端开发 NoSQL JavaScript
基于 React + Nest 全栈开发的后台系统
这篇文章介绍了一个基于React+Nest全栈开发的后台系统XmwAdmin。项目包括前端和后端技术栈,线上预览地址和登录信息。作者推荐使用pnpm包管理工具和特定的环境依赖。文章提供了项目的运行和编译代码,以及各个功能模块的介绍。还包括演示图和项目活动以及总结部分。数据库下载链接也提供了,该项目已完成后台的核心功能。
基于 React + Nest 全栈开发的后台系统
|
11月前
|
JavaScript API 开发者
零基础快速开发全栈后台管理系统(Vue3+ElementPlus+Koa2)—项目概述篇(一)
零基础快速开发全栈后台管理系统(Vue3+ElementPlus+Koa2)—项目概述篇(一)
|
Web App开发 JSON 前端开发
使用 React 和 NodeJS 创建一个全栈项目
在本文中,我将使用 React 和 NodeJS 创建一个全栈项目。介绍下如何让 Node.js 作为 web 服务器来加载静态资源,如何让 React 程序可以直接调用 Node API。
778 0
|
存储 前端开发 NoSQL
Umi3与Antd-Pro5中后台全栈项目实战(1)
0、前言 使用umi3和antd pro5从零实现全栈中后台管理系统
112 0
|
前端开发 JavaScript 小程序
前端uni-app框架之实战主要技术栈day_3
前端uni-app框架之实战主要技术栈day_3
前端uni-app框架之实战主要技术栈day_3
|
JavaScript 小程序 开发者
1.5【微信小程序全栈开发课程】安装sublime3代码编辑器以及vue插件
从第二章开始我们就要正式开始敲代码了,微信开发者工具里面的代码编辑器不太好用,我们需要自己安装一个sublime代码编辑器。
154 0
1.5【微信小程序全栈开发课程】安装sublime3代码编辑器以及vue插件
|
JavaScript 前端开发 API
「免费开源」基于Vue和Quasar的crudapi前端SPA项目实战之模块管理(十四)
通过配置的方式可以零代码实现表单管理功能,但是所有表单都没有分类,如果表单数量很多的情况下不方便查找,因此本文主要介绍表单模块管理相关内容。属于同一类型的表单可以添加到同一个模块,比如字典相关的表建立“字典”模块,用户相关的表建立“用户管理”模块,模块在首页直接展示,用户可以快速的操作对应的表单。
245 0
「免费开源」基于Vue和Quasar的crudapi前端SPA项目实战之模块管理(十四)
|
Web App开发 前端开发 JavaScript
「免费开源」基于Vue和Quasar的crudapi前端SPA项目实战之文件上传(十)
本文主要介绍文件上传相关内容。crudapi支持附件字段,表字段里面保存的是文件url字符串。附件可以通过其它文件管理系统比如阿里云的OSS进行上传,或者使用系统自带的文件管理API进行上传,包括普通文件上传和大文件切片上传两种方式。
363 0
「免费开源」基于Vue和Quasar的crudapi前端SPA项目实战之文件上传(十)