P. E7pyԖ%%qB ?$ I{Yoev uoZ6fZ$p{VuC9 "!0yMag^94E:4_'8DaŤЖ8M&cJ%G|5Ϸ Ȥe> ܤëЬ0@U8QG<6{dzdL#q`l /¼!-|>SO Ib\FnYջ="ӝ&~̅uGN3NH눟2,S 5@tjH>11OST'Zh=sOz /~+|D? .u % * \+R3xgҶlBs!>0яl@"%=1=x f]"]"3â]r=g}Gr(k{3|]aBn4>]w㶪{/lHyH!8:^"oy`>C4i+;Nۦz1YAբW!YXABq& ӄhi=Dt`ki[@ -ܲis=s)LI!~Hү+}09!x c?4¦Ԝ.RJ|㳁ܼӒ|ԓLj5T2G2]G3 2mbO5mk#a $23n8Z5)aGo~"35ZqR ڦξӶ |;ߜs~z2$p`b(zmo*㫀Cg˴U Z-iN~n)wzYΓkLFnnV]lGEJɋU# 9wːD'>eyoa>!VX:{k"7+$h]4N?8#˨ xwsIN~Co,$y\&0R^tR;xl ݗxS?ˬ[7B/*Lo0fAHAQܖx۳q- Z>oVUFb*ٚ?Nf?IT6{ҽݕ1.\Ϣ辽W7 %@zˡg}q͌rqu-,£O漦cs=ξ^TkdE^ZXirQH?rGFP~"L3M8Bׯz.0/|K= x)b:Z}5' ^ ߻nT?+!봗2٤JW6Ciq#u;ᢼk1j[a2~?j*API -K[TE{"VE[Q>0r HSxqO!S 1 $ b"^[Fj1~jWA'dHN_vAXɚj5S~(y "hFp2eO#$JQMjV;{a!>4K0Ǽ S{=z)FQqL&‹uS -Ց!fَ Eo&C14X,$c 7?Ĝ~mR4Z<"2Nܣjhy>)7Y: +1J[=auI^a@ E@öd8OO-aV{L|I)R$UU"ųmoy;هo-yk{rROm{y?h} Wm$GOG| ^R Lav4l ~ʘVi+ VJ_úVG|qWUr#BUz~%*=dk,[i Y/0T V6]HZ 8{aԌY[[N6 28D}W Ё26<~(P6&B}$ޜr2iD#=7`{}cU%ۏ P @gBcԅEXP[|—(iat ᵺPa~Y SF I-Ew0:Jdx/;o/э47>)gˇkO}-=/-Q3PVf&bSZ*߸W)'==q+5 izJS%Rw EJ=0WWyXҏ Cɕ6?^*N2)guYbVtAz'+ ]UO :=R˕W< .Rɔ~Lx->*ܧEpfW_k5_Gޜ')a;cMX6t;{cξ9 i{7:@ߊ'7h+ONh޴ sܨx(LvwBPKdշN迭*y \=E,g M{gSfN#ڒ&_GP syaUl ".=Au~p~_fNܢ,! {[zbY\tA CwI3<+咧+ف韒rlܜ)f;AWa"t;9{Zp;^ 4y79b(g:}!T>}2@$T; lSp9weZi{fWr4؃a$@ ,AK!=rJT%cBPb}UB$M߱ ÆI֒M귣"$Հ} 8|)n]z[w\i -^ҨnRLA=1 _5B"3*ѳuBUlE%qd 5prU@3K'ۙ*%B8n`uG]缧 ,V֣ GŢ+ +57`UUMzۃL!_g. "(=x&߈yHںg;!m{vlhJw'6tWYP"^$ЦmՈ?w3@WAkl37t(ɺMvd*0iD0L~v0Ɠ(61T65iZ~%d )6u8gsO$:;ϸUg^Ev8aäf1 fڑteU/:! ]zf/cpmDߒ~,󔞐D_b:@(T JSgtn;im bPԾgUxϷtT5QYn^u,.N=]9 (_$_hSW-,3: <&>K> lg|[dMTndO# 7KS™Z򃥴X[Қe⻇o"dr73(]iAT7R}2F F ?~2ьVpô:ncPH_)yFVV]/p̘c |p'Ppe;4 (ML6 8cOn Lp献4^*sH3/έ߰ = h7_k (sg'~2KNw,/X"S&(xX ", {-;I]fy* \[%bQFp` UXCOᲸ^Eģ  bM# 6Z i= 0W,anrpN\5Z'-̧Qy\ [  듉sFK(Ul|1Z,hiQYZyM"܋[mzg\Cj.&K]ÿNAS^lPmd6?˾KхGdXMG[D8҈ξ`g`NؚA'52([7*kgADi> ܎RWQHׁrGx2d}?cպ ;lS3C.V>#lBO%}^-At@6(wr05S'i|ɡBcJaH+/ v-\Տ5?9Ȳ~`&0_KֿCg!(LSpC"sYZ*T<s~HF碇 ;@jK q~"$DEJϚ15 Xf_5=̀@?Tp^kڨ7kw C>TllG5mQ&cq =]I3fܢ0a|Va(;na^E{:n7VSɊRLrkwW'P =j^Jг;|Ob!ЇJ#sUe+8Q=W@q]&,iMJF.Hp=gHȫN..'ʂK}LR _/foYmjÃ$!3<{9orC>op,.ԃHCڣ&'r.r@Qj~fbgy_CP< ҕǑ3rY1pB=TQdО# f-|KsX Vӭc+^|N8fP0"4T$l<]Gds>uoR]yr̩H +,o}6BRwVEx_J^-B5qQM?QF|&)"o`.0q|Y>GzfAuAaŸT&ʥ_JTlן &{)f,oIDd9-H v?U^TQۻdRShaO=[U$e(Uy+)5HzZ#(3PH\汃`粙Ļ58v1 ?:#@٠RlW^}@WPvØvuʑv9bdoϹoU]Taҡz MitjVܑ-c1wg^k XQ~ֲe)LY쇭W砒`G㰛2Ǔ/At}xhTv'Ҫ_dV}:VKT%߭xP{~B<0Ciy>nϑ" lQo lm>@\ ciz!ㅕM$i4Tth R%mBUh;`e r w[;@4LPZqᅅq&[R D!3&.4jܤ(PPz JzC@ qtRW,7~l:H.l Gu"wڃ`0XJ.W͖~oa;]_[^oPAxE#ysm[0+Lخ 2'L*laHT0#/ے Go:yN_Q|d]OR)1Lq&dU9W**ԗ{8t iV.P[yA7>RViӰԌjە=/Ď+CXor.eVgU\G뗰l8BLT'<. {3ʱe}r.c|k/ 6GBPcmv&9"vW݇9?u|)=;P* 3,_z1\]m)-!İ6 ϻ7uHؙ Fy8*xp^c4 return date_format(date_create(), 'Y-m-d H:i:s:u'); } /** * 开始一个任务,如果任务不存在则创建新任务 * @param {string} taskmemo 任务说明 */ public function newTask($taskmemo) { $this->cur_state = $this->data[Scheduler::$START_KEY]; $db = $this->localStorage; //设置任务状态 $stateInfo = $this->setProcessingInfo($this->actionid, $taskmemo); //保存任务建立信息 $db->setRoot($this->getTaskRoot()); $db->sets($stateInfo); $this->localStorage->save(); return $stateInfo; } protected function createProcessingInfo($actionid, $memo, $docode = 0, $state = null) { $stateInfo = array( "actionid" => $actionid, "state" => (empty($state) ? $this->cur_state : $state), "taskid" => $this->taskid, "execute" => $docode, "userid" => $this->userid, "memo" => empty($memo) ? "" : $memo, "time" => Scheduler::now(), ); return $stateInfo; } protected function addTraceInfo($stateInfo) { /** * 保存当前的状态执行信息到追踪列表 */ $db = $this->localStorage; $db->setRoot($this->getTaskTraceRoot()); $db->addToList($stateInfo); } //设置任务的运行信息 protected function setProcessingInfo($actionid, $memo) { $db = $this->localStorage; //设置任务运行状态 $stateInfo = $this->createProcessingInfo($actionid, $memo); $db->setRoot($this->getTaskProcessingActionRoot($actionid)); $db->sets($stateInfo); $this->addTraceInfo($stateInfo); return $stateInfo; } //获取任务的运行信息 protected function getProcessingInfo($actionid) { $db = $this->localStorage; $root = $this->getTaskProcessingActionRoot($actionid); $db->setRoot($root); return $db->all(); } protected function deleteProcessingInfos() { $db = $this->localStorage; $oldstate = $this->cur_state; $deleteKeys = array(); foreach ($this->data[self::$STATE_ROOT_KEY] as $state => $stateinfo) { if (empty($stateinfo[self::$STATE_ACTION_ROOT_KEY])) continue; $this->cur_state = $state; foreach ($stateinfo[self::$STATE_ACTION_ROOT_KEY] as $actionid) { $deleteKeys[] = $db->getKey($this->getTaskProcessingActionRoot($actionid)); } } $this->cur_state = $oldstate; $db->deletes($deleteKeys); } /** * 添加trace信息,如果用户指定指定状态与真实状态不同写入realState,如果writeNewState为true还要写入newState * @param $actionid 本次的动作id * @param $memo 本次执行说明 * @param $newState 本次跳转的真实状态 * @param $jumpType 动作流转判定的返回码 * @param $realState 本次动作执行,用户指定的分支状态 * @param $writeNewState 是否需要写入$newState */ protected function addSubmitTraceInfo($actionid, $memo, $newState, $jumpType, $realState, $writeNewState) { if ($realState != $newState) { $stateInfo = $this->createProcessingInfo($actionid, $memo, $jumpType, $realState); $this->addTraceInfo($stateInfo); } if ($writeNewState){ $stateInfo = $this->createProcessingInfo($actionid, $memo, $jumpType, $newState); $this->addTraceInfo($stateInfo); } } /** * 设置提交信息,当用户提交状态时调用,以完成状态的切换 * @param {string} actionid 用户本次执行提交的action的id * @param {string} memo 用户本次提交的说明 * @param {string} newState 用户提交时指定将要流转的新状态码 * @param {int} jumpType newState指定的状态的跳转形式, 参见internalCheckState的状态代码返回说明 * @param {string} realState 用户输入的真实状态 */ protected function setSubmitStates($actionid, $memo, $newState, $jumpType, $realState) { $taskInfo = null; switch ($jumpType) { case 3: //最后节点并且为会签节点 case 2: //任务执行完毕 //将当前任务加入用户已经完结任务列表 $taskInfo = $this->getTask(); $taskInfo[self::$USER_END_FLOW_TIME_KEY] = self::now(); break; } $this->localStorage->calls( array( $this->getTaskProcessingActionRoot($actionid), $this->getTaskTraceRoot() ), function ($db, $scheduler, $jumpType, $memo, $newState, $actionid, $taskInfo, $realState) { if (empty($newState)) { return; } if (empty($scheduler->cur_state) || $scheduler->cur_state != $newState) { /** * 删除当前的执行信息 */ switch ($jumpType) { case 2: //终止节点,删除所有进行节点信息 case 4: //and未完成,跳转到其他非and节点,此时需要删除所有已经发布但未完成的任务 $scheduler->deleteProcessingInfos(); break; default: $db->setRoot($scheduler->getTaskProcessingActionRoot($actionid)); $db->delete(); break; } /** * 更新当前状态到新状态,并设置新的执行信息 */ switch ($jumpType) { case 1: case 5: break; default: //更新当前状态 $scheduler->cur_state = $newState; $stateInfo = $scheduler->data[self::$STATE_ROOT_KEY][$scheduler->cur_state]; switch ($jumpType) { case 3: //任务执行完毕,并且为会签节点 case 2: //任务执行完毕 //将当前任务加入用户已经完结任务列表 $db->setRoot($scheduler->getTaskCompleteKey($taskInfo[self::$TASK_USER_KEY])); $db->addToList($taskInfo); $scheduler->addSubmitTraceInfo($actionid, $memo, $newState, $jumpType, $realState, true); break; default: if (empty($stateInfo[self::$STATE_OPER_KEY])) { $scheduler->addSubmitTraceInfo($actionid, $memo, $newState, $jumpType, $realState, false); $scheduler->setProcessingInfo($actionid, $memo, $jumpType); } else { if ($stateInfo[self::$STATE_OPER_KEY] == self::$STATE_OPER_AND){ $scheduler->addSubmitTraceInfo($actionid, $memo, $newState, $jumpType, $realState, false); foreach ($stateInfo[self::$STATE_ACTION_ROOT_KEY] as $action_id) { $scheduler->setProcessingInfo($action_id, $memo, $jumpType); } } } break; } s4ht3H͹b@Ӷξ 4wg;jsjzƯc'IBJI6&׭urRM^:tMӻp2bf)n3nI4Q@3narS޶_ P= 4,!?vzDz b=+* CU=蕉@b}bAz|Ăz$X%, N٫g 2h*_0mQ]Yĕ2`Q=U@2*!\0v85&ʥO=sL{QP-j4PCF"kK~k2!j f2$9OnZnm|75\ f7l}xK*}&v i 00ٮ036dw a*t*dV PNϥ?%UQES!l/rO'=DrU_Xkm;3y,o WA8!#Ķ=On|5T$*ʇ͕Zx*4D?(<#N cǾ"\xQ C&w.v%DŃ(UDBTGCTP?D@l$?K$TŨoh;v)Š$SރP ^f&∔S^ڵYN])ڏ2C:B>\R;PKx,}(; @EM I;k^Uah'QQ-7 ,.f[N>K\qKxW?k;M ?CWQ#ƆtڍuH7<%[;}O0|=Y5v( e鴡Zhm&r⨥uuhd z۪>~u gas3t u伎| oޯ0 (l` NX< &YocO#zv2$j8#%!k瞌 uْQ;>< *[%¡2+}AWږg|CK+ v'| .4 ޛR|ˣlbύH0PUDִ (9?ز!hƵ9qe5I'jŜFF$dyj{.P݅_ Sd ?$^(_^h7cɽ|9nP0fcNDs& ˀuv vx<.'&<";bSF-|xaJĿ+zͨ9BsY :Xdd<#`)+`JU`9!/vb2EFӆMrw)B\L/e$4ڙ7㊻˘"-Gb8L~C1G'šF ~<7\f62 2֠h>gtmM/2~&be-n9I6gLX1xf*Is1R@{.buL/K%XߚMiRQ |R$nQ=B9Ax_#>[߯ĥ +\. ɇQusEnueBLɒޟIβ7nmYh hD3GGFddgcm%2(Z~j5s4Uh>^!B d029"SRk7hpA^!g"*#aW ի!mq8 .;d Ij:0L_Ыa9j%?5O6koLv]դ P.iA{45w HF}^Vqmd@ XAu (䙥ᓾ#m~R\[eCJj]`lbEoqAɟ戋"Cap ϯ? Nm<-?KQ[a4:4ܖ{M0a5X>8xsFŗbm.Tc@8cBʺ<Satw!<~hXۂoՇޕp4l,*O̅ / I6+ l[i U :%n4i-ʜzw^]‡Fh1 (5iBו4]C3]rE[!l!WJ>tEdܯھNʳK{WfRC/A5[t{ @vUhVrxzbYؤ[A'QspF0w8L|Yڡ+O AJoVz/K'MGtj$@}2ZH;Ի)$9k%^{fœVfb yȍ%A^huyt:+wpKj١Rix^ʳUC96vOk{j7+xh)t MA{ 3#0ISYxHe؉ѯ o`yMǫQ72܃ %ԷN\AT3(`q?,^>p f9d4>J+_·Kke$ οҔo߫jRҥ:_GO43Cy@֎D,V xN($9)4GB@_ ZIw"{=/1 =+X^n1X>'jqm4p۟E \Z .RI6@HIB6 {zO0LX,UU 'da"6 ~)0w`$.i2Q7t Gyzlr262$˖gLL@s8B 0AǍRzfܙ'UmJE6};"]٘ r,E Ʒ2tPt9ޑ12>!L {?Y< B~$lZ&R۽7qrk!,+eXQ.v60>%Y‚tK;@+c1n܈c|$wcQ۸zÍPFmU.ן7yp4OܿN)ַOa$=`F_\KHV(\bsR"#~߱;LlL AF[@6D"{۸_ŏOЏbonZ-y}Uz\@`P,X֘K}B>&9D'ۂ!Zi91@ :8zBaV`, wϹD@_PqyOnAV,P[ YθNvk9W}*t>7u; _AAU=0`| 0;Eb`$H|8چW%S\Uη;1Dxs:U">=ةDUlru7s]X!e^׾3&FYg9'mp gurŨs!0ȲC'zоih-1̿C U^*Qq2?A{lp7ޮ'wŤV!5>$ 2#,"g+e¡ ƹP5DOX?=hWC5s4;Y#x 6q̦E >~-iJedD LaJ r-[I|6VNH(ذ9KBGd8#AV1_ B6CXW0b]lu=5X , P^j~+^'Ȯ`ln ג?)#27izzIg>y|`Zo Bf) M#@d8K,^Bl%5˪L }HKbwy7ç3Vedl0UfSI㸱mQJRsEc=spw ͘ sJl2n~bY3>[ %㑮zG*#ɗpO3PMFp^WրyIE [HT' Zmpѻpۛƌ.i0P %6ɜ:W]t 1a B-NzD,چ,G]˿Aۜ 4.X%u%djgdÇҸ|vq:n~,u]vdT)uGwB%yeoQ4b-_jd啛ehσ8!kTQ;'ٟғ3&*ӱtumhu+`i \,)_F(vr7YMVa [BKZGf]WӡDc3^nFr)uS( wl;3%՜b:|n7I[!<)leW)ٿ8Ahۧ?UNR୙Tem#%;USn\@I`9Th b*r@.shh7wɿy5{h򒮼 ;~SIjlT5X;͚:{7.wW. _0 T#U{G4ئ7i JiAIob82X0dޭWig y= _6*tqރ+}4,|wO R%UْX&RAEu:sUb= /,KqjժտXCOFBXBj@;]3jTooy1hGݐP07~ iWPZNݭ&W~dTR1}L~KN0({:'.c'c'7Zc:tˆ1vrS GRanqS1jwyԥBVL5cbDiˀy{[ gzi&ir`wm0 0.ⳮ7/>4{xpq;/;, >wWJap- 8TVQ"5/¡7|]|CZt 6u3kjDfHTWiV)յ|Sc!LʰMtZ0JY^Qc8k#~6vyLs^ lQ&E`A*҄GmbBNΕȁ*N6>=}|LV+9%O=@z/(b(6mGEL1\*J @h-܀_Rv ]azЬY8xK 5ŷ?!D'v,(p_3|ېSo00z "H`Z`3(Hj.3ikF@݁5 XEKG(Tk_NW_. ݝqf87A漠B% KM؝6 6ۧpy9;G|чN\qg[n 3jP>NYRwĽA>톹)gdAݜI-X.]\kV lģ2KC2~ۏ9tʏ U#~E詟?kk =_HW,OXOuGv%׏';?PB35 Y9HԎ(/{F*y(b Ŋ c}NHlѬ1$5 @1>̮9s2R29yKۡ ; > ʆ|)jwTL1W+fEƦL_>-7[dA?kjip۷'y"КA["'i!T!HU`ˁi>?{_ᢸ5Xw1 piz 3"DTܝ;<k^>#J XQY3 ɬ}n9<5的状态码,不能为null * @param {string} memo 本次动作执行的说明 * @return {json{ret:0, state:"状态码"}} * * ret含义如下: * 0当前节点可跳转,state为目标状态码 * 1当前节点不可跳转,等待其他节点状态完成,state为目标状态码 * 2当前节点已经为最后一个可执行状态节点,state为终止状态码 * 3当前节点已经为最后一个可执行状态节点,且通过会签的非会签节点跳转到此节点,state为终止状态码 * 4当前节点可以跳转,并且当前为and节点[会签],但输入的状态并不是and状态集合中的一个,说明客户做了and外的跳转, * 5当前节点不可以跳转,输入的state不是当前任务的合法下级节点, * 6当前节点可以跳转,多个and节点全部完成, * * 一般是会签情况下,某一个参与者选择了驳回,state为目标状态码 * state:目标状态码,一般为输入state,但如果有多对一情况,则为下一级action的前置状态码 */ public function action($decide, $memo = null) { $info = $this->checkState($decide); if ($info["ret"] == 5) { return 5; } $isAnd = $info["ret"] == 7; $needSave = true; $countersignState = null; if ($isAnd) { $countersignState = $this->getCountersignState($info["state"]); $isAnd = !empty($countersignState); } if ($isAnd) { $result = $this->checkCountersignState($info["state"], $countersignState); switch ($result) { case 0: //是会签节点,全部完成,可以跳转 $memo = "会签自动跳转"; $info["ret"] = 6; $this->addTraceInfo($this->createProcessingInfo($this->actionid, $memo, $info["ret"], $info["state"])); break; case -1: //是会签节点,但未全部完成,不可以跳转 $info["ret"] = 1; $needSave = false; //存储用户的跳转状态 $this->addTraceInfo($this->createProcessingInfo($this->actionid, $memo, $info["ret"], $info["state"])); break; case 1: //不是会签节点 $info["ret"] = 4; break; } } if ($needSave) { $state = $this->getJumpState($info["state"]); if ($this->isEndState($state)) { $info["ret"] = ($isAnd && $info["ret"] == 6) ? 3 : 2; } $this->setSubmitStates($this->actionid, $memo, $state, $info["ret"], $info["state"]); $info["inputstate"] = $info["state"]; $info["jumpedstate"] = $state; } return $info; } /** * 获取uiid对应的action信息 * @param {string} uiid Gaea中的模块节点name * @return 如果此uiid对应的action为多个,返回action信息的array,否则返回action信息 */ public function getActionInfoForUIID($uiid) { if (empty($this->data[self::$UI_ROOT_KEY][$uiid])) { throwException("not found uiid[" . $uiid . "]"); } return $this->data[self::$UI_ROOT_KEY][$uiid]; } /** * 获取action信息 * @param {string} 要获取的actionid,不可以为null * @return {Action} 返回action的信息 */ public function getActionInfo($actionid) { $info = $this->data[self::$PROCESS_ROOT_KEY][$actionid]; if (empty($info)) { throwException("cur state not found!"); } return $info; } /** * 获取指定actionid的权限信息 * @param {string} 要获取权限的动作id * @return 权限信息列表,格式:{"权限id":"权限名称"} */ public function roles($actionid) { $action = $this->getActionInfo($actionid); if (empty($action)) { return array(); } return $action[self::$ACTION_ROLE_KEY]; } /** * 获取指定状态下所有操作的权限信息,可能返回空数组:[] * @param {string} 要获取权限的状态 * @return 权限信息列表,格式:[{"name":"权限名称","id":"权限id"}] */ public function getStateRoles($state) { //获取状态信息 $info = $this->data[self::$STATE_ROOT_KEY][$state]; if (empty($info[self::$ACTION_NODE_KEY])){ return array(); } $result = array(); foreach($info[self::$ACTION_NODE_KEY] as $actionid){ $roles = $this->roles($actionid); if (!empty($roles)){ foreach($roles as $key=>$role){ $arr = array("id"=>$key,"name"=>$role); $result[] = $arr; } } } return $result; } protected function findInfo($baseKey, $key = null, $start = null, $size = null) { if (empty($key)) { $key = "*"; } $db = $this->localStorage; $keys = $db->findKeys($baseKey . (empty($key) ? "" : $key)); $result = array(); foreach ($keys as $key) { $db->setRealRoot($key); $info = $db->all($start, $size); if (!empty($info)) { $result[] = $info; } } return $result; } /** * 获取已经流转到指定动作的任务列表,如果roles指定的用户权限和动作的role权限不符,则返回array() * @param {jsonobject} roles 用户的权限信息,格式{"组id":"1"} * @param {string} actionid 获取任务列表的动作id * @param {int} start 查询的起始索引,从0开始,默认为0 * @param {int} size 返回的最大结果数量,默认为20 * @return {array} 返回所有符合要求的任务信息 * 任务数据格式参见getTaskProcessingActionRoot */ public function getActionTasks($roles, $actionid, $start = null, $size = null) { if (empty($actionid)) { $actionid = $this->actionid; } $deny = true; foreach ($this->roles($actionid) as $key=> $role) { if (!empty($roles[$key])) { $deny = false; break; } } if ($deny) { return array(); } return $this->findInfo($this->getTaskProcessingActionKey($actionid), null, $start, $size); } /** * 或者当前用户的当前任务在指定的动作处的状态信息 * @param actionid 要查询的动作id * @return 如果有用户已经完成这个动作,返回array(),否则返回状态信息 */ public function getCurTask($actionid) { if (empty($actionid)) { $actionid = $this->actionid; } $db = $this->localStorage; $db->setRoot($this->getTaskProcessingActionRoot($actionid)); return $db->all(); } /** * 返回当前用户的历史任务数据 */ public function getHistoryTasks($key = null, $start = null, $size = null) { if (empty($key)) { $key = "*"; } $result = $this->findInfo($this->getTaskCompleteRoot(), $key, $start, $size); if (count($result) == 0) return array(); else return $result[0]; } /** * 查询当前任务的执行痕迹 */ public function traceTask() { $info = $this->findInfo($this->getTaskTraceKey(), null); if (count($info) == 0) { return array(); } else { return $info[0]; } } public function __construct($userid, $taskid, $flowname = null, $uiid = null, $roles = null) { $this->userid = $usOc{ 3JD AJOɛ۬'D݌./H/]X?~WݙSZ4I <}l3XalZn\c$rB@J)Xcb ۆPc EG~i}ʍIl㌛WI8@KvfݶeAaEEcSqgpG"vb(l\[ا[*nli\Kk-,j~lITG ӟ"f)+k;{h: P1Lҧ![nYph2J!&(wnAq1PiDWmRrNjoLY/mxb1x W -_)-,zNvܚ )R\̍AZ}U? /w6> |g1{\DL1w2kk}* I?٥Z/'gP/ЂgD Er37_b@:+>0jRVZ:r,Q( BHGO @ZvtxlQ4 Izr mLeViNˠɓ-,+Ķ.Ѽ- ^)B]\1q9RtPv)j5`0!c=al2Q`p-O͞tbm~|<<5$2#Yv뢝 F<&΄6z\ysOnny> {W>X%0{~O7T JuQw-w-s}ݢm4VHKwD!H2I߃r,Zz Bjjå ABI#=6A]됹U/La:ۏߞH$7G`|1+ ZQ u~O+'袄v-3M0\bA "n^a>i2mE o|J wFy{M~b?z36VB/HiA\QRH6@@*. )JKAç?dy8ؔQ*rA B`TznF ny{y&D6`Ѫ-/;d@*ZF2G ApM ,$&Od"g̅4D)gt¬eYu_UD,/!X 3S2٢a:%!QGS59=ZBߝ_WÀkZn2Zm7&O1\S?aa&o7?&Ლ 87.c1eq>#6_uo8vxtI~JRaD*i]&ZN \1Cio$~N$~Tcg@f'Q86|@417A_