go语言实现用户管理系统

goweb实现用户管理系统

用户后台管理系统功能描述

登录功能

  1. 支持用户通过邮箱密码和密码进行登录。
  2. 对输入的邮箱和密码进行验证,确保用户信息的正确性。
  3. 登录成功后,更新用户的今日登录统计信息,并将用户信息存入会话(cookie)中,便于后续操作。
  4. 提供友好的错误提示,如“用户不存在”“密码错误”“用户已被禁用”等,帮助用户了解登录失败的原因。

在这里插入图片描述

package serviceimport ("UserManager/src/mapper""UserManager/src/utils""fmt""golang.org/x/crypto/bcrypt"
)type LoginService struct {Mapper *mapper.LoginMapper
}func NewLoginService(lm *mapper.LoginMapper) *LoginService {return &LoginService{Mapper: lm,}
}// 用户登录
func (ls *LoginService) LoginUser(email string, password string) (string, error) {user, err := ls.Mapper.GetUserByEmail(email)if err != nil || user == nil {return "", fmt.Errorf("用户不存在")}//验证密码if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)); err != nil {return "", fmt.Errorf("密码错误")}fmt.Println("hhh", user)if user.Status == 0 {return "", fmt.Errorf("用户已被禁用")}//生成JWTtoken, err := utils.GenerateToken(user)if err != nil {return "", fmt.Errorf("生成令牌失败")}return token, nil
}

注册功能

  1. 允许用户输入邮箱、验证码,密码及确认密码进行注册。
  2. 对邮箱进行唯一性校验,避免重复注册,并发送验证码。
  3. 检查两次输入的密码是否一致,确保用户密码的准确性。
  4. 使用 bcrypt 算法对用户密码进行加密存储,保障用户密码的安全性。
  5. 注册成功后,自动增加今日新增人数统计。

在这里插入图片描述

package serviceimport ("UserManager/src/mapper""UserManager/src/models""UserManager/src/utils""fmt""github.com/google/uuid""golang.org/x/crypto/bcrypt""regexp"
)// VerificationInfo 保存验证码及其过期时间type RegisterService struct {Mapper              *mapper.RegisterMapperEmailService        *utils.EmailServiceVerificationService *utils.VerificationService
}func NewRegisterService(rm *mapper.RegisterMapper, emailService *utils.EmailService, vService *utils.VerificationService) *RegisterService {return &RegisterService{Mapper:              rm,EmailService:        emailService,VerificationService: vService,}
}// SendVerificationCode 生成验证码,并使用 Redis 存储(有效期5分钟)后发送邮件
func (rs *RegisterService) SendVerificationCode(email string) error {code, err := rs.VerificationService.GenerateAndStoreCode(email)if err != nil {return err}subject := "您的验证码"body := fmt.Sprintf("您的验证码为:%s,请勿泄露于他人!该验证码5分钟内有效!如非本人操作,请忽略此邮件!。", code)return rs.EmailService.SendEmail(email, subject, body)
}// 用户注册
func (rs *RegisterService) RegisterUser(email, inputCode, password, passwordConfirm string) error {if !isValidPassword(password) {return fmt.Errorf("密码必须是8-12位字母和数字组合")}if password != passwordConfirm {return fmt.Errorf("两次密码输入不一致")}// 验证验证码if err := rs.VerificationService.VerifyCode(email, inputCode); err != nil {return err}// 检查邮箱是否已注册if user, _ := rs.Mapper.GetUserByEmail(email); user != nil {return fmt.Errorf("邮箱已注册")}// 加密密码hashed, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)if err != nil {return fmt.Errorf("密码加密失败:%v", err)}// 插入新用户newUser := &models.User{Email:        email,PasswordHash: string(hashed),Nickname:     "user_" + uuid.New().String()[:8],}if err := rs.Mapper.InsertUser(newUser); err != nil {return fmt.Errorf("用户注册失败:%v", err)}return nil
}// isValidPassword 校验密码是否满足8-12位字母和数字组合
func isValidPassword(password string) bool {// 1. 检查长度是否为8-12位if len(password) < 8 || len(password) > 12 {return false}// 2. 检查是否只包含字母和数字validChars, err := regexp.MatchString(`^[0-9A-Za-z]+$`, password)if err != nil || !validChars {return false}// 3. 检查是否至少包含一个字母hasLetter, err := regexp.MatchString(`[A-Za-z]`, password)if err != nil || !hasLetter {return false}// 4. 检查是否至少包含一个数字hasDigit, err := regexp.MatchString(`\d`, password)if err != nil || !hasDigit {return false}return true
}

用户管理

用户列表展示

在这里插入图片描述

  1. 以分页的形式展示系统中的用户列表,每页显示固定数量的用户记录。
  2. 提供用户的基本信息,包括用户名、角色、状态、邮箱、头像、注册时间等,方便管理员快速了解用户情况。
  3. 根据当前页码和总记录数,动态计算并显示分页导航栏,方便管理员切换页面查看不同用户数据。
用户搜索
  1. 支持管理员通过用户名关键字进行用户搜索,快速定位目标用户。
  2. 搜索结果同样以分页形式展示,方便查看大量用户数据。
  3. 提供搜索结果的总记录数、总页数等信息,帮助管理员了解搜索结果的范围。
用户创建

在这里插入图片描述

**

  1. 管理员可以输入用户名、密码、邮箱、角色、状态等信息创建新用户。
  2. 对输入的用户信息进行校验,如用户名是否已存在、必填项是否填写等。
  3. 支持上传用户头像,并对上传的文件进行类型、大小校验,确保头像的合法性。 创建成功后,自动更新今日新增人数统计。
用户更新

在这里插入图片描述

  1. 管理员可以对现有用户的信息进行修改,包括用户名、密码、邮箱、角色、状态、头像等。
  2. 在修改密码时,只有当用户输入了新密码时才会进行密码更新,并且会对新密码进行加密处理。
  3. 对修改后的用户信息进行校验,如用户名是否被其他用户占用等。
  4. 更新成功后,返回更新后的用户头像路径等信息。
用户删除

在这里插入图片描述

  1. 管理员可以删除指定的用户,但不允许删除当前登录用户自己。
  2. 删除用户时,同时删除该用户的头像文件(如果头像不是默认头像)。
  3. 删除成功后,自动更新今日被删除人数统计。
package serviceimport ("UserManager/src/mapper""UserManager/src/models""UserManager/src/utils""errors""fmt""golang.org/x/crypto/bcrypt""io"
)type UserService struct {Mapper *mapper.UserMapper
}func NewUserService(hm *mapper.UserMapper) *UserService {return &UserService{Mapper: hm,}
}// GetUsers 支持分页 + 搜索 + 状态筛选
func (us *UserService) GetUsers(keyword, statusStr string, page, pageSize int) ([]*models.User, int, error) {// 计算 offsetoffset := (page - 1) * pageSize// 委托 Mapper 执行查询并返回总数return us.Mapper.QueryUsersWithPage(keyword, statusStr, offset, pageSize)
}// 新增用户
func (us *UserService) CreateUser(email, passwordHash, nickname string, avatarFile io.Reader, avatarFileName string, role, status int) (*models.User, error) {// 上传头像到 OSSavatarURL, err := utils.UploadFileToOSS(avatarFile, avatarFileName)if err != nil {return nil, err}// 检查邮箱是否已注册if user, _ := us.Mapper.GetUserByEmail(email); user != nil {return nil, errors.New("邮箱已注册,请使用其他邮箱")}// 加密密码hashed, err := bcrypt.GenerateFromPassword([]byte(passwordHash), bcrypt.DefaultCost)if err != nil {return nil, errors.New("密码加密失败")}user := &models.User{Email:        email,PasswordHash: string(hashed),Nickname:     nickname,AvatarUrl:    avatarURL,Role:         role,Status:       status,}if err := us.Mapper.CreateUser(user); err != nil {return nil, err}return user, nil
}func (us *UserService) UpdateUser(id int, email, passwordHash, nickname string, avatarFile io.Reader, avatarFileName string, role, status int) (*models.User, error) {// 1. 先取出数据库中的原用户user, err := us.Mapper.GetUserByID(id)if err != nil {return nil, err}// 2. 如果邮箱被修改,检查是否重复if email != user.Email {if existing, _ := us.Mapper.GetUserByEmail(email); existing != nil {return nil, errors.New("邮箱已注册,请使用其他邮箱")}}// 3. 更新基本字段user.Email = emailuser.Nickname = nicknameuser.Role = roleuser.Status = status// 4. 如果前端传了非空密码,才加密并更新if passwordHash != "" {if !isValidPassword(passwordHash) {return nil, fmt.Errorf("密码必须是8-12位字母和数字组合")}hashed, err := bcrypt.GenerateFromPassword([]byte(passwordHash), bcrypt.DefaultCost)if err != nil {return nil, errors.New("密码加密失败")}user.PasswordHash = string(hashed)}// 5. 如果前端上传了新头像,才上传并更新 URLif avatarFile != nil {url, err := utils.UploadFileToOSS(avatarFile, avatarFileName)if err != nil {return nil, err}user.AvatarUrl = url}// 6. 写回数据库if err := us.Mapper.UpdateUser(user); err != nil {return nil, err}return user, nil
}// 根据用户 ID 获取用户信息
func (us *UserService) GetUserByID(id int) (*models.User, error) {return us.Mapper.GetUserByID(id)
}// 删除用户信息
func (us *UserService) DeleteUser(id int) error {return us.Mapper.DeleteUser(id)
}

用户统计与数据展示

首页统计信息展示
  1. 在系统首页展示一些关键的用户统计数据,如总用户数、本月登录人次、注销用户数量等。
    提供登录增长率、用户增长率、注销用户增长率等指标,帮助管理员了解系统的整体发展趋势
  2. 展示过去 30天的登录趋势图表,以日期为维度展示每日的登录次数,方便管理员观察登录量的变化趋势。
  3. 相关的统计信息(如今日登录人数、今日新增人数、今日被删除人数)会随着用户的登录、注册、删除等操作实时更新,确保数据的准确性和时效性。

在这里插入图片描述
在这里插入图片描述

package serviceimport ("UserManager/src/mapper""time"
)type HomeService struct {Mapper *mapper.HomeMapper
}// TrendData 用于返回给前端的访问趋势数据
type TrendData struct {Date  string `json:"date"`Count int    `json:"count"`
}// 仪表数据
type DashboardData struct {RegisteredUsers        int     `json:"registered_users"`Visits                 int     `json:"visits"`DeactivatedUsers       int     `json:"deactivated_users"`RegisteredUsersGrowth  float64 `json:"registered_users_growth"`VisitsGrowth           float64 `json:"visits_growth"`DeactivatedUsersGrowth float64 `json:"deactivated_users_growth"`
}func NewHomeService(hm *mapper.HomeMapper) *HomeService {return &HomeService{Mapper: hm,}
}// 获取仪表盘统计数据
func (hs *HomeService) GetDashboardStats() (DashboardData, error) {// 获取当前时间now := time.Now()currentUsers, err := hs.Mapper.CountRegisteredUsers(now)if err != nil {return DashboardData{}, err}currentVisits, err := hs.Mapper.CountVisits(time.Now())if err != nil {return DashboardData{}, err}currentDeactivated, err := hs.Mapper.CountDeactivatedUsers(time.Now())if err != nil {return DashboardData{}, err}//获取上个月的数据// 获取当前年份和月份year, month, _ := now.Date()// 计算上个月的年份和月份if month == time.January {year--month = time.December} else {month--}// 获取上个月的第一天firstOfMonth := time.Date(year, month, 1, 0, 0, 0, 0, now.Location())// 上个月的最后一天是本月第一天的前一天lastMonth := firstOfMonth.AddDate(0, 1, -1)previousUsers, err := hs.Mapper.CountRegisteredUsers(lastMonth)if err != nil {return DashboardData{}, err}previousVisits, err := hs.Mapper.CountVisits(lastMonth)if err != nil {return DashboardData{}, err}previousDeactivated, err := hs.Mapper.CountDeactivatedUsers(lastMonth)if err != nil {return DashboardData{}, err}// 计算增长率usersGrowth := calculateGrowth(previousUsers, currentUsers)visitsGrowth := calculateGrowth(previousVisits, currentVisits)deactivatedGrowth := calculateGrowth(previousDeactivated, currentDeactivated)return DashboardData{RegisteredUsers:        currentUsers,Visits:                 currentVisits,DeactivatedUsers:       currentDeactivated,RegisteredUsersGrowth:  usersGrowth,VisitsGrowth:           visitsGrowth,DeactivatedUsersGrowth: deactivatedGrowth,}, nil
}// calculateGrowth 计算增长率
func calculateGrowth(previous, current int) float64 {if previous == 0 {if current > 0 {return 100.0 // 从0增长到正数,视为100%增长}return 0.0 // 无变化}return (float64(current-previous) / float64(previous)) * 100
}
func (hs *HomeService) AddVisitCounts(userID int) error {err := hs.Mapper.AddVisitCounts(userID)if err != nil {return err}return nil
}// 根据传入天数获取访问趋势数据
func (hs *HomeService) GetAccessTrends(days int) ([]TrendData, error) {// 计算起始时间(包含当天)startTime := time.Now().AddDate(0, 0, -days+1)visits, err := hs.Mapper.GetVisitsFrom(startTime)if err != nil {return nil, err}// 初始化每天的访问计数(key 为日期字符串)trendMap := make(map[string]int)for i := 0; i < days; i++ {dateStr := time.Now().AddDate(0, 0, -i).Format("2006-01-02")trendMap[dateStr] = 0}// 遍历访问记录进行计数for _, visit := range visits {dateStr := visit.VisitTime.Format("2006-01-02")trendMap[dateStr]++}// 按时间顺序组织返回数据(例如从最早到最新)var trends []TrendDatafor i := days - 1; i >= 0; i-- {date := time.Now().AddDate(0, 0, -i).Format("2006-01-02")trends = append(trends, TrendData{Date:  date,Count: trendMap[date],})}return trends, nil
}

具体代码看我github,https://github.com/cxzgit/UserManager
另外utils下的oss.go这里你配一下就好了

package utilsimport ("fmt""github.com/aliyun/aliyun-oss-go-sdk/oss""io""time"
)// UploadFileToOSS 上传文件到 OSS,并返回公开访问的 URL
func UploadFileToOSS(file io.Reader, fileName string) (string, error) {endpoint := ""accessKeyID := ""accessKeySecret := ""bucketName := ""client, err := oss.New(endpoint, accessKeyID, accessKeySecret)if err != nil {return "", fmt.Errorf("failed to create OSS client: %w", err)}bucket, err := client.Bucket(bucketName)if err != nil {return "", fmt.Errorf("failed to get OSS bucket: %w", err)}// 生成唯一的对象 key(例如:avatars/时间戳_原文件名)objectKey := fmt.Sprintf("avatars/%d_%s", time.Now().UnixNano(), fileName)if err := bucket.PutObject(objectKey, file); err != nil {return "", fmt.Errorf("failed to upload file: %w", err)}// 假设 bucket 为公共读,构造公开访问的 URLossURL := fmt.Sprintf("https://%s.%s/%s", bucketName, endpoint, objectKey)return ossURL, nil}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79584.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch:RAG 和 grounding 的价值

作者&#xff1a;来自 Elastic Toms Mura 了解 RAG、grounding&#xff0c;以及如何通过将 LLM 连接到你的文档来减少幻觉。 更多阅读&#xff1a;Elasticsearch&#xff1a;在 Elastic 中玩转 DeepSeek R1 来实现 RAG 应用 想获得 Elastic 认证吗&#xff1f;查看下一期 Elast…

【黑马JavaWeb+AI知识梳理】后端Web基础01 - Maven

Maven Maven核心 Maven概述 定义&#xff1a; Maven是一款用于管理和构建Java项目的工具&#xff0c;是apache旗下的一个开源项目&#xff0c;基于项目对象模型&#xff08;POM&#xff0c;project object model&#xff09;的概念&#xff0c;通过一小段描述信息来管理项目的…

C语言易混淆知识点详解

C语言中容易混淆的知识点详解 C语言作为一门基础且强大的编程语言&#xff0c;有许多容易混淆的概念和特性。以下是C语言中一些常见易混淆知识点的详细解析&#xff1a; 1. 指针与数组 相似点&#xff1a; c 复制 下载 int arr[10]; int *ptr arr; 都可以使用[]运算符访…

MCP原理详解及实战案例(动嘴出UI稿、3D建模)

文章目录 MCP 原理介绍架构核心组件协议层传输层连接生命周期MCP与function calling: 互补关系 MCP python SDKMCP的优点 怎么用MCP&#xff1a;天气服务参考应用项目&#xff1a; REF 24年11月份&#xff0c;claude推出了模型上下文协议( MCP),作为一种潜在的解决方案&#xf…

2025年深圳杯数学建模(东三省)B题【颜色转换】原论文讲解(含完整python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2025年深圳杯数学建模&#xff08;东三省&#xff09;B题【颜色转换】完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成…

cpp学习笔记1--class

2年前学过cpp&#xff0c;但是一直没有用到&#xff0c;现在要读研了&#xff0c;终于要用到了&#xff0c;重新拿出来看一看&#xff0c;觉得很多东西都能在c和python上看到影子。 #include "iostream" class Person { private:std::string name;int age;public://…

基于YOLOv的目标检测训练数据构建方法研究—图像采集、标注、划分与增强一体化流程设计

在目标检测任务中,高质量的训练数据是模型性能提升的关键。本文围绕 YOLOv 系列模型,系统性地研究了目标检测训练数据的构建方法,提出了一套从图像采集、标注、数据集划分到数据增强的一体化流程设计 。通过多源图像采集策略确保样本多样性,结合 LabelImg 工具完成 VOC 格式…

SQL数据库操作大全:从基础到高级查询技巧

大家好&#xff0c;欢迎来到程序视点&#xff01;我是你们的老朋友.小二&#xff01; SQL数据库操作核心语法精要 数据库基础操作 创建/删除数据库&#xff1a;CREATE DATABASE / DROP DATABASE 备份SQL Server&#xff1a;使用sp_addumpdevice和BACKUP DATABASE命令 数据库…

[2025]MySQL的事务机制是什么样的?redolog,undolog、binog三种日志的区别?二阶段提交是什么?ACID怎么保证的?主从复制的过程?

MySQL事务机制与日志系统详解 一、MySQL事务机制 1. 事务特性&#xff08;ACID&#xff09; 特性实现机制原子性(Atomicity)undo log回滚,(事务作为一个整体被执行&#xff0c;包含在其中的对数据库的操作要么全部被执行&#xff0c;要么都不执行)。一致性(Consistency)约束…

LLama-v2 权重下载

地址&#xff1a;llama模型 官方github仓库&#xff1a;llama仓库 注意点 网络代理位置&#xff1a;美国下面的国家选择 United States 克隆仓库后 运行bash download.sh输入邮箱收到的URL选择要下载的权重等待下载完成即可 有问题留言&#xff01;&#xff01;&#xff01…

zephyr OS架构下构建Nordic MCU boot

目录 概述 1. 软硬件环境 1.1 软件开发环境 1.2 硬件环境 2 MCU boot 2.1 核心功能 2.2 关键术语 2.3 重要字段介绍 3 VS-Code下创建MCU-BOOT项目 3.1 软件框架结构 3.2 创建测试项目 3.3 编译项目 3.3 固件在Flash中的分布 4 验证 4.1 烧写固件 ​ 4.2 代码…

【Mytais系列】介绍、核心概念

MyBatis 是一款优秀的 持久层框架&#xff0c;它通过简化 JDBC 操作、提供灵活的 SQL 映射能力&#xff0c;成为 Java 开发中处理数据库交互的核心工具之一。以下是 MyBatis 的核心框架和概念解析&#xff1a; 一、MyBatis 框架概述 1. 核心定位 作用&#xff1a;将 Java 对象…

IO模型和多路复用

一、IO模型的基础理解 什么是IO? IO全称是 Input/Output(输入/输出),在计算机科学里主要指程序与外部设备(硬盘、网络、用户终端等)进行数据交换的操作。首要特点是: IO通常很慢(从CPU和内存的视角看)经常需要等待外部设备响应1. 为什么要谈IO模型? 当一个程序需要…

深入理解 Bash 中的 $‘...‘ 字符串语法糖

在 Bash 脚本编程中&#xff0c;字符串处理是不可或缺的一部分。为了让开发者更高效地处理特殊字符和控制字符&#xff0c;Bash 引入了一种独特的字符串语法糖&#xff1a;$&#xff08;带单引号的 ANSI-C 风格字符串&#xff09;。这种语法来源于 C 语言的 ANSI-C 标准&#x…

用Python打造自己的专属命令行工具

在日常的开发和使用过程中&#xff0c;我们常常会编写一些实用的Python脚本&#xff0c;比如用来批量处理文件、获取系统信息等。然而&#xff0c;每次都要输入python script_name.py来运行脚本&#xff0c;时间一长难免觉得繁琐。要是能像使用系统自带的命令&#xff08;如ls、…

【KWDB 创作者计划】KWDB 2.2.0多模融合架构与分布式时序引擎

KWDB介绍 KWDB数据库是由开放原子开源基金会孵化的分布式多模数据库&#xff0c;专为AIoT场景设计&#xff0c;支持时序数据、关系数据和非结构化数据的统一管理。其核心架构采用多模融合引擎&#xff0c;集成列式时序存储、行式关系存储及自适应查询优化器&#xff0c;实现跨模…

学习Linux的第二天

如何在Linux环境下做开发 Linux的一些基操 Tips&#xff1a;平常最表层的是命令行模式&#xff0c;最多见这个默认叫做命令行模式 Vi操作是什么意思呢 就是在提示符输入vi a.c 是可以创建一个a.c这个文件并进入这个输入模式 按i可以输入代码 要退出的时候按esc 再按:(冒号…

链表操作练习

要求 现在有一个双向链表&#xff0c;里面要保存歌曲的名字&#xff1b;例如 蔡琴/渡口.mp3 我们把它定义在一个link.h文件中。 #ifndef LINK_H #define LINK_H #include <stdlib.h> #include <stdio.h> #include <string.h>typedef struct Node {//保存歌…

MATLAB制作散点图:从基础到进阶的三种类型讲解

一、什么是散点图 散点图是一种用来展示两个或多个变量之间关系的图表形式。它可以帮助我们直观地观察变量之间是否存在相关性、趋势或异常值&#xff0c;常用于数据分析的初步探索阶段。 二、三种类型散点图 1. 基本二维散点图&#xff1a;最简单、最常用 基本二维散点图的…

模块方法模式(Module Method Pattern)

&#x1f9e0; 模块方法模式&#xff08;Module Method Pattern&#xff09; 模块方法模式是一种结构型设计模式&#xff0c;它将复杂的操作分解成一系列相对简单、独立且单一职责的模块。每个模块负责完成一种具体的操作&#xff0c;其他模块或系统可以通过调用这些模块的公开…