浏览代码

init project

rdluck 4 年之前
当前提交
7fec4a8585

+ 20 - 0
conf/app.conf

@@ -0,0 +1,20 @@
+appname = hongze_admin
+httpport = 8602
+runmode = dev
+autorender = false
+copyrequestbody = true
+EnableDocs = true
+
+run_mode=release
+EnableAdmin = true
+AdminPort = 8700
+
+[debug]
+mysql_url = hongze_admin:hongze_2018@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/test_weekly_report?charset=utf8mb4&loc=Asia%2FShanghai
+mysql_url_rddp = hongze_admin:hongze_2018@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/test_hongze_rddp?charset=utf8mb4&loc=Asia%2FShanghai
+mysql_url_edb = hongze_admin:hongze_2018@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/edb?charset=utf8mb4&loc=Asia%2FShanghai
+
+[release]
+mysql_url = hongze_admin:hongze_2018@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/weekly_report?charset=utf8mb4&loc=Asia%2FShanghai
+mysql_url_rddp = hongze_admin:hongze_2018@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/hongze_rddp?charset=utf8mb4&loc=Asia%2FShanghai
+mysql_url_edb = hz_server:Hzinsights2015@tcp(rm-uf6c8yi6zdq6ea7p1qo.mysql.rds.aliyuncs.com:3306)/edb?charset=utf8mb4&loc=Asia%2FShanghai

+ 262 - 0
controllers/banner.go

@@ -0,0 +1,262 @@
+package controllers
+
+import (
+	"encoding/json"
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/services"
+	"hongze/hongze_admin/utils"
+	"os"
+	"path"
+	"time"
+)
+
+//banner
+type BannerController struct {
+	BaseAuthController
+}
+
+// @Title 新增banner接口
+// @Description 新增banner
+// @Param	request	body models.BannerAddReq true "type json string"
+// @Success 200 新增成功
+// @router /add [post]
+func (this *BannerController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.BannerAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	item := new(models.Banner)
+	item.ClassifyId = req.ClassifyId
+	item.ImageUrl = req.ImgUrl
+	item.BannerType = req.BannerType
+	item.CreateTime = time.Now()
+	item.ModifyTime = time.Now()
+	item.ClassifyName = req.ClassifyName
+	item.JumpUrl = req.JumpUrl
+	err = models.AddBanner(item)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// @Title 编辑banner接口
+// @Description 编辑banner
+// @Param	request	body models.BannerEditReq true "type json string"
+// @Success 200 新增成功
+// @router /edit [post]
+func (this *BannerController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.BannerEditReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	err = models.EditBanner(&req)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+}
+
+// @Title 删除轮播图
+// @Description 删除轮播图
+// @Param	request	body models.BannerDeleteReq true "type json string"
+// @Success 200 新增成功
+// @router /delete [post]
+func (this *BannerController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.BannerDeleteReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	err = models.DeleteBanner(req.BannerId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// @Title 获取分类接口
+// @Description 获取分类
+// @Success 200 {object} models.Classify
+// @router /getClassify [get]
+func (this *BannerController) GetClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	items, err := models.GetClassify()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = items
+}
+
+// @Title 获取分类接口
+// @Description 获取分类
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   BannerType   query   int  true       "分类:1:轮播图,2:头部海报"
+// @Param   KeyWord   query   string  true       "检索关键词"
+// @Success 200 {object} models.BannerListResp
+// @router /list [get]
+func (this *BannerController) ListBanner() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	bannerType, _ := this.GetInt("BannerType")
+	keyWord := this.GetString("KeyWord")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var condition string
+	var pars []interface{}
+
+	if bannerType > 0 {
+		condition = " AND banner_type=? "
+		pars = append(pars, bannerType)
+	}
+	if keyWord != "" {
+		condition += ` AND classify_name LIKE '%` + keyWord + `%'  `
+	}
+	total, err := models.GetBannerListCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetBannerList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	page := models.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.BannerListResp)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 图片上传
+// @Description 图片上传接口
+// @Param	request	body models.BannerDeleteReq true "type json string"
+// @Success 200 新增成功
+// @router /upload [post]
+func (this *BannerController) Upload() {
+	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
+	}
+	ext := path.Ext(h.Filename)
+	dateDir := time.Now().Format("20060102")
+	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
+	err = os.MkdirAll(uploadDir, 777)
+	if err != nil {
+		br.Msg = "存储目录创建失败"
+		br.ErrMsg = "存储目录创建失败,Err:" + err.Error()
+		return
+	}
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName := randStr + ext
+	fpath := uploadDir + "/" + fileName
+	defer f.Close() //关闭上传文件
+	err = this.SaveToFile("file", fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	//上传到阿里云
+	resourceUrl, err := services.UploadAliyun(fileName, fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+
+	defer func() {
+		os.Remove(fpath)
+	}()
+
+	item := new(models.Resource)
+	item.ResourceUrl = resourceUrl
+	item.ResourceType = 1
+	item.CreateTime = time.Now()
+	newId, err := models.AddResource(item)
+	if err != nil {
+		br.Msg = "资源上传失败"
+		br.ErrMsg = "资源上传失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.ResourceResp)
+	resp.Id = newId
+	resp.ResourceUrl = resourceUrl
+
+	br.Msg = "上传成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+	return
+}

+ 156 - 0
controllers/base_auth.go

@@ -0,0 +1,156 @@
+package controllers
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/astaxie/beego"
+
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/utils"
+
+	"rdluck_tools/log"
+)
+
+var apiLog *log.Log
+
+func init() {
+	apiLog = log.Init("20060102.api")
+}
+
+type BaseAuthController struct {
+	beego.Controller
+	SysUser *models.Admin
+}
+
+func (this *BaseAuthController) Prepare() {
+	fmt.Println("enter prepare")
+	method := this.Ctx.Input.Method()
+	uri := this.Ctx.Input.URI()
+	fmt.Println("Url:", uri)
+	if method != "HEAD" {
+		if method == "POST" || method == "GET" {
+			authorization := this.Ctx.Input.Header("Authorization")
+			fmt.Println("authorization:", authorization)
+			if authorization == "" {
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "请重新授权!", ErrMsg: "请重新授权:Token is empty or account is empty"}, false, false)
+				this.StopRun()
+				return
+			}
+			authorizationArr := strings.Split(authorization, ",")
+			tokenStr := authorizationArr[0]
+			tokenArr := strings.Split(tokenStr, "=")
+			token := tokenArr[1]
+
+			accountStr := authorizationArr[1]
+			accountArr := strings.Split(accountStr, "=")
+			account := accountArr[1]
+
+			fmt.Println("token:", token)
+			fmt.Println("account:", account)
+			//校验token是否合法
+			// JWT校验Token和Account
+			if !utils.CheckToken(account, token) {
+				fmt.Println("CheckToken Err")
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "鉴权失败,请重新登录!", ErrMsg: "登录失效,请重新登陆!,CheckToken Fail"}, false, false)
+				this.StopRun()
+				return
+			}
+
+			fmt.Println("GetUserByToken")
+			session, err := models.GetSysSessionByToken(token)
+			if err != nil {
+				if err.Error() == utils.ErrNoRow() {
+					this.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "Token 信息已变更:Token: " + token}, false, false)
+					this.StopRun()
+					return
+				}
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "获取用户信息异常,Eerr:" + err.Error()}, false, false)
+				this.StopRun()
+				return
+			}
+			if session == nil {
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "sesson is empty "}, false, false)
+				this.StopRun()
+				return
+			}
+			if time.Now().After(session.ExpiredTime) {
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "请重新登录!", ErrMsg: "获取用户信息异常,Eerr:" + err.Error()}, false, false)
+				this.StopRun()
+				return
+			}
+			admin, err := models.GetSysUserById(session.SysUserId)
+			if err != nil {
+				if err.Error() == utils.ErrNoRow() {
+					this.JSON(models.BaseResponse{Ret: 408, Msg: "信息已变更,请重新登陆!", ErrMsg: "获取admin 信息失败 " + strconv.Itoa(session.SysUserId)}, false, false)
+					this.StopRun()
+					return
+				}
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "获取admin信息异常,Eerr:" + err.Error()}, false, false)
+				this.StopRun()
+				return
+			}
+			if admin == nil {
+				this.JSON(models.BaseResponse{Ret: 408, Msg: "网络异常,请稍后重试!", ErrMsg: "admin is empty "}, false, false)
+				this.StopRun()
+				return
+			}
+
+			this.SysUser = admin
+		} else {
+			this.JSON(models.BaseResponse{Ret: 408, Msg: "请求异常,请联系客服!", ErrMsg: "POST之外的请求,暂不支持"}, false, false)
+			this.StopRun()
+			return
+		}
+	}
+}
+
+func (c *BaseAuthController) ServeJSON(encoding ...bool) {
+	var (
+		hasIndent   = false
+		hasEncoding = false
+	)
+	if beego.BConfig.RunMode == beego.PROD {
+		hasIndent = false
+	}
+	if len(encoding) > 0 && encoding[0] == true {
+		hasEncoding = true
+	}
+	if c.Data["json"] == nil {
+		go utils.SendEmail("异常提醒:", "接口:"+"URI:"+c.Ctx.Input.URI()+";无返回值", utils.EmailSendToUsers)
+		return
+	}
+	baseRes := c.Data["json"].(*models.BaseResponse)
+	if baseRes != nil && baseRes.Ret != 200 && baseRes.Ret != 408 {
+		body, _ := json.Marshal(baseRes)
+		go utils.SendEmail(utils.APPNAME+"失败提醒", "URI:"+c.Ctx.Input.URI()+"<br/> ErrMsg:"+baseRes.ErrMsg+";<br/>Msg:"+baseRes.Msg+";<br/> Body:"+string(body), utils.EmailSendToUsers)
+	}
+	c.JSON(c.Data["json"], hasIndent, hasEncoding)
+}
+
+func (c *BaseAuthController) JSON(data interface{}, hasIndent bool, coding bool) error {
+	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
+	var content []byte
+	var err error
+	if hasIndent {
+		content, err = json.MarshalIndent(data, "", "  ")
+	} else {
+		content, err = json.Marshal(data)
+	}
+	if err != nil {
+		http.Error(c.Ctx.Output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
+		return err
+	}
+	ip := c.Ctx.Input.IP()
+	requestBody, _ := url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+	apiLog.Println("请求地址:", c.Ctx.Input.URI(), "Authorization:", c.Ctx.Input.Header("Authorization"), "RequestBody:", requestBody, "ResponseBody", string(content), "IP:", ip)
+	if coding {
+		content = []byte(utils.StringsToJSON(string(content)))
+	}
+	return c.Ctx.Output.Body(content)
+}

+ 67 - 0
controllers/base_common.go

@@ -0,0 +1,67 @@
+package controllers
+
+import (
+	"encoding/json"
+	"net/http"
+	"net/url"
+
+	"github.com/astaxie/beego"
+
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/utils"
+)
+
+type BaseCommonController struct {
+	beego.Controller
+}
+
+func (this *BaseCommonController) Prepare() {
+	ip := this.Ctx.Input.IP()
+	requestBody, _ := url.QueryUnescape(string(this.Ctx.Input.RequestBody))
+	apiLog.Println("请求地址:", this.Ctx.Input.URI(), "RequestBody:", requestBody, "IP:", ip)
+}
+
+func (c *BaseCommonController) ServeJSON(encoding ...bool) {
+	var (
+		hasIndent   = false
+		hasEncoding = false
+	)
+	if beego.BConfig.RunMode == beego.PROD {
+		hasIndent = false
+	}
+	if len(encoding) > 0 && encoding[0] == true {
+		hasEncoding = true
+	}
+	if c.Data["json"] == nil {
+		go utils.SendEmail("异常提醒:", "接口:"+"URI:"+c.Ctx.Input.URI()+";无返回值", utils.EmailSendToUsers)
+		return
+	}
+	baseRes := c.Data["json"].(*models.BaseResponse)
+	if baseRes != nil && !baseRes.Success {
+		go utils.SendEmail(utils.APPNAME+"失败提醒", "URI:"+c.Ctx.Input.URI()+" ErrMsg:"+baseRes.ErrMsg+";Msg"+baseRes.Msg, utils.EmailSendToUsers)
+	}
+	c.JSON(c.Data["json"], hasIndent, hasEncoding)
+}
+
+func (c *BaseCommonController) JSON(data interface{}, hasIndent bool, coding bool) error {
+	c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
+	var content []byte
+	var err error
+	if hasIndent {
+		content, err = json.MarshalIndent(data, "", "  ")
+	} else {
+		content, err = json.Marshal(data)
+	}
+	if err != nil {
+		http.Error(c.Ctx.Output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError)
+		return err
+	}
+	ip := c.Ctx.Input.IP()
+	requestBody, _ := url.QueryUnescape(string(c.Ctx.Input.RequestBody))
+	apiLog.Println("请求地址:", c.Ctx.Input.URI(), "Authorization:", c.Ctx.Input.Header("Authorization"), "RequestBody:", requestBody, "ResponseBody", string(content), "IP:", ip)
+
+	if coding {
+		content = []byte(utils.StringsToJSON(string(content)))
+	}
+	return c.Ctx.Output.Body(content)
+}

+ 354 - 0
controllers/classify.go

@@ -0,0 +1,354 @@
+package controllers
+
+import (
+	"encoding/json"
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/utils"
+	"time"
+)
+
+//分类
+type ClassifyController struct {
+	BaseAuthController
+}
+
+// @Title 新增分类接口
+// @Description 新增分类
+// @Param	request	body models.ClassifyAddReq true "type json string"
+// @Success 200 新增成功
+// @router /add [post]
+func (this *ClassifyController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ClassifyAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyName == "" {
+		br.Msg = "分类名称不可为空"
+		return
+	}
+	item, err := models.GetClassifyByName(req.ClassifyName, req.ParentId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取分类信息失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		br.Msg = "分类名称:" + req.ClassifyName + "已存在"
+		return
+	}
+	classify := new(models.Classify)
+	classify.ClassifyName = req.ClassifyName
+	classify.ParentId = req.ParentId
+	classify.CreateTime = time.Now()
+	classify.ModifyTime = time.Now()
+	classify.Abstract = req.Abstract
+	classify.Descript = req.Descript
+	err = models.AddClassify(classify)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// @Title 删除分类-检测接口
+// @Description 删除分类-信息检测,是否符合删除条件
+// @Param	request	body models.CheckDeleteClassifyReq true "type json string"
+// @Success 200 {object} models.CheckDeleteClassifyResp
+// @router /checkDeleteClassify [get]
+func (this *ClassifyController) CheckDeleteClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.CheckDeleteClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	classify, err := models.GetClassifyById(req.ClassifyId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.CheckDeleteClassifyResp)
+	if classify == nil {
+		br.Msg = "分类不存在"
+		resp.Code = 1
+		resp.Msg = "分类不存在"
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		return
+	}
+
+	//判断分类是否关联了报告
+	if classify.ParentId > 0 {
+		count, err := models.GetReportCountByClassifyId(req.ClassifyId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		if count > 0 {
+			resp.Code = 2
+			resp.Msg = "该分类有关联报告,不允许删除"
+			br.Data = resp
+			br.Ret = 200
+			br.Msg = "该分类有关联报告,不允许删除"
+			br.Success = true
+			return
+		}
+	} else {
+		subCount, err := models.GetClassifySubCountByClassifyId(req.ClassifyId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		if subCount > 0 {
+			resp.Code = 3
+			resp.Msg = "二级分类有关联报告,不允许删除"
+			br.Data = resp
+			br.Ret = 200
+			br.Msg = "二级分类有关联报告,不允许删除"
+			br.Success = true
+			return
+		}
+		subTotal, err := models.GetClassifySubCountByParentId(req.ClassifyId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		if subTotal > 0 {
+			resp.Code = 4
+			resp.Msg = "该分类下有关联分类,是否确认全部删除"
+			br.Data = resp
+			br.Ret = 200
+			br.Msg = "该分类下有关联分类,是否确认全部删除"
+			br.Success = true
+			return
+		}
+	}
+	resp.Code = 0
+	resp.Msg = "检测完成,可进行删除操作"
+	br.Ret = 200
+	br.Data = resp
+	br.Success = true
+	br.Msg = "检测成功"
+}
+
+// @Title 删除分类接口
+// @Description 删除分类
+// @Param	request	body models.DeleteClassifyReq true "type json string"
+// @Success 200 Ret=200,删除成功
+// @router /delete [post]
+func (this *ClassifyController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.DeleteClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	item, err := models.GetClassifyById(req.ClassifyId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item == nil {
+		br.Msg = "分类不存在"
+		return
+	}
+	err = models.DeleteClassify(req.ClassifyId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// @Title 修改分类接口
+// @Description 修改分类
+// @Param	request	body models.EditClassifyReq true "type json string"
+// @Success 200 Ret=200,修改成功
+// @router /edit [post]
+func (this *ClassifyController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EditClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ClassifyId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	item, err := models.GetClassifyByName(req.ClassifyName, req.ParentId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item != nil && item.Id != req.ClassifyId {
+		br.Msg = "分类名称:" + req.ClassifyName + "已存在"
+		return
+	}
+	err = models.EditClassify(req.ClassifyName, req.Abstract, req.Descript, req.ParentId, req.ClassifyId)
+	if err != nil {
+		br.Msg = "修改失败"
+		br.ErrMsg = "修改失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "修改成功"
+}
+
+// @Title 获取父级分类接口
+// @Description 获取父级分类
+// @Success 200 {object} models.Classify
+// @router /parent [get]
+func (this *ClassifyController) ParentClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	items, err := models.ParentClassify()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Data = items
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// @Title 根据id获取分类详情接口
+// @Description 根据id获取分类详情
+// @Param	request	body models.FindByIdClassifyReq true "type json string"
+// @Success 200 {object} models.Classify
+// @router /findById [get]
+func (this *ClassifyController) FindByIdClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.FindByIdClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	items, err := models.FindByIdClassify(req.ClassifyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	br.Data = items
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// @Title 获取分类列表
+// @Description 获取分类列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   KeyWord   query   string  true       "检索关键词"
+// @Success 200 {object} models.Classify
+// @router /list [get]
+func (this *ClassifyController) ListClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyWord := this.GetString("KeyWord")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	list, err := models.GetClassifyList(startSize, pageSize, keyWord)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	total, err := models.GetClassifyListCount(keyWord)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range list {
+		child, err := models.GetClassifyChild(v.Id, keyWord)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+		v.Child = child
+	}
+	page := models.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.ClassifyListResp)
+	resp.List = list
+	resp.Paging = page
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 625 - 0
controllers/ppt.go

@@ -0,0 +1,625 @@
+package controllers
+
+import (
+	"encoding/base64"
+	"encoding/json"
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/services"
+	"hongze/hongze_admin/utils"
+	"image"
+	"os"
+	"rdluck_tools/http"
+	"time"
+)
+
+//报告
+type PptController struct {
+	BaseAuthController
+}
+
+// @Title 获取ppt列表
+// @Description 获取ppt列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Success 200 {object} models.ReportListResp
+// @router /list [get]
+func (this *PptController) ListPpt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyWord := this.GetString("KeyWord")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var condition string
+	var pars []interface{}
+
+	if keyWord != "" {
+		condition += ` AND title LIKE '%` + keyWord + `%' `
+	}
+	total, err := models.GetPptListCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetPptList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	page := models.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.PptListResp)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 新增ppt
+// @Description 新增ppt接口
+// @Param	request	body models.AddPptReq true "type json string"
+// @Success 200 Ret=200 新增成功
+// @router /add [post]
+func (this *PptController) AddPpt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.AddPptReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.FirstPage.Title == "" {
+		br.Msg = "标题不能为空"
+		return
+	}
+	ppt := new(models.Ppt)
+	ppt.Title = req.FirstPage.Title
+	ppt.PptDate = req.FirstPage.PptDate
+	ppt.ReportType = req.FirstPage.ReportType
+	newId, err := models.AddPpt(ppt)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+
+	for _, v := range req.ContentPage {
+		page := new(models.PptPages)
+		page.PptId = newId
+		page.Title = v.Title
+		page.ResourceId = v.ResourceId
+		_, err = models.AddPptPages(page)
+		if err != nil {
+			br.Msg = "新增失败"
+			br.ErrMsg = "新增章节失败,Err:" + err.Error()
+			return
+		}
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// @Title 编辑ppt
+// @Description 编辑ppt接口
+// @Param	request	body models.EditPptReq true "type json string"
+// @Success 200 Ret=200 编辑成功
+// @router /edit [post]
+func (this *PptController) EditPpt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EditPptReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.FirstPage.Title == "" {
+		br.Msg = "标题不能为空"
+		return
+	}
+	ppt := new(models.Ppt)
+	ppt.Title = req.FirstPage.Title
+	ppt.PptDate = req.FirstPage.PptDate
+	ppt.ReportType = req.FirstPage.ReportType
+	err = models.EditPpt(ppt)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+
+	page := new(models.PptPages)
+	page.PptPagesId = req.FirstPage.PptPagesId
+	page.Title = req.FirstPage.Title
+	page.ImgUrl = req.FirstPage.ImgUrl
+	err = models.EditPptPages(page)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑章节失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range req.ContentPage {
+		page := new(models.PptPages)
+		page.PptId = req.PptId
+		page.Title = v.Title
+		page.ResourceId = v.ResourceId
+		page.CreateTime = time.Now()
+		page.ModifyTime = time.Now()
+		if v.PptPagesId <= 0 {
+			_, err = models.AddPptPages(page)
+			if err != nil {
+				br.Msg = "编辑失败"
+				br.ErrMsg = "新增章节失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			err = models.EditPptPages(page)
+			if err != nil {
+				br.Msg = "编辑失败"
+				br.ErrMsg = "新增章节失败,Err:" + err.Error()
+				return
+			}
+		}
+
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+}
+
+// @Title 删除ppt
+// @Description 删除ppt接口
+// @Param	request	body models.DeletePptReq true "type json string"
+// @Success 200 Ret=200 编辑成功
+// @router /delete [post]
+func (this *PptController) DeletePpt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.DeletePptReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.PptId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	err = models.DeletePpt(req.PptId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// @Title 新增ppt章节
+// @Description 新增ppt章节接口
+// @Param	request	body models.ContentPageItems true "type json string"
+// @Success 200 Ret=200 编辑成功
+// @router /addPptPages [post]
+func (this *PptController) AddPptPages() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ContentPageItems
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	page := new(models.PptPages)
+	page.PptId = req.PptId
+	page.Title = req.Title
+	page.CreateTime = time.Now()
+	page.ModifyTime = time.Now()
+	page.ResourceId = req.ResourceId
+	_, err = models.AddPptPages(page)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// @Title 获取ppt详情
+// @Description 获取ppt详情接口
+// @Param   PptId   query   int  true       "ppt_id"
+// @Success 200 {object} models.ReportListResp
+// @router /detail [get]
+func (this *PptController) DetailPpt() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pptId, _ := this.GetInt("PptId")
+	ppt, err := models.GetPptById(pptId)
+	if err != nil {
+		br.Msg = "信息获取失败"
+		br.ErrMsg = "信息获取失败,Err:" + err.Error()
+		return
+	}
+	pptPages, err := models.GetPptPagesById(pptId)
+	if err != nil {
+		br.Msg = "信息获取失败"
+		br.ErrMsg = "信息获取失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.PptDetailResp)
+	resp.Ppt = ppt
+	resp.PptPages = pptPages
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 图片上传
+// @Description 图片上传接口
+// @Param   Img   query   string  true       "图片base64字符串"
+// @Param   ResourceId   query   int  true       "策略组提供的资源id"
+// @Param   PptId   query   int  true       "PptId"
+// @Param   PptPagesId   query   int  true       "PptPagesId"
+// @Success 200 新增成功
+// @router /base64Upload [post]
+func (this *PptController) Base64Upload() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	imgData := this.GetString("Image")
+	if imgData == "" {
+		br.Msg = "图片参数错误"
+		br.ErrMsg = "图片参数错误,Img Is Empty"
+		return
+	}
+	resourceId, err := this.GetInt("ResourceId")
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "获取,策略组提供的资源id失败,Err:" + err.Error()
+		return
+	}
+
+	pptId, err := this.GetInt("PptId")
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "获取,pptId,Err:" + err.Error()
+		return
+	}
+
+	pptPagesId, err := this.GetInt("PptPagesId")
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "获取,策略组提供的资源id失败,Err:" + err.Error()
+		return
+	}
+
+	dateDir := time.Now().Format("20060102")
+	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
+	if !utils.FileIsExist(uploadDir) {
+		err = os.MkdirAll(uploadDir, 777)
+		if err != nil {
+			br.Msg = "存储目录创建失败"
+			br.ErrMsg = "存储目录创建失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	imgBase64 := base64.StdEncoding.EncodeToString([]byte(imgData))
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName := randStr + ".png"
+	savePath := uploadDir + "/" + fileName
+	err = utils.SaveBase64ToFile(imgBase64, savePath)
+	if err != nil {
+		br.Msg = "图片保存失败"
+		br.ErrMsg = "图片保存失败,Err:" + err.Error()
+		return
+	}
+	file, err := os.Open(savePath)
+	if err != nil {
+		br.Msg = "获取图片信息失败"
+		br.ErrMsg = "获取图片信息失败,Err:" + err.Error()
+		return
+	}
+	config, _, err := image.DecodeConfig(file)
+	if err != nil {
+		br.Msg = "获取图片信息失败"
+		br.ErrMsg = "获取图片信息失败,Err:" + err.Error()
+		return
+	}
+	width := config.Width
+	height := config.Height
+	//上传到阿里云
+	resourceUrl, err := services.UploadAliyun(fileName, savePath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+
+	defer func() {
+		os.Remove(savePath)
+	}()
+
+	item := new(models.Resource)
+	item.ResourceUrl = resourceUrl
+	item.ResourceType = 1
+	item.CreateTime = time.Now()
+	newId, err := models.AddResource(item)
+	if err != nil {
+		br.Msg = "资源上传失败"
+		br.ErrMsg = "资源上传失败,Err:" + err.Error()
+		return
+	}
+
+	//修改路径
+	err = models.ModifyPptPages(resourceUrl, resourceId, pptId, pptPagesId, width, height)
+	if err != nil {
+		br.Msg = "资源上传失败"
+		br.ErrMsg = "资源上传失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.ResourceResp)
+	resp.Id = newId
+	resp.ResourceUrl = resourceUrl
+	br.Msg = "上传成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+	return
+}
+
+// @Title ppt下载
+// @Description ppt下载
+// @Param   PptId   query   int  true       "PptId"
+// @Success 200 下载成功
+// @router /download [get]
+func (this *PptController) Download() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pptId, err := this.GetInt("PptId")
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "获取,pptId,Err:" + err.Error()
+		return
+	}
+	ppt, err := models.GetPptById(pptId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	filePath := ppt.PptUrl + ".ppt"
+	fileName := ppt.Title + ".ppt"
+	this.Ctx.Output.Download(filePath, fileName)
+	return
+}
+
+// @Title ppt下载
+// @Description ppt下载
+// @Param   PptId   query   int  true       "PptId"
+// @Success 200 下载成功
+// @router /downloadpptx [get]
+func (this *PptController) Downloadpptx() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pptId, err := this.GetInt("PptId")
+	if err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "获取,pptId,Err:" + err.Error()
+		return
+	}
+	ppt, err := models.GetPptById(pptId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	filePath := ppt.PptUrl + ".pptx"
+	fileName := ppt.Title + ".pptx"
+	this.Ctx.Output.Download(filePath, fileName)
+	return
+}
+
+// @Title 获取首页背景模板接口
+// @Description 获取首页背景模板接口
+// @Success 200 {object} models.PptImagesResp
+// @router /getImages [get]
+func (this *PptController) GetImages() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	imageType := 0
+	ppt, err := models.GetImages(imageType)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+
+	resp := new(models.PptImagesResp)
+	resp.List = ppt
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	return
+}
+
+// @Title 发布接口
+// @Description 发布接口
+// @Param	request	body models.PptPublishReq true "type json string"
+// @Success 200 {object} models.PptImagesResp
+// @router /publish [post]
+func (this *PptController) Publish() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req models.PptPublishReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	pptId := req.PptId
+	if pptId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+
+	pptFirstPages, err := models.GetPptFirstPage(pptId)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	pptContentPages, err := models.GetPptContentPages(pptId, pptFirstPages.PptPagesId)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	dataMap := make(map[string]interface{})
+	dataMap["FirstPage"] = pptFirstPages
+	dataMap["ContentPage"] = pptContentPages
+	dataMap["ScreenHeight"] = req.ScreenHeight
+
+	postUrl := "http://127.0.0.1:5000/publish_ppt/" //随便写的
+	postData, err := json.Marshal(dataMap)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "Marshal,Err:" + err.Error()
+		return
+	}
+
+	result, err := http.Post(postUrl, string(postData))
+	if err != nil {
+		br.Msg = "发布失败"
+		br.ErrMsg = "Marshal,Err:" + err.Error()
+		return
+	}
+	var pptResult PublishPptResult
+	err = json.Unmarshal(result, &pptResult)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "Marshal,Err:" + err.Error()
+		return
+	}
+	err = models.EditPptPath(pptId, pptResult.PptFullPath)
+	if err != nil {
+		br.Msg = "发布失败"
+		br.ErrMsg = "发布失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "发布成功"
+	return
+}
+
+type PublishPptResult struct {
+	Result      string
+	PptPath     string
+	PptName     string
+	PptFullPath string
+}
+/*
+func init() {
+	fmt.Println("start")
+	var err error
+	defer func() {
+		if err != nil {
+			fmt.Println("err:", err.Error())
+		}
+	}()
+	pptId := 111
+	if pptId <= 0 {
+		return
+	}
+
+	pptFirstPages, err := models.GetPptFirstPage(pptId)
+	if err != nil {
+		return
+	}
+	pptContentPages, err := models.GetPptContentPages(pptId, pptFirstPages.PptPagesId)
+	if err != nil {
+		return
+	}
+	dataMap := make(map[string]interface{})
+	dataMap["FirstPage"] = pptFirstPages
+	dataMap["ContentPage"] = pptContentPages
+	dataMap["ScreenHeight"] = 12000
+
+	postUrl := "http://127.0.0.1:5000/publish_ppt/" //随便写的
+	postData, err := json.Marshal(dataMap)
+	if err != nil {
+		return
+	}
+	utils.FileLog.Info("%s",string(postData))
+	result, err := http.Post(postUrl, string(postData))
+	fmt.Println("result:", string(result))
+	if err != nil {
+		return
+	}
+	var pptResult PublishPptResult
+	err = json.Unmarshal(result, &pptResult)
+	if err != nil {
+		return
+	}
+	fmt.Println("ppt:", pptResult.PptFullPath)
+	fmt.Println("end")
+}
+*/

+ 534 - 0
controllers/report.go

@@ -0,0 +1,534 @@
+package controllers
+
+import (
+	"encoding/json"
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/services"
+	"hongze/hongze_admin/utils"
+	"html"
+	"os"
+	"path"
+	"strconv"
+	"time"
+)
+
+//报告
+type ReportController struct {
+	BaseAuthController
+}
+
+// @Title 获取报告列表接口
+// @Description 获取报告列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   StartDate   query   string  true       "开始时间"
+// @Param   EndDate   query   string  true       "结束时间"
+// @Param   Frequency   query   string  true       "频度"
+// @Param   ClassifyNameFirst   query   string  true       "一级分类名称"
+// @Param   ClassifyNameSecond   query   string  true       "二级分类名称"
+// @Param   State   query   int  true       "状态"
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Param   PublishSort   query   string  true       "desc:降序,asc 升序(预留)"
+// @Success 200 {object} models.ReportListResp
+// @router /list [get]
+func (this *ReportController) ListReport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+	frequency := this.GetString("Frequency")
+	classifyNameFirst := this.GetString("ClassifyNameFirst")
+	classifyNameSecond := this.GetString("ClassifyNameSecond")
+	state, _ := this.GetInt("State")
+	keyWord := this.GetString("KeyWord")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var condition string
+	var pars []interface{}
+
+	if keyWord != "" {
+		condition += ` AND (title LIKE '%` + keyWord + `%' OR author LIKE '%` + keyWord + `%' ) `
+	}
+	if startDate != "" {
+		condition += ` AND create_time >= ? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		condition += ` AND create_time <= ? `
+		pars = append(pars, endDate)
+	}
+	if frequency != "" {
+		condition += ` AND frequency = ? `
+		pars = append(pars, frequency)
+	}
+	if classifyNameFirst != "" {
+		condition += ` AND classify_name_first = ? `
+		pars = append(pars, classifyNameFirst)
+	}
+
+	if classifyNameSecond != "" {
+		condition += ` AND classify_name_second = ? `
+		pars = append(pars, classifyNameSecond)
+	}
+	if state > 0 {
+		condition += ` AND state = ? `
+		pars = append(pars, state)
+	}
+	total, err := models.GetReportListCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetReportList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	page := models.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.ReportListResp)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 发布报告接口
+// @Description 发布报告
+// @Param	request	body models.PublishReq true "type json string"
+// @Success 200 Ret=200 发布成功
+// @router /publish [post]
+func (this *ReportController) PublishReport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.PublishReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ReportIds != "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,报告id不可为空"
+		return
+	}
+	err = models.PublishReport(req.ReportIds)
+	if err != nil {
+		br.Msg = "发布失败"
+		br.ErrMsg = "发布失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "发布成功"
+}
+
+// @Title 取消发布报告接口
+// @Description 取消发布报告
+// @Param	request	body models.PublishReq true "type json string"
+// @Success 200 Ret=200 发布成功
+// @router /publish/cancle [post]
+func (this *ReportController) PublishCancleReport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.PublishReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ReportIds != "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,报告id不可为空"
+		return
+	}
+	err = models.PublishCancleReport(req.ReportIds)
+	if err != nil {
+		br.Msg = "取消发布失败"
+		br.ErrMsg = "取消发布失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "取消发布成功"
+}
+
+// @Title 删除报告接口
+// @Description 删除报告
+// @Param	request	body models.DeleteReq true "type json string"
+// @Success 200 Ret=200 发布成功
+// @router /delete [post]
+func (this *ReportController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.DeleteReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ReportIds != "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,报告id不可为空"
+		return
+	}
+	err = models.DeleteReport(req.ReportIds)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// @Title 新增报告接口
+// @Description 新增报告
+// @Param	request	body models.AddReq true "type json string"
+// @Success 200 {object} models.AddResp
+// @router /add [post]
+func (this *ReportController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.AddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	var contentSub string
+	if req.Content != "" {
+		contentSub, err = services.GetReportContentSub(req.Content)
+		if err != nil {
+			utils.SendEmail(utils.APPNAME+"失败提醒", "解析 ContentSub 失败,Err:"+err.Error(), utils.EmailSendToUsers)
+		}
+	}
+	maxStage, err := models.GetReportStage(req.ClassifyIdFirst, req.ClassifyIdSecond)
+	if err != nil {
+		br.Msg = "期数获取失败!"
+		br.ErrMsg = "期数获取失败,Err:" + err.Error()
+		return
+	}
+
+	item := new(models.Report)
+	item.AddType = req.AddType
+	item.ClassifyIdFirst = req.ClassifyIdFirst
+	item.ClassifyNameFirst = req.ClassifyNameFirst
+	item.ClassifyIdSecond = req.ClassifyIdSecond
+	item.ClassifyNameSecond = req.ClassifyNameSecond
+	item.Title = req.Title
+	item.Abstract = req.Abstract
+	item.Author = req.Author
+	item.Frequency = req.Frequency
+	item.State = req.State
+	item.Content = html.EscapeString(req.Content)
+	item.Stage = maxStage + 1
+	item.ContentSub = html.EscapeString(contentSub)
+	item.CreateTime = req.CreateTime
+	newReportId, err := models.AddReport(item)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		return
+	}
+	//处理权限
+	{
+		permissionItems, err := models.GetPermission(req.ClassifyNameSecond)
+		if err != nil {
+			utils.SendEmail(utils.APPNAME+"失败提醒", "获取权限失败,Err:"+err.Error(), utils.EmailSendToUsers)
+		}
+		for _, v := range permissionItems {
+			err = models.AddChartPermissionChapterMapping(v.ChartPermissionId, newReportId)
+			if err != nil {
+				utils.SendEmail(utils.APPNAME+"失败提醒", "新增权限失败,Err:"+err.Error()+strconv.FormatInt(newReportId, 10), utils.EmailSendToUsers)
+			}
+		}
+	}
+	resp := new(models.AddResp)
+	resp.ReportId = newReportId
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+}
+
+// @Title 编辑报告接口
+// @Description 编辑报告
+// @Param	request	body models.EditReq true "type json string"
+// @Success 200 {object} models.EditResp
+// @router /edit [post]
+func (this *ReportController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EditReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	var contentSub string
+	if req.Content != "" {
+		contentSub, err = services.GetReportContentSub(req.Content)
+		if err != nil {
+			utils.SendEmail(utils.APPNAME+"失败提醒", "解析 ContentSub 失败,Err:"+err.Error(), utils.EmailSendToUsers)
+		}
+	}
+	item := new(models.Report)
+	item.ClassifyIdFirst = req.ClassifyIdFirst
+	item.ClassifyNameFirst = req.ClassifyNameFirst
+	item.ClassifyIdSecond = req.ClassifyIdSecond
+	item.ClassifyNameSecond = req.ClassifyNameSecond
+	item.Title = req.Title
+	item.Abstract = req.Abstract
+	item.Author = req.Author
+	item.Frequency = req.Frequency
+	item.State = req.State
+	item.Content = html.EscapeString(req.Content)
+	item.ContentSub = html.EscapeString(contentSub)
+	item.CreateTime = req.CreateTime
+	err = models.EditReport(item, req.ReportId)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.EditResp)
+	resp.ReportId = req.ReportId
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "保存成功"
+	br.Data = resp
+}
+
+// @Title 获取报告详情接口
+// @Description 获取报告详情
+// @Param	request	body models.ReportDetailReq true "type json string"
+// @Success 200 {object} models.Report
+// @router /detail [get]
+func (this *ReportController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ReportDetailReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ReportId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	item, err := models.GetReportById(req.ReportId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	item.Content = html.UnescapeString(item.Content)
+	item.ContentSub = html.UnescapeString(item.ContentSub)
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = item
+}
+
+// @Title 图片上传
+// @Description 图片上传接口
+// @Param   file   query   file  true       "文件"
+// @Success 200 新增成功
+// @router /upload [post]
+func (this *ReportController) Upload() {
+	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
+	}
+	ext := path.Ext(h.Filename)
+	dateDir := time.Now().Format("20060102")
+	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
+	err = os.MkdirAll(uploadDir, 777)
+	if err != nil {
+		br.Msg = "存储目录创建失败"
+		br.ErrMsg = "存储目录创建失败,Err:" + err.Error()
+		return
+	}
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName := randStr + ext
+	fpath := uploadDir + "/" + fileName
+	defer f.Close() //关闭上传文件
+	err = this.SaveToFile("file", fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	//上传到阿里云
+	resourceUrl, err := services.UploadAliyun(fileName, fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+
+	defer func() {
+		os.Remove(fpath)
+	}()
+
+	item := new(models.Resource)
+	item.ResourceUrl = resourceUrl
+	item.ResourceType = 1
+	item.CreateTime = time.Now()
+	newId, err := models.AddResource(item)
+	if err != nil {
+		br.Msg = "资源上传失败"
+		br.ErrMsg = "资源上传失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.ResourceResp)
+	resp.Id = newId
+	resp.ResourceUrl = resourceUrl
+	br.Msg = "上传成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+	return
+}
+
+// @Title 根据分类获取最近一次报告详情接口
+// @Description 根据分类获取最近一次报告详情
+// @Param	request	body models.ClassifyIdDetailReq true "type json string"
+// @Success 200 {object} models.Report
+// @router /classifyIdDetail [get]
+func (this *ReportController) ClassifyIdDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ClassifyIdDetailReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	item, err := models.GetReportDetailByClassifyId(req.ClassifyIdFirst, req.ClassifyIdSecond)
+	if err != nil {
+		br.Msg = "获取失败!"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	item.Content = html.UnescapeString(item.Content)
+	item.ContentSub = html.UnescapeString(item.ContentSub)
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = item
+}
+
+// @Title 模板消息推送接口
+// @Description 模板消息推送
+// @Param	request	body models.SendTemplateMsgReq true "type json string"
+// @Success 200 Ret=200 推送成功
+// @router /sendTemplateMsg [post]
+func (this *ReportController) SendTemplateMsg() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.SendTemplateMsgReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ReportId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误"
+		return
+	}
+	go services.SendWxTemplateMsg(req.ReportId)
+	err = models.ModifyReportMsgIsSend(req.ReportId)
+	if err != nil {
+		br.Msg = "发送失败"
+		br.ErrMsg = "发送失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "发送成功"
+}
+
+// @Title 获取报告作者接口
+// @Description 获取报告作者
+// @Success 200 {object} models.ReportAuthorResp
+// @router /author [get]
+func (this *ReportController) Author() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	items, err := models.GetReportAuthor()
+	if err != nil {
+		br.Msg = "获取失败!"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.ReportAuthorResp)
+	resp.List = items
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 143 - 0
controllers/sys_user.go

@@ -0,0 +1,143 @@
+package controllers
+
+import (
+	"encoding/json"
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/utils"
+	"time"
+)
+
+type SysUserController struct {
+	BaseCommonController
+}
+
+// @Title 系统用户登录接口
+// @Description 系统用户登录
+// @Param	request	body models.LoginReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /login [post]
+func (this *SysUserController) Login() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.LoginReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.Username == "" {
+		br.Msg = "请输入账号"
+		return
+	}
+
+	if req.Password == "" {
+		br.Msg = "请输入密码"
+		return
+	}
+	sysUser, err := models.CheckSysUser(req.Username, req.Password)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "登录失败,账号或密码错误"
+			br.ErrMsg = "登录失败,账号或密码错误,Err:" + err.Error()
+			return
+		}
+		br.Msg = "登录失败,账号或密码错误"
+		br.ErrMsg = "登录失败,Err:" + err.Error()
+		return
+	}
+	if sysUser == nil {
+		br.Msg = "登录失败,账号或密码错误"
+		br.ErrMsg = "登录失败,sysUser is nil "
+		return
+	}
+	account := utils.MD5(req.Username)
+	token := utils.GenToken(account)
+	sysSession := new(models.SysSession)
+	sysSession.UserName = req.Username
+	sysSession.SysUserId = sysUser.AdminId
+	sysSession.ExpiredTime = time.Now().AddDate(0, 0, 90)
+	sysSession.CreatedTime = time.Now()
+	sysSession.LastUpdatedTime = time.Now()
+	sysSession.AccessToken=token
+	err = models.AddSysSession(sysSession)
+	if err != nil {
+		br.ErrMsg = "新增session信息失败,Err:" + err.Error()
+		br.Msg = "登录失败"
+		return
+	}
+	resp := new(models.LoginResp)
+	resp.Authorization = token
+	resp.Authorization = "authorization="+token+";account="+account
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "登录成功"
+	br.Data = resp
+	//新增登录记录
+	{
+		record := new(models.SysUserLoginRecord)
+		record.Uid = sysUser.AdminId
+		record.UserName = req.Username
+		record.Ip = this.Ctx.Input.IP()
+		record.Stage = "login"
+		record.CreateTime = time.Now()
+		go models.AddSysUserLoginRecord(record)
+	}
+}
+
+type SysUserAuthController struct {
+	BaseAuthController
+}
+
+// @Title 修改密码
+// @Description 修改密码
+// @Param	request	body models.ModifyPwdReq true "type json string"
+// @Success 200 {object} models.LoginResp
+// @router /modify/pwd [post]
+func (this *SysUserAuthController) ModifyPwd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.ModifyPwdReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "登录失败,账号或密码错误"
+		br.ErrMsg = "登录失败,sysUser is nil "
+		return
+	}
+	if req.OldPwd == "" {
+		br.Msg = "原始密码不能为空"
+		return
+	}
+
+	if req.NewPwd == "" {
+		br.Msg = "新密码不能为空"
+		return
+	}
+
+	if sysUser.Password != req.OldPwd {
+		br.Msg = "旧密码错误,请重新输入"
+		return
+	}
+	err = models.ModifyPwd(sysUser.AdminId, req.NewPwd)
+	if err != nil {
+		br.Msg = "修改失败"
+		br.ErrMsg = "修改失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "修改成功"
+}

+ 1100 - 0
controllers/target.go

@@ -0,0 +1,1100 @@
+package controllers
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/tealeg/xlsx"
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/utils"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+//指标
+type TargetController struct {
+	BaseAuthController
+}
+
+// @Title 获取ppt列表
+// @Description 获取ppt列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   StartDate   query   string  true       "开始日期"
+// @Param   EndDate   query   string  true       "结束日期"
+// @Param   Frequency   query   string  true       "频度"
+// @Param   ClassifyId   query   int  true       "分类"
+// @Param   KeyWord   query   string  true       "名称关键词"
+// @Param   TradeCode   query   string  true       "指标唯一编码"
+// @Success 200 {object} models.DataListResp
+// @router /data/list [get]
+func (this *TargetController) DataList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyWord := this.GetString("KeyWord")
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+	frequency := this.GetString("Frequency")
+	tradeCode := this.GetString("TradeCode")
+	classifyId, _ := this.GetInt("ClassifyId") //分类
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var condition string
+	var pars []interface{}
+
+	if keyWord != "" {
+		condition += ` AND a.SEC_NAME LIKE '%` + keyWord + `%' `
+	}
+	if startDate != "" {
+		condition += ` AND c.DT >= ? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		condition += ` AND c.DT <= ? `
+		pars = append(pars, endDate)
+	}
+
+	if frequency != "" {
+		condition += ` AND a.frequency = ? `
+		pars = append(pars, frequency)
+	}
+
+	if classifyId > 0 {
+		condition += ` AND a.classify_id = ? `
+
+		pars = append(pars, classifyId)
+	}
+
+	if tradeCode != "" {
+		condition += ` AND c.TRADE_CODE= = ? `
+		pars = append(pars, tradeCode)
+	}
+
+	total, err := models.GetDataListCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetDataList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	page := models.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.DataListResp)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 录入数据
+// @Description 录入数据接口
+// @Param	request	body models.DataAddReq true "type json string"
+// @Success 200 Ret=200 录入成功
+// @router /data/add [post]
+func (this *TargetController) DataAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.DataAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.TradeCode == "" {
+		br.Msg = "指标编码不可为空!"
+		return
+	}
+
+	if req.CreateDate == "" {
+		br.Msg = "请选择日期"
+		return
+	}
+	item, err := models.GetDataInfo(req.TradeCode, req.CreateDate)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败!"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		br.Msg = "该指标当前日期下,数据已录入"
+		return
+	}
+	edbdata := new(models.Edbdata)
+	edbdata.TradeCode = req.TradeCode
+	edbdata.Dt = req.CreateDate
+	edbdata.Close = req.Close
+	edbdata.ModifyTime = time.Now()
+	_, err = models.AddEdbdata(edbdata)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// @Title 编辑数据
+// @Description 编辑数据接口
+// @Param	request	body models.DataEditReq true "type json string"
+// @Success 200 Ret=200 编辑数据成功
+// @router /data/edit [post]
+func (this *TargetController) DataEdit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.DataEditReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.TradeCode == "" {
+		br.Msg = "指标编码不可为空!"
+		return
+	}
+
+	if req.CreateDate == "" {
+		br.Msg = "请选择日期"
+		return
+	}
+
+	edbdata := new(models.Edbdata)
+	edbdata.TradeCode = req.TradeCode
+	edbdata.Dt = req.CreateDate
+	edbdata.Close = req.Close
+	edbdata.ModifyTime = time.Now()
+
+	if req.OldCreateDate == "" {
+		item, err := models.GetDataInfo(req.TradeCode, req.CreateDate)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取信息失败!"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		if item == nil { //新增
+			_, err = models.AddEdbdata(edbdata)
+			if err != nil {
+				br.Msg = "新增失败"
+				br.ErrMsg = "新增失败,Err:" + err.Error()
+				return
+			}
+		} else { //修改
+			err = models.EditEdbdata(edbdata)
+			if err != nil {
+				br.Msg = "编辑失败"
+				br.ErrMsg = "编辑失败,Err:" + err.Error()
+				return
+			}
+		}
+	} else {
+		if req.CreateDate == req.OldCreateDate { //修改
+			err = models.EditEdbdata(edbdata)
+			if err != nil {
+				br.Msg = "编辑失败"
+				br.ErrMsg = "编辑失败,Err:" + err.Error()
+				return
+			}
+		} else {
+			item, err := models.GetDataInfo(req.TradeCode, req.CreateDate)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取信息失败!"
+				br.ErrMsg = "获取信息失败,Err:" + err.Error()
+				return
+			}
+			if item == nil {
+				_, err = models.AddEdbdata(edbdata)
+				if err != nil {
+					br.Msg = "新增失败"
+					br.ErrMsg = "新增失败,Err:" + err.Error()
+					return
+				}
+			} else {
+				err = models.EditEdbdata(edbdata)
+				if err != nil {
+					br.Msg = "编辑失败"
+					br.ErrMsg = "编辑失败,Err:" + err.Error()
+					return
+				}
+			}
+			oldItem, err := models.GetDataInfo(req.TradeCode, req.OldCreateDate)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取信息失败!"
+				br.ErrMsg = "获取信息失败,Err:" + err.Error()
+				return
+			}
+			if oldItem != nil {
+				record := new(models.EdbdataDeleteRecord)
+				record.TradeCode = oldItem.TradeCode
+				record.Dt = oldItem.Dt
+				record.Close = oldItem.Close
+				record.ModifyTime = oldItem.ModifyTime
+				record.CreateTime = time.Now()
+				record.SysUserId = this.SysUser.AdminId
+				_, err = models.AddEdbdataDeleteRecord(record)
+				if err != nil {
+					br.Msg = "编辑失败"
+					br.ErrMsg = "新增删除记录失败,Err:" + err.Error()
+					return
+				}
+				//删除数据
+				models.DeleteEdbData(req.TradeCode, req.OldCreateDate)
+			}
+		}
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+}
+
+// @Title 指标列表
+// @Description 指标列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   StartDate   query   string  true       "开始日期"
+// @Param   EndDate   query   string  true       "结束日期"
+// @Param   Frequency   query   string  true       "频度"
+// @Param   ClassifyId   query   int  true       "分类"
+// @Param   KeyWord   query   string  true       "名称关键词"
+// @Success 200 {object} models.TargetListResp
+// @router /target/list [get]
+func (this *TargetController) TargetList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.Ret = 408
+		return
+	}
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	keyWord := this.GetString("KeyWord")
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+	frequency := this.GetString("Frequency")
+	classifyId, _ := this.GetInt("ClassifyId") //分类
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	var condition string
+	var pars []interface{}
+
+	if keyWord != "" {
+		condition += ` AND a.SEC_NAME LIKE '%` + keyWord + `%' `
+	}
+	if startDate != "" {
+		condition += ` AND c.DT >= ? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		condition += ` AND c.DT <= ? `
+		pars = append(pars, endDate)
+	}
+
+	if frequency != "" {
+		condition += ` AND a.frequency = ? `
+		pars = append(pars, frequency)
+	}
+
+	if classifyId > 0 {
+		condition += ` AND a.classify_id = ? `
+
+		pars = append(pars, classifyId)
+	}
+	mobile := sysUser.Mobile
+	total, err := models.GetEdbinfoListCount(condition, pars, mobile)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetEdbinfoList(condition, pars, startSize, pageSize, mobile)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	page := models.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.TargetListResp)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 录入指标
+// @Description 录入指标接口
+// @Param	request	body models.EdbinfoAddReq true "type json string"
+// @Success 200 Ret=200 录入成功
+// @router /target/add [post]
+func (this *TargetController) TargetAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EdbinfoAddReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	tradeCode, err := models.GetMaxTradeCode()
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取最大交易编码失败,Err:" + err.Error()
+		return
+	}
+
+	if tradeCode == "" {
+		br.Msg = "数据异常"
+		br.ErrMsg = "最大编码为空"
+		return
+	}
+	maxTradeCode, err := utils.GetMaxTradeCode(tradeCode)
+	if err != nil {
+		br.Msg = "数据异常"
+		br.ErrMsg = "获取编码信息失败,Err:" + err.Error()
+		return
+	}
+	if maxTradeCode == "" {
+		br.Msg = "编码为空,请联系技术"
+		br.ErrMsg = "编码为空,请联系技术"
+		return
+	}
+	if req.SecName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+	item, err := models.GetEdbinfoBySecName(req.SecName)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败!"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		br.Msg = "指标名称已存在"
+		return
+	}
+	err = models.AddEdbinfo(maxTradeCode, req.SecName, req.Unit, "手动", req.Frequency, req.NoticeTime, req.ClassifyId, sysUser.AdminId)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	err = models.AddEdbinfoUser(maxTradeCode, sysUser.Mobile)
+	if err != nil {
+		br.Msg = "新增失败"
+		br.ErrMsg = "新增失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "新增成功"
+}
+
+// @Title 编辑指标
+// @Description 编辑指标
+// @Param	request	body models.EdbinfoEditReq true "type json string"
+// @Success 200 Ret=200 录入成功
+// @router /target/edit [post]
+func (this *TargetController) TargetEdit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.EdbinfoEditReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	if req.TradeCode == "" {
+		br.Msg = "数据异常"
+		br.ErrMsg = "最大编码为空"
+		return
+	}
+
+	if req.SecName == "" {
+		br.Msg = "指标名称不能为空"
+		return
+	}
+	item, err := models.GetEdbinfoBySecName(req.SecName)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败!"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		if req.TradeCode != item.TradeCode {
+			br.Msg = "指标名称已存在"
+			return
+		}
+	}
+	err = models.EditEdbinfo(req.TradeCode, req.SecName, req.Unit, req.Frequency, req.NoticeTime, req.ClassifyId)
+	if err != nil {
+		br.Msg = "编辑失败"
+		br.ErrMsg = "编辑失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "编辑成功"
+}
+
+// @Title 搜索指标
+// @Description 搜索指标
+// @Param   ClassifyId   query   int  true       "分类"
+// @Param   KeyWord   query   string  true       "名称关键词"
+// @Success 200 {object} models.SearchTargetListResp
+// @router /target/search [get]
+func (this *TargetController) TargetSearch() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.Ret = 408
+		return
+	}
+	classifyId, _ := this.GetInt("ClassifyId")
+	keyWord := this.GetString("KeyWord")
+	list, err := models.SearchTargetEntry(classifyId, keyWord)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.SearchTargetListResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 获取分类
+// @Description 获取分类
+// @Success 200 {object} models.EdbdataClassifyResp
+// @router /classify [get]
+func (this *TargetController) ClassifyList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.Ret = 408
+		return
+	}
+	mobile := sysUser.Mobile
+	var wxUserId int64
+	if mobile != "" {
+		wxUser, err := models.GetUserByMobile(mobile)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取用户信息失败"
+			br.ErrMsg = "获取用户信息失败,err:" + err.Error()
+			return
+		}
+		if wxUser != nil {
+			wxUserId = wxUser.UserId
+		}
+	}
+	list, err := models.GetEdbdataClassify(wxUserId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.EdbdataClassifyResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 下载模板
+// @Description 下载模板
+// @Success 200 {object} models.EdbdataClassifyResp
+// @router /template [get]
+func (this *TargetController) TemplateDownload() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	this.Ctx.Output.Download("./static./数据导入模板.xlsx", "数据导入模板.xlsx")
+}
+
+// @Title 导入数据
+// @Description 导入数据
+// @Param   EntryFile   query   file  true       "文件"
+// @Success 200 Ret=200 录入成功
+// @router /import/data [post]
+func (this *TargetController) ImportData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	file, h, err := this.GetFile("EntryFile")
+	if err != nil {
+		br.Msg = "获取文件失败"
+		br.ErrMsg = "获取文件失败,Err:" + err.Error()
+		return
+	}
+
+	path := "./static/" + h.Filename
+	defer file.Close()
+	err = this.SaveToFile("EntryFile", path)
+	if err != nil {
+		br.Msg = "文件保存失败"
+		br.ErrMsg = "文件保存失败,Err:" + err.Error()
+		return
+	}
+	xlFile, err := xlsx.OpenFile(path)
+	if err != nil {
+		fmt.Println(err.Error())
+		return
+	}
+
+	failDatas := make([]*models.EdbdataImportFail, 0)
+	// 遍历sheet页读取
+	for _, sheet := range xlFile.Sheets {
+		fmt.Println("sheet name: ", sheet.Name)
+		//遍历行读取
+		maxRow := sheet.MaxRow
+		fmt.Println("maxRow:", maxRow)
+		fmt.Println("maxRow")
+		for i := 0; i < maxRow; i++ {
+			if i >= 2 {
+				row, err := sheet.Row(i)
+				fmt.Println(err)
+				classifyName := row.GetCell(0).Value //分类
+
+				cell1 := row.GetCell(1).Value
+				createDate := utils.ConvertToFormatDay(cell1) //录入日期
+
+				cell2 := row.GetCell(2).Value //指标名称
+				secName := strings.Trim(cell2, " ")
+
+				close := row.GetCell(3).Value //值
+				//判断指标,类型,等数据是否正常
+				classifyName = strings.Trim(classifyName, " ")
+
+				fmt.Println(classifyName, createDate, secName, close)
+
+				classify, err := models.GetEdbdataClassifyByClassifyName(classifyName)
+				if err != nil {
+					go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
+					continue
+				}
+				if classify == nil {
+					failItem := new(models.EdbdataImportFail)
+					failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+					failItem.ClassifyName = classifyName
+					failItem.CreateDate = createDate
+					failItem.SecName = secName
+					failItem.Close = close
+					failItem.Remark = "指标分类不存在"
+					failDatas = append(failDatas, failItem)
+					continue
+				}
+				//判断指标是否存在
+				target, err := models.GetTargetBySecName(secName)
+				if err != nil {
+					fmt.Println("导入数据 获取指标:Err:" + err.Error())
+					//utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取指标:Err:"+err.Error(), utils.EmailSendToUsers)
+				}
+				if target == nil {
+					fmt.Println("line 158")
+					failItem := new(models.EdbdataImportFail)
+					failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
+					failItem.ClassifyName = classifyName
+					failItem.CreateDate = createDate
+					failItem.SecName = secName
+					failItem.Close = close
+					failItem.Remark = "指标不存在"
+					failDatas = append(failDatas, failItem)
+					continue
+				}
+				//更新指标分类
+				if target.ClassifyId <= 0 && classify.ClassifyId > 0 {
+					models.ModifyTargetClassifyId(target.TradeCode, classify.ClassifyId)
+				}
+				//判断数据是否已经存在
+				count, err := models.GetTargetsDataCount(target.TradeCode, createDate)
+				if err != nil {
+					go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 判断数据是否存在失败:Err:"+err.Error(), utils.EmailSendToUsers)
+				}
+				//数据已存在,进行更新操作
+				if count > 0 {
+					edbData, err := models.GetTargetsData(target.TradeCode, createDate)
+					if err != nil {
+						go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取指标数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
+					}
+					if edbData != nil {
+						if edbData.Close <= 0 {
+							err = models.ModifyTargetsDataByImport(target.TradeCode, createDate, close)
+							if err != nil {
+								go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 修改数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
+							}
+						}
+					}
+				} else { //数据不存在,进行新增操作
+					models.AddTargetsDataByImport(target.TradeCode, createDate, close)
+					if err != nil {
+						go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增数据失败:Err:"+err.Error(), utils.EmailSendToUsers)
+					}
+				}
+			}
+		}
+	}
+	resp := new(models.EdbdataImportResp)
+	fmt.Println("failDatas:", len(failDatas))
+	if len(failDatas) > 0 {
+		for _, v := range failDatas {
+			err = models.AddEdbdataImportFail(v)
+			if err != nil {
+				go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增失败记录失败:Err:"+err.Error(), utils.EmailSendToUsers)
+			}
+		}
+		resp.Status = 1
+		resp.Msg = "存在部分导入失败"
+	} else {
+		resp.Status = 0
+	}
+	br.Msg = "导入成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+}
+
+// @Title 下载失败列表
+// @Description 下载失败列表
+// @Success 200 {object} models.EdbdataClassifyResp
+// @router /import/failList [get]
+func (this *TargetController) ImportFailListDownload() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	item, err := models.GetFailList(sysUser.AdminId)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.Msg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	xlsxFile := xlsx.NewFile()
+	sheet, err := xlsxFile.AddSheet("导入失败数据")
+	headRow := sheet.AddRow()
+	headRow.AddCell().SetValue("品种分类")
+	headRow.AddCell().SetValue("录入日期")
+	headRow.AddCell().SetValue("指标名称")
+	headRow.AddCell().SetValue("值")
+	headRow.AddCell().SetValue("备注")
+	for _, v := range item {
+		row := sheet.AddRow()
+		row.AddCell().SetValue(v.ClassifyName)
+		row.AddCell().SetValue(v.CreateDate)
+		row.AddCell().SetValue(v.SecName)
+		row.AddCell().SetValue(v.Close)
+		row.AddCell().SetValue(v.Remark)
+	}
+	fileName := time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	savePath := "./static/" + fileName
+	err = xlsxFile.Save(savePath)
+	if err != nil {
+		br.Msg = "文件保存失败"
+		br.ErrMsg = "文件保存失败,Err:" + err.Error()
+		return
+	}
+	defer func() {
+		os.Remove(savePath)
+	}()
+	this.Ctx.Output.Download(savePath, "失败列表.xlsx")
+}
+
+// @Title 导出数据
+// @Description 导出数据列表
+// @Param   StartDate   query   string  true       "开始日期"
+// @Param   EndDate   query   string  true       "结束日期"
+// @Param   Frequency   query   string  true       "频度"
+// @Param   ClassifyId   query   int  true       "分类"
+// @Param   KeyWord   query   string  true       "名称关键词"
+// @Success 200  导出成功
+// @router /export/dataList [get]
+func (this *TargetController) ExportDataList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	keyWord := this.GetString("KeyWord")
+	startDate := this.GetString("StartDate")
+	endDate := this.GetString("EndDate")
+	frequency := this.GetString("Frequency")
+	classifyId, _ := this.GetInt("ClassifyId") //分类
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	item, err := models.GetDataListForExport(startDate, endDate, frequency, keyWord, classifyId)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.Msg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	xlsxFile := xlsx.NewFile()
+	sheet, err := xlsxFile.AddSheet("导入失败数据")
+	headRow := sheet.AddRow()
+	headRow.AddCell().SetValue("录入日期")
+	headRow.AddCell().SetValue("指标名称")
+	headRow.AddCell().SetValue("频度")
+	headRow.AddCell().SetValue("分类")
+	headRow.AddCell().SetValue("单位")
+	headRow.AddCell().SetValue("值")
+	for _, v := range item {
+		row := sheet.AddRow()
+		row.AddCell().SetValue(v.Dt)
+		row.AddCell().SetValue(v.SecName)
+		row.AddCell().SetValue(v.Frequency)
+		row.AddCell().SetValue(v.ClassifyName)
+		row.AddCell().SetValue(v.Unit)
+		row.AddCell().SetValue(v.Close)
+	}
+	fileName := time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	savePath := "./static/" + fileName
+	err = xlsxFile.Save(savePath)
+	if err != nil {
+		br.Msg = "文件保存失败"
+		br.ErrMsg = "文件保存失败,Err:" + err.Error()
+		return
+	}
+	defer func() {
+		os.Remove(savePath)
+	}()
+	this.Ctx.Output.Download(savePath, "数据列表.xlsx")
+}
+
+// @Title 数据删除
+// @Description 数据删除
+// @Param	request	body models.DataDeleteReq true "type json string"
+// @Success 200 Ret=200 录入成功
+// @router /data/delete [post]
+func (this *TargetController) DataDelete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req models.DataDeleteReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	if req.TradeCode == "" {
+		br.Msg = "指标编码不可为空"
+		br.ErrMsg = "指标编码不可为空"
+		return
+	}
+
+	if req.CreateDate == "" {
+		br.Msg = "数据录入日期不可为空"
+		return
+	}
+	item, err := models.GetDataInfo(req.TradeCode, req.CreateDate)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败!"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	if item == nil {
+		br.Msg = "数据不存在"
+		return
+	}
+
+	err = models.DataDelete(req.TradeCode, req.CreateDate, item.Close, item.ModifyTime, sysUser.AdminId)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// @Title 数据删除校验
+// @Description 数据删除校验
+// @Param   TradeCode   query   string  true       "指标唯一编码"
+// @Param   CreateDate   query   string  true       "数据录入日期"
+// @Success Ret=200 可删除
+// @router /data/check [get]
+func (this *TargetController) DataCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	tradeCode := this.GetString("TradeCode")
+	createDate := this.GetString("CreateDate")
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	if tradeCode == "" {
+		br.Msg = "指标编码不可为空"
+		return
+	}
+	if createDate == "" {
+		br.Msg = "请选择日期"
+		return
+	}
+	item, err := models.GetDataInfo(tradeCode, createDate)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.Msg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	if item != nil {
+		br.Msg = "改日期已存在数据,是否确认修改?"
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "检测成功"
+}
+
+// @Title 指标删除校验
+// @Description 指标删除校验
+// @Param   TradeCode   query   string  true       "指标唯一编码"
+// @Success Ret=200 可删除
+// @router /target/check [get]
+func (this *TargetController) TargetCheck() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	tradeCode := this.GetString("TradeCode")
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	if tradeCode == "" {
+		br.Msg = "指标编码不可为空"
+		return
+	}
+
+	count, err := models.GetTargetInfoCount(tradeCode)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.Msg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	if count > 0 {
+		br.Msg = "该指标有关联数据,请先删除数据"
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "指标不存在关联数据,可直接删除"
+}
+
+// @Title 指标删除
+// @Description 指标删除
+// @Param	request	body models.TargetDeleteReq true "type json string"
+// @Success Ret=200 删除成功
+// @router /target/delete [post]
+func (this *TargetController) TargetDelete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	var req models.TargetDeleteReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.TradeCode == "" {
+		br.Msg = "指标编码不可为空"
+		return
+	}
+
+	err = models.TargetDelete(req.TradeCode)
+	if err != nil {
+		br.Msg = "删除失败"
+		br.Msg = "删除失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// @Title 获取研究员
+// @Description 获取研究员
+// @Success 200 {object} models.ResearcherListResp
+// @router /getResearcher [get]
+func (this *TargetController) GetResearcher() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+	var err error
+	list := make([]*models.Researcher, 0)
+	if sysUser.Role == "admin" {
+		list, err = models.GetResearcherEntry()
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.Msg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+	}
+	resp := new(models.ResearcherListResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 获取研究员指标
+// @Description 获取研究员指标
+// @Param   Mobile   query   string  true       "手机号"
+// @Success 200 {object} models.ResearcherListResp
+// @router /getTargetItems [get]
+func (this *TargetController) GetTargetItems() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请重新登录"
+		return
+	}
+
+	mobile := this.GetString("Mobile")
+
+	if mobile == "" {
+		mobile = sysUser.Mobile
+	}
+	items, err := models.GetTargetItems(mobile)
+	if err != nil {
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		br.Msg = "获取失败"
+		return
+	}
+	resp := new(models.TargetItemsResp)
+	resp.List = items
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 109 - 0
controllers/voice.go

@@ -0,0 +1,109 @@
+package controllers
+
+import (
+	"hongze/hongze_admin/models"
+	"hongze/hongze_admin/services"
+	"hongze/hongze_admin/utils"
+	"os"
+	"path"
+	"time"
+)
+
+//音频
+type VoiceController struct {
+	BaseAuthController
+}
+
+// @Title 音频上传
+// @Description 音频上传接口
+// @Param   file   query   file  true       "文件"
+// @Param   ReportId   query   int  true       "报告ID"
+// @Success Ret=200 上传成功
+// @router /upload [post]
+func (this *VoiceController) Upload() {
+	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
+	}
+	reportId, err := this.GetInt("ReportId")
+	if err != nil {
+		br.Msg = "获取资源信息失败"
+		br.ErrMsg = "获取资源信息失败,Err:" + err.Error()
+		return
+	}
+	report, err := models.GetReportItemById(reportId)
+	if err != nil {
+		br.Msg = "获取报告信息失败"
+		br.ErrMsg = "获取报告信息失败,Err:" + err.Error()
+		return
+	}
+
+	ext := path.Ext(h.Filename)
+	dateDir := time.Now().Format("20060102")
+	uploadDir := utils.STATIC_DIR + "hongze/" + dateDir
+	err = os.MkdirAll(uploadDir, 777)
+	if err != nil {
+		br.Msg = "存储目录创建失败"
+		br.ErrMsg = "存储目录创建失败,Err:" + err.Error()
+		return
+	}
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName := randStr + ext
+	fpath := uploadDir + "/" + fileName
+	defer f.Close() //关闭上传文件
+	err = this.SaveToFile("file", fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	//上传到阿里云
+	resourceUrl, err := services.UploadAudioAliyun(fileName, fpath)
+	if err != nil {
+		br.Msg = "文件上传失败"
+		br.ErrMsg = "文件上传失败,Err:" + err.Error()
+		return
+	}
+	defer func() {
+		os.Remove(fpath)
+	}()
+	item := new(models.Resource)
+	item.ResourceUrl = resourceUrl
+	item.ResourceType = 2
+	item.CreateTime = time.Now()
+	newId, err := models.AddResource(item)
+	if err != nil {
+		br.Msg = "资源上传失败"
+		br.ErrMsg = "资源上传失败,Err:" + err.Error()
+		return
+	}
+	playSeconds, err := utils.GetVideoPlaySeconds(fpath)
+	if err != nil {
+		br.Msg = "获取音频时间失败"
+		br.ErrMsg = "获取音频时间失败,Err:" + err.Error()
+		return
+	}
+	createTime := report.CreateTime.Format("0102")
+	videoName := report.Title + "(" + createTime + ")"
+	err = models.ModifyReportVideo(reportId, resourceUrl, videoName, playSeconds)
+	if err != nil {
+		br.Msg = "上传失败"
+		br.ErrMsg = "上传失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.ResourceResp)
+	resp.Id = newId
+	resp.ResourceUrl = resourceUrl
+	br.Msg = "上传成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+	return
+}

+ 55 - 0
main.go

@@ -0,0 +1,55 @@
+package main
+
+import (
+	"fmt"
+	"runtime"
+	"time"
+
+	_ "hongze/hongze_admin/routers"
+	"hongze/hongze_admin/utils"
+
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/context"
+	"github.com/astaxie/beego/logs"
+)
+
+func main() {
+	if beego.BConfig.RunMode == "dev" {
+		beego.BConfig.WebConfig.DirectoryIndex = true
+		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
+	}
+
+	beego.BConfig.RecoverFunc = Recover
+	beego.Run()
+}
+
+func Recover(ctx *context.Context) {
+	if err := recover(); err != nil {
+		if err == beego.ErrAbort {
+			return
+		}
+		if !beego.BConfig.RecoverPanic {
+			panic(err)
+		}
+		stack := ""
+		msg := fmt.Sprintf("The request url is  %v", ctx.Input.URL())
+		stack += msg + "</br>"
+		logs.Critical(msg)
+		msg = fmt.Sprintf("The request data is %v", string(ctx.Input.RequestBody))
+		stack += msg + "</br>"
+		logs.Critical(msg)
+		msg = fmt.Sprintf("Handler crashed with error %v", err)
+		stack += msg + "</br>"
+		logs.Critical(msg)
+		for i := 1; ; i++ {
+			_, file, line, ok := runtime.Caller(i)
+			if !ok {
+				break
+			}
+			logs.Critical(fmt.Sprintf("%s:%d", file, line))
+			stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d</br>", file, line))
+		}
+		go utils.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+	}
+	return
+}

+ 113 - 0
models/banner.go

@@ -0,0 +1,113 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type Banner struct {
+	Id           int       `orm:"column(id);pk"`
+	ClassifyId   int       `description:"分类id"`
+	ImageUrl     string    `description:"图片路径"`
+	BannerType   int       `description:"类型 1:轮播图,2:头部海报"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"修改时间"`
+	ClassifyName string    `description:"分类名称"`
+	JumpUrl      string    `description:"跳转地址"`
+}
+
+type BannerAddReq struct {
+	ImgUrl       string `description:"图片路径"`
+	BannerType   int    `description:"类型"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	JumpUrl      string `description:"跳转地址"`
+}
+
+
+//添加banner
+func AddBanner(item *Banner) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Insert(item)
+	return
+}
+
+type BannerEditReq struct {
+	BannerId     int    `description:"BannerId"`
+	ImgUrl       string `description:"图片路径"`
+	BannerType   int    `description:"类型"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	JumpUrl      string `description:"跳转地址"`
+}
+
+//编辑banner
+func EditBanner(item *BannerEditReq) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := " UPDATE banner SET classify_id = ?, image_url = ?, banner_type = ?,classify_name=?,jump_url=?, modify_time = NOW() WHERE id = ? "
+	o.Raw(sql, item.ClassifyId, item.ImgUrl, item.BannerType, item.ClassifyName, item.JumpUrl, item.BannerId).Exec()
+	return
+}
+
+type BannerDeleteReq struct {
+	BannerId int `description:"BannerId"`
+}
+
+func DeleteBanner(bannerId int) (err error) {
+	sql := `DELETE FROM banner WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, bannerId).Exec()
+	return
+}
+
+func GetClassify() (items []*Classify, err error) {
+	sql := `SELECT * FROM classify WHERE parent_id>0 ORDER BY id DESC `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type BannerList struct {
+	Id           int       `orm:"column(id);pk"`
+	ClassifyId   int       `description:"分类id"`
+	ImageUrl     string    `description:"图片路径"`
+	BannerType   int       `description:"类型 1:轮播图,2:头部海报"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"修改时间"`
+	ClassifyName string    `description:"分类名称"`
+	JumpUrl      string    `description:"跳转地址"`
+}
+
+//获取轮播图列表
+func GetBannerList(condition string, pars []interface{},startSize, pageSize int) (items []*BannerList, err error) {
+	sql := ` SELECT * FROM banner WHERE 1=1 `
+	if condition!="" {
+		sql+=condition
+	}
+	sql+=` ORDER BY  id DESC LIMIT ?,? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql,pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetBannerListCount(condition string, pars []interface{}) (count int, err error) {
+	sqlCount := ` SELECT * FROM banner WHERE 1=1 `
+	if condition!="" {
+		sqlCount+=condition
+	}
+
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sqlCount,pars).QueryRow(&count)
+	return
+}
+
+type BannerListResp struct {
+	List []*BannerList
+	Paging *PagingItem `description:"分页数据"`
+}

+ 37 - 0
models/base.go

@@ -0,0 +1,37 @@
+package models
+
+type BaseResponse struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string
+	ErrCode string
+	Data    interface{}
+	Success bool `description:"true 执行成功,false 执行失败"`
+}
+
+type BaseResponseRef struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string
+	ErrCode string
+	Data    string
+}
+
+type BaseResponseResult struct {
+	Ret     int    `description:"状态:200 成功,408 重新登录,403:为失败"`
+	Msg     string `description:"提示信息,对用户展示"`
+	ErrMsg  string `description:"错误信息,供开发定位问题"`
+	ErrCode string `description:"错误编码,预留"`
+	Data    string `description:"返回数据,json格式字符串"`
+}
+
+func (r *BaseResponse) Init() *BaseResponse {
+	return &BaseResponse{Ret: 403}
+}
+
+type BaseRequest struct {
+}
+
+func (br *BaseRequest) Init() *BaseRequest {
+	return &BaseRequest{}
+}

+ 216 - 0
models/classify.go

@@ -0,0 +1,216 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type Classify struct {
+	Id           int       `orm:"column(id);pk"`
+	ClassifyName string    `description:"分类名称"`
+	Sort         int       `json:"-"`
+	ParentId     int       `description:"父级分类id"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"修改时间"`
+	Abstract     string    `description:"简介"`
+	Descript     string    `description:"描述"`
+}
+
+type ClassifyAddReq struct {
+	ClassifyName string `description:"分类名称"`
+	ParentId     int    `description:"父级分类id,没有父级分类传0"`
+	Abstract     string `description:"简介"`
+	Descript     string `description:"描述"`
+}
+
+func GetClassifyByName(classifyName string, parentId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE classify_name=? AND parent_id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, classifyName, parentId).QueryRow(&item)
+	return
+}
+
+func GetClassifyById(classifyId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+//添加分类
+func AddClassify(item *Classify) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Insert(item)
+	return
+}
+
+func GetReportCountByClassifyId(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT COUNT(1) AS count FROM report WHERE classify_id_second=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func GetClassifySubCountByClassifyId(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT COUNT(1) as num FROM classify AS a
+        INNER JOIN report AS b ON a.id=b.classify_id_second
+        WHERE a.parent_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func GetClassifySubCountByParentId(classifyId int) (count int, err error) {
+	sqlCount := `
+	SELECT COUNT(1) as num FROM classify AS a
+	WHERE a.parent_id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sqlCount, classifyId).QueryRow(&count)
+	return
+}
+
+//删除分类
+func DeleteClassify(classifyId int) (err error) {
+	sql := `DELETE FROM classify WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, classifyId).Exec()
+	if err != nil {
+		return
+	}
+	deleteImgSql := `DELETE FROM banner WHERE classify_id=? `
+	_, err = o.Raw(deleteImgSql, classifyId).Exec()
+	return
+}
+
+//修改分类
+func EditClassify(classifyName, abstract, descript string, parentId, classifyId int) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE classify SET classify_name = ?,abstract=?, parent_id= ?,descript=?, modify_time= NOW() WHERE id = ? `
+	_, err = o.Raw(sql, classifyName, abstract, parentId, descript, classifyId).Exec()
+	return
+}
+
+//获取父级分类
+
+func ParentClassify() (items []*Classify, err error) {
+	sql := `SELECT * FROM classify WHERE parent_id=0 order by id desc `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+//根据id获取分类详情
+func FindByIdClassify(classifyId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+type ClassifyList struct {
+	Id           int       `orm:"column(id);pk"`
+	ClassifyName string    `description:"分类名称"`
+	Sort         int       `json:"-"`
+	ParentId     int       `description:"父级分类id"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"修改时间"`
+	Abstract     string    `description:"简介"`
+	Descript     string    `description:"描述"`
+	Child        []*Classify
+}
+
+type ClassifyListResp struct {
+	List   []*ClassifyList
+	Paging *PagingItem `description:"分页数据"`
+}
+
+//获取分类列表
+func GetClassifyList(startSize, pageSize int, keyWord string) (items []*ClassifyList, err error) {
+	sql := ``
+	if keyWord != "" {
+		sql = `SELECT * FROM (
+                   SELECT * FROM classify
+                   WHERE parent_id=0 AND classify_name LIKE '%` + keyWord + `%'
+                   UNION
+                   SELECT * FROM classify
+                   WHERE id IN(SELECT parent_id FROM classify
+                   WHERE parent_id>0 AND classify_name LIKE '%` + keyWord + `%')
+                   )AS t
+                   ORDER BY create_time ASC
+                   LIMIT ?,? `
+	} else {
+		sql = `SELECT * FROM classify WHERE parent_id=0 ORDER BY create_time ASC LIMIT ?,? `
+	}
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetClassifyListCount(keyWord string) (count int, err error) {
+	sqlCount := ``
+	if keyWord != "" {
+		sqlCount = `SELECT  COUNT(1) AS count FROM (
+               SELECT * FROM classify
+               WHERE parent_id=0 AND classify_name LIKE '%` + keyWord + `%'
+               UNION
+               SELECT * FROM classify
+               WHERE id IN(SELECT parent_id FROM classify
+               WHERE parent_id>0 AND classify_name LIKE '%` + keyWord + `%')
+               )AS t `
+	} else {
+		sqlCount = `SELECT COUNT(1) AS count FROM classify WHERE parent_id=0`
+	}
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sqlCount).QueryRow(&count)
+	return
+}
+
+type CheckDeleteClassifyReq struct {
+	ClassifyId int `description:"分类ID"`
+}
+
+type CheckDeleteClassifyResp struct {
+	Code int    `description:"编码:0:检测成功,可进行删除,1:分类不存在,2:该分类有关联报告,不允许删除,3:二级分类有关联报告,不允许删除,4:该分类下有关联分类,是否确认全部删除"`
+	Msg  string `description:"描述信息"`
+}
+
+type DeleteClassifyReq struct {
+	ClassifyId int `description:"分类ID"`
+}
+
+type EditClassifyReq struct {
+	ClassifyId   int    `description:"分类ID"`
+	ClassifyName string `description:"分类名称"`
+	ParentId     int    `description:"父级分类id"`
+	Abstract     string `description:"简介"`
+	Descript     string `description:"描述"`
+}
+
+type FindByIdClassifyReq struct {
+	ClassifyId int `description:"分类ID"`
+}
+
+func GetClassifyChild(parentId int, keyWord string) (items []*Classify, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ``
+	if keyWord != "" {
+		sql = `SELECT * FROM classify WHERE parent_id=? AND classify_name LIKE '%` + keyWord + `%' ORDER BY create_time ASC `
+	} else {
+		sql = `SELECT * FROM classify WHERE parent_id=? ORDER BY create_time ASC `
+	}
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}

+ 47 - 0
models/db.go

@@ -0,0 +1,47 @@
+package models
+
+import (
+	"hongze/hongze_data_entry/utils"
+	_ "github.com/go-sql-driver/mysql"
+	"time"
+
+	"rdluck_tools/orm"
+)
+
+func init() {
+
+	_ = orm.RegisterDataBase("default", "mysql", utils.MYSQL_URL)
+	orm.SetMaxIdleConns("default", 50)
+	orm.SetMaxOpenConns("default", 100)
+
+	db, _ := orm.GetDB("default")
+	db.SetConnMaxLifetime(10 * time.Minute)
+
+	_ = orm.RegisterDataBase("rddp", "mysql", utils.MYSQL_URL_RDDP)
+	orm.SetMaxIdleConns("rddp", 50)
+	orm.SetMaxOpenConns("rddp", 100)
+
+	report_db, _ := orm.GetDB("rddp")
+	report_db.SetConnMaxLifetime(10 * time.Minute)
+
+
+	_ = orm.RegisterDataBase("edb", "mysql", utils.MYSQL_URL_EDB)
+	orm.SetMaxIdleConns("edb", 50)
+	orm.SetMaxOpenConns("edb", 100)
+
+	edb_db, _ := orm.GetDB("edb")
+	edb_db.SetConnMaxLifetime(10 * time.Minute)
+
+	//注册对象
+	orm.RegisterModel(
+		new(SysUserLoginRecord),
+		new(SysSession),
+		new(Classify),
+		new(Banner),
+		new(Resource),
+		new(Report),
+		new(Edbdata),
+		new(EdbdataDeleteRecord),
+		new(EdbdataImportFail),
+	)
+}

+ 20 - 0
models/edbdata_import_fail.go

@@ -0,0 +1,20 @@
+package models
+
+import "rdluck_tools/orm"
+
+type EdbdataImportFail struct {
+	Id           int `orm:"column(id);pk"`
+	ClassifyName string
+	CreateDate   string
+	SecName      string
+	Close        string
+	Remark       string
+	SysUserId    string
+}
+
+func AddEdbdataImportFail(item *EdbdataImportFail) (err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Insert(item)
+	return err
+}

+ 66 - 0
models/paging.go

@@ -0,0 +1,66 @@
+package models
+
+import "hongze/hongze_admin/utils"
+
+type PagingReq struct {
+	CurrentIndex  int  `description:"当前页页码"`
+	PageSize      int  `description:"每页数据条数,如果不传,默认每页20条"`
+}
+
+type PagingItem struct {
+	IsStart       bool `description:"是否首页"`
+	IsEnd         bool `description:"是否最后一页"`
+	PreviousIndex int  `description:"上一页页码"`
+	NextIndex     int  `description:"下一页页码"`
+	CurrentIndex  int  `description:"当前页页码"`
+	Pages         int  `description:"总页数"`
+	Totals        int  `description:"总数据量"`
+	PageSize      int  `description:"每页数据条数"`
+}
+
+func GetPaging(currentIndex,pageSize,total int)(item *PagingItem)  {
+	if pageSize<=0 {
+		pageSize=utils.PageSize20
+	}
+	if currentIndex<=0 {
+		currentIndex=1
+	}
+	item=new(PagingItem)
+	item.PageSize=pageSize
+	item.Totals=total
+	item.CurrentIndex=currentIndex
+
+	if total<=0 {
+		item.IsStart=true
+		item.IsEnd=true
+		return
+	}
+	pages:=utils.PageCount(total,pageSize)
+	item.Pages=pages
+	if pages<=1 {
+		item.IsStart=true
+		item.IsEnd=true
+		item.PreviousIndex=1
+		item.NextIndex=1
+		return
+	}
+	if pages == currentIndex {
+		item.IsStart=false
+		item.IsEnd=true
+		item.PreviousIndex=currentIndex-1
+		item.NextIndex=currentIndex
+		return
+	}
+	if currentIndex==1 {
+		item.IsStart=true
+		item.IsEnd=false
+		item.PreviousIndex=1
+		item.NextIndex=currentIndex+1
+		return
+	}
+	item.IsStart=false
+	item.IsEnd=false
+	item.PreviousIndex=currentIndex-1
+	item.NextIndex=currentIndex+1
+	return
+}

+ 28 - 0
models/permission.go

@@ -0,0 +1,28 @@
+package models
+
+import "rdluck_tools/orm"
+
+//权限相关
+type ChartPermissionSearchKeyWordMapping struct {
+	Id                 int    `description:"id"`
+	ChartPermissionId  int    `description:"权限id"`
+	KeyWord            string `description:"二级分类名称"`
+	From               string `description:"类型标识"`
+	TacticType         string `description:"策略表type字段值"`
+	TeleconferenceSort int    `description:"电话会类型排序"`
+}
+
+func GetPermission(classifyNameSecond string) (items []*ChartPermissionSearchKeyWordMapping, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM chart_permission_search_key_word_mapping AS a WHERE a.from='rddp' AND a.key_word=? `
+	_, err = o.Raw(sql, classifyNameSecond).QueryRows(&items)
+	return
+}
+
+func AddChartPermissionChapterMapping(chartPermissionId int, reportId int64) (err error) {
+	sql := `INSERT INTO chart_permission_chapter_mapping (chart_permission_id, report_chapter_type_id,research_type)
+           VALUES(?,?,?)`
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, chartPermissionId, reportId, "rddp").Exec()
+	return
+}

+ 215 - 0
models/ppt.go

@@ -0,0 +1,215 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type Ppt struct {
+	PptId        int       `orm:"column(id)" description:"报告Id"`
+	Title        string    `description:"标题"`
+	TemplateType string    `description:"模版类型"`
+	PptDate      string    `description:"选择日期"`
+	PptUrl       string    `description:"ppt地址"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"修改时间"`
+	ReportType   string    `description:"报告类型"`
+}
+
+type PptImages struct {
+	PptImagesId int    `description:"Id"`
+	ImageUrl    string `description:"图片地址"`
+	ImageType   int    `description:"图片类型,0:首页背景模板"`
+}
+
+type PptPages struct {
+	PptPagesId int       `orm:"column(ppt_pages_id)" description:"报告章节Id"`
+	PptId      int64     `description:"ppt_id"`
+	Title      string    `description:"标题"`
+	ImgUrl     string    `description:"图片路径"`
+	CreateTime time.Time `description:"创建时间"`
+	ModifyTime time.Time `description:"修改时间"`
+	PageCode   string    `description:"编码"`
+	Width      int       `description:"宽度"`
+	Height     int       `description:"高端"`
+	ResourceId int       `description:"来源id,来自上海策略组提供的图表id"`
+}
+
+func GetPptList(condition string, pars []interface{}, startSize, pageSize int) (items []*Ppt, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT * FROM ppt WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += `ORDER BY create_time DESC LIMIT ?,?`
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetPptListCount(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT COUNT(1) AS count FROM ppt WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += `ORDER BY create_time DESC LIMIT ?,?`
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+type PptListResp struct {
+	List   []*Ppt
+	Paging *PagingItem `description:"分页数据"`
+}
+
+//新增PPT
+func AddPpt(item *Ppt) (lastId int64, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	lastId, err = o.Insert(item)
+	return
+}
+
+//删除ppt
+func DeletePpt(pptId int) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `DELETE FROM ppt WHERE ppt_id=? `
+	_, err = o.Raw(sql, pptId).Exec()
+	return
+}
+
+type AddPptReq struct {
+	FirstPage struct {
+		Title      string `json:"title"`
+		ReportType string `json:"report_type"`
+		PptDate    string `json:"ppt_date"`
+		ImgUrl     string `json:"img_url"`
+	} `json:"first_page"`
+	ContentPage []ContentPageItems `json:"content_page"`
+}
+
+type ContentPageItems struct {
+	PptId      int64  `json:"ppt_id" description:"ppt_id" `
+	PptPagesId int    `json:"ppt_pages_id" description:"章节id,新增时传0"`
+	Title      string `json:"title" description:"标题"`
+	ResourceId int    `json:"resource_id" description:"来源id,来自上海策略组提供的图表id"`
+}
+
+func AddPptPages(item *PptPages) (lastId int64, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	lastId, err = o.Insert(item)
+	return
+}
+
+type EditPptReq struct {
+	PptId     int64 `json:"ppt_id"`
+	FirstPage struct {
+		PptPagesId int    `json:"ppt_pages_id" description:"ppt_page_id"`
+		Title      string `json:"title" description:"标题"`
+		ReportType string `json:"report_type" description:"类型"`
+		PptDate    string `json:"ppt_date" description:"日期"`
+		ImgUrl     string `json:"img_url" description:"图片路径"`
+	} `json:"first_page"`
+	ContentPage []ContentPageItems `json:"content_page"`
+}
+
+func EditPpt(item *Ppt) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE  ppt SET title = ?,  ppt_date= ?, modify_time=NOW(),  report_type=? WHERE ppt_id = ? `
+	_, err = o.Raw(sql, item.Title, item.PptDate, item.ReportType, item.PptId).Exec()
+	return
+}
+
+func EditPptPages(item *PptPages) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE ppt_pages SET title= ?,  img_url= ?,  modify_time = now(),  resource_id = ? WHERE ppt_pages_id= ? `
+	_, err = o.Raw(sql, item.Title, item.ImgUrl, item.ResourceId, item.PptPagesId).Exec()
+	return
+}
+
+type DeletePptReq struct {
+	PptId int `json:"ppt_id" description:"ppt_id" `
+}
+
+func GetPptById(pptId int) (item *Ppt, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT * FROM ppt WHERE 1=1 AND id=? `
+	err = o.Raw(sql, pptId).QueryRow(&item)
+	return
+}
+
+func GetPptPagesById(pptId int) (items []*PptPages, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT * FROM ppt_pages WHERE ppt_id=? `
+	_, err = o.Raw(sql, pptId).QueryRows(&items)
+	return
+}
+
+type PptDetailResp struct {
+	PptPages []*PptPages `description:"ppt详情数据"`
+	Ppt      *Ppt        `description:"ppt数据"`
+}
+
+type Base64UploadReq struct {
+	Img        string `json:"img" description:"图片img base64" `
+	PptId      string `json:"title" description:"ppt_id"`
+	ResourceId int    `json:"resource_id" description:"来源id,来自上海策略组提供的图表id"`
+}
+
+//编辑ppt章节图片
+func ModifyPptPages(imgUrl string, resourceId, pptId, pptPagesId, width, height int) (err error) {
+	sql := "UPDATE ppt_pages SET img_url=?,width=?,height=? WHERE ppt_pages_id=? AND ppt_id=? AND resource_id=? "
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, imgUrl, width, height, pptPagesId, pptId, resourceId).Exec()
+	return
+}
+
+func GetImages(imageType int) (items []*PptImages, err error) {
+	sql := `SELECT * FROM ppt_images WHERE image_type=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, imageType).QueryRows(&items)
+	return
+}
+
+type PptImagesResp struct {
+	List []*PptImages `description:"ppt背景图片"`
+}
+
+type PptPublishReq struct {
+	PptId        int `json:"ppt_id"`
+	ScreenHeight int `description:"屏幕宽高"`
+}
+
+func GetPptFirstPage(pptId int) (item *PptPages, err error) {
+	sql := `SELECT * FROM ppt_pages WHERE ppt_id=? ORDER BY ppt_pages_id ASC LIMIT 1 `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, pptId).QueryRow(&item)
+	return
+}
+
+func GetPptContentPages(pptId, pptPageId int) (item []*PptPages, err error) {
+	sql := `SELECT * FROM ppt_pages WHERE ppt_id=? AND ppt_pages_id<>? ORDER BY ppt_pages_id ASC `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, pptId, pptPageId).QueryRows(&item)
+	return
+}
+
+func EditPptPath(pptId int, pptPath string) (err error) {
+	sql := `UPDATE ppt SET ppt_url=? WHERE ppt_id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, pptPath, pptId).Exec()
+	return
+}

+ 295 - 0
models/report.go

@@ -0,0 +1,295 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type Report struct {
+	Id                 int       `orm:"column(id)" description:"报告Id"`
+	AddType            int       `description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int       `description:"一级分类id"`
+	ClassifyNameFirst  string    `description:"一级分类名称"`
+	ClassifyIdSecond   int       `description:"二级分类id"`
+	ClassifyNameSecond string    `description:"二级分类名称"`
+	Title              string    `description:"标题"`
+	Abstract           string    `description:"摘要"`
+	Author             string    `description:"作者"`
+	Frequency          string    `description:"频度"`
+	CreateTime         string    `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	State              int       `description:"1:未发布,2:已发布"`
+	PublishTime        time.Time `description:"发布时间"`
+	Stage              int       `description:"期数"`
+	MsgIsSend          int       `description:"消息是否已发送,0:否,1:是"`
+	Content            string    `description:"内容"`
+	VideoUrl           string    `description:"音频文件URL"`
+	VideoName          string    `description:"音频文件名称"`
+	VideoPlaySeconds   string    `description:"音频播放时长"`
+	ContentSub         string    `description:"内容前两个章节"`
+}
+
+type ReportList struct {
+	Id                 int       `description:"报告Id"`
+	AddType            int       `description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int       `description:"一级分类id"`
+	ClassifyNameFirst  string    `description:"一级分类名称"`
+	ClassifyIdSecond   int       `description:"二级分类id"`
+	ClassifyNameSecond string    `description:"二级分类名称"`
+	Title              string    `description:"标题"`
+	Abstract           string    `description:"摘要"`
+	Author             string    `description:"作者"`
+	Frequency          string    `description:"频度"`
+	CreateTime         string    `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	State              int       `description:"1:未发布,2:已发布"`
+	PublishTime        time.Time `description:"发布时间"`
+	Stage              int       `description:"期数"`
+	MsgIsSend          int       `description:"消息是否已发送,0:否,1:是"`
+	Content            string    `description:"内容"`
+	VideoUrl           string    `description:"音频文件URL"`
+	VideoName          string    `description:"音频文件名称"`
+	VideoPlaySeconds   string    `description:"音频播放时长"`
+	ContentSub         string    `description:"内容前两个章节"`
+	Pv                 int       `description:"Pv"`
+	Uv                 int       `description:"Uv"`
+}
+
+type ReportListResp struct {
+	List   []*ReportList
+	Paging *PagingItem `description:"分页数据"`
+}
+
+func GetReportListCount(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT COUNT(1) AS count  FROM report WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetReportList(condition string, pars []interface{}, startSize, pageSize int) (items []*ReportList, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+
+	sql := `SELECT *,
+        (SELECT COUNT(1) FROM report_view_record AS rvr WHERE rvr.report_id=report.id) AS pv,
+        (SELECT COUNT(DISTINCT user_id) FROM report_view_record AS rvr WHERE rvr.report_id=report.id) AS uv
+        FROM report WHERE 1=1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += `ORDER BY  modify_time DESC LIMIT ?,?`
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+//发布报告
+func PublishReport(reportIds string) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE report SET state=2,publish_time=now(),modify_time=NOW() WHERE id IN (` + reportIds + `)`
+	_, err = o.Raw(sql).Exec()
+	return
+}
+
+//取消发布报告
+func PublishCancleReport(reportIds string) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ` UPDATE report SET state=1,publish_time=null WHERE id IN (` + reportIds + `)  `
+	_, err = o.Raw(sql).Exec()
+	return
+}
+
+//删除报告
+func DeleteReport(reportIds string) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ` DELETE FROM report WHERE id IN (` + reportIds + `)  `
+	_, err = o.Raw(sql).Exec()
+	return
+}
+
+func GetReportById(reportId int) (item *Report, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT * FROM report WHERE id=?`
+	err = o.Raw(sql, reportId).QueryRow(&item)
+	return
+}
+
+func GetReportStage(classifyIdFirst, classifyIdSecond int) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ``
+	if classifyIdSecond > 0 {
+		sql = "SELECT MAX(stage) AS max_stage FROM report WHERE classify_id_second=? "
+		o.Raw(sql, classifyIdSecond).QueryRow(&count)
+	} else {
+		sql = "SELECT MAX(stage) AS max_stage FROM report WHERE classify_id_first=? "
+		o.Raw(sql, classifyIdFirst).QueryRow(&count)
+	}
+	return
+}
+
+type PublishReq struct {
+	ReportIds string `description:"报告id,多个用英文逗号隔开"`
+}
+
+type DeleteReq struct {
+	ReportIds string `description:"报告id,多个用英文逗号隔开"`
+}
+
+type AddReq struct {
+	AddType            int    `description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int    `description:"一级分类id"`
+	ClassifyNameFirst  string `description:"一级分类名称"`
+	ClassifyIdSecond   int    `description:"二级分类id"`
+	ClassifyNameSecond string `description:"二级分类名称"`
+	Title              string `description:"标题"`
+	Abstract           string `description:"摘要"`
+	Author             string `description:"作者"`
+	Frequency          string `description:"频度"`
+	State              int    `description:"状态:1:未发布,2:已发布"`
+	Content            string `description:"内容"`
+	CreateTime         string `description:"创建时间"`
+}
+
+type AddResp struct {
+	ReportId int64 `description:"报告id"`
+}
+
+func AddReport(item *Report) (lastId int64, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	lastId, err = o.Insert(item)
+	return
+}
+
+type EditReq struct {
+	ReportId           int64  `description:"报告id"`
+	ClassifyIdFirst    int    `description:"一级分类id"`
+	ClassifyNameFirst  string `description:"一级分类名称"`
+	ClassifyIdSecond   int    `description:"二级分类id"`
+	ClassifyNameSecond string `description:"二级分类名称"`
+	Title              string `description:"标题"`
+	Abstract           string `description:"摘要"`
+	Author             string `description:"作者"`
+	Frequency          string `description:"频度"`
+	State              int    `description:"状态:1:未发布,2:已发布"`
+	Content            string `description:"内容"`
+	CreateTime         string `description:"创建时间"`
+}
+
+type EditResp struct {
+	ReportId int64 `description:"报告id"`
+}
+
+func EditReport(item *Report, reportId int64) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE report
+			SET
+			  classify_id_first =?,
+			  classify_name_first = ?,
+			  classify_id_second = ?,
+			  classify_name_second = ?,
+			  title = ?,
+			  abstract = = ?,
+			  author = = ?,
+			  frequency = = ?,
+			  state = = ?,
+			  content = = ?,
+			  content_sub = = ?,
+			  create_time=?,
+			  modify_time = = ?
+			WHERE id = ? `
+	_, err = o.Raw(sql, item.ClassifyIdFirst, item.ClassifyNameFirst, item.ClassifyIdSecond, item.ClassifyNameSecond, item.Title,
+		item.Abstract, item.Frequency, item.State, item.Content, item.ContentSub, item.CreateTime, time.Now(), item.Id).Exec()
+	return
+}
+
+type ReportDetailReq struct {
+	ReportId int `description:"报告id"`
+}
+
+type ClassifyIdDetailReq struct {
+	ClassifyIdFirst  int `description:"报告一级分类id"`
+	ClassifyIdSecond int `description:"报告二级分类id"`
+}
+
+func GetReportDetailByClassifyId(classifyIdFirst, classifyIdSecond int) (item *Report, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ` SELECT * FROM report WHERE 1=1 `
+	if classifyIdSecond > 0 {
+		sql = sql + ` AND classify_id_second=?   ORDER BY stage DESC LIMIT 1`
+		err = o.Raw(sql, classifyIdSecond).QueryRow(&item)
+	} else {
+		sql = sql + ` AND classify_id_first=?   ORDER BY stage DESC LIMIT 1`
+		err = o.Raw(sql, classifyIdFirst).QueryRow(&item)
+	}
+	return
+}
+
+type SendTemplateMsgReq struct {
+	ReportId int `description:"报告id"`
+}
+
+func ModifyReportMsgIsSend(reportId int) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	report, err := GetReportById(reportId)
+	if err != nil {
+		return
+	}
+	if report.MsgIsSend == 0 {
+		sql := `UPDATE report SET msg_is_send = 1 WHERE id = ? `
+		_, err = o.Raw(sql, reportId).Exec()
+	}
+	return
+}
+
+func ModifyReportVideo(reportId int, videoUrl, videoName string, playSeconds float64) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE report SET video_url=?,video_name=?,video_play_seconds=? WHERE id=? `
+	_, err = o.Raw(sql, videoUrl, videoName, playSeconds, reportId).Exec()
+	return
+}
+
+type ReportItem struct {
+	Id                 int       `orm:"column(id)" description:"报告Id"`
+	AddType            int       `description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int       `description:"一级分类id"`
+	ClassifyNameFirst  string    `description:"一级分类名称"`
+	ClassifyIdSecond   int       `description:"二级分类id"`
+	ClassifyNameSecond string    `description:"二级分类名称"`
+	Title              string    `description:"标题"`
+	Abstract           string    `description:"摘要"`
+	Author             string    `description:"作者"`
+	Frequency          string    `description:"频度"`
+	CreateTime         time.Time `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	State              int       `description:"1:未发布,2:已发布"`
+	PublishTime        time.Time `description:"发布时间"`
+	Stage              int       `description:"期数"`
+	MsgIsSend          int       `description:"消息是否已发送,0:否,1:是"`
+	Content            string    `description:"内容"`
+	VideoUrl           string    `description:"音频文件URL"`
+	VideoName          string    `description:"音频文件名称"`
+	VideoPlaySeconds   string    `description:"音频播放时长"`
+	ContentSub         string    `description:"内容前两个章节"`
+}
+
+func GetReportItemById(reportId int) (item *ReportItem, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT * FROM report WHERE id=?`
+	err = o.Raw(sql, reportId).QueryRow(&item)
+	return
+}

+ 21 - 0
models/report_author.go

@@ -0,0 +1,21 @@
+package models
+
+import "rdluck_tools/orm"
+
+type ReportAuthor struct {
+	Id           int    `description:"报告作者ID"`
+	ReportAuthor string `description:"报告作者名称"`
+}
+
+//获取报告作者
+func GetReportAuthor() (items []*ReportAuthor, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ` SELECT * FROM report_author ORDER BY id desc `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type ReportAuthorResp struct {
+	List []*ReportAuthor
+}

+ 30 - 0
models/resource.go

@@ -0,0 +1,30 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type Resource struct {
+	Id           int       `orm:"column(id);" description:"资源id"`
+	ResourceUrl  string    `description:"资源地址"`
+	CreateTime   time.Time `description:"创建时间"`
+	ResourceType int       `description:"资源类型,1:图片,2:音频,3:视频 "`
+}
+
+type ResourceResp struct {
+	Id          int64  `orm:"column(id);" description:"用户id"`
+	ResourceUrl string `description:"资源地址"`
+}
+
+func AddResource(item *Resource) (newId int64, err error) {
+	o := orm.NewOrm()
+	newId, err = o.Insert(item)
+	return
+}
+
+func GetResourceById(id string) (item *Resource, err error) {
+	sql := "SELECT * FROM resource WHERE id=? "
+	err = orm.NewOrm().Raw(sql, id).QueryRow(&item)
+	return
+}

+ 41 - 0
models/sys_session.go

@@ -0,0 +1,41 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type SysSession struct {
+	Id              int `orm:"column(id);pk"`
+	SysUserId       int
+	UserName        string
+	AccessToken     string
+	ExpiredTime     time.Time
+	CreatedTime     time.Time
+	LastUpdatedTime time.Time
+}
+
+//新增用户登录session信息
+func AddSysSession(item *SysSession) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Insert(item)
+	return
+}
+
+func GetSysSessionBySysUserId(sysUserId int) (item *SysSession, err error) {
+	sql := `SELECT * FROM sys_session WHERE sys_user_id=? AND expired_time> NOW() ORDER BY expired_time DESC LIMIT 1 `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, sysUserId).QueryRow(&item)
+	return
+}
+
+
+func GetSysSessionByToken(token string) (item *SysSession, err error) {
+	sql := `SELECT * FROM sys_session WHERE access_token=? AND expired_time> NOW() ORDER BY expired_time DESC LIMIT 1 `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, token).QueryRow(&item)
+	return
+}

+ 57 - 0
models/sys_user.go

@@ -0,0 +1,57 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type LoginReq struct {
+	Username string `description:"账号"`
+	Password string `description:"密码"`
+}
+
+type LoginResp struct {
+	Authorization string
+}
+
+type Admin struct {
+	AdminId                 int    `description:"系统用户id"`
+	AdminName               string `description:"系统用户名称"`
+	RealName                string `description:"系统用户姓名"`
+	Password                string `json:"-"`
+	LastUpdatedPasswordTime string `json:"-"`
+	Enabled                 int
+	Email                   string `description:"系统用户邮箱"`
+	LastLoginTime           string
+	CreatedTime             time.Time
+	LastUpdatedTime         string
+	Role                    string `description:"系统用户角色"`
+	Mobile                  string `description:"手机号"`
+	RoleType                int    `description:"角色类型:1需要录入指标,0:不需要"`
+}
+
+func CheckSysUser(userName, password string) (item *Admin, err error) {
+	sql := `SELECT * FROM admin WHERE admin_name=? AND password=? LIMIT 1`
+	o := orm.NewOrm()
+	err = o.Raw(sql, userName, password).QueryRow(&item)
+	return
+}
+
+func GetSysUserById(sysUserId int) (item *Admin, err error) {
+	sql := `SELECT * FROM admin WHERE admin_id=? LIMIT 1`
+	o := orm.NewOrm()
+	err = o.Raw(sql, sysUserId).QueryRow(&item)
+	return
+}
+
+func ModifyPwd(sysUserId int, newPwd string) (err error) {
+	sql := `UPDATE admin SET password=?,last_updated_time=NOW() WHERE admin_id=? `
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, newPwd, sysUserId).Exec()
+	return
+}
+
+type ModifyPwdReq struct {
+	OldPwd string `description:"旧密码"`
+	NewPwd string `description:"新密码"`
+}

+ 23 - 0
models/sys_user_login_record.go

@@ -0,0 +1,23 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+type SysUserLoginRecord struct {
+	Id         int `orm:"column(id);pk"`
+	Uid        int
+	UserName   string
+	Ip         string
+	Stage      string
+	CreateTime time.Time
+}
+
+//新增登录记录
+func AddSysUserLoginRecord(item *SysUserLoginRecord) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Insert(item)
+	return
+}

+ 768 - 0
models/target.go

@@ -0,0 +1,768 @@
+package models
+
+import (
+	"fmt"
+	"hongze/hongze_admin/utils"
+	"rdluck_tools/orm"
+	"sort"
+	"strings"
+	"time"
+)
+
+type DataList struct {
+	TradeCode    string  `orm:"column(TRADE_CODE)" description:"指标编码"`
+	SecName      string  `orm:"column(SEC_NAME)" description:"指标名称"`
+	Unit         string  `orm:"column(UNIT)" description:"单位"`
+	Remark       string  `orm:"column(REMARK)" description:"备注"`
+	Frequency    string  `description:"频度"`
+	ClassifyId   int     `description:"分类id"`
+	ClassifyName string  `description:"分类名称"`
+	Dt           string  `orm:"column(DT)" description:"录入日期"`
+	Close        float64 `orm:"column(CLOSE)" description:"录入值"`
+	ModifyTime   string  `description:"修改时间"`
+}
+
+type DataListResp struct {
+	List   []*DataList
+	Paging *PagingItem `description:"分页数据"`
+}
+
+func GetDataList(condition string, pars []interface{}, startSize, pageSize int) (items []*DataList, err error) {
+	sql := `select a.TRADE_CODE,a.SEC_NAME,a.UNIT,a.frequency,a.classify_id,b.classify_name,c.DT,c.CLOSE,c.modify_time FROM edbdata AS c
+                inner join edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+                left join edbdata_classify AS b ON a.classify_id=b.classify_id
+                where left(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0`
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` order by c.DT desc limit ?,? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func GetDataListCount(condition string, pars []interface{}) (count int, err error) {
+	sql := ` select count(1) as count FROM edbdata AS c
+                    inner join edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE    
+                    left join edbdata_classify AS b ON a.classify_id=b.classify_id
+                    where left(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0 `
+	if condition != "" {
+		sql += condition
+	}
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+type DataAddReq struct {
+	TradeCode  string  `description:"指标唯一编码"`
+	CreateDate string  `description:"创建日期"`
+	Close      float64 `description:"录入值"`
+}
+
+type Edbdata struct {
+	TradeCode  string    `orm:"column(TRADE_CODE);pk" description:"指标编码"`
+	Dt         string    `orm:"column(DT)" description:"日期"`
+	Close      float64   `orm:"column(CLOSE)" description:"值"`
+	ModifyTime time.Time `orm:"column(modify_time)" description:"修改时间"`
+}
+
+func GetDataInfo(tradeCode, creteDate string) (item *Edbdata, err error) {
+	sql := " SELECT * FROM edbdata WHERE TRADE_CODE=? AND DT=? "
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, tradeCode, creteDate).QueryRow(&item)
+	return
+}
+
+func AddEdbdata(item *Edbdata) (lastId int64, err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	lastId, err = o.Insert(item)
+	return
+}
+
+type DataEditReq struct {
+	TradeCode     string  `description:"指标唯一编码"`
+	CreateDate    string  `description:"创建日期"`
+	Close         float64 `description:"录入值"`
+	OldCreateDate string  `description:"旧的录入日期"`
+}
+
+//编辑数据
+func EditEdbdata(item *Edbdata) (err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ` UPDATE edbdata SET CLOSE = ?,modify_time=NOW() WHERE TRADE_CODE = ? AND DT = ? `
+	_, err = o.Raw(sql, item.Close, item.TradeCode, item.Dt).Exec()
+	return
+}
+
+type EdbdataDeleteRecord struct {
+	Id         int       `orm:"column(id);pk"`
+	TradeCode  string    `orm:"column(TRADE_CODE)" description:"指标编码"`
+	Dt         string    `orm:"column(DT)" description:"日期"`
+	Close      float64   `orm:"column(CLOSE)" description:"值"`
+	ModifyTime time.Time `orm:"column(modify_time)" description:"修改时间"`
+	CreateTime time.Time
+	SysUserId  int
+}
+
+func AddEdbdataDeleteRecord(item *EdbdataDeleteRecord) (lastId int64, err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	lastId, err = o.Insert(item)
+	return
+}
+
+//删除数据
+func DeleteEdbData(tradeCode, dt string) (err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ` DELETE FROM edbdata WHERE TRADE_CODE = ? AND DT = ? `
+	_, err = o.Raw(sql, tradeCode, dt).Exec()
+	return
+}
+
+type Edbinfo struct {
+	TradeCode    string `orm:"column(TRADE_CODE);pk" description:"指标code"`
+	SecName      string `orm:"column(SEC_NAME);" description:"指标名称"`
+	Unit         string `orm:"column(UNIT);" description:"单位"`
+	Remark       string `orm:"column(REMARK);" description:"备注"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	CreateDate   string `description:"创建时间"`
+	UserId       int    `description:"录入用户id"`
+	NoticeTime   string `description:"通知时间"`
+	Mobile       string `description:"录入者手机号"`
+}
+
+func GetEdbinfoListCount(condition string, pars []interface{}, mobile string) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ``
+	if mobile != "" {
+		sql = `SELECT COUNT(1) AS count FROM edbinfo AS a 
+             INNER JOIN edbinfo_user AS c ON a.TRADE_CODE=c.TRADE_CODE AND c.mobile=?
+             WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0`
+
+		if condition != "" {
+			sql += condition
+		}
+		err = o.Raw(sql, mobile, pars).QueryRow(&count)
+	} else {
+		sql := `SELECT COUNT(1) AS count FROM edbinfo AS a WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0`
+
+		if condition != "" {
+			sql += condition
+		}
+		err = o.Raw(sql, pars).QueryRow(&count)
+	}
+	return
+}
+
+func GetEdbinfoList(condition string, pars []interface{}, startSize, pageSize int, mobile string) (items []*Edbinfo, err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ``
+	if mobile != "" {
+		sql = ` SELECT a.*,b.classify_name FROM edbinfo AS a
+                    LEFT JOIN edbdata_classify AS b ON a.classify_id=b.classify_id
+                    INNER JOIN edbinfo_user AS c ON a.TRADE_CODE=c.TRADE_CODE AND c.mobile=?
+                    WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0`
+		if condition != "" {
+			sql += condition
+		}
+		sql += ` ORDER BY c.DT DESC LIMIT ?,? `
+		_, err = o.Raw(sql, mobile, pars).QueryRows(&items)
+	} else {
+		sql = `SELECT a.*,b.classify_name FROM edbinfo AS a
+                     LEFT JOIN edbdata_classify AS b on a.classify_id=b.classify_id
+                     WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0`
+		if condition != "" {
+			sql += condition
+		}
+		sql += ` ORDER BY c.DT DESC LIMIT ?,? `
+		_, err = o.Raw(sql, pars).QueryRows(&items)
+	}
+	return
+}
+
+type TargetListResp struct {
+	List   []*Edbinfo
+	Paging *PagingItem `description:"分页数据"`
+}
+
+type EdbinfoAddReq struct {
+	SecName    string `description:"指标名称"`
+	Unit       string `description:"单位"`
+	Frequency  string `description:"频度"`
+	ClassifyId int    `description:"分类id"`
+	NoticeTime string `description:"通知时间"`
+}
+
+//获取指标最大trade_code
+func GetMaxTradeCode() (max_trade_code string, err error) {
+	sql := " SELECT MAX(TRADE_CODE) AS max_trade_code FROM edbinfo WHERE LEFT(TRADE_CODE,1)='W' AND REMARK='手动' "
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql).QueryRow(&max_trade_code)
+	return
+}
+
+func GetEdbinfoBySecName(secName string) (item *Edbinfo, err error) {
+	sql := `SELECT * FROM edbinfo WHERE SEC_NAME=? AND left(TRADE_CODE,1)='W' AND REMARK='手动' `
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, secName).QueryRow(&item)
+	return
+}
+
+func AddEdbinfo(tradeCode, secName, unit, remark, frequency, noticeTime string, classifyId int, userId int) (err error) {
+	sql := `INSERT INTO edbinfo(TRADE_CODE, SEC_NAME,UNIT, REMARK,frequency, classify_id,notice_time,user_id) 
+			VALUES(?,?,?,?,?,?,?,?,?) `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, tradeCode, secName, unit, remark, frequency, classifyId, noticeTime, userId).Exec()
+	return
+}
+
+func AddEdbinfoUser(tradeCode, mobile string) (err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := `INSERT INTO edbinfo_user(TRADE_CODE, mobile) VALUES (?,?)`
+	_, err = o.Raw(sql, tradeCode, mobile).Exec()
+	return
+}
+
+type EdbinfoEditReq struct {
+	TradeCode  string `description:"指标code"`
+	SecName    string `description:"指标名称"`
+	Unit       string `description:"单位"`
+	Frequency  string `description:"频度"`
+	ClassifyId int    `description:"分类id"`
+	NoticeTime string `description:"通知时间"`
+}
+
+func EditEdbinfo(tradeCode, secName, unit, frequency, noticeTime string, classifyId int) (err error) {
+	sql := `UPDATE edbinfo SET SEC_NAME= ?, UNIT = ?,classify_id=?,frequency=?,notice_time=?,create_date=NOW() WHERE TRADE_CODE=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, secName, unit, classifyId, frequency, noticeTime, tradeCode).Exec()
+	return
+}
+
+func SearchTargetEntry(classifyId int, keyWord string) (items []*Edbinfo, err error) {
+	where := ""
+	if keyWord != "" {
+		where = `AND SEC_NAME LIKE '%` + keyWord + `%'`
+	}
+	sql := `SELECT * FROM edbinfo WHERE LEFT(TRADE_CODE,1)='W' AND REMARK='手动' AND classify_id>0 AND classify_id=? `
+	sql += where
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, classifyId).QueryRows(&items)
+	return
+}
+
+type SearchTargetListResp struct {
+	List []*Edbinfo
+}
+
+type EdbdataClassify struct {
+	ClassifyId   int
+	ClassifyName string
+	ParentId     int
+}
+
+func GetEdbdataClassifyByClassifyName(classifyName string) (item *EdbdataClassify, err error) {
+	sql := `SELECT * FROM edbdata_classify WHERE classify_name=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, classifyName).QueryRow(&item)
+	return
+}
+
+type EdbdataClassifyList struct {
+	ClassifyId   int
+	ClassifyName string
+	ParentId     int
+	Child        []*EdbdataClassify
+}
+
+func GetEdbdataClassify(userId int64) (items []*EdbdataClassifyList, err error) {
+	var newItems []*EdbdataClassifyList
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ` SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id=0 `
+	_, err = o.Raw(sql).QueryRows(&newItems)
+	if err != nil {
+		return
+	}
+	classifyLen := len(newItems)
+	for i := 0; i < classifyLen; i++ {
+		var childItems []*EdbdataClassify
+		parentId := newItems[i].ClassifyId
+		childSql := ``
+		if userId > 0 {
+			childSql = "SELECT a.classify_id,a.classify_name,a.parent_id FROM edbdata_classify AS a INNER JOIN edbdata_classify_user AS b ON a.classify_id=b.classify_id WHERE b.user_id =? AND parent_id=? ORDER BY create_time ASC "
+			_, err = o.Raw(childSql, userId, parentId).QueryRows(&childItems)
+		} else {
+			childSql = "SELECT classify_id,classify_name,parent_id FROM edbdata_classify WHERE parent_id=? ORDER BY create_time ASC "
+			_, err = o.Raw(childSql, parentId).QueryRows(&childItems)
+		}
+		if err != nil {
+			return
+		}
+		newItems[i].Child = childItems
+	}
+	for _, v := range newItems {
+		childLen := len(v.Child)
+		if childLen > 0 {
+			items = append(items, v)
+		}
+	}
+	return
+}
+
+type EdbdataClassifyResp struct {
+	List []*EdbdataClassifyList
+}
+
+func GetTargetBySecName(secName string) (item *Edbinfo, err error) {
+	sql := `SELECT * FROM edbinfo WHERE SEC_NAME=? AND left(TRADE_CODE,1)='W' AND REMARK='手动' `
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, secName).QueryRow(&item)
+	return
+}
+
+func ModifyTargetClassifyId(tradeCode string, classifyId int) (err error) {
+	sql := `UPDATE edbinfo SET classify_id=? WHERE TRADE_CODE=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, classifyId, tradeCode).Exec()
+	return
+}
+
+func GetTargetsDataCount(tradeCode, dt string) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, tradeCode, dt).QueryRow(&count)
+	return
+}
+
+func GetTargetsData(tradeCode, dt string) (item *Edbdata, err error) {
+	sql := `SELECT * FROM edbdata WHERE TRADE_CODE=? AND DT=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, tradeCode, dt).QueryRow(&item)
+	return
+}
+
+func ModifyTargetsDataByImport(tradeCode, dt, close string) (err error) {
+	sql := `UPDATE  edbdata SET CLOSE=?,modify_time=NOW() WHERE  TRADE_CODE=? AND DT=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, close, tradeCode, dt).Exec()
+	return
+}
+
+func AddTargetsDataByImport(tradeCode, dt, close string) (err error) {
+	sql := `INSERT INTO edbdata(TRADE_CODE, DT,CLOSE, modify_time)VALUES(?,?,?,NOW()) `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, tradeCode, dt, close).Exec()
+	return
+}
+
+type EdbdataImportResp struct {
+	Status int
+	Msg    string
+}
+
+func GetFailList(sysUserId int) (items []*EdbdataImportFail, err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ` SELECT * FROM edbdata_import_fail WHERE sys_user_id=? `
+	_, err = o.Raw(sql, sysUserId).QueryRows(&items)
+	return
+}
+
+type DataListForExport struct {
+	TradeCode    string `orm:"column(TRADE_CODE)" description:"指标code"`
+	SecName      string `orm:"column(SEC_NAME)" description:"指标名称"`
+	Unit         string `orm:"column(UNIT)" description:"单位"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	NoticeTime   string `description:"通知时间"`
+	ClassifyName string
+	Dt           string  `orm:"column(DT)" description:"日期"`
+	Close        float64 `orm:"column(CLOSE)" description:"值"`
+}
+
+func GetDataListForExport(startDate, endDate, frequency, keyWord string, classifyId int) (items []*DataListForExport, err error) {
+	where := ``
+	var pars []interface{}
+	if keyWord != "" {
+		where = ` AND SEC_NAME LIKE '%` + keyWord + `%`
+	}
+	if startDate != "" {
+		where += ` AND create_date>=? `
+		pars = append(pars, startDate)
+	}
+	if endDate != "" {
+		where += ` AND create_date<=? `
+		pars = append(pars, endDate)
+	}
+	if frequency != "" {
+		where += ` AND frequency=? `
+		pars = append(pars, frequency)
+	}
+	if classifyId > 0 {
+		where += ` AND classify_id=? `
+		pars = append(pars, classifyId)
+	}
+
+	sql := ` SELECT a.TRADE_CODE,a.SEC_NAME,a.UNIT,a.frequency,a.classify_id,b.classify_name,c.DT,c.CLOSE FROM edbdata AS c
+                INNER JOIN edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+                LEFT JOIN edbdata_classify AS b ON a.classify_id=b.classify_id
+                WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0 `
+	if where != "" {
+		sql += where
+	}
+	sql = sql + " ORDER BY c.DT DESC "
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+type DataDeleteReq struct {
+	TradeCode  string `description:"指标唯一编码"`
+	CreateDate string `description:"数据录入日期"`
+}
+
+func DataDelete(tradeCode, createDate string, close float64, modifyTime time.Time, sysUserId int) (err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	o.Begin()
+	defer func() {
+		if err != nil {
+			o.Rollback()
+		} else {
+			o.Commit()
+		}
+	}()
+	recordSql := ` INSERT INTO edbdata_delete_record(TRADE_CODE,DT,CLOSE,modify_time,create_time,sys_user_id) 
+                 VALUES(?,?,?,?,?,?)`
+	_, err = o.Raw(recordSql, tradeCode, createDate, close, modifyTime, time.Now(), sysUserId).Exec()
+	sql := ` DELETE FROM edbdata WHERE TRADE_CODE = ? AND DT = ? `
+	_, err = o.Raw(sql, tradeCode, createDate).Exec()
+	return
+}
+
+func GetTargetInfoCount(tradeCode string) (count int, err error) {
+	sql := ` SELECT COUNT(1) AS count FROM edbdata AS c
+           INNER JOIN edbinfo AS a ON a.TRADE_CODE=c.TRADE_CODE
+           WHERE a.TRADE_CODE=? `
+	o := orm.NewOrm()
+	o.Using("edb")
+	err = o.Raw(sql, tradeCode).QueryRow(&count)
+	return
+}
+
+type TargetDeleteReq struct {
+	TradeCode string `description:"指标唯一编码"`
+}
+
+func TargetDelete(tradeCode string) (err error) {
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := " DELETE FROM edbinfo WHERE TRADE_CODE = ? "
+	_, err = o.Raw(sql, tradeCode).Exec()
+	return
+}
+
+type Researcher struct {
+	AdminId     int    `description:"系统用户id"`
+	AdminName   string `description:"系统用户名称"`
+	RealName    string `description:"系统用户姓名"`
+	Role        string `description:"系统用户角色"`
+	Mobile      string `description:"手机号"`
+	TargetCount int    `description:"指标数量"`
+}
+
+type ResearcherListResp struct {
+	List []*Researcher
+}
+
+func GetResearcherEntry() (items []*Researcher, err error) {
+	sql := ` SELECT admin_id,admin_name,real_name,mobile,0 as target_count FROM admin WHERE role='researcher' AND role_type=1 `
+	o := orm.NewOrm()
+	o.Using("edb")
+	_, err = o.Raw(sql).QueryRows(&items)
+	researchLen := len(items)
+	for i := 0; i < researchLen; i++ {
+		var count int
+		mobile := items[i].Mobile
+
+		sqlCount := ` SELECT COUNT(DISTINCT a.TRADE_CODE) AS count FROM  edbinfo_user AS a
+            INNER JOIN edbinfo AS b ON a.TRADE_CODE=b.TRADE_CODE
+            WHERE a.mobile=? AND LEFT(b.TRADE_CODE,1)='W' AND b.REMARK='手动' AND b.classify_id>0 `
+		err = o.Raw(sqlCount, mobile).QueryRow(&count)
+		items[i].TargetCount = count
+	}
+	return
+}
+
+type EdbinfoItems struct {
+	TradeCode    string `orm:"column(TRADE_CODE);pk" description:"指标code"`
+	SecName      string `orm:"column(SEC_NAME);" description:"指标名称"`
+	Unit         string `orm:"column(UNIT);" description:"单位"`
+	Remark       string `orm:"column(REMARK);" description:"备注"`
+	Frequency    string `description:"频度"`
+	ClassifyId   int    `description:"分类id"`
+	ClassifyName string `description:"分类名称"`
+	CreateDate   string `description:"创建时间"`
+	UserId       int    `description:"录入用户id"`
+	NoticeTime   string `description:"通知时间"`
+	Mobile       string `description:"录入者手机号"`
+	ModifyDate   string `description:"待更新日期"`
+	Status       string `description:"状态:未完成/完成"`
+}
+
+type TargetItemsResp struct {
+	List SortEdbInfo
+}
+
+type SortEdbInfo []EdbinfoItems
+
+func GetTargetItems(mobile string) (lastItems SortEdbInfo, err error) {
+	var items []*EdbinfoItems
+	o := orm.NewOrm()
+	o.Using("edb")
+	sql := ` SELECT *,'' modify_date,'' status FROM edbinfo AS a WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0 `
+	if mobile != "" {
+		sql = ` SELECT *,'' modify_date,'' status FROM edbinfo AS a 
+            INNER JOIN edbinfo_user AS b ON a.TRADE_CODE=b.TRADE_CODE
+            WHERE LEFT(a.TRADE_CODE,1)='W' AND a.REMARK='手动' AND a.classify_id>0
+            AND b.mobile='` + mobile + `'`
+	}
+	sql = sql + ` ORDER BY CONVERT(a.SEC_NAME USING gbk )  COLLATE gbk_chinese_ci ASC `
+	_, err = o.Raw(sql).QueryRows(&items)
+	if err != nil {
+		return
+	}
+	itemsLen := len(items)
+	nowWeek := time.Now().Weekday().String()
+
+	fmt.Println(nowWeek)
+	finishEdbInfo := SortEdbInfo{}
+	unFinishEdbInfo := SortEdbInfo{}
+
+	for i := 0; i < itemsLen; i++ {
+		noticeTime := items[i].NoticeTime
+		frequency := items[i].Frequency
+		tradeCode := items[i].TradeCode
+
+		if noticeTime != "" {
+			if frequency == "周度" {
+				noticeArr := strings.Split(noticeTime, " ")
+				noticeWeek := noticeArr[0]
+				fmt.Println(noticeWeek)
+				addDay := 0
+
+				if nowWeek == "Sunday" {
+					if noticeWeek == "周日" {
+						addDay = 0
+					} else if noticeWeek == "周一" {
+						addDay = 1
+					} else if noticeWeek == "周二" {
+						addDay = 2
+					} else if noticeWeek == "周三" {
+						addDay = 3
+					} else if noticeWeek == "周四" {
+						addDay = 4
+					} else if noticeWeek == "周五" {
+						addDay = 5
+					} else if noticeWeek == "周六" {
+						addDay = 6
+					} else {
+						addDay = 0
+					}
+				} else if nowWeek == "Monday" {
+					if noticeWeek == "周日" {
+						addDay = 6
+					} else if noticeWeek == "周一" {
+						addDay = 0
+					} else if noticeWeek == "周二" {
+						addDay = 1
+					} else if noticeWeek == "周三" {
+						addDay = 2
+					} else if noticeWeek == "周四" {
+						addDay = 3
+					} else if noticeWeek == "周五" {
+						addDay = 4
+					} else if noticeWeek == "周六" {
+						addDay = 5
+					} else {
+						addDay = 0
+					}
+				} else if nowWeek == "Tuesday" {
+					if noticeWeek == "周日" {
+						addDay = 5
+					} else if noticeWeek == "周一" {
+						addDay = 6
+					} else if noticeWeek == "周二" {
+						addDay = 0
+					} else if noticeWeek == "周三" {
+						addDay = 1
+					} else if noticeWeek == "周四" {
+						addDay = 2
+					} else if noticeWeek == "周五" {
+						addDay = 3
+					} else if noticeWeek == "周六" {
+						addDay = 4
+					} else {
+						addDay = 0
+					}
+				} else if nowWeek == "Wednesday" {
+					if noticeWeek == "周日" {
+						addDay = 4
+					} else if noticeWeek == "周一" {
+						addDay = 5
+					} else if noticeWeek == "周二" {
+						addDay = 6
+					} else if noticeWeek == "周三" {
+						addDay = 0
+					} else if noticeWeek == "周四" {
+						addDay = 1
+					} else if noticeWeek == "周五" {
+						addDay = 2
+					} else if noticeWeek == "周六" {
+						addDay = 3
+					} else {
+						addDay = 0
+					}
+				} else if nowWeek == "Thursday" {
+					if noticeWeek == "周日" {
+						addDay = 3
+					} else if noticeWeek == "周一" {
+						addDay = 4
+					} else if noticeWeek == "周二" {
+						addDay = 5
+					} else if noticeWeek == "周三" {
+						addDay = 6
+					} else if noticeWeek == "周四" {
+						addDay = 0
+					} else if noticeWeek == "周五" {
+						addDay = 1
+					} else if noticeWeek == "周六" {
+						addDay = 2
+					} else {
+						addDay = 0
+					}
+				} else if nowWeek == "Friday" {
+					if noticeWeek == "周日" {
+						addDay = 2
+					} else if noticeWeek == "周一" {
+						addDay = 3
+					} else if noticeWeek == "周二" {
+						addDay = 4
+					} else if noticeWeek == "周三" {
+						addDay = 5
+					} else if noticeWeek == "周四" {
+						addDay = 6
+					} else if noticeWeek == "周五" {
+						addDay = 0
+					} else if noticeWeek == "周六" {
+						addDay = 1
+					} else {
+						addDay = 0
+					}
+				} else if nowWeek == "Saturday" {
+					if noticeWeek == "周日" {
+						addDay = 1
+					} else if noticeWeek == "周一" {
+						addDay = 2
+					} else if noticeWeek == "周二" {
+						addDay = 3
+					} else if noticeWeek == "周三" {
+						addDay = 4
+					} else if noticeWeek == "周四" {
+						addDay = 5
+					} else if noticeWeek == "周五" {
+						addDay = 6
+					} else if noticeWeek == "周六" {
+						addDay = 0
+					} else {
+						addDay = 0
+					}
+				}
+
+				modifyDate := time.Now().AddDate(0, 0, addDay)
+				modifyDateStr := modifyDate.Format(utils.FormatDate)
+				items[i].ModifyDate = modifyDateStr
+
+				modifyDateEndStr := modifyDate.AddDate(0, 0, -7).Format(utils.FormatDate)
+
+				fmt.Println("addDay:", addDay)
+				fmt.Println("modifyDateEndStr:", modifyDateEndStr)
+
+				count := 0
+				sqlCount := ` SELECT COUNT(1) AS num FROM edbdata WHERE TRADE_CODE=? AND DT >= ? AND DT <= ? `
+				err = o.Raw(sqlCount, tradeCode, modifyDateEndStr, modifyDateStr).QueryRow(&count)
+				if err != nil {
+					return nil, err
+				}
+				if count > 0 {
+					items[i].Status = "完成"
+					finishEdbInfo = append(finishEdbInfo, *items[i])
+				} else {
+					items[i].Status = "未完成"
+					unFinishEdbInfo = append(unFinishEdbInfo, *items[i])
+				}
+			}
+		} else {
+			items[i].Status = "完成"
+			finishEdbInfo = append(finishEdbInfo, *items[i])
+		}
+	}
+	sort.Sort(SortByModifyDate{finishEdbInfo})
+	sort.Sort(SortByModifyDate{unFinishEdbInfo})
+	lastItems = append(lastItems, unFinishEdbInfo...)
+	lastItems = append(lastItems, finishEdbInfo...)
+	return
+}
+
+//获取此 slice 的长度
+func (p SortEdbInfo) Len() int { return len(p) }
+
+// 根据元素的状态降序排序
+func (p SortEdbInfo) Less(i, j int) bool {
+	return p[i].Status > p[j].Status
+}
+
+// 交换数据
+func (p SortEdbInfo) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
+
+// 嵌套结构体  将继承 SortEdbInfo 的所有属性和方法
+// 所以相当于SortByName 也实现了 Len() 和 Swap() 方法
+type SortByStatus struct{ SortEdbInfo }
+
+// 根据元素的姓名长度降序排序 (此处按照自己的业务逻辑写)
+func (p SortByStatus) Less(i, j int) bool {
+	return len(p.SortEdbInfo[i].Status) > len(p.SortEdbInfo[j].Status)
+}
+
+type SortByModifyDate struct{ SortEdbInfo }
+
+// 根据元素的年龄降序排序 (此处按照自己的业务逻辑写)
+func (p SortByModifyDate) Less(i, j int) bool {
+	return p.SortEdbInfo[i].ModifyDate > p.SortEdbInfo[j].ModifyDate
+}

+ 120 - 0
models/wechat.go

@@ -0,0 +1,120 @@
+package models
+
+import (
+	"encoding/json"
+	"fmt"
+	"hongze/hongze_admin/utils"
+	"rdluck_tools/http"
+	"rdluck_tools/orm"
+	"strings"
+	"time"
+)
+
+type WxToken struct {
+	AccessToken string
+	ExpiresIn   int64
+	Id          int64
+}
+
+func GetWxAccessToken() (accessTokenStr string, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM wx_token LIMIT 1`
+	wxToken := new(WxToken)
+	err = o.Raw(sql).QueryRow(&wxToken)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		utils.FileLog.Info("Get wxToken Err:", err.Error())
+		return
+	}
+	//Token不存在
+	if wxToken == nil {
+		fmt.Println("wxToken is empty")
+		accessToken, err := GetWxToken()
+		if err != nil {
+			return "", err
+		}
+		if accessToken.AccessToken != "" {
+			expiresIn := time.Now().Add(time.Duration(accessToken.ExpiresIn) * time.Second).Unix()
+			addSql := "insert into wx_token (access_token,expires_in) values (?,?)"
+			_, err = o.Raw(addSql, accessToken.AccessToken, expiresIn).Exec()
+			accessTokenStr = accessToken.AccessToken
+		}
+		return accessTokenStr, err
+	} else {
+		//判断token是否过期
+		if time.Now().Unix() > wxToken.ExpiresIn {
+			accessToken, err := GetWxToken()
+			if err != nil {
+				return "", err
+			}
+			if accessToken.AccessToken != "" {
+				expiresIn := time.Now().Add(time.Duration(accessToken.ExpiresIn) * time.Second).Unix()
+				updateSql := "update wx_token set access_token = ?,expires_in = ? "
+				_, err = o.Raw(updateSql, accessToken.AccessToken, expiresIn).Exec()
+				accessTokenStr = accessToken.AccessToken
+				fmt.Println("更新 TOKEN:",err)
+			}
+			return accessTokenStr, err
+		} else {
+			return wxToken.AccessToken, nil
+		}
+	}
+	return
+}
+
+type WxAccessToken struct {
+	AccessToken string `json:"access_token"`
+	ExpiresIn   int `json:"expires_in"`
+	Errcode     int
+	Errmsg      string
+}
+
+func GetWxToken() (item *WxAccessToken, err error) {
+	getUrl := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + utils.WxAppId + "&secret=" + utils.WxAppSecret
+	result, err := http.Get(getUrl)
+	if err != nil {
+		utils.FileLog.Info("GetWxToken Err:", err.Error())
+		return
+	}
+	err = json.Unmarshal(result, &item)
+	if err != nil {
+		fmt.Println("GetWxToken Unmarshal Err:%s",err.Error())
+		return
+	}
+	if item.Errmsg != "" {
+		utils.FileLog.Info("GetWxToken fail result:%s", string(result))
+	}
+	return
+}
+
+type WxUsers struct {
+	Total int
+	Count int
+	Data  struct {
+		Openid []string
+	}
+	NextOpenid string
+}
+
+func WxUsersGet() (openIdStr string) {
+	accessToken, err := GetWxAccessToken()
+	if err != nil {
+		utils.FileLog.Info("GetWxAccessToken Err:%s", err.Error())
+		return
+	}
+	url := "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + accessToken
+	result, err := http.Get(url)
+	if err != nil {
+		utils.FileLog.Info("GetUser Err:", err.Error())
+		return
+	}
+	item := new(WxUsers)
+	err = json.Unmarshal(result, &item)
+	if err != nil {
+		fmt.Println("Unmarshal Err:", err.Error())
+		return
+	}
+	openIdStr = strings.Join(item.Data.Openid, "','")
+	openIdStr = "'" + openIdStr + "'"
+	utils.FileLog.Info("openIdStr:%s", openIdStr)
+	return
+}

+ 21 - 0
models/wechat_send_msg.go

@@ -0,0 +1,21 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+)
+
+type OpenIdList struct {
+	OpenId string
+}
+
+func GetOpenIdList() (items []*OpenIdList,err error) {
+	openIdstr:=WxUsersGet()
+	sql:=`SELECT open_id FROM wx_user AS wu 
+          INNER JOIN company AS c ON c.company_id = wu.company_id 
+          WHERE wu.open_id IS NOT NULL AND  c.type IN (1,2) `
+	if openIdstr!="" {
+		sql+=` AND open_id in (`+openIdstr+`) `
+	}
+	_,err=orm.NewOrm().Raw(sql).QueryRows(&items)
+	return
+}

+ 18 - 0
models/wx_user.go

@@ -0,0 +1,18 @@
+package models
+
+import "rdluck_tools/orm"
+
+type WxUser struct {
+	UserId int64
+	Mobile string
+	Email string
+	CompanyId int
+	ExpiredIn int64
+}
+
+func GetUserByMobile(mobile string)(item *WxUser,err error) {
+	o:=orm.NewOrm()
+	sql:=`SELECT * FROM wx_user WHERE mobile=? `
+	err=o.Raw(sql,mobile).QueryRow(&item)
+	return
+}

+ 66 - 0
routers/router.go

@@ -0,0 +1,66 @@
+// @APIVersion 1.0.0
+// @Title beego Test API
+// @Description beego has a very cool tools to autogenerate documents for your API
+// @Contact astaxie@gmail.com
+// @TermsOfServiceUrl http://beego.me/
+// @License Apache 2.0
+// @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html
+package routers
+
+import (
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/plugins/cors"
+	"hongze/hongze_admin/controllers"
+)
+
+func init() {
+	//解决跨域问题
+	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
+		AllowAllOrigins:  true,
+		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
+		AllowHeaders:     []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		ExposeHeaders:    []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		AllowCredentials: true,
+	}))
+	ns := beego.NewNamespace("/admin",
+		beego.NSNamespace("/sysuser",
+			beego.NSInclude(
+				&controllers.SysUserController{},
+			),
+			beego.NSInclude(
+				&controllers.SysUserAuthController{},
+			),
+		),
+		beego.NSNamespace("/classify",
+			beego.NSInclude(
+				&controllers.ClassifyController{},
+			),
+		),
+		beego.NSNamespace("/banner",
+			beego.NSInclude(
+				&controllers.BannerController{},
+			),
+		),
+		beego.NSNamespace("/report",
+			beego.NSInclude(
+				&controllers.ReportController{},
+			),
+		),
+		beego.NSNamespace("/voice",
+			beego.NSInclude(
+				&controllers.VoiceController{},
+			),
+		),
+		beego.NSNamespace("/ppt",
+			beego.NSInclude(
+				&controllers.PptController{},
+			),
+		),
+		beego.NSNamespace("/entry",
+			beego.NSInclude(
+				&controllers.TargetController{},
+			),
+		),
+	)
+	beego.AddNamespace(ns)
+}

+ 67 - 0
services/oss.go

@@ -0,0 +1,67 @@
+package services
+
+import (
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+	"time"
+
+	"hongze/hongze_data_entry/utils"
+)
+
+/*
+上传demo
+func init() {
+	fmt.Println("start")
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName :=  randStr + ".jpg"
+	fmt.Println("fileName:",fileName)
+	fpath:="./1.png"
+	resourceUrl,err:=UploadAliyun(fileName,fpath)
+	if err!=nil {
+		fmt.Println("UploadAliyun Err:",err.Error())
+		return
+	}
+	fmt.Println("resourceUrl:",resourceUrl)
+	fmt.Println("end")
+}
+*/
+
+//图片上传到阿里云
+func UploadAliyun(filename, filepath string) (string,error) {
+	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 := utils.Upload_dir + time.Now().Format("200601/20060102/")
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3",err
+	}
+	path = utils.Imghost + path
+	return path,err
+}
+
+
+//音频上传到阿里云
+func UploadAudioAliyun(filename, filepath string) (string,error) {
+	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 := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3",err
+	}
+	path = utils.Imghost + path
+	return path,err
+}

+ 33 - 0
services/report.go

@@ -0,0 +1,33 @@
+package services
+
+import (
+	"fmt"
+	"github.com/PuerkitoBio/goquery"
+	"html"
+	"strings"
+)
+
+func GetReportContentSub(content string) (contentSub string, err error) {
+	content = html.UnescapeString(content)
+	doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
+	if err != nil {
+		fmt.Println("create doc err:", err.Error())
+		return
+	}
+	n := 0
+	doc.Find("p").Each(func(i int, s *goquery.Selection) {
+		if n >= 5 {
+			return
+		}
+		n++
+		phtml, err := s.Html()
+		if err != nil {
+			fmt.Println("get html err", err.Error())
+			return
+		}
+		if s.Text() != "" || strings.Contains(phtml, "src") {
+			contentSub = contentSub + "<p>" + phtml + "</p>"
+		}
+	})
+	return
+}

+ 69 - 0
services/sms.go

@@ -0,0 +1,69 @@
+package services
+
+import (
+	"hongze/hongze_data_entry/utils"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/url"
+	"net/http"
+)
+
+func SendSmsCode(mobile,ip string,codeType int,vcode string)bool  {
+	flag:=false
+	tplId:=""
+	switch codeType {
+	case utils.REGISTER_CODE:
+		tplId="206722"
+	case utils.LOGIN_CODE:
+		tplId="65692"
+	}
+	result,err:=sendSms(mobile,tplId,vcode)
+	if err!=nil {
+		fmt.Println("发送短信失败")
+		return  false
+	}
+	fmt.Println("result",string(result))
+	var netReturn map[string]interface{}
+	err=json.Unmarshal(result,&netReturn)
+	if err!=nil {
+		go utils.SendEmail("短信验证码发送失败","err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		flag=false
+	}
+	if netReturn["error_code"].(float64)==0{
+		fmt.Printf("接口返回result字段是:\r\n%v",netReturn["result"])
+		flag=true
+	}else{
+		go utils.SendEmail("短信验证码发送失败"," result"+string(result), utils.EmailSendToUsers)
+		flag=false
+	}
+	return  flag
+}
+
+
+func sendSms(mobile,tplId,code string)(rs []byte, err error)  {
+	var Url *url.URL
+	apiURL := "http://v.juhe.cn/sms/send"
+	//初始化参数
+	param := url.Values{}
+	//配置请求参数,方法内部已处理urlencode问题,中文参数可以直接传参
+	param.Set("mobile", mobile) //接受短信的用户手机号码
+	param.Set("tpl_id", tplId) //您申请的短信模板ID,根据实际情况修改
+	param.Set("tpl_value", "#code#="+code) //您设置的模板变量,根据实际情况
+	param.Set("key", utils.JhGnAppKey)  //应用APPKEY(应用详细页查询)
+
+	Url, err = url.Parse(apiURL)
+	if err != nil {
+		fmt.Printf("解析url错误:\r\n%v", err)
+		return nil, err
+	}
+	//如果参数中有中文参数,这个方法会进行URLEncode
+	Url.RawQuery = param.Encode()
+	resp, err := http.Get(Url.String())
+	if err != nil {
+		fmt.Println("err:", err)
+		return nil, err
+	}
+	defer resp.Body.Close()
+	return ioutil.ReadAll(resp.Body)
+}

+ 125 - 0
services/wechat_send_msg.go

@@ -0,0 +1,125 @@
+package services
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"hongze/hongze_admin/utils"
+	"hongze/hongze_admin/models"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"time"
+)
+
+func SendWxTemplateMsg(reportId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go utils.SendEmail("发送模版消息失败"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
+			utils.FileLog.Info("发送模版消息失败,Err:%s,%s", err.Error(),msg)
+		}
+		if msg!="" {
+			utils.FileLog.Info("发送模版消息失败,msg:%s",msg)
+		}
+	}()
+	utils.FileLog.Info("%s", "services SendMsg")
+
+	report, err := models.GetReportById(reportId)
+	if err != nil {
+		msg = "GetReportInfo Err:" + err.Error()
+		return
+	}
+	if report == nil {
+		utils.FileLog.Info("报告信息不存在")
+		return
+	}
+	accessToken, err := models.GetWxAccessToken()
+	if err != nil {
+		msg = "GetWxAccessToken Err:" + err.Error()
+		return
+	}
+	if accessToken == "" {
+		msg = "accessToken is empty"
+		return
+	}
+	openIdList, err := models.GetOpenIdList()
+	if err != nil {
+		msg = "get openIdList err:" + err.Error()
+		return
+	}
+	fmt.Println("openIdListCount:", len(openIdList))
+
+	sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
+	fmt.Println("send start")
+	utils.FileLog.Info("send start")
+	if report.MsgIsSend == 0 {
+		sendMap := make(map[string]interface{})
+		sendData := make(map[string]interface{})
+
+		redirectUrl := utils.TemplateRedirectUrl + strconv.Itoa(reportId)
+		keyword1 := "弘则日度点评"
+		first := "Hi,最新一期日度点评已上线,欢迎查看"
+		keyword2 := report.Title
+		keyword3 := report.PublishTime.Format(utils.FormatDateTime)
+		keyword4 := report.Abstract
+
+		sendData["first"] = map[string]interface{}{"value": first, "color": "#173177"}
+		sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": "#173177"}
+		sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": "#173177"}
+		sendData["keyword3"] = map[string]interface{}{"value": keyword3, "color": "#173177"}
+		sendData["keyword4"] = map[string]interface{}{"value": keyword4, "color": "#173177"}
+
+		sendMap["template_id"] = utils.TemplateIdByProduct
+		sendMap["url"] = redirectUrl
+		sendMap["data"] = sendData
+		sendTemplateMsg(sendUrl, sendMap, openIdList)
+	}
+	fmt.Println("send end")
+	utils.FileLog.Info("send end")
+	return
+}
+
+func sendTemplateMsg(sendUrl string, sendMap map[string]interface{}, items []*models.OpenIdList) (err error) {
+	for _, v := range items {
+		sendMap["touser"] = v.OpenId
+		data, err := json.Marshal(sendMap)
+		if err != nil {
+			fmt.Println("SendTemplateMsgOne Marshal Err:", err.Error())
+			utils.FileLog.Info("SendTemplateMsgOne Marshal Err:%s", err.Error())
+			return err
+		}
+		err = toSendTemplateMsg(sendUrl, data)
+		if err != nil {
+			fmt.Println("send err:", err.Error())
+			utils.FileLog.Info("ToSendTemplateMsg Err:%s", err.Error())
+		}
+	}
+	return
+}
+
+func toSendTemplateMsg(sendUrl string, data []byte) (err error) {
+	utils.FileLog.Info("Send:%s", string(data))
+	client := http.Client{}
+	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(data))
+	if err != nil {
+		return
+	}
+	defer resp.Body.Close()
+
+	body, _ := ioutil.ReadAll(resp.Body)
+	utils.FileLog.Info("SendResult:%s", string(body))
+	var templateResponse SendTemplateResponse
+	err = json.Unmarshal(body, &templateResponse)
+	if err != nil {
+		utils.FileLog.Info("SendResult Unmarshal Err:%s", err.Error())
+		return err
+	}
+	return
+}
+
+type SendTemplateResponse struct {
+	Errcode int    `json:"errcode"`
+	Errmsg  string `json:"errmsg"`
+	MsgID   int    `json:"msgid"`
+}

+ 555 - 0
utils/common.go

@@ -0,0 +1,555 @@
+
+package utils
+
+import (
+	"crypto/md5"
+	"crypto/sha1"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"image"
+	"image/png"
+	"math"
+	"math/rand"
+	"os"
+	"os/exec"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+//随机数种子
+var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+func GetRandString(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 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 StringsToJSON(str string) string {
+	rs := []rune(str)
+	jsons := ""
+	for _, r := range rs {
+		rint := int(r)
+		if rint < 128 {
+			jsons += string(r)
+		} else {
+			jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
+		}
+	}
+	return jsons
+}
+
+//序列化
+func ToString(v interface{}) string {
+	data, _ := json.Marshal(v)
+	return string(data)
+}
+
+//md5加密
+func MD5(data string) string {
+	m := md5.Sum([]byte(data))
+	return hex.EncodeToString(m[:])
+}
+
+// 获取数字随机字符
+func GetRandDigit(n int) string {
+	return fmt.Sprintf("%0"+strconv.Itoa(n)+"d", rnd.Intn(int(math.Pow10(n))))
+}
+
+// 获取随机数
+func GetRandNumber(n int) int {
+	return rnd.Intn(n)
+}
+
+func GetRandInt(min, max int) int {
+	if min >= max || min == 0 || max == 0 {
+		return max
+	}
+	return rand.Intn(max-min) + min
+}
+
+func GetToday(format string) string {
+	today := time.Now().Format(format)
+	return today
+}
+
+//获取今天剩余秒数
+func GetTodayLastSecond() time.Duration {
+	today := GetToday(FormatDate) + " 23:59:59"
+	end, _ := time.ParseInLocation(FormatDateTime, today, time.Local)
+	return time.Duration(end.Unix()-time.Now().Local().Unix()) * time.Second
+}
+
+// 处理出生日期函数
+func GetBrithDate(idcard string) string {
+	l := len(idcard)
+	var s string
+	if l == 15 {
+		s = "19" + idcard[6:8] + "-" + idcard[8:10] + "-" + idcard[10:12]
+		return s
+	}
+	if l == 18 {
+		s = idcard[6:10] + "-" + idcard[10:12] + "-" + idcard[12:14]
+		return s
+	}
+	return GetToday(FormatDate)
+}
+
+//处理性别
+func WhichSexByIdcard(idcard string) string {
+	var sexs = [2]string{"女", "男"}
+	length := len(idcard)
+	if length == 18 {
+		sex, _ := strconv.Atoi(string(idcard[16]))
+		return sexs[sex%2]
+	} else if length == 15 {
+		sex, _ := strconv.Atoi(string(idcard[14]))
+		return sexs[sex%2]
+	}
+	return "男"
+}
+
+//截取小数点后几位
+func SubFloatToString(f float64, m int) string {
+	n := strconv.FormatFloat(f, 'f', -1, 64)
+	if n == "" {
+		return ""
+	}
+	if m >= len(n) {
+		return n
+	}
+	newn := strings.Split(n, ".")
+	if m == 0 {
+		return newn[0]
+	}
+	if len(newn) < 2 || m >= len(newn[1]) {
+		return n
+	}
+	return newn[0] + "." + newn[1][:m]
+}
+
+//截取小数点后几位
+func SubFloatToFloat(f float64, m int) float64 {
+	newn := SubFloatToString(f, m)
+	newf, _ := strconv.ParseFloat(newn, 64)
+	return newf
+}
+
+//获取相差时间-年
+func GetYearDiffer(start_time, end_time string) int {
+	t1, _ := time.ParseInLocation("2006-01-02", start_time, time.Local)
+	t2, _ := time.ParseInLocation("2006-01-02", end_time, time.Local)
+	age := t2.Year() - t1.Year()
+	if t2.Month() < t1.Month() || (t2.Month() == t1.Month() && t2.Day() < t1.Day()) {
+		age--
+	}
+	return age
+}
+
+//获取相差时间-秒
+func GetSecondDifferByTime(start_time, end_time time.Time) int64 {
+	diff := end_time.Unix() - start_time.Unix()
+	return diff
+}
+
+func FixFloat(f float64, m int) float64 {
+	newn := SubFloatToString(f+0.00000001, m)
+	newf, _ := strconv.ParseFloat(newn, 64)
+	return newf
+}
+
+// 将字符串数组转化为逗号分割的字符串形式  ["str1","str2","str3"] >>> "str1,str2,str3"
+func StrListToString(strList []string) (str string) {
+	if len(strList) > 0 {
+		for k, v := range strList {
+			if k == 0 {
+				str = v
+			} else {
+				str = str + "," + v
+			}
+		}
+		return
+	}
+	return ""
+}
+
+//Token
+func GetToken() string {
+	randStr := GetRandString(64)
+	token := MD5(randStr + Md5Key)
+	tokenLen := 64 - len(token)
+	return strings.ToUpper(token + GetRandString(tokenLen))
+}
+
+//数据没有记录
+func ErrNoRow() string {
+	return "<QuerySeter> no row found"
+}
+
+//校验邮箱格式
+func ValidateEmailFormatat(email string) bool {
+	reg := regexp.MustCompile(RegularEmail)
+	return reg.MatchString(email)
+}
+
+//验证是否是手机号
+func ValidateMobileFormatat(mobileNum string) bool {
+	reg := regexp.MustCompile(RegularMobile)
+	return reg.MatchString(mobileNum)
+}
+
+//判断文件是否存在
+func FileIsExist(filePath string) bool {
+	_, err := os.Stat(filePath)
+	return err == nil || os.IsExist(err)
+}
+
+//获取图片扩展名
+func GetImgExt(file string) (ext string, err error) {
+	var headerByte []byte
+	headerByte = make([]byte, 8)
+	fd, err := os.Open(file)
+	if err != nil {
+		return "", err
+	}
+	defer fd.Close()
+	_, err = fd.Read(headerByte)
+	if err != nil {
+		return "", err
+	}
+	xStr := fmt.Sprintf("%x", headerByte)
+	switch {
+	case xStr == "89504e470d0a1a0a":
+		ext = ".png"
+	case xStr == "0000010001002020":
+		ext = ".ico"
+	case xStr == "0000020001002020":
+		ext = ".cur"
+	case xStr[:12] == "474946383961" || xStr[:12] == "474946383761":
+		ext = ".gif"
+	case xStr[:10] == "0000020000" || xStr[:10] == "0000100000":
+		ext = ".tga"
+	case xStr[:8] == "464f524d":
+		ext = ".iff"
+	case xStr[:8] == "52494646":
+		ext = ".ani"
+	case xStr[:4] == "4d4d" || xStr[:4] == "4949":
+		ext = ".tiff"
+	case xStr[:4] == "424d":
+		ext = ".bmp"
+	case xStr[:4] == "ffd8":
+		ext = ".jpg"
+	case xStr[:2] == "0a":
+		ext = ".pcx"
+	default:
+		ext = ""
+	}
+	return ext, nil
+}
+
+//保存图片
+func SaveImage(path string, img image.Image) (err error) {
+	//需要保持的文件
+	imgfile, err := os.Create(path)
+	defer imgfile.Close()
+	// 以PNG格式保存文件
+	err = png.Encode(imgfile, img)
+	return err
+}
+
+//保存base64数据为文件
+func SaveBase64ToFile(content, path string) error {
+	data, err := base64.StdEncoding.DecodeString(content)
+	if err != nil {
+		return err
+	}
+	f, err := os.Create(path)
+	defer f.Close()
+	if err != nil {
+		return err
+	}
+	f.Write(data)
+	return nil
+}
+
+func SaveBase64ToFileBySeek(content, path string) (err error) {
+	data, err := base64.StdEncoding.DecodeString(content)
+	exist,err:=PathExists(path)
+	if err!=nil {
+		return
+	}
+	if !exist {
+		f, err := os.Create(path)
+		if err!=nil {
+			return err
+		}
+		n, _ := f.Seek(0, 2)
+		// 从末尾的偏移量开始写入内容
+		_, err = f.WriteAt([]byte(data), n)
+		defer f.Close()
+	}else{
+		f, err := os.OpenFile(path, os.O_WRONLY, 0644)
+		if err!=nil {
+			return err
+		}
+		n, _ := f.Seek(0, 2)
+		// 从末尾的偏移量开始写入内容
+		_, err = f.WriteAt([]byte(data), n)
+		defer f.Close()
+	}
+
+	return nil
+}
+
+func PathExists(path string) (bool,error) {
+	_, err := os.Stat(path)
+	if err == nil {
+		return true, nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
+
+func StartIndex(page, pagesize int) int {
+	if page > 1 {
+		return (page - 1) * pagesize
+	}
+	return 0
+}
+func PageCount(count, pagesize int) int {
+	if count%pagesize > 0 {
+		return count/pagesize + 1
+	} else {
+		return count / pagesize
+	}
+}
+
+func TrimHtml(src string) string {
+	//将HTML标签全转换成小写
+	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllStringFunc(src, strings.ToLower)
+
+	re, _ = regexp.Compile("\\<img[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "[图片]")
+
+	re, _ = regexp.Compile("class[\\S\\s]+?>")
+	src = re.ReplaceAllString(src, "")
+	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "")
+	return strings.TrimSpace(src)
+}
+
+//1556164246  ->  2019-04-25 03:50:46 +0000
+//timestamp
+
+func TimeToTimestamp() {
+	fmt.Println(time.Unix(1556164246, 0).Format("2006-01-02 15:04:05"))
+}
+
+func ToUnicode(text string) string {
+	textQuoted := strconv.QuoteToASCII(text)
+	textUnquoted := textQuoted[1 : len(textQuoted)-1]
+	return textUnquoted
+}
+
+func VersionToInt(version string) int {
+	version = strings.Replace(version, ".", "", -1)
+	n, _ := strconv.Atoi(version)
+	return n
+}
+func IsCheckInList(list []int, s int) bool {
+	for _, v := range list {
+		if v == s {
+			return true
+		}
+	}
+	return false
+
+}
+
+func round(num float64) int {
+	return int(num + math.Copysign(0.5, num))
+}
+
+func toFixed(num float64, precision int) float64 {
+	output := math.Pow(10, float64(precision))
+	return float64(round(num*output)) / output
+}
+
+// GetWilsonScore returns Wilson Score
+func GetWilsonScore(p, n float64) float64 {
+	if p == 0 && n == 0 {
+		return 0
+	}
+
+	return toFixed(((p+1.9208)/(p+n)-1.96*math.Sqrt(p*n/(p+n)+0.9604)/(p+n))/(1+3.8416/(p+n)), 2)
+}
+
+//将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
+func ChangeWordsToNum(str string) (numStr string) {
+	words := ([]rune)(str)
+	num := 0
+	n := 0
+	for i := 0; i < len(words); i++ {
+		word := string(words[i : i+1])
+		switch word {
+		case "万":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 10000
+			num = num*10000 + n
+			n = 0
+		case "千":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 1000
+			num += n
+			n = 0
+		case "百":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 100
+			num += n
+			n = 0
+		case "十":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 10
+			num += n
+			n = 0
+		case "一":
+			n += 1
+		case "二":
+			n += 2
+		case "三":
+			n += 3
+		case "四":
+			n += 4
+		case "五":
+			n += 5
+		case "六":
+			n += 6
+		case "七":
+			n += 7
+		case "八":
+			n += 8
+		case "九":
+			n += 9
+		case "零":
+		default:
+			if n > 0 {
+				num += n
+				n = 0
+			}
+			if num == 0 {
+				numStr += word
+			} else {
+				numStr += strconv.Itoa(num) + word
+				num = 0
+			}
+		}
+	}
+	if n > 0 {
+		num += n
+		n = 0
+	}
+	if num != 0 {
+		numStr += strconv.Itoa(num)
+	}
+	return
+}
+
+func Sha1(data string) string {
+	sha1 := sha1.New()
+	sha1.Write([]byte(data))
+	return hex.EncodeToString(sha1.Sum([]byte("")))
+}
+
+
+func GetVideoPlaySeconds(videoPath string) (playSeconds float64, err error) {
+	cmd := `ffmpeg -i ` + videoPath + `  2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//`
+	out, err := exec.Command("bash", "-c", cmd).Output()
+	if err != nil {
+		return
+	}
+	outTimes := string(out)
+	fmt.Println("outTimes:",outTimes)
+	if outTimes != "" {
+		timeArr := strings.Split(outTimes, ":")
+		h := timeArr[0]
+		m := timeArr[1]
+		s := timeArr[2]
+		hInt, err := strconv.Atoi(h)
+		if err != nil {
+			return playSeconds,err
+		}
+
+		mInt, err := strconv.Atoi(m)
+		if err != nil {
+			return playSeconds,err
+		}
+		s=strings.Trim(s," ")
+		s=strings.Trim(s,"\n")
+		sInt, err :=strconv.ParseFloat(s, 64)
+		if err != nil {
+			return playSeconds,err
+		}
+		playSeconds = float64(hInt)*3600 + float64(mInt)*60 + float64(sInt)
+	}
+	return
+}
+
+func GetMaxTradeCode(tradeCode string) (maxTradeCode string, err error) {
+	tradeCode = strings.Replace(tradeCode, "W", "", -1)
+	tradeCode = strings.Trim(tradeCode, " ")
+	tradeCodeInt, err := strconv.Atoi(tradeCode)
+	if err != nil {
+		return
+	}
+	tradeCodeInt = tradeCodeInt + 1
+	maxTradeCode = fmt.Sprintf("W%06d", tradeCodeInt)
+	return
+}
+
+
+// excel日期字段格式化 yyyy-mm-dd
+func ConvertToFormatDay(excelDaysString string) string {
+	// 2006-01-02 距离 1900-01-01的天数
+	baseDiffDay := 38719 //在网上工具计算的天数需要加2天,什么原因没弄清楚
+	curDiffDay := excelDaysString
+	b, _ := strconv.Atoi(curDiffDay)
+	// 获取excel的日期距离2006-01-02的天数
+	realDiffDay := b - baseDiffDay
+	//fmt.Println("realDiffDay:",realDiffDay)
+	// 距离2006-01-02 秒数
+	realDiffSecond := realDiffDay * 24 * 3600
+	//fmt.Println("realDiffSecond:",realDiffSecond)
+	// 2006-01-02 15:04:05距离1970-01-01 08:00:00的秒数 网上工具可查出
+	baseOriginSecond := 1136185445
+	resultTime := time.Unix(int64(baseOriginSecond+realDiffSecond), 0).Format("2006-01-02")
+	return resultTime
+}

+ 58 - 0
utils/config.go

@@ -0,0 +1,58 @@
+package utils
+
+import (
+	"github.com/astaxie/beego"
+)
+
+var (
+	RunMode        string //运行模式
+	MYSQL_URL      string //数据库连接
+	MYSQL_URL_RDDP string //数据库连接
+	MYSQL_URL_EDB  string
+)
+
+var (
+	STATIC_DIR string
+)
+
+//微信配置信息
+var (
+	WxId                string //微信原始ID
+	WxAppId             string
+	WxAppSecret         string
+	TemplateIdByProduct string//产品运行报告通知-模板ID
+	TemplateRedirectUrl string//模板消息跳转地址
+)
+
+func init() {
+	RunMode = beego.AppConfig.String("run_mode")
+	config, err := beego.AppConfig.GetSection(RunMode)
+	if err != nil {
+		panic("配置文件读取错误 " + err.Error())
+	}
+	beego.Info(RunMode + " 模式")
+	MYSQL_URL = config["mysql_url"]
+	MYSQL_URL_RDDP = config["mysql_url_rddp"]
+	MYSQL_URL_EDB = config["mysql_url_edb"]
+
+	if RunMode == "release" {
+		WxAppId = "wx4a844c734d8c8e56"
+		WxAppSecret = "26c586e7ccb3c575433f0f37797b3eeb"
+		WxId = "gh_b67e0049fb8c"
+		TemplateIdByProduct = "Cp2wF8gvBtxyWV4DeYuI172oqwyYXVRSm3AyJO42d84"
+		TemplateRedirectUrl="https://ficc.hzinsights.com/reportdtl?id="
+
+		STATIC_DIR="/home/static/imgs/"
+	} else {
+		WxAppId = "wx9b5d7291e581233a"
+		WxAppSecret = "f4d52e34021eee262dce9682b31f8861"
+		WxId = "gh_5dc508325c6f"
+		TemplateIdByProduct = "-YjuPOB7Fqd-S3ilabYa6wvjDY9aXmeEfPN6DCiy-EY"
+		TemplateRedirectUrl="http://rddpweb.brilliantstart.cn/reportdtl?id="
+
+		STATIC_DIR="/home/static/imgs/"
+	}
+}
+
+//http://adminapi.brilliantstart.cn/admin/
+//http://adminapi.brilliantstart.cn/swagger/

+ 68 - 0
utils/constants.go

@@ -0,0 +1,68 @@
+package utils
+
+const (
+	Md5Key = "Ks@h64WJ#tcVgG8$&WlNfqvLAtMgpxWN"
+)
+
+//常量定义
+const (
+	FormatTime            = "15:04:05"                //时间格式
+	FormatDate            = "2006-01-02"              //日期格式
+	FormatDateTime        = "2006-01-02 15:04:05"     //完整时间格式
+	HlbFormatDateTime     = "2006-01-02_15:04:05.999" //完整时间格式
+	FormatDateTimeUnSpace = "20060102150405"          //完整时间格式
+	PageSize15            = 15                        //列表页每页数据量
+	PageSize5             = 5
+	PageSize10            = 10
+	PageSize20            = 20
+	PageSize30            = 30
+)
+
+const (
+	APPNAME          = "弘则-日度点评-管理后台"
+	EmailSendToUsers = "glji@hzinsights.com"
+)
+
+//手机号,电子邮箱正则
+const (
+	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
+	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
+)
+
+//验证码code
+const (
+	REGISTER_CODE = iota + 1 //注册
+	LOGIN_CODE               //登录
+)
+
+//聚合短信
+var (
+	TplId    = "65692"
+	JhAppKey = "4c8504c49dd335e99cfd7b6a3a9e2415"
+)
+
+//科大讯飞--语音合成
+const (
+	XfSTATUS_FIRST_FRAME    = 0 //第一帧标识
+	XfSTATUS_CONTINUE_FRAME = 1 //中间帧标识
+	XfSTATUS_LAST_FRAME     = 2 //最后一帧标识
+	XfAPPID               = "5ed70e9d"
+	XfAPIKey                = "d580509ca262e9586fb65a7064d5ce77"
+	XfAPISecret             = "a085720dc55850c720fa5576335f847a"
+	XfHostUrl               = "wss://tts-api.xfyun.cn/v2/tts"
+	XfOrigin                = "http://tts-api.xfyun.cn/"
+	XfHost                  = "tts-api.xfyun.cn"
+)
+
+
+//OSS
+var (
+	Endpoint        string = "oss-cn-shanghai.aliyuncs.com"
+	Bucketname      string = "hongze"
+
+	Imghost         string = "http://hongze.oss-cn-shanghai.aliyuncs.com/"
+	Upload_dir      string = "static/images/"
+
+	AccessKeyId     string = "LTAIFMZYQhS2BTvW"
+	AccessKeySecret string = "12kk1ptCHoGWedhBnKRVW5hRJzq9Fq"
+)

+ 30 - 0
utils/email.go

@@ -0,0 +1,30 @@
+package utils
+
+import (
+	"gopkg.in/gomail.v2"
+	"strings"
+)
+
+//发送邮件
+func SendEmail(title, content string, touser string)bool {
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	}else{
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "317699326@qq.com ")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title+" "+GetRandString(16))
+	m.SetBody("text/html", content)
+	d := gomail.NewDialer("smtp.qq.com", 587, "317699326@qq.com", "oqdypwfcvruwcbea")
+	if err := d.DialAndSend(m); err != nil {
+		return false
+	}
+	return true
+}

+ 45 - 0
utils/jwt.go

@@ -0,0 +1,45 @@
+package utils
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/astaxie/beego/logs"
+	"github.com/dgrijalva/jwt-go"
+)
+
+var (
+	KEY = []byte("5Mb5Gdmb5x")
+)
+
+// 发放token
+func GenToken(account string) string {
+	token := jwt.New(jwt.SigningMethodHS256)
+	token.Claims = &jwt.StandardClaims{
+		NotBefore: int64(time.Now().Unix()),
+		ExpiresAt: int64(time.Now().Unix() + 3600*3),
+		Issuer:    "csdp",
+		Subject:   account,
+	}
+	ss, err := token.SignedString(KEY)
+	if err != nil {
+		logs.Error(err)
+		return ""
+	}
+	return ss
+}
+
+// 校验token
+func CheckToken(account, token string) bool {
+	t, err := jwt.Parse(token, func(*jwt.Token) (interface{}, error) {
+		return KEY, nil
+	})
+	if err != nil {
+		fmt.Println(err.Error())
+		return false
+	}
+	if account != t.Claims.(jwt.MapClaims)["sub"] {
+		return false
+	}
+	return t.Valid
+}

+ 12 - 0
utils/logs.go

@@ -0,0 +1,12 @@
+package utils
+
+import (
+	"github.com/astaxie/beego/logs"
+)
+
+var FileLog *logs.BeeLogger
+
+func init() {
+	FileLog = logs.NewLogger(1000000)
+	FileLog.SetLogger(logs.AdapterFile, `{"filename":"./rdlucklog/hongze_data_entry.log"}`)
+}