Răsfoiți Sursa

Merge branch 'master' into feature/yongyi_download

# Conflicts:
#	go.mod
#	go.sum
#	utils/constants.go
xyxie 1 an în urmă
părinte
comite
0a42094f91

+ 2 - 1
.gitignore

@@ -7,4 +7,5 @@
 binlog/
 /static/imgs/python/*
 *.gz
-*.exe
+*.exe
+eta_data_analysis

BIN
eta_data_analysis


+ 12 - 4
go.mod

@@ -10,9 +10,11 @@ require (
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/robfig/cron/v3 v3.0.1
+	github.com/shakinm/xlsReader v0.9.12
 	github.com/shopspring/decimal v1.3.1
 	github.com/tealeg/xlsx v1.0.5
 	github.com/tealeg/xlsx/v3 v3.3.5
+	github.com/xuri/excelize/v2 v2.8.0
 )
 
 require (
@@ -32,21 +34,27 @@ require (
 	github.com/kr/pretty v0.3.1 // indirect
 	github.com/kr/text v0.2.0 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+	github.com/metakeule/fmtdate v1.1.2 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
+	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/peterbourgon/diskv/v3 v3.0.1 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.16.0 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
 	github.com/prometheus/common v0.42.0 // indirect
 	github.com/prometheus/procfs v0.10.1 // indirect
+	github.com/richardlehane/mscfb v1.0.4 // indirect
+	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/rogpeppe/fastuuid v1.2.0 // indirect
 	github.com/rogpeppe/go-internal v1.10.0 // indirect
 	github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
-	golang.org/x/crypto v0.10.0 // indirect
-	golang.org/x/net v0.10.0 // indirect
-	golang.org/x/sys v0.9.0 // indirect
-	golang.org/x/text v0.10.0 // indirect
+	github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca // indirect
+	github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a // indirect
+	golang.org/x/crypto v0.12.0 // indirect
+	golang.org/x/net v0.14.0 // indirect
+	golang.org/x/sys v0.11.0 // indirect
+	golang.org/x/text v0.12.0 // indirect
 	google.golang.org/protobuf v1.30.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 60 - 7
go.sum

@@ -110,12 +110,16 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/metakeule/fmtdate v1.1.2 h1:n9M7H9HfAqp+6OA98wXGMdcAr6omshSNVct65Bks1lQ=
+github.com/metakeule/fmtdate v1.1.2/go.mod h1:2JyMFlKxeoGy1qS6obQukT0AL0Y4iNANQL8scbSdT4E=
 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/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/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/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
 github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -159,6 +163,11 @@ github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+Pymzi
 github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
 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/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
 github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
 github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
@@ -168,6 +177,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
 github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa h1:2cO3RojjYl3hVTbEvJVqrMaFmORhL6O06qdW42toftk=
 github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa/go.mod h1:Yjr3bdWaVWyME1kha7X0jsz3k2DgXNa1Pj3XGyUAbx8=
+github.com/shakinm/xlsReader v0.9.12 h1:F6GWYtCzfzQqdIuqZJ0MU3YJ7uwH1ofJtmTKyWmANQk=
+github.com/shakinm/xlsReader v0.9.12/go.mod h1:ME9pqIGf+547L4aE4YTZzwmhsij+5K9dR+k84OO6WSs=
 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
@@ -181,9 +192,12 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
 github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
 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=
@@ -193,24 +207,43 @@ github.com/tealeg/xlsx/v3 v3.3.5 h1:dzmns01jRf0SveBe7VqkcO2LCLOcypcDI6H66PiZycQ=
 github.com/tealeg/xlsx/v3 v3.3.5/go.mod h1:KV4FTFtvGy0TBlOivJLZu/YNZk6e0Qtk7eOSglWksuA=
 github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
+github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca h1:uvPMDVyP7PXMMioYdyPH+0O+Ta/UO1WFfNYMO3Wz0eg=
+github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
+github.com/xuri/excelize/v2 v2.8.0 h1:Vd4Qy809fupgp1v7X+nCS/MioeQmYVVzi495UCTqB7U=
+github.com/xuri/excelize/v2 v2.8.0/go.mod h1:6iA2edBTKxKbZAa7X5bDhcCg51xdOn1Ar5sfoXRGrQg=
+github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a h1:Mw2VNrNNNjDtw68VsEj2+st+oCSn4Uz7vZw6TbhcV1o=
+github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod h1:Nv7wKD2/bCdKUFNKcJRa99a+1+aSLlCRJFriFYdjz/I=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
-golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
+golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
+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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -220,13 +253,32 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
-golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
+golang.org/x/sys v0.11.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.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
-golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.3.3/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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -253,5 +305,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 60 - 0
models/base_from_fenwei.go

@@ -0,0 +1,60 @@
+package models
+
+import "time"
+
+// FenweiExcelIndex 汾渭Excel指标数据
+type FenweiExcelIndex struct {
+	//ClassifyName string `description:"指标目录"`
+	//ClassifySort int    `description:"指标目录排序号"`
+	IndexName    string `description:"指标名称"`
+	IndexCode    string `description:"指标编码"`
+	Unit         string `description:"单位"`
+	Sort         int    `description:"排序号"`
+	Frequency    string `description:"频度"`
+	TerminalCode string `description:"编码"`
+	ClassifyId   int    `description:"分类ID"`
+	ExcelDataMap map[string]string
+}
+
+// BaseFromFenweiClassifyItem 汾渭数据分类信息
+type BaseFromFenweiClassifyItem struct {
+	ClassifyId   int                           `description:"分类ID"`
+	ClassifyName string                        `description:"分类名称"`
+	ParentId     int                           `description:"父级id"`
+	Level        int                           `description:"层级"`
+	Sort         int                           `description:"排序字段"`
+	CreateTime   string                        `description:"创建时间"`
+	ModifyTime   string                        `description:"修改时间"`
+	Child        []*BaseFromFenweiClassifyItem `description:"子分类"`
+}
+
+type EdbLibFenweiClassifyResponse struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string
+	ErrCode string
+	Data    []BaseFromFenweiClassifyItem
+}
+
+type BaseFromFenweiIndex struct {
+	FenweiIndexId int64 `orm:"column(fenwei_index_id);pk"`
+	IndexCode     string
+	IndexName     string
+	Frequency     string
+	Unit          string
+	ClassifyId    int
+	StartDate     string
+	EndDate       string
+	Sort          int
+	TerminalCode  string
+	CreateTime    time.Time
+	ModifyTime    time.Time
+}
+
+type EdbLibFenweiIndexListResponse struct {
+	Ret     int
+	Msg     string
+	ErrMsg  string
+	ErrCode string
+	Data    []BaseFromFenweiIndex
+}

+ 3 - 1
services/base.go

@@ -44,6 +44,8 @@ func HttpPost(url, postData string, params ...string) ([]byte, error) {
 	}
 	defer resp.Body.Close()
 	b, err := ioutil.ReadAll(resp.Body)
-	fmt.Println("HttpPost:" + string(b))
+	if err != nil {
+		fmt.Println("HttpPost:" + string(b))
+	}
 	return b, err
 }

+ 903 - 0
services/base_from_fenwei.go

@@ -0,0 +1,903 @@
+package services
+
+import (
+	"encoding/json"
+	"eta/eta_data_analysis/models"
+	"eta/eta_data_analysis/utils"
+	"fmt"
+	"github.com/shakinm/xlsReader/xls"
+	"github.com/tealeg/xlsx"
+	"github.com/xuri/excelize/v2"
+	"path"
+	"strings"
+	"time"
+)
+
+const (
+	FenweiIndexNamePrefix = "fwsj" // 指标名称前缀
+
+	FenweiExcelNameA    = "动力煤产销存-66家"
+	FenweiExcelNameB    = "动力煤产销存-100家"
+	FenweiExcelNameC    = "焦煤产销存-53家"
+	FenweiNewExcelNameC = "炼焦煤产销存分省-53家"
+	FenweiExcelNameD    = "焦煤产销存-88家"
+	FenweiNewExcelNameD = "炼焦煤产销存分省-88家"
+	FenweiExcelNameE    = "样本焦化厂焦煤"
+
+	FenweiYangBenIndexNamePre    = "样本焦企炼焦煤库存可用天数"
+	FenweiYangBenIndexClassifyId = 5 // 样本焦企炼焦分类ID
+)
+
+var FenweiProvinces = []string{
+	"内蒙古", "山西", "陕西", "三省合计", "临汾市", "临汾", "吕梁市", "吕梁", "长治市", "长治", "山西其他", "河北", "合计", "山东", "其他",
+}
+
+// FenweiProvinceClassifyMapping 指标名称省份->分类省份
+var FenweiProvinceClassifyMapping = map[string]string{
+	"内蒙古":  "内蒙古",
+	"山西":   "山西",
+	"陕西":   "陕西",
+	"三省合计": "三省合计",
+	"临汾市":  "临汾市",
+	"吕梁市":  "吕梁市",
+	"长治市":  "长治市",
+	"临汾":   "临汾市",
+	"吕梁":   "吕梁市",
+	"长治":   "长治市",
+	"山西其他": "山西其他",
+	"河北":   "河北",
+	"山东":   "山东",
+	"合计":   "合计",
+	"其他":   "其他",
+}
+
+// FenweiFirstClassifyMap excel表名->一级分类ID
+var FenweiFirstClassifyMap = map[string]int{
+	FenweiExcelNameA: 1,
+	FenweiExcelNameB: 2,
+	FenweiExcelNameC: 3,
+	FenweiExcelNameD: 4,
+	FenweiExcelNameE: 5,
+}
+
+// FenweiNewDlm66DiffIndexNameReplaceMapping 动力煤66家-指标名称不同的进行替换
+var FenweiNewDlm66DiffIndexNameReplaceMapping = map[string]string{
+	"价格平均上涨幅度(元/吨)": "煤矿价格平均上涨幅度",
+	"库存库存量(万吨)":     "煤矿库存",
+	"盈亏情况盈利煤矿数量":    "盈利煤矿数量",
+	"盈亏情况平均利润(元/吨)": "煤矿平均利润",
+	"盈亏情况亏损煤矿数量":    "亏损煤矿数量",
+	"盈亏情况平均亏损(元/吨)": "煤矿平均亏损",
+	"周度产量产量(万吨)":    "煤矿周度产量",
+	"销售好":           "销售好煤矿数量",
+	"销售一般":          "销售一般煤矿数量",
+	"销售不好":          "销售不好煤矿数量",
+	"销售关闭":          "关闭煤矿数量",
+	"产能利用率产能利用率":    "煤矿产能利用率",
+	"开工率开工率":        "煤矿算术平均开工率(含停产)",
+	"价格平均下跌幅度":      "煤矿价格平均下跌幅度",
+}
+
+// FenweiNewDlm66IgnoreIndexNameMapping 动力煤66家-需要忽略的指标名称
+var FenweiNewDlm66IgnoreIndexNameMapping = []string{
+	"库存环比", "发运至港口平均利润", "周度产量环比", "开工率算数平均(不含停产矿)", "变化", "产能利用率变化", "开工率变化",
+}
+
+// FenweiNewDlm100DiffIndexNameReplaceMapping 动力煤100家-指标名称不同的进行替换
+var FenweiNewDlm100DiffIndexNameReplaceMapping = map[string]string{
+	"价格平均上涨幅度(元/吨)": "煤矿价格平均上涨幅度",
+	"价格平均下跌幅度":      "煤矿价格平均下跌幅度",
+	"库存库存量(万吨)":     "煤矿库存",
+	"库存环比":          "煤矿库存环比",
+	"盈亏情况盈利煤矿数量":    "盈利煤矿数量",
+	"盈亏情况平均利润(元/吨)": "煤矿平均利润",
+	"盈亏情况亏损煤矿数量":    "亏损煤矿数量",
+	"盈亏情况平均亏损(元/吨)": "煤矿平均亏损",
+	"发运至港口平均利润":     "煤炭发运至港口平均利润",
+	"周度产量产量(万吨)":    "煤矿周度产量",
+	"周度产量环比":        "煤矿周度产量环比",
+	"产能利用率产能利用率":    "煤矿产能利用率",
+	"产能利用率变化":       "煤矿产能利用率环比",
+	"开工率开工率":        "煤矿平均开工率",
+	"开工率变化":         "煤矿平均开工率环比",
+	"销售好":           "销售好煤矿数量",
+	"销售一般":          "销售一般煤矿数量",
+	"销售不好":          "销售不好煤矿数量",
+	"销售关闭":          "关闭煤矿数量",
+}
+
+// FenweiNewDlm100IgnoreIndexNameMapping 动力煤100家-需要忽略的指标名称
+var FenweiNewDlm100IgnoreIndexNameMapping = make([]string, 0)
+
+// FenweiNewJm53DiffIndexNameReplaceMapping 焦煤53家-指标名称不同的进行替换
+var FenweiNewJm53DiffIndexNameReplaceMapping = map[string]string{
+	"价格情况煤矿数量":       "煤矿数量",
+	"价格情况上涨煤矿数量":     "上涨煤矿数量",
+	"价格情况平均上涨(元/吨)":  "煤矿平均上涨幅度",
+	"价格情况下跌煤矿数量":     "下跌煤矿数量",
+	"价格情况平均下跌(元/吨)":  "煤矿平均下跌幅度",
+	"价格情况持平煤矿数量":     "持平煤矿数量",
+	"原煤库存情况库存总量(万吨)": "原煤库存",
+	"精煤库存情况库存总量(万吨)": "精煤库存",
+	"开工情况权重平均开工率":    "煤矿加权开工率",
+	"开工情况算数平均开工率":    "煤矿算术平均开工率",
+	"开工情况停产煤矿数量":     "停产煤矿数量",
+	"开工情况本周原煤产量(万吨)": "本周原煤产量",
+	"销售良好":     "销售好煤矿数量",
+	"销售正常":     "销售一般煤矿数量",
+	"销售不好":     "销售不好煤矿数量",
+	"成本盈利煤矿数量": "盈利煤矿数量",
+	"成本平均利润":   "煤矿平均利润",
+	"成本亏损煤矿数量": "亏损煤矿数量",
+	"成本平均亏损":   "煤矿平均亏损",
+}
+
+// FenweiNewJm53IgnoreIndexNameMapping 焦煤53家-需要忽略的指标名称
+var FenweiNewJm53IgnoreIndexNameMapping = []string{
+	"原煤库存情况环比(万吨)", "精煤库存情况环比(万吨)", "开工情况开工率变化", "开工情况停产煤矿数量变化", "开工情况环比产量变化",
+}
+
+// FenweiNewJm88DiffIndexNameReplaceMapping 焦煤88家-指标名称不同的进行替换
+var FenweiNewJm88DiffIndexNameReplaceMapping = map[string]string{
+	"价格情况煤企数量":       "煤企数量",
+	"价格情况上涨煤企数量":     "上涨煤企数量",
+	"价格情况平均上涨(元/吨)":  "煤企平均上涨幅度",
+	"价格情况下跌煤矿数量":     "下跌煤企数量",
+	"价格情况平均下跌(元/吨)":  "煤企平均下跌幅度",
+	"价格情况持平煤企数量":     "持平煤企数量",
+	"原煤库存情况库存总量(万吨)": "原煤库存",
+	"原煤库存情况环比(万吨)":   "原煤库存环比",
+	"精煤库存情况库存总量(万吨)": "精煤库存",
+	"精煤库存情况环比(万吨)":   "精煤库存环比",
+	"开工情况产能利用率":      "煤企产能利用率",
+	"开工情况产能利用率变化":    "煤企产能利用率环比",
+	"开工情况开工率":        "煤企开工率",
+	"开工情况开工率变化":      "煤企开工率环比",
+	"开工情况停产煤矿数量":     "停产煤矿数量",
+	"开工情况停产煤矿数量变化":   "停产煤矿数量变化",
+	"开工情况本周原煤产量(万吨)": "本周原煤产量",
+	"开工情况环比产量变化":     "本周原煤产量变化",
+	"本周精煤产量(万吨)":     "本周精煤产量",
+	"环比产量变化":         "本周精煤产量变化",
+	"良好":             "销售好煤企数量",
+	"正常":             "销售一般煤企数量",
+	"不好":             "销售不好煤企数量",
+	"盈利煤企数量":         "盈利煤企数量",
+	"商品煤平均利润":        "煤企平均利润",
+	"亏损煤企数量":         "亏损煤企数量",
+	"商品煤平均亏损":        "煤企平均亏损",
+}
+
+// FenweiNewJm88IgnoreIndexNameMapping 焦煤88家-需要忽略的指标名称
+var FenweiNewJm88IgnoreIndexNameMapping = make([]string, 0)
+
+var FenweiNewDiffIndexNameReplaceMapping = map[string]map[string]string{
+	FenweiExcelNameA: FenweiNewDlm66DiffIndexNameReplaceMapping,
+	FenweiExcelNameB: FenweiNewDlm100DiffIndexNameReplaceMapping,
+	FenweiExcelNameC: FenweiNewJm53DiffIndexNameReplaceMapping,
+	FenweiExcelNameD: FenweiNewJm88DiffIndexNameReplaceMapping,
+}
+
+var FenweiNewIgnoreIndexNameMapping = map[string][]string{
+	FenweiExcelNameA: FenweiNewDlm66IgnoreIndexNameMapping,
+	FenweiExcelNameB: FenweiNewDlm100IgnoreIndexNameMapping,
+	FenweiExcelNameC: FenweiNewJm53IgnoreIndexNameMapping,
+	FenweiExcelNameD: FenweiNewJm88IgnoreIndexNameMapping,
+}
+
+var FenweiNewIndexNameSuffixMapping = map[string]string{
+	FenweiExcelNameA: "/动力煤/66家样本",
+	FenweiExcelNameB: "/动力煤/100家样本",
+	FenweiExcelNameC: "/焦煤/53家样本",
+	FenweiExcelNameD: "/焦煤/88家样本",
+}
+
+var FenweiNewExcelProvinceMapping = map[string]string{
+	"内蒙古":    "内蒙古",
+	"山西":     "山西",
+	"陕西":     "陕西",
+	"三省合计":   "三省合计",
+	"山西-临汾市": "临汾",
+	"山西-吕梁市": "吕梁",
+	"山西-长治市": "长治",
+	"山西-其他":  "山西其他",
+	"山东":     "山东",
+	"其他":     "其他",
+	"合计":     "合计",
+	"河北":     "河北",
+}
+
+// AnalysisFenweiHistoryExcel 解析汾渭历史Excel数据
+func AnalysisFenweiHistoryExcel(filePath string) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Printf("AnalysisFenweiExcel ErrMsg: %s\n", err.Error())
+			utils.FileLog.Info(fmt.Sprintf("AnalysisFenweiExcel ErrMsg: %s", err.Error()))
+		}
+	}()
+
+	fileName := path.Base(filePath)
+	var indexes []*models.FenweiExcelIndex
+	var e error
+	if strings.Contains(fileName, FenweiExcelNameA) {
+		indexes, e = AnalysisFenweiHistoryExcelNormal(filePath, FenweiExcelNameA)
+	} else if strings.Contains(fileName, FenweiExcelNameB) {
+		indexes, e = AnalysisFenweiHistoryExcelNormal(filePath, FenweiExcelNameB)
+	} else if strings.Contains(fileName, FenweiExcelNameC) {
+		indexes, e = AnalysisFenweiHistoryExcelNormal(filePath, FenweiExcelNameC)
+	} else if strings.Contains(fileName, FenweiExcelNameD) {
+		indexes, e = AnalysisFenweiHistoryExcelNormal(filePath, FenweiExcelNameD)
+	} else if strings.Contains(fileName, FenweiExcelNameE) {
+		indexes, e = AnalysisFenweiExcelYangBen(filePath)
+	} else {
+		utils.FileLog.Info(fmt.Sprintf("文件名有误, FileName: %s", fileName))
+		return
+	}
+	if e != nil {
+		utils.FileLog.Info(fmt.Sprintf("获取excel数据失败, FileName: %s, Err: %s", fileName, e))
+		return
+	}
+	if len(indexes) == 0 {
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, index empty", fileName))
+		return
+	}
+
+	// 写入数据
+	params := make(map[string]interface{})
+	params["List"] = indexes
+	params["TerminalCode"] = utils.TerminalCode
+	result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_HANDLE)
+	if e != nil {
+		b, _ := json.Marshal(params)
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, PostEdbLib err: %s, params: %s", fileName, e.Error(), string(b)))
+		return
+	}
+	resp := new(models.BaseEdbLibResponse)
+	if e := json.Unmarshal(result, &resp); e != nil {
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, json.Unmarshal err: %s", fileName, e.Error()))
+		return
+	}
+	if resp.Ret != 200 {
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, Msg: %s, ErrMsg: %s", fileName, resp.Msg, resp.ErrMsg))
+		return
+	}
+	return
+}
+
+// AnalysisFenweiHistoryExcelNormal 历史数据-动力煤产销存/焦煤产销存
+func AnalysisFenweiHistoryExcelNormal(filePath, excelName string) (indexes []*models.FenweiExcelIndex, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Printf("AnalysisFenweiHistoryExcelNormal ErrMsg: %s\n", err.Error())
+			utils.FileLog.Info(fmt.Sprintf("AnalysisFenweiHistoryExcelNormal ErrMsg: %s", err.Error()))
+		}
+	}()
+
+	f, e := excelize.OpenFile(filePath)
+	if e != nil {
+		err = fmt.Errorf("open file err: %s", e.Error())
+		return
+	}
+	defer func() {
+		if e = f.Close(); e != nil {
+			err = fmt.Errorf("f close err: %s", e.Error())
+		}
+	}()
+	sheetName := f.GetSheetName(0)
+	rows, e := f.GetRows(sheetName)
+	if e != nil {
+		err = fmt.Errorf("f GetRows err: %s", e.Error())
+		return
+	}
+
+	// 获取指标分类
+	firstId := FenweiFirstClassifyMap[excelName]
+	if firstId <= 0 {
+		err = fmt.Errorf("excel名称有误, 分类不匹配, excelName: %s", excelName)
+		return
+	}
+	classifies, e := GetFenweiClassify()
+	if e != nil {
+		err = fmt.Errorf("获取指标分类失败, Err: %s", e.Error())
+		return
+	}
+	secondClassifyMap := make(map[string]int)
+	for _, v := range classifies {
+		if v.ClassifyId != firstId {
+			continue
+		}
+		for _, c := range v.Child {
+			secondClassifyMap[c.ClassifyName] = c.ClassifyId
+		}
+	}
+
+	indexes = make([]*models.FenweiExcelIndex, 0)
+	indexColIndex := make(map[int]*models.FenweiExcelIndex) // 列对应的指标(B列-?列)
+	maxCol := 0
+	sortArr := make([]string, 0) // 排序用的
+	for i, row := range rows {
+		// 首行为标题, 忽略
+		if i == 0 {
+			continue
+		}
+
+		// 第二行-指标名称
+		if i == 1 {
+			for k, cell := range row {
+				if k == 0 {
+					maxCol += 1
+					continue
+				}
+				name := strings.TrimSpace(cell)
+				name = strings.ReplaceAll(name, " ", "")
+				if name == "" {
+					break
+				}
+				maxCol += 1
+				if indexColIndex[k] == nil {
+					indexColIndex[k] = new(models.FenweiExcelIndex)
+					indexColIndex[k].ExcelDataMap = make(map[string]string)
+					indexColIndex[k].TerminalCode = utils.TerminalCode
+					indexColIndex[k].IndexName = name
+				}
+			}
+			continue
+		}
+
+		// 第三行-指标ID、指标分类
+		if i == 2 {
+			for k := 0; k < maxCol; k++ {
+				if k == 0 {
+					continue
+				}
+				if indexColIndex[k] == nil {
+					utils.FileLog.Info(fmt.Sprintf("第%d列无指标ID", k))
+					break
+				}
+				// 例:内蒙古煤矿数量/动力煤/66家样本->fwsjneimenggumksldlm66jyb
+				name := strings.ReplaceAll(indexColIndex[k].IndexName, "/", "")
+				var middle, suffix, province string
+				for _, p := range FenweiProvinces {
+					// 此处山西其他可能会被错误的给鉴别为山西, 所以优先鉴别一下山西其他
+					if strings.Contains(name, "山西其他") {
+						province = "山西其他"
+						middle = utils.GetFullPingYin("山西其他")
+						name = strings.ReplaceAll(name, p, "")
+						break
+					}
+					if strings.Contains(name, p) {
+						province = p
+						middle = utils.GetFullPingYin(p)
+						name = strings.ReplaceAll(name, p, "")
+						break
+					}
+				}
+				if middle == "" {
+					utils.FileLog.Info(fmt.Sprintf("指标名称转换编码有误, IndexName: %s", indexColIndex[k].IndexName))
+					continue
+				}
+				classifyProvince := FenweiProvinceClassifyMapping[province]
+				classifyId := secondClassifyMap[classifyProvince]
+				if classifyId <= 0 {
+					utils.FileLog.Info(fmt.Sprintf("指标名称分类不匹配, IndexName: %s", indexColIndex[k].IndexName))
+					continue
+				}
+
+				suffix = utils.GetFirstPingYin(name)
+				indexColIndex[k].IndexCode = fmt.Sprint(FenweiIndexNamePrefix, middle, suffix)
+				indexColIndex[k].ClassifyId = classifyId
+				sortArr = append(sortArr, indexColIndex[k].IndexCode)
+			}
+			continue
+		}
+
+		// 第四行-频度
+		if i == 3 {
+			for k, cell := range row {
+				if k == 0 {
+					continue
+				}
+				if indexColIndex[k] == nil {
+					utils.FileLog.Info(fmt.Sprintf("第%d列无指标名称", k))
+					break
+				}
+				frequency := strings.TrimSpace(cell)
+				indexColIndex[k].Frequency = frequency
+			}
+			continue
+		}
+
+		// 第五行-单位
+		if i == 4 {
+			for k, cell := range row {
+				if k == 0 {
+					continue
+				}
+				if indexColIndex[k] == nil {
+					utils.FileLog.Info(fmt.Sprintf("第%d列无指标单位", k))
+					break
+				}
+				unit := strings.TrimSpace(cell)
+				indexColIndex[k].Unit = unit
+			}
+			continue
+		}
+
+		// 数据行
+		if i > 4 {
+			var date string
+			for k, cell := range row {
+				if k == 0 {
+					// 日期
+					date = strings.TrimSpace(cell)
+					_, e := time.Parse(utils.FormatDate, date)
+					if e != nil {
+						// 如果第一列不是日期那么结束本行的读取
+						break
+					}
+					continue
+				}
+				// 日期数据
+				if date == "" {
+					utils.FileLog.Info(fmt.Sprintf("第%d行无数据日期", i))
+					break
+				}
+				if indexColIndex[k] == nil {
+					utils.FileLog.Info(fmt.Sprintf("第%d列无指标名称", k))
+					break
+				}
+				val := strings.TrimSpace(cell)
+				if val == "" {
+					// 单元格数据为空, 则当前日期无数据
+					continue
+				}
+				indexColIndex[k].ExcelDataMap[date] = val
+			}
+			continue
+		}
+	}
+
+	codeIndexes := make(map[string]*models.FenweiExcelIndex)
+	for _, v := range indexColIndex {
+		if v.IndexCode == "" {
+			continue
+		}
+		codeIndexes[v.IndexCode] = v
+	}
+	for _, v := range sortArr {
+		if codeIndexes[v] != nil {
+			indexes = append(indexes, codeIndexes[v])
+		}
+	}
+	return
+}
+
+// AnalysisFenweiExcelYangBen 样本焦化厂
+func AnalysisFenweiExcelYangBen(filePath string) (indexes []*models.FenweiExcelIndex, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Printf("AnalysisFenweiExcelYangBen ErrMsg: %s\n", err.Error())
+			utils.FileLog.Info(fmt.Sprintf("AnalysisFenweiExcelYangBen ErrMsg: %s", err.Error()))
+		}
+	}()
+
+	indexColIndex := make(map[int]*models.FenweiExcelIndex) // 列对应的指标(B列-E列)
+	provinces := []string{"地区", "全国", "山西", "河北", "山东"}
+	for k, v := range provinces {
+		if k == 0 {
+			continue
+		}
+		if indexColIndex[k] == nil {
+			indexColIndex[k] = new(models.FenweiExcelIndex)
+			indexColIndex[k].ExcelDataMap = make(map[string]string)
+			indexColIndex[k].TerminalCode = utils.TerminalCode
+			indexColIndex[k].ClassifyId = FenweiYangBenIndexClassifyId
+			indexColIndex[k].Frequency = "周度"
+			indexColIndex[k].Unit = "天"
+			indexColIndex[k].IndexName = fmt.Sprintf("%s/%s", FenweiYangBenIndexNamePre, v)
+
+			// 指标编码, 例:样本焦企炼焦煤库存可用天数/全国->fwsjybjqljmkckytsquanguo
+			name := strings.ReplaceAll(indexColIndex[k].IndexName, "/", "")
+			var middle, suffix string
+			for _, p := range provinces {
+				if strings.Contains(name, p) {
+					suffix = utils.GetFullPingYin(p)
+					name = strings.ReplaceAll(name, p, "")
+					break
+				}
+			}
+			if suffix == "" {
+				utils.FileLog.Info(fmt.Sprintf("指标名称转换编码有误, IndexName: %s", indexColIndex[k].IndexName))
+				continue
+			}
+			middle = utils.GetFirstPingYin(name)
+			indexColIndex[k].IndexCode = fmt.Sprint(FenweiIndexNamePrefix, middle, suffix)
+		}
+	}
+
+	maxCols := 5      // 每行只读取前5列即可
+	startDateRow := 0 // 数据日期起始行(第一行), 后面依次加4行读取
+	startDataRow := 2 // 数据值起始行(第三行), 后面依次加4行读取
+	sumDateRow := 0   // 数据日期累加的行, 每加4次重置0
+	sumDataRow := 0   // 数据值累加的行, 每加4次重置0
+	currDate := ""    // 最近的一次日期
+	stop := false     // 结束读取excel
+
+	xlsFile, e := xls.OpenFile(filePath)
+	if e != nil {
+		err = fmt.Errorf("open xls file err: %s", e.Error())
+		return
+	}
+	sheet, e := xlsFile.GetSheet(0)
+	if e != nil {
+		err = fmt.Errorf("GetSheet err: %s", e.Error())
+		return
+	}
+	rows := sheet.GetRows()
+	for i, row := range rows {
+		sumDateRow += 1
+		sumDataRow += 1
+
+		// 第一个日期行/后续每4行取一次日期
+		if i == startDateRow || sumDateRow == 4 {
+			if stop {
+				break
+			}
+			sumDateRow = 0
+
+			for k, cell := range row.GetCols() {
+				// 日期只取第一个单元格中的
+				if k > 0 {
+					break
+				}
+				strDates := strings.TrimSpace(cell.GetString())
+				strDates = strings.ReplaceAll(strDates, "样本焦企炼焦煤库存", "")
+				strDates = strings.ReplaceAll(strDates, "\x00", "")
+				strDates = strings.ReplaceAll(strDates, "本焦企炼焦煤库存", "")
+				strDateArr := strings.Split(strDates, "-")
+				// 正常情况下, 长度不为2说明读取到了最后一行了
+				if len(strDateArr) != 2 {
+					utils.FileLog.Info(fmt.Sprintf("第%d行数据日期长度有误, 结束读取", i+1))
+					stop = true
+					break
+				}
+				t, e := time.Parse("2006.1.2", strDateArr[1])
+				if e != nil {
+					utils.FileLog.Info(fmt.Sprintf("第%d行数据日期有误, err: %s", i+1, e.Error()))
+					break
+				}
+				currDate = t.Format(utils.FormatDate)
+			}
+		}
+
+		// 第一个数据行/后续每4行取一次数据
+		if i == startDataRow || sumDataRow == 4 {
+			if currDate == "" {
+				utils.FileLog.Info(fmt.Sprintf("第%d行数据对应日期有误", i+1))
+				continue
+			}
+			sumDataRow = 0
+
+			for k, cell := range row.GetCols() {
+				if k >= maxCols {
+					break
+				}
+				if k == 0 {
+					continue
+				}
+				val := cell.GetFloat64()
+				// 保留4位小数
+				indexColIndex[k].ExcelDataMap[currDate] = fmt.Sprintf("%.4f", val)
+			}
+			// 重置日期
+			currDate = ""
+		}
+	}
+
+	indexes = make([]*models.FenweiExcelIndex, 0)
+	for _, v := range indexColIndex {
+		if v.IndexCode == "" {
+			continue
+		}
+		indexes = append(indexes, v)
+	}
+	return
+}
+
+// GetFenweiClassify 获取汾渭数据分类
+func GetFenweiClassify() (classifies []models.BaseFromFenweiClassifyItem, err error) {
+	params := make(map[string]interface{})
+	result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_CLASSIFY)
+	if e != nil {
+		b, _ := json.Marshal(params)
+		err = fmt.Errorf("GetFenweiClassify, PostEdbLib err: %s, params: %s", e.Error(), string(b))
+		return
+	}
+	resp := new(models.EdbLibFenweiClassifyResponse)
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf(fmt.Sprintf("GetFenweiClassify, json.Unmarshal err: %s", e.Error()))
+		return
+	}
+	if resp.Ret != 200 {
+		err = fmt.Errorf(fmt.Sprintf("GetFenweiClassify, Msg: %s, ErrMsg: %s", resp.Msg, resp.ErrMsg))
+		return
+	}
+	classifies = resp.Data
+	return
+}
+
+// GetFenweiIndexList 获取汾渭指标列表
+func GetFenweiIndexList() (list []models.BaseFromFenweiIndex, err error) {
+	params := make(map[string]interface{})
+	result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_INDEX_LIST)
+	if e != nil {
+		b, _ := json.Marshal(params)
+		err = fmt.Errorf("GetFenweiIndexList, PostEdbLib err: %s, params: %s", e.Error(), string(b))
+		return
+	}
+	resp := new(models.EdbLibFenweiIndexListResponse)
+	if e = json.Unmarshal(result, &resp); e != nil {
+		err = fmt.Errorf(fmt.Sprintf("GetFenweiIndexList, json.Unmarshal err: %s", e.Error()))
+		return
+	}
+	if resp.Ret != 200 {
+		err = fmt.Errorf(fmt.Sprintf("GetFenweiIndexList, Msg: %s, ErrMsg: %s", resp.Msg, resp.ErrMsg))
+		return
+	}
+	list = resp.Data
+	return
+}
+
+// AnalysisFenweiNewExcel 解析汾渭增量Excel数据
+func AnalysisFenweiNewExcel(filePath string) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Printf("AnalysisFenweiNewExcel ErrMsg: %s\n", err.Error())
+			utils.FileLog.Info(fmt.Sprintf("AnalysisFenweiNewExcel ErrMsg: %s", err.Error()))
+		}
+	}()
+
+	fileName := path.Base(filePath)
+	var indexes []*models.FenweiExcelIndex
+	var e error
+	if strings.Contains(fileName, FenweiExcelNameA) {
+		indexes, e = AnalysisFenweiNewExcelNormal(filePath, FenweiExcelNameA)
+	} else if strings.Contains(fileName, FenweiExcelNameB) {
+		indexes, e = AnalysisFenweiNewExcelNormal(filePath, FenweiExcelNameB)
+	} else if strings.Contains(fileName, FenweiNewExcelNameC) {
+		indexes, e = AnalysisFenweiNewExcelNormal(filePath, FenweiExcelNameC)
+	} else if strings.Contains(fileName, FenweiNewExcelNameD) {
+		indexes, e = AnalysisFenweiNewExcelNormal(filePath, FenweiExcelNameD)
+	} else if strings.Contains(fileName, FenweiExcelNameE) {
+		indexes, e = AnalysisFenweiExcelYangBen(filePath) // 样本焦化厂-增量数据和历史数据excel格式相同
+	} else {
+		utils.FileLog.Info(fmt.Sprintf("文件名有误, FileName: %s", fileName))
+		return
+	}
+	if e != nil {
+		utils.FileLog.Info(fmt.Sprintf("获取excel数据失败, FileName: %s, Err: %s", fileName, e))
+		return
+	}
+	if len(indexes) == 0 {
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, index empty", fileName))
+		return
+	}
+
+	// 写入数据
+	params := make(map[string]interface{})
+	params["List"] = indexes
+	params["TerminalCode"] = utils.TerminalCode
+	result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_HANDLE)
+	if e != nil {
+		b, _ := json.Marshal(params)
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, PostEdbLib err: %s, params: %s", fileName, e.Error(), string(b)))
+		return
+	}
+	resp := new(models.BaseEdbLibResponse)
+	if e := json.Unmarshal(result, &resp); e != nil {
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, json.Unmarshal err: %s", fileName, e.Error()))
+		return
+	}
+	if resp.Ret != 200 {
+		utils.FileLog.Info(fmt.Sprintf("fileName: %s, Msg: %s, ErrMsg: %s", fileName, resp.Msg, resp.ErrMsg))
+		return
+	}
+	return
+}
+
+// AnalysisFenweiNewExcelNormal 增量数据-动力煤/焦煤
+func AnalysisFenweiNewExcelNormal(filePath, excelName string) (indexes []*models.FenweiExcelIndex, err error) {
+	defer func() {
+		if err != nil {
+			fmt.Printf("AnalysisFenweiNewExcelNormal ErrMsg: %s\n", err.Error())
+			utils.FileLog.Info(fmt.Sprintf("AnalysisFenweiNewExcelNormal ErrMsg: %s", err.Error()))
+		}
+	}()
+
+	xlsFile, e := xlsx.OpenFile(filePath)
+	if e != nil {
+		err = fmt.Errorf("OpenFile Err: %s", e.Error())
+		return
+	}
+
+	// 获取存量指标, 增量数据只新增存量指标的数据
+	originIndexes, e := GetFenweiIndexList()
+	if e != nil {
+		err = fmt.Errorf("GetFenweiIndexList err: %s", e.Error())
+		return
+	}
+	indexMapping := make(map[string]models.BaseFromFenweiIndex)
+	for _, v := range originIndexes {
+		indexMapping[v.IndexCode] = v
+	}
+
+	diffNameReplace := FenweiNewDiffIndexNameReplaceMapping[excelName]
+	ignoreIndexName := FenweiNewIgnoreIndexNameMapping[excelName]
+	indexNameSuffix := FenweiNewIndexNameSuffixMapping[excelName]
+	var dataRowMin, dataRowMax int // 数据起始行数
+	if excelName == FenweiExcelNameA || excelName == FenweiExcelNameB {
+		dataRowMin = 3
+		dataRowMax = 6
+	}
+	if excelName == FenweiExcelNameC {
+		dataRowMin = 3
+		dataRowMax = 10
+	}
+	if excelName == FenweiExcelNameD {
+		dataRowMin = 3
+		dataRowMax = 13
+	}
+
+	var dataDate string
+	secondRowNames := make(map[int]string) // 第二行-指标名称的上半部分
+	thirdRowNames := make(map[int]string)  // 第三行-指标名称的另一部分
+	indexes = make([]*models.FenweiExcelIndex, 0)
+	indexColIndex := make(map[string]*models.FenweiExcelIndex) // 行-列对应的指标
+	rowProvince := make(map[int]string)                        // 行对应的省份名
+	for _, sheet := range xlsFile.Sheet {
+		maxRow := sheet.MaxRow
+		for i := 0; i < maxRow; i++ {
+			cells := sheet.Row(i).Cells
+
+			// 首行为数据日期
+			if i == 0 {
+				for _, cell := range cells {
+					str := strings.TrimSpace(cell.String())
+					if str == "" {
+						continue
+					}
+					dateArr := strings.Split(str, "-")
+					if len(dateArr) != 2 {
+						err = fmt.Errorf("数据日期有误, len(dateArr): %d", len(dateArr))
+						return
+					}
+					t, e := time.ParseInLocation("2006.1.2", dateArr[1], time.Local)
+					if e != nil {
+						t, e = time.ParseInLocation("2006.01.02", dateArr[1], time.Local)
+						if e != nil {
+							err = fmt.Errorf("数据日期有误, date: %s", dateArr[1])
+							return
+						}
+					}
+					dataDate = t.Format(utils.FormatDate)
+					break
+				}
+			}
+
+			// 第二行-指标名称上半部分
+			if i == 1 {
+				for k, cell := range cells {
+					text := strings.TrimSpace(cell.String())
+					if k > 0 && text != "" {
+						// 纵向合并
+						if cell.VMerge > 0 {
+							thirdRowNames[k] = text
+							continue
+						}
+						secondRowNames[k] = text
+						// 横向合并
+						if cell.HMerge > 0 {
+							for j := 1; j <= cell.HMerge; j++ {
+								if secondRowNames[k+j] != "" {
+									continue
+								}
+								secondRowNames[k+j] = text
+							}
+						}
+					}
+				}
+			}
+
+			// 第三行-指标名称下半部分, 指标名称, 指标编码在这一步生成
+			if i == 2 {
+				for k, cell := range cells {
+					text := strings.TrimSpace(cell.String())
+					if k > 0 && text != "" {
+						thirdRowNames[k] = text
+					}
+				}
+			}
+
+			// 数据行
+			if i >= dataRowMin && i <= dataRowMax {
+				for k, cell := range cells {
+					text := strings.TrimSpace(cell.String())
+					if text == "" {
+						continue
+					}
+					// 第一个单元格为地区
+					if k == 0 {
+						if text == "合计" && (excelName == FenweiExcelNameA || excelName == FenweiExcelNameB) {
+							text = "三省合计"
+						}
+						rowProvince[i] = FenweiNewExcelProvinceMapping[text]
+						continue
+					}
+					rowsName := strings.TrimSpace(fmt.Sprint(secondRowNames[k], thirdRowNames[k]))
+					rowsName = strings.ReplaceAll(rowsName, "\n", "")
+					namePrefix := diffNameReplace[rowsName]
+					if namePrefix == "" {
+						namePrefix = rowsName
+					}
+					// 忽略部分名称
+					if utils.InArrayByStr(ignoreIndexName, namePrefix) {
+						continue
+					}
+					indexName := fmt.Sprintf("%s%s%s", rowProvince[i], namePrefix, indexNameSuffix)
+					//fmt.Printf("k: %d, %s\n", k, indexName)
+					name := strings.ReplaceAll(indexName, "/", "")
+					var middle, suffix string
+					for _, p := range FenweiProvinces {
+						// 此处山西其他可能会被错误的给鉴别为山西, 所以优先鉴别一下山西其他
+						if strings.Contains(name, "山西其他") {
+							middle = utils.GetFullPingYin("山西其他")
+							name = strings.ReplaceAll(name, p, "")
+							break
+						}
+						if strings.Contains(name, p) {
+							middle = utils.GetFullPingYin(p)
+							name = strings.ReplaceAll(name, p, "")
+							break
+						}
+					}
+					if middle == "" {
+						utils.FileLog.Info(fmt.Sprintf("指标名称转换编码有误, IndexName: %s", indexName))
+						continue
+					}
+					suffix = utils.GetFirstPingYin(name)
+					indexCode := fmt.Sprint(FenweiIndexNamePrefix, middle, suffix)
+
+					// 根据转换的编码, 匹配存量指标, 无则忽略
+					originIndex := indexMapping[indexCode]
+					if originIndex.FenweiIndexId <= 0 {
+						utils.FileLog.Info(fmt.Sprintf("无对应存量指标, IndexName: %s, IndexCode: %s", indexName, indexCode))
+						continue
+					}
+					indexKey := fmt.Sprintf("%d-%d", i, k)
+					if indexColIndex[indexKey] == nil {
+						indexColIndex[indexKey] = new(models.FenweiExcelIndex)
+						indexColIndex[indexKey].TerminalCode = utils.TerminalCode
+						indexColIndex[indexKey].ClassifyId = originIndex.ClassifyId
+						indexColIndex[indexKey].Frequency = originIndex.Frequency
+						indexColIndex[indexKey].Unit = originIndex.Unit
+						indexColIndex[indexKey].IndexName = indexName
+						indexColIndex[indexKey].IndexCode = indexCode
+						indexColIndex[indexKey].ExcelDataMap = make(map[string]string)
+						indexColIndex[indexKey].ExcelDataMap[dataDate] = text
+					}
+				}
+			}
+		}
+
+		// 只读取第一个sheet
+		break
+	}
+
+	for _, v := range indexColIndex {
+		if v.IndexCode == "" {
+			continue
+		}
+		indexes = append(indexes, v)
+	}
+	return
+}

+ 153 - 0
services/commodity_coal_coastal.go → services/commodity_coal.go

@@ -483,3 +483,156 @@ func Inland(path string) (err error) {
 
 	return
 }
+
+func Mtjh(path string) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshDataFromCoalMtjh  Err:" + err.Error())
+			utils.FileLog.Info(fmt.Sprintf("RefreshDataFromCoalMtjh, Err: %s", err))
+		}
+	}()
+	//path = "/Users/xi/Desktop/煤炭江湖数据定制化服务——中国主流港口煤炭库存20231129.xlsx"
+
+	var xlFile *xlsx.File
+	exist, err := PathExists(path)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	if exist {
+		xlFile, err = xlsx.OpenFile(path)
+		if err != nil {
+			fmt.Println("OpenFile err:", err)
+			return
+		}
+	} else {
+		fmt.Println("Not Exist")
+		return
+	}
+
+	sheetDatas := make([]models.SheetData, 0)
+	for i, sheet := range xlFile.Sheets {
+		if i > 0 {
+			break
+		}
+		data := sheet
+		sheetData := models.SheetData{
+			Name:     data.Name,
+			MaxRow:   data.MaxRow,
+			MaxCol:   data.MaxCol,
+			Hidden:   data.Hidden,
+			Selected: data.Selected,
+		}
+		rows := make([]models.Row, 0)
+		for _, v := range data.Rows {
+			cells := make([]models.Cell, 0)
+			for _, cell := range v.Cells {
+				cells = append(cells, models.Cell{
+					Value: cell.String(),
+				})
+			}
+			row := models.Row{
+				Cells: cells,
+			}
+			rows = append(rows, row)
+		}
+		sheetData.Rows = rows
+		sheetDatas = append(sheetDatas, sheetData)
+	}
+
+	params := make(map[string]interface{})
+	params["SheetData"] = sheetDatas
+	result, e := PostEdbLib(params, utils.LIB_ROUTE_COAL_MINE_MTJH)
+	if e != nil {
+		b, _ := json.Marshal(params)
+		fmt.Println(e)
+		utils.FileLog.Info(fmt.Sprintf("PostEdbLib err: %s, params: %s", e.Error(), string(b)))
+		return
+	}
+	resp := new(models.BaseEdbLibResponse)
+	if e := json.Unmarshal(result, &resp); e != nil {
+		utils.FileLog.Info(fmt.Sprintf("json.Unmarshal err: %s", e))
+		return
+	}
+	if resp.Ret != 200 {
+		utils.FileLog.Info(fmt.Sprintf("Msg: %s, ErrMsg: %s", resp.Msg, resp.ErrMsg))
+		return
+	}
+
+	return
+}
+
+func Firm(path string) (err error)  {
+	defer func() {
+		if err != nil {
+			fmt.Println("RefreshDataFromCoalFirm  Err:" + err.Error())
+			utils.FileLog.Info(fmt.Sprintf("RefreshDataFromCoalFirm, Err: %s", err))
+		}
+	}()
+	//path = "/Users/xi/Desktop/煤炭江湖数据定制化服务——中国主流港口煤炭库存20231129.xlsx"
+
+	var xlFile *xlsx.File
+	exist, err := PathExists(path)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	if exist {
+		xlFile, err = xlsx.OpenFile(path)
+		if err != nil {
+			fmt.Println("OpenFile err:", err)
+			return
+		}
+	} else {
+		fmt.Println("Not Exist")
+		return
+	}
+
+	sheetDatas := make([]models.SheetData, 0)
+	for _, sheet := range xlFile.Sheets {
+		data := sheet
+		sheetData := models.SheetData{
+			Name:     data.Name,
+			MaxRow:   data.MaxRow,
+			MaxCol:   data.MaxCol,
+			Hidden:   data.Hidden,
+			Selected: data.Selected,
+		}
+		rows := make([]models.Row, 0)
+		for _, v := range data.Rows {
+			cells := make([]models.Cell, 0)
+			for _, cell := range v.Cells {
+				cells = append(cells, models.Cell{
+					Value: cell.String(),
+				})
+			}
+			row := models.Row{
+				Cells: cells,
+			}
+			rows = append(rows, row)
+		}
+		sheetData.Rows = rows
+		sheetDatas = append(sheetDatas, sheetData)
+	}
+
+	params := make(map[string]interface{})
+	params["SheetData"] = sheetDatas
+	result, e := PostEdbLib(params, utils.LIB_ROUTE_COAL_MINE_FIRM)
+	if e != nil {
+		b, _ := json.Marshal(params)
+		fmt.Println(e)
+		utils.FileLog.Info(fmt.Sprintf("PostEdbLib err: %s, params: %s", e.Error(), string(b)))
+		return
+	}
+	resp := new(models.BaseEdbLibResponse)
+	if e := json.Unmarshal(result, &resp); e != nil {
+		utils.FileLog.Info(fmt.Sprintf("json.Unmarshal err: %s", e))
+		return
+	}
+	if resp.Ret != 200 {
+		utils.FileLog.Info(fmt.Sprintf("Msg: %s, ErrMsg: %s", resp.Msg, resp.ErrMsg))
+		return
+	}
+
+	return
+}

+ 67 - 0
services/fenwei_watch.go

@@ -0,0 +1,67 @@
+package services
+
+import (
+	"context"
+	"eta/eta_data_analysis/utils"
+	"fmt"
+	"io/fs"
+	"os"
+	"path/filepath"
+	"sync"
+)
+
+// HandleExcelFilePathMutex 创建一个互斥锁
+var HandleExcelFilePathMutex sync.Mutex
+
+func FenweiReadWatchIndexFile(context.Context) (err error) {
+	defer func() {
+		if err != nil {
+			fmt.Println("FenweiReadWatchIndexFile Err:" + err.Error())
+			utils.FileLog.Info(fmt.Sprintf("FenweiReadWatchIndexFile Err: %s", err.Error()))
+		}
+	}()
+	if utils.FenweiFileDir == "" {
+		utils.FileLog.Info("文件目录未配置")
+		return
+	}
+
+	// 上一个监听未结束时不执行
+	HandleExcelFilePathMutex.Lock()
+	defer HandleExcelFilePathMutex.Unlock()
+	//fmt.Println("FenweiFileDir: ", utils.FenweiFileDir)
+
+	err = filepath.Walk(utils.FenweiFileDir, func(path string, info fs.FileInfo, e error) error {
+		if e != nil {
+			err = fmt.Errorf("walk err: %s", e.Error())
+			return err
+		}
+		if info.IsDir() {
+			return nil
+		}
+		if path == "" {
+			return nil
+		}
+
+		//fmt.Println("path", path)
+		e = AnalysisFenweiNewExcel(path)
+		if e != nil {
+			err = fmt.Errorf("AnalysisFenweiNewExcel err: %s", e.Error())
+			return err
+		}
+
+		// 移动文件至已处理目录
+		e = utils.CreateDirIfNotExists(utils.FenweiOldFileDir)
+		if e != nil {
+			err = fmt.Errorf("CreateDirIfNotExists err: %s", e.Error())
+			return err
+		}
+		destPath := filepath.Join(utils.FenweiOldFileDir, info.Name())
+		e = os.Rename(path, destPath)
+		if e != nil {
+			err = fmt.Errorf("file move err: %s", e.Error())
+			return err
+		}
+		return nil
+	})
+	return
+}

+ 19 - 0
services/mail_attachment.go

@@ -0,0 +1,19 @@
+package services
+
+import (
+	"context"
+	"eta/eta_data_analysis/utils"
+	"fmt"
+	"os/exec"
+)
+
+func MailAttachment(context.Context) (err error)  {
+	cmd := exec.Command(utils.CoalMailAttachmentPythonVersion, utils.CoalMailAttachmentScriptPath)
+	outputByte, err := cmd.Output()
+	fmt.Println("start")
+	if err != nil {
+		return
+	}
+	fmt.Println(string(outputByte))
+	return
+}

+ 58 - 0
services/mtjh_watch.go

@@ -0,0 +1,58 @@
+package services
+
+import (
+	"eta/eta_data_analysis/utils"
+	"fmt"
+	"github.com/patrickmn/go-cache"
+	"io/fs"
+	"os"
+	"path/filepath"
+	"strings"
+	"syscall"
+	"time"
+)
+
+func mtjhWatch() {
+	fmt.Println("mtjhWatch start")
+	var err error
+	defer func() {
+		if err != nil {
+			fmt.Println("mtjhWatch Err:" + err.Error())
+		}
+	}()
+	var cacheClient *cache.Cache
+	if cacheClient == nil {
+		cacheClient = cache.New(365*24*time.Hour, 365*24*time.Hour)
+	}
+	err = filepath.Walk(utils.MtjhFilePath, func(path string, info fs.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+		if !info.IsDir() {
+			fileInfo, err := os.Stat(path)
+			if err != nil {
+				fmt.Println("os.Stat:", err.Error())
+			}
+			winFileAttr := fileInfo.Sys().(*syscall.Win32FileAttributeData)
+			modifyTimeStr := utils.SecondToTime(winFileAttr.LastWriteTime.Nanoseconds() / 1e9).Format(utils.FormatDateTime)
+
+			existModifyTime, ok := cacheClient.Get(path)
+			if ok {
+				existModifyTimeStr := existModifyTime.(string)
+				if existModifyTimeStr != modifyTimeStr {
+					if strings.Contains(path, "煤炭江湖") {
+						err = Mtjh(path)
+					}
+				}
+			} else {
+				if strings.Contains(path, "煤炭江湖") {
+					err = Mtjh(path)
+				}
+			}
+			cacheClient.Delete(path)
+			cacheClient.Set(path, modifyTimeStr, 24*time.Hour)
+		}
+		return nil
+	})
+}
+

+ 29 - 1
services/task.go

@@ -34,7 +34,6 @@ func Task() {
 
 		yongyiDownloadWeekly := task.NewTask("YongyiDownloadWeekly", "0 30 17-23 * * *", YongyiDownloadWeekyly)
 		task.AddTask("涌益咨询周度指标下载", yongyiDownloadWeekly)
-		task.StartTask()
 	}
 
 	if utils.CoalMineOpen == "1" {
@@ -48,6 +47,31 @@ func Task() {
 		c.Start()
 	}
 
+	// 汾渭数据
+	if utils.FenweiOpen == "1" {
+		// 每5分钟检测一次目录是否有新文件
+		fenWeiReadWatchIndexFile := task.NewTask("fenWeiReadWatchIndexFile", "0 */5 * * * *", FenweiReadWatchIndexFile)
+		task.AddTask("汾渭数据指标文件检测", fenWeiReadWatchIndexFile)
+	}
+
+	if utils.MtjhOpen == "1" {
+		c := cron.New(cron.WithSeconds())
+		//每2分钟检测一次指标文件是否更新
+		_, err := c.AddFunc("0 */2 * * * *", mtjhWatch)
+		if err != nil {
+			fmt.Println("watch.mtjhWatch err" + err.Error())
+			utils.FileLog.Info("watch.mtjhWatch err" + err.Error())
+		}
+		c.Start()
+	}
+
+	if utils.CoalMailAttachmentOpen == "1" {
+		mailAttachment := task.NewTask("MailAttachment", utils.CoalMailAttachmentTime, MailAttachment)
+		task.AddTask("启动获取邮件附件脚本", mailAttachment)
+	}
+
+	task.StartTask()
+
 	fmt.Println("task end")
 }
 
@@ -91,6 +115,8 @@ func ReadWatchIndexFile() {
 						err = CoastalHistory(path)
 						time.Sleep(time.Second * 10)
 						err = InlandHistory(path)
+					} else if strings.Contains(path, "分企业煤炭产量旬度数据") {
+						err = Firm(path)
 					}
 				}
 			} else {
@@ -106,6 +132,8 @@ func ReadWatchIndexFile() {
 					err = CoastalHistory(path)
 					time.Sleep(time.Second * 10)
 					err = InlandHistory(path)
+				} else if strings.Contains(path, "分企业煤炭产量旬度数据") {
+					err = Firm(path)
 				}
 			}
 			cacheClient.Delete(path)

+ 21 - 0
utils/common.go

@@ -1237,3 +1237,24 @@ func SecondToTime(sec int64) time.Time {
 	return time.Unix(sec, 0)
 }
 
+// CreateDirIfNotExists 目录是否存在
+func CreateDirIfNotExists(directoryPath string) error {
+	// 检查目录是否存在
+	_, err := os.Stat(directoryPath)
+	if os.IsNotExist(err) {
+		// 目录不存在,创建目录
+		err := os.MkdirAll(directoryPath, 0755)
+		if err != nil {
+			return fmt.Errorf("failed to create directory: %v", err)
+		}
+		fmt.Printf("Directory '%s' created successfully.\n", directoryPath)
+	} else if err != nil {
+		// 发生其他错误
+		return fmt.Errorf("failed to check directory: %v", err)
+	} else {
+		// 目录已存在
+		//fmt.Printf("Directory '%s' already exists.\n", directoryPath)
+	}
+
+	return nil
+}

+ 39 - 2
utils/config.go

@@ -44,8 +44,26 @@ var (
 
 // 中国煤炭网
 var (
-	CoalMineFilePath string //excel文件地址
-	CoalMineOpen     string //是否配置涌益生猪数据源,1已配置
+	CoalMineFilePath                string //excel文件地址
+	CoalMineOpen                    string //是否配置中国煤炭网数据源,1已配置
+	CoalMailAttachmentScriptPath    string // 获取邮件附件的脚本目录
+	CoalMailAttachmentOpen          string // 获取邮件附件功能,1已配置
+	CoalMailAttachmentTime          string // 获取邮件附件功能时间
+	CoalMailAttachmentPythonVersion string // 获取邮件附件功能python版本
+)
+
+
+// 汾渭煤炭
+var (
+	FenweiFileDir    string // excel文件目录
+	FenweiOldFileDir string // 已读取过的excel文件目录
+	FenweiOpen       string // 是否配置汾渭数据源
+)
+
+// 煤炭江湖
+var (
+	MtjhFilePath string //excel文件地址
+	MtjhOpen     string //是否配置煤炭江湖数据源,1已配置
 )
 
 var TerminalCode string
@@ -92,11 +110,30 @@ func init() {
 		YongyiFilePath = config["yongyi_file_path"]
 		YongyiOpen = config["yongyi_open"]
 	}
+
 	//中国煤炭网文件夹配置
 	{
 		CoalMineFilePath = config["coal_mine_file_path"]
 		CoalMineOpen = config["coal_mine_open"]
+		CoalMailAttachmentScriptPath = config["coal_mail_attachment_script_path"]
+		CoalMailAttachmentOpen = config["coal_mail_attachment_open"]
+		CoalMailAttachmentTime = config["coal_mail_attachment_time"]
+		CoalMailAttachmentPythonVersion = config["coal_mail_attachment_python_version"]
 	}
+
+	// 汾渭配置
+	{
+		FenweiOpen = config["fenwei_open"]
+		FenweiFileDir = config["fenwei_file_dir"]
+		FenweiOldFileDir = config["fenwei_old_file_dir"]
+	}
+
+	//煤炭江湖文件夹配置
+	{
+		MtjhFilePath = config["mtjh_file_path"]
+		MtjhOpen = config["mtjh_open"]
+	}
+
 	TerminalCode = config["terminal_code"]
 }
 

+ 59 - 51
utils/constants.go

@@ -15,7 +15,7 @@ const (
 	FormatYearMonthUnSpace     = "200601"                  //年月的日期格式
 	PageSize15                 = 15                        //列表页每页数据量
 	FormatDate1                = "2006/1/02"               //日期格式
-	FormatDateYearMonthDay     = "2006年01月02日"             //日期格式
+	FormatDateYearMonthDay     = "2006年01月02日"          //日期格式
 	FormatDatePoint            = "2006.01.02"              //日期格式
 	PageSize5                  = 5
 	PageSize10                 = 10
@@ -100,76 +100,76 @@ const (
 
 // 指标来源的中文展示
 const (
-	DATA_SOURCE_NAME_THS                                  = `同花顺`               //同花顺
-	DATA_SOURCE_NAME_WIND                                 = `wind`              //wind
-	DATA_SOURCE_NAME_PB                                   = `彭博`                //彭博
+	DATA_SOURCE_NAME_THS                                  = `同花顺`                //同花顺
+	DATA_SOURCE_NAME_WIND                                 = `wind`                  //wind
+	DATA_SOURCE_NAME_PB                                   = `彭博`                  //彭博
 	DATA_SOURCE_NAME_CALCULATE                            = `指标运算`              //指标运算
-	DATA_SOURCE_NAME_CALCULATE_LJZZY                      = `累计值转月值`            //累计值转月
-	DATA_SOURCE_NAME_CALCULATE_TBZ                        = `同比值`               //同比值
-	DATA_SOURCE_NAME_CALCULATE_TCZ                        = `同差值`               //同差值
-	DATA_SOURCE_NAME_CALCULATE_NSZYDPJJS                  = `N数值移动平均计算`         //N数值移动平均计算
+	DATA_SOURCE_NAME_CALCULATE_LJZZY                      = `累计值转月值`          //累计值转月
+	DATA_SOURCE_NAME_CALCULATE_TBZ                        = `同比值`                //同比值
+	DATA_SOURCE_NAME_CALCULATE_TCZ                        = `同差值`                //同差值
+	DATA_SOURCE_NAME_CALCULATE_NSZYDPJJS                  = `N数值移动平均计算`     //N数值移动平均计算
 	DATA_SOURCE_NAME_MANUAL                               = `手工数据`              //手工指标
-	DATA_SOURCE_NAME_LZ                                   = `隆众`                //隆众
-	DATA_SOURCE_NAME_YS                                   = `SMM`               //有色
-	DATA_SOURCE_NAME_CALCULATE_HBZ                        = `环比值`               //环比值->12
-	DATA_SOURCE_NAME_CALCULATE_HCZ                        = `环差值`               //环差值->13
-	DATA_SOURCE_NAME_CALCULATE_BP                         = `升频`                //变频,2023-2-10 13:56:01调整为"升频"->14
-	DATA_SOURCE_NAME_GL                                   = `钢联`                //钢联->15
-	DATA_SOURCE_NAME_ZZ                                   = `郑商所`               //郑商所->16
-	DATA_SOURCE_NAME_DL                                   = `大商所`               //大商所->17
-	DATA_SOURCE_NAME_SH                                   = `上期所`               //上期所->18
-	DATA_SOURCE_NAME_CFFEX                                = `中金所`               //中金所->19
+	DATA_SOURCE_NAME_LZ                                   = `隆众`                  //隆众
+	DATA_SOURCE_NAME_YS                                   = `SMM`                   //有色
+	DATA_SOURCE_NAME_CALCULATE_HBZ                        = `环比值`                //环比值->12
+	DATA_SOURCE_NAME_CALCULATE_HCZ                        = `环差值`                //环差值->13
+	DATA_SOURCE_NAME_CALCULATE_BP                         = `升频`                  //变频,2023-2-10 13:56:01调整为"升频"->14
+	DATA_SOURCE_NAME_GL                                   = `钢联`                  //钢联->15
+	DATA_SOURCE_NAME_ZZ                                   = `郑商所`                //郑商所->16
+	DATA_SOURCE_NAME_DL                                   = `大商所`                //大商所->17
+	DATA_SOURCE_NAME_SH                                   = `上期所`                //上期所->18
+	DATA_SOURCE_NAME_CFFEX                                = `中金所`                //中金所->19
 	DATA_SOURCE_NAME_SHFE                                 = `上期能源`              //上期能源->20
-	DATA_SOURCE_NAME_GIE                                  = `欧洲天然气`             //欧洲天然气->21
+	DATA_SOURCE_NAME_GIE                                  = `欧洲天然气`            //欧洲天然气->21
 	DATA_SOURCE_NAME_CALCULATE_TIME_SHIFT                 = `时间移位`              //时间移位->22
 	DATA_SOURCE_NAME_CALCULATE_ZJPJ                       = `直接拼接`              //直接拼接->23
-	DATA_SOURCE_NAME_CALCULATE_LJZTBPJ                    = `累计值同比拼接`           //累计值同比拼接->24
-	DATA_SOURCE_NAME_LT                                   = `路透`                //路透->25
-	DATA_SOURCE_NAME_COAL                                 = `中国煤炭网`             //煤炭网->26
+	DATA_SOURCE_NAME_CALCULATE_LJZTBPJ                    = `累计值同比拼接`        //累计值同比拼接->24
+	DATA_SOURCE_NAME_LT                                   = `路透`                  //路透->25
+	DATA_SOURCE_NAME_COAL                                 = `中国煤炭网`            //煤炭网->26
 	DATA_SOURCE_NAME_PYTHON                               = `代码运算`              //python代码->27
 	DATA_SOURCE_NAME_PB_FINANCE                           = `彭博财务`              //彭博财务数据->28
-	DATA_SOURCE_NAME_GOOGLE_TRAVEL                        = `our world in data` //谷歌出行数据->29
+	DATA_SOURCE_NAME_GOOGLE_TRAVEL                        = `our world in data`     //谷歌出行数据->29
 	DATA_SOURCE_NAME_PREDICT                              = `预测指标`              //普通预测指标->30
-	DATA_SOURCE_NAME_PREDICT_CALCULATE                    = `预测指标运算`            //预测指标运算->31
+	DATA_SOURCE_NAME_PREDICT_CALCULATE                    = `预测指标运算`          //预测指标运算->31
 	DATA_SOURCE_NAME_PREDICT_CALCULATE_TBZ                = `预测同比`              //预测指标 - 同比值->32
 	DATA_SOURCE_NAME_PREDICT_CALCULATE_TCZ                = `预测同差`              //预测指标 - 同差值->33
 	DATA_SOURCE_NAME_MYSTEEL_CHEMICAL                     = `钢联化工`              //钢联化工->34
 	DATA_SOURCE_NAME_CALCULATE_CJJX                       = `超季节性`              //超季节性->35
-	DATA_SOURCE_NAME_EIA_STEO                             = `EIA STERO报告`       //eia stero报告->36
+	DATA_SOURCE_NAME_EIA_STEO                             = `EIA STERO报告`         //eia stero报告->36
 	DATA_SOURCE_NAME_CALCULATE_NHCC                       = `拟合残差`              //计算指标(拟合残差)->37
-	DATA_SOURCE_NAME_COM_TRADE                            = `UN`                //联合国商品贸易数据->38
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_NSZYDPJJS          = `预测N数值移动平均计算`       //预测指标 - N数值移动平均计算 -> 39
+	DATA_SOURCE_NAME_COM_TRADE                            = `UN`                    //联合国商品贸易数据->38
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_NSZYDPJJS          = `预测N数值移动平均计算` //预测指标 - N数值移动平均计算 -> 39
 	DATA_SOURCE_NAME_CALCULATE_ADJUST                     = `数据调整`              //数据调整->40
-	DATA_SOURCE_NAME_SCI                                  = `SCI`               //卓创数据(红桃三)->41
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZZY              = `预测累计值转月值`          //预测指标 - 累计值转月->42
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_HBZ                = `预测环比值`             //预测指标 - 环比值->43
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_HCZ                = `预测环差值`             //预测指标 - 环差值->44
+	DATA_SOURCE_NAME_SCI                                  = `SCI`                   //卓创数据(红桃三)->41
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZZY              = `预测累计值转月值`      //预测指标 - 累计值转月->42
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_HBZ                = `预测环比值`            //预测指标 - 环比值->43
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_HCZ                = `预测环差值`            //预测指标 - 环差值->44
 	DATA_SOURCE_NAME_PREDICT_CALCULATE_BP                 = `预测升频`              //预测指标 - 升频->45
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_TIME_SHIFT         = `预测时间移位`            //预测指标 - 时间移位->46
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_ZJPJ               = `预测直接拼接`            //预测指标 - 直接拼接->47
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZTBPJ            = `预测累计值同比拼接`         //预测指标 - 累计值同比拼接->48
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_CJJX               = `预测超季节性`            //预测指标 - 超季节性->49
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_NHCC               = `预测拟合残差`            //预测指标 - 计算指标(拟合残差)->50
-	DATA_SOURCE_NAME_CALCULATE_JP                         = `降频`                //降频->51
-	DATA_SOURCE_NAME_CALCULATE_NH                         = `年化`                //年化->52
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_TIME_SHIFT         = `预测时间移位`          //预测指标 - 时间移位->46
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_ZJPJ               = `预测直接拼接`          //预测指标 - 直接拼接->47
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZTBPJ            = `预测累计值同比拼接`    //预测指标 - 累计值同比拼接->48
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_CJJX               = `预测超季节性`          //预测指标 - 超季节性->49
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_NHCC               = `预测拟合残差`          //预测指标 - 计算指标(拟合残差)->50
+	DATA_SOURCE_NAME_CALCULATE_JP                         = `降频`                  //降频->51
+	DATA_SOURCE_NAME_CALCULATE_NH                         = `年化`                  //年化->52
 	DATA_SOURCE_NAME_CALCULATE_KSZS                       = `扩散指数`              //扩散指数->53
 	DATA_SOURCE_NAME_PREDICT_CALCULATE_JP                 = `预测降频`              //预测指标 - 计算指标(降频)->54
 	DATA_SOURCE_NAME_PREDICT_CALCULATE_NH                 = `预测年化`              //预测指标 - 计算指标(年化)->55
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_KSZS               = `预测扩散指数`            //预测指标 - 计算指标(扩散指数)->56
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_KSZS               = `预测扩散指数`          //预测指标 - 计算指标(扩散指数)->56
 	DATA_SOURCE_NAME_BAIINFO                              = `百川盈孚`              //百川盈孚 ->57
 	DATA_SOURCE_NAME_STOCK_PLANT                          = `存量装置`              //存量装置 ->58
-	DATA_SOURCE_NAME_CALCULATE_CORRELATION                = `相关性计算`             //相关性计算->59
-	DATA_SOURCE_NAME_NATIONAL_STATISTICS                  = `国家统计局`             //国家统计局->60
-	DATA_SOURCE_NAME_CALCULATE_LJZZJ                      = `累计值转季值`            //累计值转季 -> 61
-	DATA_SOURCE_NAME_CALCULATE_LJZ                        = `累计值`               //累计值 -> 62
-	DATA_SOURCE_NAME_CALCULATE_LJZNCZJ                    = `年初至今累计值`           //累计值(年初至今) -> 63
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZZJ              = `预测累计值转季值`          //预测指标 - 累计值转季->64
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZ                = `预测累计值`             //预测指标 - 累计值 -> 65
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZNCZJ            = `预测年初至今累计值`         //预测指标 - 累计值(年初至今) -> 66
-	DATA_SOURCE_NAME_CALCULATE_STANDARD_DEVIATION         = `标准差`               //标准差->67
-	DATA_SOURCE_NAME_CALCULATE_PERCENTILE                 = `百分位`               //百分位->68
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_STANDARD_DEVIATION = `预测标准差`             //预测标准差->69
-	DATA_SOURCE_NAME_PREDICT_CALCULATE_PERCENTILE         = `预测百分位`             //预测百分位->70
+	DATA_SOURCE_NAME_CALCULATE_CORRELATION                = `相关性计算`            //相关性计算->59
+	DATA_SOURCE_NAME_NATIONAL_STATISTICS                  = `国家统计局`            //国家统计局->60
+	DATA_SOURCE_NAME_CALCULATE_LJZZJ                      = `累计值转季值`          //累计值转季 -> 61
+	DATA_SOURCE_NAME_CALCULATE_LJZ                        = `累计值`                //累计值 -> 62
+	DATA_SOURCE_NAME_CALCULATE_LJZNCZJ                    = `年初至今累计值`        //累计值(年初至今) -> 63
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZZJ              = `预测累计值转季值`      //预测指标 - 累计值转季->64
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZ                = `预测累计值`            //预测指标 - 累计值 -> 65
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_LJZNCZJ            = `预测年初至今累计值`    //预测指标 - 累计值(年初至今) -> 66
+	DATA_SOURCE_NAME_CALCULATE_STANDARD_DEVIATION         = `标准差`                //标准差->67
+	DATA_SOURCE_NAME_CALCULATE_PERCENTILE                 = `百分位`                //百分位->68
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_STANDARD_DEVIATION = `预测标准差`            //预测标准差->69
+	DATA_SOURCE_NAME_PREDICT_CALCULATE_PERCENTILE         = `预测百分位`            //预测百分位->70
 	DATA_SOURCE_NAME_FUBAO                                = `富宝数据`              //富宝数据->71
 )
 
@@ -239,4 +239,12 @@ const (
 	LIB_ROUTE_COAL_MINE_JSM             = "/coal_mine/jsm"             //jsm三省煤炭网历史数据处理excel数据并入库 数据地址
 	LIB_ROUTE_COAL_MINE_COASTAL         = "/coal_mine/coastal"         //沿海煤炭网历史数据处理excel数据并入库 数据地址
 	LIB_ROUTE_COAL_MINE_INLAND          = "/coal_mine/inland"          //内陆三省煤炭网历史数据处理excel数据并入库 数据地址
+	LIB_ROUTE_COAL_MINE_JSM             = "/coal_mine/jsm"             //jsm三省煤炭网数据处理excel数据并入库 数据地址
+	LIB_ROUTE_COAL_MINE_COASTAL         = "/coal_mine/coastal"         //沿海煤炭网数据处理excel数据并入库 数据地址
+	LIB_ROUTE_COAL_MINE_INLAND          = "/coal_mine/inland"          //内陆三省煤炭网数据处理excel数据并入库 数据地址
+	LIB_ROUTE_COAL_MINE_FIRM            = "/coal_mine/firm"            //分公司旬度煤炭网数据处理excel数据并入库 数据地址
+	LIB_ROUTE_FENWEI_HANDLE             = "fenwei/handle/excel_data"   // 汾渭煤炭excel数据入库接口地址
+	LIB_ROUTE_FENWEI_CLASSIFY           = "fenwei/classify_tree"       // 汾渭煤炭分类接口地址
+	LIB_ROUTE_FENWEI_INDEX_LIST         = "fenwei/base_index_list"     // 汾渭煤炭指标列表接口地址
+	LIB_ROUTE_COAL_MINE_MTJH            = "/mtjh/data"                 //煤炭江湖数据处理excel数据并入库 数据地址
 )