Browse Source

Merge branch '8.3' into debug

# Conflicts:
#	routers/router.go
#	utils/constants.go
Roc 2 years ago
parent
commit
61f179044b

+ 90 - 0
controllers/excel_info.go

@@ -0,0 +1,90 @@
+package controllers
+
+import (
+	"encoding/json"
+	"fmt"
+	"hongze/hongze_chart_lib/models"
+	"hongze/hongze_chart_lib/models/response"
+	"hongze/hongze_chart_lib/services/excel"
+	"hongze/hongze_chart_lib/utils"
+	"time"
+)
+
+// ExcelInfoController excel表格
+type ExcelInfoController struct {
+	BaseAuthController
+}
+
+// GetTableDetail
+// @Title 获取表格表详情
+// @Description 获取表格表详情接口
+// @Param   UniqueCode   query   string  true       "表格表唯一编码,如果是管理后台访问,传固定字符串:7c69b590249049942070ae9dcd5bf6dc"
+// @Success 200 {object} response.ExcelTableDetailResp
+// @router /detail [get]
+func (this *ExcelInfoController) GetTableDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	uniqueCode := this.GetString("UniqueCode")
+	if uniqueCode == "" {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,uniqueCode is empty"
+		return
+	}
+	key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + uniqueCode
+	resp := new(response.ExcelTableDetailResp)
+	//判断是否有缓存
+	if utils.Re == nil {
+		if utils.Re == nil && utils.Rc.IsExist(key) {
+			if data, err1 := utils.Rc.RedisBytes(key); err1 == nil {
+				err := json.Unmarshal(data, &resp)
+				if err == nil && resp != nil {
+					br.Ret = 200
+					br.Success = true
+					br.Msg = "获取成功"
+					br.Data = resp
+					fmt.Println("source redis")
+					return
+				}
+			}
+		}
+	}
+
+	excelInfo, err := models.GetExcelInfoByUniqueCode(uniqueCode)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "该表格已被删除,请刷新页面"
+			br.ErrMsg = "该表格已被删除,请刷新页面,Err:" + err.Error()
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取表格表信息失败,Err:" + err.Error()
+		return
+	}
+	luckySheetData, err := excel.GetLuckySheetData(excelInfo.Content)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	tableData, err := luckySheetData.GetTableDataByLuckySheetDataStr()
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	resp.TableInfo = tableData
+	resp.ExcelName = excelInfo.ExcelName
+	resp.ExcelImage = excelInfo.ExcelImage
+	resp.UniqueCode = excelInfo.UniqueCode
+
+	if utils.Re == nil {
+		data, _ := json.Marshal(resp)
+		utils.Rc.Put(key, data, 10*time.Minute)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 1 - 0
models/db.go

@@ -39,5 +39,6 @@ func init() {
 	orm.RegisterModel(
 		new(data_manage.EdbInfo),
 		new(ShareChartRefreshLog), //分享图表刷新日志表
+		new(ExcelInfo),            //excel表格
 	)
 }

+ 243 - 0
models/excel_info.go

@@ -0,0 +1,243 @@
+package models
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_chart_lib/utils"
+	"time"
+)
+
+// ExcelInfo excel表格详情表
+type ExcelInfo struct {
+	ExcelInfoId     int       `orm:"column(excel_info_id);pk"`
+	ExcelName       string    `description:"表格名称"`
+	UniqueCode      string    `description:"表格唯一编码"`
+	ExcelClassifyId int       `description:"表格分类id"`
+	SysUserId       int       `description:"操作人id"`
+	SysUserRealName string    `description:"操作人真实姓名"`
+	Content         string    `description:"表格内容"`
+	ExcelImage      string    `description:"表格图片"`
+	FileUrl         string    `description:"表格下载地址"`
+	Sort            int       `description:"排序字段,数字越小越排前面"`
+	IsDelete        int       `description:"是否删除,0:未删除,1:已删除"`
+	ModifyTime      time.Time `description:"最近修改日期"`
+	CreateTime      time.Time `description:"创建日期"`
+}
+
+// Update 更新 excel表格基础信息
+func (excelInfo *ExcelInfo) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	_, err = o.Update(excelInfo, cols...)
+	return
+}
+
+type MyExcelInfoList struct {
+	ExcelInfoId     int       `orm:"column(excel_info_id);pk"`
+	ExcelName       string    `description:"表格名称"`
+	UniqueCode      string    `description:"表格唯一编码"`
+	ExcelClassifyId int       `description:"表格分类id"`
+	SysUserId       int       `description:"操作人id"`
+	SysUserRealName string    `description:"操作人真实姓名"`
+	ExcelImage      string    `description:"表格图片"`
+	FileUrl         string    `description:"表格下载地址"`
+	Sort            int       `description:"排序字段,数字越小越排前面"`
+	ModifyTime      time.Time `description:"最近修改日期"`
+	CreateTime      time.Time `description:"创建日期"`
+}
+
+// AddExcelInfo 新增表格
+func AddExcelInfo(excelInfo *ExcelInfo) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// 表格信息入库
+	lastId, err := o.Insert(excelInfo)
+	if err != nil {
+		return
+	}
+	excelInfo.ExcelInfoId = int(lastId)
+	return
+}
+
+// EditExcelInfo 编辑表格
+func EditExcelInfo(excelInfo *ExcelInfo, updateExcelInfoParams []string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	// ETA表格信息变更
+	_, err = o.Update(excelInfo, updateExcelInfoParams...)
+	return
+}
+
+// GetExcelInfoById 根据id 获取eta表格详情
+func GetExcelInfoById(excelInfoId int) (item *ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_info_id=? AND is_delete=0 `
+	err = o.Raw(sql, excelInfoId).QueryRow(&item)
+	return
+}
+
+func GetExcelInfoViewById(excelInfoId int) (item *ExcelInfoView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_info_id=? AND is_delete=0 `
+	err = o.Raw(sql, excelInfoId).QueryRow(&item)
+	return
+}
+
+func GetExcelInfoCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM excel_info WHERE 1=1 AND is_delete=0 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetExcelInfoByCondition(condition string, pars []interface{}) (item *ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE 1=1 AND is_delete=0 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+// GetNextExcelInfo 根据分类id获取下一个excel表格
+func GetNextExcelInfo(classifyId int) (item *ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT b.* FROM excel_classify AS a
+			INNER JOIN excel_info AS b ON a.excel_classify_id=b.excel_classify_id
+			WHERE a.excel_classify_id>? AND is_delete=0
+			ORDER BY a.excel_classify_id ASC
+			LIMIT 1 `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+// EditExcelInfoImage 修改excel表格的图片
+func EditExcelInfoImage(excelInfoId int, imageUrl string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+
+	sql := ` UPDATE  excel_info SET excel_image=?, modify_time = NOW() WHERE excel_info_id = ? AND is_delete=0 `
+	_, err = o.Raw(sql, imageUrl, excelInfoId).Exec()
+	if err != nil {
+		fmt.Println("EditExcelInfoImage Err:", err.Error())
+		return err
+	}
+
+	return
+}
+
+// GetExcelInfoByUniqueCode 根据unique_code来获取excel表格详情
+func GetExcelInfoByUniqueCode(uniqueCode string) (item *ExcelInfoView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE unique_code=? AND is_delete=0 `
+	err = o.Raw(sql, uniqueCode).QueryRow(&item)
+	return
+}
+
+// GetFirstExcelInfoByClassifyId 获取当前分类下,且排序数相同 的排序第一条的数据
+func GetFirstExcelInfoByClassifyId(classifyId int) (item *ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_classify_id=? AND is_delete=0 order by sort asc,excel_info_id asc limit 1`
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+// UpdateExcelInfoSortByClassifyId 根据表格id更新排序
+func UpdateExcelInfoSortByClassifyId(classifyId, nowSort, prevExcelInfoId int, updateSort string) (err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` update excel_info set sort = ` + updateSort + ` WHERE excel_classify_id=? and sort > ? AND is_delete=0 `
+	if prevExcelInfoId > 0 {
+		sql += ` or (excel_info_id > ` + fmt.Sprint(prevExcelInfoId) + ` and sort = ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, classifyId, nowSort).Exec()
+	return
+}
+
+type ExcelInfoView struct {
+	ExcelInfoId     int       `orm:"column(excel_info_id);pk"`
+	ExcelName       string    `description:"表格名称"`
+	UniqueCode      string    `description:"表格唯一编码"`
+	ExcelClassifyId int       `description:"表格分类id"`
+	SysUserId       int       `description:"操作人id"`
+	SysUserRealName string    `description:"操作人真实姓名"`
+	Content         string    `description:"表格内容"`
+	ExcelImage      string    `description:"表格图片"`
+	FileUrl         string    `description:"表格下载地址"`
+	Sort            int       `description:"排序字段,数字越小越排前面"`
+	IsDelete        int       `description:"是否删除,0:未删除,1:已删除" json:"-"`
+	ModifyTime      time.Time `description:"最近修改日期"`
+	CreateTime      time.Time `description:"创建日期"`
+}
+
+// GetExcelInfoByClassifyIdAndName 根据分类id和表格名获取表格信息
+func GetExcelInfoByClassifyIdAndName(classifyId int, excelName string) (item *ExcelInfo, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_classify_id = ? and excel_name=? AND is_delete=0 `
+	err = o.Raw(sql, classifyId, excelName).QueryRow(&item)
+	return
+}
+
+// GetExcelInfoListByUniqueCodeSlice 根据表格编码获取表格列表数据
+func GetExcelInfoListByUniqueCodeSlice(uniqueCodeSlice []string) (total int64, items []*ExcelInfo, err error) {
+	num := len(uniqueCodeSlice)
+	if num <= 0 {
+		return
+	}
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE unique_code in ("` + utils.GetOrmInReplace(num) + `") AND is_delete=0 `
+	total, err = o.Raw(sql, uniqueCodeSlice).QueryRows(&items)
+	return
+}
+
+// GetExcelListByCondition 获取excel表格列表数据
+func GetExcelListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*MyExcelInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE 1=1 AND is_delete=0 `
+	if condition != "" {
+		sql += condition
+	}
+	//sql += " ORDER BY sort ASC,chart_info_id DESC LIMIT ?,? "
+	sql += " ORDER BY create_time DESC LIMIT ?,? "
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}
+
+// GetNoContentExcelListByCondition 获取没有content的excel表格列表数据
+func GetNoContentExcelListByCondition(condition string, pars []interface{}, startSize, pageSize int) (item []*MyExcelInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT excel_info_id,excel_name,unique_code,excel_classify_id,sys_user_id,sys_user_real_name,excel_image,file_url,sort,create_time,modify_time
+FROM excel_info WHERE 1=1 AND is_delete=0 `
+	if condition != "" {
+		sql += condition
+	}
+	//sql += " ORDER BY sort ASC,chart_info_id DESC LIMIT ?,? "
+	sql += " ORDER BY create_time DESC LIMIT ?,? "
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&item)
+	return
+}
+
+func GetExcelListCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT COUNT(1) AS count FROM excel_info WHERE 1=1 AND is_delete=0 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+// GetExcelViewInfoByExcelInfoId 根据excelInfoId 获取ETA表格详情
+func GetExcelViewInfoByExcelInfoId(excelInfoId int) (item *MyExcelInfoList, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT * FROM excel_info WHERE excel_info_id = ? AND is_delete=0 `
+	err = o.Raw(sql, excelInfoId).QueryRow(&item)
+	return
+}
+
+// GetExcelInfoCountByClassifyId 根据分类id获取名下表格数量
+func GetExcelInfoCountByClassifyId(classifyId int) (total int64, err error) {
+	o := orm.NewOrmUsingDB("data")
+	sql := ` SELECT count(1) total FROM excel_info WHERE excel_classify_id = ? AND is_delete=0 `
+	err = o.Raw(sql, classifyId).QueryRow(&total)
+	return
+}

+ 12 - 0
models/response/excel_info.go

@@ -0,0 +1,12 @@
+package response
+
+import "hongze/hongze_chart_lib/services/excel"
+
+// ExcelTableDetailResp  excel表格详情
+type ExcelTableDetailResp struct {
+	//ChartInfo   *ChartInfo
+	UniqueCode string `description:"表格唯一code"`
+	ExcelImage string `description:"表格截图"`
+	ExcelName  string `description:"表格名称"`
+	TableInfo  excel.TableData
+}

+ 37 - 0
routers/commentsRouter.go

@@ -0,0 +1,37 @@
+package routers
+
+import (
+	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/context/param"
+)
+
+func init() {
+
+    beego.GlobalControllerRouter["hongze/hongze_chart_lib/controllers:ChartController"] = append(beego.GlobalControllerRouter["hongze/hongze_chart_lib/controllers:ChartController"],
+        beego.ControllerComments{
+            Method: "ChartInfoDetail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_chart_lib/controllers:ChartController"] = append(beego.GlobalControllerRouter["hongze/hongze_chart_lib/controllers:ChartController"],
+        beego.ControllerComments{
+            Method: "ChartInfoRefresh",
+            Router: `/refresh`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_chart_lib/controllers:ExcelInfoController"] = append(beego.GlobalControllerRouter["hongze/hongze_chart_lib/controllers:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetTableDetail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+}

+ 5 - 0
routers/router.go

@@ -24,6 +24,11 @@ func init() {
 				&controllers.TableController{},
 			),
 		),
+		web.NSNamespace("/excel_info",
+			web.NSInclude(
+				&controllers.ExcelInfoController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 495 - 0
services/excel/lucky_sheet.go

@@ -0,0 +1,495 @@
+package excel
+
+import (
+	"encoding/json"
+	"fmt"
+	"hongze/hongze_chart_lib/utils"
+)
+
+type LuckySheetDataBak struct {
+	CalcChain []interface{}        `json:"calcChain" description:"公式链"`
+	CellData  []LuckySheetCellData `json:"celldata" description:"单元格数据"`
+	ChWidth   int64                `json:"ch_width" description:"工作表区域的宽度"`
+	Config    struct {
+		BorderInfo []struct {
+			BorderType string `json:"borderType" description:""`
+			Color      string `json:"color" description:""`
+			Range      []struct {
+				Column []int64 `json:"column" description:""`
+				Row    []int64 `json:"row" description:""`
+			} `json:"range" description:""`
+			RangeType string `json:"rangeType" description:""`
+			Style     string `json:"style" description:""`
+			Value     struct {
+				B struct {
+					Color string `json:"color" description:""`
+					Style string `json:"style" description:""`
+				} `json:"b" description:""`
+				ColIndex int64 `json:"col_index" description:""`
+				L        struct {
+					Color string `json:"color" description:""`
+					Style string `json:"style" description:""`
+				} `json:"l" description:""`
+				R struct {
+					Color string `json:"color" description:""`
+					Style string `json:"style" description:""`
+				} `json:"r" description:""`
+				RowIndex int64 `json:"row_index" description:""`
+				T        struct {
+					Color string `json:"color" description:""`
+					Style string `json:"style" description:""`
+				} `json:"t" description:""`
+			} `json:"value" description:"" description:""`
+		} `json:"borderInfo" description:""`
+		Colhidden    struct{}           `json:"colhidden" description:""`
+		Columnlen    map[string]float64 `json:"columnlen" description:""`
+		CustomHeight struct {
+			Zero int64 `json:"0"`
+		} `json:"customHeight" description:""`
+		CustomWidth struct {
+			Two int64 `json:"2" description:""`
+		} `json:"customWidth" description:""`
+		Merge  struct{}           `json:"merge" description:""`
+		Rowlen map[string]float64 `json:"rowlen" description:""`
+	} `json:"config" description:""`
+	Data [][]struct {
+		Ct struct {
+			Fa string `json:"fa"`
+			T  string `json:"t"`
+		} `json:"ct"`
+		M string      `json:"m"`
+		V interface{} `json:"v"`
+	} `json:"data" description:""`
+	DataVerification              struct{}      `json:"dataVerification" description:""`
+	Filter                        interface{}   `json:"filter" description:""`
+	FilterSelect                  interface{}   `json:"filter_select" description:""`
+	Hyperlink                     struct{}      `json:"hyperlink" description:""`
+	Images                        struct{}      `json:"images" description:""`
+	Index                         string        `json:"index" description:""`
+	JfgirdSelectSave              []interface{} `json:"jfgird_select_save" description:""`
+	LuckysheetAlternateformatSave []interface{} `json:"luckysheet_alternateformat_save" description:""`
+	LuckysheetConditionformatSave []interface{} `json:"luckysheet_conditionformat_save" description:""`
+	LuckysheetSelectSave          []struct {
+		Column      []int64 `json:"column" description:""`
+		ColumnFocus int64   `json:"column_focus" description:""`
+		Height      int64   `json:"height" description:""`
+		HeightMove  int64   `json:"height_move" description:""`
+		Left        int64   `json:"left" description:""`
+		LeftMove    int64   `json:"left_move" description:""`
+		Row         []int64 `json:"row" description:""`
+		RowFocus    int64   `json:"row_focus" description:""`
+		Top         int64   `json:"top" description:""`
+		TopMove     int64   `json:"top_move" description:""`
+		Width       int64   `json:"width" description:""`
+		WidthMove   int64   `json:"width_move" description:""`
+	} `json:"luckysheet_select_save" description:"" description:""`
+	LuckysheetSelectionRange []struct {
+		Column []int64 `json:"column" description:""`
+		Row    []int64 `json:"row" description:""`
+	} `json:"luckysheet_selection_range" description:""`
+	RhHeight          int64   `json:"rh_height" description:""`
+	ScrollLeft        int64   `json:"scrollLeft" description:""`
+	ScrollTop         int64   `json:"scrollTop" description:""`
+	Status            int64   `json:"status" description:""`
+	Visibledatacolumn []int64 `json:"visibledatacolumn" description:""`
+	Visibledatarow    []int64 `json:"visibledatarow" description:""`
+	ZoomRatio         int64   `json:"zoomRatio" description:""`
+}
+
+// LuckySheetData sheet表格数据
+type LuckySheetData struct {
+	CellData []LuckySheetCellData `json:"celldata" description:"单元格数据"`
+	ChWidth  int64                `json:"ch_width" description:"工作表区域的宽度"`
+	Config   LuckySheetDataConfig `json:"config" description:""`
+	//Index             int                  `json:"index" description:"工作表索引"`
+	RhHeight          int64   `json:"rh_height" description:"工作表区域的高度"`
+	ScrollLeft        int64   `json:"scrollLeft" description:"左右滚动条位置"`
+	ScrollTop         int64   `json:"scrollTop" description:"上下滚动条位置"`
+	Status            int64   `json:"status" description:"激活状态"`
+	VisibleDataColumn []int64 `json:"visibledatacolumn" description:"所有列的位置信息,递增的列位置数据,初始化无需设置"`
+	VisibleDataRow    []int64 `json:"visibledatarow" description:"所有行的位置信息,递增的行位置数据,初始化无需设置"`
+	ZoomRatio         int64   `json:"zoomRatio" description:"缩放比例"`
+}
+
+// LuckySheetDataConfig sheet表单的配置
+type LuckySheetDataConfig struct {
+	BorderInfo []LuckySheetDataConfigBorderInfo `json:"borderInfo" description:"边框"`
+	Colhidden  map[string]int64                 `json:"colhidden" description:"隐藏列,示例值:\"colhidden\":{\"30\":0,\"31\":0}"`
+	Columnlen  map[string]float64               `json:"columnlen" description:"每个单元格的列宽"`
+	//CustomHeight struct {
+	//	Zero int64 `json:"0"`
+	//} `json:"customHeight" description:""`
+	//CustomWidth struct {
+	//	Two int64 `json:"2" description:""`
+	//} `json:"customWidth" description:""`
+	Merge  map[string]LuckySheetDataConfigMerge `json:"merge" description:"合并单元格"`
+	Rowlen map[string]float64                   `json:"rowlen" description:"每个单元格的行高"`
+}
+
+// LuckySheetDataConfigMerge 合并单元格设置
+type LuckySheetDataConfigMerge struct {
+	Row    int `json:"r" description:"行数"`
+	Column int `json:"c" description:"列数"`
+	Rs     int `json:"rs" description:"合并的行数"`
+	Cs     int `json:"cs" description:"合并的列数"`
+}
+
+// LuckySheetDataConfigBorderInfo 单元格边框信息
+type LuckySheetDataConfigBorderInfo struct {
+	BorderType string `json:"borderType" description:"边框类型 border-left | border-right | border-top | border-bottom | border-all | border-outside | border-inside | border-horizontal | border-vertical | border-none"`
+	Color      string `json:"color" description:"边框颜色 color: 16进制颜色值"`
+	Range      []struct {
+		Column []int64 `json:"column" description:"行"`
+		Row    []int64 `json:"row" description:"列"`
+	} `json:"range" description:"选区范围 range: 行列信息数组"`
+	RangeType string                                  `json:"rangeType" description:"选区 rangeType: range | cell "`
+	Style     string                                  `json:"style" description:"边框粗细 style: 1 Thin | 2 Hair | 3 Dotted | 4 Dashed | 5 DashDot | 6 DashDotDot | 7 Double | 8 Medium | 9 MediumDashed | 10 MediumDashDot | 11 MediumDashDotDot | 12 SlantedDashDot | 13 Thick ,和aspose.cells的getLineStyle()的值对应的话,需要自己做个转换,参考 aspose.cells"`
+	Value     LuckySheetDataConfigBorderInfoCellValue `json:"value" description:"" description:"范围类型分单个单元格的数据"`
+}
+
+// LuckySheetDataConfigBorderInfoCellValue 单元格边框信息(范围类型为:单个单元格)
+type LuckySheetDataConfigBorderInfoCellValue struct {
+	B        LuckySheetDataConfigBorderInfoCell `json:"b" description:"下边框"`
+	L        LuckySheetDataConfigBorderInfoCell `json:"l" description:"左边框"`
+	R        LuckySheetDataConfigBorderInfoCell `json:"r" description:"右边框"`
+	T        LuckySheetDataConfigBorderInfoCell `json:"t" description:"上边框"`
+	ColIndex int64                              `json:"col_index" description:"第几行"`
+	RowIndex int64                              `json:"row_index" description:"第几列"`
+}
+
+// LuckySheetDataConfigBorderInfoCell 单元格边框信息(cell类型)
+type LuckySheetDataConfigBorderInfoCell struct {
+	Color string `json:"color" description:"边框颜色 color: 16进制颜色值"`
+	Style string `json:"style" description:"边框粗细 style: 1 Thin | 2 Hair | 3 Dotted | 4 Dashed | 5 DashDot | 6 DashDotDot | 7 Double | 8 Medium | 9 MediumDashed | 10 MediumDashDot | 11 MediumDashDotDot | 12 SlantedDashDot | 13 Thick ,和aspose.cells的getLineStyle()的值对应的话,需要自己做个转换,参考 aspose.cells"`
+}
+
+// LuckySheetCellData 单个单元格数据
+type LuckySheetCellData struct {
+	Col   int64               `json:"c" description:"列"`
+	Row   int64               `json:"r" description:"行"`
+	Value LuckySheetDataValue `json:"v" description:"单元格内值的数据"`
+}
+
+// LuckySheetDataValue 单元格内值的数据
+type LuckySheetDataValue struct {
+	CellType       LuckySheetDataCellType    `json:"ct" description:"单元格值格式:文本、时间等	"`
+	Value          interface{}               `json:"v" description:"原始值"`
+	Monitor        string                    `json:"m" description:"显示值"`
+	Background     string                    `json:"bg" description:"背景色,实例值:#fff000"`
+	FontFamily     int                       `json:"ff" description:"字体,0 Times New Roman、 1 Arial、2 Tahoma 、3 Verdana、4 微软雅黑、5 宋体(Song)、6 黑体(ST Heiti)、7 楷体(ST Kaiti)、 8 仿宋(ST FangSong)、9 新宋体(ST Song)、10 华文新魏、11 华文行楷、12 华文隶书	"`
+	FontColor      string                    `json:"fc" description:"字体颜色,示例值:#fff000" `
+	Bold           int                       `json:"bl" description:"粗体,0 常规 、 1加粗	"`
+	Italic         int                       `json:"it" description:"斜体,0 常规 、 1 斜体"`
+	Fontsize       string                    `json:"fs" description:"字体大小,14"`
+	CancelLine     int                       `json:"cl" description:"删除线,	0 常规 、 1 删除线"`
+	HorizontalType string                    `json:"ht" description:"水平对齐,	0 居中、1 左、2右"`
+	VerticalType   string                    `json:"vt" description:"垂直对齐,	0 中间、1 上、2下"`
+	TextRotate     string                    `json:"tr" description:"竖排文字,	3"`
+	RotateText     string                    `json:"rt" description:"文字旋转角度,	介于0~180之间的整数,包含0和180"`
+	TextBeak       int                       `json:"tb" description:"文本换行,	0 截断、1溢出、2 自动换行"`
+	Ps             LuckySheetDataCellComment `json:"ps" description:"批注"`
+	Function       string                    `json:"f" description:"公式"`
+}
+
+// LuckySheetDataCellType 单元格值格式:文本、时间等
+type LuckySheetDataCellType struct {
+	Fa string `json:"fa" description:"格式名称,例如:“General”为自动格式"`
+	T  string `json:"t" description:"格式类型,例如:“n”为数字类型"`
+	S  []struct {
+		FontFamily     string      `json:"ff" description:"字体,0 Times New Roman、 1 Arial、2 Tahoma 、3 Verdana、4 微软雅黑、5 宋体(Song)、6 黑体(ST Heiti)、7 楷体(ST Kaiti)、 8 仿宋(ST FangSong)、9 新宋体(ST Song)、10 华文新魏、11 华文行楷、12 华文隶书	"`
+		FontColor      string      `json:"fc" description:"字体颜色,示例值:#fff000" `
+		Fontsize       int         `json:"fs" description:"字体大小,14"`
+		CancelLine     int         `json:"cl" description:"删除线,	0 常规 、 1 删除线"`
+		HorizontalType string      `json:"ht" description:"水平对齐,	0 居中、1 左、2右"`
+		VerticalType   string      `json:"vt" description:"垂直对齐,	0 中间、1 上、2下"`
+		Un             int         `json:"un" description:""`
+		Bold           int         `json:"bl" description:"粗体,0 常规 、 1加粗	"`
+		Italic         int         `json:"it" description:"斜体,0 常规 、 1 斜体"`
+		Value          interface{} `json:"v" description:"原始值"`
+	} `json:"s"`
+}
+
+// LuckySheetDataCellComment 批注
+type LuckySheetDataCellComment struct {
+	Left   int    `json:"left" description:"批注框距离左边工作表边缘位置"`
+	Top    int    `json:"top" description:"批注框距离上边工作表边缘位置"`
+	Width  int    `json:"width" description:"批注框宽度"`
+	Height int    `json:"height" description:"批注框高度"`
+	Value  string `json:"value" description:"批注内容"`
+	IsShow bool   `json:"isshow" description:"是否显示批注"`
+}
+
+// GetLuckySheetData 获取LuckySheetData的结构体
+func GetLuckySheetData(jsonStr string) (item *LuckySheetData, err error) {
+	err = json.Unmarshal([]byte(jsonStr), &item)
+	return
+}
+
+// TableData 表格数据
+type TableData struct {
+	TableDataList     [][]LuckySheetDataValue
+	RowWidthList      []float64
+	RowHeightList     []float64
+	RemoveTopRow      int              `description:"移除表格上方的行数"`
+	RemoveBottomRow   int              `description:"移除表格下方的行数"`
+	RemoveLeftColumn  int              `description:"移除表格左侧的列数"`
+	RemoveRightColumn int              `description:"移除表格右侧的列数"`
+	MergeList         []TableDataMerge `description:"合并数据列"`
+}
+
+// TableDataMerge 表格数据合并单元格配置
+type TableDataMerge struct {
+	StartRowIndex    int `json:"start_row_index" description:"开始的行下标"`
+	StartColumnIndex int `json:"start_column" description:"开始的列下标"`
+	MergeRowNum      int `json:"merge_row_num" description:"合并的行数"`
+	MergeColumnNum   int `json:"merge_column_num" description:"合并的列数"`
+}
+
+// GetTableDataByLuckySheetDataStr 通过LuckySheet的string数据获取表格数据
+func (item *LuckySheetData) GetTableDataByLuckySheetDataStr() (selfTableData TableData, err error) {
+	luckySheetCellDataList := item.CellData
+	// 表格数据
+	tableDataMap := make(map[int64]map[int64]LuckySheetDataValue)
+	// 最大行,最大列
+	var maxRow, maxCol int64
+	for _, v := range luckySheetCellDataList {
+		//fmt.Println("row:", v.Row, "=====col:", v.Col)
+		if v.Row > maxRow { //最大行
+			maxRow = v.Row
+		}
+		if v.Col > maxCol { //最大列
+			maxCol = v.Col
+		}
+		var tmpRow map[int64]LuckySheetDataValue
+
+		tmpRow, ok := tableDataMap[v.Row]
+		if ok {
+			tmpRow[v.Col] = v.Value
+		} else {
+			tmpRow = make(map[int64]LuckySheetDataValue)
+			tmpRow[v.Col] = v.Value
+		}
+		tableDataMap[v.Row] = tmpRow
+	}
+
+	tableDataList := make([][]LuckySheetDataValue, 0)
+	var i int64
+
+	// 单元格宽度
+	configColumnConf := item.Config.Columnlen
+	rowWidthMap := make(map[int]float64)
+	rowWidthList := make([]float64, 0) //
+
+	// 单元格高度
+	configRowConf := item.Config.Rowlen
+	rowHeightList := make([]float64, 0) //
+
+	for i = 0; i <= maxRow; i++ {
+		//列
+		tmpTableColDataList := make([]LuckySheetDataValue, 0)
+		// 每个单元格的高度
+		tmpHeight, ok := configRowConf[fmt.Sprint(i)]
+		if !ok {
+			tmpHeight = 0
+		}
+		rowHeightList = append(rowHeightList, tmpHeight)
+
+		tmpRowData, ok := tableDataMap[i]
+		if !ok {
+			tableDataList = append(tableDataList, tmpTableColDataList)
+			continue
+		}
+
+		var j int64
+		for j = 0; j <= maxCol; j++ {
+			tmpTableColData, ok := tmpRowData[j]
+			if !ok {
+				tmpTableColData = LuckySheetDataValue{}
+			}
+
+			//单元格显示的数据处理
+			tmpTableColData.Monitor = handleCellVal(tmpTableColData)
+
+			tmpTableColDataList = append(tmpTableColDataList, tmpTableColData)
+
+			// 每个单元格的宽度
+			tmpWidth, ok := configColumnConf[fmt.Sprint(j)]
+			if !ok {
+				tmpWidth = 0
+			}
+			rowIndex := len(tmpTableColDataList) - 1
+			if _, ok2 := rowWidthMap[rowIndex]; !ok2 {
+				rowWidthList = append(rowWidthList, tmpWidth)
+			}
+			rowWidthMap[rowIndex] = tmpWidth
+		}
+
+		tableDataList = append(tableDataList, tmpTableColDataList)
+	}
+
+	//总共多少行
+	lenRow := len(tableDataList)
+
+	//移除上下空行
+	deleteRowIndexList := make([]int, 0)
+	if lenRow > 0 {
+		var flag = false
+		// 移除上方空列
+		for rowIndex := 0; rowIndex < lenRow; rowIndex++ {
+			isDelete := true
+			for _, v := range tableDataList[rowIndex] {
+				if v.Monitor != `` {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				selfTableData.RemoveTopRow++
+				deleteRowIndexList = append(deleteRowIndexList, rowIndex)
+			}
+		}
+
+		// 移除下方空行
+		flag = false
+		//尾部
+		deleteBottomRowIndexList := make([]int, 0)
+		for rowIndex := lenRow - 1; rowIndex >= 0; rowIndex-- {
+			isDelete := true
+			for _, v := range tableDataList[rowIndex] {
+				if v.Monitor != `` {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				deleteBottomRowIndexList = append(deleteBottomRowIndexList, rowIndex)
+				selfTableData.RemoveBottomRow++
+			}
+		}
+
+		if len(deleteBottomRowIndexList) > 0 {
+			deleteRowIndexList = append(deleteRowIndexList, utils.RevSlice(deleteBottomRowIndexList)...)
+		}
+
+		lenDeleteRow := len(deleteRowIndexList)
+		if lenDeleteRow > 0 {
+			for rowIndex := lenDeleteRow - 1; rowIndex >= 0; rowIndex-- {
+				//表格数据
+				tableDataList = append(tableDataList[:deleteRowIndexList[rowIndex]], tableDataList[deleteRowIndexList[rowIndex]+1:]...) // 删除开头N个元素
+
+				//表格高度
+				rowHeightList = append(rowHeightList[:deleteRowIndexList[rowIndex]], rowHeightList[deleteRowIndexList[rowIndex]+1:]...) // 删除开头N个元素
+			}
+		}
+	}
+
+	//移除前后空列
+	deleteColumnIndexList := make([]int, 0)
+	if len(tableDataList) > 0 {
+		var flag = false
+		lenColumn := len(tableDataList[0])
+		// 移除前方空列
+		for columnIndex := 0; columnIndex < lenColumn; columnIndex++ {
+			isDelete := true
+			for _, v := range tableDataList {
+				if v[columnIndex].Monitor != `` {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				selfTableData.RemoveLeftColumn++
+				deleteColumnIndexList = append(deleteColumnIndexList, columnIndex)
+			}
+		}
+
+		// 移除后方空列
+		flag = false
+		//尾部
+		deleteTailColumnIndexList := make([]int, 0)
+		for columnIndex := lenColumn - 1; columnIndex >= 0; columnIndex-- {
+			isDelete := true
+			for _, v := range tableDataList {
+				if v[columnIndex].Monitor != `` {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				deleteTailColumnIndexList = append(deleteTailColumnIndexList, columnIndex)
+				selfTableData.RemoveRightColumn++
+			}
+		}
+
+		if len(deleteTailColumnIndexList) > 0 {
+			deleteColumnIndexList = append(deleteColumnIndexList, utils.RevSlice(deleteTailColumnIndexList)...)
+		}
+
+		lenDeleteColumn := len(deleteColumnIndexList)
+		if lenDeleteColumn > 0 {
+			for columnIndex := lenDeleteColumn - 1; columnIndex >= 0; columnIndex-- {
+				//表格数据
+				for k, v := range tableDataList {
+					tableDataList[k] = append(v[:deleteColumnIndexList[columnIndex]], v[deleteColumnIndexList[columnIndex]+1:]...) // 删除开头N个元素
+				}
+
+				//表格宽度
+				rowWidthList = append(rowWidthList[:deleteColumnIndexList[columnIndex]], rowWidthList[deleteColumnIndexList[columnIndex]+1:]...) // 删除开头N个元素
+			}
+		}
+	}
+
+	//处理合并单元格
+	tableDataMergeList := make([]TableDataMerge, 0)
+	for _, v := range item.Config.Merge {
+		indexRow := v.Row - selfTableData.RemoveTopRow
+		indexColumn := v.Column - selfTableData.RemoveLeftColumn
+
+		tableDataMerge := TableDataMerge{
+			StartRowIndex:    indexRow,
+			StartColumnIndex: indexColumn,
+			MergeRowNum:      v.Rs - 1,
+			MergeColumnNum:   v.Cs - 1,
+		}
+		tableDataMergeList = append(tableDataMergeList, tableDataMerge)
+	}
+
+	// 表格数据
+	selfTableData.TableDataList = tableDataList
+	selfTableData.RowWidthList = rowWidthList
+	selfTableData.RowHeightList = rowHeightList
+	selfTableData.MergeList = tableDataMergeList
+
+	return
+}
+
+// handleCellVal 处理单元格数据
+func handleCellVal(tmpTableColData LuckySheetDataValue) (valueStr string) {
+	valueStr = tmpTableColData.Monitor
+	if valueStr == `` {
+		//valueStr = fmt.Sprint(cellInfo.Value)
+		if valueStr == `` && tmpTableColData.CellType.S != nil {
+			//不是设置在单元格上面,而是设置在文本上
+			for _, cellS := range tmpTableColData.CellType.S {
+				valueStr += fmt.Sprint(cellS.Value)
+			}
+		}
+	}
+	return
+}

+ 18 - 1
utils/common.go

@@ -622,4 +622,21 @@ func StrTimeToTime(strTime string) time.Time {
 	loc, _ := time.LoadLocation("Local") //重要:获取时区
 	resultTime, _ := time.ParseInLocation(timeLayout, strTime, loc)
 	return resultTime
-}
+}
+
+// GetOrmInReplace 获取orm的in查询替换?的方法
+func GetOrmInReplace(num int) string {
+	template := make([]string, num)
+	for i := 0; i < num; i++ {
+		template[i] = "?"
+	}
+	return strings.Join(template, ",")
+}
+
+// RevSlice 反转切片
+func RevSlice(slice []int) []int {
+	for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
+		slice[i], slice[j] = slice[j], slice[i]
+	}
+	return slice
+}

+ 1 - 0
utils/constants.go

@@ -89,6 +89,7 @@ const (
 const (
 	HZ_CHART_LIB_DETAIL = "HZ_CHART_LIB_DETAIL_"	//图表
 	HZ_TABLE_LIB_DETAIL = "HZ_TABLE_LIB_DETAIL_"	//表格
+	HZ_CHART_LIB_EXCEL_TABLE_DETAIL = "HZ_CHART_LIB_EXCEL_TABLE_DETAIL"
 )
 
 var (