base.go 13 KB

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