Dva员工增删改查Demo实现-优化

Dva员工增删改查Demo实现-优化

(后台&)

后台&

springBoot连接数据库,springBoot配置mybatis,springBoot整合日志,开启swagger

##数据源地址
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:postgresql://127.0.0.1:5432/postgres
    username: postgres
    password: 123456
    driverClassName: org.postgresql.Driver
    initialSize: 1
    maxActive: 20
    maxWait: 60000
  application:
    name: demo-service

##启用Mybatis
orm:
  mybatis:
    only: true

#mybatis
mybatis-plus:
  mapper-locations: classpath:/mapper/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.huawei.model
  global-config:
    #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
    id-type: 2
    #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
    field-strategy: 2
    #驼峰下划线转换
    db-column-underline: true
    #刷新mapper 调试神器
    refresh-mapper: true
    #数据库大写下划线转换
    #capital-mode: true
    #序列接口实现类配置
    #key-generator: com.baomidou.springboot.xxx
    #逻辑删除配置
    #logic-delete-value: 0
    #logic-not-delete-value: 1
    #自定义填充策略接口实现
    #meta-object-handler: com.baomidou.springboot.xxx
    #自定义SQL注入器
    #sql-injector: com.baomidou.springboot.xxx
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false

## 服务器端口,自行设置
server:
  port: 1111

## 服务注册中心地址
eureka:
  instance:
      status-page-url-path: /swagger-ui.html

## 日志
logging:
  config: classpath:logback.xml
  level:
    root: debug

platform:
  url: http://10.0.7.128:8080
##swagger配置
swagger:
  ##是否开启swagger文档
  enable: true
  ##网关
  host: 10.0.7.128:8080
  ##接口包(多个用,隔开)
  basePackage: com.huawei.controller
  ##文档标题
  title: 示例
  ##文档描述
  description: 变更管理的功能
  ##文档版本
  version: 1.0

logback.xml

<configuration>
    <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,,,, -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d %p (%file:%line\)- %m%n</pattern>
            <charset>UTF8</charset>
        </encoder>
    </appender>
    <appender name="basedatalog"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>basedata_log/basedata.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>basedata_log/basedata.log.%d.%i</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>64 MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>
                %d %p (%file:%line\)- %m%n
            </pattern>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
    <logger name="com.szewec" level="DEBUG">
        <appender-ref ref="basedatalog"/>
    </logger>
</configuration>

@MapperScan扫描接口

package com.huawei;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@SpringBootApplication
@RestController
@MapperScan("com.huawei.**.mapper")
public class ServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
    }

    @RequestMapping("/index")
    String index(){
    	return "Hello Basedata";
    }
}

Restful接口API,swagger使用指南,返回状态类型数据responseUtil

package com.huawei.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huawei.common.util.KeyUtil;
import com.huawei.common.util.PageUtil;
import com.huawei.common.util.RequestMessage;
import com.huawei.common.util.ResponseUtil;
import com.huawei.model.vo.PageBean;
import com.huawei.model.vo.Puser;
import com.huawei.model.vo.PuserVo;
import com.huawei.service.PuserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@RestController
@EnableSwagger2
@Api(value = "用户Controller", tags = { "用户访问接口" })
@RequestMapping("/api")
public class PuserController {

    @Resource
    private PuserService puserService;

    @ApiOperation(value = "测试接口")
    @RequestMapping("/users/test")
    public PageBean<Puser> getParamsTest(HttpServletRequest request) throws IOException {
        String field = request.getParameter("field");
        String keyword = request.getParameter("keyword");
        ObjectMapper mapper = new ObjectMapper();
        String s = "{\"total\":3,\"current\":1,\"list\":[{\"id\":1,\"name\":\"张三\",\"age\":23,\"sex\":\"女\",\"address\":\"成都\"},{\"id\":2,\"name\":\"李四\",\"age\":24,\"sex\":\"男\",\"address\":\"杭州\"},{\"id\":3,\"name\":\"王五\",\"age\":25,\"sex\":\"男\",\"address\":\"上海\"}]}";
        if(StringUtils.isNotBlank(field)){
             s = "{\"total\":3,\"current\":1,\"list\":[{\"id\":1,\"name\":\"张三111111\",\"age\":23,\"sex\":\"女\",\"address\":\"成都\"},{\"id\":2,\"name\":\"李四\",\"age\":24,\"sex\":\"男\",\"address\":\"杭州\"},{\"id\":3,\"name\":\"王五\",\"age\":25,\"sex\":\"男\",\"address\":\"上海\"}]}";
        }
        return mapper.readValue(s,new TypeReference<PageBean<Puser>>(){});
    }

    @ApiOperation(value = "用户查询接口")
    @PostMapping(value = {"/users/query","/users/query/{current}"})
    public Object usersFuzzyQuery(@PathVariable(required = false) String current,@RequestBody PuserVo puserVo) {
        Puser puser = new Puser();
        String field = puserVo.getField();
        String keyword = puserVo.getKeyword();
        if(StringUtils.isBlank(current)||"undefined".equals(current)){
            current="1";
        }
        if(StringUtils.isNotBlank(field)&&StringUtils.isNotBlank(keyword)){
            if("name".equals(field)){
                puser.setName(keyword);
            }
            if("address".equals(field)){
                puser.setAddress(keyword);
            }
        }
        PageUtil<Puser> result;
        try {
            result = puserService.usersFuzzyQuery(puser, Integer.valueOf(current));
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseUtil.failedResponse("查询异常",e.getMessage());
        }
        return  ResponseUtil.successListResponse(result);
    }

    @ApiOperation(value = "创建用户接口")
    @PostMapping("/users/create")
    public RequestMessage createUser(@ApiParam("用户实体对象")@RequestBody Puser puser) {
        int fid = KeyUtil.genUniqueKey();
        puser.setId(fid);
        try {
            puserService.addUsers(puser);
        } catch (Exception e) {
            return ResponseUtil.failedResponse("创建异常", e.getMessage());
        }
        return ResponseUtil.successResponse("创建成功");
    }

    @ApiOperation(value = "修改用户接口")
    @PutMapping("/users/update")
    public RequestMessage updateUser(@ApiParam("用户实体对象")@RequestBody Puser puser) {
        try {
            puserService.updateUser(puser);
        } catch (Exception e) {
            return ResponseUtil.failedResponse("修改异常", e.getMessage());
        }
        return ResponseUtil.successResponse("修改成功");
    }

    @ApiOperation(value = "删除用户接口")
    @ApiImplicitParam(name = "ids", value = "要删除用户的id", dataType = "String", paramType = "path", required = true)
    @DeleteMapping("/users/delete/{ids}")
    public RequestMessage deleteUsers(@PathVariable("ids") String ids) {
        if(ids != null){
            if(ids.contains(",")){
                String[] arrayIds = ids.split(",");
                List<Integer> idList = new ArrayList<>();
                for(String id:arrayIds){
                    idList.add(Integer.valueOf(id));
                }
                try {
                    puserService.deleteBatchUsers(idList);
                } catch (Exception e) {
                    return ResponseUtil.failedResponse("删除异常", e.getMessage());
                }
            }else{
                try {
                    puserService.deleteUser(Integer.valueOf(ids));
                } catch (Exception e) {
                    return ResponseUtil.failedResponse("删除异常", e.getMessage());
                }
            }
        }
        return ResponseUtil.successResponse("删除成功");
    }
}
package com.huawei.common.util;

public class RequestMessage {
	/* 服务器成功返回用户请求数据的状态码 */
	public static String SUCCESS_GETS_CODE = "200";
	/* 服务器成功返回用户请求数据的提示信息 */
	public static String SUCCESS_GETS_MSG = "ok";
	
	/* 新建或修改数据成功返回状态码 */
	public static String SUCCESS_POSTS_CODE = "201";
	/* 新建或修改数据成功返回提示信息 */
	public static String SUCCESS_POSTS_MSG = "ok";
	
	/* 请求进入后台排队(异步请求)成功状态码 */
	public static String SUCCESS_ACCEPTED_CODE = "202";
	/* 请求进入后台排队(异步请求)成功提示信息 */
	public static String SUCCESS_ACCEPTED_MSG = "Accepted";
	
	/* 删除数据成功返回状态码 */
	public static String SUCCESS_DELETES_CODE = "204";
	/* 删除数据成功返回提示信息 */
	public static String SUCCESS_DELETES_MSG = "ok";
	
	/* 服务器发生错误状态码 */
	public static String ERROR_CODE = "500";
	/* 服务器发生错误提示信息 */
	public static String ERROR_MSG = "error";
	
	/* 状态码 */
	private String code;
	/* 提示信息 */
	private String message;
	/* 服务器异常信息 */
	private String error;
	/* 成功返回的数据 */
	private Object data;

	
	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
	

	public String getError() {
		return error;
	}

	public void setError(String error) {
		this.error = error;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
	
	
}
package com.huawei.common.util;

import java.util.List;


/**
 * 接口响应数据封装工具类
 * @author zhujindan
 *
 */
public class ResponseUtil {
	/**
	 * 操作成功,返回没有分页的列表
	 * @param records
	 * @return
	 */
    public static RequestMessage successListResponse(List records) {
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.SUCCESS_GETS_CODE);
		message.setMessage(RequestMessage.SUCCESS_GETS_MSG);
        message.setData(records);
        return message;
    }
    /**
     * 操作成功,返回有分页的列表
     * @param <T>
     * @return
     */
    public static <T> PageInfo<T> successListResponse(PageInfo<T> page) {
		page.setCode(RequestMessage.SUCCESS_GETS_CODE);
		page.setMessage(RequestMessage.SUCCESS_GETS_MSG);
        return page;
    }

	/**
	 * 操作成功,返回有分页的列表
	 * @param <T>
	 * @return
	 */
	public static <T> PageUtil<T> successListResponse(PageUtil<T> page) {
		page.setCode(RequestMessage.SUCCESS_GETS_CODE);
		page.setMessage(RequestMessage.SUCCESS_GETS_MSG);
		return page;
	}

    /**
     * 操作成功,返回单个对象
     * @param obj
     * @return
     */
    public static RequestMessage successObjectResponse(Object obj){
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.SUCCESS_GETS_CODE);
		message.setMessage(RequestMessage.SUCCESS_GETS_MSG);
		message.setData(obj);
        return message;
    }
    /**
     * 操作成功,只返回结果,没有记录
     * @return
     */
    public static RequestMessage successResponse(String msg) {
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.SUCCESS_GETS_CODE);
    	if(null == msg || "".equals(msg)){
    		message.setMessage(RequestMessage.SUCCESS_GETS_CODE);
    	}else{
    		message.setMessage(msg);
    	}
        return message;
    }
    
    /**
     * 操作成功,只返回结果,没有记录(查询数据)
     * @return
     */
    public static RequestMessage successResponseGets(String msg) {
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.SUCCESS_GETS_CODE);
    	if(null == msg || "".equals(msg)){
    		message.setMessage(RequestMessage.SUCCESS_GETS_CODE);
    	}else{
    		message.setMessage(msg);
    	}
        return message;
    }
    
    /**
     * 操作成功,只返回结果,没有记录(新建或修改)
     * @return
     */
    public static RequestMessage successResponsePosts(String msg) {
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.SUCCESS_POSTS_CODE);
    	if(null == msg || "".equals(msg)){
    		message.setMessage(RequestMessage.SUCCESS_POSTS_MSG);
    	}else{
    		message.setMessage(msg);
    	}
        return message;
    }
    
    /**
     * 操作成功,只返回结果,没有记录(删除)
     * @return
     */
    public static RequestMessage successResponseDelete(String msg) {
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.SUCCESS_DELETES_CODE);
    	if(null == msg || "".equals(msg)){
    		message.setMessage(RequestMessage.SUCCESS_DELETES_MSG);
    	}else{
    		message.setMessage(msg);
    	}
        return message;
    }
    
    
    /**
     * 操作失败,返回错误描述
     * @param msg
     * @return
     */
    public static RequestMessage failedResponse(String msg,String error) {
    	RequestMessage message = new RequestMessage();
    	message.setCode(RequestMessage.ERROR_CODE);
    	if(null == msg || "".equals(msg)){
    		message.setMessage(RequestMessage.ERROR_MSG);
    	}else{
    		message.setMessage(msg);
    	}
    	message.setError(error);
        return message;
    }
    

}

后台cors跨域处理

package com.huawei.common.util;

import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {

    @Bean
    public RemoteIpFilter remoteIpFilter(){
        return new RemoteIpFilter();
    }

    @Bean
    public CorsFilter corsFilter(){
        // SpringMvc 提供了 CorsFilter 过滤器

        // 初始化cors配置对象
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许跨域的域名,如果要携带cookie,不要写*,*:代表所有域名都可以跨域访问
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);  // 设置允许携带cookie
        corsConfiguration.addAllowedMethod("*"); // 代表所有的请求方法:GET POST PUT DELETE...
        corsConfiguration.addAllowedHeader("*"); // 允许携带任何头信息

        //初始化cors配置源对象
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);

        // 返回corsFilter实例,参数:cors配置源对象
        return new CorsFilter(corsConfigurationSource);
    }

    @Bean
    public FilterRegistrationBean testFilterRegistration(){
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new MyFilter());
        registration.addUrlPatterns("/*");
        registration.addInitParameter("paramName","paramValue");
        registration.setName("MyFilter");
        registration.setOrder(1);
        return registration;
    }

    public class MyFilter implements Filter{
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {

        }

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

            HttpServletResponse res = (HttpServletResponse) servletResponse;
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            String origin = req.getHeader("Origin");
            if (!org.springframework.util.StringUtils.isEmpty(origin)) {
                //带cookie的时候,origin必须是全匹配,不能使用*
                res.addHeader("Access-Control-Allow-Origin", origin);
            }
            res.addHeader("Access-Control-Allow-Methods", "*");
            String headers = req.getHeader("Access-Control-Request-Headers");
            // 支持所有自定义头
            if (!org.springframework.util.StringUtils.isEmpty(headers)) {
                res.addHeader("Access-Control-Allow-Headers", headers);
            }
            res.addHeader("Access-Control-Max-Age", "3600");
            // enable cookie
            res.addHeader("Access-Control-Allow-Credentials", "true");
            filterChain.doFilter(req, res);
        }

        @Override
        public void destroy() {
            Map map = new HashMap();
        }
    }

}

mybatis的分页处理,mybatis接口接受多个参数,resultMap,mybatisPlus模糊查询使用,@Service,@Repository

package com.huawei.common.util;

import java.util.List;

public class PageUtil<T> {
    private int currentPageNum; //当前要看哪一页

    private int pageSize=10;//每页显示的条数

    private int totalSize;//总记录条数

    private int startIndex;//查询开始记录的索引 limit ? ?

    private int totalPageNum;//总页数

    private int prePageNum;//上一页

    private int nextPageNum;//下一页

    private List<T>  records;//当前页的记录集

    private List<T> totalRecords;//所有页的记录集

    //用于显示页面上的导航的页号  用户可自定义

    private int startPageNum;

    private int endPageNum;

    private String url;

    /* 状态 */
    private String code;

    /* 返回信息描述 */
    private String message;

    //使用构造方法,传递必要的两个参数.第一个是页码,第二个总记录条数
    public PageUtil(int currentPageNum,int totalSize)
    {
        this.currentPageNum=currentPageNum;
        this.totalSize=totalSize;
        //计算开始记录索引
        startIndex=(currentPageNum-1)*pageSize;
        //计算总页数
        totalPageNum=totalSize%pageSize==0?totalSize/pageSize:totalSize/pageSize+1;
        //计算开始和结束页号  这个根据自身可设计
        if(totalPageNum>9)
        {
            startPageNum=currentPageNum-4;
            endPageNum=currentPageNum+4;

            if(startPageNum<1)
            {
                startPageNum=1;
                endPageNum=startPageNum+8;
            }
            if(endPageNum>totalPageNum)
            {
                endPageNum=totalPageNum;
                startPageNum=endPageNum-8;
            }

        }
        else
        {
            startPageNum=1;
            endPageNum=totalPageNum;

        }


    }


    public int getStartPageNum() {
        return startPageNum;
    }


    public void setStartPageNum(int startPageNum) {
        this.startPageNum = startPageNum;
    }


    public int getEndPageNum() {
        return endPageNum;
    }


    public void setEndPageNum(int endPageNum) {
        this.endPageNum = endPageNum;
    }


    public int getPrePageNum() {
        prePageNum=currentPageNum-1;

        if(prePageNum<=0)
        {
            prePageNum=1;
        }
        return prePageNum;
    }

    public int getNextPageNum() {

        nextPageNum=currentPageNum+1;

        if(nextPageNum>totalPageNum)
        {
            nextPageNum=totalPageNum;
        }
        return nextPageNum;
    }

    public int getCurrentPageNum() {
        return currentPageNum;
    }

    public void setCurrentPageNum(int currentPageNum) {
        this.currentPageNum = currentPageNum;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalSize() {
        return totalSize;
    }

    public void setTotalSize(int totalSize) {
        this.totalSize = totalSize;
    }

    public int getStartIndex() {
        return startIndex;
    }

    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    public int getTotalPageNum() {
        return totalPageNum;
    }

    public void setTotalPageNum(int totalPageNum) {
        this.totalPageNum = totalPageNum;
    }

    public List  getRecords() {
        return records;
    }

    public void setRecords(List records) {
        this.records = records;
    }

    public void setPrePageNum(int prePageNum) {
        this.prePageNum = prePageNum;
    }

    public void setNextPageNum(int nextPageNum) {
        this.nextPageNum = nextPageNum;
    }


    public String getUrl() {
        return url;
    }


    public void setUrl(String url) {
        this.url = url;
    }

    public List<T> getTotalRecords() {
        return totalRecords;
    }

    public void setTotalRecords(List<T> totalRecords) {
        this.totalRecords = totalRecords;
    }

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}


package com.huawei.model.vo;

import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;

import java.io.Serializable;

@TableName("p_user")
public class Puser implements Serializable {
    @TableId("fid")
    private Integer fid;
    private String name;
    private String sex;
    private Integer age;
    private String address;

    public Puser() {
    }

    public Puser(Integer fid, String name, String sex, Integer age, String address) {
        this.fid = fid;
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public Integer getId() {
        return fid;
    }

    public String getSex() {
        return sex;
    }

    public Integer getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    public void setId(Integer fid) {
        this.fid = fid;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
package com.huawei.model.vo;

import java.io.Serializable;

public class PuserVo implements Serializable {
    private Integer fid;
    private String name;
    private String sex;
    private Integer age;
    private String address;
    private String field;
    private String keyword;

    public PuserVo(Integer fid, String name, String sex, Integer age, String address, String field, String keyword) {
        this.fid = fid;
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.address = address;
        this.field = field;
        this.keyword = keyword;
    }

    public PuserVo() {
    }

    public Integer getFid() {
        return fid;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public Integer getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    public String getField() {
        return field;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setFid(Integer fid) {
        this.fid = fid;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void setField(String field) {
        this.field = field;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }
}
package com.huawei.service;

import com.huawei.common.util.PageUtil;
import com.huawei.model.vo.Puser;
import java.util.List;
import java.util.Map;


public interface PuserService {
    //List<Puser> usersFuzzyQuery(Puser puser);
    PageUtil<Puser> usersFuzzyQuery(Puser puser, Integer current);
    void addUsers(Puser puser);
    Integer updateUser(Puser puser);
    Integer deleteUser(Integer id);
    Map<String,Object> getTotalRecords(Puser puser);
    Integer deleteBatchUsers(List<Integer> idList);
}
package com.huawei.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.huawei.common.util.PageUtil;
import com.huawei.mapper.PuserMapper;
import com.huawei.model.vo.Puser;
import com.huawei.service.PuserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PuserServiceImpl extends ServiceImpl<PuserMapper, Puser> implements PuserService {

    @Resource
    private PuserMapper puserMapper;

    @Override
    public PageUtil<Puser> usersFuzzyQuery(Puser puser, Integer currentPageNum) {
        Map<String, Object> totalData = getTotalRecords(puser);
        Integer totalCount = (Integer) totalData.get("totalCount");
        List<Puser> totalRecords = (List<Puser>) totalData.get("totalRecords");
        PageUtil<Puser> pu= new PageUtil<>(currentPageNum, totalCount);
        List<Puser> users= puserMapper.usersFuzzyQuery(puser,pu.getStartIndex());
        pu.setRecords(users);
        pu.setTotalRecords(totalRecords);
        return pu;
    }

    @Override
    public void addUsers(Puser puser) {
        this.insert(puser);
    }

    @Override
    public Integer updateUser(Puser puser) {
        return puserMapper.updateById(puser);
    }

    @Override
    public Integer deleteUser(Integer id) {
        return puserMapper.deleteById(id);
    }

    @Override
    public Map<String,Object> getTotalRecords(Puser puser) {
        EntityWrapper<Puser> wrapper = new EntityWrapper<>();
        if(StringUtils.isNotBlank(puser.getName())){
            wrapper.like("name", puser.getName());
        }
        if(StringUtils.isNotBlank(puser.getAddress())){
            wrapper.like("address", puser.getAddress());
        }
        List<Puser> totalRecords = puserMapper.selectList(wrapper);
        Integer totalCount = puserMapper.selectCount(wrapper);
        Map<String,Object> map = new HashMap<>();
        map.put("totalCount",totalCount);
        map.put("totalRecords",totalRecords);
        return map;
    }

    @Override
    public Integer deleteBatchUsers(List<Integer> idList) {
        return puserMapper.deleteBatchIds(idList);
    }
}
package com.huawei.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.huawei.model.vo.Puser;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface PuserMapper extends BaseMapper<Puser> {
    List<Puser> usersFuzzyQuery(@Param("user") Puser puser,@Param("current") Integer current);
    void addUsers(Puser puser);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.huawei.mapper.PuserMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.huawei.model.vo.Puser">
        <id column="fid" property="fid" />
        <result column="name" property="name" />
        <result column="age" property="age" />
        <result column="sex" property="sex" />
        <result column="address" property="address" />
    </resultMap>

    <select id="usersFuzzyQuery" parameterType="map" resultMap="BaseResultMap">
        SELECT * FROM p_user where 1=1
        <if test='user.name!=null and user.name!=" "'>
            AND name like CONCAT('%',#{user.name},'%')
        </if>
        <if test='user.address!=null and user.address!=" "'>
            AND address like CONCAT('%',#{user.address},'%')
        </if>
        ORDER BY name
        <if test='current!=null'>
            limit 10 OFFSET #{current}
        </if>
    </select>

</mapper>

(前台&)

前台&

dva入口文件,browserHistory,引入loading插件

import dva from 'dva';
import { browserHistory } from 'dva/router';
import createLoading from 'dva-loading';
// 1. Initialize
const app = dva({
 history:browserHistory
});

// 2. Plugins
app.use(createLoading());

// 3. Model
//app.model(require('./models/users/users'));

// 4. Router
app.router(require('./router'));

// 5. Start
app.start('#root');

index.less

全局css样式


html, body, :global(#root) {
  height: 100%;
  padding:0;
  margin:0;
}

router.js
webpack modal按需加载modal

import React from 'react';
import PropTypes from 'prop-types';
import { Router } from 'dva/router';

const registerModel = (app, model) => {
  if (!(app._models.filter(m => m.namespace === model.namespace).length === 1)) {
    app.model(model);
  }
};

const RouterConfig = ({ history, app }) => {
  /**
   * 添加路由,path是请求路基,name是名称说明
   * */
  const routes = [
    {
      path: '/',
      name: 'welcome',
      getComponent(nextState, cb) {
        require.ensure([], (require) => {
          cb(null, require('./routes/indexPage/IndexPage'));
        });
      },
    },
    {
      path: '/users',
      name: 'users',
      getComponent(nextState, cb) {
        require.ensure([], (require) => {
          registerModel(app, require('./models/users'));
          cb(null, require('./routes/users/UsersPage'));
        });
      },
    },
  ];
  return <Router history={history} routes={routes} />;
};

RouterConfig.propTypes = {
  history: PropTypes.object,
  app: PropTypes.object,
};

export default RouterConfig;

前端跨域设置,package.json

{
  "private": true,
  "scripts": {
    "start": "set BROWSER=none&&set PORT=2222&&roadhog server",
    "build": "roadhog build"
  },
  "engines": {
    "install-node": "6.9.2"
  },
  "dependencies": {
    "antd": "^2.12.3",
    "antd-iconfont": "^2.10.0",
    "axios": "^0.16.2",
    "babel-plugin-import": "^1.3.1",
    "babel-runtime": "^6.9.2",
    "dva": "^1.2.1",
    "dva-loading": "^0.2.1",
    "jquery": "^3.2.1",
    "prop-types": "^15.5.10",
    "qs": "^6.5.0",
    "react": "^15.4.0",
    "react-dom": "^15.4.0",
    "underscore": "^1.8.3"
  },
  "devDependencies": {
    "babel-eslint": "^7.1.1",
    "babel-plugin-dva-hmr": "^0.3.2",
    "babel-plugin-transform-runtime": "^6.9.0",
    "babel-plugin-module-resolver": "^2.7.1",
    "eslint": "^3.12.2",
    "eslint-config-airbnb": "^13.0.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^2.2.3",
    "eslint-plugin-react": "^6.8.0",
    "expect": "^1.20.2",
    "husky": "^0.12.0",
    "redbox-react": "^1.3.2",
    "roadhog": "^0.5.2"
  },
  "proxy": {
    "/api": {
      "target": "http://localhost:1111/",
      "changeOrigin":true
    }
  }
}

.roadhogrc

{
  "entry": "src/index.js",
  "theme": {
		"@icon-url": "'~antd-iconfont/iconfont'"
  },
  "proxy": {
    "/api": {
      "target": "http://localhost:1111/",
      "changeOrigin": true,
      "pathRewrite": { "^/api" : "" }
    }
  },
  "env": {
    "development": {
      "extraBabelPlugins": [
        "dva-hmr",
         ["module-resolver", {
            "alias": {
                "@": "./src"
            }
          }],
        "transform-runtime",
        ["import", {
            "libraryName": "antd",
            "libraryDirectory": "lib",
            "style": true
        }]
      ]
    },
    "production": {
      "extraBabelPlugins": [
        "transform-runtime",
		"dva-hmr",
		 ["module-resolver", {
			"alias": {
				"@": "./src"
			}
		  }],
         ["import", {
            "libraryName": "antd",
            "libraryDirectory": "lib",
            "style": true
        }]
      ]
    }
  }
}

dva的service数据接口,request fetch工具类,Error处理器
request.js

import fetch from 'dva/fetch';
import { notification } from 'antd';

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队(异步任务)。',
  204: '删除数据成功。',
  400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限(令牌、用户名、密码错误)。',
  403: '用户得到授权,但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除,且不会再得到的。',
  422: '当创建一个对象时,发生一个验证错误。',
  500: '服务器发生错误,请检查服务器。',
  502: '网关错误。',
  503: '服务不可用,服务器暂时过载或维护。',
  504: '网关超时。',
};

function parseJSON(response) {
  return response.json();
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response;
  }
  const errortext = codeMessage[response.status] || response.statusText;
  notification.error({
    message: `请求错误 ${response.status}: ${response.url}`,
    description: errortext,
  });
  const error = new Error(response.statusText);
  error.name = response.status;
  error.response = response;
  throw error;
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default function request(url, options) {
  const defaultOptions = {
    mode: 'cors',
  };
  const mergeOptions = {
    ...options,
    ...defaultOptions
  };
  return fetch(url, mergeOptions)
    .then(checkStatus)
    .then(parseJSON)
    .then((data) => ({ data }))
    .catch((err) => ({ err }));
}

commonConstant.js

export const url = "http://127.0.0.1:1111/api";

services/users.js

JSON.stringify,qs.stringify,设置请求头,请求体与请求方式,

import request from '../utils/request';
import qs from 'qs';
import {url} from '../utils/commonConstant';

export async function query(params) {
  let queryUrl =  `${url}/users/query`
  if(JSON.stringify(params) == "{}"){
    params = {}
  }else{
    queryUrl =  `${url}/users/query/${params.current}`
  }
  return request(queryUrl, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    },
    body: JSON.stringify(params),
  });
}

export async function create(params) {
  return request(`${url}/users/create`, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    },
    body: JSON.stringify(params),
  });
}

export async function remove(params) {
  return request(`${url}/users/delete/${params.id}`, {
    method: 'delete',
    body: qs.stringify(params),
  });
}

export async function update(params) {
  return request(`${url}/users/update`, {
    method: 'put',
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    },
    body: JSON.stringify(params),
  });
}

models模型结构,parse(payload)处理查询query中文请求参数,subscriptions监听路由,返回状态码,loading
location获取请求参数与url pathname,setState,select获取当前model的state
models/users.js

import { create, remove, update, query } from '../services/users';
import { parse } from 'qs';
import Utils from '../utils/utils'

export default {
  namespace: 'users',
  state: {
    list: [],
    totalRecords: [],
    total: null,
    field: '',           // 搜索框字段
    keyword: '',         // 搜索框输入的关键字
    loading: false,      // 控制加载状态
    current: 1,          // 当前页
    currentItem: {},     // 当前操作的用户对象
    modalVisible: false, // 弹出窗的显示状态
    modalType: 'create', // 弹出窗的类型(添加用户,编辑用户)
    pagination: {},       // 分页
    selectedRowKeys: [],  // 选择行的id
    selectedRows: [],   // 选择的行
    totalPageNum: 1,      // 总页数
    pageSize: 10,         // 每页大小
    type: ''               // 事件类型
  },
  effects: {
    *query({ payload }, { call, put }) {
      yield put({ type: 'setState', payload: { loading: true, payload, type: 'query' } });
      const { data } = yield call(query, parse(payload));
      if (data && data.code === "200") {
        yield put({
          type: 'setState',
          payload: {
            list: data.records,
            total: data.totalSize,
            current: data.currentPageNum,
            totalPageNum: data.totalPageNum,
            pageSize: data.pageSize,
            totalRecords: data.totalRecords,
            pagination: Utils.pagination(data),
            loading: false
          },
        });
      }
    },
    *create({ payload }, { select, call, put }) {
      yield put({ type: 'setState', payload: { loading: true, modalVisible: false } });
      const totalPageNum = yield select(({ users }) => users.totalPageNum);
      const { data } = yield call(create, payload);
      if (data.code === "200") {
        yield put({
          type: 'query',
          payload: { current: totalPageNum }
        })
        yield put({
          type: 'setState',
          payload: {
            field: '',
            keyword: '',
            loading: false
          },
        });
      }
    },
    *'delete'({ payload }, { call, put }) {
      yield put({ type: 'setState', payload: { loading: true, type: 'delete' } });
      const { data } = yield call(remove, { id: payload });
      if (data.code === "200") {
        yield put({
          type: 'query',
          payload: {}
        })
        yield put({
          type: 'setState',
          payload: {
            selectedRowKeys: [],
            selectedRows: []
          },
        });
      }
    },
    *update({ payload }, { select, call, put }) {
      yield put({ type: 'setState', payload: { loading: true, modalVisible: false } });
      const id = yield select(({ users }) => users.currentItem.id);
      const users = yield select(({ users }) => users.list);
      const newUser = { ...payload, id };
      const { data } = yield call(update, newUser);
      if (data.code === "200") {
        const newList = users.map(user => {
          if (user.id === id) {
            return { ...user, ...newUser };
          }
          return user;
        });
        yield put({
          type: 'setState',
          payload: { list: newList, loading: false, currentItem: {}, selectedRowKeys: [], selectedRows: [] },
        });
      }
    },
  },
  subscriptions: {
    setup({ dispatch, history }) {
      history.listen(location => {
        if (location.pathname === '/users') {
          dispatch({
            type: 'query',
            payload: location.query
          });
        }
      });
    },
  },
  reducers: {
    setState(state, action) {
      return { ...state, ...action.payload };
    }
  }
}

路由文件,div引入less样式,antD翻页分页处理,location获取query与hash,payload参数传递
批量删除获取table选取内容selectedRows,Modal确认框
routes/usersPage/UsersPage.jsx

import UserList from '../../components/users/UserList';
import UserSearch from '../../components/users/UserSearch';
import UserModal from '../../components/users/UserModal';
import PropTypes from 'prop-types'
import styles from './Users.less';
import { connect } from 'dva';
import React, { useEffect } from 'react'
import { routerRedux } from 'dva/router';
import { notification, Modal, message } from 'antd';

function Users({ location, dispatch, users }) {
  const {
    loading, list, totalRecords, pageSize, total, current, field, keyword,
    currentItem, modalVisible, modalType, pagination,
    selectedRowKeys, selectedRows
  } = users;

  const userSearchProps = {
    field,
    keyword,
    selectedRows,
    onAdd() {
      dispatch({
        type: 'users/setState',
        payload: {
          modalType: 'create',
          currentItem: {},
          modalVisible: true,
          type: 'create'
        },
      });
    },
    onDetail() {
      if (selectedRows.length === 0) {
        Modal.info({
          title: '信息',
          content: '请选择一个用户。'
        })
      } else if (selectedRows.length > 1) {
        notification['warning']({
          message: '提示!',
          description: '请选择一条要查看的数据。'
        });
      } else {
        dispatch({
          type: 'users/setState',
          payload: {
            modalType: 'detail',
            currentItem: selectedRows[0],
            modalVisible: true,
            type: 'detail'
          },
        });
      }
    },
    onDelete() {
      const ids = selectedRowKeys.join(',');
      if (selectedRowKeys.length === 0) {
        notification['warning']({
          message: '提示!',
          description: '请选择要删除的数据。'
        });
      } else {
        Modal.confirm({
          title: '删除提示',
          content: `您确定要删除这些数据吗?`,
          onOk: () => {
            dispatch({
              type: 'users/delete',
              payload: ids,
            });
            message.success('删除成功');
          },
        })
      }
    },
    onSearch(fieldsValue) {
      dispatch({
        type: 'users/query',
        payload: fieldsValue,
      });
    },
  };

  const userListProps = {
    dataSource: list,
    total,
    loading,
    current,
    pagination,
    selectedRowKeys,
    selectedRows,
    /*{onPageChange(page) {
      dispatch(routerRedux.push({
        pathname: '/users',
        query: { field, keyword, current:page },
      }));},
     }*/
    //前台分页
    /*onPageChange(page) {
      dispatch({
        type:'users/setState',
        payload:{
          list: totalRecords.slice((page-1)*pageSize,page*pageSize),
          current: page,
          pagination : {current: page,pageSize,total,showTotal:()=>{
            return `共${total}条`
         }}
        }
      })
    },*/
    onPageChange(page) {
      const { query: params, hash } = location;
      dispatch({
        type: 'users/query',
        payload: {
          ...params,
          current: page
        }
      })
    },
    onDeleteItem(id) {
      dispatch({
        type: 'users/delete',
        payload: id,
      });
    },
    onEditItem(item) {
      dispatch({
        type: 'users/setState',
        payload: {
          modalType: 'update',
          currentItem: item,
          modalVisible: true,
          type: 'edit'
        },
      });
    },
    onSelectedRowKeys(selectedRowKeys, selectedRows) {
      dispatch({
        type: 'users/setState',
        payload: {
          selectedRowKeys,
          selectedRows,
        },
      });
    }
  };

  const userModalProps = {
    item: modalType === 'create' ? {} : currentItem,
    type: modalType,
    currentItem,
    visible: modalVisible,
    onOk(data) {
      dispatch({
        type: `users/${modalType}`,
        payload: data,
      });
    },
    onCancel() {
      dispatch({
        type: 'users/setState',
        payload: { modalVisible: false },
      });
    }
  };

  //useEffect(() => { getUsers },[])
  return (
    <div className={styles.normal}>
      {/* 用户筛选搜索框 */}
      <UserSearch {...userSearchProps} />
      {/* 用户信息展示列表 */}
      <UserList {...userListProps} />
      {/* 添加用户 & 修改用户弹出的浮层 */}
      <UserModal {...userModalProps} />
    </div>
  );
}

Users.propTypes = {
  users: PropTypes.object,
  location: PropTypes.object,
  dispatch: PropTypes.func,
};

const mapStateToProps = ({ users }) => {
  return { users };
}

export default connect(mapStateToProps)(Users);

routes/usersPage/Users.less
 

.normal {
    width: 1200px;
    margin: 20px auto;
  }
  

PropTypes验证,Table组件,Table组件render处理单元格获取record,Popconfirm确认框,rowSelection多选框
Table单元格居中,table字典转义,pagination分页工具类
components/users/UserList.jsx

// ./src/components/Users/UserList.jsx
import React, { PropTypes } from 'react';
// 采用antd的UI组件
import { Table, Popconfirm, Pagination } from 'antd';
import styles from './UserList.less';

// 采用 stateless 的写法
const UserList = ({
  loading,
  dataSource,
  onPageChange,
  onDeleteItem,
  onEditItem,
  pagination,
  onSelectedRowKeys,
  selectedRowKeys,
}) => {
  const columns = [{
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    render: (text) => <a href="#">{text}</a>,
  }, {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
  }, {
    title: '性别',
    dataIndex: 'sex',
    key: 'sex',
    render(sex) {
      return sex == 1 ? '男' : '女'
    },
  }, {
    title: '住址',
    dataIndex: 'address',
    key: 'address',
  }, {
    title: '操作',
    key: 'operation',
    render: (text, record) => (
      <p>
        <a onClick={() => { onEditItem(record) }} >编辑</a>
        &nbsp;
        <Popconfirm title="确定要删除吗?" onConfirm={() => onDeleteItem(record.id)}>
          <a>删除</a>
        </Popconfirm>
      </p>
    ),
  }];

  //多选框
  const rowCheckSelection = {
    type: 'checkbox',
    selectedRowKeys,
    onChange: onSelectedRowKeys
  }

  return (
    <div className={styles.standardTable}>
      <Table
        bordered
        columns={columns}
        dataSource={dataSource}
        loading={loading}
        rowKey={record => record.id}
        pagination={false}
        rowSelection={rowCheckSelection}
      />
      <Pagination
        className="ant-table-pagination"
        {...pagination}
        onChange={onPageChange}
      />
    </div>
  );
}

UserList.propTypes = {
  loading: PropTypes.bool,
  dataSource: PropTypes.array,
  onPageChange: PropTypes.func,
  onDeleteItem: PropTypes.func,
  onEditItem: PropTypes.func,
  pagination: PropTypes.object,
  onSelectedRowKeys: PropTypes.array,
  selectedRowKeys: PropTypes.array,
};

export default UserList;

components/users/UserList.less

.column-left{
    text-align: left;
  }
.column-right{
    text-align: right;
 }
 .columnCell{
    display: table-cell;
    vertical-align: middle;
 }

.standardTable {

   :global {
   
   .ant-table-thead > tr > th > {
   
   text-align: center;
   
   }
   
   .ant-table-tbody > tr > td {
   
   text-align: center;
   
   }
}
}

utils/utils.js

import React from 'react';
import { Select } from 'antd'
const Option = Select.Option;
export default {
    formateDate(time){
        if(!time)return '';
        let date = new Date(time);
        return date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate()+' '+date.getHours()+':'+date.getMinutes()+':'+date.getSeconds();
    },
    pagination(data){
        return {
            current:data.currentPageNum,
            pageSize:data.pageSize,
            total: data.totalSize,
            showTotal:()=>{
                return `共${data.totalSize}条`
            },
            showQuickJumper:false
        }
    },
    getOptionList(data){
        if(!data){
            return [];
        }
        let options = [] //[<Option value="0" key="all_key">全部</Option>];
        data.map((item)=>{
            options.push(<Option value={item.id} key={item.id}>{item.name}</Option>)
        })
        return options;
    }
}

UserSearch公共查询表单BaseForm,表单查询框样式设置,获取方法中的event,获取form表单的字段,验证字段validateFields
components/users/UserSearch.jsx

import React, { PropTypes } from 'react';
import { Form, Button, Card } from 'antd';
import BaseForm from '../../components/BaseForm'
import styles from './UserSearch.less';

const UserSearch = ({
  onSearch,
  onAdd,
  onDetail,
  onDelete,
  form: {
    validateFields,
  },
}) => {
  const formList = [
    {
      type: 'SELECT',
      label: '选项',
      field: 'field',
      placeholder: '',
      initialValue: 'name',
      width: 80,
      list: [{ id: 'name', name: '姓名' }, { id: 'address', name: '住址' }]
    },
    {
      type: 'INPUT',
      label: '关键字',
      field: 'keyword',
      placeholder: '请输入关键字',
      width: 80
    }
  ]

  function handleFilter(params) {
    var event = window.event
    event.preventDefault();
    validateFields((errors) => {
      if (!!errors) {
        return;
      }
      onSearch(params);
    });
  }

  // 操作员工
  function handleOperator(type) {
    if (type === 'create') {
      onAdd();
    } else if (type === "edit" || type === 'detail') {
      if (type === 'detail') {
        onDetail();
      }
    } else if (type === "delete") {
      onDelete();
    }
  }

  return (
    <div className={styles.normal}>
      <div className={styles.search}>
        <Card>
          <BaseForm formList={formList} filterSubmit={handleFilter} />
        </Card>
        <Card className={styles.operateWrap}>
          <Button type="primary" icon="plus" onClick={() => handleOperator('create')}>新增</Button>
          <Button onClick={() => handleOperator('detail')}>查看</Button>
          <Button type="danger" icon="delete" onClick={() => handleOperator('delete')}>删除</Button>
        </Card>
      </div>
    </div>
  );
};

UserSearch.propTypes = {
  form: PropTypes.object.isRequired,
  onSearch: PropTypes.func,
  onAdd: PropTypes.func,
  onDetail: PropTypes.func,
  onDelete: PropTypes.func
};

export default Form.create()(UserSearch);

components/users/UserSearch.less


.normal {
  display: flex;
}

.search {
  flex: 1;
}

.operateWrap {
  button{
    margin-right: 10px;
  }
  margin-top:20px;
}

getFieldsValue获取表单输入内容,提价表单,重置表单,getFieldDecorator数据双向绑定,设置表单样式style
components/BaseForm/index.js

import React from 'react'
import { Input, Select, Form, Button, Checkbox, Radio, DatePicker} from 'antd'
import Utils from '../../utils/utils';
const FormItem = Form.Item;
const Option = Select.Option;
 
class FilterForm extends React.Component{
 
    handleFilterSubmit = ()=>{
        let fieldsValue = this.props.form.getFieldsValue();
        this.props.filterSubmit(fieldsValue);
    }
 
    reset = ()=>{
        this.props.form.resetFields();
    }
 
    initFormList = ()=>{
        const { getFieldDecorator } = this.props.form;
        const formList = this.props.formList;
        const formItemList = [];
        if (formList && formList.length>0){
            formList.forEach((item,i)=>{
                let label = item.label;
                let field = item.field;
                let initialValue = item.initialValue || '';
                let placeholder = item.placeholder;
                let width = item.width;
                if (item.type == '时间查询'){
                    const begin_time = <FormItem label="日期选择" key={field}>
                        {
                            getFieldDecorator('begin_time')(
                                <DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss"/>
                            )
                        }
                    </FormItem>;
                    formItemList.push(begin_time)
                    const end_time = <FormItem label="~" colon={false} key={field}>
                        {
                            getFieldDecorator('end_time')(
                                <DatePicker showTime={true} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss" />
                            )
                        }
                    </FormItem>;
                    formItemList.push(end_time)
                }else if(item.type == 'INPUT'){
                    const INPUT = <FormItem label={label} key={field}>
                        {
                            getFieldDecorator([field],{
                                initialValue: initialValue
                            })(
                                <Input type="text" placeholder={placeholder} />
                            )
                        }
                    </FormItem>;
                    formItemList.push(INPUT)
                } else if (item.type == 'SELECT') {
                    const SELECT = <FormItem label={label} key={field}>
                        {
                            getFieldDecorator([field], {
                                initialValue: initialValue
                            })(
                                <Select
                                    style={{ width: width }}
                                    placeholder={placeholder}
                                >
                                    {Utils.getOptionList(item.list)}
                                </Select>
                            )
                        }
                    </FormItem>;
                    formItemList.push(SELECT)
                } else if (item.type == 'CHECKBOX') {
                    const CHECKBOX = <FormItem label={label} key={field}>
                        {
                            getFieldDecorator([field], {
                                valuePropName: 'checked',
                                initialValue: initialValue //true | false
                            })(
                                <Checkbox>
                                    {label}
                                </Checkbox>
                            )
                        }
                    </FormItem>;
                    formItemList.push(CHECKBOX)
                }
            })
        }
        return formItemList;
    }
    render(){
        return (
            <Form layout="inline">
                { this.initFormList() }
                <FormItem>
                    <Button type="primary" style={{ margin: '0 20px' }} onClick={this.handleFilterSubmit}>查询</Button>
                    <Button onClick={this.reset}>重置</Button>
                </FormItem>
            </Form>
        );
    }
}
export default Form.create({})(FilterForm);

formItemLayout设置表单标签宽度占比,表单校验,三元表达式只读,Icon,单选框,新增修改显示不同的选择内容
components/users/UserModal.js

import React, { PropTypes } from 'react';
import { Form, Input, Modal, Icon, InputNumber, Radio } from 'antd';
const FormItem = Form.Item;
const RadioGroup = Radio.Group;

const formItemLayout = {
  labelCol: {
    span: 6,
  },
  wrapperCol: {
    span: 6,
  }
};
const formItemAddressLayout = {
  labelCol: {
    span: 6,
  },
  wrapperCol: {
    span: 14,
  }
};

const UserModal = ({
  visible,
  item = item || {},
  type,
  onOk,
  onCancel,
  form: {
    getFieldDecorator,
    validateFields,
    getFieldsValue,
  },
}) => {
  
  function handleOk() {
    if (type === 'detail') {
      onCancel();
    } else {
      validateFields((errors) => {
        if (errors) {
          return;
        }
        const data = { ...getFieldsValue(), id: item.id };
        onOk(data);
      });
    }
  }

  function checkNumber(rule, value, callback) {
    if (!value) {
      callback(new Error('年龄必须填写!'));
    }
    if (!/^[\d]{1,2}$/.test(value)) {
      callback(new Error('请输入合法年龄!'));
    } else {
      callback();
    }
  }

  const modalOpts = {
    visible,
    onOk: handleOk,
    onCancel
  };

  return (
    <Modal {...modalOpts} title={type === 'create' ? '添加用户' : (type === 'update' ? '修改用户' : '查看用户')}>
      <Form horizontal>
        <FormItem
          label="姓名:"
          hasFeedback
          {...formItemLayout}
        >
          {item && type == 'detail' ? item.name : getFieldDecorator('name', {
            initialValue: item.name,
            rules: [
              { required: true, message: '姓名必须填写!' }
            ],
          })(
            <Input type="text" prefix={<Icon type="user" />} placeholder="请输入用户名" />
          )}
        </FormItem>
        <FormItem
          label="年龄:"
          hasFeedback
          {...formItemLayout}
        >
          {item && type == 'detail' ? item.age : getFieldDecorator('age', {
            initialValue: item.age,
            rules: [
              { validator: checkNumber }, { required: true, message: '年龄必须填写!' }
            ],
          })(
            <InputNumber />
          )}
        </FormItem>
        <FormItem
          label="性别:"
          hasFeedback
          {...formItemLayout}
        >
          {item && type == 'detail' ? item.sex === '1' ? '男' : '女' : getFieldDecorator('sex', {
            initialValue: item.sex,
            rules: [
              { required: true, message: '性别必须填写!' },
            ],
          })(
            <RadioGroup>
              <Radio value="1">男</Radio>
              <Radio value="2">女</Radio>
            </RadioGroup>
          )}
        </FormItem>
        <FormItem
          label="住址:"
          hasFeedback
          {...formItemAddressLayout}
        >
          {item && type == 'detail' ? item.address : getFieldDecorator('address', {
            initialValue: item.address,
            rules: [
              { required: true, message: '住址必须填写!' },
            ],
          })(
            <Input type="address" />
          )}
        </FormItem>
      </Form>
    </Modal>
  );
};

UserModal.propTypes = {
  visible: PropTypes.any,
  form: PropTypes.object,
  item: PropTypes.object,
  type: PropTypes.string,
  onOk: PropTypes.func,
  onCancel: PropTypes.func
};

export default Form.create({
  mapPropsToFields(props) {
    if (props.type === 'create') {
      return {
        name: {},
        age: {},
        sex: {},
        address: {}
      }
    }
    return {
      name: { ...props.item.name },
      age: { ...props.item.age },
      sex: { ...props.item.sex },
      address: { ...props.item.address }
    }
  }
})(UserModal);


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wespten

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值