当前位置:   article > 正文

Spring WebFlux + React搭建后台管理系统(9):通过上传excel实现批量新增_前端react项目中实现批量新增商品业务

前端react项目中实现批量新增商品业务

有这样的需求,需要批量新增数据,但是一个一个的表单填写太麻烦,可以通过excel将数据汇总,然后通过上传的方式显示出来,在前端页面进行勾选,实现批量上传,需要实现一下功能:

  • 新增上传页面的切换
  • 上传的文件通过表格展示
  • 通过勾选将选定数据进行上传

效果展示

在这里插入图片描述

1.添加API表处理excel逻辑

  • 添加controller处理excel
  • 跟user的主体逻辑基本相同
@PostMapping(value = "/upload/url/excel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseStatus(value = HttpStatus.OK)
@PreAuthorize("hasAnyRole('ADMIN')")
public Flux<SysApi> uploadUrl(@RequestPart("file") Flux<FilePart> filePart){

    return ioService.upload(filePart, SysApi.class)
            .cast(SysApi.class);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 下载excel的逻辑
@PostMapping("/download/url/excel")
@PreAuthorize("hasAnyRole('ADMIN', 'IT', 'HR')")
public Mono<Void> downloadUrl(ServerHttpResponse response) {

    return sysApiService.findAll()
            .collectList()
            .flatMap(objs-> {
                try {
                    return ioService.downloadFromDb(objs, response, SysApi.class);
                } catch (UnsupportedEncodingException e) {
                    return Mono.error(new UnsupportedEncodingException());
                }
            });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

1.1 excel处理注意点

  • 有两点发现需要注意,由于excel中数据的不可控性,trim是必要的
case "java.util.List":
    value = Arrays.stream(str.substring(1, str.length() - 1).split(","))
            .map(String::trim)
            .collect(Collectors.toList());
  • 1
  • 2
  • 3
  • 4
  • list类型的话,如果是Nono或是blank也要给个list变量
case BLANK:
case _NONE:
    if (type.getTypeName().equals("java.util.List")) value = new ArrayList<>();
    break;
  • 1
  • 2
  • 3
  • 4

1.2 下载文件内容权限区分

  • 多种权限有获取数据的需求
  • 因此需要控制不同权限获取的数据列数不同
  • 可以通过角色不同获取不同的数据
  • 也可以通过角色将部分数据写入文件
  • 这里通过角色限定head内容,再通过head内容限定获取内容
public Mono<Void> downloadFromDb(List<?> objs, ServerHttpResponse response, Class<? extends DataChange> clazz) throws UnsupportedEncodingException {
    String fileName = new String(("test" + LocalDateTime.now().toLocalDate() + ".xlsx").getBytes(StandardCharsets.UTF_8), "iso8859-1");
    File file = new File(fileName);
    Set<String> banSet = Stream.of("createBy", "createTime", "lastUpdateBy", "lastUpdateTime", "roles", "password", "frozen").collect(Collectors.toSet());

    return isAdmin()
            .flatMap(isAdmin -> {
                List<String> header = Stream.of(clazz.getDeclaredFields())
                        .map(Field::getName)
                        .filter(it-> isAdmin || !banSet.contains(it))
                        .collect(Collectors.toList());
                return WriteExcelUtil.data2Workbook(objs, clazz, header);
            })
            .flatMap(workbook -> {
                try {
                    workbook.write(new FileOutputStream(file));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return downloadFile(response, file, fileName);
            });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 通过ReactiveSecurityContextHolder获取权限信息,然后判断是否为ADMIN用户
private Mono<Boolean> isAdmin() {
    return ReactiveSecurityContextHolder.getContext()
            .map(it-> it.getAuthentication()
                    .getAuthorities()
                    .stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toSet())
            )
            .map(it -> it.contains("ROLE_ADMIN"));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • dz用户不能下载中没有权限等信息

在这里插入图片描述

2. 前端添加api管理页面

  • 代码和user的基本相同,主要需要更换table使用的Item类
  • 上传组件
          access.canAdmin && radioValue==='upload' &&(
            <Upload {...uploadProps}
            >
              <Button type="primary">
                <UploadOutlined /> 上传
              </Button>
            </Upload>
          ),
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 通过一个radio切换查询和上传功能
  • 通过onChange更换value,通过hook进行数据切换
{access.canAdmin&&(<Radio.Group
  defaultValue="read"
  buttonStyle="solid"
  onChange={(e) => {
    setRadioValue(e.target.value)
    // @ts-ignore
    actionRef.current?.reloadAndRest();
  }}
>
  <Radio.Button value="read">查询</Radio.Button>
  <Radio.Button value="upload">上传</Radio.Button>
</Radio.Group>)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • table通过radio的value更换切换数据来源
request={()=>{
  if (radioValue === 'upload'){
    return getApiData();
  }
  return findAllApi();
}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 通过upload的onChange将上传返回数据通过hook设置
onChange(info:any) {
  if (info.file.status !== 'uploading') {
    // console.log(info.file, info.fileList);
  }
  if (info.file.status === 'done') {
    setApiData(info.file.response);
    // @ts-ignore
    actionRef.current?.reloadAndRest();
    message.success(`${info.file.name} file uploaded successfully`);
  } else if (info.file.status === 'error') {
    message.error(`${info.file.name} file upload failed.`);
  }
},
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. 实现批量新增

  • 通过表格的选项进行新增
{access.canAdmin && radioValue === 'upload'&&(<Button
  type="primary"
  onClick={async () => {
    await handleUpdateMany(selectedRowsState);
    setSelectedRows([]);
  }}
>
  批量新增
</Button>)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4.代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/68904
推荐阅读
相关标签
  

闽ICP备14008679号