636 lines
19 KiB
Go
636 lines
19 KiB
Go
package controllers
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"server/models"
|
||
"server/pkg/identity"
|
||
"server/pkg/jwtutil"
|
||
|
||
"github.com/beego/beego/v2/client/orm"
|
||
beego "github.com/beego/beego/v2/server/web"
|
||
)
|
||
|
||
// PlatformSchedTemplateController 平台端排班模板管理(全局模板,只有平台可维护)。
|
||
//
|
||
// 表:yz_platform_sched_tpl / yz_platform_sched_tpl_day
|
||
// 建表与预置数据:docs/sql/create_platform_sched_template.sql
|
||
//
|
||
// 规则:
|
||
// - 系统预置模板(is_system=1)由平台锁定:禁止编辑、删除、停用;
|
||
// - 平台可新建「自定义模板」,并编辑 / 停用 / 删除自定义模板;
|
||
// - 租户端只读取启用模板(/backend/oa/scheduling/templates),
|
||
// 调用后把规则快照进自己的排班方案,模板改动不影响已保存方案。
|
||
type PlatformSchedTemplateController struct {
|
||
beego.Controller
|
||
}
|
||
|
||
func (c *PlatformSchedTemplateController) tplClaims() (*jwtutil.Claims, error) {
|
||
return identity.Claims(c.Ctx.Request.Header.Get("Authorization"), identity.EndPlatform)
|
||
}
|
||
|
||
func (c *PlatformSchedTemplateController) tplErr(httpStatus, bizCode int, msg string) {
|
||
c.Ctx.Output.SetStatus(httpStatus)
|
||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||
_ = c.ServeJSON()
|
||
}
|
||
|
||
func (c *PlatformSchedTemplateController) tplOK(data interface{}, msg string) {
|
||
if msg == "" {
|
||
msg = "success"
|
||
}
|
||
resp := map[string]interface{}{"code": 200, "msg": msg}
|
||
if data != nil {
|
||
resp["data"] = data
|
||
}
|
||
c.Data["json"] = resp
|
||
_ = c.ServeJSON()
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 参数结构
|
||
// ---------------------------------------------------------------------------
|
||
|
||
type schedTplDayPayload struct {
|
||
DayIndex int `json:"day_index"`
|
||
DayType int8 `json:"day_type"`
|
||
ShiftName string `json:"shift_name"`
|
||
ShiftShort string `json:"shift_short"`
|
||
Color string `json:"color"`
|
||
WorkStart string `json:"work_start"`
|
||
WorkEnd string `json:"work_end"`
|
||
RestStart string `json:"rest_start"`
|
||
RestEnd string `json:"rest_end"`
|
||
WorkHours float64 `json:"work_hours"`
|
||
Remark string `json:"remark"`
|
||
}
|
||
|
||
type schedTplPayload struct {
|
||
Name string `json:"name"`
|
||
Code string `json:"code"`
|
||
TemplateType int8 `json:"template_type"`
|
||
AlignMode int8 `json:"align_mode"`
|
||
CycleDays int `json:"cycle_days"`
|
||
WeekOffset int8 `json:"week_offset"`
|
||
MonthRestDays int8 `json:"month_rest_days"`
|
||
MonthRestWeekday int8 `json:"month_rest_weekday"`
|
||
Summary string `json:"summary"`
|
||
Status int8 `json:"status"`
|
||
Sort int `json:"sort"`
|
||
Days []schedTplDayPayload `json:"days"`
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 列表 / 详情
|
||
// ---------------------------------------------------------------------------
|
||
|
||
func (c *PlatformSchedTemplateController) tplQuery() orm.QuerySeter {
|
||
return models.Orm.QueryTable(new(models.PlatformSchedTpl)).Filter("delete_time__isnull", true)
|
||
}
|
||
|
||
func (c *PlatformSchedTemplateController) tplByID(id uint64) (*models.PlatformSchedTpl, bool) {
|
||
var row models.PlatformSchedTpl
|
||
if err := c.tplQuery().Filter("id", id).One(&row); err != nil {
|
||
return nil, false
|
||
}
|
||
return &row, true
|
||
}
|
||
|
||
func (c *PlatformSchedTemplateController) tplDays(templateID uint64) []models.PlatformSchedTplDay {
|
||
rows := []models.PlatformSchedTplDay{}
|
||
_, err := models.Orm.QueryTable(new(models.PlatformSchedTplDay)).
|
||
Filter("template_id", templateID).
|
||
OrderBy("day_index").All(&rows)
|
||
if err != nil && err != orm.ErrNoRows {
|
||
return []models.PlatformSchedTplDay{}
|
||
}
|
||
return rows
|
||
}
|
||
|
||
func (c *PlatformSchedTemplateController) tplView(row *models.PlatformSchedTpl, withDays bool) map[string]interface{} {
|
||
view := map[string]interface{}{
|
||
"id": row.ID,
|
||
"code": row.Code,
|
||
"name": row.Name,
|
||
"template_type": row.TemplateType,
|
||
"template_type_text": schedTplTypeText(row.TemplateType),
|
||
"align_mode": row.AlignMode,
|
||
"cycle_days": row.CycleDays,
|
||
"week_offset": row.WeekOffset,
|
||
"month_rest_days": row.MonthRestDays,
|
||
"month_rest_weekday": row.MonthRestWeekday,
|
||
"summary": row.Summary,
|
||
"is_system": row.IsSystem,
|
||
"editable": row.IsSystem != 1,
|
||
"status": row.Status,
|
||
"sort": row.Sort,
|
||
"creater": row.Creater,
|
||
"create_time": row.CreateTime.Format("2006-01-02 15:04:05"),
|
||
}
|
||
if row.UpdateTime != nil {
|
||
view["update_time"] = row.UpdateTime.Format("2006-01-02 15:04:05")
|
||
}
|
||
if withDays {
|
||
view["days"] = c.tplDays(row.ID)
|
||
}
|
||
return view
|
||
}
|
||
|
||
func schedTplTypeText(value int8) string {
|
||
switch value {
|
||
case models.SchedTplTypeDoubleWeekend:
|
||
return "双休"
|
||
case models.SchedTplTypeSingleWeekend:
|
||
return "单休"
|
||
case models.SchedTplTypeBigSmallWeek:
|
||
return "大小周"
|
||
case models.SchedTplTypeMonthRest:
|
||
return "月休"
|
||
case models.SchedTplTypeThreeShift:
|
||
return "三班倒"
|
||
case models.SchedTplTypeWorkRestOne:
|
||
return "做一休一"
|
||
default:
|
||
return "自定义"
|
||
}
|
||
}
|
||
|
||
// List 模板列表。
|
||
// GET /platform/schedTemplates?page=1&pageSize=20&keyword=&status=&template_type=
|
||
func (c *PlatformSchedTemplateController) List() {
|
||
if _, err := c.tplClaims(); err != nil {
|
||
c.tplErr(401, 401, "未登录或登录已过期")
|
||
return
|
||
}
|
||
page, pageSize, offset := dictPageSize(&c.Controller)
|
||
|
||
qs := c.tplQuery()
|
||
if keyword := strings.TrimSpace(c.GetString("keyword")); keyword != "" {
|
||
qs = qs.Filter("name__icontains", keyword)
|
||
}
|
||
if raw := strings.TrimSpace(c.GetString("status")); raw != "" {
|
||
if value, err := strconv.Atoi(raw); err == nil {
|
||
qs = qs.Filter("status", value)
|
||
}
|
||
}
|
||
if raw := strings.TrimSpace(c.GetString("template_type")); raw != "" {
|
||
if value, err := strconv.Atoi(raw); err == nil {
|
||
qs = qs.Filter("template_type", value)
|
||
}
|
||
}
|
||
|
||
total, _ := qs.Count()
|
||
var rows []models.PlatformSchedTpl
|
||
if _, err := qs.OrderBy("sort", "id").Limit(pageSize).Offset(offset).All(&rows); err != nil && err != orm.ErrNoRows {
|
||
c.tplErr(500, 500, "查询模板失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rows))
|
||
for i := range rows {
|
||
list = append(list, c.tplView(&rows[i], false))
|
||
}
|
||
c.tplOK(map[string]interface{}{
|
||
"list": list,
|
||
"total": total,
|
||
"page": page,
|
||
"page_size": pageSize,
|
||
}, "")
|
||
}
|
||
|
||
// Detail 模板详情(含周期每日规则)。
|
||
// GET /platform/schedTemplates/:id
|
||
func (c *PlatformSchedTemplateController) Detail() {
|
||
if _, err := c.tplClaims(); err != nil {
|
||
c.tplErr(401, 401, "未登录或登录已过期")
|
||
return
|
||
}
|
||
id, err := strconv.ParseUint(strings.TrimSpace(c.Ctx.Input.Param(":id")), 10, 64)
|
||
if err != nil || id == 0 {
|
||
c.tplErr(400, 400, "无效的模板ID")
|
||
return
|
||
}
|
||
row, found := c.tplByID(id)
|
||
if !found {
|
||
c.tplErr(404, 404, "模板不存在")
|
||
return
|
||
}
|
||
c.tplOK(c.tplView(row, true), "")
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 新建 / 编辑 / 删除 / 启停
|
||
// ---------------------------------------------------------------------------
|
||
|
||
func (c *PlatformSchedTemplateController) parsePayload() (*schedTplPayload, bool) {
|
||
var payload schedTplPayload
|
||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil {
|
||
c.tplErr(400, 400, "参数错误")
|
||
return nil, false
|
||
}
|
||
return &payload, true
|
||
}
|
||
|
||
// buildDays 校验并构造周期每日规则;返回非空 msg 表示参数错误。
|
||
func buildSchedTplDays(payload *schedTplPayload) ([]models.PlatformSchedTplDay, string) {
|
||
if payload.AlignMode < models.SchedTplAlignWeek || payload.AlignMode > models.SchedTplAlignMonth {
|
||
return nil, "排班方式不合法"
|
||
}
|
||
if len(payload.Days) == 0 {
|
||
return nil, "请至少配置一天的规则"
|
||
}
|
||
|
||
cycle := payload.CycleDays
|
||
if payload.AlignMode == models.SchedTplAlignMonth {
|
||
// 月休按自然月计算,周期天数无意义
|
||
cycle = 0
|
||
if payload.MonthRestDays < 1 || payload.MonthRestDays > 15 {
|
||
return nil, "月休天数需在 1~15 天之间"
|
||
}
|
||
if payload.MonthRestWeekday < 0 || payload.MonthRestWeekday > 7 {
|
||
return nil, "月休休息周几不合法"
|
||
}
|
||
} else {
|
||
if cycle < 2 || cycle > 31 {
|
||
return nil, "周期天数需在 2~31 天之间"
|
||
}
|
||
if payload.AlignMode == models.SchedTplAlignWeek && cycle%7 != 0 {
|
||
return nil, "按自然周排班时,周期天数必须是 7 的倍数(7 / 14 / 21 / 28)"
|
||
}
|
||
if len(payload.Days) != cycle {
|
||
return nil, fmt.Sprintf("周期为 %d 天,需要配置 %d 天的规则", cycle, cycle)
|
||
}
|
||
}
|
||
|
||
seen := map[int]bool{}
|
||
workCount := 0
|
||
days := make([]models.PlatformSchedTplDay, 0, len(payload.Days))
|
||
for _, item := range payload.Days {
|
||
index := item.DayIndex
|
||
if payload.AlignMode == models.SchedTplAlignMonth {
|
||
index = len(days)
|
||
}
|
||
if index < 0 || (payload.AlignMode != models.SchedTplAlignMonth && index >= cycle) {
|
||
return nil, "每日规则的天序号不合法"
|
||
}
|
||
if seen[index] {
|
||
return nil, "每日规则的天序号重复"
|
||
}
|
||
seen[index] = true
|
||
|
||
dayType := item.DayType
|
||
if dayType != models.SchedTplDayWork && dayType != models.SchedTplDayRest {
|
||
return nil, "每日规则类型不合法(1=上班 2=休息)"
|
||
}
|
||
row := models.PlatformSchedTplDay{
|
||
DayIndex: index,
|
||
DayType: dayType,
|
||
Remark: strings.TrimSpace(item.Remark),
|
||
}
|
||
if dayType == models.SchedTplDayWork {
|
||
workCount++
|
||
row.ShiftName = strings.TrimSpace(item.ShiftName)
|
||
if row.ShiftName == "" {
|
||
return nil, fmt.Sprintf("第 %d 天选择上班,需填写班次名称", index+1)
|
||
}
|
||
if len([]rune(row.ShiftName)) > 50 {
|
||
return nil, "班次名称不能超过 50 个字符"
|
||
}
|
||
row.WorkStart = strings.TrimSpace(item.WorkStart)
|
||
row.WorkEnd = strings.TrimSpace(item.WorkEnd)
|
||
if !isValidOaTime(row.WorkStart) || !isValidOaTime(row.WorkEnd) {
|
||
return nil, fmt.Sprintf("第 %d 天的上下班时间格式应为 HH:mm", index+1)
|
||
}
|
||
if row.WorkStart == row.WorkEnd {
|
||
return nil, fmt.Sprintf("第 %d 天的上下班时间不能相同", index+1)
|
||
}
|
||
row.RestStart = strings.TrimSpace(item.RestStart)
|
||
row.RestEnd = strings.TrimSpace(item.RestEnd)
|
||
if (row.RestStart == "") != (row.RestEnd == "") {
|
||
return nil, fmt.Sprintf("第 %d 天的休息开始与结束时间需要同时填写", index+1)
|
||
}
|
||
if row.RestStart != "" && (!isValidOaTime(row.RestStart) || !isValidOaTime(row.RestEnd)) {
|
||
return nil, fmt.Sprintf("第 %d 天的休息时间格式应为 HH:mm", index+1)
|
||
}
|
||
row.ShiftShort = strings.TrimSpace(item.ShiftShort)
|
||
if row.ShiftShort == "" {
|
||
row.ShiftShort = row.ShiftName
|
||
}
|
||
row.Color = strings.TrimSpace(item.Color)
|
||
if row.Color == "" {
|
||
row.Color = "#409EFF"
|
||
}
|
||
row.WorkHours = scCalcWorkHours(row.WorkStart, row.WorkEnd, row.RestStart, row.RestEnd)
|
||
}
|
||
days = append(days, row)
|
||
}
|
||
|
||
if workCount == 0 {
|
||
return nil, "排班模板至少需要一天上班"
|
||
}
|
||
// 按天序号排序,避免前端乱序提交
|
||
for i := 0; i < len(days); i++ {
|
||
for j := i + 1; j < len(days); j++ {
|
||
if days[j].DayIndex < days[i].DayIndex {
|
||
days[i], days[j] = days[j], days[i]
|
||
}
|
||
}
|
||
}
|
||
return days, ""
|
||
}
|
||
|
||
// autoSummary 生成规则摘要(前端未填写时使用)。
|
||
func autoSummary(payload *schedTplPayload, days []models.PlatformSchedTplDay) string {
|
||
work, rest := 0, 0
|
||
shiftNames := []string{}
|
||
seenShift := map[string]bool{}
|
||
for _, day := range days {
|
||
if day.DayType == models.SchedTplDayWork {
|
||
work++
|
||
if !seenShift[day.ShiftName] {
|
||
seenShift[day.ShiftName] = true
|
||
shiftNames = append(shiftNames, fmt.Sprintf("%s %s-%s", day.ShiftName, day.WorkStart, day.WorkEnd))
|
||
}
|
||
} else {
|
||
rest++
|
||
}
|
||
}
|
||
switch payload.AlignMode {
|
||
case models.SchedTplAlignWeek:
|
||
weeks := payload.CycleDays / 7
|
||
if weeks <= 1 {
|
||
return fmt.Sprintf("每周上班 %d 天、休息 %d 天;%s", work, rest, strings.Join(shiftNames, "、"))
|
||
}
|
||
return fmt.Sprintf("%d 周循环,共上班 %d 天、休息 %d 天;%s", weeks, work, rest, strings.Join(shiftNames, "、"))
|
||
case models.SchedTplAlignMonth:
|
||
return fmt.Sprintf("每月固定休 %d 天;上班日 %s", payload.MonthRestDays, strings.Join(shiftNames, "、"))
|
||
default:
|
||
return fmt.Sprintf("每 %d 天循环,上班 %d 天、休息 %d 天;%s", payload.CycleDays, work, rest, strings.Join(shiftNames, "、"))
|
||
}
|
||
}
|
||
|
||
// Create 新建自定义模板。
|
||
// POST /platform/schedTemplates
|
||
func (c *PlatformSchedTemplateController) Create() {
|
||
claims, err := c.tplClaims()
|
||
if err != nil {
|
||
c.tplErr(401, 401, "未登录或登录已过期")
|
||
return
|
||
}
|
||
payload, ok := c.parsePayload()
|
||
if !ok {
|
||
return
|
||
}
|
||
payload.Name = strings.TrimSpace(payload.Name)
|
||
if payload.Name == "" {
|
||
c.tplErr(400, 400, "模板名称不能为空")
|
||
return
|
||
}
|
||
if len([]rune(payload.Name)) > 50 {
|
||
c.tplErr(400, 400, "模板名称不能超过 50 个字符")
|
||
return
|
||
}
|
||
if payload.TemplateType <= 0 || (payload.TemplateType > 6 && payload.TemplateType != models.SchedTplTypeCustom) {
|
||
payload.TemplateType = models.SchedTplTypeCustom
|
||
}
|
||
days, msg := buildSchedTplDays(payload)
|
||
if msg != "" {
|
||
c.tplErr(400, 400, msg)
|
||
return
|
||
}
|
||
if payload.Status != 0 {
|
||
payload.Status = 1
|
||
}
|
||
|
||
code := strings.TrimSpace(payload.Code)
|
||
if code == "" {
|
||
code = fmt.Sprintf("custom_%d", time.Now().UnixNano()/1e6)
|
||
}
|
||
exist, _ := c.tplQuery().Filter("code", code).Count()
|
||
if exist > 0 {
|
||
c.tplErr(400, 400, "模板编码已存在")
|
||
return
|
||
}
|
||
summary := strings.TrimSpace(payload.Summary)
|
||
if summary == "" {
|
||
summary = autoSummary(payload, days)
|
||
}
|
||
|
||
row := &models.PlatformSchedTpl{
|
||
Code: code,
|
||
Name: payload.Name,
|
||
TemplateType: payload.TemplateType,
|
||
AlignMode: payload.AlignMode,
|
||
CycleDays: payload.CycleDays,
|
||
WeekOffset: payload.WeekOffset,
|
||
MonthRestDays: payload.MonthRestDays,
|
||
MonthRestWeekday: payload.MonthRestWeekday,
|
||
Summary: summary,
|
||
IsSystem: 0,
|
||
Status: payload.Status,
|
||
Sort: payload.Sort,
|
||
Creater: claims.Username,
|
||
}
|
||
if row.AlignMode == models.SchedTplAlignMonth {
|
||
row.CycleDays = 0
|
||
}
|
||
|
||
tx, beginErr := orm.NewOrm().Begin()
|
||
if beginErr != nil {
|
||
c.tplErr(500, 500, "保存模板失败: "+beginErr.Error())
|
||
return
|
||
}
|
||
id, insertErr := tx.Insert(row)
|
||
if insertErr != nil {
|
||
_ = tx.Rollback()
|
||
c.tplErr(500, 500, "保存模板失败: "+insertErr.Error())
|
||
return
|
||
}
|
||
for i := range days {
|
||
days[i].TemplateID = row.ID
|
||
if _, err := tx.Insert(&days[i]); err != nil {
|
||
_ = tx.Rollback()
|
||
c.tplErr(500, 500, "保存模板规则失败: "+err.Error())
|
||
return
|
||
}
|
||
}
|
||
if err := tx.Commit(); err != nil {
|
||
c.tplErr(500, 500, "保存模板失败: "+err.Error())
|
||
return
|
||
}
|
||
_ = id
|
||
|
||
c.tplOK(c.tplView(row, true), "模板已创建")
|
||
}
|
||
|
||
// Update 编辑自定义模板;系统预置模板只读。
|
||
// POST /platform/schedTemplates/:id
|
||
func (c *PlatformSchedTemplateController) Update() {
|
||
if _, err := c.tplClaims(); err != nil {
|
||
c.tplErr(401, 401, "未登录或登录已过期")
|
||
return
|
||
}
|
||
id, err := strconv.ParseUint(strings.TrimSpace(c.Ctx.Input.Param(":id")), 10, 64)
|
||
if err != nil || id == 0 {
|
||
c.tplErr(400, 400, "无效的模板ID")
|
||
return
|
||
}
|
||
row, found := c.tplByID(id)
|
||
if !found {
|
||
c.tplErr(404, 404, "模板不存在")
|
||
return
|
||
}
|
||
if row.IsSystem == 1 {
|
||
c.tplErr(400, 400, "系统预置模板只读,不能编辑")
|
||
return
|
||
}
|
||
|
||
payload, ok := c.parsePayload()
|
||
if !ok {
|
||
return
|
||
}
|
||
payload.Name = strings.TrimSpace(payload.Name)
|
||
if payload.Name == "" {
|
||
c.tplErr(400, 400, "模板名称不能为空")
|
||
return
|
||
}
|
||
if len([]rune(payload.Name)) > 50 {
|
||
c.tplErr(400, 400, "模板名称不能超过 50 个字符")
|
||
return
|
||
}
|
||
if payload.TemplateType <= 0 || (payload.TemplateType > 6 && payload.TemplateType != models.SchedTplTypeCustom) {
|
||
payload.TemplateType = models.SchedTplTypeCustom
|
||
}
|
||
days, msg := buildSchedTplDays(payload)
|
||
if msg != "" {
|
||
c.tplErr(400, 400, msg)
|
||
return
|
||
}
|
||
if payload.Status != 0 {
|
||
payload.Status = 1
|
||
}
|
||
summary := strings.TrimSpace(payload.Summary)
|
||
if summary == "" {
|
||
summary = autoSummary(payload, days)
|
||
}
|
||
|
||
row.Name = payload.Name
|
||
row.TemplateType = payload.TemplateType
|
||
row.AlignMode = payload.AlignMode
|
||
row.CycleDays = payload.CycleDays
|
||
if row.AlignMode == models.SchedTplAlignMonth {
|
||
row.CycleDays = 0
|
||
}
|
||
row.WeekOffset = payload.WeekOffset
|
||
row.MonthRestDays = payload.MonthRestDays
|
||
row.MonthRestWeekday = payload.MonthRestWeekday
|
||
row.Summary = summary
|
||
row.Status = payload.Status
|
||
row.Sort = payload.Sort
|
||
|
||
tx, beginErr := orm.NewOrm().Begin()
|
||
if beginErr != nil {
|
||
c.tplErr(500, 500, "保存模板失败: "+beginErr.Error())
|
||
return
|
||
}
|
||
if _, err := tx.Update(row); err != nil {
|
||
_ = tx.Rollback()
|
||
c.tplErr(500, 500, "保存模板失败: "+err.Error())
|
||
return
|
||
}
|
||
// 规则整体替换:先清空旧规则再写入新规则,避免残留天数
|
||
if _, err := tx.QueryTable(new(models.PlatformSchedTplDay)).Filter("template_id", row.ID).Delete(); err != nil {
|
||
_ = tx.Rollback()
|
||
c.tplErr(500, 500, "保存模板规则失败: "+err.Error())
|
||
return
|
||
}
|
||
for i := range days {
|
||
days[i].TemplateID = row.ID
|
||
if _, err := tx.Insert(&days[i]); err != nil {
|
||
_ = tx.Rollback()
|
||
c.tplErr(500, 500, "保存模板规则失败: "+err.Error())
|
||
return
|
||
}
|
||
}
|
||
if err := tx.Commit(); err != nil {
|
||
c.tplErr(500, 500, "保存模板失败: "+err.Error())
|
||
return
|
||
}
|
||
c.tplOK(c.tplView(row, true), "模板已更新")
|
||
}
|
||
|
||
// Delete 删除自定义模板(软删除);系统预置模板禁止删除。
|
||
// DELETE /platform/schedTemplates/:id
|
||
func (c *PlatformSchedTemplateController) Delete() {
|
||
if _, err := c.tplClaims(); err != nil {
|
||
c.tplErr(401, 401, "未登录或登录已过期")
|
||
return
|
||
}
|
||
id, err := strconv.ParseUint(strings.TrimSpace(c.Ctx.Input.Param(":id")), 10, 64)
|
||
if err != nil || id == 0 {
|
||
c.tplErr(400, 400, "无效的模板ID")
|
||
return
|
||
}
|
||
row, found := c.tplByID(id)
|
||
if !found {
|
||
c.tplErr(404, 404, "模板不存在")
|
||
return
|
||
}
|
||
if row.IsSystem == 1 {
|
||
c.tplErr(400, 400, "系统预置模板不能删除")
|
||
return
|
||
}
|
||
now := time.Now()
|
||
row.DeleteTime = &now
|
||
if _, err := models.Orm.Update(row, "delete_time"); err != nil {
|
||
c.tplErr(500, 500, "删除模板失败: "+err.Error())
|
||
return
|
||
}
|
||
c.tplOK(map[string]interface{}{"id": row.ID}, "模板已删除")
|
||
}
|
||
|
||
// ToggleStatus 启用 / 停用自定义模板;系统预置模板不可停用。
|
||
// POST /platform/schedTemplates/:id/status
|
||
func (c *PlatformSchedTemplateController) ToggleStatus() {
|
||
if _, err := c.tplClaims(); err != nil {
|
||
c.tplErr(401, 401, "未登录或登录已过期")
|
||
return
|
||
}
|
||
id, err := strconv.ParseUint(strings.TrimSpace(c.Ctx.Input.Param(":id")), 10, 64)
|
||
if err != nil || id == 0 {
|
||
c.tplErr(400, 400, "无效的模板ID")
|
||
return
|
||
}
|
||
row, found := c.tplByID(id)
|
||
if !found {
|
||
c.tplErr(404, 404, "模板不存在")
|
||
return
|
||
}
|
||
if row.IsSystem == 1 {
|
||
c.tplErr(400, 400, "系统预置模板固定启用,不能停用")
|
||
return
|
||
}
|
||
status, _ := c.GetInt("status", -1)
|
||
if status != 0 && status != 1 {
|
||
var body struct {
|
||
Status int8 `json:"status"`
|
||
}
|
||
_ = json.Unmarshal(c.Ctx.Input.RequestBody, &body)
|
||
if body.Status != 0 && body.Status != 1 {
|
||
c.tplErr(400, 400, "状态只能是 0 或 1")
|
||
return
|
||
}
|
||
status = int(body.Status)
|
||
}
|
||
row.Status = int8(status)
|
||
if _, err := models.Orm.Update(row, "status"); err != nil {
|
||
c.tplErr(500, 500, "更新状态失败: "+err.Error())
|
||
return
|
||
}
|
||
c.tplOK(map[string]interface{}{"id": row.ID, "status": row.Status}, "状态已更新")
|
||
}
|