基于umi写一个用户管理CRUD
一、前端
1)目录结构
配置文件
.umirc.ts
import { defineConfig } from 'umi';
const path = require('path');
export default {// layout:{},dva: {},//约定式404404: true,base: '/myapp/',title: '我的应用',hash: true, // 清除缓存publicPath: '/myapp/',// history: {type:'hash'},nodeModulesTransform: {type: 'none',},alias: {utils: path.resolve(__dirname, 'src/utils'),},// links: [// { rel: 'icon', href: '<%= PUBLIC_PATH %>static/favico.png' },// ],// 去除配置则约定式路由// routes: [// { path: '/', component: '@/pages/index/Home' },// { path: 'myApp/register/',title:'注册', component: '@/pages/index/Register' },// { path: '/myApp/noteList',title:'记事本', component: '@/pages/page01/NoteList' },// { path: '/myApp/note',title:'记事本', component: '@/pages/page02/Note' },// { path: '/myApp/xianyu',title:'闲鱼', component: '@/pages/xianyu/Page01' },// { path: '/myApp/xianyu/goodDetail',title:'商品详情', component: '@/pages/xianyu/GoodDetail/GoodDetail' },// { path: '/myApp/xianyu/good',title:'商品详情', component: '@/pages/xianyu/GoodList/Good' },// { path: '/myApp/users',title:'用户列表', component: '@/pages/users/index' },// ],fastRefresh: {},proxy: {'/app': {target: 'http://192.168.56.1',changeOrigin: true,pathRewrite: { '^/app': '/app' },},},
};
package.json
{"private": true,"scripts": {"start": "umi dev","build": "umi build","postinstall": "umi generate tmp","prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'","test": "umi-test","test:coverage": "umi-test --coverage"},"gitHooks": {"pre-commit": "lint-staged"},"lint-staged": {"*.{js,jsx,less,md,json}": ["prettier --write"],"*.ts?(x)": ["prettier --parser=typescript --write"]},"dependencies": {"@umijs/preset-react": "1.x","antd-mobile": "latest","qs": "^6.10.1","umi": "^3.4.8"},"devDependencies": {"@types/react": "^17.0.0","@types/react-dom": "^17.0.0","@umijs/test": "^3.4.8","axios": "^0.21.1","lint-staged": "^10.0.7","prettier": "^2.2.0","react": "17.x","react-dom": "17.x","typescript": "^4.1.2","yorkie": "^2.0.0"}
}
2)弹窗组件UserModal.tsx
import React, { useEffect } from 'react';
import { Modal,Form,Input} from 'antd';const UserModal = (props) => {const [form] = Form.useForm();const {visible,onFinish,record,userNameDisable} = props;useEffect(()=>{form.setFieldsValue(record);},[props.visible]);const layout = {labelCol: { span: 6 },wrapperCol: { span: 16 },};const onOk= ()=>{form.submit();};return (<div><Modaltitle="Basic Modal"visible={visible}onOk={onOk}onCancel={props.cancelClose}forceRender><Form {...layout}name="basic"form = {form}onFinish={onFinish}><Form.Itemlabel="用户名"name="userName"><Input disabled={userNameDisable} /></Form.Item><Form.Itemlabel="密码"name="password"rules={[{ required: true, message: 'Please input your password!' }]}><Input.Password /></Form.Item><Form.Itemlabel="邮箱"name="email"rules={[{ required: true, message: 'Please input your email!' }]}><Input /></Form.Item><Form.Itemlabel="年龄"name="age"rules={[{ required: true, message: 'Please input your name!' }]}><Input /></Form.Item><Form.Itemlabel="住址"name="address"rules={[{ required: true, message: 'Please input your username!' }]}><Input /></Form.Item><Form.Itemlabel="个性标签"name="tags"rules={[{ required: true, message: 'Please input your username!' }]}><Input /></Form.Item></Form></Modal></div>)
};export default UserModal;
index.tsx
import { Table, Tag, Space, Button,Popconfirm} from 'antd';
import {useState} from 'react';
import {connect} from 'dva';
import style from './users.less'
import {add} from './service'
import UserModal from '../../component/UserModal/UserModal'const index = ({users,dispatch}) =>{const[modalVisible,setModalVisible] = useState(false);const[record,setRecord] = useState(undefined);const[userNameDisable,setUserNameDisable] = useState(false);const columns = [{title: '用户名',dataIndex: 'userName',key: 'userName',render: text => <a>{text}</a>,},{title: '年龄',dataIndex: 'age',key: 'age',},{title: '邮箱',dataIndex: 'email',key: 'email',},{title: '住址',dataIndex: 'address',key: 'address',},{title: '个性标签',key: 'tagList',dataIndex: 'tagList',render: tags => (<>{tags.map(tag => {let color = tag.length > 5 ? 'geekblue' : 'green';if (tag === 'loser') {color = 'volcano';}return (<Tag color={color} key={tag}>{tag.toUpperCase()}</Tag>);})}</>
),
},{title: '操作',key: 'action',render: (text, record) => (<Space size="middle"><a onClick={()=>{editHandler(record);}}>编辑</a><Popconfirmtitle="Are you sure delete this user?"onConfirm={() => {deleteHandler(record.userId);}}okText="Yes"cancelText="No"><a style={{color:'red'}}>删除</a></Popconfirm></Space>),},
];const editHandler = (record)=>{setModalVisible(true);setUserNameDisable(true);console.log(record);setRecord(record);};const addHandler = ()=>{setModalVisible(true);setUserNameDisable(false);};const deleteHandler = (userId:number)=>{dispatch({type: 'users/deleteById',payload: {userId,},});};const okClose = () =>{setModalVisible(false);};const cancelClose = () =>{setModalVisible(false);setRecord(undefined)};const onFinish = async values =>{if(record){values['userId'] = record.userId;dispatch({type:'users/edit',payload: values,});setModalVisible(false);}else {// dispatch({// type:'users/add',// payload: values,// });const response = await add(values);if(response.status){setModalVisible(false);}dispatch({type:'users/getRemote',});}};return (<div className={style["list-table"]}><Button style={{backgroundColor:'lightGreen'}} onClick={()=>{addHandler();}}>添加</Button><Table columns={columns}dataSource={users.data}pagination={{pageSize:8,}}rowKey="userName" /><UserModalvisible={modalVisible}okClose={okClose}cancelClose={cancelClose}record={record}onFinish = {onFinish}userNameDisable = {userNameDisable}/></div>)
};// const mapStateToProps = ({users})=>{// console.log(users);
// return {// users,
// }
// };const mapStateToProps = ({users})=>({users});export default connect(mapStateToProps)(index);
model.ts
import {Reducer,Effect,Subscription} from 'umi'
import {getRemote,edit,deleteById,add} from './service'interface UserModelType{namespace: 'users',state:{},reducers:{getList: Reducer},effects:{getRemote: Effectedit: Effectadd: EffectdeleteById: Effect},subscriptions:{setup: Subscription;}
}const userModel:UserModelType ={namespace: 'users',state:{},reducers:{getList(state,{payload}){return payload;},},effects: {*getRemote(action,{put,call}){const response = yield call(getRemote);console.log(response.data);const data = response.data;yield put({type: 'getList',payload: {data},});},*edit({payload: values},{put,call}){console.log('edit here',values);const response = yield call(edit,values);yield put({type: 'getRemote',});},*add({payload: values},{put,call}){console.log('add here',values);const response = yield call(add,values);yield put({type: 'getRemote',});},*deleteById({payload: userId},{put,call}){console.log('delete',userId);const response = yield call(deleteById,userId);yield put({type: 'getRemote',});},},subscriptions:{setup({dispatch,history}){return history.listen(({pathname})=>{if(pathname==='/users'){dispatch({type: 'getRemote'});}})}},
};export default userModel;
service.ts
import {request} from 'umi'
import {message} from 'antd'export const getRemote = async () =>{return request('/app/user/findList',{method:'get'}).then(function (response) {console.log(response);return response;}).catch(function (error) {console.log(error);});
};export const edit = async (values) =>{return request('/app/user/edit',{method:'post',data:values}).then(function (response) {if(response.status){message.success('编辑成功');}else {message.error(response.msg);}return response;}).catch(function (error) {message.error('编辑失败');console.log(error);});
};export const add = async (values) =>{return request('/app/user/add',{method:'post',data:values}).then(function (response) {if(response.status){message.success('添加成功');}else {message.error(response.msg);}return response;}).catch(function (error) {message.error('添加失败');console.log(error);});
};export const deleteById = async (userId) =>{return request('/app/user/delete',{method:'get',params:userId}).then(function (response) {message.success('删除成功');return response;}).catch(function (error) {message.error('删除失败');console.log(error);});
};
users.less
.list-table{margin: 50px auto 0;width: 80%;
}
二、后端
package com.example.readinglist.cms.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.readinglist.cms.dto.ResponseDTO;
import com.example.readinglist.cms.entity.MyAppUser;
import com.example.readinglist.cms.service.MyAppUserService;
import com.example.readinglist.util.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.validation.Valid;
import java.util.Date;
import java.util.List;/*** <p>* 用户 前端控制器* </p>** @author cruder* @since 2021-04-13*/
@RestController
@RequestMapping("/app/user")
public class MyAppUserController {@Autowiredprivate MyAppUserService myAppUserService;@GetMapping("findList")public ResponseDTO findList(MyAppUser myAppUser){List<MyAppUser> myAppUsers = myAppUserService.list(new QueryWrapper<>(myAppUser).orderByDesc("create_time"));if(ListUtils.isNotEmpty(myAppUsers)){myAppUsers.forEach(user->{user.setTagList(user.getTags().split(","));});}return ResponseDTO.success(myAppUsers);}@PostMapping("edit")public ResponseDTO edit(@Valid @RequestBody MyAppUser myAppUser){myAppUser.setUpdateTime(new Date());myAppUserService.updateById(myAppUser);return ResponseDTO.success();}@PostMapping("add")public ResponseDTO add(@RequestBody MyAppUser myAppUser){MyAppUser one = myAppUserService.getOne(new QueryWrapper<MyAppUser>().eq("user_name", myAppUser.getUserName()));if(one!=null){return ResponseDTO.failed("此用户名此存在!");}myAppUser.setCreateTime(new Date());myAppUserService.save(myAppUser);return ResponseDTO.success();}@GetMapping("delete")public ResponseDTO delete(@RequestParam Integer userId){return ResponseDTO.success(myAppUserService.removeById(userId));}}
三、实现效果
四、参考
https://www.bilibili.com/video/BV1qz411z7s3?p=16
五、部署
npm run build 打包生成的文件夹dist上传到nginx的html文件夹下,将dist改为myapp
nginx 配置
server {listen 80;server_name localhost;#charset koi8-r;#access_log logs/host.access.log main;location ~^/app/{proxy_pass http://localhost:8080;}location ^~ /myapp/{root html;try_files $uri /myapp/index.html;index index.html index.htm;}}
配置好后,浏览器输入http://localhost/myapp/users既能访问,localhost是你的nginx的所在主机地址
基于umi写一个用户管理CRUD相关推荐
- 通过一个用户管理实例学习路由react-router-dom知识
我们通过一个用户管理实例来学习react-router-dom 这个实例包括9个小组件 App.js 引入组件 Home.js 首页组件 User.js 用户管理组件 - UserList.js 用 ...
- 【vite+vue3.0】基于vite写一个将md文件渲染为js文件的插件
基于vite写一个将md文件渲染为js文件的插件 前言 尤大是这么描述 Vite 的: 「一个基于浏览器原生 ES imports 的开发服务器. 利用浏览器去解析 imports,在服务器端按需编译 ...
- python kivy显示图片_python基于Kivy写一个图形桌面时钟程序代码示例
本篇文章小编给大家分享一下python基于Kivy写一个图形桌面时钟程序代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. Kivy 是一个开源的 ...
- python时钟程序的设计总结_python基于Kivy写一个图形桌面时钟程序
kivy 是一个开源的 python 第三方库,可以用来快速开发应用程序. 它有如下三个特点: 跨平台 kivy 编写的程序可在 linux,windows,os x,android,ios 和 ra ...
- 基于bootstrap实现简单用户管理功能
基于bootstrap实现简单用户管理功能,包括增删改以及列表分页展示功能. 1.web.xml配置servlet映射: <servlet><servlet-name>User ...
- java写一个登录系统_用java写一个用户登陆界面
一.课堂测试源代码及其结果截图 用java的swing写一个用户登录界面,采用网格布局.源代码如下: /** * */ package LiuLijia; import java.awt.CardLa ...
- 【Linux服务器开发系列】手写一个用户态网络协议栈,瞬间提升你网络功底丨netmap/dpdk的实现
手写一个用户态网络协议栈,瞬间提升你网络功底 1. 网卡基础架构 2. netmap/dpdk的实现 3. 网络协议栈实战 [Linux服务器开发系列]手写一个用户态网络协议栈,瞬间提升你网络功底丨n ...
- python开发桌面时钟_python基于Kivy写一个图形桌面时钟程序
Kivy 是一个开源的 Python 第三方库,可以用来快速开发应用程序. 它有如下三个特点: 跨平台 Kivy 编写的程序可在 Linux,Windows,OS X,Android,iOS 和 Ra ...
- 自动化测试(二)如何用python写一个用户登陆功能
需求信息: 写一个判断登录的程序: 输入: username password 最大错误次数是3次,输入3次都没有登录成功,提示错误次数达到上限 需要判断输入是否为空,什么也不输入,输入一个空格.n个 ...
- 如何基于Python写一个TCP反向连接后门
0x0 介绍 在Linux系统做未授权测试,我们须准备一个安全的渗透环境,通常第一件事就是安装虚拟机.且在攻击阶段中还需要对受害系统进行控制.常见的后门大多数是利用Metasploit生成,而目前反病 ...
最新文章
- java写exe程序实例,java实现可安装的exe程序实例详解
- 快手刘霁:AI基础能力决定每个公司AI的迭代和落地效率丨MEET2020
- java知识理论_JAVA理论知识 - OSC_rnoszD的个人空间 - OSCHINA - 中文开源技术交流社区...
- 不管马斯克怎么说,中国智能汽车激光雷达军备竞赛已经开始
- JSP中文乱码问题解决方案
- Excel绘制甘特图
- 在windows上linux命令行,如何在Windows中通过Cygwin来使用Linux命令行
- Object_id用法
- eclipse编译hadoop插件
- Day 02 第二天课时总结
- 中科院C语言应聘机试编程题6,中科院计算所保研笔试+机试+面试经验分享
- JS闭包—你不知道的JavaScript上卷读书笔记(二)
- 微软:“不好意思,我们还不够Cool,不能运行”
- Acrobat DC安装教程
- mysql报错1194_ERROR 1194 (HY000): Table 't1' is marked as crashed and should be repaired
- 如何使用微PE工具箱制作U盘PE
- 无WiFi 条件下如何使用Xshell 串口访问树莓派终端
- 工控系统 SCADA(监控和数据采集)系统简介
- 标贝科技|AI企业级应用榜单发布,百度、讯飞、标贝科技等50家产品上榜
- jQuery高亮显示