// Copyright 2019  getensh.com. All rights reserved.
// Use of this source code is governed by  getensh.com.
package ctrl_v1

import (
	"context"
	"gd_management_gateway/common.in/jsonrpc2"
	"gd_management_gateway/errors"
	"gd_management_gateway/params/param_base"
	"gd_management_gateway/params/param_v1_0"
	"gd_management_gateway/rpc_apis"
	"gd_management_gateway/rpc_apis/gd_statistics"
	"gd_management_gateway/rpc_apis/gd_management"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"

	"gd_management_gateway/common.in/cache"
	"gd_management_gateway/common.in/httper"
	"gd_management_gateway/common.in/task"
	"gd_management_gateway/common.in/utils"
	"github.com/astaxie/beego"
	"github.com/tealeg/xlsx"
	"go.uber.org/zap"
)

const exportPath = "/export/"

var ServerPort = "61002"
var ServerIp = ""

// Operations about access log api
type BaseAccessLogController struct {
	metadata interface{} // 中继元数据
	beego.Controller
	LogID string
}

// SetPercentForXlsx 单元格设置百分率
func SetPercentForXlsx(percent string, cell *xlsx.Cell) {
	s := strings.TrimRight(percent, "%")

	// 对零单独处理
	f, _ := strconv.ParseFloat(s, 64)
	if f == 0 {
		cell.SetFloatWithFormat(0.0000, "0.00%")
		return
	}

	// 将百分比转为小数形式
	f = f / 100.0000
	fstring := strconv.FormatFloat(f, 'f', 4, 64)
	ffloat, _ := strconv.ParseFloat(fstring, 64)

	// 设置单元格
	cell.SetFloatWithFormat(ffloat, "0.00%")
}

// @Title 访问日志
// @Description 访问日志
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   state    query   int false "接口调用返回状态"
// @Param   code    query   string false "接口调用返回状态"
// @Param   request_param    query   string false "请求参数"
// @Param   search    query   string false "关键字"
// @Param   merchant_id    query   int64 false "商户id"
// @Param   api_id    query   int64 false "基础api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Param   page_size    query   int64 false "页大小"
// @Param   page_number    query   int64 false "页号"
// @Param   min    query   float64 false "最小耗时"
// @Param   max    query   float64 false "最大耗时"
// @Success 200 	{object} params.param_v1_0.LogQueryAccessLogResp "响应信息"
// @Failure 500 	服务器错误
// @router /access_log [get]
func (u *BaseAccessLogController) LogQueryAccessLog() {
	u.LogID = fmt.Sprintf("LogQueryAccessLog[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryAccessLogReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryAccessLogReq{}
		mreq.PageNumber = req.PageNumber
		mreq.PageSize = req.PageSize
		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ApiId = req.ApiId
		mreq.MerchantId = req.MerchantId
		mreq.State = req.State
		mreq.Code = req.Code
		mreq.RequestParam = req.RequestParam
		mreq.Search = req.Search
		mreq.Max = req.Max
		mreq.Min = req.Min
		reply, err := rpc_apis.Statistics.LogQueryAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryAccessLog"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryAccessLogResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 数据源日志
// @Description 数据源日志
//  @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   state    query   int false "接口调用返回状态"
// @Param   search    query   string false "关键字"
// @Param   request_param    query   string false "请求参数"
// @Param   provider_id    query   int64 false "三方平台id"
// @Param   provider_api_id    query   int64 false "三方api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Param   page_size    query   int64 false "页大小"
// @Param   page_number    query   int64 false "页号"
// @Param   min    query   float64 false "最小耗时"
// @Param   max    query   float64 false "最大耗时"
// @Param   raw_code    query   string false "原始错误码"
// @Success 200 	{object} params.param_v1_0.LogQueryThirdpartAccessLogResp "响应信息"
// @Failure 500 	服务器错误
// @router /thirdpart_access_log [get]
func (u *BaseAccessLogController) LogQueryThirdpartAccessLog() {
	u.LogID = fmt.Sprintf("LogQueryThirdpartAccessLog[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryThirdpartAccessLogReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryThirdpartAccessLogReq{}
		mreq.EndTimestamp = req.EndTimestamp
		mreq.StartTimestamp = req.StartTimestamp
		mreq.PageSize = req.PageSize
		mreq.PageNumber = req.PageNumber
		mreq.ProviderApiId = req.ProviderApiId
		mreq.ProviderId = req.ProviderId
		mreq.State = req.State
		mreq.RequestParam = req.RequestParam
		mreq.Search = req.Search
		mreq.Max = req.Max
		mreq.Min = req.Min
		mreq.RawCode = req.RawCode
		fmt.Println("raw code:",mreq.RawCode,req.RawCode)
		reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryThirdpartAccessLog"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryThirdpartAccessLogResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 访问日志统计
// @Description 访问日志统计
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   merchant_id    query   int64 false "商户id"
// @Param   api_id    query   int64 false "基础api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Param   page_size    query   int64 false "页大小"
// @Param   page_number    query   int64 false "页号"
// @Success 200 	{object} params.param_v1_0.LogQueryAccessLogCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /access_log_count [get]
func (u *BaseAccessLogController) LogQueryAccessLogCount() {
	u.LogID = fmt.Sprintf("LogQueryAccessLogCount[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryAccessLogCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/

		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryAccessLogCountReq{}
		mreq.PageNumber = req.PageNumber
		mreq.PageSize = req.PageSize
		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ApiId = req.ApiId
		mreq.MerchantId = req.MerchantId
		reply, err := rpc_apis.Statistics.LogQueryAccessLogCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)

		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryAccessLogCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryAccessLogCountResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 数据源查询统计
// @Description 数据源查询统
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   provider_id    query   int64 false "三方平台id"
// @Param   provider_api_id    query   int64 false "三方api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Param   page_size    query   int64 false "页大小"
// @Param   page_number    query   int64 false "页号"
// @Success 200 	{object} params.param_v1_0.LogQueryThirdpartAccessLogCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /thirdpart_accesslog_count [get]
func (u *BaseAccessLogController) LogQueryThirdpartAccessLogCount() {
	u.LogID = fmt.Sprintf("LogQueryThirdpartAccessLogCount[%d]", time.Now().UnixNano())
	req := &param_v1_0.LogQueryThirdpartAccessLogCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryThirdpartAccessLogCountReq{}
		mreq.EndTimestamp = req.EndTimestamp
		mreq.StartTimestamp = req.StartTimestamp
		mreq.PageSize = req.PageSize
		mreq.PageNumber = req.PageNumber
		mreq.ProviderApiId = req.ProviderApiId
		mreq.ProviderId = req.ProviderId
		reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessLogCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryThirdpartAccessLogCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryThirdpartAccessLogCountResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply

		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 访问日志关联数据源日志
// @Description 访问日志关联数据源日志
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   access_id    query   int true "访问日志id"
// @Param   create_time    query   string true "时间"
// @Success 200 	{object} params.param_v1_0.LogQueryAccessLogThirdpartLogResp "响应信息"
// @Failure 500 	服务器错误
// @router /access_log_get_thirdpart_log [get]
func (u *BaseAccessLogController) LogQueryAccessLogThirdpartLog() {
	u.LogID = fmt.Sprintf("LogQueryAccessLogThirdpartLog[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryAccessLogThirdpartLogReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryAccessLogThirdpartLogReq{}
		mreq.AccessId = req.AccessId
		if req.CreateTime != "" {
			timeLayout := "2006-01-02"
			loc, _ := time.LoadLocation("Local")
			array := strings.Split(req.CreateTime, " ")
			t, _ := time.ParseInLocation(timeLayout, array[0], loc)
			mreq.Timestamp = t.Unix()
		}
		reply, err := rpc_apis.Statistics.LogQueryAccessLogThirdpartLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryAccessLogThirdpartLog"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryAccessLogThirdpartLogResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 访问日志用户统计报表
// @Description 访问日志用户统计报表
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   merchant_id    query   int64 false "商户id"
// @Param   api_id    query   int64 false "基础api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Param   page_size    query   int64 false "页大小"
// @Param   page_number    query   int64 false "页号"
// @Success 200 	{object} params.param_v1_0.LogQueryUserAccessCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /user_access_count [get]
func (u *BaseAccessLogController) LogQueryUserAccessCount() {
	u.LogID = fmt.Sprintf("LogQueryUserAccessCount[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryUserAccessCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryUserAccessCountReq{}
		mreq.PageNumber = req.PageNumber
		mreq.PageSize = req.PageSize
		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ApiId = req.ApiId
		mreq.MerchantId = req.MerchantId
		reply, err := rpc_apis.Statistics.LogQueryUserAccessCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryUserAccessCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryUserAccessCountResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 访问日志接口统计详情
// @Description 访问日志接口统计详情
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   merchant_id    query   int64 false "商户id"
// @Param   api_id    query   int64 false "基础api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Success 200 	{object} params.param_v1_0.LogQueryInterfaceCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /access_log_interface_count [get]
func (u *BaseAccessLogController) LogQueryInterfaceCount() {
	u.LogID = fmt.Sprintf("LogQueryInterfaceCount[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryInterfaceCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryInterfaceCountReq{}

		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ApiId = req.ApiId
		mreq.MerchantId = req.MerchantId
		reply, err := rpc_apis.Statistics.LogQueryInterfaceCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryInterfaceCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryInterfaceCountResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 数据源接口用量统计
// @Description 数据源接口用量统计
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   provider_api_id    query   int64 false "数据源api id"
// @Param   time    query   int64 false "时间"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Success 200 	{object} params.param_v1_0.LogQueryThirdpartAccessCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /thirdpart_access_count [get]
func (u *BaseAccessLogController) LogQueryThirdpartAccessCount() {
	u.LogID = fmt.Sprintf("LogQueryInterfaceCount[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryThirdpartAccessCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryThirdpartAccessCountReq{}
		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ProviderApiId = req.ProviderApiId
		if req.Time > 0 {
			mreq.Time = time.Unix(req.Time, 0).Format("2006-01-02")
		}
		reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryThirdpartAccessCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryThirdpartAccessCountResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 数据源接口统计报表
// @Description 数据源接口统计报表
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   provider_api_id    query   int64 false "数据源api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Param   page_size    query   int64 false "页大小"
// @Param   page_number    query   int64 false "页号"
// @Success 200 	{object} params.param_v1_0.LogQueryThirdpartInterfaceCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /thirdpart_access_interface_count [get]
func (u *BaseAccessLogController) LogQueryThirdpartInterfaceCount() {
	u.LogID = fmt.Sprintf("LogQueryThirdpartInterfaceCount[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryThirdpartInterfaceCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryThirdpartInterfaceCountReq{}

		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ProviderApiId = req.ProviderApiId
		mreq.PageNumber = req.PageNumber
		mreq.PageSize = req.PageSize

		reply, err := rpc_apis.Statistics.LogQueryThirdpartInterfaceCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryThirdpartInterfaceCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryThirdpartInterfaceCountResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

func ExportUpdate(u *BaseAccessLogController, exportReq *gd_statistics.LogExportCreateReq) {
	_, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), exportReq)
	if err != nil {
		l.Error("rpc",
			zap.String("call", "LogExportCreate"),
			zap.String("args", utils.MarshalJsonString(exportReq)),
			zap.String("error", err.Error()))

	}
}

var ErrCodeMutex sync.Mutex
var ErrorCodeMap = map[string]string{}

func IsErrorCodeMapExist() bool {
	ErrCodeMutex.Lock()
	defer ErrCodeMutex.Unlock()
	if len(ErrorCodeMap) > 0 {
		return true
	}
	return false
}

func SetErrorCodeMap() {
	ErrCodeMutex.Lock()
	defer ErrCodeMutex.Unlock()
	mreq := gd_management.ManagementGetErrorListReq{}
	mreq.PageNumber = 1
	mreq.IsAll = true
	reply, err := rpc_apis.Management.ManagementGetErrorList(context.Background(), &mreq)
	if err != nil {
		return
	}
	ErrorCodeMap = map[string]string{}
	for _, v := range reply.ErrorCodeList {
		ErrorCodeMap[v.Code] = v.Msg
	}
}

func makeXlsxErrorHeader(sheet *xlsx.Sheet, codes []gd_statistics.ErrorCodeCount) {
	if IsErrorCodeMapExist() == false {
		SetErrorCodeMap()
	}
	row := sheet.AddRow()
	cell := row.AddCell()
	cell.Value = "日期"
	cell = row.AddCell()
	cell.Value = "错误总量"
	for _, v := range codes {
		cell := row.AddCell()
		if msg, ok := ErrorCodeMap[v.Code]; ok {
			cell.Value = fmt.Sprintf("%s(%s)", v.Code, msg)
		} else {
			cell.Value = v.Code
		}
		cell = row.AddCell()
		cell.Value = v.Code + "占比"
	}
}

func makeXlsxSourceHeader(sheet *xlsx.Sheet, names []gd_statistics.SourceNameCount) {
	row := sheet.AddRow()
	cell := row.AddCell()
	cell.Value = "日期"
	cell = row.AddCell()
	cell.Value = "来源总量"
	for _, v := range names {
		cell := row.AddCell()
		cell.Value = v.Name
		cell = row.AddCell()
		cell.Value = v.Name + "占比"
	}
}

func makeXlsxHeader(sheet *xlsx.Sheet, timeList string) {
	tArray := strings.Split(timeList, ",")

	row := sheet.AddRow()
	dateCell := row.AddCell()
	dateCell.Value = "时间"
	//dateCell.HMerge
	dateCell.VMerge = 1
	cell := row.AddCell()
	cell.Value = "总调用量情况"
	cell.HMerge = 4
	row.AddCell()
	row.AddCell()
	row.AddCell()
	row.AddCell()

	cell = row.AddCell()
	cell.Value = "有效调用量情况"
	cell.HMerge = 10
	if len(tArray) > 0 && tArray[0] != "" {
		cell.HMerge += len(tArray)
	}
	row = sheet.AddRow()
	row.AddCell()
	totalCell := row.AddCell()
	totalCell.Value = "调用总量"

	validCell := row.AddCell()
	validCell.Value = "有效量"

	validRateCell := row.AddCell()
	validRateCell.Value = "有效率"

	chargeCell := row.AddCell()
	chargeCell.Value = "计费量"

	chargeRateCell := row.AddCell()
	chargeRateCell.Value = "计费率"

	successCell := row.AddCell()
	successCell.Value = "成功量"

	successRateCell := row.AddCell()
	successRateCell.Value = "成功率"

	queryCell := row.AddCell()
	queryCell.Value = "查得量"

	queryRateCell := row.AddCell()
	queryRateCell.Value = "查得率"

	reuseCell := row.AddCell()
	reuseCell.Value = "复用量"

	reuseRateCell := row.AddCell()
	reuseRateCell.Value = "复用率"

	platformErrorCell := row.AddCell()
	platformErrorCell.Value = "平台异常量"

	platformErrorRateCell := row.AddCell()
	platformErrorRateCell.Value = "平台异常率"

	providerErrorCell := row.AddCell()
	providerErrorCell.Value = "数据源异常量"

	providerErrorRateCell := row.AddCell()
	providerErrorRateCell.Value = "数据源异常率"

	avgElapsedCell := row.AddCell()
	avgElapsedCell.Value = "平均时长"
	offset := 17
	for i, v := range tArray {
		if v == "" {
			return
		}
		cell := row.AddCell()
		cell.Value = fmt.Sprintf("时长大于%s秒", v)
		sheet.SetColWidth(17+i, 17+i, 20)
		offset++
	}
	for i, v := range tArray {
		if v == "" {
			return
		}
		cell := row.AddCell()
		cell.Value = fmt.Sprintf("计费调用中时长大于%s秒", v)
		sheet.SetColWidth(offset+i, offset+i, 30)
	}

}

func makeProviderXlsxHeader(sheet *xlsx.Sheet, timeList string) {
	row := sheet.AddRow()
	dateCell := row.AddCell()
	dateCell.Value = "时间"

	nameCell := row.AddCell()
	nameCell.Value = "供应商"

	totalCell := row.AddCell()
	totalCell.Value = "总量"

	successCell := row.AddCell()
	successCell.Value = "成功"

	failCell := row.AddCell()
	failCell.Value = "失败"

	failRateCell := row.AddCell()
	failRateCell.Value = "失败率"

	queryCell := row.AddCell()
	queryCell.Value = "查得"

	queryNoRecordCell := row.AddCell()
	queryNoRecordCell.Value = "查无"

	queryNoRecordRateCell := row.AddCell()
	queryNoRecordRateCell.Value = "查无率"

	avgElapsedCell := row.AddCell()
	avgElapsedCell.Value = "平均时长"

	tArray := strings.Split(timeList, ",")
	for _, v := range tArray {
		if v == "" {
			break
		}
		cell := row.AddCell()
		cell.Value = fmt.Sprintf("时长大于%s秒", v)
	}

	for _, v := range tArray {
		if v == "" {
			break
		}
		cell := row.AddCell()
		cell.Value = fmt.Sprintf("计费调用中时长大于%s秒", v)
	}
}

func parseSumRate(rate string) string {
	array := strings.Split(rate, "-")
	total := float64(0)
	for _, v := range array {
		valuestring := strings.TrimRight(v, "%")
		value, _ := strconv.ParseFloat(valuestring, 64)
		total += value
	}
	ret := strconv.FormatFloat(float64(total)/float64(len(array)), 'f', 3, 64) + "%"
	return ret
}

func parseSum(sum *gd_statistics.LogQueryUserAcessCountExport, sheet *xlsx.Sheet) {
	row := sheet.AddRow()

	if sum.Total == 0 {
		sum.ValidRate = "0%"
		sum.ChargeRate = "0%"
	} else {
		sum.ValidRate = strconv.FormatFloat(float64(100*sum.Valid)/float64(sum.Total), 'f', 2, 64) + "%"
		sum.ChargeRate = strconv.FormatFloat(float64(100*sum.Charge)/float64(sum.Total), 'f', 2, 64) + "%"
	}

	if sum.Valid == 0 {
		sum.QueryRate = "0%"
		sum.SuccessRate = "0%"
		sum.ReuseRate = "0%"
	} else {
		sum.QueryRate = strconv.FormatFloat(float64(100*sum.Query)/float64(sum.Valid), 'f', 2, 64) + "%"
		sum.SuccessRate = strconv.FormatFloat(float64(100*sum.Success)/float64(sum.Valid), 'f', 2, 64) + "%"
		sum.ReuseRate = strconv.FormatFloat(float64(100*sum.Reuse)/float64(sum.Valid), 'f', 2, 64) + "%"
		sum.PlatformErrorRate = strconv.FormatFloat(float64(100*sum.PlatformError)/float64(sum.Valid), 'f', 2, 64) + "%"
		sum.ProviderErrorRate = strconv.FormatFloat(float64(100*sum.ProviderError)/float64(sum.Valid), 'f', 2, 64) + "%"

	}

	dateCell := row.AddCell()
	dateCell.Value = sum.Date

	totalCell := row.AddCell()
	totalCell.SetInt(int(sum.Total))

	validCell := row.AddCell()
	validCell.SetInt(int(sum.Valid))

	validRateCell := row.AddCell()
	validRateCell.Value = sum.ValidRate
	SetPercentForXlsx(sum.ValidRate, validRateCell)

	chargeCell := row.AddCell()
	chargeCell.SetInt(sum.Charge)

	chargeRateCell := row.AddCell()
	SetPercentForXlsx(sum.ChargeRate, chargeRateCell)

	successCell := row.AddCell()
	successCell.SetInt(sum.Success)

	successRateCell := row.AddCell()
	SetPercentForXlsx(sum.SuccessRate, successRateCell)

	queryCell := row.AddCell()
	queryCell.SetInt(sum.Query)

	queryRateCell := row.AddCell()
	SetPercentForXlsx(sum.QueryRate, queryRateCell)

	reuseCell := row.AddCell()
	reuseCell.SetInt(sum.Reuse)

	reuseRateCell := row.AddCell()
	SetPercentForXlsx(sum.ReuseRate, reuseRateCell)

	platformErrorCell := row.AddCell()
	platformErrorCell.SetInt(sum.PlatformError)

	platformErrorRateCell := row.AddCell()
	SetPercentForXlsx(sum.PlatformErrorRate, platformErrorRateCell)

	providerErrorCell := row.AddCell()
	providerErrorCell.SetInt(sum.ProviderError)

	providerErrorRateCell := row.AddCell()
	SetPercentForXlsx(sum.ProviderErrorRate, providerErrorRateCell)

	avgElapsedCell := row.AddCell()
	sum.AvgElapsed = sum.SumElapsed / float64(sum.Total)
	elStr := strconv.FormatFloat(sum.AvgElapsed, 'f', 2, 64)
	el, _ := strconv.ParseFloat(elStr, 64)
	avgElapsedCell.SetFloatWithFormat(el, "0.00")
	for _, v := range sum.BigElapsedList {
		cell := row.AddCell()
		cell.SetInt(v)
	}
	for _, v := range sum.ChargeBigElapsedList {
		cell := row.AddCell()
		cell.SetInt(v)
	}
}

func parseProviderSum(sum *gd_statistics.LogQueryProviderCountExport, sheet *xlsx.Sheet) {
	row := sheet.AddRow()
	if sum.Total == 0 {
		sum.FailedRate = "0%"
		sum.QueryNoRecordRate = "0%"
	} else {
		sum.FailedRate = strconv.FormatFloat(float64(100*sum.Failed)/float64(sum.Total), 'f', 2, 64) + "%"
		sum.QueryNoRecordRate = strconv.FormatFloat(float64(100*sum.QueryNoRecord)/float64(sum.Total), 'f', 2, 64) + "%"
	}

	dateCell := row.AddCell()
	dateCell.Value = sum.Date

	nameCell := row.AddCell()
	nameCell.Value = " "

	totalCell := row.AddCell()
	totalCell.SetInt(int(sum.Total))

	successCell := row.AddCell()
	successCell.SetInt(int(sum.Success))

	failedCell := row.AddCell()
	failedCell.SetInt(int(sum.Failed))

	failedRateCell := row.AddCell()
	SetPercentForXlsx(sum.FailedRate, failedRateCell)

	queryCell := row.AddCell()
	queryCell.SetInt(int(sum.Query))

	queryNoRecordCell := row.AddCell()
	queryNoRecordCell.SetInt(int(sum.QueryNoRecord))

	queryNoRecordRateCell := row.AddCell()
	SetPercentForXlsx(sum.QueryNoRecordRate, queryNoRecordRateCell)

	avgElapsedCell := row.AddCell()
	elStr := strconv.FormatFloat(sum.SumElapsed/float64(sum.Total), 'f', 2, 64)
	el, _ := strconv.ParseFloat(elStr, 64)
	avgElapsedCell.SetFloatWithFormat(el, "0.00")
	for _, v := range sum.BigElapsedList {
		cell := row.AddCell()
		cell.SetInt(v)
	}
	for _, v := range sum.ChargeBigElapsedList {
		cell := row.AddCell()
		cell.SetInt(v)
	}

}

func parseErrorsCount(reply *gd_statistics.LogQueryUserAccessCountExportReply, file *xlsx.File) error {
	table := make(map[string][]gd_statistics.ErrorExport, 0)
	for index, _ := range reply.ErrorCount {
		table[reply.ErrorCount[index].ApiName] = append(table[reply.ErrorCount[index].ApiName], reply.ErrorCount[index])
	}
	if len(table) == 0 {
		file.AddSheet("空")
	}
	for k, v := range table {
		sheet, err := file.AddSheet(k + "失败分布")
		if err != nil {
			return err
		}
		makeXlsxErrorHeader(sheet, v[0].Errors)
		sumTotal := 0
		sumRate := make([]gd_statistics.ErrorCodeCount, len(v[0].Errors))
		for index, _ := range v {
			row := sheet.AddRow()
			cell := row.AddCell()
			cell.Value = v[index].Date

			cell = row.AddCell()
			cell.Value = fmt.Sprintf("%d", v[index].Total)
			sumTotal += v[index].Total
			for i := 0; i < len(v[index].Errors); i++ {
				cell := row.AddCell()
				cell.Value = fmt.Sprintf("%d", v[index].Errors[i].Count)
				cell = row.AddCell()
				cell.Value = v[index].Errors[i].Rate
				sumRate[i].Count += v[index].Errors[i].Count
			}
		}
		row := sheet.AddRow()
		cell := row.AddCell()
		cell.Value = "总"
		cell = row.AddCell()
		cell.Value = fmt.Sprintf("%d", sumTotal)
		for i := 0; i < len(sumRate); i++ {
			cell = row.AddCell()
			cell.Value = fmt.Sprintf("%d", sumRate[i].Count)
			cell = row.AddCell()
			cell.Value = strconv.FormatFloat(float64(100*sumRate[i].Count)/float64(sumTotal), 'f', 2, 64) + "%"
		}
	}
	return nil
}

func parseSourceCount(reply *gd_statistics.LogQueryUserAccessCountExportReply, file *xlsx.File) error {
	table := make(map[string][]gd_statistics.SourceExport, 0)
	for index, _ := range reply.SourceCount {
		table[reply.SourceCount[index].ApiName] = append(table[reply.SourceCount[index].ApiName], reply.SourceCount[index])
	}
	if len(table) == 0 {
		file.AddSheet("空")
	}
	for k, v := range table {
		sheet, err := file.AddSheet(k + "来源分布")
		if err != nil {
			return err
		}
		makeXlsxSourceHeader(sheet, v[0].Sources)
		sumTotal := 0
		sumRate := make([]gd_statistics.SourceNameCount, len(v[0].Sources))
		for index, _ := range v {
			row := sheet.AddRow()
			cell := row.AddCell()
			cell.Value = v[index].Date

			cell = row.AddCell()
			cell.Value = fmt.Sprintf("%d", v[index].Total)
			sumTotal += v[index].Total
			for i := 0; i < len(v[index].Sources); i++ {
				cell := row.AddCell()
				cell.Value = fmt.Sprintf("%d", v[index].Sources[i].Count)
				cell = row.AddCell()
				cell.Value = v[index].Sources[i].Rate
				sumRate[i].Count += v[index].Sources[i].Count
			}
		}
		row := sheet.AddRow()
		cell := row.AddCell()
		cell.Value = "总"
		cell = row.AddCell()
		cell.Value = fmt.Sprintf("%d", sumTotal)
		for i := 0; i < len(sumRate); i++ {
			cell = row.AddCell()
			cell.Value = fmt.Sprintf("%d", sumRate[i].Count)
			cell = row.AddCell()
			cell.Value = strconv.FormatFloat(float64(100*sumRate[i].Count)/float64(sumTotal), 'f', 2, 64) + "%"
		}
	}
	return nil
}

func sumBigElapseds(oldList []int, newList []int) []int {
	if len(oldList) == 0 {
		return newList
	}
	if len(oldList) != len(newList) {
		return oldList
	}

	for i, _ := range oldList {
		oldList[i] = oldList[i] + newList[i]
	}

	return oldList
}

func setAllCells(file *xlsx.File) {
	style := xlsx.NewStyle()
	font := xlsx.NewFont(10, "Microsoft YaHei")
	style.Font = *font
	style.Border = *xlsx.NewBorder("thin", "none", "thin", "thin")

	headerStyle := xlsx.NewStyle()
	fill := xlsx.NewFill("solid", "00B0C4DE", "00000000")
	headerStyle.Font = *font
	headerStyle.Fill = *fill
	headerStyle.Border = *xlsx.NewBorder("thin", "none", "thin", "thin")
	sheets := file.Sheets
	for i := 0; i < len(sheets); i++ {
		rows := sheets[i].Rows
		for j := 0; j < len(rows); j++ {
			cells := rows[j].Cells
			for k := 0; k < len(cells); k++ {
				if j < 2 {
					cells[k].SetStyle(headerStyle)
				} else {
					cells[k].SetStyle(style)
				}
			}
		}
	}
}

func parseAccessCount(reply *gd_statistics.LogQueryUserAccessCountExportReply, file *xlsx.File, timeList string) error {
	table := make(map[string][]gd_statistics.LogQueryUserAcessCountExport, 0)
	for index, _ := range reply.LogQueryUserAcessCount {
		table[reply.LogQueryUserAcessCount[index].ApiName] = append(table[reply.LogQueryUserAcessCount[index].ApiName], reply.LogQueryUserAcessCount[index])

	}
	if len(table) == 0 {
		file.AddSheet("空")
	}
	for k, v := range table {
		sheet, err := file.AddSheet(k + "指标")
		if err != nil {
			return err
		}
		makeXlsxHeader(sheet, timeList)
		sum := gd_statistics.LogQueryUserAcessCountExport{}
		sum.Date = "总"
		for index, _ := range v {
			row := sheet.AddRow()
			dateCell := row.AddCell()
			dateCell.Value = v[index].Date

			totalCell := row.AddCell()
			sum.Total += int(v[index].Total)
			totalCell.SetInt(int(v[index].Total))

			validCell := row.AddCell()
			sum.Valid += int(v[index].Valid)
			validCell.SetInt(int(v[index].Valid))

			validRateCell := row.AddCell()
			SetPercentForXlsx(v[index].ValidRate, validRateCell)

			chargeCell := row.AddCell()
			sum.Charge += int(v[index].Charge)
			chargeCell.SetInt(int(v[index].Charge))

			chargeRateCell := row.AddCell()
			SetPercentForXlsx(v[index].ChargeRate, chargeRateCell)

			successCell := row.AddCell()
			successCell.SetInt(v[index].Success)
			sum.Success += v[index].Success

			successRateCell := row.AddCell()
			SetPercentForXlsx(v[index].SuccessRate, successRateCell)

			queryCell := row.AddCell()
			queryCell.SetInt(v[index].Query)
			sum.Query += v[index].Query

			queryRateCell := row.AddCell()
			SetPercentForXlsx(v[index].QueryRate, queryRateCell)

			reuseCell := row.AddCell()
			reuseCell.SetInt(v[index].Reuse)
			sum.Reuse += v[index].Reuse

			reuseRateCell := row.AddCell()
			SetPercentForXlsx(v[index].ReuseRate, reuseRateCell)

			platformErrorCell := row.AddCell()
			platformErrorCell.SetInt(v[index].PlatformError)
			sum.PlatformError += v[index].PlatformError

			platformErrorRateCell := row.AddCell()
			SetPercentForXlsx(v[index].PlatformErrorRate, platformErrorRateCell)
			providerErrorCell := row.AddCell()
			providerErrorCell.SetInt(v[index].ProviderError)
			sum.ProviderError += v[index].ProviderError

			providerErrorRateCell := row.AddCell()
			SetPercentForXlsx(v[index].ProviderErrorRate, providerErrorRateCell)

			avgElapsedCell := row.AddCell()
			elStr := strconv.FormatFloat(v[index].AvgElapsed, 'f', 2, 64)
			el, _ := strconv.ParseFloat(elStr, 64)
			avgElapsedCell.SetFloatWithFormat(el, "0.00")
			sum.SumElapsed += v[index].SumElapsed

			for _, big := range v[index].BigElapsedList {
				cell := row.AddCell()
				cell.SetInt(big)
			}

			sum.BigElapsedList = sumBigElapseds(sum.BigElapsedList, v[index].BigElapsedList)
			for _, big := range v[index].ChargeBigElapsedList {
				cell := row.AddCell()
				cell.SetInt(big)
			}
			sum.ChargeBigElapsedList = sumBigElapseds(sum.ChargeBigElapsedList, v[index].ChargeBigElapsedList)

		}
		parseSum(&sum, sheet)
	}
	return nil
}

// @Title 访问日志用户统计报表导出
// @Description 访问日志用户统计报表导出
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   export    body   rpc_apis.gd_statistics.LogQueryUserAccessCountExportReq true "数据源"
// @Success 200 	{object} params.param_v1_0.LogQueryUserAccessCountResp "响应信息"
// @Failure 500 	服务器错误
// @router /user_access_count_export [post]
func (u *BaseAccessLogController) LogQueryUserAccessCountExport() {
	u.LogID = fmt.Sprintf("LogQueryUserAccessCountExport[%d]", time.Now().UnixNano())
	req := &param_v1_0.LogQueryUserAccessCountExportReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}
	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		exportReq := gd_statistics.LogExportCreateReq{}
		exportReq.Status = "开始"
		exportReq.FileName = req.Export.ExportName
		if exportReq.FileName == "" {
			return errors.ArgsError
		}
		host := u.Ctx.Request.Host
		if strings.Contains(ServerIp, "0.0.0.0") == false {
			host = ServerIp + ":" + ServerPort
		} else if strings.Contains(u.Ctx.Request.Host, ":") == false {
			host = u.Ctx.Request.Host + ":" + ServerPort
		}
		exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx"
		if true {
			exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx")
		}
		exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExportCreate"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		exportReq.Id = exportReply.Id
		defer ExportUpdate(u, &exportReq)

		mreq := gd_statistics.LogQueryUserAccessCountExportReq{}

		mreq.StartTimestamp = req.Export.StartTimestamp
		mreq.EndTimestamp = req.Export.EndTimestamp
		mreq.ApiIdList = req.Export.ApiIdList
		mreq.MerchantId = req.Export.MerchantId
		mreq.TimeList = req.Export.TimeList
		reply, err := rpc_apis.Statistics.LogQueryUserAccessCountExport(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryUserAccessCountExport"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			exportReq.Status = "失败"
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryUserAccessCountExportResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		file := xlsx.NewFile()
		if err := parseAccessCount(&reply, file, mreq.TimeList); err != nil {
			exportReq.Status = "失败"
			return err
		}
		if err := parseErrorsCount(&reply, file); err != nil {
			exportReq.Status = "失败"
			return err
		}

		if err := parseSourceCount(&reply, file); err != nil {
			exportReq.Status = "失败"
			return err
		}
		setAllCells(file)
		err = file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx")
		if true {
			utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx")
		}
		//resp.Data = reply
		if err != nil {
			exportReq.Status = "失败"
		} else {
			exportReq.Status = "完成"
		}
		httper.JSON(u.Ctx, resp, u.LogID)
		return err
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 数据源日志用户统计报表导出
// @Description 数据源日志用户统计报表导出
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   export    body   rpc_apis.gd_statistics.LogQueryProviderCountExportReq true ""
// @Success 200 	{object} params.param_v1_0.LogQueryProviderCountExportResp "响应信息"
// @Failure 500 	服务器错误
// @router /provider_count_export [post]
func (u *BaseAccessLogController) LogQueryProviderCountExport() {
	u.LogID = fmt.Sprintf("LogQueryProviderCountExport[%d]", time.Now().UnixNano())
	req := &param_v1_0.LogQueryProviderCountExportReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}
	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		exportReq := gd_statistics.LogExportCreateReq{}
		exportReq.ExportType = 1
		exportReq.Status = "开始"
		exportReq.FileName = req.Export.ExportName
		if exportReq.FileName == "" {
			return errors.ArgsError
		}
		host := u.Ctx.Request.Host
		if strings.Contains(ServerIp, "0.0.0.0") == false {
			host = ServerIp + ":" + ServerPort
		} else if strings.Contains(u.Ctx.Request.Host, ":") == false {
			host = u.Ctx.Request.Host + ":" + ServerPort
		}
		exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx"
		if true {
			exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx")
		}
		exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExportCreate"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		exportReq.Id = exportReply.Id
		defer ExportUpdate(u, &exportReq)

		mreq := gd_statistics.LogQueryProviderCountExportReq{}

		mreq.StartTimestamp = req.Export.StartTimestamp
		mreq.EndTimestamp = req.Export.EndTimestamp
		mreq.ProviderApiIdList = req.Export.ProviderApiIdList
		mreq.ProviderId = req.Export.ProviderId
		mreq.TimeList = req.Export.TimeList
		reply, err := rpc_apis.Statistics.LogQueryProviderCountExport(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryProviderCountExport"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			exportReq.Status = "失败"
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryProviderCountExportResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}

		table := make(map[string][]gd_statistics.LogQueryProviderCountExport, 0)
		for index, _ := range reply.LogQueryProviderCount {
			table[reply.LogQueryProviderCount[index].ProviderApiName] = append(table[reply.LogQueryProviderCount[index].ProviderApiName], reply.LogQueryProviderCount[index])

		}
		file := xlsx.NewFile()
		if len(table) == 0 {
			file.AddSheet("空")
		}
		for k, v := range table {
			sheet, err := file.AddSheet(k)
			if err != nil {
				exportReq.Status = "失败"
				return err
			}
			makeProviderXlsxHeader(sheet, mreq.TimeList)
			sum := gd_statistics.LogQueryProviderCountExport{}
			sum.Date = "总"
			for index, _ := range v {
				row := sheet.AddRow()

				dateCell := row.AddCell()
				dateCell.Value = v[index].Date

				nameCell := row.AddCell()
				nameCell.Value = v[index].ProviderName

				totalCell := row.AddCell()
				sum.Total += v[index].Total
				totalCell.SetInt(int(v[index].Total))

				successCell := row.AddCell()
				sum.Success += v[index].Success
				successCell.SetInt(int(v[index].Success))

				failedCell := row.AddCell()
				sum.Failed += v[index].Failed
				failedCell.SetInt(int(v[index].Failed))

				failedRateCell := row.AddCell()
				SetPercentForXlsx(v[index].FailedRate, failedRateCell)

				queryCell := row.AddCell()
				queryCell.SetInt(int(v[index].Query))
				sum.Query += v[index].Query

				queryNoRecordCell := row.AddCell()
				queryNoRecordCell.SetInt(int(v[index].QueryNoRecord))
				sum.QueryNoRecord += v[index].QueryNoRecord

				queryNoRecordRateCell := row.AddCell()
				SetPercentForXlsx(v[index].QueryNoRecordRate, queryNoRecordRateCell)

				avgElapsedCell := row.AddCell()
				elStr := strconv.FormatFloat(v[index].AvgElapsed, 'f', 2, 64)
				el, _ := strconv.ParseFloat(elStr, 64)
				avgElapsedCell.SetFloatWithFormat(el, "0.00")
				sum.AvgElapsed += v[index].AvgElapsed

				sum.SumElapsed += v[index].SumElapsed

				for _, big := range v[index].BigElapsedList {
					cell := row.AddCell()
					cell.SetInt(big)
				}
				sum.BigElapsedList = sumBigElapseds(sum.BigElapsedList, v[index].BigElapsedList)

				for _, big := range v[index].ChargeBigElapsedList {
					cell := row.AddCell()
					cell.SetInt(big)
				}
				sum.ChargeBigElapsedList = sumBigElapseds(sum.ChargeBigElapsedList, v[index].ChargeBigElapsedList)
			}
			parseProviderSum(&sum, sheet)
		}

		err = file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx")
		if true {
			utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx")
		}
		//resp.Data = reply
		if err != nil {
			exportReq.Status = "失败"
		} else {
			exportReq.Status = "完成"
		}
		httper.JSON(u.Ctx, resp, u.LogID)
		return err
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

var exportStatusMap = map[string]int{
	"开始": 1,
	"完成": 2,
	"失败": 3,
}

// 导出文件时去掉文件后的时间戳后缀
func convertExportFileName(src string) string {
	array := strings.Split(src, "_")
	length := len(array)
	if length < 2 {
		return src
	}
	timestampString := array[length-1]
	if len([]byte(timestampString)) < 19 {
		return src
	}
	_, err := strconv.ParseInt(timestampString, 10, 64)
	if err != nil {
		return src
	}
	return strings.TrimRight(src, "_"+timestampString)
}

// @Title 获取导出列表
// @Description 获取导出列表
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   page_number    query   int64 false "当前页"
// @Param   is_all    query   bool false "是否返回所有"
// @Param   export_type query int  false "api报表或数据源列表"
// @Success 200 	{object} params.param_v1_0.LogExportListResp "响应信息"
// @Failure 500 	服务器错误
// @router /exports [get]
func (u *BaseAccessLogController) LogExportList() {
	u.LogID = fmt.Sprintf("LogExportList[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogExportListReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogExportListReq{}
		mreq.PageNumber = req.PageNumber
		mreq.IsAll = req.IsAll
		mreq.ExportType = req.ExportType
		reply, err := rpc_apis.Statistics.LogExportList(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExportList"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogExportListResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		for i, v := range reply.ExportList {
			reply.ExportList[i].StatusCode, _ = exportStatusMap[v.Status]
			reply.ExportList[i].FileName = convertExportFileName(v.FileName)
		}
		resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 删除导出报表
// @Description 删除导出报表
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   id    query   int64 false "导出报告id"
// @Success 200 	{object} params.param_v1_0.LogExportDeleteResp "响应信息"
// @Failure 500 	服务器错误
// @router /export [delete]
func (u *BaseAccessLogController) LogExportDelete() {
	u.LogID = fmt.Sprintf("LogExportDelete[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogExportDeleteReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogExportDeleteReq{}

		mreq.Id = req.Id
		mreq.ExportDir = beego.BConfig.WebConfig.StaticDir["/export"]

		reply, err := rpc_apis.Statistics.LogExportDelete(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExportDelete"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		if reply.RealPath != "" {
			cache.Redis.Publish(BatchRemoveFileNotifyChannel, reply.RealPath)
		}
		resp := param_v1_0.LogExportDeleteResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}
		//resp.Data = reply
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 访问日志接口异常分析
// @Description 访问日志接口异常分析
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   merchant_id    query   int64 false "商户id"
// @Param   api_id    query   int64 false "基础api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   status query int false "0 全部 1 成功 2 失败"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Success 200 	{object} params.param_v1_0.LogQueryInterfaceAnalyzeResp "响应信息"
// @Failure 500 	服务器错误
// @router /access_log_interface_analyze [get]
func (u *BaseAccessLogController) LogQueryInterfaceAnalyze() {
	u.LogID = fmt.Sprintf("LogQueryInterfaceAnalyze[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryInterfaceCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryInterfaceCountReq{}

		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ApiId = req.ApiId
		mreq.MerchantId = req.MerchantId
		mreq.Option = req.Status
		reply, err := rpc_apis.Statistics.LogQueryInterfaceAnalyzeError(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryInterfaceAnalyzeError"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.LogQueryInterfaceAnalyzeResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
			Data: make([]gd_statistics.LogQueryInterfaceAnalyzeError, 0),
		}
		resp.Data = reply.List
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 访问日志接口数据源分析
// @Description 访问日志接口数据源分析
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   merchant_id    query   int64 false "商户id"
// @Param   api_id    query   int64 false "基础api id"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Success 200 	{object} params.param_v1_0.LogQueryInterfaceAnalyzeResp "响应信息"
// @Failure 500 	服务器错误
// @router /third_party_analyze [get]
func (u *BaseAccessLogController) LogQueryThirdPartyAnalyze() {
	u.LogID = fmt.Sprintf("LogQueryThirdPartyAnalyze[%d]", time.Now().UnixNano())

	req := &param_v1_0.LogQueryInterfaceCountReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}

		if uid != req.Uid {
			return errors.UserTokenillegality
		}

		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}

	handleDataTask := func() error {
		mreq := gd_statistics.LogQueryInterfaceCountReq{}

		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ApiId = req.ApiId
		mreq.MerchantId = req.MerchantId
		reply, err := rpc_apis.Statistics.LogQueryInterfaceThirdPartyCount(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogQueryInterfaceThirdPartyCount"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.ThirdPartyAnalyzeResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
			Data: make([]gd_statistics.LogQueryInterfaceThirdPartyCount, 0),
		}
		resp.Data = reply.List
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

// @Title 数据源异常分析
// @Description 数据源异常分析
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   provider_api_id    query   int64 false "基础api id"
// @Param   status    query   int false "0 全部 1 成功 2 异常"
// @Param   start_timestamp    query   int64 false "开始时间"
// @Param   end_timestamp    query   int64 false "结束时间"
// @Success 200 	{object} params.param_v1_0.ThirdPartyInterfaceErrorAnalyzeResp "响应信息"
// @Failure 500 	服务器错误
// @router /third_party_err_analyze [get]
func (u *BaseAccessLogController) ThirdPartyInterfaceErrorAnalyze() {
	u.LogID = fmt.Sprintf("LogQueryThirdPartyAnalyze[%d]", time.Now().UnixNano())
	req := &param_v1_0.ThirdPartyInterfaceErrorAnalyzeReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}
	handleTokenCheck := func() error {
		uid, _, err := utils.ParseToken(req.Token)
		if err != nil {
			return err
		}
		if uid != req.Uid {
			return errors.UserTokenillegality
		}
		/*if level == 0 {
			return errors.AuthNotAllow
		}*/
		return nil
	}
	handleDataTask := func() error {
		mreq := gd_statistics.ThirdPartyInterfaceErrorAnalyzeReq{}
		mreq.StartTimestamp = req.StartTimestamp
		mreq.EndTimestamp = req.EndTimestamp
		mreq.ProviderApiId = req.ProviderApiId
		mreq.Status = req.Status
		reply, err := rpc_apis.Statistics.ThirdPartyInterfaceErrorAnalyze(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "ThirdPartyInterfaceErrorAnalyze"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		resp := param_v1_0.ThirdPartyInterfaceErrorAnalyzeResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
			Data: make([]gd_statistics.ThirdPartyInterfaceErrorAnalyze, 0),
		}
		resp.Data = reply.List
		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}
	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleTokenCheck, handleDataTask,
	)
}

func ExportImpl(req *param_v1_0.LogQueryUserAccessLogExportReq,u *BaseAccessLogController) error {
	defer func() {
		if r := recover(); r != nil {
			err := fmt.Errorf("%+v", r)
			fmt.Println("export err:",err)
		}
	}()
	var headMap map[string]string
	if !req.Export.EnglishHeader {
		hReq := gd_management.ManagementGetBaseApiByRouterReq{}
		hReq.MerchantId = int(req.Export.MerchantId)
		hReq.ApiId = int(req.Export.ApiId)
		hReply, err := rpc_apis.Management.ManagementGetBaseApiByRouter(utils.NewContextFromBeegoCtx(u.Ctx), &hReq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "ManagementGetBaseApiByRouter"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			//return errors.ErrorTransform(err)
		} else {
			headMap = hReply.Data
		}
		fmt.Println("ManagementGetBaseApiByRouter:", hReply, err)
	}
	// 创建导出任务
	req.Export.ExportName = fmt.Sprintf("%s_%d", req.Export.ExportName, time.Now().UnixNano())
	exportReq := gd_statistics.LogExportCreateReq{}
	exportReq.Status = "开始"
	exportReq.ExportType = 2
	exportReq.FileName = req.Export.ExportName
	if exportReq.FileName == "" {
		return errors.ArgsError
	}
	host := u.Ctx.Request.Host
	if strings.Contains(ServerIp, "0.0.0.0") == false {
		host = ServerIp + ":" + ServerPort
	} else if strings.Contains(u.Ctx.Request.Host, ":") == false {
		host = u.Ctx.Request.Host + ":" + ServerPort
	}
	exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx"
	if true {
		exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx")
	}
	exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq)
	if err != nil {
		l.Error("rpc",
			zap.String("call", "LogExportCreate"),
			zap.String("args", utils.MarshalJsonString(req)),
			zap.String("error", err.Error()))
		return errors.ErrorTransform(err)
	}
	exportReq.Id = exportReply.Id

	// 任务执行完成后更新任务
	defer ExportUpdate(u, &exportReq)

	// 调微服务获取日志数据
	mreq := gd_statistics.LogQueryAccessLogReq{}
	mreq.StartTimestamp = req.Export.StartTimestamp
	mreq.EndTimestamp = req.Export.EndTimestamp
	mreq.ApiId = req.Export.ApiId
	mreq.MerchantId = req.Export.MerchantId
	mreq.PageNumber = 0
	mreq.PageSize = 10000
	mreq.UseId = true

	// 初始化excel manager
	mg := initLogExcelManagerNew(req.Export.IsParseParam)
	exportReq.Status = "进行中"
	ExportUpdate(u, &exportReq)
	// 考虑到数据量问题分批获取数据
	for {
		fmt.Println("111111111111111111111111111111111111111111111111111111",mreq.PageNumber)
		mreq.PageNumber += 1
		reply, err := rpc_apis.Statistics.LogExport(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExport"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			exportReq.Status = "失败"
			return errors.ErrorTransform(err)
		}

		logLen := int64(len(reply.AccessLogs))
		if len(reply.AccessLogs) == 0 {
			break
		}
		// 写入execel
		accessLogWriteToExcelNew(mg, reply.AccessLogs, headMap)

		if logLen < mreq.PageSize{
			break
		}

		mreq.LastId = reply.AccessLogs[logLen-1].Id
	}

	exportReq.Status = "完成"
	// 保存execel
	mg.baseSheet.Flush()

	if req.Export.IsParseParam{
		if mg.reqSheet != nil{
			mg.reqSheet.Flush()
		}

		if mg.resSheet != nil{
			mg.resSheet.Flush()
		}

	}

	mg.file.SaveAs(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx")
	//mg.file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx")
	if true {
		utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx")
	}

	return nil
}

// @Title 平台日志导出
// @Description 平台日志导出
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   export    body   params.param_v1_0.LogExportInfo true "导出任务信息"
// @Success 200 	{object} params.param_v1_0.LogQueryUserAccessCountExportResp "响应信息"
// @Failure 500 	服务器错误
// @router /access_log_export [post]
func (u *BaseAccessLogController) LogQueryUserAccessLogExport() {
	u.LogID = fmt.Sprintf("LogQueryUserAccessLogExport[%d]", time.Now().UnixNano())
	req := &param_v1_0.LogQueryUserAccessLogExportReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleDataTask := func() error {
		/*var headMap map[string]string
		if !req.Export.EnglishHeader {
			hReq := gd_management.ManagementGetBaseApiByRouterReq{}
			hReq.MerchantId = int(req.Export.MerchantId)
			hReq.ApiId = int(req.Export.ApiId)
			hReply, err := rpc_apis.Management.ManagementGetBaseApiByRouter(utils.NewContextFromBeegoCtx(u.Ctx), &hReq)
			if err != nil {
				l.Error("rpc",
					zap.String("call", "ManagementGetBaseApiByRouter"),
					zap.String("args", utils.MarshalJsonString(req)),
					zap.String("error", err.Error()))

			} else {
				headMap = hReply.Data
			}
			fmt.Println("ManagementGetBaseApiByRouter:", hReply, err)
		}
		// 创建导出任务
		req.Export.ExportName = fmt.Sprintf("%s_%d", req.Export.ExportName, time.Now().UnixNano())
		exportReq := gd_statistics.LogExportCreateReq{}
		exportReq.Status = "开始"
		exportReq.ExportType = 2
		exportReq.FileName = req.Export.ExportName
		if exportReq.FileName == "" {
			return errors.ArgsError
		}
		host := u.Ctx.Request.Host
		if strings.Contains(ServerIp, "0.0.0.0") == false {
			host = ServerIp + ":" + ServerPort
		} else if strings.Contains(u.Ctx.Request.Host, ":") == false {
			host = u.Ctx.Request.Host + ":" + ServerPort
		}
		exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx"
		if true {
			exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx")
		}
		exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExportCreate"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		exportReq.Id = exportReply.Id


		defer ExportUpdate(u, &exportReq)

		mreq := gd_statistics.LogQueryAccessLogReq{}
		mreq.StartTimestamp = req.Export.StartTimestamp
		mreq.EndTimestamp = req.Export.EndTimestamp
		mreq.ApiId = req.Export.ApiId
		mreq.MerchantId = req.Export.MerchantId
		mreq.PageNumber = 0
		mreq.PageSize = 1000


		// 初始化excel manager
		mg := initLogExcelManagerNew(req.Export.IsParseParam)
		total := int64(0)
		handled := int64(0)

		// 考虑到数据量问题分批获取数据
		for {
			mreq.PageNumber += 1
			reply, err := rpc_apis.Statistics.LogQueryAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
			if err != nil {
				l.Error("rpc",
					zap.String("call", "LogQueryAccessLog"),
					zap.String("args", utils.MarshalJsonString(req)),
					zap.String("error", err.Error()))
				exportReq.Status = "失败"
				return errors.ErrorTransform(err)
			}

			// 设置总数
			if total == 0 {
				total = reply.Total
			}

			// 写入execel
			accessLogWriteToExcelNew(mg, reply.AccessLogs, headMap)
			handled += int64(len(reply.AccessLogs))
			// 处理完毕
			if handled >= total {
				break
			}
		}

		exportReq.Status = "完成"
		// 保存execel
		mg.baseSheet.Flush()

		if req.Export.IsParseParam{
			if mg.reqSheet != nil{
				mg.reqSheet.Flush()
			}

			if mg.resSheet != nil{
				mg.resSheet.Flush()
			}

		}

		mg.file.SaveAs(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx")

		if true {
			utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx")
		}*/
		if req.Export.ExportName == "" {
			return errors.ArgsError
		}

		if req.Export.StartTimestamp == 0 || req.Export.EndTimestamp == 0 {
			return errors.ArgsError
		}

		// TODO 判断是否在一个月内
		monthstar := time.Unix(req.Export.StartTimestamp,0).Month()
		monthEnd := time.Unix(req.Export.EndTimestamp,0).Month()
		if monthstar != monthEnd{
			return  jsonrpc2.NewJsonError(20001, "参数错误,不能跨月导出")
		}

		go ExportImpl(req,u)
		resp := param_v1_0.LogQueryUserAccessCountExportResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}

		httper.JSON(u.Ctx, resp, u.LogID)
		return nil
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleDataTask,
	)
}

// @Title 数据源日志导出
// @Description 数据源日志导出
// @Param   token    header   string true "token"
// @Param   uid    header   int64 true "admin id"
// @Param   export    body   params.param_v1_0.ThirdpartLogExportInfo true "导出任务信息"
// @Success 200 	{object} params.param_v1_0.LogQueryUserAccessCountExportResp "响应信息"
// @Failure 500 	服务器错误
// @router /thirdpart_log_export [post]
func (u *BaseAccessLogController) LogQueryUserThirdpartLogExport() {
	u.LogID = fmt.Sprintf("LogQueryUserThirdpartLogExport[%d]", time.Now().UnixNano())
	req := &param_v1_0.LogQueryUserThirdpartLogExportReq{}
	getParamsTask := func() error {
		httper.FillRequireParams(u.Ctx, req, u.LogID)
		return nil
	}

	handleDataTask := func() error {
		// 创建导出任务
		req.Export.ExportName = fmt.Sprintf("%s_%d", req.Export.ExportName, time.Now().UnixNano())
		exportReq := gd_statistics.LogExportCreateReq{}
		exportReq.Status = "开始"
		exportReq.ExportType = 3
		exportReq.FileName = req.Export.ExportName
		if exportReq.FileName == "" {
			return errors.ArgsError
		}
		host := ServerIp + ":" + ServerPort
		exportReq.Path = "http://" + host + exportPath + req.Export.ExportName + ".xlsx"
		if true {
			exportReq.Path = getOssFileUrl(req.Export.ExportName + ".xlsx")
		}
		exportReply, err := rpc_apis.Statistics.LogExportCreate(utils.NewContextFromBeegoCtx(u.Ctx), &exportReq)
		if err != nil {
			l.Error("rpc",
				zap.String("call", "LogExportCreate"),
				zap.String("args", utils.MarshalJsonString(req)),
				zap.String("error", err.Error()))
			return errors.ErrorTransform(err)
		}
		exportReq.Id = exportReply.Id

		// 任务执行完成后更新任务
		defer ExportUpdate(u, &exportReq)

		// 调微服务获取日志数据
		mreq := gd_statistics.LogQueryThirdpartAccessLogReq{}
		mreq.StartTimestamp = req.Export.StartTimestamp
		mreq.EndTimestamp = req.Export.EndTimestamp
		mreq.ProviderApiId = req.Export.ProviderApiId
		mreq.ProviderId = req.Export.ProviderId
		mreq.PageNumber = 0
		mreq.PageSize = 1000

		// 初始化excel manager
		mg := initLogExcelManager(req.Export.IsParseParam)
		total := int64(0)
		handled := int64(0)

		// 考虑到数据量问题分批获取数据
		for {
			mreq.PageNumber += 1
			reply, err := rpc_apis.Statistics.LogQueryThirdpartAccessLog(utils.NewContextFromBeegoCtx(u.Ctx), &mreq)
			if err != nil {
				l.Error("rpc",
					zap.String("call", "LogQueryThirdpartAccessLog"),
					zap.String("args", utils.MarshalJsonString(req)),
					zap.String("error", err.Error()))
				exportReq.Status = "失败"
				return errors.ErrorTransform(err)
			}

			// 设置总数
			if total == 0 {
				total = reply.Total
			}

			// 数据写入execel
			thirdLogWriteToExcel(mg, reply.ThirdpartLogs)
			handled += int64(len(reply.ThirdpartLogs))

			// 处理完毕
			if handled >= total {
				break
			}
		}
		exportReq.Status = "完成"
		// 保存execel
		mg.file.Save(beego.BConfig.WebConfig.StaticDir["/export"] + req.Export.ExportName + ".xlsx")
		if true {
			utils.OssUploadFile(beego.BConfig.WebConfig.StaticDir["/export"]+req.Export.ExportName+".xlsx", req.Export.ExportName+".xlsx")
		}
		resp := param_v1_0.LogQueryUserAccessCountExportResp{
			SimpleResp: param_base.SimpleResp{
				Code: 0,
				Msg:  "SUCCESS",
			},
		}

		httper.JSON(u.Ctx, resp, u.LogID)
		return err
	}

	// 执行以上定义的任务
	task.Do(&task.PanicRecover{
		Ctx:   u.Ctx,
		LogID: u.LogID}, u.Ctx,
		getParamsTask, handleDataTask,
	)
}
