优化小程序报销模块
This commit is contained in:
1 parent
1e9666cefd
commit
48f3bd997c
21 files changed
+5738
-1750
No files matched your search
@@ -160,6 +160,21 @@ func (c *BackendOaScheduleController) List() {
|
||||
endDate := strings.TrimSpace(c.GetString("end_date"))
|
||||
category := strings.TrimSpace(c.GetString("category"))
|
||||
|
||||
data, code, msg := oaScheduleListData(claims.TenantId, claims.UserID,
|
||||
page, pageSize, keyword, status, priority, startDate, endDate, category)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(code, code, msg)
|
||||
return
|
||||
}
|
||||
c.oasOk(data)
|
||||
}
|
||||
|
||||
// oaScheduleListData 日程列表的共享查询逻辑,Web 后台(/backend/oa/schedule/list)
|
||||
// 与移动端(/api/oa/schedule/list)共用。
|
||||
// 返回 (数据, HTTP 状态码, 错误信息),错误信息为空串表示成功。
|
||||
func oaScheduleListData(tid, userID, page, pageSize int,
|
||||
keyword, status, priority, startDate, endDate, category string) (map[string]interface{}, int, string) {
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
@@ -181,7 +196,7 @@ func (c *BackendOaScheduleController) List() {
|
||||
|
||||
// 分类角标按全量统计(只受关键词/优先级影响),不随日历翻月或区间筛选跳动
|
||||
countOf := func(f oaScheduleFilter) int64 {
|
||||
n, _ := oaScheduleQS(claims.TenantId, claims.UserID, f).Count()
|
||||
n, _ := oaScheduleQS(tid, userID, f).Count()
|
||||
return n
|
||||
}
|
||||
today := time.Now().Format("2006-01-02")
|
||||
@@ -214,16 +229,15 @@ func (c *BackendOaScheduleController) List() {
|
||||
listFilter.Status = 1
|
||||
}
|
||||
|
||||
qs := oaScheduleQS(claims.TenantId, claims.UserID, listFilter)
|
||||
qs := oaScheduleQS(tid, userID, listFilter)
|
||||
total, _ := qs.Count()
|
||||
|
||||
var list []models.OaSchedule
|
||||
_, err = qs.OrderBy("schedule_date", "start_time", "-id").
|
||||
_, err := qs.OrderBy("schedule_date", "start_time", "-id").
|
||||
Limit(pageSize).Offset((page - 1) * pageSize).
|
||||
All(&list)
|
||||
if err != nil && err != orm.ErrNoRows {
|
||||
c.oasJsonErr(500, 500, "查询失败")
|
||||
return
|
||||
return nil, 500, "查询失败"
|
||||
}
|
||||
if list == nil {
|
||||
list = []models.OaSchedule{}
|
||||
@@ -234,11 +248,11 @@ func (c *BackendOaScheduleController) List() {
|
||||
list[i].ScheduleDate = normalizeOaDate(list[i].ScheduleDate)
|
||||
}
|
||||
|
||||
c.oasOk(map[string]interface{}{
|
||||
return map[string]interface{}{
|
||||
"list": list,
|
||||
"total": total,
|
||||
"counts": counts,
|
||||
})
|
||||
}, 200, ""
|
||||
}
|
||||
|
||||
// Holidays GET /backend/oa/holiday
|
||||
@@ -590,25 +604,36 @@ func parseOaScheduleImages(raw string) []oaScheduleImage {
|
||||
|
||||
// parseOaSchedulePayload 读取并校验新建/编辑日程的请求体;校验失败时直接输出错误响应。
|
||||
func (c *BackendOaScheduleController) parseOaSchedulePayload() (oaSchedulePayload, bool) {
|
||||
var payload oaSchedulePayload
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil || json.Unmarshal(raw, &payload) != nil {
|
||||
if err != nil {
|
||||
c.oasJsonErr(400, 400, "参数错误")
|
||||
return oaSchedulePayload{}, false
|
||||
}
|
||||
payload, msg := parseOaSchedulePayloadBody(raw)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(400, 400, msg)
|
||||
return payload, false
|
||||
}
|
||||
return payload, true
|
||||
}
|
||||
|
||||
// parseOaSchedulePayloadBody 新建/编辑日程请求体的共享校验逻辑,
|
||||
// Web 后台与移动端共用。返回 (校验后的载荷, 错误信息),错误信息为空串表示成功。
|
||||
func parseOaSchedulePayloadBody(raw []byte) (oaSchedulePayload, string) {
|
||||
var payload oaSchedulePayload
|
||||
if len(raw) == 0 || json.Unmarshal(raw, &payload) != nil {
|
||||
return payload, "参数错误"
|
||||
}
|
||||
|
||||
payload.Title = strings.TrimSpace(payload.Title)
|
||||
if payload.Title == "" {
|
||||
c.oasJsonErr(400, 400, "请输入日程标题")
|
||||
return payload, false
|
||||
return payload, "请输入日程标题"
|
||||
}
|
||||
if utf8.RuneCountInString(payload.Title) > 80 {
|
||||
c.oasJsonErr(400, 400, "日程标题不能超过80字")
|
||||
return payload, false
|
||||
return payload, "日程标题不能超过80字"
|
||||
}
|
||||
if !isValidOaDate(payload.ScheduleDate) {
|
||||
c.oasJsonErr(400, 400, "日程日期无效")
|
||||
return payload, false
|
||||
return payload, "日程日期无效"
|
||||
}
|
||||
if payload.AllDay != 0 {
|
||||
payload.AllDay = 1
|
||||
@@ -616,17 +641,14 @@ func (c *BackendOaScheduleController) parseOaSchedulePayload() (oaSchedulePayloa
|
||||
payload.EndTime = ""
|
||||
} else {
|
||||
if !isValidOaTime(payload.StartTime) {
|
||||
c.oasJsonErr(400, 400, "开始时间无效")
|
||||
return payload, false
|
||||
return payload, "开始时间无效"
|
||||
}
|
||||
if payload.EndTime != "" {
|
||||
if !isValidOaTime(payload.EndTime) {
|
||||
c.oasJsonErr(400, 400, "结束时间无效")
|
||||
return payload, false
|
||||
return payload, "结束时间无效"
|
||||
}
|
||||
if payload.EndTime < payload.StartTime {
|
||||
c.oasJsonErr(400, 400, "结束时间不能早于开始时间")
|
||||
return payload, false
|
||||
return payload, "结束时间不能早于开始时间"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -649,18 +671,16 @@ func (c *BackendOaScheduleController) parseOaSchedulePayload() (oaSchedulePayloa
|
||||
}
|
||||
payload.RemindChannels = validChannels
|
||||
if len(validChannels) == 0 {
|
||||
c.oasJsonErr(400, 400, "请至少选择一个提醒渠道")
|
||||
return payload, false
|
||||
return payload, "请至少选择一个提醒渠道"
|
||||
}
|
||||
if _, err := time.ParseInLocation("2006-01-02 15:04:05", payload.ReminderTime, time.Local); err != nil {
|
||||
c.oasJsonErr(400, 400, "提醒时间格式不合法,支持 YYYY-MM-DD HH:mm:ss")
|
||||
return payload, false
|
||||
return payload, "提醒时间格式不合法,支持 YYYY-MM-DD HH:mm:ss"
|
||||
}
|
||||
if payload.AdvanceMinutes < 0 {
|
||||
payload.AdvanceMinutes = 0
|
||||
}
|
||||
}
|
||||
return payload, true
|
||||
return payload, ""
|
||||
}
|
||||
|
||||
// Create POST /backend/oa/schedule/create
|
||||
@@ -676,6 +696,17 @@ func (c *BackendOaScheduleController) Create() {
|
||||
return
|
||||
}
|
||||
|
||||
item, code, msg := oaScheduleCreateCore(claims, payload)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(code, code, msg)
|
||||
return
|
||||
}
|
||||
c.oasOk(item)
|
||||
}
|
||||
|
||||
// oaScheduleCreateCore 创建日程(含提醒绑定)的共享逻辑,Web 后台与移动端共用。
|
||||
// 返回 (新建日程, HTTP 状态码, 错误信息),错误信息为空串表示成功。
|
||||
func oaScheduleCreateCore(claims *jwtutil.Claims, payload oaSchedulePayload) (*models.OaSchedule, int, string) {
|
||||
now := time.Now()
|
||||
item := &models.OaSchedule{
|
||||
Tid: claims.TenantId,
|
||||
@@ -695,8 +726,7 @@ func (c *BackendOaScheduleController) Create() {
|
||||
UpdateTime: &now,
|
||||
}
|
||||
if _, err := models.Orm.Insert(item); err != nil {
|
||||
c.oasJsonErr(500, 500, "保存失败")
|
||||
return
|
||||
return nil, 500, "保存失败"
|
||||
}
|
||||
|
||||
// 开启提醒:生成绑定的提醒任务,并把其 ID 回写到日程。
|
||||
@@ -713,17 +743,15 @@ func (c *BackendOaScheduleController) Create() {
|
||||
if rerr != nil {
|
||||
// 回滚已创建的日程,避免产生孤立日程
|
||||
_, _ = models.Orm.QueryTable(new(models.OaSchedule)).Filter("id", item.ID).Delete()
|
||||
c.oasJsonErr(500, 500, rerr.Error())
|
||||
return
|
||||
return nil, 500, rerr.Error()
|
||||
}
|
||||
item.ReminderID = rid
|
||||
if _, err := models.Orm.Update(item, "ReminderID"); err != nil {
|
||||
c.oasJsonErr(500, 500, "保存失败")
|
||||
return
|
||||
return nil, 500, "保存失败"
|
||||
}
|
||||
}
|
||||
|
||||
c.oasOk(item)
|
||||
return item, 200, ""
|
||||
}
|
||||
|
||||
// Update POST /backend/oa/schedule/update/:id
|
||||
@@ -745,16 +773,26 @@ func (c *BackendOaScheduleController) Update() {
|
||||
return
|
||||
}
|
||||
|
||||
item, code, msg := oaScheduleUpdateCore(claims, id, payload)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(code, code, msg)
|
||||
return
|
||||
}
|
||||
c.oasOk(item)
|
||||
}
|
||||
|
||||
// oaScheduleUpdateCore 更新日程(含提醒重绑)的共享逻辑,Web 后台与移动端共用。
|
||||
// 返回 (更新后日程, HTTP 状态码, 错误信息),错误信息为空串表示成功。
|
||||
func oaScheduleUpdateCore(claims *jwtutil.Claims, id uint64, payload oaSchedulePayload) (*models.OaSchedule, int, string) {
|
||||
var item models.OaSchedule
|
||||
err = models.Orm.QueryTable(new(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
|
||||
return nil, 404, "日程不存在"
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
@@ -781,8 +819,7 @@ func (c *BackendOaScheduleController) Update() {
|
||||
payload.AdvanceMinutes,
|
||||
)
|
||||
if rerr != nil {
|
||||
c.oasJsonErr(500, 500, rerr.Error())
|
||||
return
|
||||
return nil, 500, rerr.Error()
|
||||
}
|
||||
if item.ReminderID > 0 {
|
||||
deleteBoundReminder(item.ReminderID)
|
||||
@@ -796,11 +833,10 @@ func (c *BackendOaScheduleController) Update() {
|
||||
if _, err := models.Orm.Update(&item,
|
||||
"Title", "Content", "ScheduleDate", "StartTime", "EndTime",
|
||||
"AllDay", "Color", "Priority", "ReminderID", "UpdateTime"); err != nil {
|
||||
c.oasJsonErr(500, 500, "保存失败")
|
||||
return
|
||||
return nil, 500, "保存失败"
|
||||
}
|
||||
|
||||
c.oasOk(item)
|
||||
return &item, 200, ""
|
||||
}
|
||||
|
||||
// SetImages POST /backend/oa/schedule/images/:id
|
||||
@@ -827,33 +863,42 @@ func (c *BackendOaScheduleController) SetImages() {
|
||||
c.oasJsonErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
imagesJSON, ok := normalizeOaScheduleImages(payload.Images)
|
||||
if !ok {
|
||||
c.oasJsonErr(400, 400, "图片数量过多")
|
||||
|
||||
images, code, msg := oaScheduleSetImagesCore(claims, id, payload.Images)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(code, code, msg)
|
||||
return
|
||||
}
|
||||
c.oasOk(map[string]interface{}{"images": images})
|
||||
}
|
||||
|
||||
// oaScheduleSetImagesCore 保存日程相关图片(只存文件引用)的共享逻辑,
|
||||
// Web 后台与移动端共用。返回 (图片列表, HTTP 状态码, 错误信息),错误信息为空串表示成功。
|
||||
func oaScheduleSetImagesCore(claims *jwtutil.Claims, id uint64, images []oaScheduleImage) ([]oaScheduleImage, int, string) {
|
||||
imagesJSON, ok := normalizeOaScheduleImages(images)
|
||||
if !ok {
|
||||
return nil, 400, "图片数量过多"
|
||||
}
|
||||
|
||||
var item models.OaSchedule
|
||||
err = models.Orm.QueryTable(new(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
|
||||
return nil, 404, "日程不存在"
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
item.Images = imagesJSON
|
||||
item.UpdateTime = &now
|
||||
if _, err := models.Orm.Update(&item, "Images", "UpdateTime"); err != nil {
|
||||
c.oasJsonErr(500, 500, "保存失败")
|
||||
return
|
||||
return nil, 500, "保存失败"
|
||||
}
|
||||
|
||||
c.oasOk(map[string]interface{}{"images": parseOaScheduleImages(imagesJSON)})
|
||||
return parseOaScheduleImages(imagesJSON), 200, ""
|
||||
}
|
||||
|
||||
// UpdateContent POST /backend/oa/schedule/content/:id 仅更新备注内容。
|
||||
@@ -918,17 +963,27 @@ func (c *BackendOaScheduleController) Delete() {
|
||||
return
|
||||
}
|
||||
|
||||
code, msg := oaScheduleDeleteCore(claims, id)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(code, code, msg)
|
||||
return
|
||||
}
|
||||
c.oasOk(nil)
|
||||
}
|
||||
|
||||
// oaScheduleDeleteCore 软删除日程并清理绑定提醒的共享逻辑,Web 后台与移动端共用。
|
||||
// 返回 (HTTP 状态码, 错误信息),错误信息为空串表示成功。
|
||||
func oaScheduleDeleteCore(claims *jwtutil.Claims, id uint64) (int, string) {
|
||||
now := time.Now()
|
||||
var item models.OaSchedule
|
||||
err = models.Orm.QueryTable(new(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
|
||||
return 404, "日程不存在或已删除"
|
||||
}
|
||||
|
||||
// 先删除绑定的提醒任务,避免提醒工具里残留孤立任务
|
||||
@@ -940,11 +995,10 @@ func (c *BackendOaScheduleController) Delete() {
|
||||
item.DeleteTime = &now
|
||||
item.UpdateTime = &now
|
||||
if _, err := models.Orm.Update(&item, "IsDeleted", "DeleteTime", "UpdateTime"); err != nil {
|
||||
c.oasJsonErr(500, 500, "删除失败")
|
||||
return
|
||||
return 500, "删除失败"
|
||||
}
|
||||
|
||||
c.oasOk(nil)
|
||||
return 200, ""
|
||||
}
|
||||
|
||||
// FinishSchedule POST /backend/oa/schedule/finish/:id
|
||||
@@ -964,16 +1018,26 @@ func (c *BackendOaScheduleController) FinishSchedule() {
|
||||
return
|
||||
}
|
||||
|
||||
newStatus, code, msg := oaScheduleToggleCore(claims, id)
|
||||
if msg != "" {
|
||||
c.oasJsonErr(code, code, msg)
|
||||
return
|
||||
}
|
||||
c.oasOk(map[string]interface{}{"status": newStatus})
|
||||
}
|
||||
|
||||
// oaScheduleToggleCore 切换日程完成状态的共享逻辑,Web 后台与移动端共用。
|
||||
// 返回 (新状态, HTTP 状态码, 错误信息),错误信息为空串表示成功。
|
||||
func oaScheduleToggleCore(claims *jwtutil.Claims, id uint64) (int8, int, string) {
|
||||
var item models.OaSchedule
|
||||
err = models.Orm.QueryTable(new(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
|
||||
return 0, 404, "日程不存在"
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
@@ -990,11 +1054,10 @@ func (c *BackendOaScheduleController) FinishSchedule() {
|
||||
item.UpdateTime = &now
|
||||
|
||||
if _, err := models.Orm.Update(&item, "Status", "FinishTime", "UpdateTime"); err != nil {
|
||||
c.oasJsonErr(500, 500, "操作失败")
|
||||
return
|
||||
return 0, 500, "操作失败"
|
||||
}
|
||||
|
||||
c.oasOk(map[string]interface{}{"status": newStatus})
|
||||
return newStatus, 200, ""
|
||||
}
|
||||
|
||||
// nextOaDate 返回 dateStr 之后的第 days 天,格式仍为 "YYYY-MM-DD"。
|
||||
|
||||
Reference in new issue
Block a user