Commit b508e6f20238caf6f000a2ac617bb6a4ca37d56b

Authored by RuoYi
1 parent 8216d4e8

新增用户导入

ruoyi-ui/src/api/system/user.js
... ... @@ -117,3 +117,11 @@ export function uploadAvatar(data) {
117 117 data: data
118 118 })
119 119 }
  120 +
  121 +// 下载用户导入模板
  122 +export function importTemplate() {
  123 + return request({
  124 + url: '/system/user/importTemplate',
  125 + method: 'get'
  126 + })
  127 +}
... ...
ruoyi-ui/src/views/system/user/index.vue
... ... @@ -114,6 +114,15 @@
114 114 </el-col>
115 115 <el-col :span="1.5">
116 116 <el-button
  117 + type="info"
  118 + icon="el-icon-upload2"
  119 + size="mini"
  120 + @click="handleImport"
  121 + v-hasPermi="['system:user:import']"
  122 + >导入</el-button>
  123 + </el-col>
  124 + <el-col :span="1.5">
  125 + <el-button
117 126 type="warning"
118 127 icon="el-icon-download"
119 128 size="mini"
... ... @@ -284,11 +293,43 @@
284 293 <el-button @click="cancel">取 消</el-button>
285 294 </div>
286 295 </el-dialog>
  296 +
  297 + <!-- 用户导入对话框 -->
  298 + <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px">
  299 + <el-upload
  300 + ref="upload"
  301 + :limit="1"
  302 + accept=".xlsx, .xls"
  303 + :headers="upload.headers"
  304 + :action="upload.url + '?updateSupport=' + upload.updateSupport"
  305 + :disabled="upload.isUploading"
  306 + :on-progress="handleFileUploadProgress"
  307 + :on-success="handleFileSuccess"
  308 + :auto-upload="false"
  309 + drag
  310 + >
  311 + <i class="el-icon-upload"></i>
  312 + <div class="el-upload__text">
  313 + 将文件拖到此处,或
  314 + <em>点击上传</em>
  315 + </div>
  316 + <div class="el-upload__tip" slot="tip">
  317 + <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
  318 + <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
  319 + </div>
  320 + <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
  321 + </el-upload>
  322 + <div slot="footer" class="dialog-footer">
  323 + <el-button type="primary" @click="submitFileForm">确 定</el-button>
  324 + <el-button @click="upload.open = false">取 消</el-button>
  325 + </div>
  326 + </el-dialog>
287 327 </div>
288 328 </template>
289 329  
290 330 <script>
291   -import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus } from "@/api/system/user";
  331 +import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus, importTemplate } from "@/api/system/user";
  332 +import { getToken } from "@/utils/auth";
292 333 import { treeselect } from "@/api/system/dept";
293 334 import Treeselect from "@riophae/vue-treeselect";
294 335 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
... ... @@ -336,6 +377,21 @@ export default {
336 377 children: "children",
337 378 label: "label"
338 379 },
  380 + // 用户导入参数
  381 + upload: {
  382 + // 是否显示弹出层(用户导入)
  383 + open: false,
  384 + // 弹出层标题(用户导入)
  385 + title: "",
  386 + // 是否禁用上传
  387 + isUploading: false,
  388 + // 是否更新已经存在的用户数据
  389 + updateSupport: 0,
  390 + // 设置上传的请求头部
  391 + headers: { Authorization: "Bearer " + getToken() },
  392 + // 上传的地址
  393 + url: process.env.VUE_APP_BASE_API + "/system/user/importData"
  394 + },
339 395 // 查询参数
340 396 queryParams: {
341 397 pageNum: 1,
... ... @@ -473,9 +529,9 @@ export default {
473 529 },
474 530 // 多选框选中数据
475 531 handleSelectionChange(selection) {
476   - this.ids = selection.map(item => item.userId)
477   - this.single = selection.length!=1
478   - this.multiple = !selection.length
  532 + this.ids = selection.map(item => item.userId);
  533 + this.single = selection.length != 1;
  534 + this.multiple = !selection.length;
479 535 },
480 536 /** 新增按钮操作 */
481 537 handleAdd() {
... ... @@ -493,7 +549,7 @@ export default {
493 549 handleUpdate(row) {
494 550 this.reset();
495 551 this.getTreeselect();
496   - const userId = row.userId || this.ids
  552 + const userId = row.userId || this.ids;
497 553 getUser(userId).then(response => {
498 554 this.form = response.data;
499 555 this.postOptions = response.posts;
... ... @@ -574,6 +630,33 @@ export default {
574 630 }).then(response => {
575 631 this.download(response.msg);
576 632 }).catch(function() {});
  633 + },
  634 + /** 导入按钮操作 */
  635 + handleImport() {
  636 + this.upload.title = "用户导入";
  637 + this.upload.open = true;
  638 + },
  639 + /** 下载模板操作 */
  640 + importTemplate() {
  641 + importTemplate().then(response => {
  642 + this.download(response.msg);
  643 + });
  644 + },
  645 + // 文件上传中处理
  646 + handleFileUploadProgress(event, file, fileList) {
  647 + this.upload.isUploading = true;
  648 + },
  649 + // 文件上传成功处理
  650 + handleFileSuccess(response, file, fileList) {
  651 + this.upload.open = false;
  652 + this.upload.isUploading = false;
  653 + this.$refs.upload.clearFiles();
  654 + this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
  655 + this.getList();
  656 + },
  657 + // 提交上传文件
  658 + submitFileForm() {
  659 + this.$refs.upload.submit();
577 660 }
578 661 }
579 662 };
... ...
ruoyi/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
... ... @@ -12,12 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping;
12 12 import org.springframework.web.bind.annotation.RequestBody;
13 13 import org.springframework.web.bind.annotation.RequestMapping;
14 14 import org.springframework.web.bind.annotation.RestController;
  15 +import org.springframework.web.multipart.MultipartFile;
15 16 import com.ruoyi.common.constant.UserConstants;
16 17 import com.ruoyi.common.utils.SecurityUtils;
  18 +import com.ruoyi.common.utils.ServletUtils;
17 19 import com.ruoyi.common.utils.StringUtils;
18 20 import com.ruoyi.common.utils.poi.ExcelUtil;
19 21 import com.ruoyi.framework.aspectj.lang.annotation.Log;
20 22 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
  23 +import com.ruoyi.framework.security.LoginUser;
  24 +import com.ruoyi.framework.security.service.TokenService;
21 25 import com.ruoyi.framework.web.controller.BaseController;
22 26 import com.ruoyi.framework.web.domain.AjaxResult;
23 27 import com.ruoyi.framework.web.page.TableDataInfo;
... ... @@ -44,6 +48,9 @@ public class SysUserController extends BaseController
44 48 @Autowired
45 49 private ISysPostService postService;
46 50  
  51 + @Autowired
  52 + private TokenService tokenService;
  53 +
47 54 /**
48 55 * 获取用户列表
49 56 */
... ... @@ -66,6 +73,26 @@ public class SysUserController extends BaseController
66 73 return util.exportExcel(list, "用户数据");
67 74 }
68 75  
  76 + @Log(title = "用户管理", businessType = BusinessType.IMPORT)
  77 + @PreAuthorize("@ss.hasPermi('system:user:import')")
  78 + @PostMapping("/importData")
  79 + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
  80 + {
  81 + ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
  82 + List<SysUser> userList = util.importExcel(file.getInputStream());
  83 + LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
  84 + String operName = loginUser.getUsername();
  85 + String message = userService.importUser(userList, updateSupport, operName);
  86 + return AjaxResult.success(message);
  87 + }
  88 +
  89 + @GetMapping("/importTemplate")
  90 + public AjaxResult importTemplate()
  91 + {
  92 + ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
  93 + return util.importTemplateExcel("用户数据");
  94 + }
  95 +
69 96 /**
70 97 * 根据用户编号获取详细信息
71 98 */
... ...
ruoyi/src/main/java/com/ruoyi/project/system/domain/SysUser.java
... ... @@ -9,6 +9,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
9 9 import org.apache.commons.lang3.builder.ToStringStyle;
10 10 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
11 11 import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType;
  12 +import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type;
12 13 import com.ruoyi.framework.aspectj.lang.annotation.Excels;
13 14 import com.ruoyi.framework.web.domain.BaseEntity;
14 15  
... ... @@ -26,6 +27,7 @@ public class SysUser extends BaseEntity
26 27 private Long userId;
27 28  
28 29 /** 部门ID */
  30 + @Excel(name = "部门编号", type = Type.IMPORT)
29 31 private Long deptId;
30 32  
31 33 /** 用户账号 */
... ... @@ -65,15 +67,18 @@ public class SysUser extends BaseEntity
65 67 private String delFlag;
66 68  
67 69 /** 最后登陆IP */
68   - @Excel(name = "最后登陆IP")
  70 + @Excel(name = "最后登陆IP", type = Type.EXPORT)
69 71 private String loginIp;
70 72  
71 73 /** 最后登陆时间 */
72   - @Excel(name = "最后登陆时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
  74 + @Excel(name = "最后登陆时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
73 75 private Date loginDate;
74 76  
75 77 /** 部门对象 */
76   - @Excels({ @Excel(name = "部门名称", targetAttr = "deptName"), @Excel(name = "部门负责人", targetAttr = "leader") })
  78 + @Excels({
  79 + @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
  80 + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
  81 + })
77 82 private SysDept dept;
78 83  
79 84 /** 角色对象 */
... ...
ruoyi/src/main/java/com/ruoyi/project/system/service/ISysConfigService.java
... ... @@ -24,7 +24,7 @@ public interface ISysConfigService
24 24 * @param configKey 参数键名
25 25 * @return 参数键值
26 26 */
27   - public Object selectConfigByKey(String configKey);
  27 + public String selectConfigByKey(String configKey);
28 28  
29 29 /**
30 30 * 查询参数配置列表
... ...
ruoyi/src/main/java/com/ruoyi/project/system/service/ISysUserService.java
... ... @@ -154,4 +154,14 @@ public interface ISysUserService
154 154 * @return 结果
155 155 */
156 156 public int deleteUserByIds(Long[] userIds);
  157 +
  158 + /**
  159 + * 导入用户数据
  160 + *
  161 + * @param userList 用户数据列表
  162 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
  163 + * @param operName 操作用户
  164 + * @return 结果
  165 + */
  166 + public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
157 167 }
... ...
ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
... ... @@ -41,7 +41,7 @@ public class SysConfigServiceImpl implements ISysConfigService
41 41 * @return 参数键值
42 42 */
43 43 @Override
44   - public Object selectConfigByKey(String configKey)
  44 + public String selectConfigByKey(String configKey)
45 45 {
46 46 SysConfig config = new SysConfig();
47 47 config.setConfigKey(configKey);
... ...
ruoyi/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
... ... @@ -2,11 +2,14 @@ package com.ruoyi.project.system.service.impl;
2 2  
3 3 import java.util.ArrayList;
4 4 import java.util.List;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
5 7 import org.springframework.beans.factory.annotation.Autowired;
6 8 import org.springframework.stereotype.Service;
7 9 import org.springframework.transaction.annotation.Transactional;
8 10 import com.ruoyi.common.constant.UserConstants;
9 11 import com.ruoyi.common.exception.CustomException;
  12 +import com.ruoyi.common.utils.SecurityUtils;
10 13 import com.ruoyi.common.utils.StringUtils;
11 14 import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
12 15 import com.ruoyi.project.system.domain.SysPost;
... ... @@ -19,6 +22,7 @@ import com.ruoyi.project.system.mapper.SysRoleMapper;
19 22 import com.ruoyi.project.system.mapper.SysUserMapper;
20 23 import com.ruoyi.project.system.mapper.SysUserPostMapper;
21 24 import com.ruoyi.project.system.mapper.SysUserRoleMapper;
  25 +import com.ruoyi.project.system.service.ISysConfigService;
22 26 import com.ruoyi.project.system.service.ISysUserService;
23 27  
24 28 /**
... ... @@ -29,6 +33,8 @@ import com.ruoyi.project.system.service.ISysUserService;
29 33 @Service
30 34 public class SysUserServiceImpl implements ISysUserService
31 35 {
  36 + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
  37 +
32 38 @Autowired
33 39 private SysUserMapper userMapper;
34 40  
... ... @@ -44,6 +50,9 @@ public class SysUserServiceImpl implements ISysUserService
44 50 @Autowired
45 51 private SysUserPostMapper userPostMapper;
46 52  
  53 + @Autowired
  54 + private ISysConfigService configService;
  55 +
47 56 /**
48 57 * 根据条件分页查询用户列表
49 58 *
... ... @@ -375,4 +384,72 @@ public class SysUserServiceImpl implements ISysUserService
375 384 }
376 385 return userMapper.deleteUserByIds(userIds);
377 386 }
  387 +
  388 + /**
  389 + * 导入用户数据
  390 + *
  391 + * @param userList 用户数据列表
  392 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
  393 + * @param operName 操作用户
  394 + * @return 结果
  395 + */
  396 + @Override
  397 + public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName)
  398 + {
  399 + if (StringUtils.isNull(userList) || userList.size() == 0)
  400 + {
  401 + throw new CustomException("导入用户数据不能为空!");
  402 + }
  403 + int successNum = 0;
  404 + int failureNum = 0;
  405 + StringBuilder successMsg = new StringBuilder();
  406 + StringBuilder failureMsg = new StringBuilder();
  407 + String password = configService.selectConfigByKey("sys.user.initPassword");
  408 + for (SysUser user : userList)
  409 + {
  410 + try
  411 + {
  412 + // 验证是否存在这个用户
  413 + SysUser u = userMapper.selectUserByUserName(user.getUserName());
  414 + if (StringUtils.isNull(u))
  415 + {
  416 + user.setPassword(SecurityUtils.encryptPassword(password));
  417 + user.setCreateBy(operName);
  418 + this.insertUser(user);
  419 + successNum++;
  420 + successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
  421 + }
  422 + else if (isUpdateSupport)
  423 + {
  424 + user.setUpdateBy(operName);
  425 + this.updateUser(user);
  426 + successNum++;
  427 + successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
  428 + }
  429 + else
  430 + {
  431 + failureNum++;
  432 + failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
  433 + }
  434 + }
  435 + catch (Exception e)
  436 + {
  437 + failureNum++;
  438 + String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
  439 + failureMsg.append(msg + e.getMessage());
  440 + log.error(msg, e);
  441 + }
  442 + }
  443 + if (failureNum > 0)
  444 + {
  445 + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
  446 + throw new CustomException(failureMsg.toString());
  447 + }
  448 + else
  449 + {
  450 + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
  451 + }
  452 + return successMsg.toString();
  453 + }
  454 +
378 455 }
... ...