Browse Source

Merge branch 'bzq/dev' of eta_mini/eta_mini_crm into debug

鲍自强 11 months ago
parent
commit
c8b4835208

+ 1 - 0
.gitignore

@@ -7,3 +7,4 @@ go.sum
 scheduler/etalogs/
 scheduler/conf/
 *_test.go
+/test/

+ 2 - 3
controllers/base_auth.go

@@ -11,7 +11,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/beego/beego/v2/client/orm"
 	"github.com/beego/beego/v2/server/web"
 )
 
@@ -43,7 +42,7 @@ func (c *BaseAuthController) Prepare() {
 
 			session, err := models.GetSysSessionByToken(token)
 			if err != nil {
-				if err == orm.ErrNoRows {
+				if err.Error() == utils.ErrNoRow() {
 					c.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "Token 信息已变更:Token: " + token}, false, false)
 					c.StopRun()
 					return
@@ -70,7 +69,7 @@ func (c *BaseAuthController) Prepare() {
 			}
 			sysUser, err := models.GetSysUserById(session.SysUserId)
 			if err != nil {
-				if err == orm.ErrNoRows {
+				if err.Error() == utils.ErrNoRow() {
 					c.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "获取sysUser信息失败: " + strconv.Itoa(session.SysUserId)}, false, false)
 					c.StopRun()
 					return

+ 568 - 0
controllers/report_pdf.go

@@ -0,0 +1,568 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_mini_crm/models"
+	"eta/eta_mini_crm/models/request"
+	"eta/eta_mini_crm/models/response"
+	"eta/eta_mini_crm/services"
+	"eta/eta_mini_crm/utils"
+	"os"
+	"path"
+	"strings"
+	"time"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type ReportPdfController struct {
+	BaseAuthController
+}
+
+// Author
+// @Title 获取报告作者接口
+// @Description 获取报告作者
+// @Success 200 {object} models.ReportAuthorResp
+// @router /author [get]
+func (this *ReportPdfController) Author() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	items, err := models.GetReportAuthorList()
+	if err != nil {
+		br.Msg = "获取失败!"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = items
+}
+
+// Add
+// @Title 添加研报
+// @Description 添加研报
+// @Param	request	body request.ReportPdfAddReq true "type json string"
+// @Success 200 {object} models.ReportAuthorResp
+// @router /add [post]
+func (this *ReportPdfController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req request.ReportPdfAddReq
+	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数解析失败"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyIdFirst <= 0 {
+		br.Msg = "请选择研报所属的一级分类"
+		return
+	}
+	if req.ClassifyIdSecond <= 0 {
+		br.Msg = "请选择研报所属的二级分类"
+		return
+	}
+
+	nameFirst, err := models.GetClassifyById(req.ClassifyIdFirst)
+	if err != nil {
+		br.Msg = "添加失败"
+		br.ErrMsg = "一级类名获取失败,Err:" + err.Error()
+		return
+	}
+	nameSecond, err := models.GetClassifyById(req.ClassifyIdSecond)
+	if err != nil {
+		br.Msg = "添加失败"
+		br.ErrMsg = "二级类名获取失败,Err:" + err.Error()
+		return
+	}
+
+	pdf := &models.ReportPdf{
+		PdfUrl:             req.PdfUrl,
+		Title:              req.Title,
+		Author:             req.Author,
+		Abstract:           req.Abstract,
+		ClassifyIdFirst:    req.ClassifyIdFirst,
+		ClassifyNameFirst:  nameFirst.ClassifyName,
+		ClassifyIdSecond:   req.ClassifyIdSecond,
+		ClassifyNameSecond: nameSecond.ClassifyName,
+		PublishTime:        time.Now(),
+		ModifyTime:         time.Now(),
+		SysUserId:          this.SysUser.SysUserId,
+		SysRealName:        this.SysUser.SysRealName,
+		State:              utils.ReportStatusUp,
+	}
+	err = pdf.Add()
+	if err != nil {
+		br.Msg = "添加失败"
+		br.ErrMsg = "pdf研报新增失败,Err:" + err.Error()
+		return
+	}
+
+	br.Msg = "添加成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// @Title 上传pdf研报
+// @Description 上传pdf研报
+// @Param   File   query   file  true       "文件"
+// @Success 200 {object} models.ReportAuthorResp
+// @router /uploadPdf [post]
+func (this *ReportPdfController) UploadPdf() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	f, h, err := this.GetFile("File")
+	if err != nil {
+		br.Msg = "获取资源信息失败"
+		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
+		return
+	}
+	defer f.Close()
+
+	ext := path.Ext(h.Filename)
+	dateDir := time.Now().Format("20060102")
+	uploadDir := utils.STATIC_DIR + "dongwu/" + dateDir
+	err = os.MkdirAll(uploadDir, utils.DIR_MOD)
+	if err != nil {
+		br.Msg = "存储目录创建失败"
+		br.ErrMsg = "存储目录创建失败,Err:" + err.Error()
+		return
+	}
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName := randStr + ext
+	fpath := uploadDir + "/" + fileName
+	err = this.SaveToFile("File", fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	pdfUploadDir := utils.RESOURCE_DIR + "pdf/"
+	savePdfToOssPath := pdfUploadDir + time.Now().Format("200601/20060102/")
+	pptName := utils.GetRandStringNoSpecialChar(28)
+	savePdfToOssPath += pptName + ".pdf"
+
+	defer func() {
+		_ = os.Remove(fpath)
+	}()
+
+	ossClient := services.NewOssClient()
+	if ossClient == nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "初始化OSS服务失败"
+		return
+	}
+	pdfUrl, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+
+	base := path.Base(h.Filename)
+	resp := new(response.ReportPdfUploadResp)
+	resp.Url = pdfUrl
+	resp.FileName = base[:len(base)-len(ext)]
+
+	br.Data = resp
+	br.Msg = "上传成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// List
+// @Title pdf研报列表
+// @Description pdf研报列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ClassifyIds   query   string  true       "二级分类id,可多选用英文,隔开"
+// @Param   State   query   int  true       "研报状态, 1:已发布 2:未发布"
+// @Param   PublishStartDate   query   string  true       "发布开始时间"
+// @Param   PublishEndDate   query   string  true       "发布结束时间"
+// @Param   ModifyStartDate   query   string  true       "更新开始时间"
+// @Param   ModifyEndDate   query   string  true       "更新结束时间"
+// @Param   KeyWord   query   string  true       "报告标题/创建人"
+// @Param   SortParam   query   string  true       "排序字段"
+// @Param   SortType   query   string  true       "排序方式"
+// @Success 200 {object} models.ReportAuthorResp
+// @router /list [get]
+func (this *ReportPdfController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	classifyIds := this.GetString("ClassifyIds")
+	state, _ := this.GetInt("State")
+	publishStartDate := this.GetString("PublishStartDate")
+	publishEndDate := this.GetString("PublishEndDate")
+	modifyStartDate := this.GetString("ModifyStartDate")
+	modifyEndDate := this.GetString("ModifyEndDate")
+	keyWord := this.GetString("KeyWord")
+	sortParam := this.GetString("SortParam")
+	sortType := this.GetString("SortType")
+
+	var condition string
+	var pars []interface{}
+
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	if classifyIds != "" {
+		classifyArr := strings.Split(classifyIds, ",")
+		condition += " AND classify_id_second in (" + utils.GetOrmReplaceHolder(len(classifyArr)) + ")"
+		pars = append(pars, classifyArr)
+	}
+
+	switch state {
+	case utils.ReportStatusUp:
+		condition += " AND state = ?"
+		pars = append(pars, state)
+	case utils.ReportStatusDown:
+		condition += " AND state = ?"
+		pars = append(pars, state)
+	}
+
+	if publishStartDate != "" && publishEndDate != "" {
+		condition += " AND publish_time >= ?"
+		publishStartTime, err := time.Parse(utils.FormatDate, publishStartDate)
+		if err != nil {
+			br.Msg = "日期格式有误"
+			br.ErrMsg = "日期格式有误,Err:" + err.Error()
+			return
+		}
+		publishStartDateStr := publishStartTime.Format(utils.FormatDateTime)
+		pars = append(pars, publishStartDateStr)
+
+		condition += " AND publish_time <= ?"
+		publishEndTime, err := time.Parse(utils.FormatDate, publishEndDate)
+		if err != nil {
+			br.Msg = "日期格式有误"
+			br.ErrMsg = "日期格式有误,Err:" + err.Error()
+			return
+		}
+		publishEndTime = publishEndTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
+		publishEndDateStr := publishEndTime.Format(utils.FormatDateTime)
+		pars = append(pars, publishEndDateStr)
+	}
+	if modifyStartDate != "" && modifyEndDate != "" {
+		condition += " AND modify_time >= ?"
+		modifyStartTime, err := time.Parse(utils.FormatDate, modifyStartDate)
+		if err != nil {
+			br.Msg = "日期格式有误"
+			br.ErrMsg = "日期格式有误,Err:" + err.Error()
+			return
+		}
+		modifyStartDateStr := modifyStartTime.Format(utils.FormatDateTime)
+		pars = append(pars, modifyStartDateStr)
+
+		condition += " AND modify_time <= ?"
+		modifyEndTime, err := time.Parse(utils.FormatDate, modifyEndDate)
+		if err != nil {
+			br.Msg = "日期格式有误"
+			br.ErrMsg = "日期格式有误,Err:" + err.Error()
+			return
+		}
+		modifyEndTime = modifyEndTime.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
+		modifyEndDateStr := modifyEndTime.Format(utils.FormatDateTime)
+		pars = append(pars, modifyEndDateStr)
+	}
+	if keyWord != "" {
+		condition += ` AND (title like ? OR sys_real_name like ?) `
+		pars = utils.GetLikeKeywordPars(pars, keyWord, 2)
+	}
+	var sortCondition string
+	if sortParam != "" && sortType != "" {
+		sortCondition = " ORDER BY "
+		var param, sort string
+		switch sortParam {
+		case "PublishTime":
+			param = "publish_time"
+		case "ModifyTime":
+			param = "modify_time"
+		}
+		switch sortType {
+		case "asc":
+			sort = " ASC "
+		case "desc":
+			sort = " DESC "
+		}
+		if param != "" && sort != "" {
+			sortCondition += param + " " + sort
+		} else {
+			sortCondition = ""
+		}
+	}
+	if sortCondition == "" {
+		sortCondition = ` ORDER BY modify_time DESC `
+	}
+
+	total, err := models.GetReportPdfCountByCondition(condition, pars)
+	if err != nil {
+		br.Msg = "获取研报列表失败"
+		br.ErrMsg = "获取研报列表统计失败,Err:" + err.Error()
+		return
+	}
+
+	startSize := utils.StartIndex(currentIndex, pageSize)
+	reportList, err := models.GetReportPdfByCondition(condition, sortCondition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取研报列表失败"
+		br.ErrMsg = "获取研报列表失败,Err:" + err.Error()
+		return
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(response.ReportPdfListResp)
+	resp.List = reportList
+	resp.Paging = page
+
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+	br.Msg = "获取成功"
+}
+
+// Edit
+// @Title 编辑研报
+// @Description 编辑研报
+// @Param	request	body request.ReportPdfEditReq true "type json string"
+// @Success 200 {object} models.ReportAuthorResp
+// @router /edit [post]
+func (this *ReportPdfController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req request.ReportPdfEditReq
+	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyIdFirst <= 0 {
+		br.Msg = "请选择研报所属的一级分类"
+		return
+	}
+	if req.ClassifyIdSecond <= 0 {
+		br.Msg = "请选择研报所属的二级分类"
+		return
+	}
+	if req.PdfUrl == "" {
+		br.Msg = "请上传研报文件"
+		return
+	}
+	reportPdf, err := models.GetReportPdfById(req.ReportPdfId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "研报不存在或已删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取研报失败"
+		br.ErrMsg = "获取研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	nameFirst, err := models.GetClassifyById(req.ClassifyIdFirst)
+	if err != nil {
+		br.Msg = "文件编辑失败"
+		br.ErrMsg = "一级类名获取失败,Err:" + err.Error()
+		return
+	}
+	nameSecond, err := models.GetClassifyById(req.ClassifyIdSecond)
+	if err != nil {
+		br.Msg = "文件编辑失败"
+		br.ErrMsg = "二级类名获取失败,Err:" + err.Error()
+		return
+	}
+	if reportPdf.Title != req.Title || reportPdf.ClassifyIdFirst != req.ClassifyIdFirst || reportPdf.ClassifyIdSecond != req.ClassifyIdSecond || reportPdf.Author != req.Author || reportPdf.Abstract != req.Abstract || reportPdf.PdfUrl != req.PdfUrl {
+		reportPdf.Title = req.Title
+		reportPdf.ClassifyIdFirst = req.ClassifyIdFirst
+		reportPdf.ClassifyIdSecond = req.ClassifyIdSecond
+		reportPdf.ClassifyNameFirst = nameFirst.ClassifyName
+		reportPdf.ClassifyNameSecond = nameSecond.ClassifyName
+		reportPdf.Author = req.Author
+		reportPdf.Abstract = req.Abstract
+		reportPdf.PdfUrl = req.PdfUrl
+		reportPdf.ModifyTime = time.Now()
+		err = reportPdf.Update([]string{"title", "classify_id_first", "classify_id_second", "classify_name_first", "classify_name_second", "author", "abstract", "pdf_url", "modify_time"})
+		if err != nil {
+			br.Msg = "文件更新失败"
+			br.ErrMsg = "文件更新失败,Err:" + err.Error()
+			return
+		}
+	}
+	br.Msg = "研报编辑成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Publish
+// @Title 发布研报
+// @Description 发布研报
+// @Param   ReportPdfId   query   string  true       "pdf研报id"
+// @Success 200 {object} models.BaseResponse
+// @router /publish [get]
+func (this *ReportPdfController) Publish() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	ReportPdfId, _ := this.GetInt("ReportPdfId")
+	reportPdf, err := models.GetReportPdfById(ReportPdfId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "研报不存在或已删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取研报失败"
+		br.ErrMsg = "获取研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+	if reportPdf.State == utils.ReportStatusUp {
+		br.Msg = "研报已发布"
+		return
+	}
+	reportPdf.State = utils.ReportStatusUp
+	reportPdf.PublishTime = time.Now()
+	err = reportPdf.Update([]string{"state", "publish_time"})
+	if err != nil {
+		br.Msg = "发布研报失败"
+		br.ErrMsg = "发布研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+	br.Msg = "发布研报成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// PublishCancel
+// @Title 取消发布研报
+// @Description 取消发布研报
+// @Param   ReportPdfId   query   string  true       "pdf研报id"
+// @Success 200 {object} models.BaseResponse
+// @router /publishCancel [get]
+func (this *ReportPdfController) PublishCancel() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	ReportPdfId, _ := this.GetInt("ReportPdfId")
+	reportPdf, err := models.GetReportPdfById(ReportPdfId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "研报不存在或已删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取研报失败"
+		br.ErrMsg = "获取研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+	if reportPdf.State == utils.ReportStatusDown {
+		br.Msg = "研报已撤销"
+		return
+	}
+	reportPdf.State = utils.ReportStatusDown
+	err = reportPdf.Update([]string{"state"})
+	if err != nil {
+		br.Msg = "发布研报失败"
+		br.ErrMsg = "发布研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+	br.Msg = "撤销研报成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// delete
+// @Title 删除研报
+// @Description 删除研报
+// @Param   ReportPdfId   query   string  true       "pdf研报id"
+// @Success 200 {object} models.BaseResponse
+// @router /delete [get]
+func (this *ReportPdfController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	ReportPdfId, _ := this.GetInt("ReportPdfId")
+	reportPdf, err := models.GetReportPdfById(ReportPdfId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "研报不存在或已删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取研报失败"
+		br.ErrMsg = "获取研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+	if reportPdf.State == utils.ReportStatusUp {
+		br.Msg = "研报已发布,不可以删除"
+		return
+	}
+
+	reportPdf.State = utils.ReportStatusDown
+	err = reportPdf.Delete()
+	if err != nil {
+		br.Msg = "研报删除失败"
+		br.ErrMsg = "研报删除失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Msg = "删除研报成功"
+	br.Ret = 200
+	br.Success = true
+}
+
+// Detail
+// @Title 研报详情
+// @Description 研报详情
+// @Param   ReportPdfId   query   string  true       "pdf研报id"
+// @Success 200 {object} models.BaseResponse
+// @router /detail [get]
+func (this *ReportPdfController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	ReportPdfId, _ := this.GetInt("ReportPdfId")
+	reportPdf, err := models.GetReportPdfById(ReportPdfId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "研报不存在或已删除,请刷新页面"
+			return
+		}
+		br.Msg = "获取研报失败"
+		br.ErrMsg = "获取研报失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Data = reportPdf
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取研报成功"
+}

+ 2 - 2
controllers/sys_role.go

@@ -116,7 +116,7 @@ func (this *SysRoleController) Delete() {
 
 	role, err := models.GetSysRoleById(req.SysRoleId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "角色不存在, 请刷新页面"
 			return
 		}
@@ -230,7 +230,7 @@ func (this *SysRoleController) Edit() {
 
 	sysRole, err := models.GetSysRoleById(req.SysRoleId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "角色不存在,请刷新页面"
 			return
 		}

+ 5 - 5
controllers/sys_user.go

@@ -79,7 +79,7 @@ func (this *SysUserController) Add() {
 	}
 	_, err = models.GetSysDepartmentById(req.SysDepartmentId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "所选部门不存在"
 			return
 		}
@@ -90,7 +90,7 @@ func (this *SysUserController) Add() {
 
 	sysRole, err := models.GetSysRoleById(req.SysRoleId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "所选角色不存在"
 			return
 		}
@@ -233,7 +233,7 @@ func (this *SysUserController) Edit() {
 
 	sysUser, err := models.GetSysUserById(req.SysUserId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "用户不存在,请刷新页面"
 			return
 		}
@@ -275,7 +275,7 @@ func (this *SysUserController) Edit() {
 	var roleName string
 	roleItem, err := models.GetSysRoleById(req.SysRoleId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "角色不存在,请重新选择"
 			br.ErrMsg = "角色不存在"
 			return
@@ -452,7 +452,7 @@ func (this *SysUserController) ResetPass() {
 	}
 	sysUser, err := models.GetSysUserById(req.SysUserId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "用户已被删除, 请刷新页面"
 			return
 		}

+ 3 - 3
controllers/user.go

@@ -284,7 +284,7 @@ func (this *UserController) Edit() {
 
 	user, err := models.GetUserById(req.UserId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "用户不存在或已删除,请重新刷新页面"
 			br.ErrMsg = "用户不存在或已删除,请重新刷新页面,Err:" + err.Error()
 			return
@@ -924,7 +924,7 @@ func (this *UserController) PotentialEdit() {
 
 	user, err := models.GetUserById(req.UserId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "用户不存在或已删除,请重新刷新页面"
 			br.ErrMsg = "用户不存在或已删除,请重新刷新页面,Err:" + err.Error()
 			return
@@ -992,7 +992,7 @@ func (this *UserController) Detail() {
 	}
 	user, err := models.GetUserViewById(UserId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "用户不存在或已删除,请刷新页面"
 			return
 		}

+ 1 - 3
controllers/user_login.go

@@ -8,8 +8,6 @@ import (
 	"eta/eta_mini_crm/utils"
 	"fmt"
 	"time"
-
-	"github.com/beego/beego/v2/client/orm"
 )
 
 type UserLoginController struct {
@@ -46,7 +44,7 @@ func (this *UserLoginController) Login() {
 	}
 	sysUser, err := models.GetSysUserBySysUserName(req.UserName)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "登录失败, 账号或密码错误"
 			return
 		} else {

+ 4 - 5
controllers/user_read_record.go

@@ -9,7 +9,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
 )
 
@@ -53,7 +52,7 @@ func (this *UserReadRecordController) List() {
 	registerEndDate := this.GetString("RegisterEndDate")
 	createStartDate := this.GetString("CreateStartDate")
 	createEndDate := this.GetString("CreateEndDate")
-	sortParma := this.GetString("SortParam")
+	sortParam := this.GetString("SortParam")
 	sortType := this.GetString("SortType")
 
 	var condition string
@@ -90,10 +89,10 @@ func (this *UserReadRecordController) List() {
 			condition += `) `
 		}
 	}
-	if sortParma != "" && sortType != "" {
+	if sortParam != "" && sortType != "" {
 		sortCondition = " ORDER BY "
 		var param, sort string
-		switch sortParma {
+		switch sortParam {
 		case "LastUpdateTime":
 			param = "last_update_time"
 		case "ReadCnt":
@@ -251,7 +250,7 @@ func (this *UserReadRecordController) Detail() {
 	startSize := utils.StartIndex(currentIndex, pageSize)
 	user, err := models.GetUserById(UserId)
 	if err != nil {
-		if err == orm.ErrNoRows {
+		if err.Error() == utils.ErrNoRow() {
 			br.Msg = "用户不存在或已删除,请刷新页面"
 			return
 		}

+ 10 - 2
go.mod

@@ -3,13 +3,15 @@ module eta/eta_mini_crm
 go 1.21
 
 require (
+	github.com/aliyun/alibaba-cloud-sdk-go v1.62.789
+	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
+	github.com/aws/aws-sdk-go v1.54.18
 	github.com/beego/bee/v2 v2.1.0
 	github.com/beego/beego/v2 v2.1.0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/go-sql-driver/mysql v1.7.0
 	github.com/rdlucklib/rdluck_tools v1.0.3
-	github.com/robfig/cron/v3 v3.0.1
 )
 
 require (
@@ -18,9 +20,13 @@ require (
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
-	github.com/kr/text v0.2.0 // indirect
+	github.com/jmespath/go-jmespath v0.4.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.15.1 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
@@ -31,6 +37,8 @@ require (
 	golang.org/x/net v0.7.0 // indirect
 	golang.org/x/sys v0.6.0 // indirect
 	golang.org/x/text v0.7.0 // indirect
+	golang.org/x/time v0.5.0 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect
+	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 7 - 0
models/classify.go

@@ -35,3 +35,10 @@ func GetClassifyList() (items []*ClassifyView, err error) {
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
 }
+
+func GetClassifyById(classifyId int) (item *ClassifyView, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM classify WHERE enabled=1 AND id=?`
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}

+ 1 - 0
models/db.go

@@ -39,5 +39,6 @@ func init() {
 		new(SysMessageReport),
 		new(CrmConfig),
 		new(UserChangeRecord),
+		new(ReportPdf),
 	)
 }

+ 26 - 0
models/report_author.go

@@ -0,0 +1,26 @@
+package models
+
+import (
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type ReportAuthor struct {
+	Id           int       `orm:"column(id)" description:"报告作者ID"`
+	ReportAuthor string    `description:"报告作者名称"`
+	AuthorType   int       `description:"类型,1:中文;2:英文"`
+	Enable       int       `description:"是否启用,0:禁用,1:启用"`
+	IsDelete     int       `description:"是否删除,0:未删除,1:已删除"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"更新时间"`
+}
+
+// GetReportAuthorList 获取报告作者列表
+func GetReportAuthorList() (items []*ReportAuthor, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+
+	sql := ` SELECT * FROM report_author WHERE is_delete=0 AND enable=1 ORDER BY id desc  `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 82 - 0
models/report_pdf.go

@@ -0,0 +1,82 @@
+package models
+
+import (
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type ReportPdf struct {
+	ReportPdfId        int       `orm:"pk" description:"id"`
+	PdfUrl             string    `description:"pdf文件URL"`
+	Title              string    `description:"pdf文件标题"`
+	Author             string    `description:"作者"`
+	Abstract           string    `description:"摘要"`
+	ClassifyIdFirst    int       `description:"一级分类id"`
+	ClassifyNameFirst  string    `description:"一级分类名称"`
+	ClassifyIdSecond   int       `description:"二级分类id"`
+	ClassifyNameSecond string    `description:"二级分类名称"`
+	Stage              int       `description:"期数"`
+	PublishTime        time.Time `description:"发布时间"`
+	ModifyTime         time.Time `description:"更新时间"`
+	Pv                 int       `description:"pv"`
+	Uv                 int       `description:"uv"`
+	SysUserId          int       `description:"创建人id"`
+	SysRealName        string    `description:"创建人姓名"`
+	State              int       `description:"状态"`
+}
+
+func (r *ReportPdf) Add() (err error) {
+	o := orm.NewOrm()
+	// 计算研报期数
+	sql := `SELECT COUNT(*) + 1 AS count FROM report_pdf WHERE classify_id_second=?`
+	err = o.Raw(sql, r.ClassifyIdSecond).QueryRow(&r.Stage)
+	if err != nil {
+		return
+	}
+	_, err = o.Insert(r)
+	return
+}
+
+func (r *ReportPdf) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(r, cols...)
+	return
+}
+
+func (r *ReportPdf) Delete() (err error) {
+	o := orm.NewOrm()
+	_, err = o.Delete(r)
+	return
+}
+
+func GetReportPdfCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(*) AS count FROM report_pdf WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetReportPdfByCondition(condition, sortCondition string, pars []interface{}, startPage, pageSize int) (items []*ReportPdf, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM report_pdf WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	if sortCondition != "" {
+		sql += sortCondition // 排序
+	}
+	sql += ` LIMIT ?,?`
+	_, err = o.Raw(sql, pars, startPage, pageSize).QueryRows(&items)
+	return
+}
+
+func GetReportPdfById(id int) (item *ReportPdf, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM report_pdf WHERE report_pdf_id=?`
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}

+ 20 - 0
models/request/report_pdf.go

@@ -0,0 +1,20 @@
+package request
+
+type ReportPdfAddReq struct {
+	PdfUrl           string `description:"pdf文件URL"`
+	Title            string `description:"标题"`
+	Author           string `description:"作者"`
+	Abstract         string `description:"摘要"`
+	ClassifyIdFirst  int    `description:"一级分类id"`
+	ClassifyIdSecond int    `description:"二级分类id"`
+}
+
+type ReportPdfEditReq struct {
+	ReportPdfId      int    `description:"id"`
+	PdfUrl           string `description:"pdf文件URL"`
+	Title            string `description:"标题"`
+	Author           string `description:"作者"`
+	Abstract         string `description:"摘要"`
+	ClassifyIdFirst  int    `description:"一级分类id"`
+	ClassifyIdSecond int    `description:"二级分类id"`
+}

+ 17 - 0
models/response/report_pdf.go

@@ -0,0 +1,17 @@
+package response
+
+import (
+	"eta/eta_mini_crm/models"
+
+	"github.com/rdlucklib/rdluck_tools/paging"
+)
+
+type ReportPdfListResp struct {
+	List   []*models.ReportPdf
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+type ReportPdfUploadResp struct {
+	Url      string `description:"pdf文件URL"`
+	FileName string `description:"pdf文件名称"`
+}

+ 1 - 0
models/user_read_record.go

@@ -24,6 +24,7 @@ type UserReadRecord struct {
 	CreateDate          string    `description:"创建日期"`
 	StayTime            string    `description:"停留时间"`
 	StayTimestamp       string    `description:"停留时间戳"`
+	ReportType          int       `description:"报告类型:1-普通研报;2-pdf研报"`
 }
 
 type ReadCntStaitc struct {

+ 81 - 0
routers/commentsRouter.go

@@ -25,6 +25,87 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "Author",
+            Router: `/author`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/delete`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "Publish",
+            Router: `/publish`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "PublishCancel",
+            Router: `/publishCancel`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:ReportPdfController"],
+        beego.ControllerComments{
+            Method: "UploadPdf",
+            Router: `/uploadPdf`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:SellerController"] = append(beego.GlobalControllerRouter["eta/eta_mini_crm/controllers:SellerController"],
         beego.ControllerComments{
             Method: "List",

+ 5 - 0
routers/router.go

@@ -62,6 +62,11 @@ func init() {
 				&controllers.UserReadRecordController{},
 			),
 		),
+		beego.NSNamespace("/report_pdf",
+			beego.NSInclude(
+				&controllers.ReportPdfController{},
+			),
+		),
 	)
 	beego.AddNamespace(ns)
 }

+ 5 - 3
scheduler/task.go

@@ -53,9 +53,11 @@ func ModifyUserStatus(ctx context.Context) (err error) {
 		record.CreateTime = time.Now()
 		userRecordList = append(userRecordList, record)
 	}
-	err = models.UserChangeRecordMultiInsert(userRecordList)
-	if err != nil {
-		return
+	if len(userRecordList) > 0 {
+		err = models.UserChangeRecordMultiInsert(userRecordList)
+		if err != nil {
+			return
+		}
 	}
 	return
 }

+ 199 - 0
services/oss.go

@@ -0,0 +1,199 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"eta/eta_mini_crm/utils"
+	"fmt"
+	"time"
+
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
+)
+
+type STSToken struct {
+	AccessKeyId     string
+	AccessKeySecret string
+	SecurityToken   string
+	ExpiredTime     string
+	RegionId        string
+	Bucketname      string
+	Endpoint        string
+	Imghost         string
+}
+
+type OssClient interface {
+	UploadFile(string, string, string) (string, error)
+	GetUploadToken() (OssToken, error)
+}
+
+func NewOssClient() OssClient {
+	// 默认使用阿里云OSS
+	return new(AliOss)
+}
+
+// OssToken 此处为了兼容前端那边所以有重复的
+type OssToken struct {
+	AccessKeyId string
+	SecretKeyId string
+	RegionId    string
+	Bucketname  string
+	Endpoint    string
+	ImgHost     string
+	UseSSL      string
+	Port        string
+	//AccessKeyId     string
+	AccessKeySecret string
+	SecurityToken   string
+	ExpiredTime     string
+	//RegionId        string
+	//Bucketname      string
+	//Endpoint        string
+	Imghost      string
+	S3ForceStyle bool
+	S3Protocol   string
+}
+
+// GetOssSTSToken 获取STSToken
+func GetOssSTSToken() (item *STSToken, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info(err.Error())
+		}
+	}()
+	item = new(STSToken)
+	// 获取缓存中的Token
+	recent, _ := utils.Rc.RedisString(utils.STSTokenCacheKey)
+	if recent != "" {
+		lastToken := new(STSToken)
+		if e := json.Unmarshal([]byte(recent), &lastToken); e != nil {
+			err = errors.New("GetOssSTSToken lastToken Unmarshal Err: " + e.Error())
+			return
+		}
+		// 未防止正在上传大文件时Token过期, 将判定的过期时间提前10分钟
+		afterTime := time.Now().Local().Add(10 * time.Minute)
+		expired, e := time.ParseInLocation(utils.FormatDateTime, lastToken.ExpiredTime, time.Local)
+		if e != nil {
+			err = errors.New("GetOssSTSToken expiredTime Parse Err: " + e.Error())
+			return
+		}
+		if expired.After(afterTime) {
+			item.AccessKeyId = lastToken.AccessKeyId
+			item.AccessKeySecret = lastToken.AccessKeySecret
+			item.SecurityToken = lastToken.SecurityToken
+			item.ExpiredTime = lastToken.ExpiredTime
+			item.RegionId = utils.RegionId
+			item.Bucketname = utils.Bucketname
+			item.Endpoint = utils.Imghost
+			item.Imghost = utils.Imghost
+			return
+		}
+	}
+	// 已过期则获取新的token
+	newToken, e := NewSTSToken()
+	if e != nil {
+		err = errors.New("GetOssSTSToken NewSTSToken Err: " + e.Error())
+		return
+	}
+	newTokenJson, e := json.Marshal(newToken)
+	if e != nil {
+		err = errors.New("GetOssSTSToken NewToken JSON Err: " + e.Error())
+		return
+	}
+	// 覆盖缓存
+	if e := utils.Rc.Put(utils.STSTokenCacheKey, newTokenJson, time.Hour); e != nil {
+		err = errors.New("GetOssSTSToken SetRedis Err: " + e.Error())
+		return
+	}
+	item = newToken
+	return
+}
+
+// NewSTSToken 获取一个新的STSToken
+func NewSTSToken() (item *STSToken, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info(err.Error())
+		}
+	}()
+	item = new(STSToken)
+	client, e := sts.NewClientWithAccessKey("cn-shanghai", utils.RAMAccessKeyId, utils.RAMAccessKeySecret)
+	if e != nil {
+		err = errors.New("NewSTSToken NewClient Err: " + e.Error())
+		return
+	}
+	request := sts.CreateAssumeRoleRequest()
+	request.Scheme = utils.AliStsScheme
+	request.RegionId = utils.RegionId
+	request.RoleArn = utils.RoleArn
+	now := time.Now().Format(utils.FormatDateTimeUnSpace)
+	request.RoleSessionName = utils.RoleSessionName + now
+	request.DurationSeconds = "3600"
+	request.ConnectTimeout = 300 * time.Second
+	request.ReadTimeout = 300 * time.Second
+
+	response, e := client.AssumeRole(request)
+	if e != nil {
+		err = errors.New("NewSTSToken AssumeRole Err: " + e.Error())
+		return
+	}
+	if response != nil {
+		item.AccessKeyId = response.Credentials.AccessKeyId
+		item.AccessKeySecret = response.Credentials.AccessKeySecret
+		item.SecurityToken = response.Credentials.SecurityToken
+		t, _ := time.Parse(time.RFC3339, response.Credentials.Expiration)
+		expiration := t.In(time.Local)
+		item.ExpiredTime = expiration.Format(utils.FormatDateTime)
+		item.RegionId = utils.RegionId
+		item.Bucketname = utils.Bucketname
+		item.Endpoint = utils.Imghost
+		item.Imghost = utils.Imghost
+	}
+	return
+}
+
+type AliOss struct{}
+
+// UploadFile 上传文件
+func (m *AliOss) UploadFile(fileName, filePath, savePath string) (string, error) {
+	if utils.AccessKeyId == `` {
+		return "0", errors.New("阿里云信息未配置")
+	}
+	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+	if err != nil {
+		return "1", err
+	}
+	bucket, err := client.Bucket(utils.Bucketname)
+	if err != nil {
+		return "2", err
+	}
+
+	path := savePath
+	if savePath == "" {
+		path = utils.UploadDir + time.Now().Format("200601/20060102/") + fileName
+	}
+	err = bucket.PutObjectFromFile(path, filePath)
+	if err != nil {
+		return "3", err
+	}
+	resourceUrl := utils.Imghost + path
+	return resourceUrl, err
+}
+
+func (m *AliOss) GetUploadToken() (token OssToken, err error) {
+	stsToken, e := GetOssSTSToken()
+	if e != nil {
+		err = fmt.Errorf("GetOssSTSToken err: %s", e.Error())
+		return
+	}
+	token.AccessKeyId = stsToken.AccessKeyId
+	token.AccessKeySecret = stsToken.AccessKeySecret
+	token.SecurityToken = stsToken.SecurityToken
+	token.ExpiredTime = stsToken.ExpiredTime
+	token.RegionId = stsToken.RegionId
+	token.Bucketname = stsToken.Bucketname
+	token.Endpoint = stsToken.Endpoint
+	token.Imghost = stsToken.Imghost
+	return
+}

+ 32 - 0
utils/common.go

@@ -3,10 +3,16 @@ package utils
 import (
 	"crypto/md5"
 	"encoding/hex"
+	"math/rand"
 	"regexp"
 	"strconv"
+	"strings"
+	"time"
 )
 
+// 随机种子
+var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+
 func MD5(data string) string {
 	m := md5.Sum([]byte(data))
 	return hex.EncodeToString(m[:])
@@ -64,3 +70,29 @@ func StringsToJSON(str string) string {
 	}
 	return jsons
 }
+
+// 数据没有记录
+func ErrNoRow() string {
+	return "<QuerySeter> no row found"
+}
+
+func GetRandStringNoSpecialChar(size int) string {
+	allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
+	randomSb := ""
+	digitSize := len(allLetterDigit)
+	for i := 0; i < size; i++ {
+		randomSb += allLetterDigit[rnd.Intn(digitSize)]
+	}
+	return randomSb
+}
+
+func GetOrmReplaceHolder(num int) string {
+	var stringBuffer strings.Builder
+	for i := 0; i < num; i++ {
+		stringBuffer.WriteString("?")
+		if i != num-1 {
+			stringBuffer.WriteString(",")
+		}
+	}
+	return stringBuffer.String()
+}

+ 62 - 0
utils/config.go

@@ -17,7 +17,37 @@ var (
 	Rc          RedisClient //redis缓存
 )
 
+// 阿里云配置
 var (
+	Bucketname       string
+	Endpoint         string
+	Imghost          string
+	UploadDir        string
+	Upload_Audio_Dir string
+	AccessKeyId      string
+	AccessKeySecret  string
+)
+
+// 阿里云oss前端上传用
+var (
+	AliStsScheme       string
+	RegionId           string
+	RoleArn            string
+	RoleSessionName    string
+	RAMAccessKeyId     string
+	RAMAccessKeySecret string
+	STSTokenCacheKey   string
+)
+
+// 基础配置
+var (
+	STATIC_DIR   string
+	RESOURCE_DIR string
+)
+
+var (
+	LogPath    string //调用过程中的日志存放地址
+	LogFile    string
 	ApiLogPath string // 接口请求地址和接口返回值日志存放地址
 	ApiLogFile string
 	BinLogPath string // 数据库相关的日志存放地址
@@ -60,6 +90,38 @@ func init() {
 	// 接口返回加密KEY
 	DesKey = config["des_key"]
 
+	// OSS相关
+	{
+		Endpoint = config["endpoint"]
+		Bucketname = config["bucket_name"]
+		Imghost = config["img_host"]
+		UploadDir = config["upload_dir"]
+		Upload_Audio_Dir = config["upload_audio_dir"]
+		AccessKeyId = config["access_key_id"]
+		AccessKeySecret = config["access_key_secret"]
+	}
+
+	// OSS相关(前端使用)
+	{
+		AliStsScheme = config["ali_sts_scheme"]
+		RegionId = config["region_id"]
+		RoleArn = config["role_arn"]
+		RoleSessionName = config["role_session_name"]
+		RAMAccessKeyId = config["ram_access_key_id"]
+		RAMAccessKeySecret = config["ram_access_key_secret"]
+		STSTokenCacheKey = config["sts_token_cache_key"]
+	}
+
+	// 静态文件目录
+	STATIC_DIR = config["static_dir"]
+	if STATIC_DIR == "" {
+		STATIC_DIR = "./static"
+	}
+	RESOURCE_DIR = config["resource_dir"]
+	if RESOURCE_DIR == "" {
+		RESOURCE_DIR = "dongwu/"
+	}
+
 	// 初始化缓存
 	redisClient, err := initRedis(config["redis_type"], config["beego_cache"])
 	if err != nil {

+ 11 - 0
utils/constants.go

@@ -1,5 +1,7 @@
 package utils
 
+import "io/fs"
+
 const (
 	UserLoginSalt = "MiQM9YUdf89T2uIH"         // 用户登录盐值
 	DesKeySalt    = "MxuqSoUrTAmyRd9fb0TtlrPk" // DesKey盐值
@@ -42,6 +44,9 @@ const (
 	MaxDepartmentLevel         = 3
 )
 
+// DIR_MOD 目录创建权限
+const DIR_MOD fs.FileMode = 0766 // Unix permission bits
+
 // 用户状态定义
 const (
 	UserStatusNo        = 0 //禁用
@@ -49,6 +54,12 @@ const (
 	UserStatusFormal    = 2 //正式用户
 )
 
+// Pdf研报状态定义
+const (
+	ReportStatusUp   = 1 // 研报已发布
+	ReportStatusDown = 2 // 研报未发布
+)
+
 // 免验证接口
 var NoAuthApiMap = map[string]bool{
 	"/role/menu/buttons":      true,

+ 27 - 2
utils/logs.go

@@ -11,14 +11,39 @@ import (
 const (
 	DefaultBinlogPath = "./etalogs/binlog"
 	DefaultApiLogPath = "./etalogs/apilog"
+	DefaultLogPath    = "./etalogs/filelog"
 )
 
 var (
-	BinLog *logs.BeeLogger
-	ApiLog *logs.BeeLogger
+	BinLog  *logs.BeeLogger
+	ApiLog  *logs.BeeLogger
+	FileLog *logs.BeeLogger
 )
 
 func init() {
+	if LogMaxDays == 0 {
+		LogMaxDays = 30
+	}
+	logPath := LogPath
+	if logPath == "" {
+		logPath = DefaultLogPath
+	}
+	logFile := LogFile
+	if logFile == "" {
+		logFile = "filelog.log"
+	}
+	os.MkdirAll(logPath, os.ModePerm)
+
+	// 打开文件
+	logFileName := path.Join(logPath, logFile)
+	FileLog = logs.NewLogger(1000000)
+	logConf := getDefaultLogConfig()
+
+	logConf.FileName = logFileName
+	b, _ := json.Marshal(logConf)
+	FileLog.SetLogger(logs.AdapterFile, string(b))
+	FileLog.EnableFuncCallDepth(true)
+
 	initApiLog()
 	initBinLog()
 }