client.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. package wfclient
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "encoding/xml"
  6. "errors"
  7. "fmt"
  8. "net/http"
  9. "strconv"
  10. "strings"
  11. "git.qianqiusoft.com/qianqiusoft/light-apiengine/config"
  12. "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys"
  13. "git.qianqiusoft.com/qianqiusoft/light-apiengine/utils"
  14. )
  15. type Filter struct {
  16. GroupOp string `json:"groupOp"`
  17. Rules []*FilterField `json:"rules"`
  18. }
  19. type FilterField struct {
  20. Field string `json:"field"`
  21. Op string `json:"op"`
  22. Data string `json:"data"`
  23. }
  24. type WFClient struct {
  25. endpoint string
  26. authorization string
  27. userId string
  28. username string
  29. token string
  30. domain string
  31. }
  32. var _wfendpoint = ""
  33. func init() {
  34. _wfendpoint = config.AppConfig.GetKey("wfendpoint")
  35. }
  36. /**
  37. * @brief: single instance
  38. */
  39. func NewWFClient(c *entitys.CtrlContext) *WFClient {
  40. tk, _ := c.Ctx.Get("token")
  41. token := tk.(*entitys.Token)
  42. instance := &WFClient{}
  43. instance.endpoint = _wfendpoint
  44. instance.authorization, _ = instance.createAuthorization(token.LoginID, token.AccessToken, token.Domain)
  45. instance.userId = token.UserId
  46. instance.token = token.AccessToken
  47. HttpClientInstance().setRequestInterseptor(instance.wfReqInterseptor)
  48. return instance
  49. }
  50. /**
  51. * @brief: init
  52. * @param1 endpoint: endpoint of wf service, do not end with /; such as http://wf.qianqiusoft.com
  53. * @param2 userId: user's id
  54. * @param3 username: username
  55. * @param4 token: token
  56. * @param5 domain: domain, its default value is qianqiusoft.com
  57. * @return1: information of error, nil if everything is all right
  58. */
  59. func (w *WFClient) Init(endpoint, userId, username, token, domain string) error {
  60. if w.token == token && w.authorization != "" {
  61. fmt.Println("wfclient token", w.token, "does already exist, token is", w.authorization)
  62. return nil
  63. }
  64. var err error = nil
  65. w.endpoint = endpoint
  66. w.userId = userId
  67. w.authorization, err = w.createAuthorization(username, token, domain)
  68. w.token = token
  69. if err != nil {
  70. return err
  71. } else {
  72. return nil
  73. }
  74. }
  75. /**
  76. * @brief: create or update the define,
  77. * @param1 defineId: id of define, if the define with id does already exist, update the define
  78. * @param2 defineName: name of define
  79. * @param3 defineDesc: description of define
  80. * @param4 diagram: diagram of define
  81. * @param5 formName: name of the form
  82. * @return1 information of error
  83. */
  84. func (w *WFClient) CreateOrUpdateDefine(defineId, defineName, defineDesc, diagram, formName, tag, code string) ([]byte, error) {
  85. if defineId == "" {
  86. defineId = utils.NewUUID()
  87. }
  88. url := w.getFullUrl(fmt.Sprintf("api/wf_define/%s", defineId))
  89. fmt.Println("----url:", url)
  90. params := make(map[string]string)
  91. params["define_id"] = defineId
  92. params["name"] = defineName
  93. params["descript"] = defineDesc
  94. params["data"] = diagram
  95. params["form"] = formName
  96. params["code"] = code
  97. params["tag"] = tag
  98. return HttpClientInstance().post(url, params, nil)
  99. }
  100. func (w *WFClient) FetchDefine(defineId string) ([]byte, error) {
  101. url := w.getFullUrl("api/wf_define/" + defineId)
  102. fmt.Println(url)
  103. return HttpClientInstance().get(url, nil, nil)
  104. }
  105. func (w *WFClient) FetchAllDefines() ([]byte, error) {
  106. url := w.getFullUrl("api/wf_define/all")
  107. return HttpClientInstance().get(url, nil, nil)
  108. }
  109. /**
  110. * @brief: get the flow define by tag
  111. * @param1 tag: tag of the define, split by ,
  112. * @return1: content of response
  113. * @return2: information of error, nil if everything is all right
  114. */
  115. func (w *WFClient) FetchDefinesByTag(tag string) ([]byte, error) {
  116. url := w.getFullUrl("api/wf_define/list/tag")
  117. params := make(map[string]string)
  118. params["tag"] = tag
  119. return HttpClientInstance().get(url, params, nil)
  120. }
  121. /**
  122. * @brief: get the flow design diagram
  123. * @param1 id: id of flow define
  124. * @return1: content of response
  125. * @return2: information of error, nil if everything is all right
  126. */
  127. func (w *WFClient) FetchDesignDiagram(defineId string) ([]byte, error) {
  128. url := w.getFullUrl(fmt.Sprintf("api/wf_define/designer/%s", defineId))
  129. return HttpClientInstance().get(url, nil, nil)
  130. }
  131. /**
  132. * @brief: create a wf instance
  133. * @param1 defineId: id of wf define
  134. * @param2 name: name of instance
  135. * @param3 formData: data to submit
  136. * @return1: content of response
  137. * @return2: error
  138. */
  139. func (w *WFClient) CreateInstance(defineId, name, formData string) ([]byte, error) {
  140. url := w.getFullUrl("api/wf_instance")
  141. params := make(map[string]string)
  142. params["define_id"] = defineId
  143. params["name"] = name
  144. params["form_data"] = formData
  145. return HttpClientInstance().post(url, params, nil)
  146. }
  147. // 更新流程实例表单
  148. func (w *WFClient) UpdateInstanceForm(instanceId, formData string) ([]byte, error) {
  149. url := w.getFullUrl("api/wf_instance/updateFormData")
  150. params := make(map[string]string)
  151. params["instance_id"] = instanceId
  152. params["form_data"] = formData
  153. return HttpClientInstance().post(url, params, nil)
  154. }
  155. type Choice struct {
  156. XMLName xml.Name `xml:"choice"json:"-"`
  157. Name string `json:"name"xml:"name"`
  158. Trans Transition `json:"trans"xml:"transition"`
  159. }
  160. type Transition struct {
  161. XMLName xml.Name `xml:"transition"json:"-"`
  162. Name string `json:"name"xml:"name"`
  163. To string `json:"to"xml:"to"`
  164. Points string `json:"-"xml:"points"`
  165. Conditions []*Condition `json:"conditions,omitempty"`
  166. Callback string `json:"callback"xml:"callback"`
  167. }
  168. type Condition struct {
  169. Operator string `json:"operator"xml:"operator"`
  170. DataKey string `json:"data_key"xml:"data_key"`
  171. Value string `json:"value"xml:"value"`
  172. Logic string `json:"logic"xml:"logic"`
  173. }
  174. /**
  175. * @brief: run the wf instance
  176. * @param1 instanceId: id of instance
  177. * @param2 userId: approver id
  178. * @param3 choice: choice
  179. * @param4 options: options
  180. * @return1 content of response
  181. * @return2 error
  182. */
  183. func (w *WFClient) Run(instanceId, userId, choice, options, nextStep string, c *entitys.CtrlContext) ([]byte, error) {
  184. url := w.getFullUrl("api/wf_instance/run")
  185. params := make(map[string]string)
  186. params["instance_id"] = instanceId
  187. params["users"] = userId
  188. if choice != "" {
  189. params["choice"] = choice
  190. }
  191. if options != "" {
  192. params["opinion"] = options
  193. }
  194. if nextStep != "" {
  195. params["nextStep"] = nextStep
  196. }
  197. var RunRespInfo struct {
  198. DefineId string `json:"define_id"`
  199. InstanceId string `json:"instance_id"`
  200. DefineName string `json:"define_name"`
  201. InstanceName string `json:"instance_name"`
  202. Choices []*Choice `json:"choices"`
  203. Transition *Transition `json:"transition"`
  204. StepType string `json:"step_type"`
  205. FormData string `json:"form_data"`
  206. StepName string `json:"step_name"`
  207. ActorType string `json:"actor_type"`
  208. Executor string `json:"executor"`
  209. StartCallback string `json:"start_callback"`
  210. }
  211. bytess, err := HttpClientInstance().post(url, params, nil)
  212. if err != nil {
  213. return nil, err
  214. }
  215. //fmt.Println("------------->>>>>--------", string(bytess))
  216. err = json.Unmarshal(bytess, &RunRespInfo)
  217. if err != nil {
  218. return nil, err
  219. }
  220. fmt.Println("------------------------------------->121", RunRespInfo.StartCallback)
  221. // 节点回调
  222. callbacks := strings.Split(RunRespInfo.StartCallback, ",")
  223. for _, callbackKye := range callbacks {
  224. callWFCallback(callbackKye, &CallbackArg{
  225. DefineId: RunRespInfo.DefineId,
  226. InstanceId: RunRespInfo.DefineId,
  227. DefineName: RunRespInfo.DefineName,
  228. InstanceName: RunRespInfo.InstanceName,
  229. FormData: RunRespInfo.FormData,
  230. Choice: choice,
  231. Executor: RunRespInfo.Executor,
  232. UserId: w.userId,
  233. Context: c,
  234. })
  235. }
  236. // 连线回调
  237. linkCallbacks := []string{}
  238. if RunRespInfo.StepType == "begin" || RunRespInfo.StepType == "normal" {
  239. linkCallbacks = strings.Split(RunRespInfo.Transition.Callback, ",")
  240. } else {
  241. for _, c := range RunRespInfo.Choices {
  242. if c.Name == choice {
  243. linkCallbacks = strings.Split(c.Trans.Callback, ",")
  244. }
  245. }
  246. }
  247. for _, callbackKye := range linkCallbacks {
  248. callWFCallback(callbackKye, &CallbackArg{
  249. DefineId: RunRespInfo.DefineId,
  250. InstanceId: RunRespInfo.DefineId,
  251. DefineName: RunRespInfo.DefineName,
  252. InstanceName: RunRespInfo.InstanceName,
  253. FormData: RunRespInfo.FormData,
  254. Choice: choice,
  255. Executor: RunRespInfo.Executor,
  256. UserId: w.userId,
  257. Context: c,
  258. })
  259. }
  260. return []byte{}, nil
  261. }
  262. /**
  263. * @brief: pre the wf instance
  264. * @param1 instanceId: id of instance
  265. * @param2 choice: choice of step
  266. * @return1 content of response
  267. * @return2 error
  268. */
  269. func (w *WFClient) PreRun(instanceId, choice string) ([]byte, error) {
  270. url := w.getFullUrl("api/wf_instance/prerun")
  271. params := make(map[string]string)
  272. params["instance_id"] = instanceId
  273. params["choice"] = choice
  274. return HttpClientInstance().post(url, params, nil)
  275. }
  276. /**
  277. * @brief: fetch my instances
  278. * @param1 page: page num, start from 1
  279. * @param2 rows: count per page, its default value is 10000
  280. * @return1: content of response
  281. * @return2: information of error
  282. */
  283. func (w *WFClient) FetchMyInstances(page, rows int) ([]byte, error) {
  284. url := w.getFullUrl("/api/wf_instance/mime")
  285. params := make(map[string]string)
  286. params["page"] = strconv.FormatInt(int64(page), 10)
  287. params["pageSize"] = strconv.FormatInt(int64(rows), 10)
  288. return HttpClientInstance().get(url, params, nil)
  289. }
  290. /**
  291. * @brief: fetch current step of login user
  292. * @param1 instanceId: id of instance
  293. * @return1 content of response
  294. * @return2 error
  295. */
  296. func (w *WFClient) FetchCurrentStepByLoginUser(instanceId string) ([]byte, error) {
  297. url := w.getFullUrl("/api/wf_instance/user/current")
  298. params := make(map[string]string)
  299. params["instance_id"] = instanceId
  300. return HttpClientInstance().get(url, params, nil)
  301. }
  302. /**
  303. * @brief: fetch current step of instance
  304. * @param1 instanceId: id of instance
  305. * @return1 content of response
  306. * @return2 error
  307. */
  308. func (w *WFClient) FetchCurrentStep(instanceId string) ([]byte, error) {
  309. url := w.getFullUrl("/api/wf_instance/current")
  310. params := make(map[string]string)
  311. params["instance_id"] = instanceId
  312. return HttpClientInstance().get(url, params, nil)
  313. }
  314. /**
  315. * @brief: fetch my to do list
  316. * @param1 page: page num, start from 1
  317. * @param2 rows: count per page, its default value is 10000
  318. * @return1: content of response
  319. * @return2: information of error
  320. */
  321. func (w *WFClient) FetchToDoList(page, rows int) ([]byte, error) {
  322. url := w.getFullUrl("/api/wf_instance/todo")
  323. params := make(map[string]string)
  324. params["page"] = strconv.FormatInt(int64(page), 10)
  325. params["pageSize"] = strconv.FormatInt(int64(rows), 10)
  326. return HttpClientInstance().get(url, params, nil)
  327. }
  328. /**
  329. * @brief: fetch my done list
  330. * @param1 page: page num, start from 1
  331. * @param2 rows: count per page, its default value is 10000
  332. * @return1: content of response
  333. * @return2: information of error
  334. */
  335. func (w *WFClient) FetchDoneList(page, rows int) ([]byte, error) {
  336. url := w.getFullUrl("/api/wf_instance/done")
  337. params := make(map[string]string)
  338. params["page"] = strconv.FormatInt(int64(page), 10)
  339. params["pageSize"] = strconv.FormatInt(int64(rows), 10)
  340. return HttpClientInstance().get(url, params, nil)
  341. }
  342. func (w *WFClient) FetchWFINstances(page, rows int, filters, sidx, sord string) ([]byte, error) {
  343. url := w.getFullUrl("/api/wf_instance/list")
  344. fmt.Println("wf url: ", url)
  345. params := make(map[string]string)
  346. params["page"] = strconv.FormatInt(int64(page), 10)
  347. params["rows"] = strconv.FormatInt(int64(rows), 10)
  348. params["sidx"] = sidx
  349. params["sord"] = sord
  350. params["filters"] = filters
  351. return HttpClientInstance().get(url, params, nil)
  352. }
  353. /**
  354. * @brief: wf req interseptor
  355. * @param1 r: http req
  356. */
  357. func (w *WFClient) wfReqInterseptor(r *http.Request) {
  358. //r.Header.Add("Authorization", w.authorization)
  359. fmt.Println("header add token", w.token)
  360. r.Header.Add("token", w.token)
  361. }
  362. /**
  363. * @brief: create the authorization by username, token and domain
  364. * @param2 username: username
  365. * @param3 token: token
  366. * @param4 domain: domain, its default value is qianqiusoft.com
  367. * @return1 authorization, such as Bearer adfeadfsdfsdffds
  368. * @return2 information of error, nil if everything is all right
  369. */
  370. func (w *WFClient) createAuthorization(username, token, domain string) (string, error) {
  371. if username == "" || token == "" {
  372. return "", errors.New("username or token is empty")
  373. }
  374. if domain == "" {
  375. domain = "qianqiusoft.com"
  376. }
  377. w.username = username
  378. w.token = token
  379. w.domain = domain
  380. tstr := fmt.Sprintf("%s:%s:%s", username, token, domain)
  381. tbase64str := base64.StdEncoding.EncodeToString([]byte(tstr))
  382. finalStr := "sso-auth-token:" + tbase64str
  383. return "Bearer " + base64.StdEncoding.EncodeToString([]byte(finalStr)), nil
  384. }
  385. /**
  386. * @brief: get full url
  387. * @param1 path: api path, such as /api/wf_instance/done
  388. * @return1 url with query params
  389. */
  390. func (w *WFClient) getFullUrl(path string) string {
  391. path = strings.TrimLeft(path, "/")
  392. return fmt.Sprintf("%s/%s", w.endpoint, path)
  393. }
  394. //撤回
  395. func (w *WFClient) Recall(definedId string) ([]byte, error) {
  396. url := w.getFullUrl("/api/wf_instance/recall")
  397. params := make(map[string]string)
  398. params["instance_id"] = definedId
  399. return HttpClientInstance().post(url, params, nil)
  400. }
  401. //终止
  402. func (w *WFClient) Interrupt(definedId string, formData map[string]interface{}, c *entitys.CtrlContext) ([]byte, error) {
  403. url := w.getFullUrl("/api/wf_instance/interrupt")
  404. params := make(map[string]string)
  405. params["instance_id"] = definedId
  406. var RunRespInfo struct {
  407. DefineId string `json:"define_id"`
  408. InstanceId string `json:"instance_id"`
  409. DefineName string `json:"define_name"`
  410. InstanceName string `json:"instance_name"`
  411. Choices []*Choice `json:"choices"`
  412. Transition *Transition `json:"transition"`
  413. StepType string `json:"step_type"`
  414. FormData string `json:"form_data"`
  415. StepName string `json:"step_name"`
  416. ActorType string `json:"actor_type"`
  417. Executor string `json:"executor"`
  418. StartCallback string `json:"start_callback"`
  419. }
  420. bytess, err := HttpClientInstance().post(url, params, nil)
  421. if err != nil {
  422. return nil, err
  423. }
  424. callWFCallback("interrupt", &CallbackArg{
  425. DefineId: RunRespInfo.DefineId,
  426. InstanceId: definedId,
  427. DefineName: RunRespInfo.DefineName,
  428. InstanceName: RunRespInfo.InstanceName,
  429. FormData: formData["form_data"].(string),
  430. Executor: RunRespInfo.Executor,
  431. UserId: w.userId,
  432. Context: c,
  433. })
  434. return bytess, err
  435. }
  436. //撤回
  437. func (w *WFClient) Delete(definedId string) ([]byte, error) {
  438. url := w.getFullUrl("/api/wf_define/delete")
  439. params := make(map[string]string)
  440. params["define_id"] = definedId
  441. return HttpClientInstance().post(url, params, nil)
  442. }