base.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. package service
  2. import (
  3. "context"
  4. "dashoo.cn/opms_libary/multipart"
  5. "encoding/base64"
  6. "fmt"
  7. "github.com/gogf/gf/encoding/gurl"
  8. "github.com/gogf/gf/text/gstr"
  9. "github.com/gogf/gf/util/guid"
  10. "github.com/xuri/excelize/v2"
  11. "io/ioutil"
  12. "log"
  13. "net/http"
  14. "os"
  15. "reflect"
  16. "strings"
  17. "dashoo.cn/opms_libary/myerrors"
  18. "dashoo.cn/opms_libary/request"
  19. "github.com/gogf/gf/container/gmap"
  20. "github.com/gogf/gf/frame/g"
  21. "github.com/gogf/gf/util/gconv"
  22. "github.com/smallnest/rpcx/share"
  23. "dashoo.cn/common_definition/comm_def"
  24. "dashoo.cn/opms_libary/micro_srv"
  25. "github.com/gogf/gf/database/gdb"
  26. "github.com/gogf/gf/os/gtime"
  27. )
  28. var (
  29. // DingTalkSpaceId 钉钉 空间Id。
  30. DingTalkSpaceId = "21077726250"
  31. // CommonUpdateFieldEx UpdateFieldEx 更新过滤字段
  32. CommonUpdateFieldEx = []interface{}{"created_by", "created_name", "created_time"}
  33. UpdateFieldEx = []interface{}{"id", "created_by", "created_name", "created_time"}
  34. )
  35. func Sequence(db gdb.DB, name string) (string, error) {
  36. v, err := db.GetValue("select `nextval`( ? );", name)
  37. if err != nil {
  38. return "", err
  39. }
  40. return v.String(), nil
  41. }
  42. func SequenceYearRest(db gdb.DB, name string) (int, error) {
  43. v, err := db.GetValue("select `next_year_reset_val`( ? );", name)
  44. if err != nil {
  45. return 0, err
  46. }
  47. return v.Int(), nil
  48. }
  49. // SetCreatedInfo 插入数据库时设置创建信息
  50. func SetCreatedInfo(entry interface{}, id int, name string) {
  51. v := reflect.ValueOf(entry)
  52. t := reflect.TypeOf(entry)
  53. if t.Kind() == reflect.Map {
  54. data := entry.(map[string]interface{})
  55. data["created_by"] = id
  56. data["created_name"] = name
  57. data["created_time"] = gtime.Now()
  58. return
  59. }
  60. if t.Kind() == reflect.Ptr {
  61. t = t.Elem()
  62. v = v.Elem()
  63. }
  64. if t.Kind() == reflect.Slice {
  65. }
  66. if t.Kind() != reflect.Struct {
  67. log.Println("Check type error not Struct")
  68. return
  69. }
  70. for i := 0; i < t.NumField(); i++ {
  71. fieldName := t.Field(i).Name
  72. if tag, ok := t.Field(i).Tag.Lookup("orm"); ok {
  73. switch tag {
  74. case "created_by":
  75. v.FieldByName(fieldName).Set(reflect.ValueOf(id))
  76. case "created_name":
  77. v.FieldByName(fieldName).Set(reflect.ValueOf(name))
  78. case "created_time":
  79. v.FieldByName(fieldName).Set(reflect.ValueOf(gtime.Now()))
  80. }
  81. }
  82. }
  83. }
  84. // SetUpdatedInfo 插入数据库时设置修改信息
  85. func SetUpdatedInfo(entry interface{}, id int, name string) {
  86. v := reflect.ValueOf(entry)
  87. t := reflect.TypeOf(entry)
  88. if t.Kind() == reflect.Map {
  89. data := entry.(map[string]interface{})
  90. data["updated_by"] = id
  91. data["updated_name"] = name
  92. data["updated_time"] = gtime.Now()
  93. return
  94. }
  95. if t.Kind() == reflect.Ptr {
  96. t = t.Elem()
  97. v = v.Elem()
  98. }
  99. if t.Kind() != reflect.Struct {
  100. log.Println("Check type error not Struct")
  101. return
  102. }
  103. for i := 0; i < t.NumField(); i++ {
  104. fieldName := t.Field(i).Name
  105. if tag, ok := t.Field(i).Tag.Lookup("orm"); ok {
  106. switch tag {
  107. case "updated_by":
  108. v.FieldByName(fieldName).Set(reflect.ValueOf(id))
  109. case "updated_name":
  110. v.FieldByName(fieldName).Set(reflect.ValueOf(name))
  111. case "updated_time":
  112. v.FieldByName(fieldName).Set(reflect.ValueOf(gtime.Now()))
  113. }
  114. }
  115. }
  116. }
  117. // Div 数字转字母
  118. func Div(Num int) string {
  119. var (
  120. Str string = ""
  121. k int
  122. temp []int //保存转化后每一位数据的值,然后通过索引的方式匹配A-Z
  123. )
  124. //用来匹配的字符A-Z
  125. Slice := []string{"", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
  126. "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
  127. if Num > 26 { //数据大于26需要进行拆分
  128. for {
  129. k = Num % 26 //从个位开始拆分,如果求余为0,说明末尾为26,也就是Z,如果是转化为26进制数,则末尾是可以为0的,这里必须为A-Z中的一个
  130. if k == 0 {
  131. temp = append(temp, 26)
  132. k = 26
  133. } else {
  134. temp = append(temp, k)
  135. }
  136. Num = (Num - k) / 26 //减去Num最后一位数的值,因为已经记录在temp中
  137. if Num <= 26 { //小于等于26直接进行匹配,不需要进行数据拆分
  138. temp = append(temp, Num)
  139. break
  140. }
  141. }
  142. } else {
  143. return Slice[Num]
  144. }
  145. for _, value := range temp {
  146. Str = Slice[value] + Str //因为数据切分后存储顺序是反的,所以Str要放在后面
  147. }
  148. return Str
  149. }
  150. type GetDictReq struct {
  151. DictType string `p:"dictType" v:"required#字典类型不能为空"`
  152. DefaultValue string `p:"defaultValue"`
  153. }
  154. type GetDictLabelByTypeAndValueReq struct {
  155. DictType string `p:"dictType"` //字典类型
  156. DictValue string `p:"dictValue"` //字典标签
  157. }
  158. func baseGetDictDataByType(ctx context.Context, typ string) ([]interface{}, error) {
  159. srv := micro_srv.InitMicroSrvClient("Dict", "micro_srv.auth")
  160. defer srv.Close()
  161. resp := &comm_def.CommonMsg{}
  162. err := srv.Call(ctx, "GetDictDataByType", GetDictReq{
  163. DictType: typ,
  164. }, resp)
  165. if err != nil {
  166. return nil, fmt.Errorf("获取字典 %s %s", typ, err.Error())
  167. }
  168. fmt.Println(resp.Data)
  169. data := resp.Data.(map[string]interface{})["Values"].([]interface{})
  170. fmt.Println(data)
  171. return data, nil
  172. }
  173. func GetDictDataByType(ctx context.Context, typ string) (map[string]string, error) {
  174. data, err := baseGetDictDataByType(ctx, typ)
  175. if err != nil {
  176. return nil, err
  177. }
  178. res := map[string]string{}
  179. for _, i := range data {
  180. info := i.(map[string]interface{})
  181. res[info["DictValue"].(string)] = info["DictLabel"].(string)
  182. }
  183. return res, nil
  184. }
  185. // Find获取一个切片并在其中查找元素。如果找到它,它将返回它的密钥,否则它将返回-1和一个错误的bool。
  186. func FindItem(slice []string, val string) (int, bool) {
  187. for i, item := range slice {
  188. if item == val {
  189. return i, true
  190. }
  191. }
  192. return -1, false
  193. }
  194. // 有序
  195. func GetDictDataTreeByType(ctx context.Context, typ string) (*gmap.ListMap, error) {
  196. data, err := baseGetDictDataByType(ctx, typ)
  197. if err != nil {
  198. return nil, err
  199. }
  200. res := gmap.NewListMap(true)
  201. for _, i := range data {
  202. info := i.(map[string]interface{})
  203. res.Set(info["DictValue"], info["DictLabel"])
  204. }
  205. return res, nil
  206. }
  207. // 根据字典类型和字典值获取字典明细名称
  208. func GetDictLabelByTypeAndValue(ctx context.Context, dictType, value string) (string, error) {
  209. srv := micro_srv.InitMicroSrvClient("Dict", "micro_srv.auth")
  210. defer srv.Close()
  211. resp := &comm_def.CommonMsg{}
  212. err := srv.Call(ctx, "GetDictLabelByTypeAndValue", GetDictLabelByTypeAndValueReq{
  213. DictType: dictType,
  214. DictValue: value,
  215. }, resp)
  216. if err != nil {
  217. g.Log().Error(err)
  218. return value, nil
  219. }
  220. return gconv.String(resp.Data), nil
  221. }
  222. func StringSlicecontains(s []string, ele string) bool {
  223. for _, i := range s {
  224. if i == ele {
  225. return true
  226. }
  227. }
  228. return false
  229. }
  230. // CreateSystemMessage 创建系统消息
  231. func CreateSystemMessage(msg g.MapStrStr) error {
  232. srv := micro_srv.InitMicroSrvClient("SystemMessage", "micro_srv.auth")
  233. defer srv.Close()
  234. resp := &comm_def.CommonMsg{}
  235. tenant := g.Config().GetString("micro_srv.tenant")
  236. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  237. err := srv.Call(ctx, "Create", msg, resp)
  238. if err != nil {
  239. g.Log().Error(err)
  240. return myerrors.MicroCallError("系统创建消息失败")
  241. }
  242. fmt.Println(resp.Data)
  243. return nil
  244. }
  245. type DeptIdReq struct {
  246. DeptId int `json:"dept_id,omitempty"`
  247. Include bool `json:"include,omitempty"`
  248. }
  249. // GetUsersByDept 根据部门获取用户
  250. func GetUsersByDept(ctx context.Context, req *DeptIdReq) (map[string]int, error) {
  251. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  252. defer srv.Close()
  253. resp := &comm_def.CommonMsg{}
  254. err := srv.Call(ctx, "GetUserByDept", req, resp)
  255. if err != nil {
  256. return nil, myerrors.MicroCallError("获取部门下用户失败")
  257. }
  258. if resp.Data == nil {
  259. return nil, myerrors.TipsError("部门不存在")
  260. }
  261. fmt.Println(resp.Data)
  262. data := resp.Data.([]interface{})
  263. fmt.Println(data)
  264. res := map[string]int{}
  265. for _, i := range data {
  266. info := i.(map[string]interface{})
  267. res[info["NickName"].(string)] = gconv.Int(info["Id"])
  268. }
  269. return res, nil
  270. }
  271. type SysUserSearchReq struct {
  272. KeyWords string `json:"keyWords"`
  273. DeptId int `json:"deptId"` //部门id
  274. DeptIds []int //所属部门id数据
  275. Phone string `json:"phone"`
  276. Status string `json:"status"`
  277. Roles []string `json:"roles"`
  278. Posts []string `json:"posts"`
  279. Groups []string `json:"groups"`
  280. request.PageReq
  281. }
  282. // GetUsersByRoleCode 根据角色编码获取用户
  283. func GetUsersByRoleCode(ctx context.Context, roleCode []string, pageSize ...int) (map[string]int, error) {
  284. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  285. defer srv.Close()
  286. resp := &comm_def.CommonMsg{}
  287. req := &SysUserSearchReq{Roles: roleCode, Status: "10"}
  288. if len(pageSize) > 0 {
  289. req.PageSize = pageSize[0]
  290. }
  291. err := srv.Call(ctx, "GetList", req, resp)
  292. if err != nil {
  293. return nil, myerrors.MicroCallError("根据角色编码获取用户失败")
  294. }
  295. if resp.Data == nil {
  296. return nil, myerrors.TipsError("用户不存在")
  297. }
  298. data := resp.Data.(map[string]interface{})
  299. list := data["list"].([]interface{})
  300. res := map[string]int{}
  301. for _, i := range list {
  302. info := i.(map[string]interface{})
  303. res[info["NickName"].(string)] = gconv.Int(info["Id"])
  304. }
  305. return res, nil
  306. }
  307. // GetUserListByRoleCode 根据角色编码获取用户列表
  308. func GetUserListByRoleCode(ctx context.Context, roleCode []string, pageSize ...int) ([]map[string]interface{}, error) {
  309. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  310. defer srv.Close()
  311. resp := &comm_def.CommonMsg{}
  312. req := &SysUserSearchReq{Roles: roleCode, Status: "10"}
  313. if len(pageSize) > 0 {
  314. req.PageSize = pageSize[0]
  315. }
  316. err := srv.Call(ctx, "GetList", req, resp)
  317. if err != nil {
  318. return nil, myerrors.MicroCallError("根据角色编码获取用户失败")
  319. }
  320. if resp.Data == nil {
  321. return nil, myerrors.TipsError("用户不存在")
  322. }
  323. data := resp.Data.(map[string]interface{})
  324. list := data["list"].([]interface{})
  325. var res []map[string]interface{}
  326. for _, i := range list {
  327. info := i.(map[string]interface{})
  328. data := map[string]interface{}{
  329. "Id": gconv.Int(info["Id"]),
  330. "NickName": info["NickName"].(string),
  331. }
  332. res = append(res, data)
  333. }
  334. return res, nil
  335. }
  336. // 获取用户权限
  337. func GetUserDataScope(userId int) (g.Map, error) {
  338. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  339. defer srv.Close()
  340. req := &comm_def.IdReq{Id: int64(userId)}
  341. resp := &comm_def.CommonMsg{}
  342. tenant := g.Config().GetString("micro_srv.tenant")
  343. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  344. err := srv.Call(ctx, "GetDataScope", req, resp)
  345. if err != nil || resp.Data == nil {
  346. g.Log().Error(err)
  347. return nil, myerrors.MicroCallError("获取用户权限失败")
  348. }
  349. return resp.Data.(g.Map), nil
  350. }
  351. // 跟进发送邮件消息
  352. func GSendMail(msg g.MapStrStr) error {
  353. srv := micro_srv.InitMicroSrvClient("Message", "micro_srv.auth")
  354. defer srv.Close()
  355. resp := &comm_def.CommonMsg{}
  356. tenant := g.Config().GetString("micro_srv.tenant")
  357. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  358. err := srv.Call(ctx, "SendMail", msg, resp)
  359. if err != nil {
  360. g.Log().Error(err)
  361. return myerrors.MicroCallError("项目未跟进发送邮件提醒失败")
  362. }
  363. fmt.Println(resp.Data)
  364. return nil
  365. }
  366. func ColumnInt(m *gdb.Model, name string) ([]int, error) {
  367. v, err := m.Fields(name).Array()
  368. if err != nil {
  369. return nil, err
  370. }
  371. res := []int{}
  372. for _, i := range v {
  373. res = append(res, i.Int())
  374. }
  375. return res, nil
  376. }
  377. func ColumnString(m *gdb.Model, name string) ([]string, error) {
  378. v, err := m.Fields(name).Array()
  379. if err != nil {
  380. return nil, err
  381. }
  382. res := []string{}
  383. for _, i := range v {
  384. res = append(res, i.String())
  385. }
  386. return res, nil
  387. }
  388. func StringsContains(s []string, ele string) bool {
  389. for _, i := range s {
  390. if i == ele {
  391. return true
  392. }
  393. }
  394. return false
  395. }
  396. func BuildProjectPermissionWhere(userId int, roles []string) string {
  397. allVisibleRoles := []string{
  398. "GeneralManager",
  399. "SalesDirector",
  400. "ResearchAndDevelopmentDirector",
  401. "ResearchAndDevelopmentSupervisor",
  402. "PersonnelDirector",
  403. "SysAdmin",
  404. "GeneralManagerAssistant",
  405. }
  406. for _, role := range allVisibleRoles {
  407. if StringsContains(roles, role) {
  408. return ""
  409. }
  410. }
  411. conditions := []string{}
  412. if StringsContains(roles, "RegionalManager") {
  413. conditions = append(conditions, fmt.Sprintf(
  414. "EXISTS (SELECT 1 FROM base_region_auth WHERE user_id = %d AND city_id = sales_region_id)",
  415. userId,
  416. ))
  417. }
  418. if StringsContains(roles, "SalesEngineer") {
  419. conditions = append(conditions, fmt.Sprintf("sales_user_id = %d", userId))
  420. }
  421. if StringsContains(roles, "ProjectManager") ||
  422. StringsContains(roles, "ProjectDeliveryManager") {
  423. conditions = append(conditions, fmt.Sprintf("delivery_user_id = %d", userId))
  424. }
  425. if StringsContains(roles, "OperationsEngineer") {
  426. conditions = append(conditions, fmt.Sprintf("attribute4 = %d", userId))
  427. }
  428. if len(conditions) > 0 {
  429. return fmt.Sprintf("(%s)", strings.Join(conditions, " OR "))
  430. }
  431. return "1=0"
  432. }
  433. func UserIdByRoles(db gdb.DB, roles ...string) ([]int, error) {
  434. roleId, err := ColumnInt(db.Table("sys_role").Where("role_key in (?)", roles), "id")
  435. if err != nil {
  436. return nil, err
  437. }
  438. return ColumnInt(db.Table("sys_user_role").Where("role_id in (?)", roleId), "user_id")
  439. }
  440. func UserDingtalkUid(db gdb.DB, id int) (string, error) {
  441. v, err := db.Table("sys_user").Where("id = ?", id).Fields("dingtalk_uid").Value()
  442. if err != nil {
  443. return "", err
  444. }
  445. uid := v.String()
  446. if uid == "" {
  447. return "", fmt.Errorf("没有找到 %d 的钉钉用户id", id)
  448. }
  449. return uid, nil
  450. }
  451. func SliceIntDeduplication(elems []int) []int {
  452. emap := map[int]struct{}{}
  453. for _, i := range elems {
  454. emap[i] = struct{}{}
  455. }
  456. ret := []int{}
  457. for i := range emap {
  458. ret = append(ret, i)
  459. }
  460. return ret
  461. }
  462. // DownloadTempFile 下载临时文件
  463. func DownloadTempFile(url string) (*multipart.FileHeader, error) {
  464. r, err := http.Get(url)
  465. if err != nil {
  466. g.Log().Error(err)
  467. return nil, err
  468. }
  469. if r.StatusCode != http.StatusOK {
  470. return nil, fmt.Errorf("DownloadFile from %s StatusCode %d", url, r.StatusCode)
  471. }
  472. defer r.Body.Close()
  473. bytes, err := ioutil.ReadAll(r.Body)
  474. if err != nil {
  475. g.Log().Error(err)
  476. return nil, err
  477. }
  478. names := gstr.Split(r.Header.Get("Content-Disposition"), "filename=")
  479. fileName := guid.S()
  480. if len(names) > 1 {
  481. fileName, _ = gurl.Decode(names[1])
  482. fileName = gstr.TrimStr(fileName, `"`)
  483. }
  484. file, err := os.CreateTemp("", fileName)
  485. if err != nil {
  486. g.Log().Error(err)
  487. }
  488. file.Write(bytes)
  489. fmt.Println(file.Name())
  490. fileData := new(multipart.FileHeader)
  491. fileData.FileName = fileName
  492. fileData.FileSize = gconv.Int64(r.Header.Get("Content-Length"))
  493. fileData.File = file
  494. return fileData, nil
  495. }
  496. // getExcelHeader 获取Excel表头
  497. func getExcelHeader(exportStruct interface{}, tag string) ([]string, g.MapStrStr) {
  498. var headerList []string
  499. headerMap := g.MapStrStr{}
  500. reqType := reflect.TypeOf(exportStruct)
  501. if reqType.Kind() == reflect.Ptr {
  502. reqType = reqType.Elem()
  503. }
  504. for i := 0; i < reqType.NumField(); i++ {
  505. fieldName, ok := reqType.Field(i).Tag.Lookup("json")
  506. if !ok {
  507. fieldName = reqType.Field(i).Name
  508. }
  509. if tag, ok := reqType.Field(i).Tag.Lookup(tag); ok {
  510. headerList = append(headerList, tag)
  511. headerMap[tag] = fieldName
  512. }
  513. }
  514. return headerList, headerMap
  515. }
  516. // CommonExportExcel 公共单表导出excel
  517. func CommonExportExcel(ctx context.Context, fileName string, exportStruct interface{}, dataList []map[string]interface{}, handleFunc ...func(map[string]interface{}, string) interface{}) (path string, err error) {
  518. headerList, headerMap := getExcelHeader(exportStruct, "export")
  519. // 转换数据
  520. xlsxFile := excelize.NewFile()
  521. defer xlsxFile.Close()
  522. // 插入表头
  523. if fileName == "" {
  524. fileName = "Sheet1"
  525. }
  526. colStyle, err := xlsxFile.NewStyle(&excelize.Style{
  527. Alignment: &excelize.Alignment{
  528. Horizontal: "center",
  529. Vertical: "center",
  530. WrapText: true,
  531. },
  532. Font: &excelize.Font{
  533. Size: 11,
  534. Family: "宋体",
  535. },
  536. })
  537. headerStyle, err := xlsxFile.NewStyle(&excelize.Style{
  538. Alignment: &excelize.Alignment{
  539. Horizontal: "center",
  540. Vertical: "center",
  541. },
  542. Fill: excelize.Fill{
  543. Type: "pattern",
  544. Color: []string{"#CCE5FF"},
  545. Pattern: 1,
  546. },
  547. Border: []excelize.Border{
  548. {Type: "left", Color: "#000000", Style: 1},
  549. {Type: "top", Color: "#000000", Style: 1},
  550. {Type: "bottom", Color: "#000000", Style: 1},
  551. {Type: "right", Color: "#000000", Style: 1},
  552. },
  553. })
  554. lastColName, err := excelize.ColumnNumberToName(len(headerList))
  555. xlsxFile.SetColStyle("Sheet1", "A:"+lastColName, colStyle)
  556. xlsxFile.SetCellStyle("Sheet1", "A1", lastColName+"1", headerStyle)
  557. xlsxFile.SetRowHeight("Sheet1", 1, 40)
  558. xlsxFile.SetColWidth("Sheet1", "A", lastColName, 20)
  559. handleProcessColIndex := -1
  560. for i, h := range headerList {
  561. if h == "处理过程" {
  562. handleProcessColIndex = i + 1
  563. break
  564. }
  565. }
  566. if handleProcessColIndex > 0 {
  567. handleColName, _ := excelize.ColumnNumberToName(handleProcessColIndex)
  568. xlsxFile.SetColWidth("Sheet1", handleColName, handleColName, 40)
  569. }
  570. xlsxFile.SetSheetName("Sheet1", fileName)
  571. xlsxFile.SetSheetRow(fileName, "A1", &headerList)
  572. if err != nil {
  573. return "", err
  574. }
  575. for k, item := range dataList {
  576. var row []interface{}
  577. for _, h := range headerList {
  578. val := item[headerMap[h]]
  579. if len(handleFunc) > 0 {
  580. val = handleFunc[0](item, headerMap[h])
  581. }
  582. row = append(row, val)
  583. }
  584. xlsxFile.SetSheetRow(fileName, fmt.Sprintf("A%d", k+2), &row)
  585. }
  586. //dir := g.Config().GetString("setting.export-path")
  587. //gfile.Mkdir(dir)
  588. //path = dir + "/" + fileName + gtime.Now().Format("Y-m-d_H-i-s") + ".xlsx"
  589. //// 根据指定路径保存文件
  590. //if err := xlsxFile.SaveAs(path); err != nil {
  591. // g.Log().Error(ctx, err)
  592. //}
  593. buf, err := xlsxFile.WriteToBuffer()
  594. if err != nil {
  595. return "", err
  596. }
  597. path = base64.StdEncoding.EncodeToString(buf.Bytes())
  598. return path, err
  599. }