先看样子:

一、后端

package com.example.readinglist.cms.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.util.StringUtils;
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);}@GetMapping("findPage")public ResponseDTO findPage(Page<MyAppUser> page, MyAppUser myAppUser){IPage<MyAppUser> appUserIPage = myAppUserService.page(page,new QueryWrapper<MyAppUser>().like(!StringUtils.isEmpty(myAppUser.getUserName()),"user_name",myAppUser.getUserName()).eq(myAppUser.getAge()!=null,"age",myAppUser.getAge()).orderByDesc("create_time"));return ResponseDTO.success(appUserIPage);}@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));}}

针对分页器无效,需要加如下配置

package com.example.readinglist.config;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;/*** Mybatis Plus 配置类** @author *cruder*/
@EnableTransactionManagement
@Configuration
@MapperScan("com.example.readinglist.cms.dao.*")
public class MybatisPlusConfig {@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}
}

二、前端
信息卡片组件
UserInfo.tsx

import React, { useEffect ,useState} from 'react';
import {Modal,Toast,InputItem} from 'antd-mobile'
import style from './userinfo.less';
import {deleteById,edit} from '@/pages/index/users/service'const alert = Modal.alert;const UserInfo = (props) => {const {user} = props;const[modalVisible,setModalVisible] = useState(false);const[userInfo,setUserInfo] = useState({...user});const layout = {labelCol: { span: 6 },wrapperCol: { span: 16 },};const handleEdit = (user)=>{console.log('监听到编辑事件',user);setModalVisible(true);};const deleteHandle = (userId)=>{console.log('监听到点击删除按钮事件',userId);alert('Delete', 'Are you sure???', [{ text: 'Cancel', onPress: () => console.log('cancel') },{text: 'Ok',onPress: () =>new Promise((resolve) => {console.log('点击确认',userId);const response = deleteById({userId:userId});console.log(response);Toast.info('delete successfully', 1);setTimeout(resolve, 2000);window.location.href = '/myapp/index/users';}),},])};const onClose = async() => {const response = await edit(userInfo);console.log(response);if(response.status===1){setModalVisible(false);window.location.href = '/myapp/index/users';}else {Toast.fail('edit fail!'+response.msg,Toast.LONG)}};const handleChange = (name,val) =>{console.log('监听到输入框变化',name,val);userInfo[name]=val;};return (<div className={style.outDiv}><div><span className={style.title}>{user.userName}</span><span className={style.tags}>{user.tags}</span></div><div>年龄:{user.age}</div><div>邮箱:{user.email}</div><div>住址:{user.address}</div><button className={style.button_edit} onClick={() => {handleEdit(user);}}>编辑</button><button className={style.button_delete} onClick={()=>{deleteHandle(user.userId);}}>删除</button><Modal visible={modalVisible}transparentmaskClosable={false}title= "编辑个人信息"footer={[{ text: '确认', onPress: () => { console.log('ok');onClose(); } },{ text: '取消', onPress: () => { console.log('cancel');setModalVisible(false); } }]}><div className={style.inputDiv}><div><label>昵称</label><input defaultValue={user.userName} onChange={val => handleChange('userName',val.target.value)}/></div><div><label>年龄</label><input defaultValue={user.age} onChange={val => handleChange('age',val.target.value)}/></div><div><label>标签</label><input defaultValue={user.tags} onChange={val => handleChange('tags',val.target.value)}/></div><div><label>住址</label><input defaultValue={user.address} onChange={val => handleChange('address',val.target.value)}/></div><div><label>邮箱</label><input defaultValue={user.email} onChange={val => handleChange('email',val.target.value)}/></div></div></Modal></div>)
};export default UserInfo;

userinfo.less

.outDiv{width: 80%;border: 1px solid white;border-radius: 10px;margin: 15px auto 0;background-color: white;position: relative;padding: 10px;
}.title{font-size: large;font-weight: bolder;margin-right: 10px;color: #1d39c4;
}.outDiv div{padding-right: 50px;
}.tags{font-size: smaller;color: darkgreen;border: 1px solid darkgreen;
}.tags:hover{font-size: large;color: #d46b08;
}.button_edit{position: absolute;top: 30px;right: 10px;color: white;border: white 1px solid;padding: 2px 8px;border-radius: 5px;background-color: #0e80d2;
}.button_delete{position: absolute;top: 60px;right: 10px;color: white;padding: 2px 8px;border-radius: 5px;border: white 1px solid;background-color: orangered;
}.inputDiv{div{margin-top: 5px;input{width:80%;}label{width: 20%;color: black;margin-right: 3px;}}
}

users页
index.tsx

import {Pagination,Button,SearchBar} from 'antd-mobile'
import  {useState} from 'react';
import {connect} from 'dva';
import style from './users.less'
import {add} from './service'
import UserModal from '../../../component/UserModal/UserModal'
import UserInfo from '../../../component/UserInfo/UserInfo'const index = ({users1,dispatch}) =>{const[modalVisible,setModalVisible] = useState(false);const[record,setRecord] = useState(undefined);const[userNameDisable,setUserNameDisable] = useState(false);const array = users1.data;console.log(array);const locale = {prevText: '上一页',nextText: '下一页',};const editHandler = (record)=>{setModalVisible(true);setUserNameDisable(true);console.log(record);setRecord(record);};const addHandler = ()=>{setModalVisible(true);setUserNameDisable(false);};const deleteHandler = (userId:number)=>{dispatch({type: 'users1/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:'users1/edit',payload: values,});setModalVisible(false);}else {// dispatch({//   type:'users1/add',//   payload: values,// });const response = await add(values);if(response.status){setModalVisible(false);}dispatch({type:'users1/getPage',payload:{current:1,size:6}});}};const handlePageChange = current=>{dispatch({type:'users1/getPage',payload:{current:current,size:6}});};const handleSearch = val =>{dispatch({type:'users1/getPage',payload:{userName:val}});};return (<div><div className={style.topDiv}><Button type='primary' size='small' className={style.btn_add} onClick={()=>{addHandler();}}>添加</Button><SearchBar onSubmit={val=>handleSearch(val)}/></div><div>{array!==undefined?users1.data.records.map(item=>(<UserInfo key={item.userId} user={item}/>)):null}</div><UserModalvisible={modalVisible}okClose={okClose}cancelClose={cancelClose}record={record}onFinish = {onFinish}userNameDisable = {userNameDisable}/>{array!==undefined?<Paginationstyle={{position:'fixed',width:'100%',bottom:'0'}}total={array.pages}current={array.current}locale={locale} onChange={e=>handlePageChange(e)} />:null}</div>)
};// const mapStateToProps = ({users})=>{//   console.log(users);
//   return {//     users,
//   }
// };const mapStateToProps = ({users1})=>({users1});export default connect(mapStateToProps)(index);

model.ts

import {Reducer,Effect,Subscription} from 'umi'
import {getRemote, edit, deleteById, add, getPage} from './service'interface UserModelType{namespace: 'users1',state:{},reducers:{getList: ReducerfindPage: Reducer},effects:{getRemote: EffectgetPage: Effectedit: Effectadd: EffectdeleteById: Effect},subscriptions:{setup: Subscription;}
}const userModel:UserModelType ={namespace: 'users1',state:{},reducers:{getList(state,{payload}){return payload;},findPage(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},});},*getPage({payload: values},{put,call}){const response = yield call(getPage,values);console.log(response.data);const data = response.data;yield put({type: 'findPage',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: 'getPage',});},*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})=>{console.log(pathname,history);if(pathname==='/index/users'){dispatch({type: 'getPage',payload:{current:1,size:6}});}})}},
};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 getPage = async (page) =>{return request('/app/user/findPage',{method:'get',params:page}).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) =>{console.log('点击确认',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

.topDiv{margin: 15px auto 0;width: 80%;position: relative;.btn_add{background-color: lightgreen;width:25%;color: darkblue;font-size: larger;margin-left: 0;}
}

矬就矬在,编辑和删除的弹窗组件是放在UserInfo卡片组件里的,直接在卡片组件里面调用接口,没用到model里的接口。总之关系很乱,要单独弄一个弹窗组件并实现组件之间通信这一点实际上没搞明白。

写了一个很矬( cuó)的移动端用户管理相关推荐

  1. 最短路径 自己写的一个很简单的模板 dijkstra算法

    根据图论课本上的一个图自己写的一个最短路径的dijkstra算法 #include<stdio.h> const int m=999999999; int main() {int tu[8 ...

  2. 介绍一个很全面源码关于android 账户管理的源码

    基础开始--这些是主要部分: 认证令牌(auth- Token)-服务器提供的临时访问令牌(或安全令牌).用户需要识别出这样的标记并将其附加到他发送到服务器的每个请求上.在这篇文章中,我将使用OAut ...

  3. 用python写注册登录_用Python实现web端用户登录和注册功能的教程

    用户管理是绝大部分Web网站都需要解决的问题.用户管理涉及到用户注册和登录. 用户注册相对简单,我们可以先通过API把用户注册这个功能实现了: _RE_MD5 = re.compile(r'^[0-9 ...

  4. 一个很好用的移动端Lightbox特效插件(二)

    上一篇博客本人主要是介绍了Lightbox插件的一些语法,这篇文章主要是介绍本人用Lightbox插件编写的一个实例,让大家更深入地了解这个Lightbox插件. 首先,看一下这个实例最终的效果: 接 ...

  5. 【Android进阶】如何写一个很屌的动画(3)---高仿腾讯手机管家火箭动画

    系列中其他文章: [Android进阶]如何写一个很屌的动画(1)-先实现一个简易的自定义动画框架 [Android进阶]如何写一个很屌的动画(2)-动画的好帮手们 [Android进阶]如何写一个很 ...

  6. 在linux中建立一个vim的目录,Linux学习笔记一(目录结构、Vim编辑器、用户管理)...

    1.Linux介绍 linux是一个开源.免费的操做系统,其稳定性.安全性.处理多并发已经获得 业界的承认,目前不少企业级的项目都会部署到Linux/unix系统上. Linux主要的发行版: Ubu ...

  7. 一个男生写的关于怎么追女生昨天没有说一个很关键的东西

    一个男生写的关于怎么追女生昨天没有说一个很关键的东西就是怎么认识更多的MM 的确没有开始的认识就谈不上以后的追求 我的个人体会就是网上找本校的MM聊天算一种认识更多MM的好方法 对于低年纪的同学,参加 ...

  8. python写一个很简单的Atm机系统,使用pickle模块和json模块来保存数据

    我做的是一个很简单的Atm系统,很多都没约束条件 目的: 用面向对象思维来处理 运用文件的读写 文件的读写用pickle模块和json模块来处理 pickle模块: pickle模块处理数据功能很强大 ...

  9. 随着上网次数越来越多,IE地址栏中留下大量的历史网址,感觉很不爽,于是决心写一个清除IE地址栏的应用程序,随说有“上网助手”,但它要在能上网时才起作用,我想在不能上网时来对系统进行清理,于是写了一个叫

    随着上网次数越来越多,IE地址栏中留下大量的历史网址,感觉很不爽,于是决心写一个清除IE地址栏的应用程序,随说有"上网助手",但它要在能上网时才起作用,我想在不能上网时来对系统进行 ...

  10. C语言写一个很好玩的皇帝的后宫小游戏

    C语言写一个很好玩的皇帝的后宫小游戏 前言 先演示一下 上源码 总结 前言 只是单纯喜欢C语言,闲着无事把以前学习的时候的案例编了一下,都是很基础的代码,for,swich,if这些,基础好的看完后完 ...

最新文章

  1. 实对称矩阵的性质_浅谈矩阵的相似对角化(一)
  2. Java基础:基本数据类型包装类
  3. 将网卡中断分布到多个cpu上的方法
  4. flash推荐助手怎么关掉_彻底清除“FF新推荐”“Flash助手”的弹出广告
  5. oracle java 面试题及答案_Oracle面试题及答案
  6. Python一行代码
  7. Spread for Windows Forms高级主题(4)---自定义用户交互
  8. 1、position用法技巧,2、CSS 属性 选择器,3、CSS 选择器
  9. 1010 Radix(25 分)
  10. android 系统字体无效,android内嵌H5页面,字体设置失效的问题
  11. kaggle泰坦尼克号
  12. mis是商科还是计算机专业,MIS是什么?管理信息系统MIS和计算机科学CS有什么区别?...
  13. 档案管理系统,项目总结
  14. 05.SQL Server(高级查询)
  15. 记一次iphone更换电池难以取下旧电池解决办法
  16. NCE4 L5 Youth
  17. [实变函数]3.3 可测集类
  18. 狂肝半个月-嵌入式开发学习学习路线+知识汇总
  19. [洛谷 P4084 USACO17DEC] Barn Painting G (树形dp经典)
  20. 1741: 通讯录编排

热门文章

  1. 【雷达】Tracking radar targets with multiple reflection points
  2. 在js中对HTML的radio标签和checkbox标签的选择项进行输出
  3. Linux入门命令解释(1)
  4. 将系统语言设置成英语
  5. 问题:js中怎么继承属性
  6. Chrome Firefox for Linux 直达下载链接
  7. 浅谈Empty、Nothing
  8. -seo要掌握的20条网站的准则
  9. 洛谷P1156 垃圾陷阱【线性dp】
  10. 学习笔记 : 表达式目录树相关问题参照该demo expression拼接与拆解 expression转sql...