优化日程增加文件上传功能
This commit is contained in:
@@ -299,6 +299,51 @@ type oaSchedulePayload struct {
|
||||
Priority int8 `json:"priority"`
|
||||
}
|
||||
|
||||
// oaScheduleImage 日程相关图片(截图/照片),只存文件引用,不存二进制。
|
||||
type oaScheduleImage struct {
|
||||
ID uint64 `json:"id"`
|
||||
URL string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
const (
|
||||
oaScheduleMaxImages = 20
|
||||
oaScheduleMaxImageURL = 500
|
||||
oaScheduleMaxImageName = 120
|
||||
)
|
||||
|
||||
// normalizeOaScheduleImages 校验并序列化日程图片列表:
|
||||
// 丢弃无 url 或超长的条目,条目数超限时返回 false。
|
||||
func normalizeOaScheduleImages(list []oaScheduleImage) (string, bool) {
|
||||
if len(list) > oaScheduleMaxImages {
|
||||
return "", false
|
||||
}
|
||||
out := make([]oaScheduleImage, 0, len(list))
|
||||
for _, img := range list {
|
||||
img.URL = strings.TrimSpace(img.URL)
|
||||
if img.URL == "" || len(img.URL) > oaScheduleMaxImageURL {
|
||||
continue
|
||||
}
|
||||
img.Name = strings.TrimSpace(img.Name)
|
||||
if utf8.RuneCountInString(img.Name) > oaScheduleMaxImageName {
|
||||
img.Name = string([]rune(img.Name)[:oaScheduleMaxImageName])
|
||||
}
|
||||
out = append(out, img)
|
||||
}
|
||||
raw, err := json.Marshal(out)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
return string(raw), true
|
||||
}
|
||||
|
||||
// parseOaScheduleImages 解析 images 列;脏数据返回空数组,不阻断详情展示。
|
||||
func parseOaScheduleImages(raw string) []oaScheduleImage {
|
||||
list := make([]oaScheduleImage, 0)
|
||||
_ = json.Unmarshal([]byte(raw), &list)
|
||||
return list
|
||||
}
|
||||
|
||||
// parseOaSchedulePayload 读取并校验新建/编辑日程的请求体;校验失败时直接输出错误响应。
|
||||
func (c *BackendOaScheduleController) parseOaSchedulePayload() (oaSchedulePayload, bool) {
|
||||
var payload oaSchedulePayload
|
||||
@@ -442,6 +487,59 @@ func (c *BackendOaScheduleController) Update() {
|
||||
c.oasOk(item)
|
||||
}
|
||||
|
||||
// SetImages POST /backend/oa/schedule/images/:id
|
||||
// 单独维护日程的相关图片(文件已先上传到文件管理,这里只存引用)。
|
||||
// 与 Update 分开,避免编辑标题/时间等基础信息时把图片清空。
|
||||
func (c *BackendOaScheduleController) SetImages() {
|
||||
claims, err := c.oaScheduleClaims()
|
||||
if err != nil {
|
||||
c.oasJsonErr(401, 401, "未登录或无权限")
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.oasJsonErr(400, 400, "无效ID")
|
||||
return
|
||||
}
|
||||
|
||||
var payload struct {
|
||||
Images []oaScheduleImage `json:"images"`
|
||||
}
|
||||
raw, _ := io.ReadAll(c.Ctx.Request.Body)
|
||||
if len(raw) > 0 && json.Unmarshal(raw, &payload) != nil {
|
||||
c.oasJsonErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
imagesJSON, ok := normalizeOaScheduleImages(payload.Images)
|
||||
if !ok {
|
||||
c.oasJsonErr(400, 400, "图片数量过多")
|
||||
return
|
||||
}
|
||||
|
||||
var item models.OaSchedule
|
||||
err = models.Orm.QueryTable(new(models.OaSchedule)).
|
||||
Filter("id", id).
|
||||
Filter("is_deleted", 0).
|
||||
Filter("tid", claims.TenantId).
|
||||
Filter("user_id", claims.UserID).
|
||||
One(&item)
|
||||
if err != nil {
|
||||
c.oasJsonErr(404, 404, "日程不存在")
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
item.Images = imagesJSON
|
||||
item.UpdateTime = &now
|
||||
if _, err := models.Orm.Update(&item, "Images", "UpdateTime"); err != nil {
|
||||
c.oasJsonErr(500, 500, "保存失败")
|
||||
return
|
||||
}
|
||||
|
||||
c.oasOk(map[string]interface{}{"images": parseOaScheduleImages(imagesJSON)})
|
||||
}
|
||||
|
||||
// Delete DELETE /backend/oa/schedule/delete/:id 软删除日程。
|
||||
func (c *BackendOaScheduleController) Delete() {
|
||||
claims, err := c.oaScheduleClaims()
|
||||
@@ -577,6 +675,7 @@ func carryOaSchedule(item *models.OaSchedule, targetDate string, claims *jwtutil
|
||||
UserName: item.UserName,
|
||||
Title: item.Title,
|
||||
Content: item.Content,
|
||||
Images: item.Images,
|
||||
ScheduleDate: targetDate,
|
||||
StartTime: item.StartTime,
|
||||
EndTime: item.EndTime,
|
||||
|
||||
@@ -21,6 +21,8 @@ type OaSchedule struct {
|
||||
UserName string `orm:"column(user_name);size(100);default()" json:"user_name"`
|
||||
Title string `orm:"column(title);size(255)" json:"title"`
|
||||
Content string `orm:"column(content);type(text);null" json:"content"`
|
||||
// Images 相关图片(截图/照片),存 JSON 数组:[{"id":1,"url":"","name":""}]
|
||||
Images string `orm:"column(images);type(text);null" json:"images"`
|
||||
ScheduleDate string `orm:"column(schedule_date);type(date)" json:"schedule_date"`
|
||||
StartTime string `orm:"column(start_time);size(8);default()" json:"start_time"`
|
||||
EndTime string `orm:"column(end_time);size(8);default()" json:"end_time"`
|
||||
@@ -45,7 +47,7 @@ func (m *OaSchedule) TableName() string {
|
||||
|
||||
var oaScheduleCarryColumnsOnce sync.Once
|
||||
|
||||
// EnsureOaScheduleCarryColumns 为日程表补齐"顺延到下一天"所需字段。
|
||||
// EnsureOaScheduleCarryColumns 为日程表补齐"顺延到下一天"与"相关图片"所需字段。
|
||||
// 历史库可能早于该特性建表,这里在首次访问日程接口时自动补列,
|
||||
// 字段已存在时 MySQL 会报 duplicate column,统一忽略,不阻断主流程。
|
||||
func EnsureOaScheduleCarryColumns() error {
|
||||
@@ -59,6 +61,7 @@ func EnsureOaScheduleCarryColumns() error {
|
||||
"ALTER TABLE yz_backend_oa_schedule ADD COLUMN carry_over tinyint NOT NULL DEFAULT 0 COMMENT '是否已顺延到下一天 0-否 1-是'",
|
||||
"ALTER TABLE yz_backend_oa_schedule ADD COLUMN carry_count int NOT NULL DEFAULT 0 COMMENT '累计顺延次数'",
|
||||
"ALTER TABLE yz_backend_oa_schedule ADD COLUMN carry_to_date varchar(10) NOT NULL DEFAULT '' COMMENT '顺延目标日期(YYYY-MM-DD)'",
|
||||
"ALTER TABLE yz_backend_oa_schedule ADD COLUMN images text NULL COMMENT '相关图片JSON数组 [{id,url,name}]'",
|
||||
}
|
||||
for _, sql := range alters {
|
||||
if _, e := Orm.Raw(sql).Exec(); e != nil {
|
||||
|
||||
@@ -280,6 +280,7 @@ func RegisterAuthRoutes() {
|
||||
beego.Router("/backend/oa/schedule/finish/:id", &controllers.BackendOaScheduleController{}, "post:FinishSchedule")
|
||||
beego.Router("/backend/oa/schedule/carry/:id", &controllers.BackendOaScheduleController{}, "post:CarrySchedule")
|
||||
beego.Router("/backend/oa/schedule/carry-pending", &controllers.BackendOaScheduleController{}, "post:CarryPending")
|
||||
beego.Router("/backend/oa/schedule/images/:id", &controllers.BackendOaScheduleController{}, "post:SetImages")
|
||||
|
||||
// OA通知公告
|
||||
beego.Router("/backend/oa/notice/list", &controllers.BackendOaNoticeController{}, "get:List")
|
||||
|
||||
Reference in New Issue
Block a user