259 lines
7.5 KiB
Go
259 lines
7.5 KiB
Go
package models
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/base64"
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
|
||
"github.com/beego/beego/v2/client/orm"
|
||
"golang.org/x/crypto/scrypt"
|
||
)
|
||
|
||
// Employee 员工模型
|
||
type Employee struct {
|
||
Id int `orm:"auto" json:"id"`
|
||
TenantId int `orm:"column(tenant_id);default(0)" json:"tenant_id"`
|
||
EmployeeNo string `orm:"column(employee_no);size(50)" json:"employee_no"`
|
||
Name string `orm:"size(50)" json:"name"`
|
||
Phone string `orm:"size(20);null" json:"phone"`
|
||
Email string `orm:"size(100);null" json:"email"`
|
||
DepartmentId int `orm:"column(department_id);null;default(0)" json:"department_id"`
|
||
PositionId int `orm:"column(position_id);null;default(0)" json:"position_id"`
|
||
Role int `orm:"column(role);null;default(0)" json:"role"` // 角色ID
|
||
BankName string `orm:"column(bank_name);size(100);null" json:"bank_name"`
|
||
BankAccount string `orm:"column(bank_account);size(50);null" json:"bank_account"`
|
||
Password string `orm:"size(255);null" json:"-"` // 不返回给前端
|
||
Salt string `orm:"size(100);null" json:"-"` // 不返回给前端
|
||
LastLoginTime *time.Time `orm:"column(last_login_time);null;type(datetime)" json:"last_login_time,omitempty"`
|
||
LastLoginIp string `orm:"column(last_login_ip);null;size(50)" json:"last_login_ip,omitempty"`
|
||
Status int8 `orm:"column(status);default(1)" json:"status"` // 1-在职,0-离职
|
||
CreateTime time.Time `orm:"column(create_time);type(datetime);auto_now_add" json:"create_time"`
|
||
UpdateTime time.Time `orm:"column(update_time);type(datetime);auto_now" json:"update_time"`
|
||
DeleteTime *time.Time `orm:"column(delete_time);null;type(datetime)" json:"delete_time,omitempty"`
|
||
}
|
||
|
||
// TableName 设置表名
|
||
func (e *Employee) TableName() string {
|
||
return "yz_tenant_employees"
|
||
}
|
||
|
||
func init() {
|
||
orm.RegisterModel(new(Employee))
|
||
}
|
||
|
||
// GetTenantEmployees 获取租户下的所有员工
|
||
func GetTenantEmployees(tenantId int) ([]*Employee, error) {
|
||
o := orm.NewOrm()
|
||
var employees []*Employee
|
||
_, err := o.QueryTable("yz_tenant_employees").
|
||
Filter("tenant_id", tenantId).
|
||
Filter("delete_time__isnull", true).
|
||
OrderBy("-create_time").
|
||
All(&employees)
|
||
return employees, err
|
||
}
|
||
|
||
// GetEmployeeById 根据ID获取员工信息
|
||
func GetEmployeeById(id int) (*Employee, error) {
|
||
o := orm.NewOrm()
|
||
employee := &Employee{Id: id}
|
||
err := o.Read(employee)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
// 检查是否已删除
|
||
if employee.DeleteTime != nil {
|
||
return nil, orm.ErrNoRows
|
||
}
|
||
return employee, nil
|
||
}
|
||
|
||
// generateSalt 生成随机盐值
|
||
func generateEmployeeSalt() (string, error) {
|
||
salt := make([]byte, 16)
|
||
_, err := rand.Read(salt)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return base64.URLEncoding.EncodeToString(salt), nil
|
||
}
|
||
|
||
// hashEmployeePassword 使用scrypt算法对密码进行加密
|
||
func hashEmployeePassword(password, salt string) (string, error) {
|
||
saltBytes, err := base64.URLEncoding.DecodeString(salt)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
const (
|
||
N = 16384
|
||
r = 8
|
||
p = 1
|
||
)
|
||
hashBytes, err := scrypt.Key([]byte(password), saltBytes, N, r, p, 32)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return base64.URLEncoding.EncodeToString(hashBytes), nil
|
||
}
|
||
|
||
// AddEmployee 添加员工(自动设置默认密码)
|
||
func AddEmployee(employee *Employee, defaultPassword string) (int64, error) {
|
||
// 生成盐值
|
||
salt, err := generateEmployeeSalt()
|
||
if err != nil {
|
||
return 0, fmt.Errorf("生成盐值失败: %v", err)
|
||
}
|
||
employee.Salt = salt
|
||
|
||
// 加密默认密码
|
||
hashedPassword, err := hashEmployeePassword(defaultPassword, salt)
|
||
if err != nil {
|
||
return 0, fmt.Errorf("密码加密失败: %v", err)
|
||
}
|
||
employee.Password = hashedPassword
|
||
|
||
o := orm.NewOrm()
|
||
id, err := o.Insert(employee)
|
||
return id, err
|
||
}
|
||
|
||
// UpdateEmployee 更新员工信息
|
||
func UpdateEmployee(employee *Employee) error {
|
||
o := orm.NewOrm()
|
||
_, err := o.Update(employee, "employee_no", "name", "phone", "email", "department_id", "position_id", "role", "bank_name", "bank_account", "status", "update_time")
|
||
return err
|
||
}
|
||
|
||
// ResetEmployeePassword 重置员工密码为默认密码
|
||
func ResetEmployeePassword(employeeId int, defaultPassword string) error {
|
||
o := orm.NewOrm()
|
||
employee := &Employee{Id: employeeId}
|
||
if err := o.Read(employee); err != nil {
|
||
return fmt.Errorf("员工不存在: %v", err)
|
||
}
|
||
|
||
// 生成新盐值
|
||
salt, err := generateEmployeeSalt()
|
||
if err != nil {
|
||
return fmt.Errorf("生成盐值失败: %v", err)
|
||
}
|
||
employee.Salt = salt
|
||
|
||
// 加密默认密码
|
||
hashedPassword, err := hashEmployeePassword(defaultPassword, salt)
|
||
if err != nil {
|
||
return fmt.Errorf("密码加密失败: %v", err)
|
||
}
|
||
employee.Password = hashedPassword
|
||
|
||
_, err = o.Update(employee, "Password", "Salt")
|
||
return err
|
||
}
|
||
|
||
// ChangeEmployeePassword 修改员工密码
|
||
func ChangeEmployeePassword(employeeId int, oldPassword, newPassword string) error {
|
||
o := orm.NewOrm()
|
||
employee := &Employee{Id: employeeId}
|
||
if err := o.Read(employee); err != nil {
|
||
return fmt.Errorf("员工不存在: %v", err)
|
||
}
|
||
|
||
// 验证旧密码
|
||
if !verifyEmployeePassword(oldPassword, employee.Salt, employee.Password) {
|
||
return errors.New("旧密码不正确")
|
||
}
|
||
|
||
// 加密新密码
|
||
hashedPassword, err := hashEmployeePassword(newPassword, employee.Salt)
|
||
if err != nil {
|
||
return fmt.Errorf("密码加密失败: %v", err)
|
||
}
|
||
employee.Password = hashedPassword
|
||
|
||
_, err = o.Update(employee, "Password")
|
||
return err
|
||
}
|
||
|
||
// verifyEmployeePassword 验证密码是否正确
|
||
func verifyEmployeePassword(password, salt, storedHash string) bool {
|
||
hash, err := hashEmployeePassword(password, salt)
|
||
if err != nil {
|
||
return false
|
||
}
|
||
return hash == storedHash
|
||
}
|
||
|
||
// ValidateEmployee 验证员工登录信息(使用工号作为登录账号)
|
||
func ValidateEmployee(employeeNo, password string, tenantId int) (*Employee, error) {
|
||
o := orm.NewOrm()
|
||
|
||
// 1. 根据工号和租户ID查询员工(排除已删除的)
|
||
var employee Employee
|
||
err := o.QueryTable("yz_tenant_employees").
|
||
Filter("employee_no", employeeNo).
|
||
Filter("tenant_id", tenantId).
|
||
Filter("delete_time__isnull", true).
|
||
Filter("status", 1). // 只允许在职员工登录
|
||
One(&employee)
|
||
|
||
if err == orm.ErrNoRows {
|
||
return nil, errors.New("员工不存在或已离职")
|
||
}
|
||
if err != nil {
|
||
return nil, fmt.Errorf("查询员工失败: %v", err)
|
||
}
|
||
|
||
// 2. 检查密码和盐是否存在
|
||
if employee.Password == "" || employee.Salt == "" {
|
||
return nil, errors.New("员工密码未设置,请联系管理员")
|
||
}
|
||
|
||
// 3. 验证密码
|
||
if verifyEmployeePassword(password, employee.Salt, employee.Password) {
|
||
return &employee, nil
|
||
}
|
||
return nil, errors.New("密码不正确")
|
||
}
|
||
|
||
// DeleteEmployee 软删除员工
|
||
func DeleteEmployee(id int) error {
|
||
o := orm.NewOrm()
|
||
employee := &Employee{Id: id}
|
||
if err := o.Read(employee); err != nil {
|
||
return err
|
||
}
|
||
now := time.Now()
|
||
employee.DeleteTime = &now
|
||
_, err := o.Update(employee, "delete_time")
|
||
return err
|
||
}
|
||
|
||
// GetAllEmployees 获取所有员工(排除已删除的)
|
||
func GetAllEmployees() ([]*Employee, error) {
|
||
o := orm.NewOrm()
|
||
var employees []*Employee
|
||
_, err := o.QueryTable("yz_tenant_employees").
|
||
Filter("delete_time__isnull", true).
|
||
OrderBy("-create_time").
|
||
All(&employees)
|
||
return employees, err
|
||
}
|
||
|
||
// IsEmployee 检查指定的ID是否是员工(用于判断登录类型)
|
||
func IsEmployee(id int) bool {
|
||
o := orm.NewOrm()
|
||
employee := &Employee{Id: id}
|
||
err := o.Read(employee)
|
||
if err != nil {
|
||
return false
|
||
}
|
||
// 检查是否已删除
|
||
if employee.DeleteTime != nil {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|