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/…