更新若干事项
This commit is contained in:
1 parent
68cdaf38fa
commit
9898962836
30 files changed
+7715
No files matched your search
@@ -0,0 +1,196 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"server/models"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
// schedulingEmployee 排班看板/方案预览里的员工视图。
|
||||
// Department 保留组织 ID 字符串,DepartmentName 供前端直接展示。
|
||||
type schedulingEmployee struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Account string `json:"account"`
|
||||
Department string `json:"department"`
|
||||
DepartmentName string `json:"department_name"`
|
||||
Position string `json:"position"`
|
||||
Phone string `json:"phone"`
|
||||
AccountStatus int8 `json:"account_status"`
|
||||
}
|
||||
|
||||
// scOrgIndex 租户组织架构的内存索引,用于把“部门/小组”展开成部门子树,
|
||||
// 以及给员工补齐部门名称。一次请求只加载一次,避免 N+1 查询。
|
||||
type scOrgIndex struct {
|
||||
rows map[uint64]models.BackendOrganization
|
||||
children map[uint64][]uint64
|
||||
names map[uint64]string
|
||||
}
|
||||
|
||||
func (c *BackendOaSchedulingController) scLoadOrgIndex(tid uint64) *scOrgIndex {
|
||||
index := &scOrgIndex{
|
||||
rows: map[uint64]models.BackendOrganization{},
|
||||
children: map[uint64][]uint64{},
|
||||
names: map[uint64]string{},
|
||||
}
|
||||
var rows []models.BackendOrganization
|
||||
_, err := models.Orm.QueryTable(new(models.BackendOrganization)).
|
||||
Filter("tid", tid).
|
||||
Filter("delete_time__isnull", true).
|
||||
All(&rows)
|
||||
if err != nil {
|
||||
return index
|
||||
}
|
||||
for _, row := range rows {
|
||||
index.rows[row.ID] = row
|
||||
index.names[row.ID] = row.OrgName
|
||||
index.children[row.ParentID] = append(index.children[row.ParentID], row.ID)
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// subtreeIDs 返回节点自身及其全部下级组织 ID。
|
||||
func (index *scOrgIndex) subtreeIDs(root uint64) map[uint64]bool {
|
||||
result := map[uint64]bool{}
|
||||
if root == 0 {
|
||||
return result
|
||||
}
|
||||
queue := []uint64{root}
|
||||
for len(queue) > 0 {
|
||||
current := queue[0]
|
||||
queue = queue[1:]
|
||||
if result[current] {
|
||||
continue
|
||||
}
|
||||
result[current] = true
|
||||
queue = append(queue, index.children[current]...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (index *scOrgIndex) name(id uint64) string {
|
||||
if name, ok := index.names[id]; ok {
|
||||
return name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// scBaseEmployeeQuery 排班可选员工:未删除、非离职。
|
||||
func (c *BackendOaSchedulingController) scBaseEmployeeQuery(tid uint64) orm.QuerySeter {
|
||||
return models.Orm.QueryTable(new(models.BackendEmployee)).
|
||||
Filter("tid", tid).
|
||||
Filter("delete_time__isnull", true).
|
||||
Exclude("account_status", 2)
|
||||
}
|
||||
|
||||
func scEmployeeDepartmentID(row models.BackendEmployee) uint64 {
|
||||
if row.Department == nil {
|
||||
return 0
|
||||
}
|
||||
id, err := strconv.ParseUint(strings.TrimSpace(*row.Department), 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func (c *BackendOaSchedulingController) scEmployeeDTOs(tid uint64, rows []models.BackendEmployee) []schedulingEmployee {
|
||||
index := c.scLoadOrgIndex(tid)
|
||||
result := make([]schedulingEmployee, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
orgID := scEmployeeDepartmentID(row)
|
||||
position := ""
|
||||
if row.Position != nil {
|
||||
position = *row.Position
|
||||
}
|
||||
phone := ""
|
||||
if row.Phone != nil {
|
||||
phone = *row.Phone
|
||||
}
|
||||
result = append(result, schedulingEmployee{
|
||||
ID: row.ID,
|
||||
Name: row.Name,
|
||||
Account: row.Account,
|
||||
Department: strconv.FormatUint(orgID, 10),
|
||||
DepartmentName: index.name(orgID),
|
||||
Position: position,
|
||||
Phone: phone,
|
||||
AccountStatus: row.AccountStatus,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// scEmployeesByOrg 按组织节点取员工;includeChild=true 时包含全部下级组织,
|
||||
// 这样选中“公司/部门/小组”任意层级都能覆盖到该范围内的所有人。
|
||||
func (c *BackendOaSchedulingController) scEmployeesByOrg(tid, orgID uint64, includeChild bool) ([]models.BackendEmployee, error) {
|
||||
qs := c.scBaseEmployeeQuery(tid)
|
||||
if orgID > 0 {
|
||||
allowed := map[uint64]bool{orgID: true}
|
||||
if includeChild {
|
||||
allowed = c.scLoadOrgIndex(tid).subtreeIDs(orgID)
|
||||
}
|
||||
values := make([]string, 0, len(allowed))
|
||||
for id := range allowed {
|
||||
values = append(values, strconv.FormatUint(id, 10))
|
||||
}
|
||||
qs = qs.Filter("department__in", values)
|
||||
}
|
||||
var rows []models.BackendEmployee
|
||||
_, err := qs.OrderBy("department", "id").All(&rows)
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// scEmployeesByIDs 按员工 ID 取员工,保持传入顺序由前端自行处理。
|
||||
func (c *BackendOaSchedulingController) scEmployeesByIDs(tid uint64, ids []uint64) ([]models.BackendEmployee, error) {
|
||||
if len(ids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var rows []models.BackendEmployee
|
||||
_, err := c.scBaseEmployeeQuery(tid).Filter("id__in", ids).All(&rows)
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// scResolveEmployees 把方案范围(公司 / 部门小组 / 指定员工)展开成员工列表。
|
||||
func (c *BackendOaSchedulingController) scResolveEmployees(tid uint64, scopeType int8, orgID uint64, includeChild bool, employeeIDs []uint64) ([]models.BackendEmployee, error) {
|
||||
switch scopeType {
|
||||
case models.OaScopeEmployees:
|
||||
return c.scEmployeesByIDs(tid, employeeIDs)
|
||||
case models.OaScopeCompany:
|
||||
return c.scEmployeesByOrg(tid, 0, false)
|
||||
default:
|
||||
return c.scEmployeesByOrg(tid, orgID, includeChild)
|
||||
}
|
||||
}
|
||||
|
||||
// scWorkdays 从日期区间中筛出命中的星期(1=周一 ... 7=周日)。
|
||||
// 未选择任何星期表示每天。
|
||||
func scWorkdays(dates []string, weekdays map[int]bool) []string {
|
||||
if len(weekdays) == 0 {
|
||||
return dates
|
||||
}
|
||||
result := make([]string, 0, len(dates))
|
||||
for _, date := range dates {
|
||||
parsed, ok := scParseDate(date)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
weekday := int(parsed.Weekday())
|
||||
if weekday == 0 {
|
||||
weekday = 7
|
||||
}
|
||||
if weekdays[weekday] {
|
||||
result = append(result, date)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in new issue
Block a user