base.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. package service
  2. import (
  3. "context"
  4. "dashoo.cn/opms_libary/multipart"
  5. "fmt"
  6. "github.com/gogf/gf/encoding/gurl"
  7. "github.com/gogf/gf/text/gstr"
  8. "github.com/gogf/gf/util/guid"
  9. "io/ioutil"
  10. "log"
  11. "net/http"
  12. "os"
  13. "reflect"
  14. "dashoo.cn/opms_libary/myerrors"
  15. "dashoo.cn/opms_libary/request"
  16. "github.com/gogf/gf/container/gmap"
  17. "github.com/gogf/gf/frame/g"
  18. "github.com/gogf/gf/util/gconv"
  19. "github.com/smallnest/rpcx/share"
  20. "dashoo.cn/common_definition/comm_def"
  21. "dashoo.cn/opms_libary/micro_srv"
  22. "github.com/gogf/gf/database/gdb"
  23. "github.com/gogf/gf/os/gtime"
  24. )
  25. var (
  26. // DingTalkSpaceId 钉钉 空间Id。
  27. DingTalkSpaceId = "21077726250"
  28. // CommonUpdateFieldEx UpdateFieldEx 更新过滤字段
  29. CommonUpdateFieldEx = []interface{}{"created_by", "created_name", "created_time"}
  30. UpdateFieldEx = []interface{}{"id", "created_by", "created_name", "created_time"}
  31. )
  32. func Sequence(db gdb.DB, name string) (string, error) {
  33. v, err := db.GetValue("select `nextval`( ? );", name)
  34. if err != nil {
  35. return "", err
  36. }
  37. return v.String(), nil
  38. }
  39. func SequenceYearRest(db gdb.DB, name string) (int, error) {
  40. v, err := db.GetValue("select `next_year_reset_val`( ? );", name)
  41. if err != nil {
  42. return 0, err
  43. }
  44. return v.Int(), nil
  45. }
  46. // SetCreatedInfo 插入数据库时设置创建信息
  47. func SetCreatedInfo(entry interface{}, id int, name string) {
  48. v := reflect.ValueOf(entry)
  49. t := reflect.TypeOf(entry)
  50. if t.Kind() == reflect.Map {
  51. data := entry.(map[string]interface{})
  52. data["created_by"] = id
  53. data["created_name"] = name
  54. data["created_time"] = gtime.Now()
  55. return
  56. }
  57. if t.Kind() == reflect.Ptr {
  58. t = t.Elem()
  59. v = v.Elem()
  60. }
  61. if t.Kind() == reflect.Slice {
  62. }
  63. if t.Kind() != reflect.Struct {
  64. log.Println("Check type error not Struct")
  65. return
  66. }
  67. for i := 0; i < t.NumField(); i++ {
  68. fieldName := t.Field(i).Name
  69. if tag, ok := t.Field(i).Tag.Lookup("orm"); ok {
  70. switch tag {
  71. case "created_by":
  72. v.FieldByName(fieldName).Set(reflect.ValueOf(id))
  73. case "created_name":
  74. v.FieldByName(fieldName).Set(reflect.ValueOf(name))
  75. case "created_time":
  76. v.FieldByName(fieldName).Set(reflect.ValueOf(gtime.Now()))
  77. }
  78. }
  79. }
  80. }
  81. // SetUpdatedInfo 插入数据库时设置修改信息
  82. func SetUpdatedInfo(entry interface{}, id int, name string) {
  83. v := reflect.ValueOf(entry)
  84. t := reflect.TypeOf(entry)
  85. if t.Kind() == reflect.Map {
  86. data := entry.(map[string]interface{})
  87. data["updated_by"] = id
  88. data["updated_name"] = name
  89. data["updated_time"] = gtime.Now()
  90. return
  91. }
  92. if t.Kind() == reflect.Ptr {
  93. t = t.Elem()
  94. v = v.Elem()
  95. }
  96. if t.Kind() != reflect.Struct {
  97. log.Println("Check type error not Struct")
  98. return
  99. }
  100. for i := 0; i < t.NumField(); i++ {
  101. fieldName := t.Field(i).Name
  102. if tag, ok := t.Field(i).Tag.Lookup("orm"); ok {
  103. switch tag {
  104. case "updated_by":
  105. v.FieldByName(fieldName).Set(reflect.ValueOf(id))
  106. case "updated_name":
  107. v.FieldByName(fieldName).Set(reflect.ValueOf(name))
  108. case "updated_time":
  109. v.FieldByName(fieldName).Set(reflect.ValueOf(gtime.Now()))
  110. }
  111. }
  112. }
  113. }
  114. // Div 数字转字母
  115. func Div(Num int) string {
  116. var (
  117. Str string = ""
  118. k int
  119. temp []int //保存转化后每一位数据的值,然后通过索引的方式匹配A-Z
  120. )
  121. //用来匹配的字符A-Z
  122. Slice := []string{"", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
  123. "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
  124. if Num > 26 { //数据大于26需要进行拆分
  125. for {
  126. k = Num % 26 //从个位开始拆分,如果求余为0,说明末尾为26,也就是Z,如果是转化为26进制数,则末尾是可以为0的,这里必须为A-Z中的一个
  127. if k == 0 {
  128. temp = append(temp, 26)
  129. k = 26
  130. } else {
  131. temp = append(temp, k)
  132. }
  133. Num = (Num - k) / 26 //减去Num最后一位数的值,因为已经记录在temp中
  134. if Num <= 26 { //小于等于26直接进行匹配,不需要进行数据拆分
  135. temp = append(temp, Num)
  136. break
  137. }
  138. }
  139. } else {
  140. return Slice[Num]
  141. }
  142. for _, value := range temp {
  143. Str = Slice[value] + Str //因为数据切分后存储顺序是反的,所以Str要放在后面
  144. }
  145. return Str
  146. }
  147. type GetDictReq struct {
  148. DictType string `p:"dictType" v:"required#字典类型不能为空"`
  149. DefaultValue string `p:"defaultValue"`
  150. }
  151. type GetDictLabelByTypeAndValueReq struct {
  152. DictType string `p:"dictType"` //字典类型
  153. DictValue string `p:"dictValue"` //字典标签
  154. }
  155. func baseGetDictDataByType(ctx context.Context, typ string) ([]interface{}, error) {
  156. srv := micro_srv.InitMicroSrvClient("Dict", "micro_srv.auth")
  157. defer srv.Close()
  158. resp := &comm_def.CommonMsg{}
  159. err := srv.Call(ctx, "GetDictDataByType", GetDictReq{
  160. DictType: typ,
  161. }, resp)
  162. if err != nil {
  163. return nil, fmt.Errorf("获取字典 %s %s", typ, err.Error())
  164. }
  165. fmt.Println(resp.Data)
  166. data := resp.Data.(map[string]interface{})["Values"].([]interface{})
  167. fmt.Println(data)
  168. return data, nil
  169. }
  170. func GetDictDataByType(ctx context.Context, typ string) (map[string]string, error) {
  171. data, err := baseGetDictDataByType(ctx, typ)
  172. if err != nil {
  173. return nil, err
  174. }
  175. res := map[string]string{}
  176. for _, i := range data {
  177. info := i.(map[string]interface{})
  178. res[info["DictValue"].(string)] = info["DictLabel"].(string)
  179. }
  180. return res, nil
  181. }
  182. // Find获取一个切片并在其中查找元素。如果找到它,它将返回它的密钥,否则它将返回-1和一个错误的bool。
  183. func FindItem(slice []string, val string) (int, bool) {
  184. for i, item := range slice {
  185. if item == val {
  186. return i, true
  187. }
  188. }
  189. return -1, false
  190. }
  191. // 有序
  192. func GetDictDataTreeByType(ctx context.Context, typ string) (*gmap.ListMap, error) {
  193. data, err := baseGetDictDataByType(ctx, typ)
  194. if err != nil {
  195. return nil, err
  196. }
  197. res := gmap.NewListMap(true)
  198. for _, i := range data {
  199. info := i.(map[string]interface{})
  200. res.Set(info["DictValue"], info["DictLabel"])
  201. }
  202. return res, nil
  203. }
  204. // 根据字典类型和字典值获取字典明细名称
  205. func GetDictLabelByTypeAndValue(ctx context.Context, dictType, value string) (string, error) {
  206. srv := micro_srv.InitMicroSrvClient("Dict", "micro_srv.auth")
  207. defer srv.Close()
  208. resp := &comm_def.CommonMsg{}
  209. err := srv.Call(ctx, "GetDictLabelByTypeAndValue", GetDictLabelByTypeAndValueReq{
  210. DictType: dictType,
  211. DictValue: value,
  212. }, resp)
  213. if err != nil {
  214. g.Log().Error(err)
  215. return value, nil
  216. }
  217. return gconv.String(resp.Data), nil
  218. }
  219. func StringSlicecontains(s []string, ele string) bool {
  220. for _, i := range s {
  221. if i == ele {
  222. return true
  223. }
  224. }
  225. return false
  226. }
  227. // CreateSystemMessage 创建系统消息
  228. func CreateSystemMessage(msg g.MapStrStr) error {
  229. srv := micro_srv.InitMicroSrvClient("SystemMessage", "micro_srv.auth")
  230. defer srv.Close()
  231. resp := &comm_def.CommonMsg{}
  232. tenant := g.Config().GetString("micro_srv.tenant")
  233. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  234. err := srv.Call(ctx, "Create", msg, resp)
  235. if err != nil {
  236. g.Log().Error(err)
  237. return myerrors.MicroCallError("系统创建消息失败")
  238. }
  239. fmt.Println(resp.Data)
  240. return nil
  241. }
  242. type DeptIdReq struct {
  243. DeptId int `json:"dept_id,omitempty"`
  244. Include bool `json:"include,omitempty"`
  245. }
  246. // GetUsersByDept 根据部门获取用户
  247. func GetUsersByDept(ctx context.Context, req *DeptIdReq) (map[string]int, error) {
  248. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  249. defer srv.Close()
  250. resp := &comm_def.CommonMsg{}
  251. err := srv.Call(ctx, "GetUserByDept", req, resp)
  252. if err != nil {
  253. return nil, myerrors.MicroCallError("获取部门下用户失败")
  254. }
  255. if resp.Data == nil {
  256. return nil, myerrors.TipsError("部门不存在")
  257. }
  258. fmt.Println(resp.Data)
  259. data := resp.Data.([]interface{})
  260. fmt.Println(data)
  261. res := map[string]int{}
  262. for _, i := range data {
  263. info := i.(map[string]interface{})
  264. res[info["NickName"].(string)] = gconv.Int(info["Id"])
  265. }
  266. return res, nil
  267. }
  268. type SysUserSearchReq struct {
  269. KeyWords string `json:"keyWords"`
  270. DeptId int `json:"deptId"` //部门id
  271. DeptIds []int //所属部门id数据
  272. Phone string `json:"phone"`
  273. Status string `json:"status"`
  274. Roles []string `json:"roles"`
  275. Posts []string `json:"posts"`
  276. Groups []string `json:"groups"`
  277. request.PageReq
  278. }
  279. // GetUsersByRoleCode 根据角色编码获取用户
  280. func GetUsersByRoleCode(ctx context.Context, roleCode []string, pageSize ...int) (map[string]int, error) {
  281. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  282. defer srv.Close()
  283. resp := &comm_def.CommonMsg{}
  284. req := &SysUserSearchReq{Roles: roleCode, Status: "10"}
  285. if len(pageSize) > 0 {
  286. req.PageSize = pageSize[0]
  287. }
  288. err := srv.Call(ctx, "GetList", req, resp)
  289. if err != nil {
  290. return nil, myerrors.MicroCallError("根据角色编码获取用户失败")
  291. }
  292. if resp.Data == nil {
  293. return nil, myerrors.TipsError("用户不存在")
  294. }
  295. data := resp.Data.(map[string]interface{})
  296. list := data["list"].([]interface{})
  297. res := map[string]int{}
  298. for _, i := range list {
  299. info := i.(map[string]interface{})
  300. res[info["NickName"].(string)] = gconv.Int(info["Id"])
  301. }
  302. return res, nil
  303. }
  304. // GetUserListByRoleCode 根据角色编码获取用户列表
  305. func GetUserListByRoleCode(ctx context.Context, roleCode []string, pageSize ...int) ([]map[string]interface{}, error) {
  306. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  307. defer srv.Close()
  308. resp := &comm_def.CommonMsg{}
  309. req := &SysUserSearchReq{Roles: roleCode, Status: "10"}
  310. if len(pageSize) > 0 {
  311. req.PageSize = pageSize[0]
  312. }
  313. err := srv.Call(ctx, "GetList", req, resp)
  314. if err != nil {
  315. return nil, myerrors.MicroCallError("根据角色编码获取用户失败")
  316. }
  317. if resp.Data == nil {
  318. return nil, myerrors.TipsError("用户不存在")
  319. }
  320. data := resp.Data.(map[string]interface{})
  321. list := data["list"].([]interface{})
  322. var res []map[string]interface{}
  323. for _, i := range list {
  324. info := i.(map[string]interface{})
  325. data := map[string]interface{}{
  326. "Id": gconv.Int(info["Id"]),
  327. "NickName": info["NickName"].(string),
  328. }
  329. res = append(res, data)
  330. }
  331. return res, nil
  332. }
  333. // 获取用户权限
  334. func GetUserDataScope(userId int) (g.Map, error) {
  335. srv := micro_srv.InitMicroSrvClient("User", "micro_srv.auth")
  336. defer srv.Close()
  337. req := &comm_def.IdReq{Id: int64(userId)}
  338. resp := &comm_def.CommonMsg{}
  339. tenant := g.Config().GetString("micro_srv.tenant")
  340. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  341. err := srv.Call(ctx, "GetDataScope", req, resp)
  342. if err != nil || resp.Data == nil {
  343. g.Log().Error(err)
  344. return nil, myerrors.MicroCallError("获取用户权限失败")
  345. }
  346. return resp.Data.(g.Map), nil
  347. }
  348. // 跟进发送邮件消息
  349. func GSendMail(msg g.MapStrStr) error {
  350. srv := micro_srv.InitMicroSrvClient("Message", "micro_srv.auth")
  351. defer srv.Close()
  352. resp := &comm_def.CommonMsg{}
  353. tenant := g.Config().GetString("micro_srv.tenant")
  354. ctx := context.WithValue(context.TODO(), share.ReqMetaDataKey, map[string]string{"tenant": tenant})
  355. err := srv.Call(ctx, "SendMail", msg, resp)
  356. if err != nil {
  357. g.Log().Error(err)
  358. return myerrors.MicroCallError("项目未跟进发送邮件提醒失败")
  359. }
  360. fmt.Println(resp.Data)
  361. return nil
  362. }
  363. func ColumnInt(m *gdb.Model, name string) ([]int, error) {
  364. v, err := m.Fields(name).Array()
  365. if err != nil {
  366. return nil, err
  367. }
  368. res := []int{}
  369. for _, i := range v {
  370. res = append(res, i.Int())
  371. }
  372. return res, nil
  373. }
  374. func ColumnString(m *gdb.Model, name string) ([]string, error) {
  375. v, err := m.Fields(name).Array()
  376. if err != nil {
  377. return nil, err
  378. }
  379. res := []string{}
  380. for _, i := range v {
  381. res = append(res, i.String())
  382. }
  383. return res, nil
  384. }
  385. func StringsContains(s []string, ele string) bool {
  386. for _, i := range s {
  387. if i == ele {
  388. return true
  389. }
  390. }
  391. return false
  392. }
  393. func UserIdByRoles(db gdb.DB, roles ...string) ([]int, error) {
  394. roleId, err := ColumnInt(db.Table("sys_role").Where("role_key in (?)", roles), "id")
  395. if err != nil {
  396. return nil, err
  397. }
  398. return ColumnInt(db.Table("sys_user_role").Where("role_id in (?)", roleId), "user_id")
  399. }
  400. func UserDingtalkUid(db gdb.DB, id int) (string, error) {
  401. v, err := db.Table("sys_user").Where("id = ?", id).Fields("dingtalk_uid").Value()
  402. if err != nil {
  403. return "", err
  404. }
  405. uid := v.String()
  406. if uid == "" {
  407. return "", fmt.Errorf("没有找到 %d 的钉钉用户id", id)
  408. }
  409. return uid, nil
  410. }
  411. func SliceIntDeduplication(elems []int) []int {
  412. emap := map[int]struct{}{}
  413. for _, i := range elems {
  414. emap[i] = struct{}{}
  415. }
  416. ret := []int{}
  417. for i := range emap {
  418. ret = append(ret, i)
  419. }
  420. return ret
  421. }
  422. // DownloadTempFile 下载临时文件
  423. func DownloadTempFile(url string) (*multipart.FileHeader, error) {
  424. r, err := http.Get(url)
  425. if err != nil {
  426. g.Log().Error(err)
  427. return nil, err
  428. }
  429. if r.StatusCode != http.StatusOK {
  430. return nil, fmt.Errorf("DownloadFile from %s StatusCode %d", url, r.StatusCode)
  431. }
  432. defer r.Body.Close()
  433. bytes, err := ioutil.ReadAll(r.Body)
  434. if err != nil {
  435. g.Log().Error(err)
  436. return nil, err
  437. }
  438. names := gstr.Split(r.Header.Get("Content-Disposition"), "filename=")
  439. fileName := guid.S()
  440. if len(names) > 1 {
  441. fileName, _ = gurl.Decode(names[1])
  442. fileName = gstr.TrimStr(fileName, `"`)
  443. }
  444. file, err := os.CreateTemp("", fileName)
  445. if err != nil {
  446. g.Log().Error(err)
  447. }
  448. file.Write(bytes)
  449. fmt.Println(file.Name())
  450. fileData := new(multipart.FileHeader)
  451. fileData.FileName = fileName
  452. fileData.FileSize = gconv.Int64(r.Header.Get("Content-Length"))
  453. fileData.File = file
  454. return fileData, nil
  455. }