瀏覽代碼

add:将看板的审批迁移到知识资源的审批

zqbao 3 月之前
父節點
當前提交
7ba3ec01e2

+ 505 - 0
controllers/knowledge_approve/knowledge_approve.go

@@ -0,0 +1,505 @@
+package knowledge_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/controllers"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/knowledge_approve/request"
+	"eta_gn/eta_api/models/knowledge_approve/response"
+	"eta_gn/eta_api/services/knowledge_approve"
+	"eta_gn/eta_api/utils"
+	"fmt"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type KnowledgeApproveController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 审批列表
+// @Description 审批列表
+// @Param   PageSize			query	int		true	"每页数据条数"
+// @Param   CurrentIndex		query	int		true	"当前页页码"
+// @Param   ListType			query   int     true	"列表类型:1-待处理;2-已处理;3-我发起的"
+// @Param   ClassifyId			query	int		false	"分类ID"
+// @Param   Keyword				query	string	false	"搜索关键词"
+// @Param   ApproveState		query	int		false	"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"
+// @Param   TimeType			query	int		false	"时间类型:1-提交时间;2-处理时间;3-审批时间"
+// @Param   StartTime			query	string	false	"开始时间"
+// @Param   EndTime				query	string	false	"结束时间"
+// @Param   SortField			query	int		false	"排序字段:1-提交时间;2-处理时间;3-审批时间"
+// @Param   SortRule			query	int		false	"排序方式: 1-正序; 2-倒序(默认)"
+// @Success 200 {object} report_approve.KnowledgeApproveListResp
+// @router /list [get]
+func (this *KnowledgeApproveController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	listType, _ := this.GetInt("ListType")
+	approveState, _ := this.GetInt("ApproveState")
+	timeType, _ := this.GetInt("TimeType")
+	startTime := this.GetString("StartTime")
+	endTime := this.GetString("EndTime")
+	sortField, _ := this.GetInt("SortField")
+	sortRule, _ := this.GetInt("SortRule")
+	classifyId, _ := this.GetInt("ClassifyId")
+	keyword := this.GetString("Keyword")
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize10
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize := paging.StartIndex(currentIndex, pageSize)
+
+	var list []*response.KnowledgeApproveItemOrmResp
+	var total int
+	var msg string
+	var err error
+
+	classifyList, msg, err := knowledge_approve.GetKnowledgeClassifyAll()
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批列表成功"
+		}
+		br.ErrMsg = "获取分类列表失败, Err: " + err.Error()
+		return
+	}
+	classifyMap := make(map[int]string)
+	for _, v := range classifyList {
+		classifyMap[v.BiDashboardClassifyId] = v.BiDashboardClassifyName
+	}
+
+	switch listType {
+	case 1:
+		list, total, msg, err = knowledge_approve.ProcessingKnowledgeApprove(sysUser.AdminId, classifyId, timeType, sortField, sortRule, startSize, pageSize, sysUser.RealName, startTime, endTime, keyword)
+	case 2:
+		list, total, msg, err = knowledge_approve.SolvedKnowledgeApprove(sysUser.AdminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize, sysUser.RealName, startTime, endTime, keyword)
+	case 3:
+		list, total, msg, err = knowledge_approve.MyApplyKnowledgeApproves(sysUser.AdminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize, sysUser.RealName, startTime, endTime, keyword)
+	default:
+		br.Msg = "列表类型错误"
+		return
+	}
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批列表失败"
+		}
+		br.ErrMsg = "获取审批列表失败, Err: " + err.Error()
+		return
+	}
+	for _, v := range list {
+		v.ClassifyName = classifyMap[v.ClassifyId]
+	}
+
+	resp := new(response.KnowledgeApproveListResp)
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.List = list
+	resp.Paging = page
+
+	br.Msg = "获取审批列表成功"
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+}
+
+// list
+// @Title 公共看板分类列表
+// @Description 公共看板分类列表
+// @Success 200 {object} report_approve.BiApproveFlowDetailItem
+// @router /classify/list [get]
+func (this *KnowledgeApproveController) ClassifyList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	res, msg, err := knowledge_approve.GetPulicKnowledgeClassifyList()
+	if err != nil {
+		if msg == "" {
+			br.Msg = "获取分类列表失败"
+		} else {
+			br.Msg = msg
+		}
+		br.ErrMsg = err.Error()
+		return
+	}
+
+	br.Data = res
+	br.Msg = "获取分类列表成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Approve
+// @Title 通过审批
+// @Description 通过审批
+// @Param	request	body request.KnowledgeApprovePassReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /approve [post]
+func (this *KnowledgeApproveController) Approve() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.KnowledgeApprovePassReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.KnowledgeApproveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, KnowledgeApproveId: %d", req.KnowledgeApproveId)
+		return
+	}
+
+	// 通过审批
+	msg, err := knowledge_approve.PassKnowledgeApprove(req.KnowledgeApproveId, sysUser.AdminId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "通过审批失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Detail
+// @Title 审批详情
+// @Description 审批详情
+// @Param   KnowledgeApproveId  query  int  true  "审批ID"
+// @Success 200 {object} report_approve.KnowledgeApproveDetail
+// @router /detail [get]
+func (this *KnowledgeApproveController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	approveId, _ := this.GetInt("KnowledgeApproveId")
+	if approveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, KnowledgeApproveId: %d", approveId)
+		return
+	}
+
+	resp, msg, err := knowledge_approve.GetApproveDetail(approveId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批详情失败"
+		}
+		br.ErrMsg = "获取审批详情失败, Err: " + err.Error()
+		return
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Refuse
+// @Title 驳回审批
+// @Description 驳回审批
+// @Param	request	body request.KnowledgeApproveRefuseReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /refuse [post]
+func (this *KnowledgeApproveController) Refuse() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.KnowledgeApproveRefuseReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.KnowledgeApproveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, KnowledgeApproveId: %d", req.KnowledgeApproveId)
+		return
+	}
+	maxStrLen := 500
+	approvelen := len([]rune(req.ApproveRemark))
+	if approvelen > maxStrLen {
+		br.Msg = fmt.Sprintf("审批驳回原因不能超过%d字", maxStrLen)
+		return
+	}
+	msg, err := knowledge_approve.KnowledgeApproveRefuse(req.KnowledgeApproveId, sysUser.AdminId, req.ApproveRemark)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "驳回审批失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Cancel
+// @Title 撤销审批
+// @Description 撤销审批
+// @Param	request	body report_approve.KnowledgeApproveCancelReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /cancel [post]
+func (this *KnowledgeApproveController) Cancel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.KnowledgeApproveCancelReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.KnowledgeApproveId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, KnowledgeApproveId: %d", req.KnowledgeApproveId)
+		return
+	}
+
+	// 撤销审批
+	msg, e := knowledge_approve.KnowledgeApproveCancel(req.KnowledgeApproveId, sysUser.AdminId, sysUser.RealName)
+	if e != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "撤销审批失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// MessageList
+// @Title 审批消息列表
+// @Description 审批消息列表
+// @Param   PageSize			query	int		true	"每页数据条数"
+// @Param   CurrentIndex		query	int		true	"当前页页码"
+// @Success 200 {object} report_approve.KnowledgeApproveMessageListResp
+// @router /message/list [get]
+func (this *KnowledgeApproveController) MessageList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	currentIndex, _ := this.GetInt("currentIndex")
+	pageSize, _ := this.GetInt("pageSize")
+	// 分页
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	resp := new(response.KnowledgeApproveMessageListResp)
+	resp.List = make([]*response.KnowledgeApproveMessageItem, 0)
+	list, total, unRead, msg, err := knowledge_approve.GetKnowledgeApproveMessage(sysUser.AdminId, startSize, pageSize)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批消息失败"
+		}
+		br.ErrMsg = "获取审批消息失败, Err: " + err.Error()
+		return
+	}
+	resp.List = list
+	resp.UnreadTotal = unRead
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// MessageRead
+// @Title 消息已读
+// @Description 消息已读
+// @Param	request	body report_approve.KnowledgeApproveMessageReadReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /message/read [post]
+func (this *KnowledgeApproveController) MessageRead() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.KnowledgeApproveMessageReadReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+	if req.MessageId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = fmt.Sprintf("参数有误, MessageId: %d", req.MessageId)
+		return
+	}
+
+	msg, err := knowledge_approve.ReadKnowledgeMessage(req.MessageId, sysUser.AdminId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "操作失败"
+		}
+		br.ErrMsg = "消息已读失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// CheckApproveOpen
+// @Title 校验分类是否开启审批
+// @Description 校验分类是否开启审批
+// @Param	request	body report_approve.KnowledgeApproveCheckApproveOpenReq true "type json string"
+// @Success 200 string "操作成功"
+// @router /classify/check_open [post]
+func (this *KnowledgeApproveController) CheckApproveOpen() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req request.KnowledgeApproveCheckApproveOpenReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数解析失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验是否开启了审批流
+	opening, e := knowledge_approve.CheckKnowledgeOpenApprove(req.ClassifyId)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "校验报告是否开启审批流失败, Err: " + e.Error()
+		return
+	}
+
+	br.Data = opening
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 305 - 0
controllers/knowledge_approve/knowledge_approve_flow.go

@@ -0,0 +1,305 @@
+package knowledge_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/controllers"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/knowledge_approve/request"
+	"eta_gn/eta_api/models/knowledge_approve/response"
+	"eta_gn/eta_api/services/knowledge_approve"
+	"eta_gn/eta_api/utils"
+	"strings"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type KnowledgeApproveFlowController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 审批流列表
+// @Description 审批流列表
+// @Param   PageSize			query	int		true	"每页数据条数"
+// @Param   CurrentIndex		query	int		true	"当前页页码"
+// @Param   ClassifyId		query	int		false	"分类ID"
+// @Param   Keyword				query	string	false	"搜索关键词"
+// @Param   SortRule			query	int		false	"排序方式: 1-正序; 2-倒序(默认)"
+// @Success 200 {object} report_approve.ReportApproveListResp
+// @router /flow/list [get]
+func (c *KnowledgeApproveFlowController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	pageSize, _ := c.GetInt("PageSize")
+	currentIndex, _ := c.GetInt("CurrentIndex")
+	keyword := c.GetString("Keyword")
+	classifyId, _ := c.GetInt("ClassifyId", 0)
+	sortRule, _ := c.GetInt("SortRule", 2)
+	if pageSize <= 0 {
+		pageSize = utils.PageSize10
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	var condition string
+	var pars []interface{}
+	if keyword != "" {
+		condition = ` AND flow_name LIKE ?`
+		pars = utils.GetLikeKeywordPars(pars, keyword, 1)
+	}
+	if classifyId > 0 {
+		condition += ` AND classify_id = ?`
+		pars = append(pars, classifyId)
+	}
+	startSize := paging.StartIndex(currentIndex, pageSize)
+	orderMap := map[int]string{1: "ASC", 2: "DESC"}
+	if sortRule == 0 {
+		sortRule = 2
+	}
+	condition += " ORDER BY create_time " + orderMap[sortRule]
+
+	res, total, msg, err := knowledge_approve.GetKnowledgeApproveFlowList(condition, pars, startSize, pageSize)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批流列表失败"
+		}
+		br.ErrMsg = "获取审批流列表失败, err:" + err.Error()
+		return
+	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(response.KnowledgeApproveFlowListResp)
+	resp.List = res
+	resp.Paging = page
+
+	br.Data = resp
+	br.Msg = "获取审批流列表成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// Add
+// @Title 新增审批流
+// @Description 新增审批流
+// @Param	request	body request.KnowledgeApproveFlowSaveReq true "type json string"
+// @Success 200
+// @router /flow/add [post]
+func (c *KnowledgeApproveFlowController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req *request.KnowledgeApproveFlowSaveReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = "参数解析失败, err:" + err.Error()
+		return
+	}
+	req.FlowName = strings.TrimSpace(req.FlowName)
+	if req.FlowName == "" {
+		br.Msg = "审批流名称不能为空"
+		return
+	}
+
+	if len([]rune(req.FlowName)) > 20 {
+		br.Msg = "审批流名称最多输入20个字符"
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择审批分类"
+		return
+	}
+	if len(req.Nodes) == 0 {
+		br.Msg = "请添加审批流程"
+		return
+	}
+
+	if req.KnowledgeApproveFlowId > 0 {
+		br.Msg = "审批流已存在"
+		return
+	}
+
+	_, msg, err := knowledge_approve.SaveKnowledgeApproveFlow(req)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "新增审批流失败"
+		}
+		br.ErrMsg = "新增审批流失败, err:" + err.Error()
+		return
+	}
+
+	br.Msg = "新增审批流成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// edit
+// @Title 新增审批流
+// @Description 新增审批流
+// @Param	request	body request.KnowledgeApproveFlowSaveReq true "type json string"
+// @Success 200 {object} report_approve.ReportApproveFlowDetailItem
+// @router /flow/edit [post]
+func (c *KnowledgeApproveFlowController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req *request.KnowledgeApproveFlowSaveReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = "参数解析失败, err:" + err.Error()
+		return
+	}
+	req.FlowName = strings.TrimSpace(req.FlowName)
+	if req.FlowName == "" {
+		br.Msg = "审批流名称不能为空"
+		return
+	}
+
+	if len([]rune(req.FlowName)) > 20 {
+		br.Msg = "审批流名称最多输入20个字符"
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "请选择审批分类"
+		return
+	}
+	if len(req.Nodes) == 0 {
+		br.Msg = "请添加审批流程"
+		return
+	}
+
+	if req.KnowledgeApproveFlowId == 0 {
+		br.Msg = "审批流不存在, 请刷新重试"
+		return
+	}
+
+	ok, msg, err := knowledge_approve.SaveKnowledgeApproveFlow(req)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "编辑审批流失败"
+		}
+		br.ErrMsg = "编辑审批流失败, err:" + err.Error()
+		return
+	}
+	if !ok {
+		br.Msg = msg
+		return
+	}
+
+	br.Msg = "编辑审批流成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// delete
+// @Title 新增审批流
+// @Description 新增审批流
+// @Param	request	body request.KnowledgeApproveFlowRemoveReq true "type json string"
+// @Success 200 {object} report_approve.ReportApproveFlowDetailItem
+// @router /flow/remove [post]
+func (c *KnowledgeApproveFlowController) Remove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	var req *request.KnowledgeApproveFlowRemoveReq
+	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = "参数解析失败, err:" + err.Error()
+		return
+	}
+	if req.KnowledgeApproveFlowId <= 0 {
+		br.Msg = "审批流不存在, 请刷新重试"
+		return
+	}
+	ok, msg, err := knowledge_approve.DeleteKnowledgeApproveFlow(req.KnowledgeApproveFlowId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "删除审批流失败"
+		}
+		br.ErrMsg = "删除审批流失败, err:" + err.Error()
+		return
+	}
+	if !ok {
+		br.Msg = msg
+		return
+	}
+
+	br.Msg = "删除审批流成功"
+	br.Success = true
+	br.Ret = 200
+}
+
+// Detail
+// @Title 审批流详情
+// @Description 审批流详情
+// @Param	KnowledgeApproveFlowId   query	int   true "看板审批流ID"
+// @Success 200 {object} report_approve.ReportApproveFlowDetailItem
+// @router /flow/detail [get]
+func (c *KnowledgeApproveFlowController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		c.Data["json"] = br
+		c.ServeJSON()
+	}()
+	sysUser := c.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	flowId, _ := c.GetInt("KnowledgeApproveFlowId")
+	if flowId <= 0 {
+		br.Msg = "审批流不存在"
+		return
+	}
+	detail, msg, err := knowledge_approve.GetKnowledgeApproveFlowDetail(flowId)
+	if err != nil {
+		if msg != "" {
+			br.Msg = msg
+		} else {
+			br.Msg = "获取审批流详情失败"
+		}
+		br.ErrMsg = "获取审批流详情失败, err:" + err.Error()
+		return
+	}
+	if detail == nil {
+		br.Msg = "审批流不存在"
+		return
+	}
+
+	br.Data = detail
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取审批流详情成功"
+}

+ 197 - 0
models/knowledge_approve/knowledge_approve.go

@@ -0,0 +1,197 @@
+package knowledge_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"fmt"
+	"time"
+)
+
+type KnowledgeApprove struct {
+	KnowledgeApproveId int       `gorm:"column:knowledge_approve_id;primary_key"`
+	KnowledgeId        int       `gorm:"column:knowledge_id"`
+	KnowledgeTitle     string    `gorm:"column:knowledge_title"`
+	ClassifyId         int       `gorm:"column:classify_id"`
+	State              int       `gorm:"column:state"` //  '审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回'
+	FlowId             int       `gorm:"column:flow_id"`
+	FlowVersion        int       `gorm:"column:flow_version"`
+	StartNodeId        int       `gorm:"column:start_node_id"`
+	CurrNodeId         int       `gorm:"column:curr_node_id"`
+	ApplyUserId        int       `gorm:"column:apply_user_id"`
+	ApplyUserName      string    `gorm:"column:apply_user_name"`
+	ApproveRemark      string    `gorm:"column:approve_remark"`
+	ApproveTime        time.Time `gorm:"column:approve_time"`
+	CreateTime         time.Time `gorm:"column:create_time"`
+	ModifyTime         time.Time `gorm:"column:update_time"`
+}
+
+var KnowledgeApproveCols = struct {
+	KnowledgeApproveId string
+	KnowledgeId        string
+	KnowledgeTitle     string
+	ClassifyId         string
+	State              string //  '审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回'
+	FlowId             string
+	FlowVersion        string
+	StartNodeId        string
+	CurrNodeId         string
+	ApplyUserId        string
+	ApplyUserName      string
+	ApproveRemark      string
+	ApproveTime        string
+	CreateTime         string
+	ModifyTime         string
+}{
+	KnowledgeApproveId: "knowledge_approve_id",
+	KnowledgeId:        "knowledge_id",
+	KnowledgeTitle:     "knowledge_title",
+	ClassifyId:         "classify_id",
+	State:              "state",
+	FlowId:             "flow_id",
+	FlowVersion:        "flow_version",
+	StartNodeId:        "start_node_id",
+	CurrNodeId:         "curr_node_id",
+	ApplyUserId:        "apply_user_id",
+	ApplyUserName:      "apply_user_name",
+	ApproveRemark:      "approve_remark",
+	ApproveTime:        "approve_time",
+	CreateTime:         "create_time",
+	ModifyTime:         "modify_time",
+}
+
+type KnowledgeApproveItemOrm struct {
+	KnowledgeApproveId       int       `description:"审批ID"`
+	KnowledgeApproveRecordId int       `description:"审批记录ID"`
+	KnowledgeId              int       `description:"报告ID"`
+	KnowledgeTitle           string    `description:"报告标题"`
+	ClassifyId               int       `description:"分类ID"`
+	State                    int       `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	RecordState              int       `description:"审批记录状态:1-待审批;2-已通过;3-已驳回"`
+	FlowId                   int       `description:"审批流ID"`
+	FlowVersion              int       `description:"审批流版本"`
+	StartNodeId              int       `description:"开始节点ID"`
+	CurrNodeId               int       `description:"当前节点ID"`
+	ApplyUserId              int       `description:"申请人ID"`
+	ApplyUserName            string    `description:"申请人姓名"`
+	ApproveRemark            string    `description:"审批备注"`
+	ApproveTime              time.Time `description:"审批时间"`
+	HandleTime               time.Time `description:"处理时间"`
+	CreateTime               time.Time `description:"创建时间"`
+	ModifyTime               time.Time `description:"修改时间"`
+	NodeState                int       `description:"当前节点审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回" json:"-"`
+	NodeApproveTime          time.Time `description:"当前节点审批时间" json:"-"`
+}
+
+func (b *KnowledgeApprove) TableName() string {
+	return "knowledge_approve"
+}
+
+func (b *KnowledgeApprove) Update(cols []string) (err error) {
+	db := global.DmSQL["rddp"]
+	err = db.Model(b).Select(cols).Updates(b).Error
+	return
+}
+
+func (b *KnowledgeApprove) Create() (err error) {
+	db := global.DmSQL["rddp"]
+	err = db.Create(b).Error
+	return
+}
+
+func GetKnowledgeApproveByFlowIdAndVersionId(knowledgeFlowId int, flowVersion int) (item []*KnowledgeApprove, err error) {
+	db := global.DmSQL["rddp"]
+	err = db.Where("flow_id = ? AND flow_version = ?", knowledgeFlowId, flowVersion).Find(&item).Error
+	return
+}
+
+func GetKnowledgeApproveById(knowledgeApproveId int) (item *KnowledgeApprove, err error) {
+	db := global.DmSQL["rddp"]
+	err = db.Where("knowledge_approve_id = ?", knowledgeApproveId).First(&item).Error
+	return
+}
+
+// GetApprovingKnowledgeApproveCount 获取待处理的审批分页列表总数
+func GetApprovingKnowledgeApproveCount(cond string, pars []interface{}) (count int, err error) {
+	base := fmt.Sprintf(`SELECT a.knowledge_approve_record_id
+		FROM knowledge_approve_record AS a
+		JOIN knowledge_approve AS b ON a.knowledge_approve_id = b.knowledge_approve_id AND a.node_id = b.curr_node_id
+		WHERE 1 = 1 %s`, cond)
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM (%s) t`, base)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+// GetApprovingKnowledgeApprovePageList 获取待处理的审批列表-分页
+func GetApprovingKnowledgeApprovePageList(cond string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*KnowledgeApproveItemOrm, err error) {
+	order := `ORDER BY a.create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT a.knowledge_approve_record_id, a.state AS record_state, b.*
+		FROM knowledge_approve_record AS a
+		JOIN knowledge_approve AS b ON a.knowledge_approve_id = b.knowledge_approve_id AND a.node_id = b.curr_node_id
+		WHERE 1 = 1 %s %s
+		LIMIT ?,?`, cond, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+// GetApprovedKnowledgeApproveCount 获取已处理的审批分页列表总数
+func GetApprovedKnowledgeApproveCount(cond string, pars []interface{}) (count int, err error) {
+	base := fmt.Sprintf(`SELECT a.knowledge_approve_record_id
+		FROM knowledge_approve_record AS a
+		JOIN knowledge_approve AS b ON a.knowledge_approve_id = b.knowledge_approve_id
+		WHERE 1 = 1 %s`, cond)
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM (%s) t`, base)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+// GetApprovedKnowledgeApprovePageList 获取已处理的审批列表-分页
+func GetApprovedKnowledgeApprovePageList(cond string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*KnowledgeApproveItemOrm, err error) {
+	order := `ORDER BY a.create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT a.knowledge_approve_record_id, a.node_state AS record_state,a.node_state,a.node_approve_time, a.node_approve_time AS handle_time, b.*
+		FROM knowledge_approve_record AS a
+		JOIN knowledge_approve AS b ON a.knowledge_approve_id = b.knowledge_approve_id
+		WHERE 1 = 1 %s %s
+		LIMIT ?,?`, cond, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+// GetApplyKnowledgeApproveCount 获取我发起的审批分页列表总数
+func GetApplyKnowledgeApproveCount(cond string, pars []interface{}) (count int, err error) {
+	base := fmt.Sprintf(`SELECT a.* FROM knowledge_approve AS a WHERE 1 = 1 %s`, cond)
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM (%s) t`, base)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+// GetApplyKnowledgeApprovePageList 获取我发起的审批列表-分页
+func GetApplyKnowledgeApprovePageList(cond string, pars []interface{}, orderRule string, startSize, pageSize int) (items []*KnowledgeApproveItemOrm, err error) {
+	order := `ORDER BY a.create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT a.* FROM knowledge_approve AS a WHERE 1 = 1 %s %s LIMIT ?,?`, cond, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func GetKnowledgeApproveByBoardId(knowledgeApproveId int) (item *KnowledgeApprove, err error) {
+	db := global.DmSQL["rddp"]
+	err = db.Where("knowledge_id = ?", knowledgeApproveId).Order("create_time DESC").First(&item).Error
+	return
+}
+
+func GetKnowledgeApproveCountByState(state int) (count int, err error) {
+	db := global.DmSQL["rddp"]
+	sql := `SELECT COUNT(*) FROM knowledge_approve WHERE state = ?`
+	err = db.Raw(sql, state).Scan(&count).Error
+	return
+}

+ 185 - 0
models/knowledge_approve/knowledge_approve_flow.go

@@ -0,0 +1,185 @@
+package knowledge_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"fmt"
+	"time"
+)
+
+type KnowledgeApproveFlow struct {
+	KnowledgeApproveFlowId int       `gorm:"column:knowledge_approve_flow_id;primaryKey"`
+	FlowName               string    `gorm:"column:flow_name"`
+	ClassifyId             int       `gorm:"column:classify_id"`
+	ClassifyName           string    `gorm:"column:classify_name"`
+	CurrVersion            int       `gorm:"column:curr_version"`
+	CreateTime             time.Time `gorm:"column:create_time"`
+	ModifyTime             time.Time `gorm:"column:modify_time"`
+}
+
+var KnowledgeApproveFlowCols = struct {
+	KnowledgeApproveFlowId string
+	FlowName               string
+	ClassifyId             string
+	CurrVersion            string
+	CreateTime             string
+	ModifyTime             string
+}{
+	KnowledgeApproveFlowId: "knowledge_approve_flow_id",
+	FlowName:               "flow_name",
+	ClassifyId:             "classify_id",
+	CurrVersion:            "curr_version",
+	CreateTime:             "create_time",
+	ModifyTime:             "modify_time",
+}
+
+func (b *KnowledgeApproveFlow) TableName() string {
+	return "knowledge_approve_flow"
+}
+
+func (b *KnowledgeApproveFlow) Add(node []*KnowledgeApproveNode) (err error) {
+	prevNodes := make([]*KnowledgeApproveNode, 0)
+	o := global.DmSQL["rddp"].Begin()
+	defer func() {
+		if err != nil {
+			o.Rollback()
+		} else {
+			o.Commit()
+		}
+
+		// 更新每个节点的下一个节点信息, 放在事务中会更新失败
+		if e := UpdateNextNodes(prevNodes); e != nil {
+			err = fmt.Errorf("UpdatePrevNodes err: %s", e.Error())
+			return
+		}
+	}()
+
+	err = o.Create(b).Error
+	if err != nil {
+		err = fmt.Errorf("insert approve err: %v", err)
+		return
+	}
+
+	nodesLen := len(node)
+	if nodesLen == 0 {
+		return
+	}
+	prevId := 0
+	prevNode := new(KnowledgeApproveNode)
+	for k, v := range node {
+		v.KnowledgeApproveFlowId = b.KnowledgeApproveFlowId
+		v.PrevNodeId = prevId
+		err = o.Create(v).Error
+		if err != nil {
+			err = fmt.Errorf("insert node err: %v", err)
+			return
+		}
+		prevId = v.KnowledgeApproveNodeId
+
+		// 下一个节点
+		if prevNode != nil && k > 0 && k < nodesLen {
+			prevNode.NextNodeId = v.KnowledgeApproveNodeId
+			prevNodes = append(prevNodes, prevNode)
+		}
+		prevNode = v
+	}
+	return
+}
+
+func (b *KnowledgeApproveFlow) Update(cols []string, node []*KnowledgeApproveNode) (err error) {
+	prevNodes := make([]*KnowledgeApproveNode, 0)
+	o := global.DmSQL["rddp"].Begin()
+	defer func() {
+		if err != nil {
+			o.Rollback()
+		} else {
+			o.Commit()
+		}
+
+		// 更新每个节点的下一个节点信息, 放在事务中会更新失败
+		if e := UpdateNextNodes(prevNodes); e != nil {
+			err = fmt.Errorf("UpdatePrevNodes err: %s", e.Error())
+			return
+		}
+	}()
+	err = o.Model(b).Select(cols).Updates(b).Error
+	if err != nil {
+		return
+	}
+
+	nodesLen := len(node)
+	if nodesLen == 0 {
+		return
+	}
+	prevId := 0
+	prevNode := new(KnowledgeApproveNode)
+	for k, v := range node {
+		v.KnowledgeApproveFlowId = b.KnowledgeApproveFlowId
+		v.PrevNodeId = prevId
+		err = o.Create(v).Error
+		if err != nil {
+			err = fmt.Errorf("insert node err: %v", err)
+			return
+		}
+		prevId = v.KnowledgeApproveNodeId
+
+		// 下一个节点
+		if prevNode != nil && k > 0 && k < nodesLen {
+			prevNode.NextNodeId = v.KnowledgeApproveNodeId
+			prevNodes = append(prevNodes, prevNode)
+		}
+		prevNode = v
+	}
+	return
+}
+
+func (b *KnowledgeApproveFlow) Delete() error {
+	return global.DmSQL["rddp"].Delete(b).Error
+}
+
+func (m *KnowledgeApproveFlow) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *KnowledgeApproveFlow, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s `, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).First(&item).Error
+	return
+}
+
+func GetKnowledgeApproveFlowById(knowledgeApproveFlowId int) (item *KnowledgeApproveFlow, err error) {
+	err = global.DmSQL["rddp"].Where("knowledge_approve_flow_id = ?", knowledgeApproveFlowId).First(&item).Error
+	return
+}
+
+func GetKnowledgeApproveFlowByClassifyId(classifyId int) (item *KnowledgeApproveFlow, err error) {
+	err = global.DmSQL["rddp"].Where("classify_id = ?", classifyId).First(&item).Error
+	return
+}
+
+func GetKnowledgeApproveFlowByCondition(condition string, pars []interface{}, startSize, pageSize int) (items []*KnowledgeApproveFlow, err error) {
+	o := global.DmSQL["rddp"]
+	sql := "SELECT * FROM knowledge_approve_flow WHERE 1=1 "
+	if condition != "" {
+		sql += condition
+	}
+	sql += " LIMIT ?,?"
+	pars = append(pars, startSize, pageSize)
+	err = o.Raw(sql, pars...).Scan(&items).Error
+	return
+}
+
+func GetKnowledgeApproveFlowCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := global.DmSQL["rddp"]
+	sql := "SELECT COUNT(*) AS count FROM knowledge_approve_flow WHERE 1=1 "
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func UpdateFlowClassifyName(classifyId int, classifyName string) (err error) {
+	o := global.DmSQL["rddp"]
+	err = o.Model(&KnowledgeApproveFlow{}).Where("classify_id = ?", classifyId).Update("classify_name", classifyName).Error
+	return
+}

+ 115 - 0
models/knowledge_approve/knowledge_approve_message.go

@@ -0,0 +1,115 @@
+package knowledge_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type KnowledgeApproveMessage struct {
+	Id                 int       `gorm:"primaryKey;column:id"`
+	SendUserId         int       `gorm:"column:send_user_id"`         // 发送人Id
+	ReceiveUserId      int       `gorm:"column:receive_user_id"`      // 接收者Id
+	Content            string    `gorm:"column:content"`              // 消息内容
+	Remark             string    `gorm:"column:remark"`               // 备注信息
+	KnowledgeApproveId int       `gorm:"column:knowledge_approve_id"` // 审批Id
+	ApproveState       int       `gorm:"column:approve_state"`        // 审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回
+	IsRead             int       `gorm:"column:is_read"`              // 是否已读:0-未读;1-已读
+	CreateTime         time.Time `gorm:"column:create_time"`          // 创建时间
+	ModifyTime         time.Time `gorm:"column:modify_time"`          // 修改时间
+}
+
+var KnowledgeApproveMessageCols = struct {
+	Id                 string
+	SendUserId         string
+	ReceiveUserId      string
+	Content            string
+	Remark             string
+	KnowledgeApproveId string
+	ApproveState       string
+	IsRead             string
+	CreateTime         string
+	ModifyTime         string
+}{
+	Id:                 "id",
+	SendUserId:         "send_user_id",
+	ReceiveUserId:      "receive_user_id",
+	Content:            "content",
+	Remark:             "remark",
+	KnowledgeApproveId: "knowledge_approve_id",
+	ApproveState:       "approve_state",
+	IsRead:             "is_read",
+	CreateTime:         "create_time",
+	ModifyTime:         "modify_time",
+}
+
+func (r *KnowledgeApproveMessage) TableName() string {
+	return "knowledge_approve_message"
+}
+
+func (r *KnowledgeApproveMessage) Create() (err error) {
+	o := global.DmSQL["rddp"]
+	err = o.Create(r).Error
+	return err
+}
+
+func (m *KnowledgeApproveMessage) PrimaryId() string {
+	return KnowledgeApproveMessageCols.Id
+}
+
+func (r *KnowledgeApproveMessage) CreateMulti(items []*KnowledgeApproveMessage) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := global.DmSQL["rddp"]
+	err = o.CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (m *KnowledgeApproveMessage) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Scan(&count).Error
+	return
+}
+
+func (m *KnowledgeApproveMessage) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*KnowledgeApproveMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *KnowledgeApproveMessage) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*KnowledgeApproveMessage, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	pars = append(pars, startSize, pageSize)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *KnowledgeApproveMessage) GetItemById(id int) (item *KnowledgeApproveMessage, err error) {
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? `, m.TableName(), m.PrimaryId())
+	err = global.DmSQL["rddp"].Raw(sql, id).First(&item).Error
+	return
+}
+
+func (m *KnowledgeApproveMessage) Update(cols []string) (err error) {
+	err = global.DmSQL["rddp"].Model(m).Select(cols).Updates(m).Error
+	return
+}

+ 90 - 0
models/knowledge_approve/knowledge_approve_node.go

@@ -0,0 +1,90 @@
+package knowledge_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type KnowledgeApproveNode struct {
+	KnowledgeApproveNodeId int       `gorm:"column:knowledge_approve_node_id;primaryKey"`
+	KnowledgeApproveFlowId int       `gorm:"column:knowledge_approve_flow_id"`
+	PrevNodeId             int       `gorm:"column:prev_node_id"`
+	NextNodeId             int       `gorm:"column:next_node_id"`
+	NodeType               int       `gorm:"column:node_type"`
+	ApproveType            int       `gorm:"column:approve_type"`
+	Users                  string    `gorm:"column:users"`
+	CurrVersion            int       `gorm:"column:curr_version"`
+	CreatedTime            time.Time `gorm:"column:created_time"`
+}
+
+var KnowledgeApproveNodeCols = struct {
+	KnowledgeApproveNodeId string
+	KnowledgeApproveFlowId string
+	PrevNodeId             string
+	NextNodeId             string
+	NodeType               string
+	ApproveType            string
+	Users                  string
+	CurrVersion            string
+	CreatedTime            string
+}{
+	KnowledgeApproveNodeId: "knowledge_approve_node_id",
+	KnowledgeApproveFlowId: "knowledge_approve_flow_id",
+	PrevNodeId:             "prev_node_id",
+	NextNodeId:             "next_node_id",
+	NodeType:               "node_type",
+	ApproveType:            "approve_type",
+	Users:                  "users",
+	CurrVersion:            "curr_version",
+	CreatedTime:            "created_time",
+}
+
+func (b *KnowledgeApproveNode) TableName() string {
+	return "knowledge_approve_node"
+}
+
+func (m *KnowledgeApproveNode) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*KnowledgeApproveNode, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY created_time DESC, knowledge_approve_node_id ASC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func UpdateNextNodes(nodes []*KnowledgeApproveNode) (err error) {
+	if len(nodes) == 0 {
+		return
+	}
+	updateCols := []string{"NextNodeId"}
+	for _, v := range nodes {
+		e := global.DmSQL["rddp"].Select(updateCols).Updates(v).Error
+		if e != nil {
+			err = fmt.Errorf("prev node update err: %v", e)
+			return
+		}
+	}
+	return
+}
+
+func GetKnowledgeApproveNodeByCondition(condition string, pars []interface{}) (node []*KnowledgeApproveNode, err error) {
+	o := global.DmSQL["rddp"]
+	sql := "SELECT * FROM knowledge_approve_node WHERE 1=1 "
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).Find(&node).Error
+	return
+}
+
+func GetKnowledgeApproveNodeByFlowIdAndVersionId(flowId int, versionId int) (node []*KnowledgeApproveNode, err error) {
+	err = global.DmSQL["rddp"].Model(&KnowledgeApproveNode{}).Where("knowledge_approve_flow_id =? AND curr_version =?", flowId, versionId).Scan(&node).Error
+	return
+}

+ 152 - 0
models/knowledge_approve/knowledge_approve_record.go

@@ -0,0 +1,152 @@
+package knowledge_approve
+
+import (
+	"eta_gn/eta_api/global"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"strings"
+	"time"
+)
+
+type KnowledgeApproveRecord struct {
+	KnowledgeApproveRecordId int       `gorm:"column:knowledge_approve_record_id;primary_key"`
+	KnowledgeApproveId       int       `gorm:"column:knowledge_approve_id"`
+	State                    int       `gorm:"column:state"`
+	NodeId                   int       `gorm:"column:node_id"`
+	NodeType                 int       `gorm:"column:node_type"`
+	PrevNodeId               int       `gorm:"column:prev_node_id"`
+	NextNodeId               int       `gorm:"column:next_node_id"`
+	ApproveType              int       `gorm:"column:approve_type"`
+	ApproveUserId            int       `gorm:"column:approve_user_id"`
+	ApproveUserName          string    `gorm:"column:approve_user_name"`
+	ApproveUserSort          int       `gorm:"column:approve_user_sort"`
+	ApproveRemark            string    `gorm:"column:approve_remark"`
+	ApproveTime              time.Time `gorm:"column:approve_time"`
+	CreateTime               time.Time `gorm:"column:create_time"`
+	ModifyTime               time.Time `gorm:"column:modify_time"`
+	NodeState                int       `gorm:"column:node_state"`
+	NodeApproveUserId        int       `gorm:"column:node_approve_user_id"`
+	NodeApproveUserName      string    `gorm:"column:node_approve_user_name"`
+	NodeApproveTime          time.Time `gorm:"column:node_approve_time"`
+}
+
+var KnowledgeApproveRecordCols = struct {
+	KnowledgeApproveRecordId string
+	KnowledgeApproveId       string
+	State                    string
+	NodeId                   string
+	NodeType                 string
+	PrevNodeId               string
+	NextNodeId               string
+	ApproveType              string
+	ApproveUserId            string
+	ApproveUserName          string
+	ApproveUserSort          string
+	ApproveRemark            string
+	ApproveTime              string
+	CreateTime               string
+	ModifyTime               string
+	NodeState                string
+	NodeApproveUserId        string
+	NodeApproveUserName      string
+	NodeApproveTime          string
+}{
+	KnowledgeApproveRecordId: "knowledge_approve_record_id",
+	KnowledgeApproveId:       "knowledge_approve_id",
+	State:                    "state",
+	NodeId:                   "node_id",
+	NodeType:                 "node_type",
+	PrevNodeId:               "prev_node_id",
+	NextNodeId:               "next_node_id",
+	ApproveType:              "approve_type",
+	ApproveUserId:            "approve_user_id",
+	ApproveUserName:          "approve_user_name",
+	ApproveUserSort:          "approve_user_sort",
+	ApproveRemark:            "approve_remark",
+	ApproveTime:              "approve_time",
+	CreateTime:               "create_time",
+	ModifyTime:               "modify_time",
+	NodeState:                "node_state",
+	NodeApproveUserId:        "node_approve_user_id",
+	NodeApproveUserName:      "node_approve_user_name",
+	NodeApproveTime:          "node_approve_time",
+}
+
+func (b *KnowledgeApproveRecord) TableName() string {
+	return "knowledge_approve_record"
+}
+
+func (b *KnowledgeApproveRecord) Create() (err error) {
+	o := global.DmSQL["rddp"]
+	err = o.Create(b).Error
+	return
+}
+
+func (b *KnowledgeApproveRecord) CreateMulti(items []*KnowledgeApproveRecord) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := global.DmSQL["rddp"]
+	err = o.CreateInBatches(items, utils.MultiAddNum).Error
+	return
+}
+
+func (b *KnowledgeApproveRecord) Update(cols []string) (err error) {
+	o := global.DmSQL["rddp"]
+	err = o.Model(b).Select(cols).Updates(b).Error
+	return
+}
+
+func GetKnowledgeApproveRecordByCondition(condition string, pars []interface{}) (record *KnowledgeApproveRecord, err error) {
+	o := global.DmSQL["rddp"]
+	sql := `SELECT * FROM knowledge_approve_record WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).First(&record).Error
+	return
+}
+
+func GetKnowledgeApproveRecordItemsByCondition(condition string, pars []interface{}) (items []*KnowledgeApproveRecord, err error) {
+	order := `ORDER BY create_time DESC`
+	sql := fmt.Sprintf(`SELECT * FROM knowledge_approve_record WHERE 1=1 %s %s`, condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (b *KnowledgeApproveRecord) UpdateNodeState(knowledgeApproveId, nodeId, nodeState, nodeApproveUserId int, nodeApproveUserName string, nodeApproveTime time.Time) (err error) {
+	pars := make([]interface{}, 0)
+	pars = append(pars, nodeState, nodeApproveUserId, nodeApproveUserName, nodeApproveTime)
+
+	// 更新条件
+	whereParas := []interface{}{knowledgeApproveId, nodeId}
+	pars = append(pars, whereParas...)
+
+	sql := fmt.Sprintf(`UPDATE %s SET node_state=?,node_approve_user_id=?,node_approve_user_name=?,node_approve_time=? WHERE knowledge_approve_id = ? AND node_id = ?`, b.TableName())
+	err = global.DmSQL["rddp"].Exec(sql, pars...).Error
+	return
+}
+
+func (m *KnowledgeApproveRecord) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*KnowledgeApproveRecord, err error) {
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).Find(&items).Error
+	return
+}
+
+func (m *KnowledgeApproveRecord) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *KnowledgeApproveRecord, err error) {
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
+	err = global.DmSQL["rddp"].Raw(sql, pars...).First(&item).Error
+	return
+}

+ 21 - 0
models/knowledge_approve/request/knowledge_approve.go

@@ -0,0 +1,21 @@
+package request
+
+type KnowledgeApprovePassReq struct {
+	KnowledgeApproveId int `description:"审批ID"`
+}
+
+// KnowledgeApproveRefuseReq 审批驳回请求体
+type KnowledgeApproveRefuseReq struct {
+	KnowledgeApproveId int    `description:"审批ID"`
+	ApproveRemark      string `description:"驳回理由"`
+}
+
+// KnowledgeApproveCancelReq 撤销审批请求体
+type KnowledgeApproveCancelReq struct {
+	KnowledgeApproveId int `description:"审批ID"`
+}
+
+// KnowledgeApproveCheckApproveOpenReq 校验分类是否打开审批请求体
+type KnowledgeApproveCheckApproveOpenReq struct {
+	ClassifyId int `description:"一级分类ID"`
+}

+ 23 - 0
models/knowledge_approve/request/knowledge_approve_flow.go

@@ -0,0 +1,23 @@
+package request
+
+type KnowledgeApproveFlowSaveReq struct {
+	KnowledgeApproveFlowId int
+	ClassifyId             int
+	FlowName               string
+	Nodes                  []Node
+}
+
+type Node struct {
+	ApproveType int `description:"审批类型: 1-依次审批, 2-会签, 3-或签"`
+	Users       []User
+}
+
+type User struct {
+	UserId   int    `description:"用户ID"`
+	UserName string `description:"用户名"`
+	UserType string `description:"用户类型: user-用户 role-角色"`
+}
+
+type KnowledgeApproveFlowRemoveReq struct {
+	KnowledgeApproveFlowId int
+}

+ 5 - 0
models/knowledge_approve/request/knowledge_approve_message.go

@@ -0,0 +1,5 @@
+package request
+
+type KnowledgeApproveMessageReadReq struct {
+	MessageId int `description:"审批消息ID"`
+}

+ 90 - 0
models/knowledge_approve/response/knowledge_approve.go

@@ -0,0 +1,90 @@
+package response
+
+// KnowledgeApproveDetail 审批详情信息
+type KnowledgeApproveDetail struct {
+	Knowledge        *KnowledgeApproveDetailKnowledge `description:"报告信息"`
+	Approve          *KnowledgeApproveDetailItem      `description:"审批信息"`
+	ApproveFlowNodes []*KnowledgeApproveDetailNodes   `description:"审批节点信息"`
+}
+
+// KnowledgeApproveDetailKnowledge 审批详情-报告信息
+type KnowledgeApproveDetailKnowledge struct {
+	KnowledgeId       int    `description:"知识资源ID"`
+	KnowledgeTitle    string `description:"知识资源标题"`
+	KnowledgeCode     string `description:"知识资源code"`
+	KnowledgeClassify string `description:"知识资源分类"`
+}
+
+// KnowledgeApproveDetailItem 审批详情-审批信息
+type KnowledgeApproveDetailItem struct {
+	KnowledgeApproveId int    `description:"审批ID"`
+	State              int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	FlowId             int    `description:"审批流ID"`
+	FlowVersion        int    `description:"审批流版本"`
+	StartNodeId        int    `description:"开始节点ID"`
+	CurrNodeId         int    `description:"当前节点ID"`
+	ApplyUserId        int    `description:"申请人ID"`
+	ApplyUserName      string `description:"申请人姓名"`
+	ApproveTime        string `description:"审批时间"`
+	CreateTime         string `description:"创建时间"`
+	ModifyTime         string `description:"修改时间"`
+}
+
+// KnowledgeApproveDetailNodes 审批详情-节点信息
+type KnowledgeApproveDetailNodes struct {
+	KnowledgeApproveNodeId int                               `description:"知识资源审批节点ID"`
+	KnowledgeApproveFlowId int                               `description:"知识资源审批流ID"`
+	PrevNodeId             int                               `description:"上一个节点ID(0为开始节点)"`
+	NextNodeId             int                               `description:"下一个节点ID(0为结束节点)"`
+	NodeType               int                               `description:"节点类型:0-审批;1-抄送"`
+	ApproveType            int                               `description:"审批类型:1-依次审批;2-会签;3-或签"`
+	Users                  []*KnowledgeApproveDetailNodeUser `description:"审批人信息"`
+}
+
+// KnowledgeApproveDetailNodeUser 审批详情-节点用户信息
+type KnowledgeApproveDetailNodeUser struct {
+	KnowledgeApproveNodeUserReq
+	ApproveRecord *KnowledgeApproveDetailNodeUserRecord `description:"用户审批记录"`
+}
+
+// KnowledgeApproveNodeUserReq 报告审批节点用户请求体
+type KnowledgeApproveNodeUserReq struct {
+	UserType string `description:"审批人类型: user-用户; role-角色"`
+	UserId   int    `description:"用户/角色ID"`
+	UserName string `description:"用户/角色姓名"`
+	Sort     int    `description:"排序"`
+}
+
+// KnowledgeApproveDetailNodeUserRecord 审批详情-节点用户审批记录
+type KnowledgeApproveDetailNodeUserRecord struct {
+	KnowledgeApproveRecordId int    `description:"审批记录ID"`
+	State                    int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	ApproveUserId            int    `description:"审批人ID"`
+	ApproveUserName          string `description:"审批人姓名"`
+	ApproveRemark            string `description:"审批备注"`
+	ApproveTime              string `description:"审批时间"`
+}
+
+type KnowledgeApproveItemOrmResp struct {
+	KnowledgeApproveId       int    `description:"审批ID"`
+	KnowledgeApproveRecordId int    `description:"审批记录ID"`
+	KnowledgeId              int    `description:"报告ID"`
+	KnowledgeTitle           string `description:"报告标题"`
+	ClassifyId               int    `description:"分类ID"`
+	ClassifyName             string `description:"分类名称"`
+	State                    int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	RecordState              int    `description:"审批记录状态:1-待审批;2-已通过;3-已驳回"`
+	FlowId                   int    `description:"审批流ID"`
+	FlowVersion              int    `description:"审批流版本"`
+	StartNodeId              int    `description:"开始节点ID"`
+	CurrNodeId               int    `description:"当前节点ID"`
+	ApplyUserId              int    `description:"申请人ID"`
+	ApplyUserName            string `description:"申请人姓名"`
+	ApproveRemark            string `description:"审批备注"`
+	ApproveTime              string `description:"审批时间"`
+	HandleTime               string `description:"处理时间"`
+	CreateTime               string `description:"创建时间"`
+	ModifyTime               string `description:"修改时间"`
+	NodeState                int    `description:"当前节点审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回" json:"-"`
+	NodeApproveTime          string `description:"当前节点审批时间" json:"-"`
+}

+ 46 - 0
models/knowledge_approve/response/knowledge_approve_flow.go

@@ -0,0 +1,46 @@
+package response
+
+import (
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type KnowledgeApproveFlowItem struct {
+	KnowledgeApproveFlowId int    `description:"主键"`
+	FlowName               string `description:"知识资源审批流程名称"`
+	ClassifyId             int    `description:"分类ID"`
+	ClassifyName           string `description:"分类名称"`
+	CurrVersion            int    `description:"当前版本"`
+	CreateTime             string `description:"创建时间"`
+	ModifyTime             string `description:"修改时间"`
+}
+
+type KnowledgeApproveFlowListResp struct {
+	List   []*KnowledgeApproveFlowItem
+	Paging *paging.PagingItem
+}
+
+type KnowledgeApproveFlowDetailResp struct {
+	KnowledgeApproveFlowItem `description:"审批流信息"`
+	Nodes                    []*KnowledgeApproveNodeItem `description:"节点信息"`
+}
+
+type KnowledgeApproveNodeUser struct {
+	UserType string `description:"审批人类型: user-用户; role-角色"`
+	UserId   int    `description:"用户/角色ID"`
+	UserName string `description:"用户/角色姓名"`
+	Sort     int    `description:"排序"`
+}
+type KnowledgeApproveNodeItem struct {
+	KnowledgeApproveNodeId int                         `description:"知识资源审批节点ID"`
+	KnowledgeApproveFlowId int                         `description:"知识资源审批流ID"`
+	PrevNodeId             int                         `description:"上一个节点ID(0为开始节点)"`
+	NextNodeId             int                         `description:"下一个节点ID(0为结束节点)"`
+	NodeType               int                         `description:"节点类型:0-审批;1-抄送"`
+	ApproveType            int                         `description:"审批类型:1-依次审批;2-会签;3-或签"`
+	Users                  []*KnowledgeApproveNodeUser `description:"审批人信息"`
+}
+
+type KnowledgeApproveListResp struct {
+	List   []*KnowledgeApproveItemOrmResp
+	Paging *paging.PagingItem
+}

+ 24 - 0
models/knowledge_approve/response/knowledge_approve_message.go

@@ -0,0 +1,24 @@
+package response
+
+import "github.com/rdlucklib/rdluck_tools/paging"
+
+// KnowledgeApproveMessageListResp 审批消息列表响应体
+type KnowledgeApproveMessageListResp struct {
+	List        []*KnowledgeApproveMessageItem
+	Paging      *paging.PagingItem `description:"分页数据"`
+	UnreadTotal int                `description:"消息未读数"`
+}
+
+// KnowledgeApproveMessageItem 报告审批消息信息
+type KnowledgeApproveMessageItem struct {
+	Id                 int
+	SendUserId         int    `description:"发送人ID"`
+	ReceiveUserId      int    `description:"接收者ID"`
+	Content            string `description:"消息内容"`
+	Remark             string `description:"备注信息"`
+	KnowledgeApproveId int    `description:"审批ID"`
+	ApproveState       int    `description:"审批状态:1-待审批;2-已审批;3-已驳回;4-已撤回"`
+	IsRead             int    `description:"是否已读:0-未读;1-已读"`
+	CreateTime         string `description:"创建时间"`
+	ModifyTime         string `description:"修改时间"`
+}

+ 7 - 0
routers/router.go

@@ -24,6 +24,7 @@ import (
 	"eta_gn/eta_api/controllers/data_stat"
 	"eta_gn/eta_api/controllers/fe_calendar"
 	"eta_gn/eta_api/controllers/knowledge"
+	"eta_gn/eta_api/controllers/knowledge_approve"
 	"eta_gn/eta_api/controllers/report_approve"
 	"eta_gn/eta_api/controllers/sandbox"
 	"eta_gn/eta_api/controllers/semantic_analysis"
@@ -359,6 +360,12 @@ func init() {
 				&controllers.ImageConfController{},
 			),
 		),
+		web.NSNamespace("/knowledge_approve",
+			web.NSInclude(
+				&knowledge_approve.KnowledgeApproveController{},
+				&knowledge_approve.KnowledgeApproveFlowController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 32 - 0
services/knowledge_approve/constant.go

@@ -0,0 +1,32 @@
+package knowledge_approve
+
+// 看板状态
+const (
+	KnowledgeStateUnpublished = 1 // 未公开
+	// BiStatePublished   = 2 // 已发布
+	// BiStateWaitSubmit  = 3 // 待提交
+	KnowledgeStateWaitApprove = 4 // 待审批
+	KnowledgeStateRefused     = 5 // 已驳回
+	KnowledgeStatePass        = 6 // 已通过
+)
+
+// 节点审批方式
+const (
+	NodeApproveTypeRoll = 1 // 依次审批
+	NodeApproveTypeAll  = 2 // 会签
+	NodeApproveTypeAny  = 3 // 或签
+)
+
+// 节点审批人类型
+const (
+	NodeUserTypeNormal = "user" // 用户
+	NodeUserTypeRole   = "role" // 角色
+)
+
+// 报告审批状态
+const (
+	KnowledgeApproveStateApproving = 1 // 待审批
+	KnowledgeApproveStatePass      = 2 // 已审批
+	KnowledgeApproveStateRefuse    = 3 // 已驳回
+	KnowledgeApproveStateCancel    = 4 // 已撤销
+)

+ 1121 - 0
services/knowledge_approve/knowledge_approve.go

@@ -0,0 +1,1121 @@
+package knowledge_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/models"
+	"eta_gn/eta_api/models/bi_dashboard"
+	"eta_gn/eta_api/models/knowledge_approve"
+	"eta_gn/eta_api/models/knowledge_approve/response"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"sort"
+	"strings"
+	"time"
+)
+
+var (
+	timeField   = map[int]string{1: fmt.Sprintf("a.%s", knowledge_approve.KnowledgeApproveRecordCols.CreateTime), 2: fmt.Sprintf("a.%s", knowledge_approve.KnowledgeApproveRecordCols.NodeApproveTime), 3: fmt.Sprintf("b.%s", knowledge_approve.KnowledgeApproveCols.ApproveTime)}
+	myTimeField = map[int]string{1: knowledge_approve.KnowledgeApproveCols.CreateTime, 3: knowledge_approve.KnowledgeApproveCols.ApproveTime}
+	orderRules  = map[int]string{1: "ASC", 2: "DESC"}
+)
+
+func GetPulicKnowledgeClassifyList() (res []*bi_dashboard.BiDashboardClassifyItem, msg string, err error) {
+	classifyList, err := bi_dashboard.GetBiDashboardClassifyAllList()
+	if err != nil {
+		msg = "获取公共分类列表失败"
+		return
+	}
+	res = toClassifyItem(classifyList)
+	return
+}
+
+func PassKnowledgeApprove(approveId int, adminId int) (msg string, err error) {
+	approveItem, e := knowledge_approve.GetKnowledgeApproveById(approveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批不存在, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		return
+	}
+
+	if approveItem.State != KnowledgeApproveStateApproving {
+		msg = "审批状态有误, 请刷新页面"
+		err = fmt.Errorf("审批状态有误, State: %d", approveItem.State)
+		return
+	}
+
+	var ApprovePars []interface{}
+	Approveconds := ` AND bi_approve_id =? AND approve_user_id =? AND state =? `
+	ApprovePars = append(ApprovePars, approveId, adminId, KnowledgeApproveStateApproving)
+
+	recordItem, er := knowledge_approve.GetKnowledgeApproveRecordByCondition(Approveconds, ApprovePars)
+	if er != nil {
+		if utils.IsErrNoRow(er) {
+			msg = "无权审批"
+			err = er
+			return
+		}
+		msg = "操作失败"
+		return
+	}
+
+	// 查询审批流和审批流节点
+	flowItem, e := knowledge_approve.GetKnowledgeApproveFlowById(approveItem.FlowId)
+	if e != nil {
+		err = fmt.Errorf("获取审批流失败, Err: %s", e.Error())
+		return
+	}
+	nodePars := make([]interface{}, 0)
+	nodeCond := ` AND bi_approve_flow_id =? AND curr_version =? `
+	nodePars = append(nodePars, flowItem.KnowledgeApproveFlowId, flowItem.CurrVersion)
+	nodeItems, e := knowledge_approve.GetKnowledgeApproveNodeByCondition(nodeCond, nodePars)
+	if e != nil {
+		err = fmt.Errorf("ApproveNodes GetItemsByCondition err: %s", e.Error())
+		return
+	}
+	if len(nodeItems) == 0 {
+		err = fmt.Errorf("无审批节点")
+		return
+	}
+	nodeMap := make(map[int]*knowledge_approve.KnowledgeApproveNode)
+	for _, v := range nodeItems {
+		nodeMap[v.KnowledgeApproveNodeId] = v
+	}
+
+	// 取出审批记录的节点
+	currNodeItem := nodeMap[recordItem.NodeId]
+	if currNodeItem == nil {
+		err = fmt.Errorf("当前节点信息有误")
+		return
+	}
+	currNode, e := FormatKnowledgeApproveNode2Item(currNodeItem)
+	if e != nil {
+		err = fmt.Errorf("当前节点信息有误, Err: %s", e.Error())
+		return
+	}
+	now := time.Now().Local()
+	recordItem.State = KnowledgeApproveStatePass
+	recordItem.ApproveTime = now
+	recordItem.ModifyTime = now
+	recordItem.NodeState = KnowledgeApproveStatePass
+	recordItem.NodeApproveUserId = recordItem.ApproveUserId
+	recordItem.NodeApproveUserName = recordItem.ApproveUserName
+	recordItem.NodeApproveTime = now
+
+	recordCols := []string{"State", "ApproveTime", "ModifyTime", "NodeState", "NodeApproveUserId", "NodeApproveUserName", "NodeApproveTime"}
+	lastApprove := false
+
+	// 依次审批
+	if currNode.ApproveType == NodeApproveTypeRoll {
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		// 检查依次审批情况
+		sort.Slice(currNode.Users, func(k, j int) bool {
+			return currNode.Users[k].Sort < currNode.Users[j].Sort
+		})
+		userLen := len(currNode.Users)
+		//lastRoll := false
+		nextUser := new(response.KnowledgeApproveNodeUser) // 下一个审批人, 为nil则表示当前审批人即为最后
+		for k, v := range currNode.Users {
+			// 当前审批人
+			if v.UserId == adminId && recordItem.ApproveUserSort == v.Sort {
+				if (k + 1) < userLen {
+					nextUser = currNode.Users[k+1]
+				}
+			}
+		}
+		// 当前节点下一个审批人, 生成下一个审批记录且return
+		if nextUser.UserId > 0 {
+			newRecord := new(knowledge_approve.KnowledgeApproveRecord)
+			newRecord.KnowledgeApproveId = recordItem.KnowledgeApproveId
+			newRecord.State = KnowledgeApproveStateApproving
+			newRecord.NodeId = currNode.KnowledgeApproveNodeId
+			newRecord.PrevNodeId = currNode.PrevNodeId
+			newRecord.NextNodeId = currNode.NextNodeId
+			newRecord.ApproveType = currNode.ApproveType
+			newRecord.ApproveUserId = nextUser.UserId
+			newRecord.ApproveUserName = nextUser.UserName
+			newRecord.ApproveUserSort = nextUser.Sort
+			newRecord.CreateTime = now
+			newRecord.ModifyTime = now
+			newRecord.NodeState = KnowledgeApproveStateApproving
+			if e = newRecord.Create(); e != nil {
+				err = fmt.Errorf("生成审批记录失败, Err: %s", e.Error())
+				return
+			}
+
+			// 推送审批消息
+			go func() {
+				messageItem := new(knowledge_approve.KnowledgeApproveMessage)
+				messageItem.SendUserId = approveItem.ApplyUserId
+				messageItem.ReceiveUserId = nextUser.UserId
+				messageItem.Content = "您有新的待办任务"
+				messageItem.Remark = fmt.Sprintf("%s提交的【%s】需要您审批,请及时处理", approveItem.ApplyUserName, approveItem.KnowledgeTitle)
+				messageItem.KnowledgeApproveId = approveItem.KnowledgeApproveId
+				messageItem.ApproveState = KnowledgeApproveStateApproving
+				messageItem.CreateTime = now
+				messageItem.ModifyTime = now
+				if e = messageItem.Create(); e != nil {
+					utils.FileLog.Info(fmt.Sprintf("PassKnowledgeApprove message err: %s", e.Error()))
+					return
+				}
+			}()
+			return
+		}
+
+		// 更新审批当前节点并进入下一个节点
+		if currNode.NextNodeId > 0 {
+			nextNode := nodeMap[currNode.NextNodeId]
+			approveItem.CurrNodeId = currNode.NextNodeId
+			approveItem.ModifyTime = now
+			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
+				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
+				return
+			}
+			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.KnowledgeApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.KnowledgeTitle)
+			return
+		} else {
+			// 最后一个节点
+			lastApprove = true
+		}
+	}
+
+	// 会签
+	if currNode.ApproveType == NodeApproveTypeAll {
+		// 查询其他审批人是否已审批
+		otherCond := ` AND bi_approve_id =? AND node_id =? AND approve_user_id <> ? `
+		otherPars := make([]interface{}, 0)
+		otherPars = append(otherPars, approveItem.KnowledgeApproveId, recordItem.NodeId, adminId)
+		otherRecords, e := knowledge_approve.GetKnowledgeApproveRecordItemsByCondition(otherCond, otherPars)
+		if e != nil {
+			err = fmt.Errorf("获取节点审批记录失败, Err: %s", e.Error())
+			return
+		}
+		otherPass := true
+		for _, v := range otherRecords {
+			if v.State != KnowledgeApproveStatePass {
+				otherPass = false
+			}
+		}
+
+		// 其他人未审批, 仅更新当前审批记录
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		// 其他人已审批且为最后节点
+		if otherPass && currNode.NextNodeId == 0 {
+			lastApprove = true
+		}
+
+		// 其他人已审批且不为最后节点, 进入下一节点
+		if otherPass && currNode.NextNodeId > 0 {
+			nextNode := nodeMap[currNode.NextNodeId]
+			approveItem.CurrNodeId = currNode.NextNodeId
+			approveItem.ModifyTime = now
+			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
+				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
+				return
+			}
+			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.KnowledgeApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.KnowledgeTitle)
+			return
+		}
+	}
+
+	// 或签
+	if currNode.ApproveType == NodeApproveTypeAny {
+		// 需检查一下审批的当前节点和记录的节点是否匹配, 不匹配可能是因为另外的审批人已通过, 所以此处应给提示
+		// 前端也有做相应的判断,但是两个人同时进入审批详情页时就可能出现这种情况
+		if approveItem.CurrNodeId != recordItem.NodeId {
+			msg = "该节点已完成审批, 请刷新页面"
+			return
+		}
+
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		// 将该审批的同一个节点的记录标记为已审批
+		if e = recordItem.UpdateNodeState(recordItem.KnowledgeApproveId, recordItem.NodeId, recordItem.NodeState, recordItem.NodeApproveUserId, recordItem.NodeApproveUserName, recordItem.NodeApproveTime); e != nil {
+			err = fmt.Errorf("更新同一节点的其他审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+
+		if currNode.NextNodeId == 0 {
+			lastApprove = true
+		}
+		if currNode.NextNodeId > 0 {
+			nextNode := nodeMap[currNode.NextNodeId]
+			approveItem.CurrNodeId = currNode.NextNodeId
+			approveItem.ModifyTime = now
+			if e = approveItem.Update([]string{"CurrNodeId", "ModifyTime"}); e != nil {
+				err = fmt.Errorf("更新审批当前节点失败, Err: %s", e.Error())
+				return
+			}
+			err = BuildNextNodeRecordAndMsg(nextNode, approveItem.KnowledgeApproveId, approveItem.ApplyUserId, approveItem.ApplyUserName, approveItem.KnowledgeTitle)
+			return
+		}
+	}
+
+	// 最后一个审批, 更新审批记录、审批、报告状态、推送消息给申请人
+	if lastApprove {
+		if e = recordItem.Update(recordCols); e != nil {
+			err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+			return
+		}
+		approveItem.State = KnowledgeApproveStatePass
+		approveItem.ApproveTime = now
+		approveItem.ModifyTime = now
+		approveCols := []string{"State", "ApproveTime", "ModifyTime"}
+		if e = approveItem.Update(approveCols); e != nil {
+			err = fmt.Errorf("更新审批信息失败, Err: %s", e.Error())
+			return
+		}
+		if e = updateKnowledgeApproveState(approveItem.KnowledgeId, KnowledgeStatePass); e != nil {
+			err = fmt.Errorf("更新报告审批状态失败, Err: %s", e.Error())
+			return
+		}
+
+		go func() {
+			messageItem := new(knowledge_approve.KnowledgeApproveMessage)
+			messageItem.SendUserId = adminId
+			messageItem.ReceiveUserId = approveItem.ApplyUserId
+			messageItem.Content = "您提交的审批已通过"
+			messageItem.Remark = fmt.Sprintf("您提交的【%s】已通过", approveItem.KnowledgeTitle)
+			messageItem.KnowledgeApproveId = approveItem.KnowledgeApproveId
+			messageItem.ApproveState = KnowledgeApproveStatePass
+			messageItem.CreateTime = now
+			messageItem.ModifyTime = now
+			if e = messageItem.Create(); e != nil {
+				utils.FileLog.Info(fmt.Sprintf("PassKnowledgeApprove message err: %s", e.Error()))
+				return
+			}
+		}()
+	}
+	return
+
+}
+
+func toClassifyItem(src []*bi_dashboard.BiDashboardClassify) (dst []*bi_dashboard.BiDashboardClassifyItem) {
+	for _, item := range src {
+		dst = append(dst, &bi_dashboard.BiDashboardClassifyItem{
+			BiDashboardClassifyId:   item.BiDashboardClassifyId,
+			BiDashboardClassifyName: item.BiDashboardClassifyName,
+		})
+	}
+	return
+}
+
+// BuildNextNodeRecordAndMsg 生成下一个节点的审批记录并推送消息
+func BuildNextNodeRecordAndMsg(approveNodeItem *knowledge_approve.KnowledgeApproveNode, approveId, sysAdminId int, sysAdminName, biTitle string) (err error) {
+	if approveNodeItem == nil {
+		err = fmt.Errorf("approve node nil")
+		return
+	}
+
+	// 根据节点审批方式生成审批记录
+	now := time.Now().Local()
+	approveNode, e := FormatKnowledgeApproveNode2Item(approveNodeItem)
+	if e != nil {
+		err = fmt.Errorf("FormatKnowledgeApproveNode2Item err: %s", e.Error())
+		return
+	}
+	if len(approveNode.Users) == 0 {
+		err = fmt.Errorf("审批节点用户有误")
+		return
+	}
+	newRecords := make([]*knowledge_approve.KnowledgeApproveRecord, 0)
+	sort.Slice(approveNode.Users, func(k, j int) bool {
+		return approveNode.Users[k].Sort < approveNode.Users[j].Sort
+	})
+	for _, u := range approveNode.Users {
+		r := new(knowledge_approve.KnowledgeApproveRecord)
+		r.KnowledgeApproveId = approveId
+		r.State = KnowledgeApproveStateApproving
+		r.NodeId = approveNode.KnowledgeApproveNodeId
+		r.PrevNodeId = approveNode.PrevNodeId
+		r.NextNodeId = approveNode.NextNodeId
+		r.ApproveType = approveNode.ApproveType
+		r.ApproveUserId = u.UserId
+		r.ApproveUserName = u.UserName
+		r.ApproveUserSort = u.Sort
+		r.CreateTime = now
+		r.ModifyTime = now
+		r.NodeState = KnowledgeApproveStateApproving // 当前节点审批状态
+		newRecords = append(newRecords, r)
+		// 依次审批仅生成一条记录
+		if approveNode.ApproveType == NodeApproveTypeRoll {
+			break
+		}
+	}
+
+	recordOb := new(knowledge_approve.KnowledgeApproveRecord)
+	if e = recordOb.CreateMulti(newRecords); e != nil {
+		err = fmt.Errorf("生成节点审批记录失败, Err: %s", e.Error())
+		return
+	}
+
+	// 推送审批消息
+	go func() {
+		messageOb := new(knowledge_approve.KnowledgeApproveMessage)
+		messages := make([]*knowledge_approve.KnowledgeApproveMessage, 0)
+		for _, v := range newRecords {
+			m := new(knowledge_approve.KnowledgeApproveMessage)
+			m.SendUserId = sysAdminId
+			m.ReceiveUserId = v.ApproveUserId
+			m.Content = "您有新的待办任务"
+			m.Remark = fmt.Sprintf("%s提交的【%s】需要您审批,请及时处理", sysAdminName, biTitle)
+			m.KnowledgeApproveId = approveId
+			m.ApproveState = KnowledgeApproveStateApproving
+			m.CreateTime = now
+			m.ModifyTime = now
+			messages = append(messages, m)
+		}
+		e = messageOb.CreateMulti(messages)
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("BuildNextNodeRecordAndMsg messages err: %s", e.Error()))
+			return
+		}
+	}()
+	return
+}
+
+// updateKnowledgeApproveState 更新知识资源审批状态
+func updateKnowledgeApproveState(knowledgeId, state int) (err error) {
+	// updateCols := []string{"ApproveId", "State", "ModifyTime"}
+	updateCols := []string{"State", "ModifyTime"}
+	KnowledgeItem, e := bi_dashboard.GetDashboardById(knowledgeId)
+	if e != nil && !utils.IsErrNoRow(e) {
+		err = fmt.Errorf("获取知识资源失败, Err: %s", e.Error())
+		return
+	}
+	if KnowledgeItem != nil && KnowledgeItem.BiDashboardId > 0 {
+		KnowledgeItem.State = state
+		KnowledgeItem.ModifyTime = time.Now().Local()
+
+		if e = KnowledgeItem.Update(updateCols); e != nil {
+			err = fmt.Errorf("更新知识资源审批状态失败, Err: %s", e.Error())
+			return
+		}
+	}
+	return
+}
+
+func ProcessingKnowledgeApprove(adminId, classifyId, timeType, sortField, sortRule, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.KnowledgeApproveItemOrmResp, respTotal int, msg string, err error) {
+	cond := fmt.Sprintf(` AND a.%s = ? AND b.%s = ? AND a.%s = ?`, knowledge_approve.KnowledgeApproveRecordCols.State, knowledge_approve.KnowledgeApproveCols.State, knowledge_approve.KnowledgeApproveRecordCols.ApproveUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, KnowledgeApproveStateApproving, KnowledgeApproveStateApproving, adminId)
+	order := ""
+
+	// 筛选条件
+	if classifyId > 0 {
+		cond += fmt.Sprintf(` AND b.%s = ?`, knowledge_approve.KnowledgeApproveCols.ClassifyId)
+		pars = append(pars, classifyId)
+	}
+	if timeType <= 0 {
+		timeType = 1
+	}
+	if timeType == 1 && startTime != "" && endTime != "" {
+		_, e := time.Parse(utils.FormatDate, startTime)
+		if e != nil {
+			msg = "开始时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
+		if e != nil {
+			msg = "结束时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime = tmpEndTime.AddDate(0, 0, 1)
+		cond += fmt.Sprintf(` AND (b.%s BETWEEN ? AND ?)`, knowledge_approve.KnowledgeApproveCols.CreateTime)
+		pars = append(pars, startTime, tmpEndTime)
+	}
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += fmt.Sprintf(` AND b.%s LIKE ?`, knowledge_approve.KnowledgeApproveCols.KnowledgeTitle)
+		pars = append(pars, kw)
+	}
+	if sortField > 0 && sortRule > 0 {
+		orderField := timeField[sortField]
+		if orderField == "" {
+			msg = "时间排序字段有误"
+			return
+		}
+		orderRule := orderRules[sortRule]
+		if orderRule == "" {
+			msg = "时间排序方式有误"
+			return
+		}
+		order = fmt.Sprintf("%s %s", orderField, orderRule)
+	}
+	total, e := knowledge_approve.GetApprovingKnowledgeApproveCount(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovingKnowledgeApproveCount err: %s", e.Error())
+		return
+	}
+	list, e := knowledge_approve.GetApprovingKnowledgeApprovePageList(cond, pars, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovingKnowledgeApprovePageList err: %s", e.Error())
+		return
+	}
+
+	respList = toKnowledgeApproveItemOrmResp(list)
+	respTotal = total
+	return
+}
+
+// SolvedKnowledgeApprove 已处理的审批
+func SolvedKnowledgeApprove(adminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.KnowledgeApproveItemOrmResp, respTotal int, msg string, err error) {
+	cond := fmt.Sprintf(` AND a.%s = ? AND a.%s IN (?)`, knowledge_approve.KnowledgeApproveRecordCols.ApproveUserId, knowledge_approve.KnowledgeApproveRecordCols.NodeState)
+	pars := make([]interface{}, 0)
+	pars = append(pars, adminId, []int{KnowledgeApproveStatePass, KnowledgeApproveStateRefuse})
+	order := ""
+
+	// 筛选条件
+	if classifyId > 0 {
+		cond += fmt.Sprintf(` AND b.%s = ?`, knowledge_approve.KnowledgeApproveCols.ClassifyId)
+		pars = append(pars, classifyId)
+	}
+	if timeType > 0 && startTime != "" && endTime != "" {
+		_, e := time.Parse(utils.FormatDate, startTime)
+		if e != nil {
+			msg = "开始时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
+		if e != nil {
+			msg = "结束时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime = tmpEndTime.AddDate(0, 0, 1)
+		cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, timeField[timeType])
+		pars = append(pars, startTime, tmpEndTime)
+	}
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += fmt.Sprintf(` AND b.%s LIKE ?`, knowledge_approve.KnowledgeApproveCols.KnowledgeTitle)
+		pars = append(pars, kw)
+	}
+	if sortField > 0 && sortRule > 0 {
+		orderField := timeField[sortField]
+		if orderField == "" {
+			msg = "时间排序字段有误"
+			return
+		}
+		orderRule := orderRules[sortRule]
+		if orderRule == "" {
+			msg = "时间排序方式有误"
+			return
+		}
+		order = fmt.Sprintf("%s %s", orderField, orderRule)
+	}
+	if approveState > 0 {
+		cond += fmt.Sprintf(` AND a.%s = ?`, knowledge_approve.KnowledgeApproveRecordCols.NodeState)
+		pars = append(pars, approveState)
+	}
+	total, e := knowledge_approve.GetApprovedKnowledgeApproveCount(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovedKnowledgeApproveCount err: %s", e.Error())
+		return
+	}
+	list, e := knowledge_approve.GetApprovedKnowledgeApprovePageList(cond, pars, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApprovedKnowledgeApprovePageList err: %s", e.Error())
+		return
+	}
+
+	for _, v := range list {
+		// 这个时候的状态,用审批状态
+		v.RecordState = v.NodeState
+		v.ApproveTime = v.NodeApproveTime
+	}
+	respList = toKnowledgeApproveItemOrmResp(list)
+	respTotal = total
+	return
+}
+
+func MyApplyKnowledgeApproves(adminId, classifyId, timeType, sortField, sortRule, approveState, startSize, pageSize int, adminName, startTime, endTime, keyword string) (respList []*response.KnowledgeApproveItemOrmResp, respTotal int, msg string, err error) {
+	cond := fmt.Sprintf(` AND a.%s = ?`, knowledge_approve.KnowledgeApproveCols.ApplyUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, adminId)
+	order := ""
+
+	// 筛选条件
+	if classifyId > 0 {
+		cond += fmt.Sprintf(` AND a.%s = ?`, knowledge_approve.KnowledgeApproveCols.ClassifyId)
+		pars = append(pars, classifyId)
+	}
+	if timeType > 0 && startTime != "" && endTime != "" {
+		_, e := time.Parse(utils.FormatDate, startTime)
+		if e != nil {
+			msg = "开始时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTime, e := time.Parse(utils.FormatDate, endTime)
+		if e != nil {
+			msg = "结束时间格式有误"
+			err = e
+			return
+		}
+		tmpEndTimeStr := tmpEndTime.AddDate(0, 0, 1).Format(utils.FormatDate)
+		cond += fmt.Sprintf(` AND (%s BETWEEN ? AND ?)`, myTimeField[timeType])
+		pars = append(pars, startTime, tmpEndTimeStr)
+	}
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += fmt.Sprintf(` AND a.%s LIKE ?`, knowledge_approve.KnowledgeApproveCols.KnowledgeTitle)
+		pars = append(pars, kw)
+	}
+	if sortField > 0 && sortRule > 0 {
+		orderField := myTimeField[sortField]
+		if orderField == "" {
+			msg = "时间排序字段有误"
+			return
+		}
+		orderRule := orderRules[sortRule]
+		if orderRule == "" {
+			msg = "时间排序方式有误"
+			return
+		}
+		order = fmt.Sprintf("%s %s", orderField, orderRule)
+	}
+	if approveState > 0 {
+		cond += fmt.Sprintf(` AND a.%s = ?`, knowledge_approve.KnowledgeApproveRecordCols.State)
+		pars = append(pars, approveState)
+	}
+	total, e := knowledge_approve.GetApplyKnowledgeApproveCount(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApplyKnowledgeApproveCount err: %s", e.Error())
+		return
+	}
+	respTotal = total
+	list, e := knowledge_approve.GetApplyKnowledgeApprovePageList(cond, pars, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetApplyKnowledgeApprovePageList err: %s", e.Error())
+		return
+	}
+	respList = toKnowledgeApproveItemOrmResp(list)
+	return
+}
+
+func GetApproveDetail(approveId int) (resp *response.KnowledgeApproveDetail, msg string, err error) {
+	approveItem, e := knowledge_approve.GetKnowledgeApproveById(approveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批已被删除, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "获取失败"
+		err = fmt.Errorf("GetItemById err: %s", e.Error())
+		return
+	}
+
+	// 审批信息
+	detail := new(response.KnowledgeApproveDetail)
+	detail.Approve = new(response.KnowledgeApproveDetailItem)
+	detail.Approve.KnowledgeApproveId = approveItem.KnowledgeApproveId
+	detail.Approve.State = approveItem.State
+	detail.Approve.FlowId = approveItem.FlowId
+	detail.Approve.FlowVersion = approveItem.FlowVersion
+	detail.Approve.StartNodeId = approveItem.StartNodeId
+	detail.Approve.CurrNodeId = approveItem.CurrNodeId
+	detail.Approve.ApplyUserId = approveItem.ApplyUserId
+	detail.Approve.ApplyUserName = approveItem.ApplyUserName
+	detail.Approve.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.ApproveTime)
+	detail.Approve.CreateTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.CreateTime)
+	detail.Approve.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, approveItem.ModifyTime)
+
+	// 审批节点
+	nodeOb := new(knowledge_approve.KnowledgeApproveNode)
+	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, knowledge_approve.KnowledgeApproveNodeCols.KnowledgeApproveFlowId, knowledge_approve.KnowledgeApproveNodeCols.CurrVersion)
+	nodePars := make([]interface{}, 0)
+	nodePars = append(nodePars, approveItem.FlowId, approveItem.FlowVersion)
+	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetItemsByCondition err: %s", e.Error())
+		return
+	}
+
+	// 审批记录
+	recordOb := new(knowledge_approve.KnowledgeApproveRecord)
+	recordCond := fmt.Sprintf(` AND %s = ?`, knowledge_approve.KnowledgeApproveRecordCols.KnowledgeApproveId)
+	recordPars := make([]interface{}, 0)
+	recordPars = append(recordPars, approveItem.KnowledgeApproveId)
+	recordItems, e := recordOb.GetItemsByCondition(recordCond, recordPars, []string{}, fmt.Sprintf("%s DESC", knowledge_approve.KnowledgeApproveRecordCols.ApproveTime))
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetItemsByCondition err: %s", e.Error())
+		return
+	}
+	recordMap := make(map[string]*knowledge_approve.KnowledgeApproveRecord)
+	for _, v := range recordItems {
+		k := fmt.Sprintf("%d-%d", v.NodeId, v.ApproveUserId)
+		recordMap[k] = v
+	}
+
+	// 审批流节点详情
+	detail.ApproveFlowNodes = make([]*response.KnowledgeApproveDetailNodes, 0)
+	for _, v := range nodeItems {
+		t := new(response.KnowledgeApproveDetailNodes)
+		t.KnowledgeApproveNodeId = v.KnowledgeApproveNodeId
+		t.KnowledgeApproveFlowId = v.KnowledgeApproveFlowId
+		t.PrevNodeId = v.PrevNodeId
+		t.NextNodeId = v.NextNodeId
+		t.NodeType = v.NodeType
+		t.ApproveType = v.ApproveType
+		t.Users = make([]*response.KnowledgeApproveDetailNodeUser, 0)
+		us := make([]*response.KnowledgeApproveNodeUserReq, 0)
+		if v.Users != "" {
+			e = json.Unmarshal([]byte(v.Users), &us)
+			if e != nil {
+				msg = "获取失败"
+				err = fmt.Errorf("json.Unmarshal err: %s", e.Error())
+				return
+			}
+		}
+		for _, vu := range us {
+			u := new(response.KnowledgeApproveDetailNodeUser)
+			u.UserType = vu.UserType
+			u.UserId = vu.UserId
+			u.UserName = vu.UserName
+			u.Sort = vu.Sort
+			// 审批记录
+			k := fmt.Sprintf("%d-%d", v.KnowledgeApproveNodeId, vu.UserId)
+			r := recordMap[k]
+			if r != nil {
+				u.ApproveRecord = new(response.KnowledgeApproveDetailNodeUserRecord)
+				u.ApproveRecord.KnowledgeApproveRecordId = r.KnowledgeApproveRecordId
+				u.ApproveRecord.State = r.State
+				u.ApproveRecord.ApproveUserId = r.ApproveUserId
+				u.ApproveRecord.ApproveUserName = r.ApproveUserName
+				u.ApproveRecord.ApproveRemark = r.ApproveRemark
+				u.ApproveRecord.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, r.ApproveTime)
+			}
+			t.Users = append(t.Users, u)
+		}
+		sort.Slice(t.Users, func(k, j int) bool {
+			return t.Users[k].Sort < t.Users[j].Sort
+		})
+		detail.ApproveFlowNodes = append(detail.ApproveFlowNodes, t)
+	}
+
+	// 看板信息
+	cnClassifyIdName := make(map[int]string)
+	cnClassify, e := bi_dashboard.GetBiDashboardClassifyAllList()
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetKnowledgeDashboardClassifyAllList err: %s", e.Error())
+		return
+	}
+	for _, v := range cnClassify {
+		cnClassifyIdName[v.BiDashboardClassifyId] = v.BiDashboardClassifyName
+	}
+	detail.Knowledge = new(response.KnowledgeApproveDetailKnowledge)
+	detail.Knowledge.KnowledgeId = approveItem.KnowledgeId
+	detail.Knowledge.KnowledgeTitle = approveItem.KnowledgeTitle
+	detail.Knowledge.KnowledgeClassify = cnClassifyIdName[approveItem.ClassifyId]
+	resp = detail
+	return
+}
+
+func KnowledgeApproveRefuse(knowledgeApproveId, adminId int, approveRemark string) (msg string, err error) {
+	approveItem, e := knowledge_approve.GetKnowledgeApproveById(knowledgeApproveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批不存在, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		err = fmt.Errorf("GetKnowledgeApproveById err: %s", e.Error())
+		return
+	}
+	if approveItem.State != KnowledgeApproveStateApproving {
+		msg = "审批状态有误, 请刷新页面"
+		err = fmt.Errorf("审批状态有误, State: %d", approveItem.State)
+		return
+	}
+
+	// 校验审批记录和审批
+	recordOb := new(knowledge_approve.KnowledgeApproveRecord)
+	recordCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, knowledge_approve.KnowledgeApproveRecordCols.KnowledgeApproveId, knowledge_approve.KnowledgeApproveRecordCols.ApproveUserId, knowledge_approve.KnowledgeApproveRecordCols.State)
+	recordPars := make([]interface{}, 0)
+	recordPars = append(recordPars, approveItem.KnowledgeApproveId, adminId, KnowledgeApproveStateApproving)
+	recordItem, e := recordOb.GetItemByCondition(recordCond, recordPars, "")
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "无权审批"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		err = fmt.Errorf("GetItemByCondition err: %s", e.Error())
+		return
+	}
+
+	// 驳回审批
+	if e = refuseKnowledgeApprove(approveItem, recordItem, approveRemark, adminId); e != nil {
+		msg = "操作失败"
+		err = fmt.Errorf("RefuseKnowledgeApprove err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// refuseKnowledgeApprove 驳回审批
+func refuseKnowledgeApprove(approveItem *knowledge_approve.KnowledgeApprove, recordItem *knowledge_approve.KnowledgeApproveRecord, approveRemark string, sysAdminId int) (err error) {
+	if approveItem == nil {
+		err = fmt.Errorf("审批信息有误")
+		return
+	}
+	if recordItem == nil {
+		err = fmt.Errorf("审批记录有误")
+		return
+	}
+
+	// 更新审批记录
+	now := time.Now().Local()
+	recordItem.State = KnowledgeApproveStateRefuse
+	recordItem.ApproveRemark = approveRemark
+	recordItem.ApproveTime = now
+	recordItem.ModifyTime = now
+
+	recordItem.NodeState = KnowledgeApproveStateRefuse
+	recordItem.NodeApproveUserId = recordItem.ApproveUserId
+	recordItem.NodeApproveUserName = recordItem.ApproveUserName
+	recordItem.NodeApproveTime = now
+
+	recordCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime", "NodeState", "NodeApproveUserId", "NodeApproveUserName", "NodeApproveTime"}
+	if e := recordItem.Update(recordCols); e != nil {
+		err = fmt.Errorf("更新审批记录状态失败, Err: %s", e.Error())
+		return
+	}
+
+	// 将该审批的同一个节点的记录标记为已审批
+	if e := recordItem.UpdateNodeState(recordItem.KnowledgeApproveId, recordItem.NodeId, recordItem.NodeState, recordItem.NodeApproveUserId, recordItem.NodeApproveUserName, recordItem.NodeApproveTime); e != nil {
+		err = fmt.Errorf("更新同一节点的其他审批记录状态失败, Err: %s", e.Error())
+		return
+	}
+
+	// 驳回-更新审批, 报告状态, 推送消息
+	approveItem.State = KnowledgeApproveStateRefuse
+	approveItem.ApproveRemark = approveRemark
+	approveItem.ApproveTime = now
+	approveItem.ModifyTime = now
+	approveCols := []string{"State", "ApproveRemark", "ApproveTime", "ModifyTime"}
+	if e := approveItem.Update(approveCols); e != nil {
+		err = fmt.Errorf("更新审批状态失败, Err: %s", e.Error())
+		return
+	}
+
+	if e := updateKnowledgeApproveState(approveItem.KnowledgeId, KnowledgeStateRefused); e != nil {
+		err = fmt.Errorf("更新报告状态失败, Err: %s", e.Error())
+		return
+	}
+
+	// 推送驳回消息给申请人
+	go func() {
+		messageItem := new(knowledge_approve.KnowledgeApproveMessage)
+		messageItem.SendUserId = sysAdminId
+		messageItem.ReceiveUserId = approveItem.ApplyUserId
+		messageItem.Content = "您提交的审批被驳回"
+		messageItem.Remark = fmt.Sprintf("您提交的【%s】已被驳回", approveItem.KnowledgeTitle)
+		messageItem.KnowledgeApproveId = approveItem.KnowledgeApproveId
+		messageItem.ApproveState = KnowledgeApproveStateRefuse
+		messageItem.CreateTime = now
+		messageItem.ModifyTime = now
+		if e := messageItem.Create(); e != nil {
+			utils.FileLog.Info(fmt.Sprintf("ApproveKnowledge message err: %s", e.Error()))
+			return
+		}
+	}()
+	return
+}
+
+func KnowledgeApproveCancel(knowledgeApproveId, adminId int, adminName string) (msg string, err error) {
+	approveItem, e := knowledge_approve.GetKnowledgeApproveById(knowledgeApproveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "审批已被删除, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "操作失败"
+		err = fmt.Errorf("GetKnowledgeApproveById err: %s", e.Error())
+		return
+	}
+	if approveItem.ApplyUserId != adminId {
+		msg = "非申请人不可撤销"
+		err = fmt.Errorf("非申请人不可撤销")
+		return
+	}
+
+	// 撤销审批
+	e = cancelKnowledgeApprove(approveItem.KnowledgeId, approveItem.KnowledgeApproveId, adminId, adminName)
+	if e != nil {
+		msg = "操作失败"
+		err = fmt.Errorf("cancelKnowledgeApprove err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// cancelKnowledgeApprove 撤回审批
+func cancelKnowledgeApprove(biId, approveId, sysAdminId int, sysAdminName string) (err error) {
+	// 默认内部审批, 如果是走的第三方审批, 那么仅修改状态
+	confMap, e := models.GetBusinessConf()
+	if e != nil {
+		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
+		return
+	}
+	openMap := map[string]bool{"false": false, "true": true}
+	openApprove := openMap[confMap[models.BusinessConfIsBIApprove]]
+	if !openApprove {
+		//err = fmt.Errorf("未开启审批")
+		return
+	}
+
+	// 修改审批信息状态
+	approveItem, e := knowledge_approve.GetKnowledgeApproveById(approveId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			err = e
+			return
+		}
+		err = fmt.Errorf("approve GetItemById err: %s", e.Error())
+		return
+	}
+	if approveItem.State == KnowledgeApproveStateCancel {
+		return
+	}
+	approveItem.State = KnowledgeApproveStateCancel
+	approveItem.ModifyTime = time.Now()
+	cols := []string{"State", "ModifyTime"}
+	if e = approveItem.Update(cols); e != nil {
+		err = fmt.Errorf("approve Update err: %s", e.Error())
+		return
+	}
+
+	// 修改报告状态
+	e = updateKnowledgeApproveState(biId, KnowledgeStateUnpublished)
+	if e != nil {
+		err = fmt.Errorf("更新报告审批撤回失败, Err: %s", e.Error())
+		return
+	}
+
+	// 推送撤回消息
+	go func() {
+		recordOb := new(knowledge_approve.KnowledgeApproveRecord)
+		recordCond := fmt.Sprintf(` AND %s = ?`, knowledge_approve.KnowledgeApproveRecordCols.KnowledgeApproveId)
+		recordPars := make([]interface{}, 0)
+		recordPars = append(recordPars, approveId)
+		recordItems, e := recordOb.GetItemsByCondition(recordCond, recordPars, []string{}, "")
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("approve record GetItemsByCondition err: %s", e.Error()))
+			return
+		}
+
+		messageOb := new(knowledge_approve.KnowledgeApproveMessage)
+		messages := make([]*knowledge_approve.KnowledgeApproveMessage, 0)
+		for _, v := range recordItems {
+			m := new(knowledge_approve.KnowledgeApproveMessage)
+			m.SendUserId = sysAdminId
+			m.ReceiveUserId = v.ApproveUserId
+			m.Content = fmt.Sprintf("%s提交的【%s】已撤回", sysAdminName, approveItem.KnowledgeTitle)
+			m.KnowledgeApproveId = approveId
+			m.ApproveState = KnowledgeApproveStateCancel
+			m.CreateTime = time.Now().Local()
+			m.ModifyTime = time.Now().Local()
+			messages = append(messages, m)
+		}
+		e = messageOb.CreateMulti(messages)
+		if e != nil {
+			utils.FileLog.Info(fmt.Sprintf("CancelKnowledgeApprove messages err: %s", e.Error()))
+			return
+		}
+	}()
+	return
+}
+
+// CheckKnowledgeOpenApprove 校验报告是否开启了审批流
+func CheckKnowledgeOpenApprove(classifyId int) (opening bool, err error) {
+	// 获取审批配置
+	confMap, e := models.GetBusinessConf()
+	if e != nil {
+		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
+		return
+	}
+	openMap := map[string]bool{"false": false, "true": true}
+	openApprove := openMap[confMap[models.BusinessConfIsBIApprove]]
+
+	// 查询对应分类是否有审批流
+	flowOb := new(knowledge_approve.KnowledgeApproveFlow)
+	flowCond := fmt.Sprintf(` AND %s = ?`, knowledge_approve.KnowledgeApproveFlowCols.ClassifyId)
+	flowPars := make([]interface{}, 0)
+	flowPars = append(flowPars, classifyId)
+	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
+	if e != nil {
+		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
+		return
+	}
+
+	// 开启审批/有审批流
+	if openApprove && (flowItem != nil) {
+		opening = true
+		return
+	}
+	return
+}
+
+// SubmitKnowledgeApprove 提交审批
+func SubmitKnowledgeApprove(knowledgeId int, knowledgeTitle string, classifyId int, sysAdminId int, sysAdminName string) (approveId int, err error) {
+	// 默认内部审批, 如果是走的第三方审批, 那么仅修改状态
+	confMap, e := models.GetBusinessConf()
+	if e != nil {
+		err = fmt.Errorf("GetBusinessConf err: %s", e.Error())
+		return
+	}
+	openMap := map[string]bool{"false": false, "true": true}
+	openApprove := openMap[confMap[models.BusinessConfIsBIApprove]]
+	if !openApprove {
+		err = fmt.Errorf("未开启审批")
+		return
+	}
+
+	// 查询审批流
+	flowOb := new(knowledge_approve.KnowledgeApproveFlow)
+	flowCond := fmt.Sprintf(` AND %s = ?`, knowledge_approve.KnowledgeApproveFlowCols.ClassifyId)
+	flowPars := make([]interface{}, 0)
+	flowPars = append(flowPars, classifyId)
+	flowItem, e := flowOb.GetItemByCondition(flowCond, flowPars, "")
+	if e != nil {
+		err = fmt.Errorf("ApproveFlow GetItemByCondition err: %s", e.Error())
+		return
+	}
+
+	// 查询审批节点
+	nodeOb := new(knowledge_approve.KnowledgeApproveNode)
+	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, knowledge_approve.KnowledgeApproveNodeCols.KnowledgeApproveFlowId, knowledge_approve.KnowledgeApproveNodeCols.CurrVersion)
+	nodePars := make([]interface{}, 0)
+	nodePars = append(nodePars, flowItem.KnowledgeApproveFlowId, flowItem.CurrVersion)
+	nodeItems, e := nodeOb.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
+	if e != nil {
+		err = fmt.Errorf("ApproveNodes GetItemsByCondition err: %s", e.Error())
+		return
+	}
+	if len(nodeItems) == 0 {
+		err = fmt.Errorf("无审批节点")
+		return
+	}
+
+	// 取出首个节点
+	firstNodeItem := new(knowledge_approve.KnowledgeApproveNode)
+	for _, v := range nodeItems {
+		if v.PrevNodeId == 0 {
+			firstNodeItem = v
+			continue
+		}
+	}
+	if firstNodeItem == nil {
+		err = fmt.Errorf("首个审批节点有误")
+		return
+	}
+
+	// 审批信息
+	now := time.Now().Local()
+	newApprove := new(knowledge_approve.KnowledgeApprove)
+	newApprove.KnowledgeId = knowledgeId
+	newApprove.KnowledgeTitle = knowledgeTitle
+	newApprove.ClassifyId = classifyId
+	newApprove.State = KnowledgeApproveStateApproving
+	newApprove.FlowId = flowItem.KnowledgeApproveFlowId
+	newApprove.FlowVersion = flowItem.CurrVersion
+	newApprove.StartNodeId = firstNodeItem.KnowledgeApproveNodeId
+	newApprove.CurrNodeId = firstNodeItem.KnowledgeApproveNodeId
+	newApprove.ApplyUserId = sysAdminId
+	newApprove.ApplyUserName = sysAdminName
+	newApprove.CreateTime = now
+	newApprove.ModifyTime = now
+	if e = newApprove.Create(); e != nil {
+		err = fmt.Errorf("生成审批信息失败, Err: %s", e.Error())
+		return
+	}
+	approveId = newApprove.KnowledgeApproveId
+
+	// 生成节点审批记录
+	err = BuildNextNodeRecordAndMsg(firstNodeItem, newApprove.KnowledgeApproveId, sysAdminId, sysAdminName, newApprove.KnowledgeTitle)
+	return
+}
+
+func toKnowledgeApproveItemOrmResp(src []*knowledge_approve.KnowledgeApproveItemOrm) (res []*response.KnowledgeApproveItemOrmResp) {
+	for _, v := range src {
+		r := new(response.KnowledgeApproveItemOrmResp)
+		r.KnowledgeApproveId = v.KnowledgeApproveId
+		r.KnowledgeApproveRecordId = v.KnowledgeApproveRecordId
+		r.KnowledgeId = v.KnowledgeId
+		r.KnowledgeTitle = v.KnowledgeTitle
+		r.ClassifyId = v.ClassifyId
+		r.State = v.State
+		r.RecordState = v.RecordState
+		r.FlowId = v.FlowId
+		r.FlowVersion = v.FlowVersion
+		r.StartNodeId = v.StartNodeId
+		r.CurrNodeId = v.CurrNodeId
+		r.ApplyUserId = v.ApplyUserId
+		r.ApplyUserName = v.ApplyUserName
+		r.ApproveRemark = v.ApproveRemark
+		r.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, v.ApproveTime)
+		r.HandleTime = utils.TimeTransferString(utils.FormatDateTime, v.HandleTime)
+		r.CreateTime = utils.TimeTransferString(utils.FormatDateTime, v.CreateTime)
+		r.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, v.ModifyTime)
+		r.NodeState = v.NodeState
+		res = append(res, r)
+	}
+	return
+}
+
+func GetKnowledgeClassifyAll() (list []*bi_dashboard.BiDashboardClassify, msg string, err error) {
+	ClassifyList, e := bi_dashboard.GetBiDashboardClassifyAllList()
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("GetKnowledgeDashboardClassifyAllList err: %s", e.Error())
+		return
+	}
+	list = ClassifyList
+	return
+}
+
+func CheckHasApprovingKnowledge() (ok bool, err error) {
+	count, err := knowledge_approve.GetKnowledgeApproveCountByState(KnowledgeApproveStateApproving)
+	if err != nil {
+		return
+	}
+	if count > 0 {
+		ok = true
+	}
+	return
+}

+ 258 - 0
services/knowledge_approve/knowledge_approve_flow.go

@@ -0,0 +1,258 @@
+package knowledge_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/models/bi_dashboard"
+	knowledge_approve "eta_gn/eta_api/models/knowledge_approve"
+	"eta_gn/eta_api/models/knowledge_approve/request"
+	"eta_gn/eta_api/models/knowledge_approve/response"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+// GetKnowledgeApproveFlowList 获取BI审批流列表
+func GetKnowledgeApproveFlowList(condition string, pars []interface{}, startSize, pageSize int) (items []*response.KnowledgeApproveFlowItem, total int, msg string, err error) {
+	total, err = knowledge_approve.GetKnowledgeApproveFlowCountByCondition(condition, pars)
+	if err != nil {
+		msg = "获取审批流程列表失败"
+		return
+	}
+	if total == 0 {
+		items = make([]*response.KnowledgeApproveFlowItem, 0)
+		return
+	}
+	flowList, err := knowledge_approve.GetKnowledgeApproveFlowByCondition(condition, pars, startSize, pageSize)
+	if err != nil {
+		msg = "获取审批流程列表失败"
+		return
+	}
+	items = toKnowledgeApproveFlowItem(flowList)
+	return
+}
+
+// SaveKnowledgeApproveFlow 保存审批流
+func SaveKnowledgeApproveFlow(flow *request.KnowledgeApproveFlowSaveReq) (ok bool, msg string, err error) {
+	classifyInfo, err := bi_dashboard.GetBiDashboardClassifyById(flow.ClassifyId)
+	if err != nil {
+		if utils.IsErrNoRow(err) {
+			msg = "保存审批流失败, 分类不存在"
+			return
+		}
+		msg = "保存审批流失败"
+		return
+	}
+	if flow.KnowledgeApproveFlowId == 0 {
+		tmp, er := knowledge_approve.GetKnowledgeApproveFlowByClassifyId(flow.ClassifyId)
+		if er != nil && !utils.IsErrNoRow(er) {
+			msg = "保存审批流失败"
+			err = er
+			return
+		}
+		if tmp != nil && tmp.KnowledgeApproveFlowId > 0 {
+			msg = "保存审批流失败, 分类下已存在审批流"
+			err = fmt.Errorf("分类下已存在审批流")
+			return
+		}
+
+		t := &knowledge_approve.KnowledgeApproveFlow{
+			FlowName:     flow.FlowName,
+			ClassifyId:   flow.ClassifyId,
+			ClassifyName: classifyInfo.BiDashboardClassifyName,
+			CurrVersion:  1,
+			CreateTime:   time.Now(),
+			ModifyTime:   time.Now(),
+		}
+		knowledgeFlowNodeItems := make([]*knowledge_approve.KnowledgeApproveNode, 0)
+		for _, node := range flow.Nodes {
+			knowledgeFlowNode := new(knowledge_approve.KnowledgeApproveNode)
+			knowledgeFlowNode.ApproveType = node.ApproveType
+			knowledgeFlowNode.CurrVersion = t.CurrVersion
+			userBytes, er := json.Marshal(node.Users)
+			if er != nil {
+				err = er
+				msg = "保存审批流失败"
+				return
+			}
+			knowledgeFlowNode.Users = string(userBytes)
+			knowledgeFlowNode.CreatedTime = time.Now()
+			knowledgeFlowNodeItems = append(knowledgeFlowNodeItems, knowledgeFlowNode)
+		}
+		err = t.Add(knowledgeFlowNodeItems)
+		if err != nil {
+			msg = "保存审批流失败"
+			return
+		}
+		ok = true
+	} else {
+		resFlow, er := knowledge_approve.GetKnowledgeApproveFlowById(flow.KnowledgeApproveFlowId)
+		if er != nil {
+			msg = "保存审批流失败"
+			err = er
+			return
+		}
+		ok, err = CheckDeleteKnowledgeApproveFlow(resFlow.KnowledgeApproveFlowId)
+		if err != nil {
+			msg = "保存审批流失败"
+			return
+		}
+		if !ok {
+			msg = "保存审批流失败, 存在还未审批的报告"
+			return
+		}
+		var updateCols []string
+		if resFlow.FlowName != flow.FlowName {
+			resFlow.FlowName = flow.FlowName
+			updateCols = append(updateCols, "flow_name")
+		}
+		resFlow.CurrVersion += 1
+		resFlow.ModifyTime = time.Now()
+		updateCols = append(updateCols, "modify_time", "curr_version")
+
+		knowledgeFlowNodeItems := make([]*knowledge_approve.KnowledgeApproveNode, 0)
+		for _, node := range flow.Nodes {
+			knowledgeFlowNode := new(knowledge_approve.KnowledgeApproveNode)
+			knowledgeFlowNode.ApproveType = node.ApproveType
+			knowledgeFlowNode.CurrVersion = resFlow.CurrVersion
+			userBytes, er := json.Marshal(node.Users)
+			if er != nil {
+				err = er
+				msg = "保存审批流失败"
+				return
+			}
+			knowledgeFlowNode.Users = string(userBytes)
+			knowledgeFlowNode.CreatedTime = time.Now()
+			knowledgeFlowNodeItems = append(knowledgeFlowNodeItems, knowledgeFlowNode)
+		}
+
+		err = resFlow.Update(updateCols, knowledgeFlowNodeItems)
+		if err != nil {
+			msg = "保存审批流失败"
+			return
+		}
+		ok = true
+	}
+	return
+}
+
+// GetKnowledgeApproveFlowDetail 获取审批流详情
+func GetKnowledgeApproveFlowDetail(flowId int) (detail *response.KnowledgeApproveFlowDetailResp, msg string, err error) {
+	flowInfo, err := knowledge_approve.GetKnowledgeApproveFlowById(flowId)
+	if err != nil {
+		msg = "获取审批流详情失败"
+		return
+	}
+	flowNodes, err := knowledge_approve.GetKnowledgeApproveNodeByFlowIdAndVersionId(flowId, flowInfo.CurrVersion)
+	if err != nil {
+		msg = "获取审批流详情失败"
+		return
+	}
+	detail, err = FormatFlowAndNodesItem2Detail(flowInfo, flowNodes)
+	if err != nil {
+		msg = "获取审批流详情失败"
+		return
+	}
+	return
+}
+
+// DeleteKnowledgeApproveFlow 删除审批流
+func DeleteKnowledgeApproveFlow(flowId int) (ok bool, msg string, err error) {
+	ok, err = CheckDeleteKnowledgeApproveFlow(flowId)
+	if err != nil {
+		if utils.IsErrNoRow(err) {
+			msg = "删除审批流失败, 审批流不存在"
+			return
+		}
+		msg = "删除审批流失败"
+		return
+	}
+	if !ok {
+		msg = "删除审批流失败, 存在还未审批的报告"
+		return
+	}
+
+	t := &knowledge_approve.KnowledgeApproveFlow{
+		KnowledgeApproveFlowId: flowId,
+	}
+	err = t.Delete()
+	if err != nil {
+		msg = "删除审批流失败"
+		return
+	}
+	ok = true
+	return
+}
+
+// CheckDeleteKnowledgeApproveFlow 检查是否可以删除审批流
+func CheckDeleteKnowledgeApproveFlow(flowId int) (ok bool, err error) {
+	flowInfo, err := knowledge_approve.GetKnowledgeApproveFlowById(flowId)
+	if err != nil {
+		return
+	}
+	// 检查是否存在还未审批的知识资源
+	approveList, err := knowledge_approve.GetKnowledgeApproveByFlowIdAndVersionId(flowInfo.KnowledgeApproveFlowId, flowInfo.CurrVersion)
+	if err != nil {
+		return
+	}
+	for _, v := range approveList {
+		if v.State == KnowledgeApproveStateApproving {
+			return false, nil
+		}
+	}
+
+	ok = true
+	return
+}
+
+func toKnowledgeApproveFlowItem(src []*knowledge_approve.KnowledgeApproveFlow) (res []*response.KnowledgeApproveFlowItem) {
+	res = make([]*response.KnowledgeApproveFlowItem, 0, len(src))
+	for _, item := range src {
+		res = append(res, &response.KnowledgeApproveFlowItem{
+			KnowledgeApproveFlowId: item.KnowledgeApproveFlowId,
+			FlowName:               item.FlowName,
+			ClassifyId:             item.ClassifyId,
+			ClassifyName:           item.ClassifyName,
+			CurrVersion:            item.CurrVersion,
+			CreateTime:             item.CreateTime.Format(utils.FormatDateTime),
+			ModifyTime:             item.ModifyTime.Format(utils.FormatDateTime),
+		})
+	}
+	return
+}
+
+func FormatFlowAndNodesItem2Detail(flowItem *knowledge_approve.KnowledgeApproveFlow, nodeItems []*knowledge_approve.KnowledgeApproveNode) (detail *response.KnowledgeApproveFlowDetailResp, err error) {
+	if flowItem == nil {
+		return
+	}
+	detail = new(response.KnowledgeApproveFlowDetailResp)
+	detail.KnowledgeApproveFlowId = flowItem.KnowledgeApproveFlowId
+	detail.FlowName = flowItem.FlowName
+	detail.ClassifyId = flowItem.ClassifyId
+	detail.CreateTime = utils.TimeTransferString(utils.FormatDateTime, flowItem.CreateTime)
+	detail.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, flowItem.ModifyTime)
+	detail.Nodes = make([]*response.KnowledgeApproveNodeItem, 0)
+	for _, v := range nodeItems {
+		t, e := FormatKnowledgeApproveNode2Item(v)
+		if e != nil {
+			err = fmt.Errorf("format node err: %s", e.Error())
+			return
+		}
+		detail.Nodes = append(detail.Nodes, t)
+	}
+	return
+}
+
+func ModifyKnowledgeApproveFlowClassify(classifyId int, classifyName string) (err error) {
+	flow, err := knowledge_approve.GetKnowledgeApproveFlowByClassifyId(classifyId)
+	if err != nil && !utils.IsErrNoRow(err) {
+		return
+	}
+	if utils.IsErrNoRow(err) {
+		err = nil
+		return
+	}
+	if classifyName != "" && flow.ClassifyName != classifyName {
+		err = knowledge_approve.UpdateFlowClassifyName(classifyId, classifyName)
+	}
+	return
+}

+ 89 - 0
services/knowledge_approve/knowledge_approve_message.go

@@ -0,0 +1,89 @@
+package knowledge_approve
+
+import (
+	"eta_gn/eta_api/models/knowledge_approve"
+	"eta_gn/eta_api/models/knowledge_approve/response"
+	"eta_gn/eta_api/utils"
+	"fmt"
+	"time"
+)
+
+func GetKnowledgeApproveMessage(adminId, startSize, pageSize int) (list []*response.KnowledgeApproveMessageItem, total, unread int, msg string, err error) {
+	cond := fmt.Sprintf(` AND %s = ?`, knowledge_approve.KnowledgeApproveMessageCols.ReceiveUserId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, adminId)
+	order := fmt.Sprintf(`%s ASC, %s DESC`, knowledge_approve.KnowledgeApproveMessageCols.IsRead, knowledge_approve.KnowledgeApproveMessageCols.CreateTime)
+
+	messageOb := new(knowledge_approve.KnowledgeApproveMessage)
+	total, e := messageOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetCountByCondition, Err: %s", e.Error())
+		return
+	}
+	tmpList, e := messageOb.GetPageItemsByCondition(cond, pars, []string{}, order, startSize, pageSize)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetPageItemsByCondition, Err: %s", e.Error())
+		return
+	}
+	for _, v := range tmpList {
+		t := FormatKnowledgeApproveMessage2Item(v)
+		list = append(list, t)
+	}
+
+	// 未读消息数
+	cond += fmt.Sprintf(` AND %s = ?`, knowledge_approve.KnowledgeApproveMessageCols.IsRead)
+	pars = append(pars, 0)
+	unreadTotal, e := messageOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetCountByCondition, Err: %s", e.Error())
+		return
+	}
+	unread = unreadTotal
+	return
+}
+
+func ReadKnowledgeMessage(msgId int, adminId int) (msg string, err error) {
+	messageOb := new(knowledge_approve.KnowledgeApproveMessage)
+	messageItem, e := messageOb.GetItemById(msgId)
+	if e != nil {
+		if utils.IsErrNoRow(e) {
+			msg = "消息不存在, 请刷新页面"
+			err = e
+			return
+		}
+		msg = "获取失败"
+		err = fmt.Errorf("message.GetItemById, Err: %s", e.Error())
+		return
+	}
+	messageItem.IsRead = 1
+	messageItem.ModifyTime = time.Now().Local()
+	cols := []string{"IsRead", "ModifyTime"}
+	if e = messageItem.Update(cols); e != nil {
+		msg = "操作失败"
+		err = fmt.Errorf("message.Update, Err: %s", e.Error())
+		return
+	}
+	return
+}
+
+// FormatKnowledgeApproveMessage2Item 格式化报告审批消息
+func FormatKnowledgeApproveMessage2Item(origin *knowledge_approve.KnowledgeApproveMessage) (item *response.KnowledgeApproveMessageItem) {
+	item = new(response.KnowledgeApproveMessageItem)
+	if origin == nil {
+		return
+	}
+	item.Id = origin.Id
+	item.SendUserId = origin.SendUserId
+	item.ReceiveUserId = origin.ReceiveUserId
+	item.Content = origin.Content
+	item.Remark = origin.Remark
+	item.KnowledgeApproveId = origin.KnowledgeApproveId
+	item.ApproveState = origin.ApproveState
+	item.IsRead = origin.IsRead
+	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, origin.CreateTime)
+	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, origin.ModifyTime)
+	return
+}

+ 31 - 0
services/knowledge_approve/knowledge_approve_node.go

@@ -0,0 +1,31 @@
+package knowledge_approve
+
+import (
+	"encoding/json"
+	"eta_gn/eta_api/models/knowledge_approve"
+	"eta_gn/eta_api/models/knowledge_approve/response"
+	"fmt"
+)
+
+// FormatKnowledgeApproveNode2Item 格式化报告审批节点信息
+func FormatKnowledgeApproveNode2Item(origin *knowledge_approve.KnowledgeApproveNode) (item *response.KnowledgeApproveNodeItem, err error) {
+	if origin == nil {
+		return
+	}
+	item = new(response.KnowledgeApproveNodeItem)
+	item.KnowledgeApproveNodeId = origin.KnowledgeApproveNodeId
+	item.KnowledgeApproveFlowId = origin.KnowledgeApproveFlowId
+	item.PrevNodeId = origin.PrevNodeId
+	item.NextNodeId = origin.NextNodeId
+	item.NodeType = origin.NodeType
+	item.ApproveType = origin.ApproveType
+	item.Users = make([]*response.KnowledgeApproveNodeUser, 0)
+	if origin.Users != "" {
+		e := json.Unmarshal([]byte(origin.Users), &item.Users)
+		if e != nil {
+			err = fmt.Errorf("node users unmarshal err: %s", e.Error())
+			return
+		}
+	}
+	return
+}