package controllers import ( "crypto/sha256" "encoding/hex" "encoding/json" "strconv" "strings" "time" "server/models" "github.com/beego/beego/v2/client/orm" beego "github.com/beego/beego/v2/server/web" ) // BackendErpController 兼容 backend 前端 /admin/erp/* 组织机构、员工、职位接口。 type BackendErpController struct { beego.Controller } type erpOrganizationDTO struct { ID uint64 `json:"id"` Tid uint64 `json:"tid"` TenantID uint64 `json:"tenant_id"` OrgName string `json:"org_name"` OrgCode string `json:"org_code"` ParentID uint64 `json:"parent_id"` ParentName string `json:"parent_name"` LeaderID uint64 `json:"leader_id"` LeaderName string `json:"leader_name"` IsCompany int `json:"is_company"` Sort uint `json:"sort"` Status int8 `json:"status"` Remark string `json:"remark"` } type erpEmployeeDTO struct { ID uint `json:"id"` Tid int `json:"tid"` TenantID int `json:"tenant_id"` Account string `json:"account"` Name string `json:"name"` Gender int8 `json:"gender"` Sex int8 `json:"sex"` Birthday string `json:"birthday"` AffiliateUnit string `json:"affiliate_unit"` AffiliateUnitName string `json:"affiliate_unit_name"` Department string `json:"department"` DepartmentName string `json:"department_name"` Position string `json:"position"` Education string `json:"education"` Nation string `json:"nation"` Phone string `json:"phone"` Wechat string `json:"wechat"` Email string `json:"email"` HomeAddress string `json:"home_address"` AccountStatus int8 `json:"account_status"` Status int8 `json:"status"` } type erpPositionDTO struct { ID uint64 `json:"id"` TenantID uint64 `json:"tenant_id"` Tid uint64 `json:"tid"` DepartmentID uint64 `json:"department_id"` PositionCode string `json:"position_code"` PositionName string `json:"position_name"` PositionType int8 `json:"position_type"` Status int8 `json:"status"` Sort uint `json:"sort"` } // GetOrganization 获取组织机构列表。 // GET /admin/erp/getOrganization func (c *BackendErpController) GetOrganization() { tid, _ := c.GetInt("tid") qs := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("delete_time__isnull", true). Exclude("status", 0) if tid > 0 { qs = qs.Filter("tid", tid) } var rows []models.BackendErpOrganization _, err := qs.OrderBy("sort", "id").All(&rows) if err != nil { c.jsonError(500, "查询组织机构失败: "+err.Error()) return } list := make([]erpOrganizationDTO, 0, len(rows)) for _, row := range rows { list = append(list, c.organizationDTO(row)) } c.jsonOK(list) } // GetOrganizationDetail 获取组织机构详情。 // GET /admin/erp/getOrganizationDetail/:id func (c *BackendErpController) GetOrganizationDetail() { id, ok := c.pathUint64(":id") if !ok { c.jsonError(400, "无效ID") return } var row models.BackendErpOrganization err := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("id", id). Filter("delete_time__isnull", true). Exclude("status", 0). One(&row) if err != nil { c.jsonError(404, "组织机构不存在") return } c.jsonOK(c.organizationDTO(row)) } // CreateOrganization 创建组织机构。 // POST /admin/erp/createOrganization func (c *BackendErpController) CreateOrganization() { body := c.parseJSONBody() orgName, _ := c.getStringValue(body, "org_name", "name") orgName = strings.TrimSpace(orgName) if orgName == "" { c.jsonError(400, "组织名称不能为空") return } orgCode, _ := c.getStringValue(body, "org_code", "code") orgCode = strings.TrimSpace(orgCode) if orgCode == "" { orgCode = "ORG" + c.nowCompactString() } tid, _ := c.getUint64Value(body, "tid", "tenant_id") parentID, _ := c.getUint64Value(body, "parent_id") leaderID, hasLeader := c.getUint64Value(body, "leader_id") sortVal, _ := c.getUintValue(body, "sort") isCompany, hasCompany := c.getIntValue(body, "is_company") status, hasStatus := c.getIntValue(body, "status") remark, _ := c.getStringValue(body, "remark") row := models.BackendErpOrganization{ Tid: tid, OrgName: orgName, OrgCode: orgCode, ParentID: parentID, Sort: sortVal, IsCompany: boolInt(parentID == 0), Status: 1, Remark: strPtrIfNotEmpty(remark), } if hasLeader && leaderID > 0 { row.LeaderID = &leaderID } if hasCompany { row.IsCompany = isCompany } if hasStatus { row.Status = int8(status) } id, err := models.Orm.Insert(&row) if err != nil { c.jsonError(500, "创建组织机构失败: "+err.Error()) return } c.jsonOK(map[string]interface{}{"id": id}) } // EditOrganization 更新组织机构。 // POST /admin/erp/editOrganization/:id func (c *BackendErpController) EditOrganization() { id, ok := c.pathUint64(":id") if !ok { c.jsonError(400, "无效ID") return } body := c.parseJSONBody() update := orm.Params{} if v, has := c.getStringValue(body, "org_name", "name"); has { v = strings.TrimSpace(v) if v == "" { c.jsonError(400, "组织名称不能为空") return } update["org_name"] = v } if v, has := c.getStringValue(body, "org_code", "code"); has { update["org_code"] = strings.TrimSpace(v) } if v, has := c.getUint64Value(body, "parent_id"); has { update["parent_id"] = v } if v, has := c.getUint64Value(body, "tid", "tenant_id"); has { update["tid"] = v } if v, has := c.getUint64Value(body, "leader_id"); has { update["leader_id"] = nullableUint64(v) } if v, has := c.getUintValue(body, "sort"); has { update["sort"] = v } if v, has := c.getIntValue(body, "is_company"); has { update["is_company"] = v } if v, has := c.getIntValue(body, "status"); has { update["status"] = int8(v) } if v, has := c.getStringValue(body, "remark"); has { update["remark"] = nullableString(v) } if len(update) == 0 { c.jsonError(400, "无更新字段") return } num, err := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("id", id). Filter("delete_time__isnull", true). Update(update) if err != nil { c.jsonError(500, "更新组织机构失败: "+err.Error()) return } if num == 0 { c.jsonError(404, "组织机构不存在") return } c.jsonOK(nil) } // DeleteOrganization 删除组织机构。 // DELETE /admin/erp/deleteOrganization/:id func (c *BackendErpController) DeleteOrganization() { id, ok := c.pathUint64(":id") if !ok { c.jsonError(400, "无效ID") return } childCount, err := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("parent_id", id). Filter("delete_time__isnull", true). Exclude("status", 0). Count() if err != nil { c.jsonError(500, "检查子组织失败: "+err.Error()) return } if childCount > 0 { c.jsonError(400, "请先删除下级组织") return } now := c.nowString() num, err := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("id", id). Filter("delete_time__isnull", true). Update(orm.Params{"delete_time": now, "status": int8(0)}) if err != nil { c.jsonError(500, "删除组织机构失败: "+err.Error()) return } if num == 0 { c.jsonError(404, "组织机构不存在") return } c.jsonOK(nil) } // GetCompanys 获取企业单位列表。 // GET /admin/erp/getCompanys func (c *BackendErpController) GetCompanys() { tid, _ := c.GetInt("tid") qs := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("delete_time__isnull", true). Exclude("status", 0). Filter("is_company", 1) if tid > 0 { qs = qs.Filter("tid", tid) } var rows []models.BackendErpOrganization _, err := qs.OrderBy("sort", "id").All(&rows) if err != nil { c.jsonError(500, "查询企业单位失败: "+err.Error()) return } list := make([]erpOrganizationDTO, 0, len(rows)) for _, row := range rows { list = append(list, c.organizationDTO(row)) } c.jsonOK(list) } // GetDepartments 获取部门列表。 // GET /admin/erp/getDepartments?parent_id=1 func (c *BackendErpController) GetDepartments() { parentID, _ := c.GetInt("parent_id") tid, _ := c.GetInt("tid") qs := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("delete_time__isnull", true). Exclude("status", 0) if parentID > 0 { qs = qs.Filter("parent_id", parentID) } else { qs = qs.Filter("is_company", 0) } if tid > 0 { qs = qs.Filter("tid", tid) } var rows []models.BackendErpOrganization _, err := qs.OrderBy("sort", "id").All(&rows) if err != nil { c.jsonError(500, "查询部门失败: "+err.Error()) return } list := make([]erpOrganizationDTO, 0, len(rows)) for _, row := range rows { list = append(list, c.organizationDTO(row)) } c.jsonOK(list) } // GetEmployee 获取员工列表。 // GET /admin/erp/getEmployee?tid=1 func (c *BackendErpController) GetEmployee() { tid, _ := c.GetInt("tid") qs := models.Orm.QueryTable(new(models.BackendErpEmployee)).Filter("delete_time__isnull", true) if tid > 0 { qs = qs.Filter("tid", tid) } var rows []models.BackendErpEmployee _, err := qs.OrderBy("-id").All(&rows) if err != nil { c.jsonError(500, "查询员工失败: "+err.Error()) return } list := make([]erpEmployeeDTO, 0, len(rows)) for _, row := range rows { list = append(list, c.employeeDTO(row)) } c.jsonOK(list) } // GetEmployeeDetail 获取员工详情。 // GET /admin/erp/getEmployeeDetail/:id func (c *BackendErpController) GetEmployeeDetail() { id, ok := c.pathUint(":id") if !ok { c.jsonError(400, "无效ID") return } var row models.BackendErpEmployee err := models.Orm.QueryTable(new(models.BackendErpEmployee)). Filter("id", id). Filter("delete_time__isnull", true). One(&row) if err != nil { c.jsonError(404, "员工不存在") return } c.jsonOK(c.employeeDTO(row)) } // CreateEmployee 创建员工。 // POST /admin/erp/createEmployee func (c *BackendErpController) CreateEmployee() { body := c.parseJSONBody() name, _ := c.getStringValue(body, "name") name = strings.TrimSpace(name) if name == "" { c.jsonError(400, "姓名不能为空") return } account, _ := c.getStringValue(body, "account") account = strings.TrimSpace(account) if account == "" { account = "EMP" + c.nowCompactString() } tid, _ := c.getIntValue(body, "tid", "tenant_id") gender, hasGender := c.getIntValue(body, "gender", "sex") status, hasStatus := c.getIntValue(body, "account_status", "status") password, _ := c.getStringValue(body, "password") birthday, _ := c.getStringValue(body, "birthday") affiliateUnit, _ := c.getStringValue(body, "affiliate_unit") department, _ := c.getStringValue(body, "department") position, _ := c.getStringValue(body, "position") education, _ := c.getStringValue(body, "education") nation, _ := c.getStringValue(body, "nation") phone, _ := c.getStringValue(body, "phone") wechat, _ := c.getStringValue(body, "wechat") email, _ := c.getStringValue(body, "email") homeAddress, _ := c.getStringValue(body, "home_address") row := models.BackendErpEmployee{ Tid: nullableIntPtr(tid), Account: account, Password: hashEmployeePassword(password), Name: name, Gender: 0, Birthday: parseDatePtr(birthday), AffiliateUnit: strPtrIfNotEmpty(affiliateUnit), Department: strPtrIfNotEmpty(department), Position: strPtrIfNotEmpty(position), Education: strPtrIfNotEmpty(education), Nation: strPtrIfNotEmpty(nation), Phone: strPtrIfNotEmpty(phone), Wechat: strPtrIfNotEmpty(wechat), Email: strPtrIfNotEmpty(email), HomeAddress: strPtrIfNotEmpty(homeAddress), AccountStatus: 1, } if hasGender { row.Gender = int8(gender) } if hasStatus { row.AccountStatus = int8(status) } id, err := models.Orm.Insert(&row) if err != nil { c.jsonError(500, "创建员工失败: "+err.Error()) return } c.jsonOK(map[string]interface{}{"id": id}) } // EditEmployee 更新员工。 // POST /admin/erp/editEmployee/:id func (c *BackendErpController) EditEmployee() { id, ok := c.pathUint(":id") if !ok { c.jsonError(400, "无效ID") return } body := c.parseJSONBody() update := orm.Params{} if v, has := c.getStringValue(body, "account"); has && strings.TrimSpace(v) != "" { update["account"] = strings.TrimSpace(v) } if v, has := c.getStringValue(body, "name"); has { v = strings.TrimSpace(v) if v == "" { c.jsonError(400, "姓名不能为空") return } update["name"] = v } if v, has := c.getIntValue(body, "tid", "tenant_id"); has { update["tid"] = nullableInt(v) } if v, has := c.getIntValue(body, "gender", "sex"); has { update["gender"] = int8(v) } if v, has := c.getStringValue(body, "birthday"); has { update["birthday"] = parseDatePtr(v) } if v, has := c.getStringValue(body, "affiliate_unit"); has { update["affiliate_unit"] = nullableString(v) } if v, has := c.getStringValue(body, "department"); has { update["department"] = nullableString(v) } if v, has := c.getStringValue(body, "position"); has { update["position"] = nullableString(v) } if v, has := c.getStringValue(body, "education"); has { update["education"] = nullableString(v) } if v, has := c.getStringValue(body, "nation"); has { update["nation"] = nullableString(v) } if v, has := c.getStringValue(body, "phone"); has { update["phone"] = nullableString(v) } if v, has := c.getStringValue(body, "wechat"); has { update["wechat"] = nullableString(v) } if v, has := c.getStringValue(body, "email"); has { update["email"] = nullableString(v) } if v, has := c.getStringValue(body, "home_address"); has { update["home_address"] = nullableString(v) } if v, has := c.getIntValue(body, "account_status", "status"); has { update["account_status"] = int8(v) } if v, has := c.getStringValue(body, "password"); has && strings.TrimSpace(v) != "" { update["password"] = hashEmployeePassword(v) } if len(update) == 0 { c.jsonError(400, "无更新字段") return } num, err := models.Orm.QueryTable(new(models.BackendErpEmployee)). Filter("id", id). Filter("delete_time__isnull", true). Update(update) if err != nil { c.jsonError(500, "更新员工失败: "+err.Error()) return } if num == 0 { c.jsonError(404, "员工不存在") return } c.jsonOK(nil) } // DeleteEmployee 删除员工。 // DELETE /admin/erp/deleteEmployee/:id func (c *BackendErpController) DeleteEmployee() { id, ok := c.pathUint(":id") if !ok { c.jsonError(400, "无效ID") return } num, err := models.Orm.QueryTable(new(models.BackendErpEmployee)). Filter("id", id). Filter("delete_time__isnull", true). Update(orm.Params{"delete_time": c.nowString(), "account_status": int8(2)}) if err != nil { c.jsonError(500, "删除员工失败: "+err.Error()) return } if num == 0 { c.jsonError(404, "员工不存在") return } c.jsonOK(nil) } // GetPosition 获取职位列表。 // GET /admin/erp/getPosition func (c *BackendErpController) GetPosition() { tid, _ := c.GetInt("tid") departmentID, _ := c.GetInt("department_id") qs := models.Orm.QueryTable(new(models.BackendErpPosition)) if tid > 0 { qs = qs.Filter("tenant_id", tid) } if departmentID > 0 { qs = qs.Filter("department_id", departmentID) } var rows []models.BackendErpPosition _, err := qs.OrderBy("sort", "id").All(&rows) if err != nil { c.jsonError(500, "查询职位失败: "+err.Error()) return } list := make([]erpPositionDTO, 0, len(rows)) for _, row := range rows { list = append(list, c.positionDTO(row)) } c.jsonOK(list) } // GetPositionDetail 获取职位详情。 // GET /admin/erp/getPositionDetail/:id func (c *BackendErpController) GetPositionDetail() { id, ok := c.pathUint64(":id") if !ok { c.jsonError(400, "无效ID") return } var row models.BackendErpPosition err := models.Orm.QueryTable(new(models.BackendErpPosition)).Filter("id", id).One(&row) if err != nil { c.jsonError(404, "职位不存在") return } c.jsonOK(c.positionDTO(row)) } // CreatePosition 创建职位。 // POST /admin/erp/createPosition func (c *BackendErpController) CreatePosition() { body := c.parseJSONBody() tenantID, _ := c.getUint64Value(body, "tenant_id", "tid") departmentID, _ := c.getUint64Value(body, "department_id") positionName, _ := c.getStringValue(body, "position_name", "name") positionName = strings.TrimSpace(positionName) if positionName == "" { c.jsonError(400, "职位名称不能为空") return } positionCode, _ := c.getStringValue(body, "position_code", "code") positionCode = strings.TrimSpace(positionCode) if positionCode == "" { positionCode = "POS" + c.nowCompactString() } positionType, _ := c.getIntValue(body, "position_type") status, hasStatus := c.getIntValue(body, "status") sortVal, _ := c.getUintValue(body, "sort") row := models.BackendErpPosition{ TenantID: tenantID, DepartmentID: departmentID, PositionCode: positionCode, PositionName: positionName, PositionType: int8(positionType), Status: 1, Sort: sortVal, } if hasStatus { row.Status = int8(status) } id, err := models.Orm.Insert(&row) if err != nil { c.jsonError(500, "创建职位失败: "+err.Error()) return } c.jsonOK(map[string]interface{}{"id": id}) } // EditPosition 更新职位。 // POST /admin/erp/editPosition/:id func (c *BackendErpController) EditPosition() { id, ok := c.pathUint64(":id") if !ok { c.jsonError(400, "无效ID") return } body := c.parseJSONBody() update := orm.Params{} if v, has := c.getUint64Value(body, "tenant_id", "tid"); has { update["tenant_id"] = v } if v, has := c.getUint64Value(body, "department_id"); has { update["department_id"] = v } if v, has := c.getStringValue(body, "position_code", "code"); has { update["position_code"] = strings.TrimSpace(v) } if v, has := c.getStringValue(body, "position_name", "name"); has { v = strings.TrimSpace(v) if v == "" { c.jsonError(400, "职位名称不能为空") return } update["position_name"] = v } if v, has := c.getIntValue(body, "position_type"); has { update["position_type"] = int8(v) } if v, has := c.getIntValue(body, "status"); has { update["status"] = int8(v) } if v, has := c.getUintValue(body, "sort"); has { update["sort"] = v } if len(update) == 0 { c.jsonError(400, "无更新字段") return } num, err := models.Orm.QueryTable(new(models.BackendErpPosition)).Filter("id", id).Update(update) if err != nil { c.jsonError(500, "更新职位失败: "+err.Error()) return } if num == 0 { c.jsonError(404, "职位不存在") return } c.jsonOK(nil) } // DeletePosition 删除职位。 // DELETE /admin/erp/deletePosition/:id func (c *BackendErpController) DeletePosition() { id, ok := c.pathUint64(":id") if !ok { c.jsonError(400, "无效ID") return } num, err := models.Orm.QueryTable(new(models.BackendErpPosition)).Filter("id", id).Delete() if err != nil { c.jsonError(500, "删除职位失败: "+err.Error()) return } if num == 0 { c.jsonError(404, "职位不存在") return } c.jsonOK(nil) } func (c *BackendErpController) organizationDTO(row models.BackendErpOrganization) erpOrganizationDTO { parentName := "" if row.ParentID > 0 { var parent models.BackendErpOrganization if err := models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("id", row.ParentID). One(&parent); err == nil { parentName = parent.OrgName } } leaderID := uint64(0) leaderName := "" if row.LeaderID != nil { leaderID = *row.LeaderID var employee models.BackendErpEmployee if err := models.Orm.QueryTable(new(models.BackendErpEmployee)). Filter("id", leaderID). One(&employee); err == nil { leaderName = employee.Name } } return erpOrganizationDTO{ ID: row.ID, Tid: row.Tid, TenantID: row.Tid, OrgName: row.OrgName, OrgCode: row.OrgCode, ParentID: row.ParentID, ParentName: parentName, LeaderID: leaderID, LeaderName: leaderName, IsCompany: row.IsCompany, Sort: row.Sort, Status: row.Status, Remark: derefString(row.Remark), } } func (c *BackendErpController) employeeDTO(row models.BackendErpEmployee) erpEmployeeDTO { tid := 0 if row.Tid != nil { tid = *row.Tid } birthday := "" if row.Birthday != nil { birthday = row.Birthday.Format("2006-01-02") } affiliateUnit := derefString(row.AffiliateUnit) department := derefString(row.Department) affiliateUnitName := c.organizationNameByIDString(affiliateUnit) departmentName := c.organizationNameByIDString(department) return erpEmployeeDTO{ ID: row.ID, Tid: tid, TenantID: tid, Account: row.Account, Name: row.Name, Gender: row.Gender, Sex: row.Gender, Birthday: birthday, AffiliateUnit: affiliateUnit, AffiliateUnitName: affiliateUnitName, Department: department, DepartmentName: departmentName, Position: derefString(row.Position), Education: derefString(row.Education), Nation: derefString(row.Nation), Phone: derefString(row.Phone), Wechat: derefString(row.Wechat), Email: derefString(row.Email), HomeAddress: derefString(row.HomeAddress), AccountStatus: row.AccountStatus, Status: row.AccountStatus, } } func (c *BackendErpController) organizationNameByIDString(idValue string) string { idValue = strings.TrimSpace(idValue) if idValue == "" { return "" } id, err := strconv.ParseUint(idValue, 10, 64) if err != nil || id == 0 { return "" } var org models.BackendErpOrganization err = models.Orm.QueryTable(new(models.BackendErpOrganization)). Filter("id", id). Filter("delete_time__isnull", true). One(&org) if err != nil { return "" } return org.OrgName } func (c *BackendErpController) positionDTO(row models.BackendErpPosition) erpPositionDTO { return erpPositionDTO{ ID: row.ID, TenantID: row.TenantID, Tid: row.TenantID, DepartmentID: row.DepartmentID, PositionCode: row.PositionCode, PositionName: row.PositionName, PositionType: row.PositionType, Status: row.Status, Sort: row.Sort, } } func (c *BackendErpController) parseJSONBody() map[string]interface{} { body := map[string]interface{}{} contentType := strings.ToLower(c.Ctx.Input.Header("Content-Type")) if !strings.Contains(contentType, "json") { return body } if len(c.Ctx.Input.RequestBody) == 0 { return body } _ = json.Unmarshal(c.Ctx.Input.RequestBody, &body) return body } func (c *BackendErpController) getStringValue(body map[string]interface{}, keys ...string) (string, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case string: return val, true case float64: return strconv.FormatFloat(val, 'f', -1, 64), true case bool: return strconv.FormatBool(val), true default: return strings.TrimSpace(strings.Trim(strings.ReplaceAll(strings.ReplaceAll(toJSON(val), "\n", ""), "\r", ""), "\"")), true } } if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil { _ = c.Ctx.Request.ParseMultipartForm(32 << 20) } if val := c.GetString(key); val != "" { return val, true } } return "", false } func (c *BackendErpController) getIntValue(body map[string]interface{}, keys ...string) (int, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case float64: return int(val), true case int: return val, true case string: if strings.TrimSpace(val) == "" { return 0, true } parsed, err := strconv.Atoi(strings.TrimSpace(val)) return parsed, err == nil } } if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil { _ = c.Ctx.Request.ParseMultipartForm(32 << 20) } if val := c.GetString(key); val != "" { parsed, err := strconv.Atoi(strings.TrimSpace(val)) return parsed, err == nil } } return 0, false } func (c *BackendErpController) getUintValue(body map[string]interface{}, keys ...string) (uint, bool) { v, ok := c.getIntValue(body, keys...) if !ok || v < 0 { return 0, ok } return uint(v), true } func (c *BackendErpController) getUint64Value(body map[string]interface{}, keys ...string) (uint64, bool) { for _, key := range keys { if v, ok := body[key]; ok { switch val := v.(type) { case float64: if val < 0 { return 0, false } return uint64(val), true case int: if val < 0 { return 0, false } return uint64(val), true case string: if strings.TrimSpace(val) == "" { return 0, true } parsed, err := strconv.ParseUint(strings.TrimSpace(val), 10, 64) return parsed, err == nil } } if c.Ctx.Request.Form == nil && c.Ctx.Request.PostForm == nil && c.Ctx.Request.MultipartForm == nil { _ = c.Ctx.Request.ParseMultipartForm(32 << 20) } if val := c.GetString(key); val != "" { parsed, err := strconv.ParseUint(strings.TrimSpace(val), 10, 64) return parsed, err == nil } } return 0, false } func (c *BackendErpController) pathUint(name string) (uint, bool) { id, err := strconv.ParseUint(c.Ctx.Input.Param(name), 10, 64) return uint(id), err == nil && id > 0 } func (c *BackendErpController) pathUint64(name string) (uint64, bool) { id, err := strconv.ParseUint(c.Ctx.Input.Param(name), 10, 64) return id, err == nil && id > 0 } func (c *BackendErpController) jsonOK(data interface{}) { resp := map[string]interface{}{"code": 200, "msg": "success"} if data != nil { resp["data"] = data } c.Data["json"] = resp _ = c.ServeJSON() } func (c *BackendErpController) jsonError(code int, msg string) { c.Data["json"] = map[string]interface{}{"code": code, "msg": msg} _ = c.ServeJSON() } func (c *BackendErpController) nowString() string { return time.Now().Format("2006-01-02 15:04:05") } func (c *BackendErpController) nowCompactString() string { return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(c.nowString(), "-", ""), ":", ""), " ", "") } func strPtrIfNotEmpty(v string) *string { v = strings.TrimSpace(v) if v == "" { return nil } return &v } func nullableString(v string) interface{} { v = strings.TrimSpace(v) if v == "" { return nil } return v } func nullableInt(v int) interface{} { if v <= 0 { return nil } return v } func nullableIntPtr(v int) *int { if v <= 0 { return nil } return &v } func nullableUint64(v uint64) interface{} { if v == 0 { return nil } return v } func derefString(v *string) string { if v == nil { return "" } return *v } func boolInt(v bool) int { if v { return 1 } return 0 } func toJSON(v interface{}) string { b, _ := json.Marshal(v) return string(b) } func parseDatePtr(v string) *time.Time { v = strings.TrimSpace(v) if v == "" { return nil } if t, err := time.Parse("2006-01-02", v); err == nil { return &t } if t, err := time.Parse("2006-01-02 15:04:05", v); err == nil { return &t } return nil } // hashEmployeePassword 适配 yz_backend_erp_employee.password varchar(64),使用 sha256 hex。 // 如果密码为空则返回空字符串,符合表默认值。 func hashEmployeePassword(plain string) string { plain = strings.TrimSpace(plain) if plain == "" { return "" } sum := sha256.Sum256([]byte(plain)) return hex.EncodeToString(sum[:]) }