作者 RuoYi

新增用户导入

@@ -117,3 +117,11 @@ export function uploadAvatar(data) { @@ -117,3 +117,11 @@ export function uploadAvatar(data) {
117 data: data 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 +}
@@ -114,6 +114,15 @@ @@ -114,6 +114,15 @@
114 </el-col> 114 </el-col>
115 <el-col :span="1.5"> 115 <el-col :span="1.5">
116 <el-button 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 type="warning" 126 type="warning"
118 icon="el-icon-download" 127 icon="el-icon-download"
119 size="mini" 128 size="mini"
@@ -284,11 +293,43 @@ @@ -284,11 +293,43 @@
284 <el-button @click="cancel">取 消</el-button> 293 <el-button @click="cancel">取 消</el-button>
285 </div> 294 </div>
286 </el-dialog> 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 </div> 327 </div>
288 </template> 328 </template>
289 329
290 <script> 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 import { treeselect } from "@/api/system/dept"; 333 import { treeselect } from "@/api/system/dept";
293 import Treeselect from "@riophae/vue-treeselect"; 334 import Treeselect from "@riophae/vue-treeselect";
294 import "@riophae/vue-treeselect/dist/vue-treeselect.css"; 335 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
@@ -336,6 +377,21 @@ export default { @@ -336,6 +377,21 @@ export default {
336 children: "children", 377 children: "children",
337 label: "label" 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 queryParams: { 396 queryParams: {
341 pageNum: 1, 397 pageNum: 1,
@@ -473,9 +529,9 @@ export default { @@ -473,9 +529,9 @@ export default {
473 }, 529 },
474 // 多选框选中数据 530 // 多选框选中数据
475 handleSelectionChange(selection) { 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 handleAdd() { 537 handleAdd() {
@@ -493,7 +549,7 @@ export default { @@ -493,7 +549,7 @@ export default {
493 handleUpdate(row) { 549 handleUpdate(row) {
494 this.reset(); 550 this.reset();
495 this.getTreeselect(); 551 this.getTreeselect();
496 - const userId = row.userId || this.ids 552 + const userId = row.userId || this.ids;
497 getUser(userId).then(response => { 553 getUser(userId).then(response => {
498 this.form = response.data; 554 this.form = response.data;
499 this.postOptions = response.posts; 555 this.postOptions = response.posts;
@@ -574,6 +630,33 @@ export default { @@ -574,6 +630,33 @@ export default {
574 }).then(response => { 630 }).then(response => {
575 this.download(response.msg); 631 this.download(response.msg);
576 }).catch(function() {}); 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 };
@@ -12,12 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping; @@ -12,12 +12,16 @@ import org.springframework.web.bind.annotation.PutMapping;
12 import org.springframework.web.bind.annotation.RequestBody; 12 import org.springframework.web.bind.annotation.RequestBody;
13 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.RequestMapping;
14 import org.springframework.web.bind.annotation.RestController; 14 import org.springframework.web.bind.annotation.RestController;
  15 +import org.springframework.web.multipart.MultipartFile;
15 import com.ruoyi.common.constant.UserConstants; 16 import com.ruoyi.common.constant.UserConstants;
16 import com.ruoyi.common.utils.SecurityUtils; 17 import com.ruoyi.common.utils.SecurityUtils;
  18 +import com.ruoyi.common.utils.ServletUtils;
17 import com.ruoyi.common.utils.StringUtils; 19 import com.ruoyi.common.utils.StringUtils;
18 import com.ruoyi.common.utils.poi.ExcelUtil; 20 import com.ruoyi.common.utils.poi.ExcelUtil;
19 import com.ruoyi.framework.aspectj.lang.annotation.Log; 21 import com.ruoyi.framework.aspectj.lang.annotation.Log;
20 import com.ruoyi.framework.aspectj.lang.enums.BusinessType; 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 import com.ruoyi.framework.web.controller.BaseController; 25 import com.ruoyi.framework.web.controller.BaseController;
22 import com.ruoyi.framework.web.domain.AjaxResult; 26 import com.ruoyi.framework.web.domain.AjaxResult;
23 import com.ruoyi.framework.web.page.TableDataInfo; 27 import com.ruoyi.framework.web.page.TableDataInfo;
@@ -44,6 +48,9 @@ public class SysUserController extends BaseController @@ -44,6 +48,9 @@ public class SysUserController extends BaseController
44 @Autowired 48 @Autowired
45 private ISysPostService postService; 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,6 +73,26 @@ public class SysUserController extends BaseController
66 return util.exportExcel(list, "用户数据"); 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 */
@@ -9,6 +9,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder; @@ -9,6 +9,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
9 import org.apache.commons.lang3.builder.ToStringStyle; 9 import org.apache.commons.lang3.builder.ToStringStyle;
10 import com.ruoyi.framework.aspectj.lang.annotation.Excel; 10 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
11 import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType; 11 import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType;
  12 +import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type;
12 import com.ruoyi.framework.aspectj.lang.annotation.Excels; 13 import com.ruoyi.framework.aspectj.lang.annotation.Excels;
13 import com.ruoyi.framework.web.domain.BaseEntity; 14 import com.ruoyi.framework.web.domain.BaseEntity;
14 15
@@ -26,6 +27,7 @@ public class SysUser extends BaseEntity @@ -26,6 +27,7 @@ public class SysUser extends BaseEntity
26 private Long userId; 27 private Long userId;
27 28
28 /** 部门ID */ 29 /** 部门ID */
  30 + @Excel(name = "部门编号", type = Type.IMPORT)
29 private Long deptId; 31 private Long deptId;
30 32
31 /** 用户账号 */ 33 /** 用户账号 */
@@ -65,15 +67,18 @@ public class SysUser extends BaseEntity @@ -65,15 +67,18 @@ public class SysUser extends BaseEntity
65 private String delFlag; 67 private String delFlag;
66 68
67 /** 最后登陆IP */ 69 /** 最后登陆IP */
68 - @Excel(name = "最后登陆IP") 70 + @Excel(name = "最后登陆IP", type = Type.EXPORT)
69 private String loginIp; 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 private Date loginDate; 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 private SysDept dept; 82 private SysDept dept;
78 83
79 /** 角色对象 */ 84 /** 角色对象 */
@@ -24,7 +24,7 @@ public interface ISysConfigService @@ -24,7 +24,7 @@ public interface ISysConfigService
24 * @param configKey 参数键名 24 * @param configKey 参数键名
25 * @return 参数键值 25 * @return 参数键值
26 */ 26 */
27 - public Object selectConfigByKey(String configKey); 27 + public String selectConfigByKey(String configKey);
28 28
29 /** 29 /**
30 * 查询参数配置列表 30 * 查询参数配置列表
@@ -154,4 +154,14 @@ public interface ISysUserService @@ -154,4 +154,14 @@ public interface ISysUserService
154 * @return 结果 154 * @return 结果
155 */ 155 */
156 public int deleteUserByIds(Long[] userIds); 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 }
@@ -41,7 +41,7 @@ public class SysConfigServiceImpl implements ISysConfigService @@ -41,7 +41,7 @@ public class SysConfigServiceImpl implements ISysConfigService
41 * @return 参数键值 41 * @return 参数键值
42 */ 42 */
43 @Override 43 @Override
44 - public Object selectConfigByKey(String configKey) 44 + public String selectConfigByKey(String configKey)
45 { 45 {
46 SysConfig config = new SysConfig(); 46 SysConfig config = new SysConfig();
47 config.setConfigKey(configKey); 47 config.setConfigKey(configKey);
@@ -2,11 +2,14 @@ package com.ruoyi.project.system.service.impl; @@ -2,11 +2,14 @@ package com.ruoyi.project.system.service.impl;
2 2
3 import java.util.ArrayList; 3 import java.util.ArrayList;
4 import java.util.List; 4 import java.util.List;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
5 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.stereotype.Service; 8 import org.springframework.stereotype.Service;
7 import org.springframework.transaction.annotation.Transactional; 9 import org.springframework.transaction.annotation.Transactional;
8 import com.ruoyi.common.constant.UserConstants; 10 import com.ruoyi.common.constant.UserConstants;
9 import com.ruoyi.common.exception.CustomException; 11 import com.ruoyi.common.exception.CustomException;
  12 +import com.ruoyi.common.utils.SecurityUtils;
10 import com.ruoyi.common.utils.StringUtils; 13 import com.ruoyi.common.utils.StringUtils;
11 import com.ruoyi.framework.aspectj.lang.annotation.DataScope; 14 import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
12 import com.ruoyi.project.system.domain.SysPost; 15 import com.ruoyi.project.system.domain.SysPost;
@@ -19,6 +22,7 @@ import com.ruoyi.project.system.mapper.SysRoleMapper; @@ -19,6 +22,7 @@ import com.ruoyi.project.system.mapper.SysRoleMapper;
19 import com.ruoyi.project.system.mapper.SysUserMapper; 22 import com.ruoyi.project.system.mapper.SysUserMapper;
20 import com.ruoyi.project.system.mapper.SysUserPostMapper; 23 import com.ruoyi.project.system.mapper.SysUserPostMapper;
21 import com.ruoyi.project.system.mapper.SysUserRoleMapper; 24 import com.ruoyi.project.system.mapper.SysUserRoleMapper;
  25 +import com.ruoyi.project.system.service.ISysConfigService;
22 import com.ruoyi.project.system.service.ISysUserService; 26 import com.ruoyi.project.system.service.ISysUserService;
23 27
24 /** 28 /**
@@ -29,6 +33,8 @@ import com.ruoyi.project.system.service.ISysUserService; @@ -29,6 +33,8 @@ import com.ruoyi.project.system.service.ISysUserService;
29 @Service 33 @Service
30 public class SysUserServiceImpl implements ISysUserService 34 public class SysUserServiceImpl implements ISysUserService
31 { 35 {
  36 + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
  37 +
32 @Autowired 38 @Autowired
33 private SysUserMapper userMapper; 39 private SysUserMapper userMapper;
34 40
@@ -44,6 +50,9 @@ public class SysUserServiceImpl implements ISysUserService @@ -44,6 +50,9 @@ public class SysUserServiceImpl implements ISysUserService
44 @Autowired 50 @Autowired
45 private SysUserPostMapper userPostMapper; 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,4 +384,72 @@ public class SysUserServiceImpl implements ISysUserService
375 } 384 }
376 return userMapper.deleteUserByIds(userIds); 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 }