205 lines
6.2 KiB
Go
205 lines
6.2 KiB
Go
package controllers
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
"server/models"
|
|
|
|
"github.com/beego/beego/v2/client/orm"
|
|
)
|
|
|
|
// 移动端通讯录(企业内部通讯录)只读接口。
|
|
//
|
|
// 复用 AppOaController 的鉴权与响应封装(oaClaims / oaErr / oaOk):
|
|
// 鉴权放宽到 app / platform 令牌,数据一律按 JWT 中的 TenantId 隔离,前端无法指定租户。
|
|
// 写入能力(同步员工 / 新增 / 编辑 / 删除)仍留在 Web 管理端。
|
|
|
|
// appContactDTO 通讯录条目 DTO(移动端展示字段)。
|
|
func appContactDTO(row models.BackendErpContact, orgName string) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"id": row.ID,
|
|
"org_id": contactDerefUint64(row.OrgID),
|
|
"org_name": orgName,
|
|
"contact_type": row.ContactType,
|
|
"contact_name": row.ContactName,
|
|
"gender": row.Gender,
|
|
"phone": contactDerefString(row.Phone),
|
|
"mobiles": contactDerefString(row.Mobiles),
|
|
"work_phone": contactDerefString(row.WorkPhone),
|
|
"email": contactDerefString(row.Email),
|
|
"wechat": contactDerefString(row.Wechat),
|
|
"qq": contactDerefString(row.QQ),
|
|
"avatar": contactDerefString(row.Avatar),
|
|
"company_name": contactDerefString(row.CompanyName),
|
|
"dept_name": contactDerefString(row.DeptName),
|
|
"position_title": contactDerefString(row.PositionTitle),
|
|
"address": contactDerefString(row.Address),
|
|
"remark": contactDerefString(row.Remark),
|
|
"is_starred": row.IsStarred,
|
|
"status": row.Status,
|
|
}
|
|
}
|
|
|
|
// appContactOrgNames 批量查询组织 ID → 名称映射,避免逐行查询。
|
|
func appContactOrgNames(ids []uint64) map[uint64]string {
|
|
names := make(map[uint64]string)
|
|
if len(ids) == 0 {
|
|
return names
|
|
}
|
|
var orgs []models.BackendOrganization
|
|
if _, err := models.Orm.QueryTable(new(models.BackendOrganization)).
|
|
Filter("id__in", ids).All(&orgs); err == nil {
|
|
for _, o := range orgs {
|
|
names[o.ID] = o.OrgName
|
|
}
|
|
}
|
|
return names
|
|
}
|
|
|
|
// ContactList GET /app/oa/contact/list 通讯录分页列表。
|
|
// 支持 keyword(姓名/手机号/邮箱/职位/部门)、org_id(按组织筛选)、contact_type(1 内部 2 外部)。
|
|
func (c *AppOaController) ContactList() {
|
|
claims, err := c.oaClaims()
|
|
if err != nil {
|
|
c.oaErr(401, 401, "未登录或无权限")
|
|
return
|
|
}
|
|
|
|
page, _ := c.GetInt("page", 1)
|
|
pageSize, _ := c.GetInt("pageSize", 20)
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 || pageSize > 100 {
|
|
pageSize = 20
|
|
}
|
|
keyword := strings.TrimSpace(c.GetString("keyword"))
|
|
orgID, _ := c.GetUint64("org_id")
|
|
contactType, _ := c.GetInt("contact_type")
|
|
|
|
qs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
|
Filter("delete_time__isnull", true).
|
|
Exclude("status", 0).
|
|
Filter("tid", claims.TenantId)
|
|
if orgID > 0 {
|
|
qs = qs.Filter("org_id", orgID)
|
|
}
|
|
if contactType > 0 {
|
|
qs = qs.Filter("contact_type", contactType)
|
|
}
|
|
if keyword != "" {
|
|
cond := orm.NewCondition()
|
|
cond = cond.Or("contact_name__contains", keyword)
|
|
cond = cond.Or("phone__contains", keyword)
|
|
cond = cond.Or("mobiles__contains", keyword)
|
|
cond = cond.Or("email__contains", keyword)
|
|
cond = cond.Or("position_title__contains", keyword)
|
|
cond = cond.Or("dept_name__contains", keyword)
|
|
// 用 GetCond().AndCond 追加,避免 SetCond 覆盖掉租户等前置过滤条件
|
|
qs = qs.SetCond(qs.GetCond().AndCond(cond))
|
|
}
|
|
|
|
total, _ := qs.Count()
|
|
|
|
var rows []models.BackendErpContact
|
|
if _, err := qs.OrderBy("-is_starred", "contact_name", "-id").
|
|
Limit(pageSize).Offset((page - 1) * pageSize).All(&rows); err != nil && err != orm.ErrNoRows {
|
|
c.oaErr(500, 500, "查询通讯录失败")
|
|
return
|
|
}
|
|
|
|
ids := make([]uint64, 0, len(rows))
|
|
for _, r := range rows {
|
|
if r.OrgID != nil && *r.OrgID > 0 {
|
|
ids = append(ids, *r.OrgID)
|
|
}
|
|
}
|
|
names := appContactOrgNames(ids)
|
|
|
|
list := make([]map[string]interface{}, 0, len(rows))
|
|
for _, r := range rows {
|
|
orgName := ""
|
|
if r.OrgID != nil {
|
|
orgName = names[*r.OrgID]
|
|
}
|
|
list = append(list, appContactDTO(r, orgName))
|
|
}
|
|
|
|
c.oaOk(map[string]interface{}{"list": list, "total": total, "page": page, "pageSize": pageSize})
|
|
}
|
|
|
|
// ContactOrgTree GET /app/oa/contact/org-tree 组织架构树(含各部门内部联系人数量)。
|
|
func (c *AppOaController) ContactOrgTree() {
|
|
claims, err := c.oaClaims()
|
|
if err != nil {
|
|
c.oaErr(401, 401, "未登录或无权限")
|
|
return
|
|
}
|
|
|
|
var orgs []models.BackendOrganization
|
|
if _, err := models.Orm.QueryTable(new(models.BackendOrganization)).
|
|
Filter("delete_time__isnull", true).
|
|
Exclude("status", 0).
|
|
Filter("tid", claims.TenantId).
|
|
OrderBy("sort", "id").All(&orgs); err != nil && err != orm.ErrNoRows {
|
|
c.oaErr(500, 500, "查询组织架构失败")
|
|
return
|
|
}
|
|
|
|
counts := make(map[uint64]int64)
|
|
for _, org := range orgs {
|
|
cnt, _ := models.Orm.QueryTable(new(models.BackendErpContact)).
|
|
Filter("org_id", org.ID).
|
|
Filter("tid", claims.TenantId).
|
|
Filter("delete_time__isnull", true).
|
|
Exclude("status", 0).
|
|
Filter("contact_type", 1).Count()
|
|
counts[org.ID] = cnt
|
|
}
|
|
|
|
total, _ := models.Orm.QueryTable(new(models.BackendErpContact)).
|
|
Filter("tid", claims.TenantId).
|
|
Filter("delete_time__isnull", true).
|
|
Exclude("status", 0).
|
|
Filter("contact_type", 1).Count()
|
|
|
|
tree := (&BackendErpContactController{}).buildContactOrgTree(orgs, counts, uint64(total))
|
|
c.oaOk(tree)
|
|
}
|
|
|
|
// ContactDetail GET /app/oa/contact/:id 联系人详情。
|
|
func (c *AppOaController) ContactDetail() {
|
|
claims, err := c.oaClaims()
|
|
if err != nil {
|
|
c.oaErr(401, 401, "未登录或无权限")
|
|
return
|
|
}
|
|
|
|
id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
|
if id == 0 {
|
|
c.oaErr(400, 400, "无效的联系人ID")
|
|
return
|
|
}
|
|
|
|
var row models.BackendErpContact
|
|
if models.Orm.QueryTable(new(models.BackendErpContact)).
|
|
Filter("id", id).
|
|
Filter("tid", claims.TenantId).
|
|
Filter("delete_time__isnull", true).
|
|
Exclude("status", 0).One(&row) != nil {
|
|
c.oaErr(404, 404, "联系人不存在")
|
|
return
|
|
}
|
|
|
|
orgName := ""
|
|
if row.OrgID != nil && *row.OrgID > 0 {
|
|
var org models.BackendOrganization
|
|
if models.Orm.QueryTable(new(models.BackendOrganization)).
|
|
Filter("id", *row.OrgID).One(&org) == nil {
|
|
orgName = org.OrgName
|
|
}
|
|
}
|
|
|
|
c.oaOk(appContactDTO(row, orgName))
|
|
} |