789 lines
24 KiB
Go
789 lines
24 KiB
Go
package controller
|
||
|
||
import (
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"be.ems/src/framework/config"
|
||
"be.ems/src/framework/constants/admin"
|
||
"be.ems/src/framework/constants/common"
|
||
"be.ems/src/framework/i18n"
|
||
"be.ems/src/framework/utils/ctx"
|
||
"be.ems/src/framework/utils/date"
|
||
"be.ems/src/framework/utils/file"
|
||
"be.ems/src/framework/utils/parse"
|
||
"be.ems/src/framework/utils/regular"
|
||
"be.ems/src/framework/vo/result"
|
||
"be.ems/src/modules/system/model"
|
||
"be.ems/src/modules/system/service"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/gin-gonic/gin/binding"
|
||
)
|
||
|
||
// 实例化控制层 SysUserController 结构体
|
||
var NewSysUser = &SysUserController{
|
||
sysUserService: service.NewSysUserImpl,
|
||
sysRoleService: service.NewSysRoleImpl,
|
||
sysPostService: service.NewSysPostImpl,
|
||
sysDictDataService: service.NewSysDictDataImpl,
|
||
sysConfigService: service.NewSysConfigImpl,
|
||
}
|
||
|
||
// 用户信息
|
||
//
|
||
// PATH /system/user
|
||
type SysUserController struct {
|
||
// 用户服务
|
||
sysUserService service.ISysUser
|
||
// 角色服务
|
||
sysRoleService service.ISysRole
|
||
// 岗位服务
|
||
sysPostService service.ISysPost
|
||
// 字典数据服务
|
||
sysDictDataService service.ISysDictData
|
||
// 参数配置服务
|
||
sysConfigService service.ISysConfig
|
||
}
|
||
|
||
// 用户信息列表
|
||
//
|
||
// GET /list
|
||
func (s *SysUserController) List(c *gin.Context) {
|
||
querys := ctx.QueryMap(c)
|
||
dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "u")
|
||
data := s.sysUserService.SelectUserPage(querys, dataScopeSQL)
|
||
|
||
rows := data["rows"].([]model.SysUser)
|
||
// 闭包函数处理多语言
|
||
language := ctx.AcceptLanguage(c)
|
||
converI18n := func(language string, arr *[]model.SysUser) {
|
||
for i := range *arr {
|
||
(*arr)[i].NickName = i18n.TKey(language, (*arr)[i].NickName)
|
||
(*arr)[i].Remark = i18n.TKey(language, (*arr)[i].Remark)
|
||
(*arr)[i].Dept.DeptName = i18n.TKey(language, (*arr)[i].Dept.DeptName)
|
||
for ri := range (*arr)[i].Roles {
|
||
(*arr)[i].Roles[ri].RoleName = i18n.TKey(language, (*arr)[i].Roles[ri].RoleName)
|
||
}
|
||
}
|
||
}
|
||
converI18n(language, &rows)
|
||
|
||
c.JSON(200, result.Ok(data))
|
||
}
|
||
|
||
// 用户信息详情
|
||
//
|
||
// GET /:userId
|
||
func (s *SysUserController) Info(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
userId := c.Param("userId")
|
||
if userId == "" {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
|
||
// 查询系统角色列表
|
||
dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "")
|
||
roles := s.sysRoleService.SelectRoleList(model.SysRole{}, dataScopeSQL)
|
||
|
||
// 不是系统指定管理员需要排除其角色
|
||
if !config.IsAdmin(userId) {
|
||
rolesFilter := make([]model.SysRole, 0)
|
||
for _, r := range roles {
|
||
if r.RoleID != admin.ROLE_ID {
|
||
rolesFilter = append(rolesFilter, r)
|
||
}
|
||
}
|
||
roles = rolesFilter
|
||
}
|
||
|
||
// 闭包函数处理多语言
|
||
converI18nRoles := func(language string, arr *[]model.SysRole) {
|
||
for i := range *arr {
|
||
(*arr)[i].RoleName = i18n.TKey(language, (*arr)[i].RoleName)
|
||
(*arr)[i].Remark = i18n.TKey(language, (*arr)[i].Remark)
|
||
}
|
||
}
|
||
converI18nRoles(language, &roles)
|
||
|
||
// 查询系统岗位列表
|
||
posts := s.sysPostService.SelectPostList(model.SysPost{})
|
||
|
||
// 闭包函数处理多语言
|
||
converI18nPosts := func(language string, arr *[]model.SysPost) {
|
||
for i := range *arr {
|
||
(*arr)[i].PostName = i18n.TKey(language, (*arr)[i].PostName)
|
||
(*arr)[i].Remark = i18n.TKey(language, (*arr)[i].Remark)
|
||
}
|
||
}
|
||
converI18nPosts(language, &posts)
|
||
|
||
// 新增用户时,用户ID为0
|
||
if userId == "0" {
|
||
c.JSON(200, result.OkData(map[string]any{
|
||
"user": map[string]any{},
|
||
"roleIds": []string{},
|
||
"postIds": []string{},
|
||
"roles": roles,
|
||
"posts": posts,
|
||
}))
|
||
return
|
||
}
|
||
|
||
// 检查用户是否存在
|
||
user := s.sysUserService.SelectUserById(userId)
|
||
if user.UserID != userId {
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.noData")))
|
||
return
|
||
}
|
||
|
||
// 处理多语言
|
||
user.NickName = i18n.TKey(language, user.NickName)
|
||
user.Remark = i18n.TKey(language, user.Remark)
|
||
user.Dept.DeptName = i18n.TKey(language, user.Dept.DeptName)
|
||
for ri := range user.Roles {
|
||
user.Roles[ri].RoleName = i18n.TKey(language, user.Roles[ri].RoleName)
|
||
}
|
||
|
||
// 角色ID组
|
||
roleIds := make([]string, 0)
|
||
for _, r := range user.Roles {
|
||
roleIds = append(roleIds, r.RoleID)
|
||
}
|
||
|
||
// 岗位ID组
|
||
postIds := make([]string, 0)
|
||
userPosts := s.sysPostService.SelectPostListByUserId(userId)
|
||
for _, p := range userPosts {
|
||
postIds = append(postIds, p.PostID)
|
||
}
|
||
|
||
c.JSON(200, result.OkData(map[string]any{
|
||
"user": user,
|
||
"roleIds": roleIds,
|
||
"postIds": postIds,
|
||
"roles": roles,
|
||
"posts": posts,
|
||
}))
|
||
}
|
||
|
||
// 用户信息新增
|
||
//
|
||
// POST /
|
||
func (s *SysUserController) Add(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
var body model.SysUser
|
||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||
if err != nil || body.UserID != "" {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
|
||
// 密码单独取,避免序列化输出
|
||
var bodyPassword struct {
|
||
Password string `json:"password" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindBodyWith(&bodyPassword, binding.JSON); err != nil {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
body.Password = bodyPassword.Password
|
||
|
||
// 检查用户登录账号是否唯一
|
||
uniqueUserName := s.sysUserService.CheckUniqueUserName(body.UserName, "")
|
||
if !uniqueUserName {
|
||
// 新增用户【%s】失败,登录账号已存在
|
||
// msg := fmt.Sprintf("Failed to add user [%s], login account already exists", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errNameExists", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
|
||
// 检查手机号码格式并判断是否唯一
|
||
if body.PhoneNumber != "" {
|
||
if regular.ValidMobile(body.PhoneNumber) {
|
||
uniquePhone := s.sysUserService.CheckUniquePhone(body.PhoneNumber, "")
|
||
if !uniquePhone {
|
||
// 新增用户【%s】失败,手机号码已存在
|
||
// msg := fmt.Sprintf("Failed to add user [%s], cell phone number already exists", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errPhoneExists", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
} else {
|
||
// 新增用户【%s】失败,手机号码格式错误
|
||
// msg := fmt.Sprintf("Failed to add user [%s], wrong format of cell phone number", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errPhoneFormat", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
}
|
||
|
||
// 检查邮箱格式并判断是否唯一
|
||
if body.Email != "" {
|
||
if regular.ValidEmail(body.Email) {
|
||
uniqueEmail := s.sysUserService.CheckUniqueEmail(body.Email, "")
|
||
if !uniqueEmail {
|
||
// 新增用户【%s】失败,邮箱已存在
|
||
// msg := fmt.Sprintf("Failed to add user [%s], mailbox already exists", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errEmailExists", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
} else {
|
||
// 新增用户【%s】失败,邮箱格式错误
|
||
// msg := fmt.Sprintf("Failed to add user [%s], mailbox format error", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errEmailFormat", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
}
|
||
|
||
body.CreateBy = ctx.LoginUserToUserName(c)
|
||
insertId := s.sysUserService.InsertUser(body)
|
||
if insertId != "" {
|
||
c.JSON(200, result.Ok(nil))
|
||
return
|
||
}
|
||
c.JSON(200, result.Err(nil))
|
||
}
|
||
|
||
// 用户信息修改
|
||
//
|
||
// POST /
|
||
func (s *SysUserController) Edit(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
var body model.SysUser
|
||
err := c.ShouldBindBodyWith(&body, binding.JSON)
|
||
if err != nil || body.UserID == "" {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
|
||
// 检查是否管理员用户
|
||
if config.IsAdmin(body.UserID) {
|
||
// 不允许操作管理员用户
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.errOperateAdmin")))
|
||
return
|
||
}
|
||
|
||
user := s.sysUserService.SelectUserById(body.UserID)
|
||
if user.UserID != body.UserID {
|
||
// 没有可访问用户数据!
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.noData")))
|
||
return
|
||
}
|
||
|
||
// 检查用户登录账号是否唯一
|
||
uniqueUserName := s.sysUserService.CheckUniqueUserName(body.UserName, body.UserID)
|
||
if !uniqueUserName {
|
||
// 修改用户【%s】失败,登录账号已存在
|
||
// msg := fmt.Sprintf("Failed to modify user [%s], login account already exists", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errNameExists", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
|
||
// 检查手机号码格式并判断是否唯一
|
||
if body.PhoneNumber != "" {
|
||
if regular.ValidMobile(body.PhoneNumber) {
|
||
uniquePhone := s.sysUserService.CheckUniquePhone(body.PhoneNumber, body.UserID)
|
||
if !uniquePhone {
|
||
// 修改用户【%s】失败,手机号码已存在
|
||
// msg := fmt.Sprintf("Failed to modify user [%s], cell phone number already exists", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errPhoneExists", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
} else {
|
||
// 修改用户【%s】失败,手机号码格式错误
|
||
// msg := fmt.Sprintf("Failed to modify user [%s], wrong format of cell phone number", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errPhoneFormat", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
}
|
||
|
||
// 检查邮箱格式并判断是否唯一
|
||
if body.Email != "" {
|
||
if regular.ValidEmail(body.Email) {
|
||
uniqueEmail := s.sysUserService.CheckUniqueEmail(body.Email, body.UserID)
|
||
if !uniqueEmail {
|
||
// 修改用户【%s】失败,邮箱已存在
|
||
// msg := fmt.Sprintf("Failed to modify user [%s], mailbox already exists", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errEmailExists", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
} else {
|
||
// 修改用户【%s】失败,邮箱格式错误
|
||
// msg := fmt.Sprintf("Failed to modify user [%s], mailbox format error", body.UserName)
|
||
msg := i18n.TTemplate(language, "user.errEmailFormat", map[string]any{"name": body.UserName})
|
||
c.JSON(200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
}
|
||
|
||
body.UserName = "" // 忽略修改登录用户名称
|
||
body.Password = "" // 忽略修改密码
|
||
body.LoginIP = "" // 忽略登录IP
|
||
body.LoginDate = 0 // 忽略登录时间
|
||
body.UpdateBy = ctx.LoginUserToUserName(c)
|
||
rows := s.sysUserService.UpdateUserAndRolePost(body)
|
||
if rows > 0 {
|
||
c.JSON(200, result.Ok(nil))
|
||
return
|
||
}
|
||
c.JSON(200, result.Err(nil))
|
||
}
|
||
|
||
// 用户信息删除
|
||
//
|
||
// DELETE /:userIds
|
||
func (s *SysUserController) Remove(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
userIds := c.Param("userIds")
|
||
if userIds == "" {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
// 处理字符转id数组后去重
|
||
ids := strings.Split(userIds, ",")
|
||
uniqueIDs := parse.RemoveDuplicates(ids)
|
||
if len(uniqueIDs) <= 0 {
|
||
c.JSON(200, result.Err(nil))
|
||
return
|
||
}
|
||
|
||
// 检查是否管理员用户
|
||
for _, id := range uniqueIDs {
|
||
if config.IsAdmin(id) {
|
||
// 不允许操作管理员用户
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.errOperateAdmin")))
|
||
return
|
||
}
|
||
}
|
||
|
||
rows, err := s.sysUserService.DeleteUserByIds(uniqueIDs)
|
||
if err != nil {
|
||
c.JSON(200, result.ErrMsg(err.Error()))
|
||
return
|
||
}
|
||
// 删除成功:%d
|
||
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||
c.JSON(200, result.OkMsg(msg))
|
||
}
|
||
|
||
// 用户重置密码
|
||
//
|
||
// PUT /resetPwd
|
||
func (s *SysUserController) ResetPwd(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
var body struct {
|
||
UserID string `json:"userId" binding:"required"`
|
||
Password string `json:"password" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
|
||
// 检查是否管理员用户
|
||
if config.IsAdmin(body.UserID) {
|
||
// 不允许操作内置用户
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.errOperateAdmin")))
|
||
return
|
||
}
|
||
|
||
user := s.sysUserService.SelectUserById(body.UserID)
|
||
if user.UserID != body.UserID {
|
||
// 没有可访问用户数据!
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.noData")))
|
||
return
|
||
}
|
||
if !regular.ValidPassword(body.Password) {
|
||
// 登录密码至少包含大小写字母、数字、特殊符号,且不少于6位
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.errPasswd")))
|
||
return
|
||
}
|
||
|
||
userName := ctx.LoginUserToUserName(c)
|
||
info := model.SysUser{
|
||
UserID: body.UserID,
|
||
Password: body.Password,
|
||
UpdateBy: userName,
|
||
}
|
||
rows := s.sysUserService.UpdateUser(info)
|
||
if rows > 0 {
|
||
c.JSON(200, result.Ok(nil))
|
||
return
|
||
}
|
||
c.JSON(200, result.Err(nil))
|
||
}
|
||
|
||
// 用户状态修改
|
||
//
|
||
// PUT /changeStatus
|
||
func (s *SysUserController) Status(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
var body struct {
|
||
UserID string `json:"userId" binding:"required"`
|
||
Status string `json:"status" binding:"required"`
|
||
}
|
||
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
|
||
// 检查是否存在
|
||
user := s.sysUserService.SelectUserById(body.UserID)
|
||
if user.UserID != body.UserID {
|
||
// 没有可访问用户数据!
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.noData")))
|
||
return
|
||
}
|
||
|
||
// 与旧值相等不变更
|
||
if user.Status == body.Status {
|
||
// 变更状态与旧值相等!
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.statusEq")))
|
||
return
|
||
}
|
||
|
||
userName := ctx.LoginUserToUserName(c)
|
||
info := model.SysUser{
|
||
UserID: body.UserID,
|
||
Status: body.Status,
|
||
UpdateBy: userName,
|
||
}
|
||
rows := s.sysUserService.UpdateUser(info)
|
||
if rows > 0 {
|
||
c.JSON(200, result.Ok(nil))
|
||
return
|
||
}
|
||
c.JSON(200, result.Err(nil))
|
||
}
|
||
|
||
// 用户信息列表导出
|
||
//
|
||
// POST /export
|
||
func (s *SysUserController) Export(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
// 查询结果,根据查询条件结果,单页最大值限制
|
||
// querys := ctx.BodyJSONMap(c)
|
||
querys := map[string]any{
|
||
"pageNum": 1,
|
||
"pageSize": 1000,
|
||
}
|
||
dataScopeSQL := ctx.LoginUserToDataScopeSQL(c, "d", "u")
|
||
data := s.sysUserService.SelectUserPage(querys, dataScopeSQL)
|
||
if data["total"].(int64) == 0 {
|
||
// 导出数据记录为空
|
||
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.exportEmpty")))
|
||
return
|
||
}
|
||
rows := data["rows"].([]model.SysUser)
|
||
|
||
// 闭包函数处理多语言
|
||
converI18n := func(language string, arr *[]model.SysUser) {
|
||
for i := range *arr {
|
||
(*arr)[i].NickName = i18n.TKey(language, (*arr)[i].NickName)
|
||
(*arr)[i].Remark = i18n.TKey(language, (*arr)[i].Remark)
|
||
(*arr)[i].Dept.DeptName = i18n.TKey(language, (*arr)[i].Dept.DeptName)
|
||
for ri := range (*arr)[i].Roles {
|
||
(*arr)[i].Roles[ri].RoleName = i18n.TKey(language, (*arr)[i].Roles[ri].RoleName)
|
||
}
|
||
}
|
||
}
|
||
converI18n(language, &rows)
|
||
|
||
// 导出文件名称
|
||
fileName := fmt.Sprintf("user_export_%d_%d.xlsx", len(rows), time.Now().UnixMilli())
|
||
// 第一行表头标题
|
||
headerCells := map[string]string{
|
||
"A1": i18n.TKey(language, "user.export.id"),
|
||
"B1": i18n.TKey(language, "user.export.name"),
|
||
"C1": i18n.TKey(language, "user.export.nick"),
|
||
"D1": i18n.TKey(language, "user.export.role"),
|
||
"E1": i18n.TKey(language, "user.export.deptName"),
|
||
"F1": i18n.TKey(language, "user.export.loginIP"),
|
||
"G1": i18n.TKey(language, "user.export.loginDate"),
|
||
"H1": i18n.TKey(language, "user.export.status"),
|
||
// "F1": i18n.TKey(language, "user.export.sex"),
|
||
// "E1": i18n.TKey(language, "user.export.phone"),
|
||
// "D1": i18n.TKey(language, "user.export.email"),
|
||
// "I1": i18n.TKey(language, "user.export.deptID"),
|
||
// "K1": i18n.TKey(language, "user.export.deptLeader"),
|
||
}
|
||
// 读取用户性别字典数据
|
||
// dictSysUserSex := s.sysDictDataService.SelectDictDataByType("sys_user_sex")
|
||
// 从第二行开始的数据
|
||
dataCells := make([]map[string]any, 0)
|
||
for i, row := range rows {
|
||
idx := strconv.Itoa(i + 2)
|
||
// 用户性别
|
||
// sysUserSex := row.Sex
|
||
// for _, v := range dictSysUserSex {
|
||
// if row.Sex == v.DictValue {
|
||
// sysUserSex = i18n.TKey(language, v.DictLabel)
|
||
// break
|
||
// }
|
||
// }
|
||
// 帐号状态
|
||
statusValue := i18n.TKey(language, "dictData.disable")
|
||
if row.Status == "1" {
|
||
statusValue = i18n.TKey(language, "dictData.normal")
|
||
}
|
||
// 用户角色, 默认导出首个
|
||
userRole := ""
|
||
if len(row.Roles) > 0 {
|
||
userRole = i18n.TKey(language, row.Roles[0].RoleName)
|
||
}
|
||
dataCells = append(dataCells, map[string]any{
|
||
"A" + idx: row.UserID,
|
||
"B" + idx: row.UserName,
|
||
"C" + idx: row.NickName,
|
||
"D" + idx: userRole,
|
||
"E" + idx: row.Dept.DeptName,
|
||
"F" + idx: row.LoginIP,
|
||
"G" + idx: date.ParseDateToStr(row.LoginDate, date.YYYY_MM_DD_HH_MM_SS),
|
||
"H" + idx: statusValue,
|
||
// "E" + idx: row.PhoneNumber,
|
||
// "F" + idx: sysUserSex,
|
||
// "D" + idx: row.Email,
|
||
// "I" + idx: row.Dept.DeptID,
|
||
// "K" + idx: row.Dept.Leader,
|
||
})
|
||
}
|
||
|
||
// 导出数据表格
|
||
saveFilePath, err := file.WriteSheet(headerCells, dataCells, fileName, "")
|
||
if err != nil {
|
||
c.JSON(200, result.ErrMsg(err.Error()))
|
||
return
|
||
}
|
||
|
||
c.FileAttachment(saveFilePath, fileName)
|
||
}
|
||
|
||
// 用户信息列表导入模板下载
|
||
//
|
||
// GET /importTemplate
|
||
func (s *SysUserController) Template(c *gin.Context) {
|
||
fileName := fmt.Sprintf("user_import_template_%d.xlsx", time.Now().UnixMilli())
|
||
|
||
// 多语言处理
|
||
language := ctx.AcceptLanguage(c)
|
||
asserPath := fmt.Sprintf("assets/template/excel/user_import_template_%s.xlsx", language)
|
||
|
||
// 从 embed.FS 中读取默认配置文件内容
|
||
assetsDir := config.GetAssetsDirFS()
|
||
// 读取内嵌文件
|
||
fileData, err := assetsDir.ReadFile(asserPath)
|
||
if err != nil {
|
||
c.String(500, "Failed to read file")
|
||
return
|
||
}
|
||
|
||
// 设置响应头
|
||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
|
||
c.Header("Content-Type", "application/octet-stream")
|
||
|
||
// 返回响应体
|
||
c.Data(200, "application/octet-stream", fileData)
|
||
}
|
||
|
||
// 用户信息列表导入
|
||
//
|
||
// POST /importData
|
||
func (s *SysUserController) ImportData(c *gin.Context) {
|
||
language := ctx.AcceptLanguage(c)
|
||
// 允许进行更新
|
||
updateSupport := c.PostForm("updateSupport")
|
||
// 上传的文件
|
||
formFile, err := c.FormFile("file")
|
||
if err != nil || updateSupport == "" {
|
||
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||
return
|
||
}
|
||
|
||
// 保存表格文件
|
||
filePath, err := file.TransferExeclUploadFile(formFile)
|
||
if err != nil {
|
||
c.JSON(200, result.ErrMsg(err.Error()))
|
||
return
|
||
}
|
||
|
||
// 读取表格数据
|
||
rows, err := file.ReadSheet(filePath, "")
|
||
if err != nil {
|
||
c.JSON(200, result.ErrMsg(err.Error()))
|
||
return
|
||
}
|
||
|
||
// 获取操作人名称
|
||
operName := ctx.LoginUserToUserName(c)
|
||
isUpdateSupport := parse.Boolean(updateSupport)
|
||
|
||
// 读取默认初始密码
|
||
initPassword := s.sysConfigService.SelectConfigValueByKey("sys.user.initPassword")
|
||
// 读取用户性别字典数据
|
||
dictSysUserSex := s.sysDictDataService.SelectDictDataByType("sys_user_sex")
|
||
|
||
// 导入记录
|
||
successNum := 0
|
||
failureNum := 0
|
||
successMsgArr := []string{}
|
||
failureMsgArr := []string{}
|
||
mustItemArr := []string{"B", "C"}
|
||
for _, row := range rows {
|
||
// 检查必填列
|
||
ownItem := true
|
||
for _, item := range mustItemArr {
|
||
if v, ok := row[item]; !ok || v == "" {
|
||
ownItem = false
|
||
break
|
||
}
|
||
}
|
||
if !ownItem {
|
||
mustItemArrStr := strings.Join(mustItemArr, "、")
|
||
failureNum++
|
||
// 表格中必填列表项,
|
||
msg := i18n.TTemplate(language, "user.import.mustItem", map[string]any{"text": mustItemArrStr})
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
continue
|
||
}
|
||
|
||
// 用户性别转值
|
||
sysUserSex := "0"
|
||
for _, v := range dictSysUserSex {
|
||
label := i18n.TKey(language, v.DictLabel)
|
||
if row["F"] == label {
|
||
sysUserSex = v.DictValue
|
||
break
|
||
}
|
||
}
|
||
// 用户状态
|
||
sysUserStatus := common.STATUS_NO
|
||
if row["G"] == "正常" || row["G"] == "Normal" {
|
||
sysUserStatus = common.STATUS_YES
|
||
}
|
||
// 用户角色 拿编号
|
||
sysUserRole := ""
|
||
if v, ok := row["H"]; ok && v != "" {
|
||
sysUserRole = strings.SplitN(v, "-", 2)[0]
|
||
if sysUserRole == "1" {
|
||
sysUserRole = ""
|
||
}
|
||
}
|
||
|
||
// 构建用户实体信息
|
||
newSysUser := model.SysUser{
|
||
UserType: "sys",
|
||
Password: initPassword,
|
||
DeptID: row["I"],
|
||
UserName: row["B"],
|
||
NickName: row["C"],
|
||
PhoneNumber: row["E"],
|
||
Email: row["D"],
|
||
Status: sysUserStatus,
|
||
Sex: sysUserSex,
|
||
RoleIDs: []string{sysUserRole},
|
||
}
|
||
|
||
// 检查手机号码格式并判断是否唯一
|
||
if newSysUser.PhoneNumber != "" {
|
||
if regular.ValidMobile(newSysUser.PhoneNumber) {
|
||
uniquePhone := s.sysUserService.CheckUniquePhone(newSysUser.PhoneNumber, "")
|
||
if !uniquePhone {
|
||
// 用户编号:%s 手机号码 %s 已存在
|
||
msg := i18n.TTemplate(language, "user.import.phoneExist", map[string]any{"id": row["A"], "phone": newSysUser.PhoneNumber})
|
||
failureNum++
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
continue
|
||
}
|
||
} else {
|
||
// 用户编号:%s 手机号码 %s 格式错误
|
||
msg := i18n.TTemplate(language, "user.import.phoneFormat", map[string]any{"id": row["A"], "phone": newSysUser.PhoneNumber})
|
||
failureNum++
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
continue
|
||
}
|
||
}
|
||
|
||
// 检查邮箱格式并判断是否唯一
|
||
if newSysUser.Email != "" {
|
||
if regular.ValidEmail(newSysUser.Email) {
|
||
uniqueEmail := s.sysUserService.CheckUniqueEmail(newSysUser.Email, "")
|
||
if !uniqueEmail {
|
||
// 用户编号:%s 用户邮箱 %s 已存在
|
||
msg := i18n.TTemplate(language, "user.import.emailExist", map[string]any{"id": row["A"], "email": newSysUser.Email})
|
||
failureNum++
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
continue
|
||
}
|
||
} else {
|
||
// 用户编号:%s 用户邮箱 %s 格式错误
|
||
msg := i18n.TTemplate(language, "user.import.emailFormat", map[string]any{"id": row["A"], "email": newSysUser.Email})
|
||
failureNum++
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
continue
|
||
}
|
||
}
|
||
|
||
// 验证是否存在这个用户
|
||
userInfo := s.sysUserService.SelectUserByUserName(newSysUser.UserName)
|
||
if userInfo.UserName != newSysUser.UserName {
|
||
newSysUser.CreateBy = operName
|
||
insertId := s.sysUserService.InsertUser(newSysUser)
|
||
if insertId != "" {
|
||
// 用户编号:%s 登录名称 %s 导入成功
|
||
msg := i18n.TTemplate(language, "user.import.success", map[string]any{"id": row["A"], "name": newSysUser.UserName})
|
||
successNum++
|
||
successMsgArr = append(successMsgArr, msg)
|
||
} else {
|
||
// 用户编号:%s 登录名称 %s 导入失败
|
||
msg := i18n.TTemplate(language, "user.import.fail", map[string]any{"id": row["A"], "name": newSysUser.UserName})
|
||
failureNum++
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
}
|
||
continue
|
||
}
|
||
|
||
// 如果用户已存在 同时 是否更新支持
|
||
if userInfo.UserName == newSysUser.UserName && isUpdateSupport {
|
||
newSysUser.UserID = userInfo.UserID
|
||
newSysUser.UpdateBy = operName
|
||
rows := s.sysUserService.UpdateUser(newSysUser)
|
||
if rows > 0 {
|
||
// 用户编号:%s 登录名称 %s 更新成功
|
||
msg := i18n.TTemplate(language, "user.import.successUpdate", map[string]any{"id": row["A"], "name": newSysUser.UserName})
|
||
successNum++
|
||
successMsgArr = append(successMsgArr, msg)
|
||
} else {
|
||
// 用户编号:%s 登录名称 %s 更新失败
|
||
msg := i18n.TTemplate(language, "user.import.failUpdate", map[string]any{"id": row["A"], "name": newSysUser.UserName})
|
||
failureNum++
|
||
failureMsgArr = append(failureMsgArr, msg)
|
||
}
|
||
continue
|
||
}
|
||
}
|
||
|
||
message := ""
|
||
if failureNum > 0 {
|
||
// 很抱歉,导入失败!共 %d 条数据格式不正确,错误如下:
|
||
msg := i18n.TTemplate(language, "user.import.failTip", map[string]any{"num": failureNum})
|
||
message = strings.Join(append([]string{msg}, failureMsgArr...), "<br/>")
|
||
} else {
|
||
// 恭喜您,数据已全部导入成功!共 %d 条,数据如下:
|
||
msg := i18n.TTemplate(language, "user.import.successTip", map[string]any{"num": successNum})
|
||
message = strings.Join(append([]string{msg}, successMsgArr...), "<br/>")
|
||
}
|
||
|
||
c.JSON(200, result.OkMsg(message))
|
||
}
|