package trade_analysis

import (
	"encoding/json"
	"eta/eta_api/controllers"
	"eta/eta_api/models"
	"eta/eta_api/models/data_manage/excel"
	tradeAnalysisModel "eta/eta_api/models/data_manage/trade_analysis"
	tradeAnalysisRequest "eta/eta_api/models/data_manage/trade_analysis/request"
	tradeAnalysisResponse "eta/eta_api/models/data_manage/trade_analysis/response"
	"eta/eta_api/services"
	tradeAnalysisService "eta/eta_api/services/data/trade_analysis"
	"eta/eta_api/utils"
	"fmt"
	"github.com/tealeg/xlsx"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// TradeAnalysisTableController 多空分析表格
type TradeAnalysisTableController struct {
	controllers.BaseAuthController
}

// Preview
// @Title 表格预览
// @Description 表格预览
// @Param	request	body request.TablePreviewReq true "type json string"
// @Success 200 {object} response.TableResp
// @router /table/preview [post]
func (this *TradeAnalysisTableController) Preview() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req tradeAnalysisRequest.TablePreviewReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常"
		br.ErrMsg = fmt.Sprintf("参数解析异常: %v", e)
		return
	}
	// 校验配置
	pass, tips := tradeAnalysisService.CheckAnalysisTableExtraConfig(req.TableConfig)
	if !pass {
		br.Msg = tips
		return
	}

	// 根据配置获取表格行数据
	tableRows, e := tradeAnalysisService.GetTableRowsDataByConfig(req.TableConfig)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("获取表格行数据失败, %v", e)
		return
	}

	// 响应
	resp := new(tradeAnalysisResponse.TableResp)
	resp.TableData = tableRows
	resp.TableName = strings.TrimSpace(req.TableName)
	resp.ClassifyId = req.ClassifyId
	resp.TableConfig = req.TableConfig
	resp.TableCols = make([]*tradeAnalysisModel.TradeAnalysisTableColumnItem, 0)
	if len(req.TableCols) > 0 {
		resp.TableCols = req.TableCols
	}
	if len(req.TableCols) == 0 {
		// 获取默认的表头信息
		colOb := new(tradeAnalysisModel.TradeAnalysisTableColumn)
		cond := fmt.Sprintf(` AND %s = 0`, colOb.Cols().ExcelInfoId)
		defaultCols, e := colOb.GetItemsByCondition(cond, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC", colOb.Cols().Sort))
		if e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("获取默认表头设置失败, %v", e)
			return
		}
		for _, v := range defaultCols {
			resp.TableCols = append(resp.TableCols, v.Format2Item())
		}
	}

	br.Data = resp
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Save
// @Title 保存表格
// @Description 保存表格
// @Param	request	body request.TableSaveReq true "type json string"
// @Success 200 string "操作成功"
// @router /table/save [post]
func (this *TradeAnalysisTableController) Save() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req tradeAnalysisRequest.TableSaveReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常"
		br.ErrMsg = fmt.Sprintf("参数解析异常: %v", e)
		return
	}
	// 校验配置
	pass, tips := tradeAnalysisService.CheckAnalysisTableExtraConfig(req.TableConfig)
	if !pass {
		br.Msg = tips
		return
	}
	req.TableName = strings.TrimSpace(req.TableName)
	if req.TableName == "" {
		br.Msg = "请输入表格名称"
		return
	}
	if req.ClassifyId <= 0 {
		br.Msg = "请选择分类"
		return
	}
	configByte, e := json.Marshal(req.TableConfig)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("表格配置JSON格式化失败, %v", e)
		return
	}
	extraConfig := string(configByte)

	// 表格数据
	tableRows, e := tradeAnalysisService.GetTableRowsDataByConfig(req.TableConfig)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("获取表格行数据失败, %v", e)
		return
	}
	contentByte, e := json.Marshal(tableRows)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("表格数据JSON格式化失败, %v", e)
		return
	}
	excelContent := string(contentByte)

	// 新增表格
	var excelId int
	if req.ExcelInfoId <= 0 {
		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) + "_" + utils.GetRandString(10)
		newExcel := &excel.ExcelInfo{
			ExcelName:          req.TableName,
			Source:             utils.TRADE_ANALYSIS_TABLE,
			ExcelType:          1,
			UniqueCode:         utils.MD5(utils.EXCEL_DATA_PREFIX + "_" + timestamp),
			ExcelClassifyId:    req.ClassifyId,
			SysUserId:          sysUser.AdminId,
			SysUserRealName:    sysUser.RealName,
			Content:            excelContent,
			ExtraConfig:        extraConfig,
			UpdateUserId:       sysUser.AdminId,
			UpdateUserRealName: sysUser.RealName,
			ModifyTime:         time.Now(),
			CreateTime:         time.Now(),
		}
		if e := newExcel.Create(); e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("新增表格失败, %v", e)
			return
		}
		excelId = newExcel.ExcelInfoId
	}

	// 更新表格
	if req.ExcelInfoId > 0 {
		excelItem, e := excel.GetExcelInfoById(req.ExcelInfoId)
		if e != nil {
			if e.Error() == utils.ErrNoRow() {
				br.Msg = "表格不存在, 请刷新页面"
				return
			}
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("获取表格信息失败, %v", e)
			return
		}
		excelItem.ExcelName = req.TableName
		excelItem.ExcelClassifyId = req.ClassifyId
		excelItem.Content = excelContent
		excelItem.ExtraConfig = extraConfig
		excelItem.UpdateUserId = sysUser.AdminId
		excelItem.UpdateUserRealName = sysUser.RealName
		excelItem.ModifyTime = time.Now()
		updateCols := []string{"ExcelName", "ExcelClassifyId", "ExtraConfig", "Content", "UpdateUserId", "UpdateUserRealName", "ModifyTime"}
		if e = excelItem.Update(updateCols); e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("更新表格信息失败, %v", e)
			return
		}
		excelId = excelItem.ExcelInfoId
	}
	if excelId <= 0 {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("表格ID异常: %d", excelId)
		return
	}

	// 表头信息
	columnOb := new(tradeAnalysisModel.TradeAnalysisTableColumn)
	configColumns := make([]*tradeAnalysisModel.TradeAnalysisTableColumn, 0)
	if len(req.TableCols) > 0 {
		for _, v := range req.TableCols {
			t := new(tradeAnalysisModel.TradeAnalysisTableColumn)
			t.ExcelInfoId = excelId
			t.ColumnKey = v.ColumnKey
			t.ColumnName = v.ColumnName
			t.ColumnNameEn = v.ColumnNameEn
			t.Sort = v.Sort
			t.IsMust = v.IsMust
			t.IsShow = v.IsShow
			t.IsSort = v.IsSort
			t.CreateTime = time.Now()
			t.ModifyTime = time.Now()
			configColumns = append(configColumns, t)
		}
	} else {
		// 获取默认的表头信息
		cond := fmt.Sprintf(` AND %s = 0`, columnOb.Cols().ExcelInfoId)
		defaultCols, e := columnOb.GetItemsByCondition(cond, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC", columnOb.Cols().Sort))
		if e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("获取默认表头设置失败, %v", e)
			return
		}
		for _, v := range defaultCols {
			v.Id = 0
			v.ExcelInfoId = excelId
			v.CreateTime = time.Now()
			v.ModifyTime = time.Now()
			configColumns = append(configColumns, v)
		}
	}

	// 删除并新增表头
	{
		cond := fmt.Sprintf(`%s = ?`, columnOb.Cols().ExcelInfoId)
		pars := make([]interface{}, 0)
		pars = append(pars, excelId)
		if e = columnOb.RemoveByCondition(cond, pars); e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("删除原表头配置失败, %v", e)
			return
		}
		if e = columnOb.CreateMulti(configColumns); e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("批量新增表头配置失败, %v", e)
			return
		}
	}

	br.Data = excelId
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Detail
// @Title 表格详情
// @Description 表格详情
// @Param   ExcelInfoId  query  int  true  "表格ID"
// @Success 200 {object} response.TableResp
// @router /table/detail [get]
func (this *TradeAnalysisTableController) Detail() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	excelId, _ := this.GetInt("ExcelInfoId", 0)
	if excelId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("表格ID不可为空, ID: %d", excelId)
		return
	}

	// 获取表格信息
	excelItem, e := excel.GetExcelInfoById(excelId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "表格不存在, 请刷新页面"
			return
		}
		br.Msg = "获取失败"
		br.ErrMsg = fmt.Sprintf("获取表格信息失败, %v", e)
		return
	}
	if excelItem.Source != utils.TRADE_ANALYSIS_TABLE {
		br.Msg = "获取失败"
		br.ErrMsg = fmt.Sprintf("表格类型异常, Source: %d", excelItem.Source)
		return
	}
	var tableConfig tradeAnalysisModel.TableExtraConfig
	if e = json.Unmarshal([]byte(excelItem.ExtraConfig), &tableConfig); e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = fmt.Sprintf("解析表格配置失败, err: %v, config: %s", e, excelItem.ExtraConfig)
		return
	}

	// 表格数据
	tableRows := make([]*tradeAnalysisModel.TableRowData, 0)
	if excelItem.Content != "" {
		if e = json.Unmarshal([]byte(excelItem.Content), &tableRows); e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = fmt.Sprintf("解析表格配置失败, err: %v, config: %s", e, excelItem.ExtraConfig)
			return
		}
	} else {
		// 根据配置获取表格行数据
		tableRows, e = tradeAnalysisService.GetTableRowsDataByConfig(tableConfig)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = fmt.Sprintf("获取表格行数据失败, %v", e)
			return
		}
	}

	// 响应
	resp := new(tradeAnalysisResponse.TableResp)
	resp.ExcelInfoId = excelItem.ExcelInfoId
	resp.TableData = tableRows
	resp.TableName = strings.TrimSpace(excelItem.ExcelName)
	resp.ClassifyId = excelItem.ExcelClassifyId
	resp.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, excelItem.ModifyTime)
	resp.TableConfig = tableConfig
	resp.TableCols = make([]*tradeAnalysisModel.TradeAnalysisTableColumnItem, 0)
	// 获取表头信息
	{
		colOb := new(tradeAnalysisModel.TradeAnalysisTableColumn)
		cond := fmt.Sprintf(" AND %s = ?", colOb.Cols().ExcelInfoId)
		pars := make([]interface{}, 0)
		pars = append(pars, excelId)
		configCols, e := colOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", colOb.Cols().Sort))
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = fmt.Sprintf("获取表格表头设置失败, %v", e)
			return
		}
		// 表头信息为空
		if len(configCols) == 0 {
			defaultCols, e := colOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC", colOb.Cols().Sort))
			if e != nil {
				br.Msg = "操作失败"
				br.ErrMsg = fmt.Sprintf("获取默认表头设置失败, %v", e)
				return
			}
			configCols = defaultCols
		}
		for _, v := range configCols {
			resp.TableCols = append(resp.TableCols, v.Format2Item())
		}
	}
	resp.Button = services.GetTradeAnalysisTableOpButton(excelItem.SysUserId, sysUser.AdminId, sysUser.RoleTypeCode, false)

	br.Data = resp
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
}

// SaveAs
// @Title 表格另存为
// @Description 表格另存为
// @Param	request	body request.TableSaveAsReq true "type json string"
// @Success 200 string "操作成功"
// @router /table/save_as [post]
func (this *TradeAnalysisTableController) SaveAs() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req tradeAnalysisRequest.TableSaveAsReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常"
		br.ErrMsg = fmt.Sprintf("参数解析异常: %v", e)
		return
	}
	req.TableName = strings.TrimSpace(req.TableName)
	if req.TableName == "" {
		br.Msg = "请输入表格名称"
		return
	}
	if req.ClassifyId <= 0 {
		br.Msg = "请选择分类"
		return
	}

	// 原表格
	excelItem, e := excel.GetExcelInfoById(req.ExcelInfoId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "原表格不存在, 请刷新页面"
			return
		}
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("获取表格信息失败, %v", e)
		return
	}

	// 新表格
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) + "_" + utils.GetRandString(10)
	newExcel := &excel.ExcelInfo{
		ExcelName:          req.TableName,
		Source:             utils.TRADE_ANALYSIS_TABLE,
		ExcelType:          1,
		UniqueCode:         utils.MD5(utils.EXCEL_DATA_PREFIX + "_" + timestamp),
		ExcelClassifyId:    req.ClassifyId,
		SysUserId:          sysUser.AdminId,
		SysUserRealName:    sysUser.RealName,
		Content:            excelItem.Content,
		ExtraConfig:        excelItem.ExtraConfig,
		UpdateUserId:       sysUser.AdminId,
		UpdateUserRealName: sysUser.RealName,
		ModifyTime:         time.Now(),
		CreateTime:         time.Now(),
	}
	if e := newExcel.Create(); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("新增表格失败, %v", e)
		return
	}

	// 表头信息
	columnOb := new(tradeAnalysisModel.TradeAnalysisTableColumn)
	configColumns := make([]*tradeAnalysisModel.TradeAnalysisTableColumn, 0)
	{
		cond := fmt.Sprintf(` AND %s = ?`, columnOb.Cols().ExcelInfoId)
		pars := make([]interface{}, 0)
		pars = append(pars, req.ExcelInfoId)
		originColumns, e := columnOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", columnOb.Cols().Sort))
		if e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("获取默认表头设置失败, %v", e)
			return
		}
		for _, v := range originColumns {
			v.Id = 0
			v.ExcelInfoId = newExcel.ExcelInfoId
			v.CreateTime = time.Now()
			v.ModifyTime = time.Now()
			configColumns = append(configColumns, v)
		}
	}
	// 没找到就获取默认的表头信息
	if len(configColumns) == 0 {
		cond := fmt.Sprintf(` AND %s = 0`, columnOb.Cols().ExcelInfoId)
		defaultCols, e := columnOb.GetItemsByCondition(cond, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC", columnOb.Cols().Sort))
		if e != nil {
			br.Msg = "操作失败"
			br.ErrMsg = fmt.Sprintf("获取默认表头设置失败, %v", e)
			return
		}
		for _, v := range defaultCols {
			v.Id = 0
			v.ExcelInfoId = newExcel.ExcelInfoId
			v.CreateTime = time.Now()
			v.ModifyTime = time.Now()
			configColumns = append(configColumns, v)
		}
	}
	// 新增表头
	if e = columnOb.CreateMulti(configColumns); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("批量新增表头配置失败, %v", e)
		return
	}

	br.Data = newExcel.ExcelInfoId
	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Refresh
// @Title 刷新表格
// @Description 刷新表格
// @Param	request	body request.TableRefreshReq true "type json string"
// @Success 200 string "操作成功"
// @router /table/refresh [post]
func (this *TradeAnalysisTableController) Refresh() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req tradeAnalysisRequest.TableRefreshReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常"
		br.ErrMsg = fmt.Sprintf("参数解析异常: %v", e)
		return
	}
	if req.ExcelInfoId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("表格ID有误: %d", req.ExcelInfoId)
		return
	}

	cacheKey := fmt.Sprintf("%s_%d", utils.CACHE_EXCEL_REFRESH, req.ExcelInfoId)
	if utils.Rc.IsExist(cacheKey) {
		br.Ret = 200
		br.Success = true
		br.Msg = "系统处理中,请勿频繁操作"
		return
	}
	utils.Rc.SetNX(cacheKey, 1, 2*time.Minute)
	defer func() {
		_ = utils.Rc.Delete(cacheKey)
	}()

	// 获取表格信息
	item, e := excel.GetExcelInfoById(req.ExcelInfoId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Msg = "表格不存在, 请刷新页面"
			return
		}
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("获取表格信息失败, %v", e)
		return
	}

	// 获取表格内容
	var tableConfig tradeAnalysisModel.TableExtraConfig
	if item.ExtraConfig == "" {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("表格配置为空, ExcelId: %d", item.ExcelInfoId)
		return
	}
	if e = json.Unmarshal([]byte(item.ExtraConfig), &tableConfig); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("表格配置解析失败, ExcelId: %d, Err: %v", item.ExcelInfoId, e)
		return
	}
	tableData, e := tradeAnalysisService.GetTableRowsDataByConfig(tableConfig)
	if e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("获取表格行数据失败, %v", e)
		return
	}
	content, e := json.Marshal(tableData)
	if e != nil {
		br.Msg = "表格数据JSON格式化失败"
		br.ErrMsg = fmt.Sprintf("表格数据JSON格式化失败, %v", e)
		return
	}
	item.Content = string(content)

	// 更新内容
	updateCols := []string{"Content", "ModifyTime"}
	if e = item.Update(updateCols); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("更新表格数据失败, %v", e)
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Remove
// @Title 删除表格
// @Description 删除表格
// @Param	request	body request.TableRemoveReq true "type json string"
// @Success 200 string "操作成功"
// @router /table/remove [post]
func (this *TradeAnalysisTableController) Remove() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req tradeAnalysisRequest.TableRemoveReq
	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
		br.Msg = "参数解析异常"
		br.ErrMsg = fmt.Sprintf("参数解析异常: %v", e)
		return
	}
	if req.ExcelInfoId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("表格ID有误: %d", req.ExcelInfoId)
		return
	}

	// 获取表格信息
	excelItem, e := excel.GetExcelInfoById(req.ExcelInfoId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			br.Ret = 200
			br.Success = true
			br.Msg = "操作成功"
			return
		}
		br.Msg = "获取失败"
		br.ErrMsg = fmt.Sprintf("获取表格信息失败, %v", e)
		return
	}

	// 软删
	excelItem.IsDelete = 1
	excelItem.UpdateUserId = sysUser.AdminId
	excelItem.UpdateUserRealName = sysUser.RealName
	excelItem.ModifyTime = time.Now()
	updateCols := []string{"IsDelete", "UpdateUserId", "UpdateUserRealName", "ModifyTime"}
	if e = excelItem.Update(updateCols); e != nil {
		br.Msg = "操作失败"
		br.ErrMsg = fmt.Sprintf("删除表格信息失败, %v", e)
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "操作成功"
}

// Download
// @Title 下载表格
// @Description 下载表格
// @Param   ExcelInfoId  query  int  true  "表格ID"
// @Success 200  下载成功
// @router /table/download [get]
func (this *TradeAnalysisTableController) Download() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
			utils.FileLog.Info(fmt.Sprintf("多空分析表格-下载失败, ErrMsg: %s", br.ErrMsg))
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录,SysUser Is Empty"
		br.Ret = 408
		return
	}
	excelId, _ := this.GetInt("ExcelInfoId")
	if excelId <= 0 {
		br.Msg = "参数有误"
		br.ErrMsg = fmt.Sprintf("表格ID有误: %d", excelId)
		return
	}

	// 获取表格信息
	excelItem, e := excel.GetExcelInfoById(excelId)
	if e != nil {
		br.Msg = "下载失败"
		br.ErrMsg = fmt.Sprintf("获取表格信息失败, %v", e)
		return
	}

	// 获取表头信息
	configCols := make([]*tradeAnalysisModel.TradeAnalysisTableColumn, 0)
	{
		colOb := new(tradeAnalysisModel.TradeAnalysisTableColumn)
		cond := fmt.Sprintf(" AND %s = ?", colOb.Cols().ExcelInfoId)
		pars := make([]interface{}, 0)
		pars = append(pars, excelId)
		items, e := colOb.GetItemsByCondition(cond, pars, []string{}, fmt.Sprintf("%s ASC", colOb.Cols().Sort))
		if e != nil {
			br.Msg = "下载失败"
			br.ErrMsg = fmt.Sprintf("获取表格表头设置失败, %v", e)
			return
		}
		configCols = items
		// 表头信息为空
		if len(configCols) == 0 {
			defaultCols, e := colOb.GetItemsByCondition(``, make([]interface{}, 0), []string{}, fmt.Sprintf("%s ASC", colOb.Cols().Sort))
			if e != nil {
				br.Msg = "下载失败"
				br.ErrMsg = fmt.Sprintf("获取默认表头设置失败, %v", e)
				return
			}
			configCols = defaultCols
		}
	}
	if len(configCols) == 0 {
		br.Msg = "下载失败"
		br.ErrMsg = fmt.Sprintf("表头信息异常")
		return
	}

	// 表格数据
	tableRows := make([]*tradeAnalysisModel.TableRowData, 0)
	var tableConfig tradeAnalysisModel.TableExtraConfig
	if excelItem.Content != "" {
		if e = json.Unmarshal([]byte(excelItem.Content), &tableRows); e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = fmt.Sprintf("解析表格配置失败, err: %v, config: %s", e, excelItem.ExtraConfig)
			return
		}
	} else {
		// 根据配置获取表格行数据
		if e = json.Unmarshal([]byte(excelItem.ExtraConfig), &tableConfig); e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = fmt.Sprintf("解析表格配置失败, err: %v, config: %s", e, excelItem.ExtraConfig)
			return
		}
		tableRows, e = tradeAnalysisService.GetTableRowsDataByConfig(tableConfig)
		if e != nil {
			br.Msg = "获取失败"
			br.ErrMsg = fmt.Sprintf("获取表格行数据失败, %v", e)
			return
		}
	}

	// 生成excel
	dir, _ := os.Executable()
	exPath := filepath.Dir(dir)
	downFile := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
	xlsxFile := xlsx.NewFile()

	sheetNew := new(xlsx.Sheet)
	sheetNew, e = xlsxFile.AddSheet("Sheet1")
	if e != nil {
		br.Msg = "下载失败"
		br.ErrMsg = fmt.Sprintf("生成Sheet失败, %v", e)
		return
	}

	// 第一行-表头
	headerRow := sheetNew.AddRow()
	var headerKeys []string
	for _, v := range configCols {
		if v.IsShow == 0 {
			continue
		}
		headerRow.AddCell().SetValue(v.ColumnName)
		headerKeys = append(headerKeys, v.ColumnKey)
	}

	// 数据行
	for _, v := range tableRows {
		row := sheetNew.AddRow()
		rv := reflect.ValueOf(v)

		// v为指针先解引用
		if rv.Kind() == reflect.Ptr {
			rv = rv.Elem()
		}

		// 获取对应key的值
		for _, h := range headerKeys {
			fieldVal := rv.FieldByName(h)
			if fieldVal.IsValid() {
				cell := row.AddCell()
				cell.SetString(fmt.Sprint(fieldVal.Interface()))
				continue
			}
			row.AddCell().SetString("")
		}
	}

	// 保存文件
	if e = xlsxFile.Save(downFile); e != nil {
		br.Msg = "下载失败"
		br.ErrMsg = fmt.Sprintf("保存文件内容失败, %v", e)
		return
	}
	fileName := fmt.Sprintf(`%s%s.xlsx`, excelItem.ExcelName, time.Now().Format("06.01.02"))
	this.Ctx.Output.Download(downFile, fileName)
	defer func() {
		_ = os.Remove(downFile)
	}()

	br.Ret = 200
	br.Success = true
	br.Msg = "下载成功"
}