更新若干功能
This commit is contained in:
1 parent
892ba5886d
commit
79d5ae6b66
45 files changed
+6755
-38
No files matched your search
@@ -0,0 +1,237 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"server/pkg/identity"
|
||||
"server/services/dailyreport"
|
||||
)
|
||||
|
||||
// OA 工作日报(小程序端)。与后台 /backend/oa/dailyreport/* 共用
|
||||
// services/dailyreport 的权限与校验逻辑,仅在响应包装与上传入口上有差异。
|
||||
|
||||
// dailyReportCtx 解析移动端令牌并组装日报身份。
|
||||
func (c *AppOaController) dailyReportCtx() (*dailyreport.UserContext, bool) {
|
||||
claims, err := c.oaClaims()
|
||||
if err != nil {
|
||||
code := identity.Status(err)
|
||||
c.oaErr(code, code, err.Error())
|
||||
return nil, false
|
||||
}
|
||||
u, err := dailyreport.BuildContext(
|
||||
uint64(claims.TenantId), uint64(claims.UserID), claims.Username, claims.UserType == "platform")
|
||||
if err != nil {
|
||||
code := dailyreport.StatusOf(err, 500)
|
||||
msg := err.Error()
|
||||
if code == 500 {
|
||||
msg = "操作失败,请稍后重试"
|
||||
}
|
||||
c.oaErr(code, code, msg)
|
||||
return nil, false
|
||||
}
|
||||
return u, true
|
||||
}
|
||||
|
||||
func (c *AppOaController) dailyReportFail(err error) {
|
||||
code := dailyreport.StatusOf(err, 500)
|
||||
msg := err.Error()
|
||||
if code == 500 {
|
||||
msg = "操作失败,请稍后重试"
|
||||
}
|
||||
c.oaErr(code, code, msg)
|
||||
}
|
||||
|
||||
func (c *AppOaController) dailyReportID() uint64 {
|
||||
id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
||||
if id == 0 {
|
||||
c.oaErr(400, 400, "无效ID")
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// DailyReportProfile GET /api/oa/dailyreport/profile
|
||||
func (c *AppOaController) DailyReportProfile() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
teamOrgs := u.TeamOrgIDs
|
||||
if teamOrgs == nil {
|
||||
teamOrgs = []uint64{}
|
||||
}
|
||||
c.oaOk(map[string]interface{}{
|
||||
"user_id": u.UID,
|
||||
"user_name": u.Name,
|
||||
"org_id": u.OrgID,
|
||||
"org_name": u.OrgName,
|
||||
"is_admin": u.IsAdmin,
|
||||
"can_view_team": u.CanViewTeam,
|
||||
"team_org_ids": teamOrgs,
|
||||
"window_start": dailyreport.WindowStart(),
|
||||
"window_end": dailyreport.Today(),
|
||||
"backfill_days": dailyreport.BackfillDays,
|
||||
})
|
||||
}
|
||||
|
||||
// DailyReportMineList GET /api/oa/dailyreport/mine/list
|
||||
func (c *AppOaController) DailyReportMineList() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 20)
|
||||
res, err := dailyreport.ListMine(u, dailyreport.MineQuery{
|
||||
StartDate: strings.TrimSpace(c.GetString("start_date")),
|
||||
EndDate: strings.TrimSpace(c.GetString("end_date")),
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(res)
|
||||
}
|
||||
|
||||
// DailyReportSave POST /api/oa/dailyreport/save
|
||||
func (c *AppOaController) DailyReportSave() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var in dailyreport.SaveInput
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil || json.Unmarshal(raw, &in) != nil {
|
||||
c.oaErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
item, err := dailyreport.Save(u, in)
|
||||
if err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(item)
|
||||
}
|
||||
|
||||
// DailyReportDetail GET /api/oa/dailyreport/detail/:id
|
||||
func (c *AppOaController) DailyReportDetail() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id := c.dailyReportID()
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
detail, err := dailyreport.GetDetail(u, id)
|
||||
if err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(detail)
|
||||
}
|
||||
|
||||
// DailyReportDelete DELETE /api/oa/dailyreport/delete/:id
|
||||
func (c *AppOaController) DailyReportDelete() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id := c.dailyReportID()
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
if err := dailyreport.Delete(u, id); err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// DailyReportTeamStatus GET /api/oa/dailyreport/team/status
|
||||
func (c *AppOaController) DailyReportTeamStatus() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 20)
|
||||
orgID, _ := c.GetInt64("org_id", 0)
|
||||
res, err := dailyreport.TeamStatus(u, dailyreport.TeamQuery{
|
||||
Date: strings.TrimSpace(c.GetString("date")),
|
||||
OrgID: uint64(orgID),
|
||||
Keyword: strings.TrimSpace(c.GetString("keyword")),
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(res)
|
||||
}
|
||||
|
||||
// DailyReportTeamOrgs GET /api/oa/dailyreport/team/orgs
|
||||
func (c *AppOaController) DailyReportTeamOrgs() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
orgs, err := dailyreport.TeamOrgs(u)
|
||||
if err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(map[string]interface{}{"list": orgs})
|
||||
}
|
||||
|
||||
// DailyReportComment POST /api/oa/dailyreport/comment
|
||||
func (c *AppOaController) DailyReportComment() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var payload oaDailyReportCommentPayload
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil || json.Unmarshal(raw, &payload) != nil {
|
||||
c.oaErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if payload.ReportID == 0 {
|
||||
c.oaErr(400, 400, "缺少日报ID")
|
||||
return
|
||||
}
|
||||
comment, err := dailyreport.AddComment(u, payload.ReportID, payload.Content, payload.ReplyToID)
|
||||
if err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(comment)
|
||||
}
|
||||
|
||||
// DailyReportCommentDelete DELETE /api/oa/dailyreport/comment/:id
|
||||
func (c *AppOaController) DailyReportCommentDelete() {
|
||||
u, ok := c.dailyReportCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id := c.dailyReportID()
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
if err := dailyreport.DeleteComment(u, id); err != nil {
|
||||
c.dailyReportFail(err)
|
||||
return
|
||||
}
|
||||
c.oaOk(map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// DailyReportUpload POST /api/oa/dailyreport/upload(multipart,字段名 file)
|
||||
// 复用 OA 附件上传:图片 / PDF,单个文件 ≤10MB,落入租户文件管理。
|
||||
func (c *AppOaController) DailyReportUpload() {
|
||||
c.uploadTenantImage()
|
||||
}
|
||||
@@ -348,6 +348,10 @@ func (c *BackendCrmBusinessController) ChangeStage() {
|
||||
pipelineErr(&c.Controller, 400, 400, "商机已转化并锁定,不能流转阶段")
|
||||
return
|
||||
}
|
||||
if biz.Status == 3 {
|
||||
pipelineErr(&c.Controller, 400, 400, "商机已废弃,请先恢复为「跟进中」再流转阶段")
|
||||
return
|
||||
}
|
||||
// 阶段未变化:直接幂等返回,不写日志
|
||||
if strings.TrimSpace(biz.Stage) == stage {
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": biz.ID, "stage": biz.Stage})
|
||||
@@ -364,6 +368,78 @@ func (c *BackendCrmBusinessController) ChangeStage() {
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": biz.ID, "stage": stage})
|
||||
}
|
||||
|
||||
// ChangeStatus POST /backend/crm/business/:id/status
|
||||
// 商机状态流转:1跟进中 / 3已废弃。
|
||||
// 「已转化项目(2)」不走本接口,须用「转项目」完成(会锁定商机)。
|
||||
func (c *BackendCrmBusinessController) ChangeStatus() {
|
||||
claims, err := pipelineClaims(&c.Controller)
|
||||
if err != nil {
|
||||
code := identity.Status(err)
|
||||
pipelineErr(&c.Controller, code, code, err.Error())
|
||||
return
|
||||
}
|
||||
id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64)
|
||||
if id == 0 {
|
||||
pipelineErr(&c.Controller, 400, 400, "无效的ID")
|
||||
return
|
||||
}
|
||||
raw, _ := io.ReadAll(c.Ctx.Request.Body)
|
||||
var p struct {
|
||||
Status int8 `json:"status"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
pipelineErr(&c.Controller, 400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if p.Status != 1 && p.Status != 3 {
|
||||
pipelineErr(&c.Controller, 400, 400, "仅支持流转为「跟进中 / 已废弃」,转为已转化项目请使用「转项目」")
|
||||
return
|
||||
}
|
||||
tenantID := pipelineTenantID(claims)
|
||||
var biz models.TenantCrmBusiness
|
||||
if err := models.Orm.QueryTable(new(models.TenantCrmBusiness)).
|
||||
Filter("id", id).Filter("tenant_id", tenantID).
|
||||
Filter("delete_time__isnull", true).One(&biz); err != nil {
|
||||
pipelineErr(&c.Controller, 404, 404, "商机未找到")
|
||||
return
|
||||
}
|
||||
// 数据范围校验:非管理员仅能操作本人(负责人或创建人)的数据
|
||||
if !canAccessCrmRecord(claims, biz.OwnerUserID, biz.CreateUserID) {
|
||||
pipelineErr(&c.Controller, 403, 403, "无权操作该商机数据")
|
||||
return
|
||||
}
|
||||
if biz.Locked == 1 || biz.Status == 2 {
|
||||
pipelineErr(&c.Controller, 400, 400, "商机已转化并锁定,不能流转状态")
|
||||
return
|
||||
}
|
||||
// 状态未变化:直接幂等返回,不写日志
|
||||
if biz.Status == p.Status {
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": biz.ID, "status": biz.Status})
|
||||
return
|
||||
}
|
||||
if _, err := models.Orm.QueryTable(new(models.TenantCrmBusiness)).
|
||||
Filter("id", id).Filter("tenant_id", tenantID).
|
||||
Update(map[string]interface{}{"status": p.Status, "update_time": time.Now()}); err != nil {
|
||||
pipelineErr(&c.Controller, 500, 500, "状态更新失败: "+err.Error())
|
||||
return
|
||||
}
|
||||
crmWriteLog(tenantID, 2, biz.ID, "status",
|
||||
fmt.Sprintf("商机状态:%s → %s", businessStatusName(biz.Status), businessStatusName(p.Status)), claims)
|
||||
pipelineOk(&c.Controller, map[string]interface{}{"id": biz.ID, "status": p.Status})
|
||||
}
|
||||
|
||||
// businessStatusName 商机状态文案(用于操作日志):1跟进中 / 2已转化项目 / 3已废弃
|
||||
func businessStatusName(s int8) string {
|
||||
switch s {
|
||||
case 2:
|
||||
return "已转化项目"
|
||||
case 3:
|
||||
return "已废弃"
|
||||
default:
|
||||
return "跟进中"
|
||||
}
|
||||
}
|
||||
|
||||
// businessStageName 商机阶段文案(用于操作日志):1初步接洽 … 5赢单 / 6输单
|
||||
func businessStageName(s string) string {
|
||||
switch strings.TrimSpace(s) {
|
||||
@@ -480,6 +556,10 @@ func (c *BackendCrmBusinessController) Convert() {
|
||||
pipelineErr(&c.Controller, 400, 400, "商机已转化,不能重复转化")
|
||||
return
|
||||
}
|
||||
if biz.Status == 3 {
|
||||
pipelineErr(&c.Controller, 400, 400, "商机已废弃,请先恢复为「跟进中」再转项目")
|
||||
return
|
||||
}
|
||||
|
||||
projectName := strings.TrimSpace(p.ProjectName)
|
||||
if projectName == "" {
|
||||
|
||||
@@ -475,6 +475,10 @@ func (c *BackendCrmClueController) Convert() {
|
||||
pipelineErr(&c.Controller, 400, 400, "线索已转化,不能重复转化")
|
||||
return
|
||||
}
|
||||
if clue.Status == 3 {
|
||||
pipelineErr(&c.Controller, 400, 400, "线索已废弃,请先恢复为「跟进中」再转化商机")
|
||||
return
|
||||
}
|
||||
|
||||
// 1. 处理客户:新建正式客户 或 关联已有客户
|
||||
customerName := strings.TrimSpace(p.Customer.CustomerName)
|
||||
|
||||
@@ -57,12 +57,15 @@ func isTenantAdmin(userID int, tenantID int) bool {
|
||||
if tu.GroupID == 0 {
|
||||
return true
|
||||
}
|
||||
// 「租户管理员」「租户用户」是 cid=2 且 tenant_id=0 的全局预置角色,
|
||||
// 只有租户自建角色才带自己的 tenant_id,因此两种归属都要接受,
|
||||
// 否则全局角色会因 tenant_id 不匹配而永远查不到角色。
|
||||
cond := orm.NewCondition().
|
||||
And("id", tu.GroupID).
|
||||
And("cid", 2).
|
||||
AndCond(orm.NewCondition().Or("tenant_id", 0).Or("tenant_id", tenantID))
|
||||
var role models.AdminRole
|
||||
if err := models.Orm.QueryTable(new(models.AdminRole)).
|
||||
Filter("id", tu.GroupID).
|
||||
Filter("cid", 2).
|
||||
Filter("tenant_id", tenantID).
|
||||
One(&role); err != nil {
|
||||
if err := models.Orm.QueryTable(new(models.AdminRole)).SetCond(cond).One(&role); err != nil {
|
||||
return false
|
||||
}
|
||||
if role.Name == "租户管理员" {
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"server/pkg/identity"
|
||||
"server/pkg/jwtutil"
|
||||
"server/services/dailyreport"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// BackendOaDailyReportController OA工作日报(后台 PC 端)。
|
||||
//
|
||||
// 可见范围由 services/dailyreport 统一判定:
|
||||
// - 本人:自己的全部日报(含草稿),补写窗口内可编辑/删除;
|
||||
// - 部门主管:本人作为负责人的部门及其下级部门成员「已提交」的日报;
|
||||
// - 租户管理员:全租户日报,可删除任意日报与评论。
|
||||
type BackendOaDailyReportController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (c *BackendOaDailyReportController) odrClaims() (*jwtutil.Claims, error) {
|
||||
return identity.Claims(c.Ctx.Request.Header.Get("Authorization"), identity.EndBackend)
|
||||
}
|
||||
|
||||
func (c *BackendOaDailyReportController) odrErr(status, bizCode int, msg string) {
|
||||
c.Ctx.Output.SetStatus(status)
|
||||
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *BackendOaDailyReportController) odrOk(data interface{}) {
|
||||
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": data}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *BackendOaDailyReportController) odrFail(err error) {
|
||||
code := dailyreport.StatusOf(err, 500)
|
||||
msg := err.Error()
|
||||
if code == 500 {
|
||||
msg = "操作失败,请稍后重试"
|
||||
}
|
||||
c.odrErr(code, code, msg)
|
||||
}
|
||||
|
||||
// odrCtx 解析令牌并组装日报身份;失败时已输出响应。
|
||||
func (c *BackendOaDailyReportController) odrCtx() (*dailyreport.UserContext, bool) {
|
||||
claims, err := c.odrClaims()
|
||||
if err != nil {
|
||||
code := identity.Status(err)
|
||||
c.odrErr(code, code, err.Error())
|
||||
return nil, false
|
||||
}
|
||||
u, err := dailyreport.BuildContext(
|
||||
uint64(claims.TenantId), uint64(claims.UserID), claims.Username, claims.UserType == "platform")
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return nil, false
|
||||
}
|
||||
return u, true
|
||||
}
|
||||
|
||||
func (c *BackendOaDailyReportController) odrIDParam(name string) uint64 {
|
||||
id, _ := strconv.ParseUint(c.Ctx.Input.Param(name), 10, 64)
|
||||
if id == 0 {
|
||||
c.odrErr(400, 400, "无效ID")
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// Profile GET /backend/oa/dailyreport/profile
|
||||
// 返回当前用户身份、补写窗口与团队可见性,供页面决定是否显示「团队日报」Tab。
|
||||
func (c *BackendOaDailyReportController) Profile() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
teamOrgs := u.TeamOrgIDs
|
||||
if teamOrgs == nil {
|
||||
teamOrgs = []uint64{}
|
||||
}
|
||||
c.odrOk(map[string]interface{}{
|
||||
"user_id": u.UID,
|
||||
"user_name": u.Name,
|
||||
"org_id": u.OrgID,
|
||||
"org_name": u.OrgName,
|
||||
"is_admin": u.IsAdmin,
|
||||
"can_view_team": u.CanViewTeam,
|
||||
"team_org_ids": teamOrgs,
|
||||
"window_start": dailyreport.WindowStart(),
|
||||
"window_end": dailyreport.Today(),
|
||||
"backfill_days": dailyreport.BackfillDays,
|
||||
})
|
||||
}
|
||||
|
||||
// MineList GET /backend/oa/dailyreport/mine/list
|
||||
// 我的日报分页列表,支持 start_date/end_date 筛选。
|
||||
func (c *BackendOaDailyReportController) MineList() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 20)
|
||||
res, err := dailyreport.ListMine(u, dailyreport.MineQuery{
|
||||
StartDate: strings.TrimSpace(c.GetString("start_date")),
|
||||
EndDate: strings.TrimSpace(c.GetString("end_date")),
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(res)
|
||||
}
|
||||
|
||||
// Save POST /backend/oa/dailyreport/save
|
||||
// 新建或更新日报;submit=true 提交,false 存草稿。
|
||||
func (c *BackendOaDailyReportController) Save() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var in dailyreport.SaveInput
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil || json.Unmarshal(raw, &in) != nil {
|
||||
c.odrErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
item, err := dailyreport.Save(u, in)
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(item)
|
||||
}
|
||||
|
||||
// Detail GET /backend/oa/dailyreport/detail/:id
|
||||
func (c *BackendOaDailyReportController) Detail() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id := c.odrIDParam(":id")
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
detail, err := dailyreport.GetDetail(u, id)
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(detail)
|
||||
}
|
||||
|
||||
// Delete DELETE /backend/oa/dailyreport/delete/:id
|
||||
func (c *BackendOaDailyReportController) Delete() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id := c.odrIDParam(":id")
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
if err := dailyreport.Delete(u, id); err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(map[string]interface{}{"id": id})
|
||||
}
|
||||
|
||||
// TeamStatus GET /backend/oa/dailyreport/team/status
|
||||
// 团队日报汇总:date/org_id/keyword/page/pageSize。
|
||||
func (c *BackendOaDailyReportController) TeamStatus() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
page, _ := c.GetInt("page", 1)
|
||||
pageSize, _ := c.GetInt("pageSize", 20)
|
||||
orgID, _ := c.GetInt64("org_id", 0)
|
||||
res, err := dailyreport.TeamStatus(u, dailyreport.TeamQuery{
|
||||
Date: strings.TrimSpace(c.GetString("date")),
|
||||
OrgID: uint64(orgID),
|
||||
Keyword: strings.TrimSpace(c.GetString("keyword")),
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
})
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(res)
|
||||
}
|
||||
|
||||
// TeamOrgs GET /backend/oa/dailyreport/team/orgs
|
||||
func (c *BackendOaDailyReportController) TeamOrgs() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
orgs, err := dailyreport.TeamOrgs(u)
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(map[string]interface{}{"list": orgs})
|
||||
}
|
||||
|
||||
type oaDailyReportCommentPayload struct {
|
||||
ReportID uint64 `json:"report_id"`
|
||||
Content string `json:"content"`
|
||||
ReplyToID uint64 `json:"reply_to_id"`
|
||||
}
|
||||
|
||||
// Comment POST /backend/oa/dailyreport/comment
|
||||
func (c *BackendOaDailyReportController) Comment() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var payload oaDailyReportCommentPayload
|
||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil || json.Unmarshal(raw, &payload) != nil {
|
||||
c.odrErr(400, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
if payload.ReportID == 0 {
|
||||
c.odrErr(400, 400, "缺少日报ID")
|
||||
return
|
||||
}
|
||||
comment, err := dailyreport.AddComment(u, payload.ReportID, payload.Content, payload.ReplyToID)
|
||||
if err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(comment)
|
||||
}
|
||||
|
||||
// DeleteComment DELETE /backend/oa/dailyreport/comment/:id
|
||||
func (c *BackendOaDailyReportController) DeleteComment() {
|
||||
u, ok := c.odrCtx()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
id := c.odrIDParam(":id")
|
||||
if id == 0 {
|
||||
return
|
||||
}
|
||||
if err := dailyreport.DeleteComment(u, id); err != nil {
|
||||
c.odrFail(err)
|
||||
return
|
||||
}
|
||||
c.odrOk(map[string]interface{}{"id": id})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"server/services/wechatmini"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// =============================================================
|
||||
// 官网前台只读接口:小程序公开信息
|
||||
//
|
||||
// 供 website SPA / H5 / 其他端调取平台端「小程序配置」里维护的
|
||||
// 小程序名称、AppID 与二维码图片地址,无需登录。
|
||||
// GET /site/miniapp 已启用小程序列表(含 qrcode_url)
|
||||
//
|
||||
// 说明:qrcode_url 形如 /uploads/xxx(本地存储)或 CDN 绝对地址,
|
||||
// 相对地址由前端拼接接口域名。
|
||||
// =============================================================
|
||||
|
||||
// IndexMiniAppController 小程序公开信息
|
||||
type IndexMiniAppController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// List GET /site/miniapp 已启用小程序列表(含二维码图片地址)
|
||||
func (c *IndexMiniAppController) List() {
|
||||
list, err := wechatmini.ListEnabledApps()
|
||||
if err != nil {
|
||||
c.Ctx.Output.SetStatus(500)
|
||||
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取小程序列表失败"}
|
||||
_ = c.ServeJSON()
|
||||
return
|
||||
}
|
||||
c.Data["json"] = map[string]interface{}{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": map[string]interface{}{"list": list},
|
||||
}
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
@@ -155,6 +155,7 @@ func (c *PlatformWechatMiniController) SaveApp() {
|
||||
Name string `json:"name"`
|
||||
AppID string `json:"app_id"`
|
||||
AppSecret string `json:"app_secret"`
|
||||
QrcodeURL string `json:"qrcode_url"`
|
||||
Enabled int `json:"enabled"`
|
||||
AutoBind int `json:"auto_bind"`
|
||||
Remark string `json:"remark"`
|
||||
@@ -177,6 +178,7 @@ func (c *PlatformWechatMiniController) SaveApp() {
|
||||
Name: p.Name,
|
||||
AppID: p.AppID,
|
||||
AppSecret: p.AppSecret,
|
||||
QrcodeURL: p.QrcodeURL,
|
||||
Enabled: p.Enabled == 1,
|
||||
AutoBind: p.AutoBind == 1,
|
||||
Remark: p.Remark,
|
||||
|
||||
Reference in new issue
Block a user