ziwen 1 年間 前
コミット
4d9ac74695

+ 86 - 0
controllers/excel_info.go

@@ -0,0 +1,86 @@
+package controllers
+
+import (
+	"hongze/hongze_ETA_mobile_api/models"
+	"hongze/hongze_ETA_mobile_api/models/data_manage"
+	"hongze/hongze_ETA_mobile_api/models/data_manage/response"
+	"hongze/hongze_ETA_mobile_api/services/excel"
+	"hongze/hongze_ETA_mobile_api/utils"
+)
+
+// ExcelInfoController ETA表格管理
+type ExcelInfoController struct {
+	BaseAuthController
+}
+
+
+
+// GetExcelTableData
+// @Title 获取excel表格的table数据
+// @Description 获取excel表格的table数据接口
+// @Param   UniqueCode   query   string  true       "表格code"
+// @Success 200 {object} response.ExcelTableDetailResp
+// @router /excel_info/table_data [get]
+func (this *ExcelInfoController) GetExcelTableData() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	uniqueCode := this.GetString("UniqueCode")
+
+	var err error
+	if uniqueCode == `` {
+		br.Msg = "请选择表格"
+		br.ErrMsg = "UniqueCode未传"
+		br.IsSendEmail = false
+		return
+	}
+	//获取eta表格信息
+	excelInfo, err := data_manage.GetExcelInfoByUniqueCode(uniqueCode)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取ETA表格信息失败,Err:" + err.Error()
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "ETA表格被删除,请刷新页面"
+			br.ErrMsg = "ETA表格被删除,请刷新页面,Err:" + err.Error()
+			br.IsSendEmail = false
+		}
+		return
+	}
+
+	luckySheetData, err := excel.GetLuckySheetData(excelInfo.Content)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取excel数据失败,Err:" + err.Error()
+		return
+	}
+	tableData, err := luckySheetData.GetTableDataByLuckySheetDataStr()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "转换成table失败,Err:" + err.Error()
+		return
+	}
+
+	tableData = excel.HandleTableCell(tableData)
+
+	resp := response.ExcelTableDetailResp{
+		UniqueCode: excelInfo.UniqueCode,
+		ExcelImage: excelInfo.ExcelImage,
+		ExcelName:  excelInfo.ExcelName,
+		TableInfo:  tableData,
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+

ファイルの差分が大きいため隠しています
+ 587 - 0
controllers/resource.go


+ 25 - 5
go.mod

@@ -9,38 +9,58 @@ require (
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-sql-driver/mysql v1.7.0
 	github.com/go-xorm/xorm v0.7.9
+	github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53
 	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
 	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/shopspring/decimal v1.3.1
+	github.com/tealeg/xlsx v1.0.5
+	github.com/xuri/excelize/v2 v2.7.1
 	github.com/yidane/formula v0.0.0-20210902154546-0782e1736717
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )
 
 require (
 	github.com/andybalholm/cascadia v1.3.1 // indirect
-	github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/garyburd/redigo v1.6.3 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
+	github.com/jmespath/go-jmespath v0.4.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/kr/text v0.2.0 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.14.0 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
 	github.com/prometheus/common v0.37.0 // indirect
 	github.com/prometheus/procfs v0.8.0 // indirect
+	github.com/richardlehane/mscfb v1.0.4 // indirect
+	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
-	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
-	golang.org/x/net v0.7.0 // indirect
-	golang.org/x/sys v0.5.0 // indirect
-	golang.org/x/text v0.7.0 // indirect
+	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
+	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
+	golang.org/x/crypto v0.8.0 // indirect
+	golang.org/x/net v0.9.0 // indirect
+	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
+	golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
 	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+	gopkg.in/ini.v1 v1.66.2 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	xorm.io/builder v0.3.6 // indirect
 	xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb // indirect
 )
+
+require (
+	github.com/aliyun/alibaba-cloud-sdk-go v1.62.274
+	github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible
+	github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02 // indirect
+)

+ 53 - 6
go.sum

@@ -56,13 +56,15 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
+github.com/aliyun/alibaba-cloud-sdk-go v1.62.274 h1:UKoNWCTvUohk0besAPgnSzilZMWrb4Mul37DE8/KCdA=
+github.com/aliyun/alibaba-cloud-sdk-go v1.62.274/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs=
+github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible h1:KpbJFXwhVeuxNtBJ74MCGbIoaBok2uZvkD7QXp2+Wis=
+github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
 github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
 github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02 h1:o2oaBQGTzO+xNh12e7xWkphNe7H2DTiWv1ml9a2P9PQ=
 github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20211218165449-dd623ecc2f02/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
-github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
 github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -227,6 +229,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -365,16 +368,20 @@ github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod
 github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
 github.com/jackc/pgx v3.6.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
 github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
@@ -386,6 +393,8 @@ github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0t
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
+github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53 h1:+8X3HMX8A2QhvNg3dImiQTCiVUt6BQXz1mW+/DrWI+k=
+github.com/kgiannakakis/mp3duration v0.0.0-20191013070830-d834f8d5ed53/go.mod h1:E61jD6q4yJ6Cu9uDGRAfiENM1G5TVZhOog0Y3+GgTpQ=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -452,10 +461,14 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
@@ -496,6 +509,8 @@ github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKw
 github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
+github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
+github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
 github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
 github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
 github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
@@ -571,6 +586,11 @@ github.com/rabbitmq/amqp091-go v1.2.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0V
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rdlucklib/rdluck_tools v1.0.3 h1:iOtK2QPlPQ6CL6c1htCk5VnFCHzyG6DCfJtunrMswK0=
 github.com/rdlucklib/rdluck_tools v1.0.3/go.mod h1:9Onw9o4w19C8KE5lxb8GyxgRBbZweRVkQSc79v38EaA=
+github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
+github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
+github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
+github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
+github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -630,14 +650,26 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
 github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
+github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
+github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
+github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
+github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
+github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
+github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI=
+github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/yidane/formula v0.0.0-20210902154546-0782e1736717 h1:9CTJJpdISGxMAELfVlprj5kZEsJEaNAWiobv8ZAd72U=
 github.com/yidane/formula v0.0.0-20210902154546-0782e1736717/go.mod h1:9/dQiKiN04yPMdgsuFmKGuI2Hdp6OmFV9gSWS1col6g=
 github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod h1:Nv7wKD2/bCdKUFNKcJRa99a+1+aSLlCRJFriFYdjz/I=
@@ -682,6 +714,7 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@@ -707,8 +740,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -725,6 +759,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
+golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -746,6 +782,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -796,8 +833,10 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -818,6 +857,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -892,11 +932,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -905,12 +947,14 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
 golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -970,6 +1014,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1089,6 +1134,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
+gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=

+ 248 - 0
models/data_manage/excel_info.go

@@ -0,0 +1,248 @@
+package data_manage
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_ETA_mobile_api/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 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
+}
+
+// GetNextExcelInfoByCondition 根据条件获取下一个表格
+func GetNextExcelInfoByCondition(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
+	}
+	sql += " ORDER BY sort asc , create_time desc LIMIT 1 "
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+// GetNextExcelInfo 根据分类id获取下一个excel表格
+func GetNextExcelInfo(classifyId, classifySort 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.sort>? OR (a.sort=? and a.excel_classify_id>?) ) AND a.is_delete=0 AND b.is_delete=0
+			ORDER BY a.sort ASC,b.sort asc,b.create_time desc
+			LIMIT 1 `
+	err = o.Raw(sql, classifySort, classifySort, 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 *ExcelInfo, 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
+}
+
+// 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
+}
+
+// GetMyExcelListByAdminId 根据操作人id获取表格列表
+func GetMyExcelListByAdminId(adminId int) (item []*MyChartView, err error) {
+	o := orm.NewOrmUsingDB("data")
+	//sql := ` SELECT * FROM my_chart WHERE 1=1 AND admin_id=? `
+
+	sql := ` SELECT a.*,GROUP_CONCAT(c.my_chart_classify_id SEPARATOR ',') AS my_chart_classify_id FROM my_chart AS a
+			LEFT JOIN  my_chart_classify_mapping AS b ON a.my_chart_id=b.my_chart_id AND a.admin_id=b.admin_id
+			LEFT JOIN my_chart_classify AS c ON b.my_chart_classify_id=c.my_chart_classify_id AND b.admin_id=c.admin_id
+			WHERE 1=1 AND a.admin_id=? AND a.source=2
+			GROUP BY a.chart_info_id `
+	_, err = o.Raw(sql, adminId).QueryRows(&item)
+	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
+}

+ 27 - 0
models/data_manage/response/excel_info.go

@@ -0,0 +1,27 @@
+package response
+
+import (
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hongze_ETA_mobile_api/models/data_manage"
+	"hongze/hongze_ETA_mobile_api/services/excel"
+)
+
+// AddExcelInfoResp 添加excel表格的返回
+type AddExcelInfoResp struct {
+	ExcelInfoId int    `description:"表格id"`
+	UniqueCode  string `description:"表格唯一编码"`
+}
+
+// ExcelListResp 表格列表返回数据
+type ExcelListResp struct {
+	Paging *paging.PagingItem
+	List   []*data_manage.MyExcelInfoList
+}
+
+// ExcelTableDetailResp  excel表格详情
+type ExcelTableDetailResp struct {
+	UniqueCode string `description:"表格唯一code"`
+	ExcelImage string `description:"表格截图"`
+	ExcelName  string `description:"表格名称"`
+	TableInfo  excel.TableData
+}

+ 57 - 0
models/resource.go

@@ -0,0 +1,57 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type Resource struct {
+	Id           int       `orm:"column(id);" description:"资源id"`
+	ResourceUrl  string    `description:"资源地址"`
+	CreateTime   time.Time `description:"创建时间"`
+	ResourceType int       `description:"资源类型,1:图片,2:音频,3:视频 ,4:ppt"`
+}
+
+type ResourceResp struct {
+	Id           int64  `orm:"column(id);" description:"用户id"`
+	ResourceUrl  string `description:"资源地址"`
+	PlaySeconds  uint32 `description:"播放时长,单位秒"`
+	Source       string
+	CacheKey     string
+	ResourceName string `description:"资源名称"`
+}
+
+func AddResource(item *Resource) (newId int64, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	newId, err = o.Insert(item)
+	return
+}
+
+func GetResourceById(id string) (item *Resource, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := "SELECT * FROM resource WHERE id=? "
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+type ResourceBase64Resp struct {
+	Image string `description:"图片,base64字符串"`
+}
+
+type PptResourceResp struct {
+	Id          int64    `orm:"column(id);" description:"用户id"`
+	ResourceUrl []string `description:"资源地址"`
+	PlaySeconds uint32   `description:"播放时长,单位秒"`
+}
+
+type ImageSvgToPngResp struct {
+	Data struct {
+		ResourceURL string `json:"ResourceUrl"`
+	} `json:"Data"`
+	ErrCode     string `json:"ErrCode"`
+	ErrMsg      string `json:"ErrMsg"`
+	IsSendEmail bool   `json:"IsSendEmail"`
+	Msg         string `json:"Msg"`
+	Ret         int64  `json:"Ret"`
+	Success     bool   `json:"Success"`
+}

+ 63 - 0
routers/commentsRouter.go

@@ -16,6 +16,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ExcelInfoController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ExcelInfoController"],
+        beego.ControllerComments{
+            Method: "GetExcelTableData",
+            Router: `/excel_info/table_data`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:PptCommonController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:PptCommonController"],
         beego.ControllerComments{
             Method: "Download",
@@ -601,6 +610,60 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"],
+        beego.ControllerComments{
+            Method: "Upload",
+            Router: `/image/upload`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"],
+        beego.ControllerComments{
+            Method: "UploadV2",
+            Router: `/image/uploadV2`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"],
+        beego.ControllerComments{
+            Method: "OssSTSToken",
+            Router: `/oss/get_sts_token`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"],
+        beego.ControllerComments{
+            Method: "UploadImageBase64",
+            Router: `/upload_image_base64`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"],
+        beego.ControllerComments{
+            Method: "VideoUpload",
+            Router: `/video/upload`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:ResourceController"],
+        beego.ControllerComments{
+            Method: "VoiceUpload",
+            Router: `/voice/upload`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:SysUserAuthController"] = append(beego.GlobalControllerRouter["hongze/hongze_ETA_mobile_api/controllers:SysUserAuthController"],
         beego.ControllerComments{
             Method: "CheckPwd",

+ 11 - 0
routers/router.go

@@ -9,6 +9,7 @@ package routers
 
 import (
 	"hongze/hongze_ETA_mobile_api/controllers"
+	"hongze/hongze_ETA_mobile_api/controllers/data_manage"
 
 	"github.com/beego/beego/v2/server/web"
 	"github.com/beego/beego/v2/server/web/filter/cors"
@@ -58,6 +59,16 @@ func init() {
 				&controllers.PptEnglishCommonController{},
 			),
 		),
+		web.NSNamespace("/datamanage",
+			web.NSInclude(
+				&data_manage.ChartInfoController{},
+			),
+		),
+		web.NSNamespace("/resource",
+			web.NSInclude(
+				&controllers.ResourceController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 1396 - 0
services/excel/lucky_sheet.go

@@ -0,0 +1,1396 @@
+package excel
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/tealeg/xlsx"
+	"github.com/xuri/excelize/v2"
+	"hongze/hongze_ETA_mobile_api/utils"
+	"os"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+)
+
+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          float64 `json:"rh_height" description:""`
+	ScrollLeft        float64 `json:"scrollLeft" description:""`
+	ScrollTop         float64 `json:"scrollTop" description:""`
+	Status            int64   `json:"status" description:""`
+	Visibledatacolumn []int64 `json:"visibledatacolumn" description:""`
+	Visibledatarow    []int64 `json:"visibledatarow" description:""`
+	ZoomRatio         float64 `json:"zoomRatio" description:"sheet缩放比例"`
+}
+
+// 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          float64 `json:"rh_height" description:"工作表区域的高度"`
+	ScrollLeft        float64 `json:"scrollLeft" description:"左右滚动条位置"`
+	ScrollTop         float64 `json:"scrollTop" description:"上下滚动条位置"`
+	Status            int64   `json:"status" description:"激活状态"`
+	VisibleDataColumn []int64 `json:"visibledatacolumn" description:"所有列的位置信息,递增的列位置数据,初始化无需设置"`
+	VisibleDataRow    []int64 `json:"visibledatarow" description:"所有行的位置信息,递增的行位置数据,初始化无需设置"`
+	ZoomRatio         float64 `json:"zoomRatio" description:"sheet缩放比例"`
+}
+
+// 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 int         `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"`
+	Sl    interface{} `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                    `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 华文隶书	"`
+	FF             interface{}            `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       int                    `description:"字体大小,14"`
+	CancelLine     int                    ` description:"删除线,	0 常规 、 1 删除线"`
+	HorizontalType int                    `description:"水平对齐,	0 居中、1 左、2右"`
+	VerticalType   int                    ` description:"垂直对齐,	0 中间、1 上、2下"`
+	Fs             interface{}            `json:"fs" description:"字体大小,14"`
+	Cl             interface{}            `json:"cl" description:"删除线,	0 常规 、 1 删除线"`
+	Ht             interface{}            `json:"ht" description:"水平对齐,	0 居中、1 左、2右"`
+	Vt             interface{}            `json:"vt" description:"垂直对齐,	0 中间、1 上、2下"`
+	//TextRotate     string                    `json:"tr" description:"竖排文字,	3"`
+	//RotateText string                    `json:"rt" description:"文字旋转角度,	介于0~180之间的整数,包含0和180"`
+	TextBeak  int                       `description:"文本换行,	0 截断、1溢出、2 自动换行"`
+	Tb        interface{}               `json:"tb" description:"文本换行,	0 截断、1溢出、2 自动换行"`
+	Ps        LuckySheetDataCellComment `json:"ps" description:"批注"`
+	Function  string                    `json:"f" description:"公式"`
+	MergeCell LuckySheetDataConfigMerge `json:"mc" description:"合并单元格信息"`
+}
+
+// LuckySheetDataCellType 单元格值格式:文本、时间等
+type LuckySheetDataCellType struct {
+	Fa string `json:"fa" description:"格式名称,例如:“General”为自动格式"`
+	T  string `json:"t" description:"格式类型,例如:“n”为数字类型"`
+	S  []struct {
+		FontFamily     int         `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 华文隶书	"`
+		FF             interface{} `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         `description:"字体大小,14"`
+		CancelLine     int         ` description:"删除线,	0 常规 、 1 删除线"`
+		HorizontalType int         `description:"水平对齐,	0 居中、1 左、2右"`
+		VerticalType   int         `description:"垂直对齐,	0 中间、1 上、2下"`
+		Fs             interface{} `json:"fs" description:"字体大小,14"`
+		Cl             interface{} `json:"cl" description:"删除线,	0 常规 、 1 删除线"`
+		Ht             interface{} `json:"ht" description:"水平对齐,	0 居中、1 左、2右"`
+		Vt             interface{} `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)
+	for k, v := range item.CellData {
+		value := v.Value
+		value.Fontsize = getIntValueByInterface(value.Fs)
+		value.CancelLine = getIntValueByInterface(value.Cl)
+		value.HorizontalType = getIntValueByInterface(value.Ht)
+		value.VerticalType = getIntValueByInterface(value.Vt)
+		value.FontFamily = getIntValueByInterface(value.FF)
+		value.TextBeak = getIntValueByInterface(value.Tb)
+
+		if len(value.CellType.S) > 0 {
+			for kk, vv := range value.CellType.S {
+				vv.Fontsize = getIntValueByInterface(vv.Fs)
+				vv.CancelLine = getIntValueByInterface(vv.Cl)
+				vv.HorizontalType = getIntValueByInterface(vv.Ht)
+				vv.VerticalType = getIntValueByInterface(vv.Vt)
+				vv.FontFamily = getIntValueByInterface(vv.FF)
+				value.CellType.S[kk] = vv
+			}
+		}
+
+		item.CellData[k].Value = value
+	}
+	if len(item.Config.BorderInfo) > 0 {
+		for k, v := range item.Config.BorderInfo {
+			v.Value.T.Style = getIntValueByInterface(v.Value.T.Style)
+			v.Value.B.Style = getIntValueByInterface(v.Value.B.Style)
+			v.Value.L.Style = getIntValueByInterface(v.Value.L.Style)
+			v.Value.R.Style = getIntValueByInterface(v.Value.R.Style)
+			item.Config.BorderInfo[k] = v
+		}
+	}
+	return
+}
+
+func getIntValueByInterface(valInterface interface{}) (val int) {
+	if valInterface == nil {
+		return
+	}
+	switch reflect.TypeOf(valInterface).Kind() {
+	case reflect.String:
+		tmpValue := reflect.ValueOf(valInterface).String()
+		tmpValInt, err := strconv.Atoi(tmpValue)
+		if err != nil {
+			val = 0
+		} else {
+			val = tmpValInt
+		}
+	case reflect.Int, reflect.Int32, reflect.Int64:
+		tmpValue := reflect.ValueOf(valInterface).Int()
+		val = int(tmpValue)
+	}
+	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 {
+			tmpRowData = make(map[int64]LuckySheetDataValue)
+		}
+
+		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)
+	}
+
+	// 数据处理,移除上下左右空行空列
+	tableDataList, tableRemoveNum, rowHeightList, rowWidthList, tableDataMergeList := handleTableDataList(tableDataList, item.Config.Merge, rowHeightList, rowWidthList)
+
+	// 表格数据
+	{
+		// 移除空白单元格信息
+		selfTableData.RemoveTopRow = tableRemoveNum.RemoveTopRow
+		selfTableData.RemoveBottomRow = tableRemoveNum.RemoveBottomRow
+		selfTableData.RemoveLeftColumn = tableRemoveNum.RemoveLeftColumn
+		selfTableData.RemoveRightColumn = tableRemoveNum.RemoveRightColumn
+	}
+
+	selfTableData.TableDataList = tableDataList
+	selfTableData.RowWidthList = rowWidthList
+	selfTableData.RowHeightList = rowHeightList
+	selfTableData.MergeList = tableDataMergeList
+
+	return
+}
+
+// TableRemoveNum 上下左右移除的空行空列数量
+type TableRemoveNum struct {
+	RemoveTopRow      int `description:"移除表格上方的行数"`
+	RemoveBottomRow   int `description:"移除表格下方的行数"`
+	RemoveLeftColumn  int `description:"移除表格左侧的列数"`
+	RemoveRightColumn int `description:"移除表格右侧的列数"`
+}
+
+// handleTableDataList 表格数据处理(移除上下左右的空行空列)
+func handleTableDataList(tableDataList [][]LuckySheetDataValue, luckySheetDataConfigMergeList map[string]LuckySheetDataConfigMerge, rowHeightList, rowWidthList []float64) ([][]LuckySheetDataValue, TableRemoveNum, []float64, []float64, []TableDataMerge) {
+
+	var removeTopRow, removeBottomRow, removeLeftColumn, removeRightColumn int //上下左右需要移除的空行空列
+	tableDataMergeList := make([]TableDataMerge, 0)                            //待合并的单元格信息
+
+	//总共多少行
+	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 != `` || (v.MergeCell.Row != rowIndex && v.MergeCell.Row != 0) {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				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)
+				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 len(v) <= 0 {
+					continue
+				}
+				if v[columnIndex].Monitor != `` || (v[columnIndex].MergeCell.Column != columnIndex && v[columnIndex].MergeCell.Column != 0) {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				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 len(v) <= 0 {
+					continue
+				}
+				if v[columnIndex].Monitor != `` || (v[columnIndex].MergeCell.Column != columnIndex && v[columnIndex].MergeCell.Column != 0) {
+					isDelete = false
+					flag = true
+					break
+				}
+			}
+			if flag {
+				break
+			}
+			if isDelete {
+				deleteTailColumnIndexList = append(deleteTailColumnIndexList, columnIndex)
+				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个元素
+			}
+		}
+	}
+
+	//处理合并单元格
+	for _, v := range luckySheetDataConfigMergeList {
+		indexRow := v.Row - removeTopRow
+		indexColumn := v.Column - removeLeftColumn
+
+		tableDataMerge := TableDataMerge{
+			StartRowIndex:    indexRow,
+			StartColumnIndex: indexColumn,
+			MergeRowNum:      v.Rs - 1,
+			MergeColumnNum:   v.Cs - 1,
+		}
+		tableDataMergeList = append(tableDataMergeList, tableDataMerge)
+	}
+
+	return tableDataList, TableRemoveNum{
+		RemoveTopRow:      removeTopRow,
+		RemoveBottomRow:   removeBottomRow,
+		RemoveLeftColumn:  removeLeftColumn,
+		RemoveRightColumn: removeRightColumn,
+	}, rowHeightList, rowWidthList, tableDataMergeList
+}
+
+func (item *LuckySheetData) ToExcel() (downloadFilePath string, err error) {
+	tableData, err := item.GetTableDataByLuckySheetDataStr()
+
+	//dir, err := os.Executable()
+	//exPath := filepath.Dir(dir)
+	//downloadFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	downloadFilePath, err = getDownloadPath()
+	if err != nil {
+		return
+	}
+	xlsxFile := xlsx.NewFile()
+	if err != nil {
+		return
+	}
+	style := xlsx.NewStyle()
+	alignment := xlsx.Alignment{
+		Horizontal: "center",
+		Vertical:   "center",
+		WrapText:   true,
+	}
+
+	style.Alignment = alignment
+	style.ApplyAlignment = true
+
+	sheet, err := xlsxFile.AddSheet("sheet1")
+	if err != nil {
+		return
+	}
+	for k, v := range tableData.RowWidthList {
+		err = sheet.SetColWidth(k, k, v/10)
+		if err != nil {
+			return
+		}
+	}
+
+	for index, v := range tableData.TableDataList {
+		tmpRow := sheet.AddRow()
+
+		//设置单元格高度
+		if tableData.RowHeightList[index] > 0 {
+			tmpRow.SetHeight(tableData.RowHeightList[index] / 2)
+		}
+
+		for _, cellInfo := range v {
+			tmpStyle := new(xlsx.Style)
+			//xlsx.Style{
+			//	Fill:            xlsx.Fill{},
+			//	ApplyBorder:     false,
+			//	ApplyFill:       false,
+			//	ApplyFont:       false,
+			//	NamedStyleIndex: nil,
+			//}
+
+			//fill := *NewFill("solid", "FF000000", "00FF0000")
+			defaultFill := xlsx.DefaultFill()
+			if cellInfo.Background != `` {
+				defaultFill.PatternType = "solid"
+				backgroundColor := cellInfo.Background
+				// 这么做是为了避免传入的是RGB的格式(rgb(255, 255, 255))
+				backgroundColor = getColor(backgroundColor)
+
+				defaultFill.BgColor = strings.TrimPrefix(backgroundColor, "#")
+				defaultFill.FgColor = strings.TrimPrefix(backgroundColor, "#")
+
+			}
+			tmpStyle.Fill = *defaultFill
+
+			// 获取表格字体配置
+			tmpStyle.Font = getExcelFontConf(cellInfo)
+			//获取表格单元格排列配置
+			tmpStyle.ApplyAlignment = true
+			tmpStyle.Alignment = getExcelAlignmentConf(cellInfo)
+			//边框配置
+			tmpStyle.Border = xlsx.Border{
+				Left:        "thin",
+				LeftColor:   "000000",
+				Right:       "thin",
+				RightColor:  "000000",
+				Top:         "thin",
+				TopColor:    "000000",
+				Bottom:      "thin",
+				BottomColor: "000000",
+			}
+			//tmpStyle.ApplyAlignment = true
+			//tmpStyle.Alignment.WrapText = true
+
+			tmpRow := tmpRow.AddCell()
+
+			tmpRow.SetStyle(tmpStyle)
+			valueStr := cellInfo.Monitor
+			if valueStr == `` {
+				//valueStr = fmt.Sprint(cellInfo.Value)
+				if valueStr == `` && cellInfo.CellType.S != nil {
+					//不是设置在单元格上面,而是设置在文本上
+					for _, cellS := range cellInfo.CellType.S {
+						valueStr += fmt.Sprint(cellS.Value)
+					}
+				}
+			}
+			tmpRow.SetString(valueStr)
+			//if cellInfo.Function != `` {
+			//	tmpRow.SetFormula(cellInfo.Function)
+			//}
+		}
+	}
+
+	for _, v := range tableData.MergeList {
+		for k, cell := range sheet.Row(v.StartRowIndex).Cells {
+			if v.StartColumnIndex == k {
+				cell.Merge(v.MergeColumnNum, v.MergeRowNum)
+			}
+		}
+	}
+	//return
+	err = xlsxFile.Save(downloadFilePath)
+	if err != nil {
+		return
+	}
+	//randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
+	//downloadFileName := "即将到期客户数据_" + randStr + ".xlsx"
+	//this.Ctx.Output.Download(downLoadnFilePath, downloadFileName)
+	return
+}
+
+// getDownloadPath 获取下载地址
+func getDownloadPath() (fpath string, err error) {
+	dateDir := time.Now().Format("20060102")
+	uploadDir := "static/xls/" + dateDir
+	err = os.MkdirAll(uploadDir, 0766)
+	if err != nil {
+		return
+	}
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName := randStr + ".xlsx"
+	fpath = uploadDir + "/" + fileName
+	return
+}
+
+// getExcelFontConf 获取表格字体配置
+func getExcelFontConf(cellInfo LuckySheetDataValue) xlsx.Font {
+	fontSize := 10
+	familyName := ``
+	var isBold, isItalic, isUnderline bool
+	// 字体
+	{
+		if cellInfo.Bold == 1 {
+			isBold = true
+		}
+		if cellInfo.Italic == 1 {
+			isItalic = true
+		}
+		if cellInfo.CancelLine == 1 {
+			isUnderline = true
+		}
+
+		//if cellInfo.Fontsize != `` {
+		//	convSize, _ := strconv.Atoi(cellInfo.Fontsize)
+		//	if convSize > 0 {
+		//		fontSize = convSize
+		//	}
+		//}
+		if cellInfo.Fontsize > 0 {
+			fontSize = cellInfo.Fontsize
+		}
+		tmpFamilyName, familyNameOk := LuckyFontFamilyMap[cellInfo.FontFamily]
+		if !familyNameOk {
+			tmpFamilyName = "宋体"
+		}
+		familyName = tmpFamilyName
+	}
+
+	return xlsx.Font{
+		Size: fontSize,
+		Name: familyName,
+		//Family: v2.FontFamily,
+		//Charset:   0,
+		Color:     strings.TrimPrefix(cellInfo.FontColor, "#"),
+		Bold:      isBold,
+		Italic:    isItalic,
+		Underline: isUnderline,
+	}
+}
+
+// getExcelAlignmentConf 获取表格单元格排列配置
+func getExcelAlignmentConf(cellInfo LuckySheetDataValue) xlsx.Alignment {
+	//自动换行
+	isWrapText := false
+	if cellInfo.TextBeak == 2 {
+		isWrapText = true
+	}
+	rotateText := 0
+	//if cellInfo.RotateText != `` {
+	//	convSize, _ := strconv.Atoi(cellInfo.RotateText)
+	//	if convSize > 0 {
+	//		rotateText = convSize
+	//	}
+	//}
+	return xlsx.Alignment{
+		Horizontal: LuckyHorizontalMap[cellInfo.HorizontalType],
+		//Indent:       0,
+		//ShrinkToFit:  false,
+		TextRotation: rotateText,
+		Vertical:     LuckyVerticalMap[cellInfo.VerticalType],
+		WrapText:     isWrapText,
+	}
+}
+
+// getExcelBorderConf 获取表格边框配置
+//func getExcelBorderConf(list []LuckySheetDataConfigBorderInfo) (v xlsx.Border) {
+//	// 字体
+//	for _, v := range list {
+//		//v.BorderType
+//		//v.Style
+//
+//		if v.RangeType == "cell" {
+//
+//			xlsx.Border{
+//				Left:        LuckyBorderMap[v.Value.L.Style],
+//				LeftColor:   strings.TrimPrefix(v.Value.L.Color, "#"),
+//				Right:       LuckyBorderMap[v.Value.R.Style],
+//				RightColor:  strings.TrimPrefix(v.Value.R.Color, "#"),
+//				Top:         LuckyBorderMap[v.Value.T.Style],
+//				TopColor:    strings.TrimPrefix(v.Value.T.Color, "#"),
+//				Bottom:      LuckyBorderMap[v.Value.B.Style],
+//				BottomColor: strings.TrimPrefix(v.Value.B.Color, "#"),
+//			}
+//		} else {
+//			xlsx.Border{
+//				Left:        LuckyBorderMap[v.Style],
+//				LeftColor:   strings.TrimPrefix(v.Color, "#"),
+//				Right:       LuckyBorderMap[v.Style],
+//				RightColor:  strings.TrimPrefix(v.Color, "#"),
+//				Top:         LuckyBorderMap[v.Style],
+//				TopColor:    strings.TrimPrefix(v.Color, "#"),
+//				Bottom:      LuckyBorderMap[v.Style],
+//				BottomColor: strings.TrimPrefix(v.Color, "#"),
+//			}
+//		}
+//		//v.Value.T.Style
+//
+//	}
+//
+//	return
+//}
+
+// LuckyFontFamilyMap 字体map
+var LuckyFontFamilyMap = map[int]string{
+	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: "华文隶书",
+}
+
+// LuckyBorderMap 边框map
+var LuckyBorderMap = map[string]string{
+	"":   "Thin",
+	"1":  "Thin",
+	"2":  "Hair",
+	"3":  "Dotted",
+	"4":  "Dashed",
+	"5":  "DashDot",      //宋体(Song)、
+	"6":  "DashDotDot",   // 黑体(ST Heiti)
+	"7":  "Double",       //楷体(ST Kaiti),
+	"8":  "Medium",       //仿宋(ST FangSong),
+	"9":  "MediumDashed", //新宋体(ST Song),
+	"10": "MediumDashDot",
+	"11": "MediumDashDotDot",
+	"12": "SlantedDashDot",
+	"13": "Thick",
+}
+
+// LuckyHorizontalMap 水平对齐map
+var LuckyHorizontalMap = map[int]string{
+	//"":  "general",
+	0: "center",
+	1: "left",
+	2: "right",
+}
+
+// LuckyVerticalMap 垂直对齐map
+var LuckyVerticalMap = map[int]string{
+	//"":  "center",
+	0: "center",
+	1: "top",
+	//2: "bottom",
+}
+
+// GetColumnName Return the ColumnName
+func GetColumnName(rowNumber int, colNumber int) (colName string, err error) {
+	if rowNumber < 1 || colNumber < 1 {
+		err = errors.New("Row and Column Number can not be less than 1")
+		return
+	}
+
+	dividend := colNumber
+	var modulo int
+	for dividend > 0 {
+		modulo = (dividend - 1) % 26
+		// Convert int to char
+		colName = string(65+modulo) + colName
+		dividend = (int)((dividend - modulo) / 26)
+	}
+
+	colName = colName + strconv.Itoa(rowNumber)
+	return
+}
+
+// GetTableDataByLuckySheetDataStrBak 通过LuckySheet的string数据获取表格数据(备份:2022-08-23 10:30:32)
+func (item *LuckySheetData) GetTableDataByLuckySheetDataStrBak() (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 {
+			tmpRowData = make(map[int64]LuckySheetDataValue)
+		}
+
+		var j int64
+		for j = 0; j <= maxCol; j++ {
+			tmpTableColData, ok := tmpRowData[j]
+			if !ok {
+				tmpTableColData = LuckySheetDataValue{}
+			}
+			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 != `` || (v.MergeCell.Row != rowIndex && v.MergeCell.Row != 0) {
+					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 len(v) <= 0 {
+					continue
+				}
+				if v[columnIndex].Monitor != `` || (v[columnIndex].MergeCell.Column != columnIndex && v[columnIndex].MergeCell.Column != 0) {
+					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 len(v) <= 0 {
+					continue
+				}
+				if v[columnIndex].Monitor != `` || (v[columnIndex].MergeCell.Column != columnIndex && v[columnIndex].MergeCell.Column != 0) {
+					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
+}
+
+func (item *LuckySheetData) ToExcel2() (downloadFilePath string, err error) {
+	tableData, err := item.GetTableDataByLuckySheetDataStr()
+
+	downloadFilePath, err = getDownloadPath()
+	if err != nil {
+		return
+	}
+
+	f := excelize.NewFile()
+	// Create a new sheet.
+	sheetName := `Sheet1`
+	sheetIndex, _ := f.NewSheet(sheetName)
+
+	//设置列宽度
+	for k, v := range tableData.RowWidthList {
+		colName, tmpErr := excelize.ColumnNumberToName(k + 1)
+		if tmpErr != nil {
+			err = errors.New("获取单元格列名失败,ERR:" + tmpErr.Error())
+			err = tmpErr
+			return
+		}
+		err = f.SetColWidth(sheetName, colName, colName, v/10)
+		if err != nil {
+			err = errors.New("设置列宽度,ERR:" + tmpErr.Error())
+			return
+		}
+	}
+
+	// 写入数据
+	for index, v := range tableData.TableDataList {
+		//设置单元格高度
+		if tableData.RowHeightList[index] > 0 {
+			tmpErr := f.SetRowHeight(sheetName, index+1, tableData.RowHeightList[index]/2)
+			if tmpErr != nil {
+				err = errors.New("设置单元格高度失败,ERR:" + tmpErr.Error())
+				return
+			}
+		}
+
+		for colunmIndex, cellInfo := range v {
+			//f.NewStyle
+			defaultFill := excelize.Fill{
+				//Type:    "solid",
+				Pattern: 1,
+				//Color:   []string{cellInfo.Background},
+				Shading: 0,
+			}
+			if cellInfo.Background != `` {
+				defaultFill.Type = "solid"
+				defaultFill.Color = []string{cellInfo.Background}
+			}
+
+			cellStyle := &excelize.Style{
+				Border: []excelize.Border{
+					{Type: "left", Color: "000000", Style: 1},
+					{Type: "top", Color: "000000", Style: 1},
+					{Type: "bottom", Color: "000000", Style: 1},
+					{Type: "right", Color: "000000", Style: 1},
+					//{Type: "diagonalDown", Color: "A020F0", Style: 7},
+					//{Type: "diagonalUp", Color: "A020F0", Style: 8},
+				},
+				Fill:      defaultFill,
+				Font:      getExcelizeFontConf(cellInfo),
+				Alignment: getExcelizeAlignmentConf(cellInfo),
+				//Protection:    nil,
+				//NumFmt:        0,
+				//DecimalPlaces: 0,
+				//CustomNumFmt:  nil,
+				//Lang:   "",
+				//NegRed: false,
+			}
+
+			cellStyleId, tmpErr := f.NewStyle(cellStyle)
+			if tmpErr != nil {
+				err = errors.New("new Style 失败,ERR:" + tmpErr.Error())
+				return
+			}
+			columnName, tmpErr := excelize.ColumnNumberToName(colunmIndex + 1)
+			if tmpErr != nil {
+				err = errors.New("获取单元格列名失败,ERR:" + tmpErr.Error())
+				return
+			}
+			cellName := columnName + strconv.Itoa(index+1)
+
+			tmpErr = f.SetCellStyle(sheetName, cellName, cellName, cellStyleId)
+			if tmpErr != nil {
+				err = errors.New("设置style失败,ERR:" + tmpErr.Error())
+				return
+			}
+
+			valueStr := cellInfo.Monitor
+			if valueStr == `` {
+				//valueStr = fmt.Sprint(cellInfo.Value)
+				if valueStr == `` && cellInfo.CellType.S != nil {
+					//不是设置在单元格上面,而是设置在文本上
+					for _, cellS := range cellInfo.CellType.S {
+						valueStr += fmt.Sprint(cellS.Value)
+					}
+				}
+			}
+			tmpErr = f.SetCellStr(sheetName, cellName, valueStr)
+			if tmpErr != nil {
+				err = errors.New("设置单元格数据失败,ERR:" + tmpErr.Error())
+				return
+			}
+		}
+	}
+
+	for _, v := range tableData.MergeList {
+		//开始列
+		startColumnName, tmpErr := excelize.ColumnNumberToName(v.StartColumnIndex + 1)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		startCellName := startColumnName + strconv.Itoa(v.StartRowIndex+1)
+		//结束列
+		endColumnName, tmpErr := excelize.ColumnNumberToName(v.StartColumnIndex + v.MergeColumnNum + 1)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		endCellName := endColumnName + strconv.Itoa(v.StartRowIndex+v.MergeRowNum+1)
+		err = f.MergeCell(sheetName, startCellName, endCellName)
+		if err != nil {
+			return
+		}
+	}
+
+	// Set active sheet of the workbook.
+	f.SetActiveSheet(sheetIndex)
+	// Save spreadsheet by the given path.
+	err = f.SaveAs(downloadFilePath)
+	return
+}
+
+// getExcelizeFontConf 获取表格字体配置
+func getExcelizeFontConf(cellInfo LuckySheetDataValue) *excelize.Font {
+	fontSize := 10
+	familyName := ``
+
+	//single 单线  、double 双线
+	underlineStyle := ``
+	var isBold, isItalic, isUnderline bool
+	// 字体
+	{
+		if cellInfo.Bold == 1 {
+			isBold = true
+		}
+		if cellInfo.Italic == 1 {
+			isItalic = true
+		}
+		if cellInfo.CancelLine == 1 {
+			isUnderline = true
+		}
+
+		//if cellInfo.Fontsize != `` {
+		//	convSize, _ := strconv.Atoi(cellInfo.Fontsize)
+		//	if convSize > 0 {
+		//		fontSize = convSize
+		//	}
+		//}
+		if cellInfo.Fontsize > 0 {
+			fontSize = cellInfo.Fontsize
+		}
+		tmpFamilyName, familyNameOk := LuckyFontFamilyMap[cellInfo.FontFamily]
+		if !familyNameOk {
+			tmpFamilyName = "宋体"
+		}
+		familyName = tmpFamilyName
+	}
+	if isUnderline {
+		underlineStyle = "single"
+	}
+
+	//VertAlign取值:
+	//BASELINE、superscript、subscript
+	return &excelize.Font{
+		Bold:      isBold,
+		Italic:    isItalic,
+		Underline: underlineStyle,
+		Family:    familyName,
+		Size:      float64(fontSize),
+		Strike:    isUnderline,
+		Color:     cellInfo.FontColor,
+		VertAlign: "",
+	}
+}
+
+// getExcelizeAlignmentConf 获取表格单元格排列配置
+func getExcelizeAlignmentConf(cellInfo LuckySheetDataValue) *excelize.Alignment {
+	//自动换行
+	isWrapText := false
+	if cellInfo.TextBeak == 2 {
+		isWrapText = true
+	}
+	rotateText := 0
+	//if cellInfo.RotateText != `` {
+	//	convSize, _ := strconv.Atoi(cellInfo.RotateText)
+	//	if convSize > 0 {
+	//		rotateText = convSize
+	//	}
+	//}
+	return &excelize.Alignment{
+		Horizontal: LuckyHorizontalMap[cellInfo.HorizontalType],
+		//Indent:          0,
+		//JustifyLastLine: false,
+		//ReadingOrder:   0,
+		//RelativeIndent: 0,
+		//ShrinkToFit:    false,
+		TextRotation: rotateText,
+		Vertical:     LuckyVerticalMap[cellInfo.VerticalType],
+		WrapText:     isWrapText,
+	}
+}
+
+// getColor 获取hex颜色
+func getColor(bgStr string) string {
+	if strings.Contains(bgStr, "(") {
+		arr := strings.Split(bgStr, ",")
+		if len(arr) != 3 {
+			return bgStr
+		}
+
+		// 第一位
+		tmpFirstArr := strings.Split(arr[0], "(")
+		arr[0] = tmpFirstArr[len(tmpFirstArr)-1]
+
+		// 最后一位
+		tmpLastArr := strings.Split(arr[2], ")")
+		arr[2] = tmpLastArr[0]
+
+		rgbArr := make([]int64, 0)
+		for _, v := range arr {
+			tmpInt, err := strconv.Atoi(utils.TrimStr(v))
+			if err != nil {
+				return bgStr
+			}
+			rgbArr = append(rgbArr, int64(tmpInt))
+		}
+
+		rgb := RGB{
+			rgbArr[0],
+			rgbArr[1],
+			rgbArr[2],
+		}
+		bgStr = "" + rgb.Rgb2Hex().Str
+	}
+	return bgStr
+}

+ 101 - 0
services/excel/lucky_sheet_table.go

@@ -0,0 +1,101 @@
+package excel
+
+import (
+	"fmt"
+	"sort"
+)
+
+// HandleTableCell 前端d毛需要我根据合并单元格处理掉多余的单元格
+func HandleTableCell(oldTableData TableData) (newTableData TableData) {
+	newTableData = oldTableData
+
+	mergeList := oldTableData.MergeList
+	lenMergeList := len(mergeList)
+	if lenMergeList <= 0 {
+		return
+	}
+
+	deleteRowMap := make(map[int]map[int]int)
+	deleteRowList := make([]int, 0)
+	deleteColumnMap := make(map[int][]int, 0)
+	for i := lenMergeList - 1; i >= 0; i-- {
+		tmpMerge := mergeList[i]
+
+		//
+		for rowIndex := tmpMerge.MergeRowNum; rowIndex >= 0; rowIndex-- {
+			tmpColumnMap := make(map[int]int)
+			if columnMap, ok := deleteRowMap[tmpMerge.StartRowIndex+rowIndex]; ok {
+				tmpColumnMap = columnMap
+			} else {
+				deleteRowList = append(deleteRowList, tmpMerge.StartRowIndex+rowIndex)
+			}
+
+			deleteColumnList := make([]int, 0)
+			if columnList, ok := deleteColumnMap[tmpMerge.StartRowIndex+rowIndex]; ok {
+				deleteColumnList = columnList
+			}
+
+			for columnIndex := tmpMerge.MergeColumnNum; columnIndex >= 0; columnIndex-- {
+				if rowIndex == 0 && columnIndex == 0 {
+					continue
+				}
+				tmpColumnMap[tmpMerge.StartColumnIndex+columnIndex] = tmpMerge.StartColumnIndex + columnIndex
+				deleteColumnList = append(deleteColumnList, tmpMerge.StartColumnIndex+columnIndex)
+			}
+
+			// 待删除的行
+			deleteRowMap[tmpMerge.StartRowIndex+rowIndex] = tmpColumnMap
+			// 该行待删除的列
+			deleteColumnMap[tmpMerge.StartRowIndex+rowIndex] = deleteColumnList
+		}
+	}
+
+	sort.Ints(deleteRowList)
+
+	for i := len(deleteRowList) - 1; i >= 0; i-- {
+		rowIndex := deleteRowList[i]
+		deleteColumnList := deleteColumnMap[rowIndex]
+		sort.Ints(deleteColumnList)
+		for i := len(deleteColumnList) - 1; i >= 0; i-- {
+			columnIndex := deleteColumnList[i]
+
+			// 最后一行合并单元格时,就不再次移除合并的单元格,避免数组越界
+			if rowIndex >= len(newTableData.TableDataList) {
+				continue
+			}
+			tmpColumnDataList := newTableData.TableDataList[rowIndex]
+
+			// 最后一列合并单元格时,就不再次移除合并的单元格,避免数组越界
+			if columnIndex >= len(tmpColumnDataList) {
+				continue
+			}
+			newTableData.TableDataList[rowIndex] = append(tmpColumnDataList[:columnIndex], tmpColumnDataList[columnIndex+1:]...) // 删除开头N个元素
+			//fmt.Println("row:", rowIndex, "===column:", columnIndex)
+		}
+	}
+
+	// 数据值处理
+	for rowIndex, colList := range newTableData.TableDataList {
+		for colIndex, v := range colList {
+			v.Monitor = handleCellVal(v)
+			colList[colIndex] = v
+		}
+		newTableData.TableDataList[rowIndex] = colList
+	}
+	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
+}

+ 37 - 0
services/excel/rgb2hex.go

@@ -0,0 +1,37 @@
+package excel
+
+import "strconv"
+
+// RGB与HEX颜色互转
+
+type RGB struct {
+	Red,
+	Green,
+	Blue int64
+}
+
+type HEX struct {
+	Str string
+}
+
+func t2x(t int64) string {
+	result := strconv.FormatInt(t, 16)
+	if len(result) == 1 {
+		result = "0" + result
+	}
+	return result
+}
+
+func (color RGB) Rgb2Hex() HEX {
+	r := t2x(color.Red)
+	g := t2x(color.Green)
+	b := t2x(color.Blue)
+	return HEX{r + g + b}
+}
+
+func (color HEX) Hex2Rgb() RGB {
+	r, _ := strconv.ParseInt(color.Str[:2], 16, 10)
+	g, _ := strconv.ParseInt(color.Str[2:4], 16, 18)
+	b, _ := strconv.ParseInt(color.Str[4:], 16, 10)
+	return RGB{r, g, b}
+}

+ 284 - 0
services/oss.go

@@ -0,0 +1,284 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+	"hongze/hongze_ETA_mobile_api/services/alarm_msg"
+	"os"
+	"time"
+
+	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
+	"hongze/hongze_ETA_mobile_api/utils"
+)
+
+var (
+	RoleArn            = "acs:ram::1884217364581072:role/hzossrole"
+	RoleSessionName    = "hzossRole"
+	RAMAccessKeyId     = "LTAI5t9S36LXduhTnECVY6Hn"
+	RAMAccessKeySecret = "V6FG5bdzjKKqMpqEqxeWijJCdzDCuL"
+	STSTokenCacheKey   = "hongze_admin_sts_token"
+)
+
+/*
+上传demo
+func init() {
+	fmt.Println("start")
+	randStr := utils.GetRandStringNoSpecialChar(28)
+	fileName :=  randStr + ".jpg"
+	fmt.Println("fileName:",fileName)
+	fpath:="./1.png"
+	resourceUrl,err:=UploadAliyun(fileName,fpath)
+	if err!=nil {
+		fmt.Println("UploadAliyun Err:",err.Error())
+		return
+	}
+	fmt.Println("resourceUrl:",resourceUrl)
+	fmt.Println("end")
+}
+*/
+
+// 图片上传到阿里云
+func UploadAliyun(filename, filepath string) (string, error) {
+	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+	if err != nil {
+		return "1", err
+	}
+	bucket, err := client.Bucket(utils.Bucketname)
+	if err != nil {
+		return "2", err
+	}
+	path := utils.Upload_dir + time.Now().Format("200601/20060102/")
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3", err
+	}
+	path = utils.Imghost + path
+	return path, err
+}
+
+// UploadAliyunV2 图片上传到阿里云
+func UploadAliyunV2(filename, filepath string) (string, error) {
+	client, err := oss.New(Endpoint, AccessKeyId, AccessKeySecret)
+	if err != nil {
+		return "1", err
+	}
+	bucket, err := client.Bucket(Bucketname)
+	if err != nil {
+		return "2", err
+	}
+	path := UploadDir + time.Now().Format("200601/20060102/")
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3", err
+	}
+	path = Imghost + path
+	return path, err
+}
+
+// 音频上传到阿里云
+func UploadAudioAliyun(filename, filepath string) (string, error) {
+	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+	if err != nil {
+		return "1", err
+	}
+	bucket, err := client.Bucket(utils.Bucketname)
+	if err != nil {
+		return "2", err
+	}
+	path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3", err
+	}
+	path = utils.Imghost + path
+	return path, err
+}
+
+// 视频上传到阿里云
+func UploadVideoAliyun(filename, filepath, savePath string) error {
+	defer func() {
+		os.Remove(filepath)
+	}()
+	client, err := oss.New(utils.Endpoint, utils.AccessKeyId, utils.AccessKeySecret)
+	if err != nil {
+		return err
+	}
+	bucket, err := client.Bucket(utils.Bucketname)
+	if err != nil {
+		return err
+	}
+	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+	//path += filename
+	err = bucket.PutObjectFromFile(savePath, filepath)
+	if err != nil {
+		return err
+	}
+	//path = utils.Imghost + path
+	//return path,err
+	return err
+}
+
+const (
+	HzEndpoint          = "oss-cn-shanghai.aliyuncs.com"
+	HzBucketName string = "hzchart"
+)
+
+// 上传文件到阿里云
+func UploadFileToAliyun(filename, filepath, savePath string) error {
+	defer func() {
+		os.Remove(filepath)
+	}()
+	client, err := oss.New(HzEndpoint, utils.AccessKeyId, utils.AccessKeySecret)
+	if err != nil {
+		return err
+	}
+	bucket, err := client.Bucket(HzBucketName)
+	if err != nil {
+		return err
+	}
+	//path := utils.Upload_Audio_Dir + time.Now().Format("200601/20060102/")
+	//path += filename
+	err = bucket.PutObjectFromFile(savePath, filepath)
+	if err != nil {
+		return err
+	}
+	//path = utils.Imghost + path
+	//return path,err
+	return err
+}
+
+type STSToken struct {
+	AccessKeyId     string
+	AccessKeySecret string
+	SecurityToken   string
+	ExpiredTime     string
+}
+
+// GetOssSTSToken 获取STSToken
+func GetOssSTSToken() (item *STSToken, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info(err.Error())
+			go alarm_msg.SendAlarmMsg("获取STSToken失败, ErrMsg: "+err.Error(), 3)
+		}
+	}()
+	item = new(STSToken)
+	// 获取缓存中的Token
+	recent, _ := utils.Rc.RedisString(STSTokenCacheKey)
+	if recent != "" {
+		lastToken := new(STSToken)
+		if e := json.Unmarshal([]byte(recent), &lastToken); e != nil {
+			err = errors.New("GetOssSTSToken lastToken Unmarshal Err: " + e.Error())
+			return
+		}
+		// 未防止正在上传大文件时Token过期, 将判定的过期时间提前10分钟
+		afterTime := time.Now().Local().Add(10 * time.Minute)
+		expired, e := time.ParseInLocation(utils.FormatDateTime, lastToken.ExpiredTime, time.Local)
+		if e != nil {
+			err = errors.New("GetOssSTSToken expiredTime Parse Err: " + e.Error())
+			return
+		}
+		if expired.After(afterTime) {
+			item.AccessKeyId = lastToken.AccessKeyId
+			item.AccessKeySecret = lastToken.AccessKeySecret
+			item.SecurityToken = lastToken.SecurityToken
+			item.ExpiredTime = lastToken.ExpiredTime
+			return
+		}
+	}
+	// 已过期则获取新的token
+	newToken, e := NewSTSToken()
+	if e != nil {
+		err = errors.New("GetOssSTSToken NewSTSToken Err: " + e.Error())
+		return
+	}
+	newTokenJson, e := json.Marshal(newToken)
+	if e != nil {
+		err = errors.New("GetOssSTSToken NewToken JSON Err: " + e.Error())
+		return
+	}
+	// 覆盖缓存
+	if e := utils.Rc.Put(STSTokenCacheKey, newTokenJson, time.Hour); e != nil {
+		err = errors.New("GetOssSTSToken SetRedis Err: " + e.Error())
+		return
+	}
+	item = newToken
+	return
+}
+
+// NewSTSToken 获取一个新的STSToken
+func NewSTSToken() (item *STSToken, err error) {
+	defer func() {
+		if err != nil {
+			utils.FileLog.Info(err.Error())
+		}
+	}()
+	item = new(STSToken)
+	client, e := sts.NewClientWithAccessKey("cn-shanghai", RAMAccessKeyId, RAMAccessKeySecret)
+	if e != nil {
+		err = errors.New("NewSTSToken NewClient Err: " + e.Error())
+		return
+	}
+	request := sts.CreateAssumeRoleRequest()
+	request.Scheme = "https"
+	request.RegionId = "cn-shanghai"
+	request.RoleArn = RoleArn
+	now := time.Now().Format(utils.FormatDateTimeUnSpace)
+	request.RoleSessionName = RoleSessionName + now
+	request.DurationSeconds = "3600"
+
+	response, e := client.AssumeRole(request)
+	if e != nil {
+		err = errors.New("NewSTSToken AssumeRole Err: " + e.Error())
+		return
+	}
+	if response != nil {
+		item.AccessKeyId = response.Credentials.AccessKeyId
+		item.AccessKeySecret = response.Credentials.AccessKeySecret
+		item.SecurityToken = response.Credentials.SecurityToken
+		t, _ := time.Parse(time.RFC3339, response.Credentials.Expiration)
+		expiration := t.In(time.Local)
+		item.ExpiredTime = expiration.Format(utils.FormatDateTime)
+	}
+	return
+}
+
+// 后台用于传研报小程序二维码
+var (
+	Bucketname      string = "hzchart"
+	Endpoint        string = "oss-cn-shanghai.aliyuncs.com"
+	Imghost         string = "https://hzstatic.hzinsights.com/"
+	UploadDir       string = "static/images/"
+	AccessKeyId     string = "LTAIFMZYQhS2BTvW"
+	AccessKeySecret string = "12kk1ptCHoGWedhBnKRVW5hRJzq9Fq"
+)
+
+// UploadAliyunToDir 上传至hzchart
+func UploadAliyunToDir(filename, filepath, uploadDir, fileDir string) (string, error) {
+	client, err := oss.New(Endpoint, AccessKeyId, AccessKeySecret)
+	if err != nil {
+		return "1", err
+	}
+	bucket, err := client.Bucket(Bucketname)
+	if err != nil {
+		return "2", err
+	}
+	if uploadDir == "" {
+		uploadDir = UploadDir
+	}
+	if fileDir == "" {
+		fileDir = time.Now().Format("200601/20060102/")
+	}
+	path := uploadDir + fileDir
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3", err
+	}
+	path = Imghost + path
+	return path, err
+}

+ 89 - 0
services/video.go

@@ -0,0 +1,89 @@
+package services
+
+import (
+	"bytes"
+	"encoding/binary"
+	"io"
+	"unicode"
+)
+
+
+func GetChineseCount(str1 string) []string {
+	fontArr := make([]string, 0)
+	str := ""
+	count := 0
+	for _, char := range str1 {
+		str += string(char)
+		if unicode.Is(unicode.Han, char) {
+			count++
+			if count >= 1700 {
+				fontArr = append(fontArr, str)
+				str = ""
+				count = 0
+			}
+		}
+	}
+	fontArr = append(fontArr, str)
+	return fontArr
+}
+
+// BoxHeader 信息头
+type BoxHeader struct {
+	Size       uint32
+	FourccType [4]byte
+	Size64     uint64
+}
+
+// GetMP4Duration 获取视频时长,以秒计
+func GetMP4Duration(reader io.ReaderAt) (lengthOfTime uint32, err error) {
+	var info = make([]byte, 0x10)
+	var boxHeader BoxHeader
+	var offset int64 = 0
+	// 获取moov结构偏移
+	for {
+		_, err = reader.ReadAt(info, offset)
+		if err != nil {
+			return
+		}
+		boxHeader = getHeaderBoxInfo(info)
+		fourccType := getFourccType(boxHeader)
+		if fourccType == "moov" {
+			break
+		}
+		// 有一部分mp4 mdat尺寸过大需要特殊处理
+		if fourccType == "mdat" {
+			if boxHeader.Size == 1 {
+				offset += int64(boxHeader.Size64)
+				continue
+			}
+		}
+		offset += int64(boxHeader.Size)
+	}
+	// 获取moov结构开头一部分
+	moovStartBytes := make([]byte, 0x100)
+	_, err = reader.ReadAt(moovStartBytes, offset)
+	if err != nil {
+		return
+	}
+	// 定义timeScale与Duration偏移
+	timeScaleOffset := 0x1C
+	durationOffest := 0x20
+	timeScale := binary.BigEndian.Uint32(moovStartBytes[timeScaleOffset : timeScaleOffset+4])
+	Duration := binary.BigEndian.Uint32(moovStartBytes[durationOffest : durationOffest+4])
+	lengthOfTime = Duration / timeScale
+	return
+}
+
+// getHeaderBoxInfo 获取头信息
+func getHeaderBoxInfo(data []byte) (boxHeader BoxHeader) {
+	buf := bytes.NewBuffer(data)
+	binary.Read(buf, binary.BigEndian, &boxHeader)
+	return
+}
+
+// getFourccType 获取信息头类型
+func getFourccType(boxHeader BoxHeader) (fourccType string) {
+	fourccType = string(boxHeader.FourccType[:])
+	return
+}
+

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません