common.php 120KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326
  1. <?php
  2. error_reporting(E_ERROR | E_PARSE);
  3. /**
  4. * 行为绑定
  5. */
  6. \think\Hook::add('app_init', 'app\\common\\behavior\\InitConfigBehavior');
  7. use app\common\adapter\AuthAdapter;
  8. use app\admin\model\User as UserModel;
  9. use app\admin\model\Field as FieldModel;
  10. use think\Request;
  11. use think\Db;
  12. use extend\email\Email;
  13. use think\Lang;
  14. use think\helper\Time;
  15. use com\IpLocation;
  16. use app\crm\traits\DataTime;
  17. /**
  18. * 对象 转 数组
  19. *
  20. * @param object $obj 对象
  21. * @return array
  22. */
  23. function object_to_array($obj)
  24. {
  25. $obj = (array)$obj;
  26. foreach ($obj as $k => $v) {
  27. if (gettype($v) == 'resource') {
  28. return;
  29. }
  30. if (gettype($v) == 'object' || gettype($v) == 'array') {
  31. $obj[$k] = (array)object_to_array($v);
  32. }
  33. }
  34. return $obj;
  35. }
  36. /**
  37. * 数组 转 对象
  38. *
  39. * @param array $arr 数组
  40. * @return object
  41. */
  42. function array_to_object($arr)
  43. {
  44. if (gettype($arr) != 'array') {
  45. return;
  46. }
  47. foreach ($arr as $k => $v) {
  48. if (gettype($v) == 'array' || getType($v) == 'object') {
  49. $arr[$k] = (object)array_to_object($v);
  50. }
  51. }
  52. return (object)$arr;
  53. }
  54. /**
  55. * 返回对象
  56. * @param array $array 响应数据
  57. */
  58. function resultArray($array)
  59. {
  60. if (isset($array['data'])) {
  61. $array['error'] = '';
  62. $code = 200;
  63. } elseif (is_array($array['error'])) {
  64. $code = 402; //返回数组格式
  65. $array['data'] = '';
  66. } elseif (isset($array['error'])) {
  67. $code = 400;
  68. $array['data'] = '';
  69. }
  70. return json([
  71. 'code' => $code,
  72. 'data' => $array['data'],
  73. 'error' => $array['error']
  74. ]);
  75. }
  76. /**
  77. * 调试方法
  78. * @param array $data [description]
  79. */
  80. function p($data, $die = 1)
  81. {
  82. echo "<pre>";
  83. print_r($data);
  84. echo "</pre>";
  85. if ($die) die;
  86. }
  87. /**
  88. * 用户密码加密方法
  89. * @param string $str 加密的字符串
  90. * @param [type] $auth_key 加密符
  91. * @param [string] $username 用户名
  92. * @return string 加密后长度为32的字符串
  93. */
  94. function user_md5($str, $auth_key = '', $username = '')
  95. {
  96. return '' === $str ? '' : md5(sha1($str) . md5($str . $auth_key));
  97. }
  98. /**
  99. * 金额展示规则,超过1万时以万为单位,低于1万时以千为单位,低于1千时以元为单位
  100. * @param string $money 金额
  101. * @return string
  102. * @author Michael_xu
  103. */
  104. function money_view($money)
  105. {
  106. $data = '0元';
  107. if (($money / 10000) > 1) {
  108. $data = is_int($money / 10000) ? ($money / 10000) . '万' : rand(($money / 10000), 2) . '万';
  109. } elseif (($money / 1000) > 1) {
  110. $data = is_int($money / 1000) ? ($money / 1000) . '千' : rand(($money / 1000), 2) . '千';
  111. } else {
  112. $data = $money . '元';
  113. }
  114. return $data;
  115. }
  116. /**
  117. * 高级筛选条件
  118. * @param $array 条件数组
  119. * @param $module 相关模块
  120. * @return string
  121. * @author Michael_xu
  122. */
  123. function where_arr($array = [], $m = '', $c = '', $a = '')
  124. {
  125. $userModel = new UserModel();
  126. $checkStatusList = ['待审核', '审核中', '审核通过', '审核失败', '已撤回', '未提交', '已作废'];
  127. $checkStatusArray = ['待审核' => 0, '审核中' => 1, '审核通过' => 2, '审核失败' => 3, '已撤回' => 4, '未提交' => 5, '已作废' => 6];
  128. //查询自定义字段模块多选字段类型
  129. $check_field_arr = [];
  130. //特殊字段
  131. //过滤系统参数
  132. $unset_arr = ['page', 'limit', 'order_type', 'order_field'];
  133. if (!is_array($array)) {
  134. return [];
  135. }
  136. $types = $c;
  137. foreach ($array as $k => $v) {
  138. if (!in_array($k, $unset_arr)) {
  139. $c = $types . '.';
  140. if ($k == 'customer_name') {
  141. $k = 'name';
  142. $c = 'customer.';
  143. }
  144. if ($k == 'contract_name') {
  145. $k = 'name';
  146. $c = 'contract.';
  147. }
  148. if ($k == 'business_name') {
  149. $k = 'name';
  150. $c = 'business.';
  151. }
  152. if ($k == 'contacts_name') {
  153. $k = 'name';
  154. $c = 'contacts.';
  155. }
  156. if ($v['form_type'] == 'date') {
  157. if (!empty($v['start'])) $v['start'] = date('Y-m-d', $v['start']);
  158. if (!empty($v['end'])) $v['end'] = date('Y-m-d', $v['end']);
  159. }
  160. # 自定义字段的user team_id(非自定义字段)
  161. if ($v['form_type'] == 'user' && in_array($k, ['team_id'])) {
  162. // ro_user_id rw_user_id
  163. if ($v['condition'] == 'in') {
  164. return "(" . $c . 'ro_user_id' . " like ',%" . $v['value'] . "OR " . $c . 'rw_user_id' . " like ',%" . $v['value'] . ")";
  165. } elseif ($v['condition'] == 'not in') {
  166. return "(" . $c . $k . " not like ',%" . $v['value'][0] . "%,' OR " . $c . $k . " is null)";
  167. } elseif ($v['condition'] == 'isNull') {
  168. return "(" . $c . 'ro_user_id' . "eq" . $v['value'] . "OR " . $c . 'rw_user_id' . " eq" . $v['value'] . ")";
  169. } elseif ($v['condition'] == 'isNotNull') {
  170. return "(" . $c . 'ro_user_id' . "neq" . $v['value'] . "OR " . $c . 'rw_user_id' . " neq" . $v['value'] . ")";
  171. }
  172. }
  173. # 自定义字段的user、structure类型
  174. if (($v['form_type'] == 'user' && !in_array($k, ['create_user_id', 'owner_user_id'])) || $v['form_type'] == 'structure') {
  175. if ($v['condition'] == 'is') $v['condition'] = 'contains';
  176. if ($v['condition'] == 'isNot') {
  177. return "(" . $c . $k . " not like ',%" . $v['value'][0] . "%,' OR " . $c . $k . " is null)";
  178. }
  179. }
  180. # 处理多选字段的精确搜索
  181. if ($v['form_type'] == 'checkbox' && !empty($v['value'])) {
  182. if ($v['condition'] == 'is' && count($v['value']) == 1) $v['value'][0] = ',' . $v['value'][0] . ',';
  183. if ($v['condition'] == 'is' && count($v['value']) > 1) {
  184. $checkboxLike = '';
  185. foreach ($v['value'] as $kk => $vv) {
  186. $checkboxLike .= $c . $k . " like " . "',%" . $vv . "%,' AND ";
  187. }
  188. return "(" . $checkboxLike . "LENGTH(" . $c . $k . ") = LENGTH('" . arrayToString($v['value']) . "'))";
  189. }
  190. }
  191. if ($types == 'contract' && !empty($v['value'])) {
  192. switch ($k) {
  193. case 'business_id' :
  194. $k = 'name';
  195. $c = 'business.';
  196. break;
  197. case 'contacts_id' :
  198. $contactsIds = [];
  199. foreach ($v['value'] as $kk => $vv) {
  200. $contactsIdArray = db('crm_contacts')->whereLike('name', '%' . $vv . '%')->column('contacts_id');
  201. foreach ($contactsIdArray as $kkk => $vvv) {
  202. $contactsIds[] = $vvv;
  203. }
  204. }
  205. $v['value'] = array_unique($contactsIds);
  206. break;
  207. }
  208. }
  209. if ($types == 'receivables' && $v['name'] == '合同编号' && !empty($v['value'])) {
  210. $k = 'num';
  211. $c = 'contract.';
  212. }
  213. if ($types == 'receivables' && $k == 'plan_id' && !empty($v['value'])) {
  214. $planIds = [];
  215. foreach ($v['value'] as $kk => $vv) {
  216. $planIdArray = db('crm_receivables_plan')->whereLike('num', '%' . $vv . '%')->column('plan_id');
  217. foreach ($planIdArray as $kkk => $vvv) {
  218. $planIds[] = $vvv;
  219. }
  220. }
  221. $v['value'] = array_unique($planIds);
  222. }
  223. if ($types == 'invoice' && $v['type'] == 'invoice_status' && !empty($v['value'])) {
  224. foreach ($v['value'] as $kk => $vv) {
  225. if ($vv == '已开票') $v['value'][$kk] = 1;
  226. if ($vv == '未开票') $v['value'][$kk] = 0;
  227. }
  228. }
  229. if ($types == 'visit' && $v['type'] == 'contract_name' && !empty($v['value'])) {
  230. $k = 'num';
  231. $c = 'contract.';
  232. }
  233. if ($types == 'visit' && $v['type'] == 'contacts_name' && !empty($v['value'])) {
  234. $k = 'name';
  235. $c = 'contacts.';
  236. }
  237. if ($k == 'check_status' && is_array($v) && in_array($v['value'][0], $checkStatusList) && !empty($v['value'])) {
  238. $v['value'] = $checkStatusArray[$v['value'][0]] ?: '0';
  239. }
  240. if (is_array($v)) {
  241. if ($v['state']) {
  242. $address_where[] = '%' . $v['state'] . '%';
  243. if ($v['city']) {
  244. $address_where[] = '%' . $v['city'] . '%';
  245. if ($v['area']) {
  246. $address_where[] = '%' . $v['area'] . '%';
  247. }
  248. }
  249. if ($v['condition'] == 'not_contain') {
  250. $where[$c . $k] = ['notlike', $address_where, 'OR'];
  251. } else {
  252. $where[$c . $k] = ['like', $address_where, 'AND'];
  253. }
  254. } elseif (!empty($v['value']['state'])) {
  255. $addressWhere[] = '%' . $v['value']['state'] . '%';
  256. if (!empty($v['value']['city'])) $addressWhere[] = '%' . $v['value']['city'] . '%';
  257. if (!empty($v['value']['area'])) $addressWhere[] = '%' . $v['value']['area'] . '%';
  258. if ($v['condition'] == 'is') {
  259. $where[$c . $k] = ['like', $addressWhere, 'AND'];
  260. } else {
  261. $where[$c . $k] = ['notlike', $addressWhere, 'OR'];
  262. }
  263. } elseif (!empty($v['start']) || !empty($v['end'])) {
  264. if ($v['start'] && $v['end']) {
  265. $where[$c . $k] = ['between', [$v['start'], $v['end']]];
  266. } elseif ($v['start']) {
  267. $where[$c . $k] = ['egt', $v['start']];
  268. } else {
  269. $where[$c . $k] = ['elt', $v['end']];
  270. }
  271. } elseif (!empty($v['start_date']) || !empty($v['end_date'])) {
  272. if ($v['start_date'] && $v['end_date']) {
  273. $where[$c . $k] = ['between', [$v['start_date'], $v['end_date']]];
  274. } elseif ($v['start_date']) {
  275. $where[$c . $k] = ['egt', $v['start_date']];
  276. } else {
  277. $where[$c . $k] = ['elt', $v['end_date']];
  278. }
  279. } elseif (!empty($v['value']) || $v['value'] === '0') {
  280. if (in_array($k, $check_field_arr)) {
  281. $where[$c . $k] = field($v['value'], 'contains');
  282. } else {
  283. if ($v['condition'] == 'isNot' || $v['condition'] == 'notContains') {
  284. $where[$c . $k] = [field($v['value'], $v['condition'], $k), ['null'], 'or'];
  285. } else {
  286. $where[$c . $k] = field($v['value'], $v['condition'], $k);
  287. }
  288. }
  289. } elseif (in_array($v['condition'], ['isNull', 'isNotNull', 'in'])) {
  290. $where[$c . $k] = field($v['value'], $v['condition']);
  291. } else {
  292. $where[$c . $k] = $v;
  293. }
  294. } elseif (!empty($v)) {
  295. $where[$c . $k] = field($v);
  296. } else {
  297. $where[$c . $k] = $v;
  298. }
  299. }
  300. }
  301. # 商机阶段为赢单、输单、无效的值保存在is_end中,将status_id改为is_end;
  302. if (!empty($where['business.status_id']) && in_array($where['business.status_id'][1], [1, 2, 3])) {
  303. $where['business.is_end'] = $where['business.status_id'];
  304. unset($where['business.status_id']);
  305. }
  306. return $where ?: [];
  307. }
  308. /**
  309. * 高级筛选
  310. *
  311. * @param array $param 搜索参数
  312. * @param string $m 模块:crm log work ...
  313. * @param string $c 栏目:leads customer ...
  314. * @param string $a 方法:index save ...
  315. * @return array
  316. * @since 2021-05-20
  317. * @author fanqi
  318. */
  319. function advancedQuery($param, $m = '', $c = '', $a = '')
  320. {
  321. // 结果数据
  322. $result = [];
  323. // 原始前缀
  324. $prefix = $c . '.';
  325. // 等于(时间段)类型
  326. $betweenType = [
  327. 'year', 'lastYear', 'nextYear', 'firstHalfYear', 'nextHalfYear', 'quarter', 'lastQuarter',
  328. 'nextQuarter', 'month', 'lastMonth', 'nextMonth', 'week', 'lastWeek', 'nextWeek', 'today',
  329. 'yesterday', 'tomorrow', 'previous7day', 'previous30day', 'future7day', 'future30day'
  330. ];
  331. foreach ($param as $key => $value) {
  332. // 过滤不能参与搜索的字段类型
  333. if (!empty($value['form_type']) && in_array($value['form_type'], ['file', 'handwriting_sign', 'desc_text', 'detail_table', 'date_interval'])) continue;
  334. // 初始化前缀
  335. $c = $prefix;
  336. // 清除空格
  337. if (isset($value['condition'])) $value['condition'] = trim($value['condition']);
  338. // 处理表前缀和字段名称
  339. list($c, $key) = advancedQueryParam($c, $key, $value['name']);
  340. if ($key == 'check_status' && !is_array($value)) $result[$c . $key] = $value;
  341. if ($key == 'status_id' && !is_array($value)) $result[$c . $key] = $value;
  342. if ($key == 'customer_id' && !is_array($value)) $result['customer.' . $key] = $value;
  343. if ($key == 'contract_id' && !is_array($value)) $result['contract.' . $key] = $value;
  344. if ($key == 'business_id' && !is_array($value)) $result['business.' . $key] = $value;
  345. // 仪表盘参数
  346. if (!empty($value['value'][0]) && empty($value['condition'])) {
  347. $value['condition'] = 'is';
  348. $value['form_type'] = 'user';
  349. }
  350. if (!empty($value['start']) && !empty($value['end'])) {
  351. $value['value'][0] = date('Y-m-d H:i:s', $value['start']);
  352. $value['value'][1] = date('Y-m-d H:i:s', $value['end']);
  353. $value['form_type'] = 'datetime';
  354. $value['condition'] = 'between';
  355. }
  356. if ($key == 'check_status' && !is_array($value)) {
  357. unset($value);
  358. $value['value'][0] = '审核通过';
  359. $value['form_type'] = 'check_status';
  360. $value['name'] = '审核状态';
  361. $value['type'] = 'check_status';
  362. $value['condition'] = 'is';
  363. }
  364. // 代办事项
  365. if (isset($value) && !isset($value['condition']) && !isset($value['value']) && !isset($value['form_type'])) {
  366. $result[$c . $key] = is_array($value) ? $value : ['in', $value];
  367. continue;
  368. }
  369. // 等于(时间段)类型筛选
  370. if (!empty($value['value'][0]) && in_array($value['value'][0], $betweenType)) {
  371. $value = advancedQueryHandleDate($value);
  372. }
  373. // 创建人、负责人
  374. if (in_array($key, ['create_user_id', 'owner_user_id'])) {
  375. if($value['condition'] == 'contains'){
  376. $result[$c . $key] = ['in', $value['value']];
  377. }else if ($value['condition'] == 'notContains') {
  378. $result[$c . $key] = ['not in', $value['value']];
  379. }else if ($value['condition'] == 'isNull') {
  380. $result[$c . $key] = ['eq', ''];
  381. }else if ($value['condition'] == 'isNotNull') {
  382. $result[$c . $key] = ['neq', ''];
  383. }
  384. }
  385. // 模块、审核状态、成交状态、产品分类、单行文本、多行文本、网址、手机、邮箱、下拉框、布尔值、多选、定位、创建人、负责人
  386. if (isset($value['form_type']) && in_array($value['form_type'], ['module', 'check_status', 'deal_status', 'category', 'text', 'textarea', 'mobile', 'email', 'select', 'boolean_value', 'checkbox', 'location', 'website','user',])) {
  387. $res = advancedQueryFormatForCommon($value['value'], $value['condition'], $value['form_type'], $key);
  388. if($key == 'order_id'){
  389. $arr = [];
  390. if($c == 'outbound.'){
  391. $retreatOutboundIds = db('jxc_retreat')
  392. ->alias('a')
  393. ->join('jxc_outbound b','a.retreat_id = b.order_id')
  394. ->where('a.order_number', [$res[0], $res[1]])
  395. ->where('b.outbound_type', '采购退货出库')
  396. // ->fetchSql()
  397. ->column('outbound_id');
  398. $saleOutboundIds = db('jxc_sale')
  399. ->alias('a')
  400. ->join('jxc_outbound b','a.sale_id = b.order_id')
  401. ->where('a.order_number', [$res[0], $res[1]])
  402. ->where('b.outbound_type', '销售出库')
  403. // ->fetchSql()
  404. ->column('outbound_id');
  405. $arr = empty($retreatOutboundIds) ? $saleOutboundIds : array_merge($retreatOutboundIds,$saleOutboundIds);
  406. $result[$c . 'outbound_id'] = ['in', $arr];
  407. }elseif ($c == 'receipt.') {
  408. $purchaseOutboundIds = db('jxc_purchase')
  409. ->alias('a')
  410. ->join('jxc_receipt b','a.purchase_id = b.order_id')
  411. ->where('a.order_number', [$res[0], $res[1]])
  412. ->where('b.receipt_type', '采购入库')
  413. // ->fetchSql()
  414. ->column('b.receipt_id');
  415. $salereturnOutboundIds = db('jxc_salereturn')
  416. ->alias('a')
  417. ->join('jxc_receipt b','a.salereturn_id = b.order_id')
  418. ->where('a.order_number', [$res[0], $res[1]])
  419. ->where('b.receipt_type', '销售退货入库')
  420. // ->fetchSql()
  421. ->column('b.receipt_id');
  422. $arr = empty($purchaseOutboundIds) ? $salereturnOutboundIds : array_merge($purchaseOutboundIds,$salereturnOutboundIds);
  423. $result[$c . 'receipt_id'] = ['in', $arr];
  424. }
  425. }else if($key == 'related_id'){
  426. $arr = [];
  427. if($c == 'collection.'){
  428. $retreatOutboundIds = db('jxc_retreat')
  429. ->alias('a')
  430. ->join('jxc_collection b','a.retreat_id = b.related_id')
  431. ->where('a.order_number', [$res[0], $res[1]])
  432. ->where('b.collection_type', '采购退货')
  433. // ->fetchSql()
  434. ->column('collection_note_id');
  435. $saleOutboundIds = db('jxc_sale')
  436. ->alias('a')
  437. ->join('jxc_collection b','a.sale_id = b.related_id')
  438. ->where('a.order_number', [$res[0], $res[1]])
  439. ->where('b.collection_type', '销售回款')
  440. // ->fetchSql()
  441. ->column('collection_note_id');
  442. $arr = empty($retreatOutboundIds) ? $saleOutboundIds : array_merge($retreatOutboundIds,$saleOutboundIds);
  443. $result[$c . 'collection_note_id'] = ['in', $arr];
  444. }elseif ($c == 'payment.') {
  445. $purchaseOutboundIds = db('jxc_purchase')
  446. ->alias('a')
  447. ->join('jxc_payment b','a.purchase_id = b.related_id')
  448. ->where('a.order_number', [$res[0], $res[1]])
  449. ->where('b.payment_type', '采购')
  450. // ->fetchSql()
  451. ->column('b.payment_note_id');
  452. $salereturnOutboundIds = db('jxc_salereturn')
  453. ->alias('a')
  454. ->join('jxc_payment b','a.salereturn_id = b.related_id')
  455. ->where('a.order_number', [$res[0], $res[1]])
  456. ->where('b.payment_type', '销售退货')
  457. // ->fetchSql()
  458. ->column('b.payment_note_id');
  459. $arr = empty($purchaseOutboundIds) ? $salereturnOutboundIds : array_merge($purchaseOutboundIds,$salereturnOutboundIds);
  460. $result[$c . 'payment_note_id'] = ['in', $arr];
  461. }
  462. }else if($key == 'collection_object'){
  463. $arr = [];
  464. if($c == 'collection.'){
  465. $supplierOutboundIds = db('jxc_supplier')
  466. ->alias('a')
  467. ->join('jxc_collection b','a.supplier_id = b.collection_object')
  468. ->where('a.supplier_name', [$res[0], $res[1]])
  469. ->where('b.collection_type', '采购退货')
  470. // ->fetchSql()
  471. ->column('collection_note_id');
  472. $customerOutboundIds = db('crm_customer')
  473. ->alias('a')
  474. ->join('jxc_collection b','a.customer_id = b.collection_object')
  475. ->where('a.name', [$res[0], $res[1]])
  476. ->where('b.collection_type', '销售回款')
  477. // ->fetchSql()
  478. ->column('collection_note_id');
  479. $arr = empty($supplierOutboundIds) ? $customerOutboundIds : array_merge($supplierOutboundIds,$customerOutboundIds);
  480. $result[$c . 'collection_note_id'] = ['in', $arr];
  481. }elseif ($c == 'payment.') {
  482. $supplierOutboundIds = db('jxc_supplier')
  483. ->alias('a')
  484. ->join('jxc_payment b','a.supplier_id = b.collection_object')
  485. ->where('a.supplier_name', [$res[0], $res[1]])
  486. ->where('b.payment_type', '采购')
  487. // ->fetchSql()
  488. ->column('b.payment_note_id');
  489. $customerOutboundIds = db('crm_customer')
  490. ->alias('a')
  491. ->join('jxc_payment b','a.customer_id = b.collection_object')
  492. ->where('a.name', [$res[0], $res[1]])
  493. ->where('b.payment_type', '销售退货')
  494. // ->fetchSql()
  495. ->column('b.payment_note_id');
  496. $arr = empty($supplierOutboundIds) ? $customerOutboundIds : array_merge($supplierOutboundIds,$customerOutboundIds);
  497. $result[$c . 'payment_note_id'] = ['in', $arr];
  498. }
  499. // }else if($key == 'sp_data_value'){
  500. // foreach ($res[1] as $key => $v) {
  501. // $arr[] = '%'.$v.'%';
  502. // }
  503. // $w['sp_data_value'] = ['like', $arr, 'OR'];
  504. // $product_ids = db('jxc_product')->where($w)->fetchSql()->column('product_id');
  505. // $result[$c . 'sp_data_value'] = [$res[0], $product_ids];
  506. }else{
  507. $result[$c . $key] = advancedQueryFormatForCommon($value['value'], $value['condition'], $value['form_type'], $key);
  508. }
  509. }
  510. // 日期、日期时间、数字、货币、百分数、下次联系时间
  511. if (isset($value['form_type']) && in_array($value['form_type'], ['date', 'datetime', 'number', 'floatnumber', 'percent', 'next_time'])) {
  512. $result[$c . $key] = advancedQueryFormatForDate($value);
  513. }
  514. // 地址(固定字段)、地址(自定义字段)
  515. if (isset($value['form_type']) && in_array($value['form_type'], ['map_address', 'position'])) {
  516. $result[$c . $key] = advancedQueryFormatForAddress($value['value'], $value['form_type']);
  517. }
  518. // 人员、部门
  519. if (isset($value['form_type']) && in_array($value['form_type'], ['user', 'structure', 'single_user']) && !in_array($key, ['create_user_id', 'owner_user_id']) && $value['type'] != 'team_id') {
  520. if ($value['type'] == 'owner_structure') { # 所属部门
  521. $userIds = db('admin_user')->whereIn('structure_id', implode(',', $value['value']))->column('id');
  522. $result[$c . 'owner_user_id'] = ['in', $userIds];
  523. } else {
  524. $result[$c . $key] = advancedQueryFormatForPersonnel($value['value'], $value['condition']);
  525. }
  526. }
  527. // 商机状态组
  528. if (isset($value['form_type']) && $value['form_type'] == 'business_type') {
  529. if (!empty($value['type_id'])) $result[$c . 'type_id'] = ['eq', $value['type_id']];
  530. if (!empty($value['status_id']) && in_array($value['status_id'], [1, 2, 3])) $result[$c . 'is_end'] = ['eq', $value['status_id']];
  531. if (!empty($value['status_id']) && !in_array($value['status_id'], [1, 2, 3])) $result[$c . 'status_id'] = ['eq', $value['status_id']];
  532. }
  533. // 回款计划
  534. if (isset($value['form_type']) && $value['form_type'] == 'receivables_plan' && !empty($value['value'])) {
  535. $result[$c . 'plan_id'] = advancedQueryFormatForPlan($value['value']);
  536. }
  537. }
  538. return $result;
  539. }
  540. /**
  541. * 处理高级筛选查询前缀、字段名称
  542. *
  543. * @param string $prefix 表前缀
  544. * @param string $field 字段名
  545. * @param string $name 字段中文名
  546. * @return array
  547. * @since 2021-05-22
  548. * @author fanqi
  549. */
  550. function advancedQueryParam($prefix, $field, $name)
  551. {
  552. // 要变更的前缀
  553. $prefixChange = [
  554. 'customer_name' => 'customer.',
  555. 'contacts_name' => 'contacts.',
  556. 'business_name' => 'business.',
  557. 'contract_name' => 'contract.',
  558. 'business_id' => 'business.',
  559. 'contacts_id' => 'contacts.',
  560. 'supplier_id' => 'supplier.',
  561. 'purchase_id' => 'purchase.',
  562. 'sale_id' => 'sale.',
  563. 'warehouse_id' => 'warehouse.',
  564. 'original_warehouse_id' => 'warehouse.',
  565. 'current_warehouse_id' => 'warehouse.',
  566. ];
  567. # 处理供应商
  568. if (in_array($field, ['supplier_id'])) {
  569. $prefix = $prefixChange[$field];
  570. $field = 'supplier_name';
  571. }
  572. # 处理仓库
  573. if (in_array($field, ['warehouse_id'])) {
  574. $prefix = $prefixChange[$field];
  575. $field = 'warehouse_name';
  576. }
  577. if (in_array($field, ['original_warehouse_id', 'current_warehouse_id'])) {
  578. $prefix = $prefixChange[$field];
  579. $field = 'warehouse_name';
  580. }
  581. # 采购单、销售单
  582. if (in_array($field, ['purchase_id', 'sale_id'])) {
  583. $prefix = $prefixChange[$field];
  584. $field = 'order_number';
  585. }
  586. // 处理客户名称、联系人名称、商机名称、合同名称字段
  587. if (in_array($field, ['customer_name', 'contacts_name', 'business_name', 'contract_name']) && $name != '合同编号') {
  588. $prefix = $prefixChange[$field];
  589. $field = 'name';
  590. }
  591. // 处理合同下的商机ID、客户ID字段
  592. if ($prefix == 'contract.' && in_array($field, ['business_id', 'contacts_id'])) {
  593. $prefix = $prefixChange[$field];
  594. $field = 'name';
  595. }
  596. // 处理回款、回访下的合同编号
  597. if (in_array($prefix, ['receivables.', 'visit.']) && $name == '合同编号') {
  598. $prefix = 'contract.';
  599. $field = 'num';
  600. }
  601. // 处理回访下的联系人
  602. if ($prefix == 'visit.' && $field == 'contacts_id') {
  603. $prefix = 'contacts.';
  604. $field = 'name';
  605. }
  606. return [$prefix, $field];
  607. }
  608. /**
  609. * 回款计划查询条件
  610. *
  611. * @param array $data 搜索参数
  612. * @return array
  613. * @since 2021-05-22
  614. * @author fanqi
  615. */
  616. function advancedQueryFormatForPlan($data)
  617. {
  618. $result = [];
  619. $planIds = db('crm_receivables_plan')->whereIn('num', $data)->column('plan_id');
  620. if (!empty($planIds)) $result = ['in', $planIds];
  621. return $result;
  622. }
  623. /**
  624. * 地址(固定字段)、地址(自定义字段)查询条件
  625. *
  626. * @param array $data 搜索参数
  627. * @param string $formType 字段类型
  628. * @return array
  629. * @since 2021-05-21
  630. * @author fanqi
  631. */
  632. function advancedQueryFormatForAddress($data, $formType)
  633. {
  634. if ($formType == 'map_address') $data = implode(chr(10), $data);
  635. if ($formType == 'position') {
  636. $data = array_filter(array_column($data[0], 'name'));
  637. $data = implode(',', $data);
  638. }
  639. return ['like', '%' . trim($data) . '%'];
  640. }
  641. /**
  642. * 人员、部门、回访人查询条件
  643. *
  644. * @param array $data 查询参数
  645. * @param string $condition 查询条件
  646. * @return array
  647. */
  648. function advancedQueryFormatForPersonnel($data, $condition)
  649. {
  650. // 处理查询条件
  651. if ($condition == 'is') $condition = 'contains';
  652. if ($condition == 'isNot') $condition = 'notContains';
  653. // 处理查询参数
  654. if (in_array($condition, ['contains', 'notContains'])) {
  655. array_walk($data, function ($value, $key) use (&$data) {
  656. $data[$key] = '%,' . $value . ',%';
  657. });
  658. }
  659. // 搜索条件
  660. return advancedQueryWhere($condition, $data);
  661. }
  662. /**
  663. * 日期、日期时间、数字、货币、百分数查询条件
  664. *
  665. * @param array $data 搜索参数、类型、条件
  666. * @return array
  667. * @since 2021-05-20
  668. * @author fanqi
  669. */
  670. function advancedQueryFormatForDate($data)
  671. {
  672. # 转换日期时间类型格式
  673. if (in_array($data['form_type'], ['datetime', 'next_time']) && !empty($data['value'][0])) $data['value'][0] = strtotime($data['value'][0]);
  674. if (in_array($data['form_type'], ['datetime', 'next_time']) && !empty($data['value'][1])) $data['value'][1] = strtotime($data['value'][1]);
  675. return advancedQueryWhere($data['condition'], count($data['value']) == 2 ? $data['value'] : $data['value'][0]);
  676. }
  677. /**
  678. * 模块、审核状态、成交状态、产品分类、单行文本、多行文本、网址、手机、邮箱、下拉框、布尔值、多选、定位、创建人、负责人
  679. *
  680. * @param array $data 要查询的数据
  681. * @param string $condition 查询方式
  682. * @param string $formType 字段类型
  683. * @return array
  684. * @since 2021-05-20
  685. * @author fanqi
  686. */
  687. function advancedQueryFormatForCommon($data, $condition, $formType, $key)
  688. {
  689. // 处理查询方式
  690. if (in_array($formType, ['checkbox']) && $condition == 'is') $condition = 'contains';
  691. if (in_array($formType, ['checkbox']) && $condition == 'isNot') $condition = 'notContains';
  692. // 处理查询参数
  693. if(in_array($condition, ['contains', 'notContains']) && in_array($key,['create_user_id','owner_user_id'])){
  694. $data = advancedQueryDataUserform($data, $condition);
  695. }elseif (in_array($condition, ['contains', 'notContains', 'startWith', 'endWith'])){
  696. $data = advancedQueryDataTransform($data, $condition);
  697. }
  698. // 处理回访形式
  699. if (in_array($key, ['shape', 'satisfaction'])) {
  700. array_walk($data, function ($value, $key) use (&$data) {
  701. $data[$key] = $value . "\r";
  702. });
  703. }
  704. // 处理审核状态
  705. if ($formType == 'check_status') {
  706. $data[0] = str_replace('待审核', 0, $data[0]);
  707. $data[0] = str_replace('审核中', 1, $data[0]);
  708. $data[0] = str_replace('审核通过', 2, $data[0]);
  709. $data[0] = str_replace('审核失败', 3, $data[0]);
  710. $data[0] = str_replace('已撤回', 4, $data[0]);
  711. $data[0] = str_replace('未提交', 5, $data[0]);
  712. $data[0] = str_replace('已作废', 6, $data[0]);
  713. }
  714. return advancedQueryWhere($condition, $data,$key);
  715. }
  716. /**
  717. * 设置搜索条件
  718. *
  719. * @param string $condition 查询方式
  720. * @param string|array $data 查询数据
  721. * @return array
  722. * @since 2021-05-22
  723. * @author fanqi
  724. */
  725. function advancedQueryWhere($condition, $data, $key='')
  726. {
  727. $result = [];
  728. // NULL(0)不存在、IS(1)等于、IS_NOT(2)不等于、CONTAINS(3)包含、NOT_CONTAINS(4)不包含、IS_NULL(5)为空、IS_NOT_NULL(6)不为空
  729. // GT(7)大于、EGT(8)大于等于、LT(9)小于、ELT(10)小于等于、ID(11)通过id、PREFIX(12) 前缀匹配、SUFFIX(13) 后缀匹配、RANGE(14) 数字区间
  730. if ($condition == "in") $result = ['in', $data]; // 等于
  731. if ($condition == 'is') $result = ['in', $data]; // 等于
  732. if ($condition == 'isNot') $result = [['notin', $data],['null'],'OR']; // 不等于
  733. if ($condition == 'contains') $result = ['like', $data, 'OR']; // 包含
  734. if ($condition == 'notContains') $result = [['notlike', $data, 'AND'],['null'],'OR']; // 不包含
  735. if ($condition == 'startWith') $result = ['like', $data, 'OR']; // 开始于
  736. if ($condition == 'endWith') $result = ['like', $data, 'OR']; // 结束于
  737. if ($condition == 'gt') $result = ['gt', $data]; // 大于
  738. if ($condition == 'lt') $result = ['lt', $data]; // 小于
  739. if ($condition == 'egt') $result = ['egt', $data]; // 大于等于
  740. if ($condition == 'elt') $result = ['elt', $data]; // 小于等于
  741. if ($condition == 'between') $result = ['between', $data]; // 处于某个时间段
  742. if ($condition == 'range') $result = ['between', $data]; // 处于某个时间段
  743. if ($condition == 'isNull') $result = [['eq', ''], ['null'], 'OR']; // 为空
  744. if ($condition == 'isNotNull') $result = [['neq', ''], ['not null'], 'AND']; // 不为空
  745. if ($condition == 'contains' && in_array($key,['create_user_id','owner_user_id'])) $result = ['in', $data]; // 暂定为创建人 负责人 包含
  746. if ($condition == 'notContains' && in_array($key,['create_user_id','owner_user_id'])) $result = ['notin', $data]; // 暂定为创建人 负责人不包含
  747. return $result;
  748. }
  749. /**
  750. * 处理要查询的数据
  751. *
  752. * @param array $data 要查询的数据
  753. * @param string $condition 查询方式
  754. * @return mixed
  755. * @since 2021-05-20
  756. * @author fanqi
  757. */
  758. function advancedQueryDataTransform($data, $condition)
  759. {
  760. if (in_array($condition, ['contains', 'notContains'])) {
  761. array_walk($data, function ($value, $key) use (&$data) {
  762. $data[$key] = '%' . $value . '%';
  763. });
  764. }
  765. if ($condition == 'startWith') {
  766. array_walk($data, function ($value, $key) use (&$data) {
  767. $data[$key] = $value . '%';
  768. });
  769. }
  770. if ($condition == 'endWith') {
  771. array_walk($data, function ($value, $key) use (&$data) {
  772. $data[$key] = '%' . $value;
  773. });
  774. }
  775. return $data;
  776. }
  777. /**
  778. * 处理要查询的数据 包含不包含条件 数据为数字专用
  779. *
  780. * @param array $data 要查询的数据
  781. * @param string $condition 查询方式
  782. * @return mixed
  783. * @author: alvin guogaobo
  784. * @version: 11.1.0
  785. * Date: 2021/9/2 14:44
  786. */
  787. function advancedQueryDataUserform($data, $condition){
  788. if (in_array($condition, ['contains', 'notContains'])) {
  789. array_walk($data, function ($value, $key) use (&$data) {
  790. $data[$key] = $value;
  791. });
  792. }
  793. return $data;
  794. }
  795. /**
  796. * 等于(时间段)数据处理
  797. *
  798. * @param $data
  799. * @return array
  800. * @since 2021-06-11
  801. * @author fanqi
  802. */
  803. function advancedQueryHandleDate($data)
  804. {
  805. // 本年度
  806. if ($data['value'][0] == 'year') {
  807. $arrTime = DataTime::year();
  808. $data['value'][0] = date('Y-m-d 00:00:00', $arrTime[0]);
  809. $data['value'][1] = date('Y-m-d 23:59:59', $arrTime[1]);
  810. }
  811. // 上一年度
  812. if ($data['value'][0] == 'lastYear') {
  813. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '-1 year'));
  814. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '-1 year'));
  815. }
  816. // 下一年度
  817. if ($data['value'][0] == 'nextYear') {
  818. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '+1 year'));
  819. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '+1 year'));
  820. }
  821. // 上半年
  822. if ($data['value'][0] == 'firstHalfYear') {
  823. $data['value'][0] = date('Y-01-01 00:00:00');
  824. $data['value'][1] = date('Y-06-30 23:59:59');
  825. }
  826. // 下半年
  827. if ($data['value'][0] == 'nextHalfYear') {
  828. $data['value'][0] = date('Y-07-01 00:00:00');
  829. $data['value'][1] = date('Y-12-31 23:59:59');
  830. }
  831. // 本季度
  832. if ($data['value'][0] == 'quarter') {
  833. $season = ceil((date('n')) / 3);
  834. $data['value'][0] = date('Y-m-d H:i:s', mktime(0, 0, 0, $season * 3 - 3 + 1, 1, date('Y')));
  835. $data['value'][1] = date('Y-m-d H:i:s', mktime(23, 59, 59, $season * 3, date('t', mktime(0, 0, 0, $season * 3, 1, date("Y"))), date('Y')));
  836. }
  837. // 上一季度
  838. if ($data['value'][0] == 'lastQuarter') {
  839. $season = ceil((date('n')) / 3) - 1;
  840. $data['value'][0] = date('Y-m-d H:i:s', mktime(0, 0, 0, $season * 3 - 3 + 1, 1, date('Y')));
  841. $data['value'][1] = date('Y-m-d H:i:s', mktime(23, 59, 59, $season * 3, date('t', mktime(0, 0, 0, $season * 3, 1, date("Y"))), date('Y')));
  842. }
  843. // 下一季度
  844. if ($data['value'][0] == 'nextQuarter') {
  845. $season = ceil((date('n')) / 3);
  846. $data['value'][0] = date('Y-m-d H:i:s', mktime(0, 0, 0, $season * 3 + 1, 1, date('Y')));
  847. $data['value'][1] = date('Y-m-d H:i:s', mktime(23, 59, 59, $season * 3 + 3, date('t', mktime(0, 0, 0, $season * 3, 1, date("Y"))), date('Y')));
  848. }
  849. // 本月
  850. if ($data['value'][0] == 'month') {
  851. $data['value'][0] = date('Y-m-01 00:00:00');
  852. $data['value'][1] = date('Y-m-31 23:59:59');
  853. }
  854. // 上月
  855. if ($data['value'][0] == 'lastMonth') {
  856. $data['value'][0] = date('Y-m-01 00:00:00', strtotime(date('Y-m-d') . '-1 month'));
  857. $data['value'][1] = date('Y-m-31 23:59:59', strtotime(date('Y-m-d') . '-1 month'));
  858. }
  859. // 下月
  860. if ($data['value'][0] == 'nextMonth') {
  861. $data['value'][0] = date('Y-m-01 00:00:00', strtotime(date('Y-m-d') . '+1 month'));
  862. $data['value'][1] = date('Y-m-31 23:59:59', strtotime(date('Y-m-d') . '+1 month'));
  863. }
  864. // 本周
  865. if ($data['value'][0] == 'week') {
  866. $data['value'][0] = date('Y-m-d 00:00:00', mktime(0, 0, 0, date('m'), date('d') - date('w') + 1, date('Y')));
  867. $data['value'][1] = date('Y-m-d 23:59:59', mktime(23, 59, 59, date('m'), date('d') - date('w') + 7, date('Y')));
  868. }
  869. // 上周
  870. if ($data['value'][0] == 'lastWeek') {
  871. $date = date("Y-m-d");
  872. $w = date("w", strtotime($date));
  873. $d = $w ? $w - 1 : 6;
  874. $start = date("Y-m-d", strtotime($date . " - " . $d . " days"));
  875. $data['value'][0] = date('Y-m-d', strtotime($start . " - 7 days"));
  876. $data['value'][1] = date('Y-m-d', strtotime($start . " - 1 days"));
  877. }
  878. // 下周
  879. if ($data['value'][0] == 'nextWeek') {
  880. $date = date("Y-m-d");
  881. $w = date("w", strtotime($date));
  882. $d = $w ? $w - 1 : 6;
  883. $start = date("Y-m-d", strtotime($date . " - " . $d . " days"));
  884. $data['value'][0] = date('Y-m-d', strtotime($start . " + 7 days"));
  885. $data['value'][1] = date('Y-m-d', strtotime($start . " + 13 days"));
  886. }
  887. // 今天
  888. if ($data['value'][0] == 'today') {
  889. $data['value'][0] = date('Y-m-d 00:00:00');
  890. $data['value'][1] = date('Y-m-d 23:59:59');
  891. }
  892. // 昨天
  893. if ($data['value'][0] == 'yesterday') {
  894. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '-1 day'));
  895. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '-1 day'));
  896. }
  897. // 明天
  898. if ($data['value'][0] == 'tomorrow') {
  899. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '+1 day'));
  900. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '+1 day'));
  901. }
  902. // 过去7天
  903. if ($data['value'][0] == 'previous7day') {
  904. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '-7 day'));
  905. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '-1 day'));
  906. }
  907. // 过去30天
  908. if ($data['value'][0] == 'previous30day') {
  909. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '-30 day'));
  910. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '-1 day'));
  911. }
  912. // 未来7天
  913. if ($data['value'][0] == 'future7day') {
  914. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '+1 day'));
  915. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '+7 day'));
  916. }
  917. // 未来30天
  918. if ($data['value'][0] == 'future30day') {
  919. $data['value'][0] = date('Y-m-d 00:00:00', strtotime(date('Y-m-d') . '+1 day'));
  920. $data['value'][1] = date('Y-m-d 23:59:59', strtotime(date('Y-m-d') . '+30 day'));
  921. }
  922. return $data;
  923. }
  924. /**
  925. * 根据搜索生成where条件
  926. *
  927. * @param string $search 搜索内容
  928. * @param $condition 搜索条件
  929. * @param $k 搜索字段
  930. * @return array|Closure|string[]
  931. */
  932. function field($search, $condition = '', $k = '')
  933. {
  934. switch (trim($condition)) {
  935. case "is" :
  936. $where = ['in', $search];
  937. break;
  938. case "isNot" :
  939. $where = ['notin', $search];
  940. break;
  941. case "contains" :
  942. $containsWhere = [];
  943. foreach ((array)$search as $key1 => $value1) $containsWhere[] = '%' . $value1 . '%';
  944. $where = ['like', $containsWhere, 'OR'];
  945. break;
  946. case "notContains" :
  947. $containsWhere = [];
  948. foreach ((array)$search as $key1 => $value1) $containsWhere[] = '%' . $value1 . '%';
  949. $where = ['notlike', $containsWhere, 'AND'];
  950. break;
  951. case "startWith" :
  952. $startWithWhere = [];
  953. foreach ((array)$search as $key1 => $value1) $startWithWhere[] = $value1 . '%';
  954. $where = ['like', $startWithWhere, 'OR'];
  955. break;
  956. case "endWith" :
  957. $endWithWhere = [];
  958. foreach ((array)$search as $key1 => $value1) $endWithWhere[] = '%' . $value1;
  959. $where = ['like', $endWithWhere, 'OR'];
  960. break;
  961. case "isNull" :
  962. $where = ['eq', ''];
  963. break;
  964. case "isNotNull" :
  965. $where = ['neq', ''];
  966. break;
  967. case "eq" :
  968. $where = function ($query) use ($search, $k) {
  969. foreach ((array)$search as $key1 => $value1) {
  970. $query->whereOr($k, $value1);
  971. }
  972. };
  973. break;
  974. case "neq" :
  975. $where = function ($query) use ($search, $k) {
  976. foreach ((array)$search as $key1 => $value1) {
  977. $query->whereOr($k, '<>', $value1);
  978. }
  979. };
  980. break;
  981. case "gt" :
  982. $where = function ($query) use ($search, $k) {
  983. foreach ((array)$search as $key1 => $value1) {
  984. $query->whereOr($k, '>', $value1);
  985. }
  986. };
  987. break;
  988. case "egt" :
  989. $where = function ($query) use ($search, $k) {
  990. foreach ((array)$search as $key1 => $value1) {
  991. $query->whereOr($k, '>=', $value1);
  992. }
  993. };
  994. break;
  995. case "lt" :
  996. $where = function ($query) use ($search, $k) {
  997. foreach ((array)$search as $key1 => $value1) {
  998. $query->whereOr($k, '<', $value1);
  999. }
  1000. };
  1001. break;
  1002. case "elt" :
  1003. $where = function ($query) use ($search, $k) {
  1004. foreach ((array)$search as $key1 => $value1) {
  1005. $query->whereOr($k, '<=', $value1);
  1006. }
  1007. };
  1008. break;
  1009. case "in" :
  1010. $where = ['in', $search];
  1011. break;
  1012. default :
  1013. $where = ['eq', $search];
  1014. break;
  1015. }
  1016. return $where;
  1017. }
  1018. /**
  1019. * 将单个搜索转换为高级搜索格式
  1020. * @param string $value 搜索内容
  1021. * @param $condition 搜索条件
  1022. * @return array
  1023. * @author Michael_xu
  1024. */
  1025. function field_arr($value, $condition = '')
  1026. {
  1027. if (is_array($value)) {
  1028. } else {
  1029. $condition = $condition ?: 'eq';
  1030. $where_arr = ['value' => $value, 'condition' => $condition];
  1031. }
  1032. return $where_arr;
  1033. }
  1034. /**
  1035. * 记录操作日志
  1036. * @param $id array 操作对象id数组
  1037. * @return
  1038. * @author Michael_xu
  1039. */
  1040. function actionLog($id, $join_user_ids = '', $structure_ids = '', $content = '')
  1041. {
  1042. if (!is_array($id)) {
  1043. $idArr[] = $id;
  1044. } else {
  1045. $idArr = $id;
  1046. }
  1047. $header = Request::instance()->header();
  1048. $authKey = $header['authkey'];
  1049. $cache = cache('Auth_' . $authKey);
  1050. if (!$cache) {
  1051. return false;
  1052. }
  1053. $userInfo = $cache['userInfo'];
  1054. $category = $userInfo['id'] == 1 ? '管理员' : '员工';
  1055. $request = request();
  1056. $m = strtolower($request->module());
  1057. $c = strtolower($request->controller());
  1058. $a = strtolower($request->action());
  1059. $res_action = true;
  1060. foreach ($idArr as $v) {
  1061. $data = [];
  1062. $data['user_id'] = $userInfo['id'];
  1063. $data['module_name'] = $module_name = $m;
  1064. $data['controller_name'] = $controller_name = $c;
  1065. $data['action_name'] = $action_name = $a;
  1066. $data['action_id'] = $v;
  1067. $data['create_time'] = time();
  1068. $data['client_ip'] = request()->ip();
  1069. $data['content'] = $content ?: lang('ACTIONLOG', [$category, $userInfo['realname'], date('Y-m-d H:i:s'), lang($action_name), $v, lang($controller_name)]);
  1070. $data['join_user_ids'] = $join_user_ids ?: ''; //抄送人
  1071. $data['structure_ids'] = $structure_ids ?: ''; //抄送部门
  1072. if ($action_name == 'delete' || $action_name == 'commentdel') {
  1073. $data['action_delete'] = 1;
  1074. }
  1075. if (!db('admin_action_log')->insert($data)) {
  1076. $res_action = false;
  1077. }
  1078. # 数据操作日志
  1079. db('admin_operation_log')->insert([
  1080. 'user_id' => $userInfo['id'],
  1081. 'client_ip' => request()->ip(),
  1082. 'module' => $m . '_' . $c,
  1083. 'action_id' => $v,
  1084. 'content' => $content,
  1085. 'create_time' => time()
  1086. ]);
  1087. }
  1088. if ($res_action) {
  1089. return true;
  1090. } else {
  1091. return false;
  1092. }
  1093. }
  1094. /**
  1095. * 判断操作权限
  1096. * @param
  1097. * @return
  1098. * @author Michael_xu
  1099. */
  1100. function checkPerByAction($m, $c, $a)
  1101. {
  1102. /*获取头部信息*/
  1103. $header = Request::instance()->header();
  1104. $authKey = $header['authkey'];
  1105. $cache = cache('Auth_' . $authKey);
  1106. if (!$cache) {
  1107. return false;
  1108. }
  1109. $userInfo = $cache['userInfo'];
  1110. $adminTypes = adminGroupTypes($userInfo['id']);
  1111. if (in_array(1, $adminTypes)) {
  1112. return true;
  1113. }
  1114. if (empty($m) && empty($c) && empty($a)) {
  1115. $request = Request::instance();
  1116. $m = strtolower($request->module());
  1117. $c = strtolower($request->controller());
  1118. $a = strtolower($request->action());
  1119. }
  1120. $authAdapter = new AuthAdapter($authKey);
  1121. $ruleName = $m . '-' . $c . '-' . $a;
  1122. if (!$authAdapter->checkIntime($ruleName, $userInfo['id'])) {
  1123. return false;
  1124. }
  1125. return true;
  1126. }
  1127. /**
  1128. * 给树状菜单添加level并去掉没有子菜单的菜单项
  1129. * @param array $data [description]
  1130. * @param integer $root [description]
  1131. * @param string $child [description]
  1132. * @param string $level [description]
  1133. */
  1134. function memuLevelClear($data, $root = 1, $child = 'children', $level = 'level')
  1135. {
  1136. if (is_array($data)) {
  1137. foreach ($data as $key => $val) {
  1138. // $data[$key]['selected'] = false;
  1139. $data[$key]['level'] = $root;
  1140. if (!empty($val[$child]) && is_array($val[$child])) {
  1141. $data[$key][$child] = memuLevelClear($val[$child], $root + 1);
  1142. } else if ($root < 3 && $data[$key]['menu_type'] == 1) {
  1143. unset($data[$key]);
  1144. }
  1145. if (empty($data[$key][$child]) && ($data[$key]['level'] == 1) && ($data[$key]['menu_type'] == 1)) {
  1146. unset($data[$key]);
  1147. }
  1148. }
  1149. return array_values($data);
  1150. }
  1151. return array();
  1152. }
  1153. /**
  1154. * [rulesDeal 给树状规则表处理成 module-controller-action ]
  1155. * @AuthorHTL
  1156. * @DateTime
  1157. * @param [array] $data [树状规则数组]
  1158. * @return [array] [返回数组]
  1159. */
  1160. function rulesDeal($data)
  1161. {
  1162. if (is_array($data)) {
  1163. $ret = [];
  1164. foreach ($data as $k1 => $v1) {
  1165. $str1 = $v1['name'];
  1166. if (is_array($v1['children'])) {
  1167. foreach ($v1['children'] as $k2 => $v2) {
  1168. $str2 = $str1 . '-' . $v2['name'];
  1169. if (is_array($v2['children'])) {
  1170. foreach ($v2['children'] as $k3 => $v3) {
  1171. $str3 = $str2 . '-' . $v3['name'];
  1172. $ret[] = $str3;
  1173. }
  1174. } else {
  1175. $ret[] = $str2;
  1176. }
  1177. }
  1178. } else {
  1179. $ret[] = $str1;
  1180. }
  1181. }
  1182. return $ret;
  1183. }
  1184. return [];
  1185. }
  1186. /**
  1187. * 获取下属userId
  1188. * @param $self == true 包含自己
  1189. * @param $type == 0 下属userid
  1190. * @param $type == 1 全部userid
  1191. * @param $user_id 需要查询的user_id
  1192. * @author Michael_xu
  1193. */
  1194. function getSubUserId($self = true, $type = 0, $user_id = '')
  1195. {
  1196. $request = Request::instance();
  1197. $header = $request->header();
  1198. $authKey = $header['authkey'];
  1199. $cache = cache('Auth_' . $authKey);
  1200. if (!$user_id) {
  1201. if (!$cache) {
  1202. return false;
  1203. }
  1204. $userInfo = $cache['userInfo'];
  1205. $user_id = $userInfo['id'];
  1206. $adminTypes = adminGroupTypes($user_id);
  1207. if (in_array(1, $adminTypes)) {
  1208. $type = 1;
  1209. }
  1210. }
  1211. $belowIds = [];
  1212. if (empty($type)) {
  1213. if ($user_id) {
  1214. $belowIds = getSubUser($user_id);
  1215. }
  1216. } else {
  1217. $belowIds = getSubUser(0);
  1218. }
  1219. if ($self == true) {
  1220. $belowIds[] = $user_id;
  1221. } else {
  1222. $belowIds = $belowIds ? array_diff($belowIds, array($user_id)) : [];
  1223. }
  1224. return array_unique($belowIds);
  1225. }
  1226. /**
  1227. * 获取下属userId
  1228. * @author Michael_xu
  1229. */
  1230. function getSubUser($userId, $queried = [], $allUserList = [])
  1231. {
  1232. if (empty($allUserList)) {
  1233. $allUserList = db('admin_user')->field('id,parent_id')->select();
  1234. }
  1235. foreach ($allUserList as $k => $v) {
  1236. if ($v['parent_id'] == $userId) {
  1237. $sub_user[] = $v['id'];
  1238. }
  1239. }
  1240. if ($sub_user) {
  1241. foreach ($sub_user as $v) {
  1242. if (in_array($v, $queried)) {
  1243. continue;
  1244. }
  1245. $queried[] = $v;
  1246. $son_user = [];
  1247. $son_user = getSubUser($v, $queried, $allUserList);
  1248. if (!empty($son_user)) {
  1249. $sub_user = array_merge($sub_user, $son_user);
  1250. }
  1251. }
  1252. }
  1253. return $sub_user;
  1254. }
  1255. /**
  1256. * 阿里大于短信发送
  1257. * @param unknown $appkey
  1258. * @param unknown $secret
  1259. * @param unknown $signName 短信签名
  1260. * @param unknown $smsParam
  1261. * @param unknown $templateCode 短信模板
  1262. * @param unknown $send_mobile 接收手机号
  1263. * @param unknown $code 短信验证码
  1264. * @param unknown $template_code 模板参数
  1265. */
  1266. function aliSmsSend($send_mobile, $code, $signName, $templateCode)
  1267. {
  1268. $appkey = '';
  1269. $secret = '';
  1270. import('alimsg.api.Sms', EXTEND_PATH);
  1271. header('Content-Type: text/plain; charset=utf-8');
  1272. $sms = new Sms($appkey, $secret);
  1273. $template_code = array("code" => $code);
  1274. $response = $sms->sendSms($signName, $templateCode, $send_mobile, $template_code);
  1275. $data = object_to_array($response);
  1276. if ($data['Message'] == 'OK' && $data['Code'] == "OK") {
  1277. return true;
  1278. } else {
  1279. return false;
  1280. }
  1281. }
  1282. /**
  1283. * 发送邮件
  1284. * @param unknown $toemail
  1285. * @param unknown $title
  1286. * @param unknown $content
  1287. * @return boolean
  1288. */
  1289. function emailSend($email_host, $email_id, $email_pass, $email_addr, $toemail, $title, $content)
  1290. {
  1291. $result = false;
  1292. try {
  1293. $mail = new Email();
  1294. $mail->setServer($email_host, $email_id, $email_pass);
  1295. $mail->setFrom($email_addr);
  1296. $mail->setReceiver($toemail);
  1297. $mail->setMailInfo($title, $content);
  1298. $result = $mail->sendMail();
  1299. } catch (\Exception $e) {
  1300. $result = false;
  1301. }
  1302. return $result;
  1303. }
  1304. /**
  1305. * 发送站内信
  1306. * @param $user_id 接收人user_id
  1307. * @param $action_id 操作id
  1308. * @param $sysMessage 1为系统消息
  1309. * @param $content 消息内容
  1310. * @return
  1311. * @author Michael_xu
  1312. */
  1313. function sendMessage($user_id, $content, $action_id, $sysMessage = 0)
  1314. {
  1315. $content = trim($content);
  1316. if (!$user_id) return false;
  1317. if (!$content) return false;
  1318. if (!is_array($user_id)) {
  1319. $user_ids[] = $user_id;
  1320. } else {
  1321. $user_ids = $user_id;
  1322. }
  1323. $user_ids = array_unique(array_filter($user_ids));
  1324. $request = request();
  1325. $m = strtolower($request->module());
  1326. $c = strtolower($request->controller());
  1327. $a = strtolower($request->action());
  1328. $userInfo = [];
  1329. if ($sysMessage == 0) {
  1330. $header = $request->header();
  1331. $authkey = $header['authkey'];
  1332. $cache = cache('Auth_' . $authkey);
  1333. if (!$cache) {
  1334. return false;
  1335. }
  1336. $userInfo = $cache['userInfo'];
  1337. }
  1338. foreach ($user_ids as $v) {
  1339. $data = [];
  1340. $data['content'] = $content;
  1341. $data['from_user_id'] = $userInfo['id'] ?: 0;
  1342. $data['to_user_id'] = $v;
  1343. $data['read_time'] = 0;
  1344. $data['send_time'] = time();
  1345. $data['module_name'] = $m;
  1346. $data['controller_name'] = $c;
  1347. $data['action_name'] = $a;
  1348. $data['action_id'] = $action_id;
  1349. db('admin_message')->insert($data);
  1350. }
  1351. return true;
  1352. }
  1353. /**
  1354. * 格式化字节大小
  1355. * @param number $size 字节数
  1356. * @param string $delimiter 数字和单位分隔符
  1357. * @return string 格式化后的带单位的大小
  1358. * @author
  1359. */
  1360. function format_bytes($size, $delimiter = '')
  1361. {
  1362. $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
  1363. for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
  1364. return round($size, 2) . $delimiter . $units[$i];
  1365. }
  1366. /**
  1367. * 数据修改日志
  1368. * @param $types 类型
  1369. * @param $action_id 操作ID
  1370. * @param $newData 新数据
  1371. * @param $newData 新数据
  1372. * @return
  1373. * @author Michael_xu
  1374. */
  1375. function updateActionLog($user_id, $types, $action_id, $oldData = [], $newData = [], $content = '')
  1376. {
  1377. # 转格式
  1378. if (!empty($oldData['next_time']) && $oldData['next_time'] != strtotime($oldData['next_time'])) {
  1379. $oldData['next_time'] = strtotime($oldData['next_time']);
  1380. }
  1381. if (is_array($oldData) && is_array($newData) && $user_id) {
  1382. $differentData = array_diff_assoc($newData, $oldData);
  1383. $fieldModel = new FieldModel();
  1384. $userModel = new UserModel();
  1385. $structureModel = new \app\admin\model\Structure();
  1386. $field_arr = $fieldModel->getField(['types' => $types, 'unFormType' => ['file', 'form']]); //获取字段属性
  1387. $newFieldArr = array();
  1388. foreach ($field_arr as $k => $v) {
  1389. $newFieldArr[$v['field']] = $v;
  1390. }
  1391. $unField = ['update_time', 'create_time']; //定义过滤字段
  1392. $message = [];
  1393. $un_form_type = ['file', 'form'];
  1394. foreach ($differentData as $k => $v) {
  1395. if ($newFieldArr[$k] && !in_array($newFieldArr[$k]['form_type'], $un_form_type)) {
  1396. $field_name = '';
  1397. $field_name = $newFieldArr[$k]['name'];
  1398. $new_value = $v ?: '空';
  1399. $old_value = $oldData[$k] ?: '空';
  1400. if ($newFieldArr[$k]['form_type'] == 'datetime') {
  1401. $new_value = $v ? date('Y-m-d', $v) : '空';
  1402. if (date('Y-m-d H:i:s', strtotime($oldData[$k])) == $oldData[$k]) {
  1403. $old_value = !empty($oldData[$k]) ? $oldData[$k] : '空';
  1404. } else {
  1405. $old_value = !empty($oldData[$k]) ? date('Y-m-d', $oldData[$k]) : '空';
  1406. }
  1407. if (empty($v) && empty($oldData[$k])) continue;
  1408. } elseif ($newFieldArr[$k]['form_type'] == 'user') {
  1409. $new_value = $v ? implode(',', $userModel->getUserNameByArr(stringToArray($v))) : '';
  1410. $old_value = $v ? implode(',', $userModel->getUserNameByArr(stringToArray($oldData[$k]))) : '';
  1411. } elseif ($newFieldArr[$k]['form_type'] == 'structure') {
  1412. $new_value = $v ? implode(',', $structureModel->getStructureNameByArr(stringToArray($v))) : '';
  1413. $old_value = $v ? implode(',', $structureModel->getStructureNameByArr(stringToArray($oldData[$k]))) : '';
  1414. } elseif ($newFieldArr[$k]['form_type'] == 'business_status') {
  1415. $new_value = $v ? db('crm_business_status')->where(['status_id' => $v])->value('name') : '';
  1416. $old_value = $v ? db('crm_business_status')->where(['status_id' => $oldData[$k]])->value('name') : '';
  1417. } elseif ($newFieldArr[$k]['form_type'] == 'business_type') {
  1418. $new_value = $v ? db('crm_business_type')->where(['type_id' => $v])->value('name') : '';
  1419. $old_value = $v ? db('crm_business_type')->where(['type_id' => $oldData[$k]])->value('name') : '';
  1420. } elseif ($newFieldArr[$k]['form_type'] == 'customer') {
  1421. $new_value = $v ? db('crm_customer')->where(['customer_id' => $v])->value('name') : '';
  1422. $old_value = $v ? db('crm_customer')->where(['customer_id' => $oldData[$k]])->value('name') : '';
  1423. } elseif ($newFieldArr[$k]['form_type'] == 'category') {
  1424. $new_value = $v ? db('crm_product_category')->where(['category_id' => $v])->value('name') : '';
  1425. $old_value = $v ? db('crm_product_category')->where(['category_id' => $oldData[$k]])->value('name') : '';
  1426. } elseif ($newFieldArr[$k]['form_type'] == 'business') {
  1427. $new_value = $v ? db('crm_business')->where(['business_id' => $v])->value('name') : '';
  1428. $old_value = $v ? db('crm_business')->where(['business_id' => $oldData[$k]])->value('name') : '';
  1429. } elseif ($newFieldArr[$k]['field'] == 'check_status') {
  1430. $statusArr = ['0' => '待审核', '1' => '审核中', '2' => '审核通过', '3' => '已拒绝', '4' => '已撤回', '5' => '未提交'];
  1431. $new_value = $statusArr[$v];
  1432. $old_value = $statusArr[$oldData[$k]];
  1433. } elseif ($newFieldArr[$k]['form_type'] == 'visit') {
  1434. $new_value = $v ? db('crm_visit')->where(['visit_id' => $v])->value('number') : '';
  1435. $old_value = $v ? db('crm_visit')->where(['visit_id' => $oldData[$k]])->value('number') : '';
  1436. } elseif ($newFieldArr[$k]['form_type'] == 'single_user') {
  1437. $new_value = $v ? db('admin_user')->where(['id' => $v])->value('realname') : '';
  1438. $old_value = $v ? db('admin_user')->where(['id' => $oldData['owner_user_id']])->value('realname') : '';
  1439. } elseif ($newFieldArr[$k]['form_type'] == 'floatnumber') {
  1440. $new_value = $v ? number_format($v, 2) : '';
  1441. }
  1442. if ($old_value != $new_value) {
  1443. $message[] = '将 ' . "'" . $field_name . "'" . ' 由 ' . $old_value . ' 修改为 ' . $new_value;
  1444. }
  1445. }
  1446. }
  1447. if ($message) {
  1448. $data = [];
  1449. $data['user_id'] = $user_id;
  1450. $data['create_time'] = time();
  1451. $data['types'] = $types;
  1452. $data['action_id'] = $action_id;
  1453. $data['content'] = implode('.|.', $message);
  1454. db('admin_action_record')->insert($data);
  1455. }
  1456. } elseif ($content) {
  1457. $data = [];
  1458. $data['user_id'] = $user_id;
  1459. $data['create_time'] = time();
  1460. $data['types'] = $types;
  1461. $data['action_id'] = $action_id;
  1462. $data['content'] = $content;
  1463. db('admin_action_record')->insert($data);
  1464. }
  1465. }
  1466. /**
  1467. * 截取字符串
  1468. * @param $start 开始截取位置
  1469. * @param $length 截取长度
  1470. * @return
  1471. * @author Michael_xu
  1472. */
  1473. function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true)
  1474. {
  1475. if (function_exists("mb_substr")) {
  1476. $slice = mb_substr($str, $start, $length, $charset);
  1477. } elseif (function_exists('iconv_substr')) {
  1478. $slice = iconv_substr($str, $start, $length, $charset);
  1479. if (false === $slice) {
  1480. $slice = '';
  1481. }
  1482. } else {
  1483. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  1484. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  1485. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  1486. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  1487. preg_match_all($re[$charset], $str, $match);
  1488. $slice = join("", array_slice($match[0], $start, $length));
  1489. }
  1490. if (utf8_strlen($str) < $length) $suffix = false;
  1491. return $suffix ? $slice . '...' : $slice;
  1492. }
  1493. function utf8_strlen($string = null)
  1494. {
  1495. preg_match_all("/./us", $string, $match);
  1496. return count($match[0]);
  1497. }
  1498. /**
  1499. * 合法性验证
  1500. * @param client_sign 签名参数值,使用相同规则对提交参数进行加密验证
  1501. * @return
  1502. * @author Michael_xu
  1503. */
  1504. function checkVerify($saftCode = '5kcrm@')
  1505. {
  1506. $parmList = Request::instance()->post();
  1507. $header = $request->header();
  1508. $parmList['sessionId'] = $header['sessionId'];
  1509. $authkey = $header['authKey'];
  1510. $clientSign = $parmList['client_sign'];
  1511. if ($clientSign) {
  1512. unset($parmList['client_sign']);
  1513. if (count($parmList) > 0) {
  1514. // 对要签名参数按照签名格式组合
  1515. foreach ($parmList as $key => $value) {
  1516. if (isset($_POST[$key])) {
  1517. $parame[$key] = $key . '=' . trim($_POST[$key]);
  1518. } else {
  1519. return false;
  1520. }
  1521. }
  1522. ksort($parame); //参数排序
  1523. $returnValue = implode("&", $parame); //拼接字符串
  1524. if ($returnValue) {
  1525. //base64加密
  1526. $signCalc = base64_encode(hash_hmac("sha1", $returnValue, $saftCode . $authkey, $raw_output = false));
  1527. // 检查参数签名是否一致
  1528. if (trim($clientSign) != trim($signCalc)) {
  1529. return false;
  1530. } else {
  1531. return true;
  1532. }
  1533. } else {
  1534. return false;
  1535. }
  1536. } else {
  1537. return false;
  1538. }
  1539. } else {
  1540. //签名认证错误
  1541. return false;
  1542. }
  1543. }
  1544. /**
  1545. * 数组转换字符串(以逗号隔开)
  1546. * @param
  1547. * @return
  1548. * @author Michael_xu
  1549. */
  1550. function arrayToString($array)
  1551. {
  1552. if (!is_array($array)) {
  1553. $data_arr[] = $array;
  1554. } else {
  1555. $data_arr = $array;
  1556. }
  1557. $data_arr = array_filter($data_arr); //数组去空
  1558. $data_arr = array_unique($data_arr); //数组去重
  1559. $data_arr = array_merge($data_arr);
  1560. $string = $data_arr ? ',' . implode(',', $data_arr) . ',' : '';
  1561. return $string ?: '';
  1562. }
  1563. /**
  1564. * 字符串转换数组(以逗号隔开)
  1565. * @param
  1566. * @return
  1567. * @author Michael_xu
  1568. */
  1569. function stringToArray($string)
  1570. {
  1571. if (is_array($string)) {
  1572. $data_arr = array_unique(array_filter($string));
  1573. } else {
  1574. $data_arr = $string ? array_unique(array_filter(explode(',', $string))) : [];
  1575. }
  1576. $data_arr = $data_arr ? array_merge($data_arr) : [];
  1577. return $data_arr ?: [];
  1578. }
  1579. /**
  1580. * 根据时间戳获取星期几
  1581. * @param $time 要转换的时间戳
  1582. */
  1583. function getTimeWeek($time, $i = 0)
  1584. {
  1585. $weekarray = array("日", "一", "二", "三", "四", "五", "六");
  1586. $oneD = 24 * 60 * 60;
  1587. return "星期" . $weekarray[date("w", $time + $oneD * $i)];
  1588. }
  1589. /**
  1590. * 二维数组排序(选择)
  1591. * @param $select 要进行排序的select结果集
  1592. * @param $field 排序的字段
  1593. * @param $order 排序方式1降序2升序
  1594. */
  1595. function sort_select($select = array(), $field, $order = 1)
  1596. {
  1597. $count = count($select);
  1598. if ($order == 1) {
  1599. for ($i = 0; $i < $count; $i++) {
  1600. $k = $i;
  1601. for ($j = $i; $j < $count; $j++) {
  1602. if ($select[$k][$field] < $select[$j][$field]) {
  1603. $k = $j;
  1604. }
  1605. }
  1606. $temp = $select[$i];
  1607. $select[$i] = $select[$k];
  1608. $select[$k] = $temp;
  1609. }
  1610. return $select;
  1611. } else {
  1612. for ($i = 0; $i < $count; $i++) {
  1613. $k = $i;
  1614. for ($j = $i; $j < $count; $j++) {
  1615. if ($select[$k][$field] > $select[$j][$field]) {
  1616. $k = $j;
  1617. }
  1618. }
  1619. $temp = $select[$i];
  1620. $select[$i] = $select[$k];
  1621. $select[$k] = $temp;
  1622. }
  1623. return $select;
  1624. }
  1625. }
  1626. /**
  1627. * 将秒数转换为时间 (年、天、小时、分、秒)
  1628. * @param
  1629. */
  1630. function getTimeBySec($time)
  1631. {
  1632. if (is_numeric($time)) {
  1633. $value = array(
  1634. "years" => 0, "days" => 0, "hours" => 0,
  1635. "minutes" => 0, "seconds" => 0,
  1636. );
  1637. if ($time >= 31556926) {
  1638. $value["years"] = floor($time / 31556926);
  1639. $time = ($time % 31556926);
  1640. $t .= $value["years"] . "年";
  1641. }
  1642. if ($time >= 86400) {
  1643. $value["days"] = floor($time / 86400);
  1644. $time = ($time % 86400);
  1645. $t .= $value["days"] . "天";
  1646. }
  1647. if ($time >= 3600) {
  1648. $value["hours"] = floor($time / 3600);
  1649. $time = ($time % 3600);
  1650. $t .= $value["hours"] . "小时";
  1651. }
  1652. if ($time >= 60) {
  1653. $value["minutes"] = floor($time / 60);
  1654. $time = ($time % 60);
  1655. $t .= $value["minutes"] . "分钟";
  1656. }
  1657. if ($time < 60) {
  1658. $value["seconds"] = floor($time);
  1659. $t .= $value["seconds"] . "秒";
  1660. }
  1661. return $t;
  1662. } else {
  1663. return (bool)FALSE;
  1664. }
  1665. }
  1666. /*
  1667. *根据年月计算有几天
  1668. */
  1669. function getmonthByYM($param)
  1670. {
  1671. $month = $param['month'] ? $param['month'] : date('m', time());
  1672. $year = $param['year'] ? $param['year'] : date('Y', time());
  1673. if (in_array($month, array('1', '3', '5', '7', '8', '01', '03', '05', '07', '08', '10', '12'))) {
  1674. $days = '31';
  1675. } elseif ($month == 2) {
  1676. if ($year % 400 == 0 || ($year % 4 == 0 && $year % 100 !== 0)) {
  1677. //判断是否是闰年
  1678. $days = '29';
  1679. } else {
  1680. $days = '28';
  1681. }
  1682. } else {
  1683. $days = '30';
  1684. }
  1685. return $days;
  1686. }
  1687. /**
  1688. * 根据时间戳计算当月天数
  1689. * @param
  1690. */
  1691. function getmonthdays($time)
  1692. {
  1693. $month = date('m', $time);
  1694. $year = date('Y', $time);
  1695. if (in_array($month, array('1', '3', '5', '7', '8', '01', '03', '05', '07', '08', '10', '12'))) {
  1696. $days = '31';
  1697. } elseif ($month == 2) {
  1698. if ($year % 400 == 0 || ($year % 4 == 0 && $year % 100 !== 0)) {
  1699. //判断是否是闰年
  1700. $days = '29';
  1701. } else {
  1702. $days = '28';
  1703. }
  1704. } else {
  1705. $days = '30';
  1706. }
  1707. return $days;
  1708. }
  1709. /**
  1710. * 生成从开始时间到结束时间的日期数组
  1711. * @param type,默认时间戳格式
  1712. * @param type = 1 时,date格式
  1713. * @param type = 2 时,获取每日开始、结束时间
  1714. */
  1715. function dateList($start, $end, $type = 0)
  1716. {
  1717. if (!is_numeric($start) || !is_numeric($end) || ($end <= $start)) return '';
  1718. $i = 0;
  1719. //从开始日期到结束日期的每日时间戳数组
  1720. $d = array();
  1721. if ($type == 1) {
  1722. while ($start <= $end) {
  1723. $d[$i] = date('Y-m-d', $start);
  1724. $start = $start + 86400;
  1725. $i++;
  1726. }
  1727. } else {
  1728. while ($start <= $end) {
  1729. $d[$i] = $start;
  1730. $start = $start + 86400;
  1731. $i++;
  1732. }
  1733. }
  1734. if ($type == 2) {
  1735. $list = array();
  1736. foreach ($d as $k => $v) {
  1737. $list[$k] = getDateRange($v);
  1738. }
  1739. return $list;
  1740. } else {
  1741. return $d;
  1742. }
  1743. }
  1744. /**
  1745. * 获取指定日期开始时间与结束时间
  1746. */
  1747. function getDateRange($timestamp)
  1748. {
  1749. $ret = array();
  1750. $ret['sdate'] = strtotime(date('Y-m-d', $timestamp));
  1751. $ret['edate'] = strtotime(date('Y-m-d', $timestamp)) + 86400;
  1752. return $ret;
  1753. }
  1754. /**
  1755. * 生成从开始月份到结束月份的月份数组
  1756. * @param int $start 开始时间戳
  1757. * @param int $end 结束时间戳
  1758. */
  1759. function monthList($start, $end)
  1760. {
  1761. if (!is_numeric($start) || !is_numeric($end) || ($end <= $start)) return '';
  1762. $start = date('Y-m', $start);
  1763. $end = date('Y-m', $end);
  1764. //转为时间戳
  1765. $start = strtotime($start . '-01');
  1766. $end = strtotime($end . '-01');
  1767. $i = 0;
  1768. $d = array();
  1769. while ($start <= $end) {
  1770. //这里累加每个月的的总秒数 计算公式:上一月1号的时间戳秒数减去当前月的时间戳秒数
  1771. $d[$i] = $start;
  1772. $start += strtotime('+1 month', $start) - $start;
  1773. $i++;
  1774. }
  1775. return $d;
  1776. }
  1777. /**
  1778. * 人民币转大写
  1779. * @param
  1780. */
  1781. function cny($ns)
  1782. {
  1783. static $cnums = array("零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"),
  1784. $cnyunits = array("圆", "角", "分"),
  1785. $grees = array("拾", "佰", "仟", "万", "拾", "佰", "仟", "亿");
  1786. list($ns1, $ns2) = explode(".", $ns, 2);
  1787. $ns2 = array_filter(array($ns2[1], $ns2[0]));
  1788. $ret = array_merge($ns2, array(implode("", _cny_map_unit(str_split($ns1), $grees)), ""));
  1789. $ret = implode("", array_reverse(_cny_map_unit($ret, $cnyunits)));
  1790. return str_replace(array_keys($cnums), $cnums, $ret);
  1791. }
  1792. function _cny_map_unit($list, $units)
  1793. {
  1794. $ul = count($units);
  1795. $xs = array();
  1796. foreach (array_reverse($list) as $x) {
  1797. $l = count($xs);
  1798. if ($x != "0" || !($l % 4)) {
  1799. $n = ($x == '0' ? '' : $x) . ($units[($l - 1) % $ul]);
  1800. } else {
  1801. $n = is_numeric($xs[0][0]) ? $x : '';
  1802. }
  1803. array_unshift($xs, $n);
  1804. }
  1805. return $xs;
  1806. }
  1807. /**
  1808. * 根据类型获取上一类型时间戳数组
  1809. */
  1810. function getLstTimeByType($type = 'today')
  1811. {
  1812. switch ($type) {
  1813. case 'yesterday' :
  1814. $timeArr = Time::yesterday();
  1815. break;
  1816. case 'week' :
  1817. $timeArr = Time::week();
  1818. break;
  1819. case 'lastWeek' :
  1820. $timeArr = Time::lastWeek();
  1821. break;
  1822. case 'month' :
  1823. $timeArr = Time::month();
  1824. break;
  1825. case 'lastMonth' :
  1826. $timeArr = Time::lastMonth();
  1827. break;
  1828. case 'quarter' :
  1829. //本季度
  1830. $month = date('m');
  1831. if ($month == 1 || $month == 2 || $month == 3) {
  1832. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1833. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1834. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1835. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1836. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1837. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1838. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1839. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1840. } else {
  1841. $daterange_start_time = strtotime(date('Y-10-01 00:00:00'));
  1842. $daterange_end_time = strtotime(date("Y-12-31 23:59:59"));
  1843. }
  1844. $timeArr = array($daterange_start_time, $daterange_end_time);
  1845. break;
  1846. case 'lastQuarter' :
  1847. //上季度
  1848. $month = date('m');
  1849. if ($month == 1 || $month == 2 || $month == 3) {
  1850. $year = date('Y') - 1;
  1851. $daterange_start_time = strtotime(date($year . '-10-01 00:00:00'));
  1852. $daterange_end_time = strtotime(date($year . '-12-31 23:59:59'));
  1853. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1854. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1855. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1856. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1857. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1858. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1859. } else {
  1860. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1861. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1862. }
  1863. $timeArr = array($daterange_start_time, $daterange_end_time);
  1864. break;
  1865. case 'year' :
  1866. $timeArr = Time::year();
  1867. break;
  1868. case 'lastYear' :
  1869. $timeArr = Time::lastYear();
  1870. break;
  1871. default :
  1872. $timeArr = Time::today();
  1873. break;
  1874. }
  1875. return $timeArr;
  1876. }
  1877. /**
  1878. * 根据类型获取开始结束时间戳数组
  1879. * @param
  1880. */
  1881. function getTimeByType($type = 'today', $is_last = false)
  1882. {
  1883. $lastArr = [];
  1884. switch ($type) {
  1885. case 'yesterday' :
  1886. $timeArr = Time::yesterday();
  1887. break;
  1888. case 'week' :
  1889. $timeArr = Time::week();
  1890. break;
  1891. case 'lastWeek' :
  1892. $timeArr = Time::lastWeek();
  1893. break;
  1894. case 'month' :
  1895. $timeArr = Time::month();
  1896. break;
  1897. case 'lastMonth' :
  1898. $timeArr = Time::lastMonth();
  1899. break;
  1900. case 'quarter' :
  1901. //本季度
  1902. $month = date('m');
  1903. if ($month == 1 || $month == 2 || $month == 3) {
  1904. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1905. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1906. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1907. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1908. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1909. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1910. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1911. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1912. } else {
  1913. $daterange_start_time = strtotime(date('Y-10-01 00:00:00'));
  1914. $daterange_end_time = strtotime(date("Y-12-31 23:59:59"));
  1915. }
  1916. $timeArr = array($daterange_start_time, $daterange_end_time);
  1917. break;
  1918. case 'lastQuarter' :
  1919. //上季度
  1920. $month = date('m');
  1921. if ($month == 1 || $month == 2 || $month == 3) {
  1922. $year = date('Y') - 1;
  1923. $daterange_start_time = strtotime(date($year . '-10-01 00:00:00'));
  1924. $daterange_end_time = strtotime(date($year . '-12-31 23:59:59'));
  1925. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1926. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1927. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1928. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1929. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1930. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1931. } else {
  1932. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1933. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1934. }
  1935. $timeArr = array($daterange_start_time, $daterange_end_time);
  1936. break;
  1937. case 'year' :
  1938. $timeArr = Time::year();
  1939. break;
  1940. case 'lastYear' :
  1941. $timeArr = Time::lastYear();
  1942. break;
  1943. default :
  1944. $timeArr = Time::today();
  1945. break;
  1946. }
  1947. if ($is_last) {
  1948. return $lastArr;
  1949. } else {
  1950. return $timeArr;
  1951. }
  1952. }
  1953. /**
  1954. * 服务器附件完整路径处理
  1955. * @param
  1956. */
  1957. function getFullPath($path)
  1958. {
  1959. if ($path) {
  1960. $protocol = strpos(strtolower($_SERVER['REQUEST_SCHEME']), 'https') === false ? 'http' : 'https';
  1961. return $protocol . '://' . $_SERVER['HTTP_HOST'] . substr($_SERVER["SCRIPT_NAME"], 0, -10) . substr(str_replace(DS, '/', $path), 1);
  1962. } else {
  1963. return '';
  1964. }
  1965. }
  1966. /*取得文件后缀*/
  1967. function getExtension($filename)
  1968. {
  1969. $mytext = substr($filename, strrpos($filename, '.') + 1);
  1970. return $mytext;
  1971. }
  1972. /**
  1973. * 生成编号
  1974. * @param prefix 前缀
  1975. * @return
  1976. * @author Michael_xu
  1977. */
  1978. function prefixNumber($prefix, $number_id = 0, $str = 5)
  1979. {
  1980. return $prefixNumber = $prefix . str_pad($number_id, $str, 0, STR_PAD_LEFT); //填充字符串的左侧(将字符串填充为新的长度)
  1981. }
  1982. /**
  1983. * curl 模拟GET请求
  1984. * @author lee
  1985. ***/
  1986. function curl_get($url)
  1987. {
  1988. //初始化
  1989. $ch = curl_init();
  1990. //设置抓取的url
  1991. curl_setopt($ch, CURLOPT_URL, $url);
  1992. //设置获取的信息以文件流的形式返回,而不是直接输出。
  1993. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  1994. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书
  1995. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // https请求 不验证hosts
  1996. //执行命令
  1997. $output = curl_exec($ch);
  1998. curl_close($ch); //释放curl句柄
  1999. return $output;
  2000. }
  2001. /**
  2002. * 地址坐标转换
  2003. * @param prefix 前缀
  2004. * @return
  2005. * @author Michael_xu
  2006. */
  2007. function get_lng_lat($address)
  2008. {
  2009. $map_ak = config('map_ak');
  2010. $url = "http://api.map.baidu.com/geocoder/v2/?address=$address&output=json&ak=$map_ak&callback=showLocation";
  2011. $ret_script = curl_get($url);
  2012. preg_match_all("/\{.*?\}}/is", $ret_script, $matches);
  2013. $ret_arr = json_decode($matches[0][0], true);
  2014. if ($ret_arr['status'] == 0) { //成功
  2015. $location['lng'] = $ret_arr['result']['location']['lng'];
  2016. $location['lat'] = $ret_arr['result']['location']['lat'];
  2017. return $location;
  2018. } else {
  2019. return false;
  2020. }
  2021. }
  2022. /**
  2023. * 导出数据为excel表格
  2024. * @param $data 一个二维数组,结构如同从数据库查出来的数组
  2025. * @param $title excel的第一行标题,一个数组,如果为空则没有标题
  2026. * @param $filename 下载的文件名
  2027. * @param exportexcel($arr,array('id','账户','密码','昵称'),'文件名!');
  2028. */
  2029. function exportexcel($data = array(), $title = array(), $filename = 'report')
  2030. {
  2031. header("Content-type:application/octet-stream");
  2032. header("Accept-Ranges:bytes");
  2033. header("Content-type:application/vnd.ms-excel");
  2034. header("Content-Disposition:attachment;filename=" . $filename . ".xls");
  2035. header("Pragma: no-cache");
  2036. header("Expires: 0");
  2037. //导出xls 开始
  2038. if (!empty($title)) {
  2039. foreach ($title as $k => $v) {
  2040. $title[$k] = iconv("UTF-8", "GB2312", $v);
  2041. }
  2042. $title = implode("\t", $title);
  2043. echo "$title\n";
  2044. }
  2045. if (!empty($data)) {
  2046. foreach ($data as $key => $val) {
  2047. foreach ($val as $ck => $cv) {
  2048. $data[$key][$ck] = iconv("UTF-8", "GB2312", $cv);
  2049. }
  2050. $data[$key] = implode("\t", $data[$key]);
  2051. }
  2052. echo implode("\n", $data);
  2053. }
  2054. }
  2055. //根据数据库查询出来数组获取某个字段拼接字符串
  2056. function getFieldArray($array = array(), $field = '')
  2057. {
  2058. if (is_array($array) && $field) {
  2059. $ary = array();
  2060. foreach ($array as $value) {
  2061. $ary[] = $value[$field];
  2062. }
  2063. $str = implode(',', $ary);
  2064. return $str;
  2065. } else {
  2066. return false;
  2067. }
  2068. }
  2069. /**
  2070. * 检查该字段若必填,加上"*"
  2071. * @param is_null 是否为空 0否 1是
  2072. * @param name 字段名称
  2073. **/
  2074. function sign_required($is_null, $name)
  2075. {
  2076. if ($is_null == 1) {
  2077. return '*' . $name;
  2078. } else {
  2079. return $name;
  2080. }
  2081. }
  2082. /**
  2083. * [获取是否有管理员角色 adminGroupTypes]
  2084. * @param user_id 当前人ID
  2085. * @return
  2086. */
  2087. function adminGroupTypes($user_id)
  2088. {
  2089. $userModel = new UserModel();
  2090. $groupsArr = $userModel->get($user_id)->groups;
  2091. $groupids = [];
  2092. if ($groupsArr) {
  2093. foreach ($groupsArr as $key => $val) {
  2094. $groupids[] = $val['id'];
  2095. }
  2096. }
  2097. $types = db('admin_group')->where(['id' => ['in', $groupids]])->group('types')->column('types');
  2098. if ($user_id == 1) {
  2099. $types[] = 1;
  2100. }
  2101. return $types ?: [];
  2102. }
  2103. /**
  2104. * [权限数组]
  2105. * @param ruleIds 当前人权限id
  2106. * @return
  2107. */
  2108. function rulesListToArray($rulesList, $ruleIds = [])
  2109. {
  2110. $newList = [];
  2111. if (!is_array($rulesList)) {
  2112. return array();
  2113. } else {
  2114. foreach ($rulesList as $k => $v) {
  2115. if (!is_array($v['children'])) continue;
  2116. foreach ($v['children'] as $k1 => $v1) {
  2117. if (!is_array($v1['children'])) continue;
  2118. foreach ($v1['children'] as $k2 => $v2) {
  2119. $check = false;
  2120. if (in_array($v2['id'], $ruleIds)) {
  2121. $check = true;
  2122. }
  2123. $newList[$v['name']][$v1['name']][$v2['name']] = $check;
  2124. }
  2125. }
  2126. }
  2127. }
  2128. return $newList ?: [];
  2129. }
  2130. /**
  2131. * [获取下一审批信息 nextCheckData]
  2132. * @param user_id 审批申请人ID
  2133. * @param flow_id 审批流ID
  2134. * @param types 关联对象
  2135. * @param types_id 联对象ID
  2136. * @param order_id 审批排序ID
  2137. * @return
  2138. */
  2139. function nextCheckData($user_id, $flow_id, $types, $types_id, $order_id, $check_user_id)
  2140. {
  2141. $new_order_id = $order_id;
  2142. $max_order_id = db('admin_examine_step')->where(['flow_id' => $flow_id])->max('order_id'); //审批流最大排序ID
  2143. $examineStepModel = new \app\admin\model\ExamineStep();
  2144. $stepInfo = $examineStepModel->getStepByOrder($flow_id, $new_order_id); //审批步骤
  2145. $next_user_ids = [];
  2146. $is_end = 0; //审批结束
  2147. //固定流程(status 1负责人主管,2指定用户(任意一人),3指定用户(多人会签),4上一级审批人主管)
  2148. //当前步骤审批人user_id
  2149. $step_user_ids = $examineStepModel->getUserByStep($stepInfo['step_id'], $user_id);
  2150. if ($step_user_ids) {
  2151. if (!$order_id) {
  2152. //创建时使用
  2153. $sub_user_ids = stringToArray($step_user_ids);
  2154. } else {
  2155. if ($stepInfo['status'] == 3) {
  2156. //会签(并关系)
  2157. //当前步骤已审批user_id
  2158. $check_user_ids = $examineStepModel->getUserByCheck($types, $types_id, $new_order_id);
  2159. $user_ids[] = $check_user_id;
  2160. $check_user_ids = $check_user_ids ? array_merge($check_user_ids, $user_ids) : $user_ids;
  2161. //剩余审批人user_id
  2162. $sub_user_ids = $check_user_ids ? array_diff(explode(',', $step_user_ids), $check_user_ids) : $step_user_ids;
  2163. $sub_user_ids = array_unique(array_filter($sub_user_ids));
  2164. if (!$sub_user_ids) {
  2165. $is_end = 1;
  2166. }
  2167. } else {
  2168. $is_end = 1;
  2169. }
  2170. }
  2171. } else {
  2172. $is_end = 1;
  2173. }
  2174. if ($is_end == 1) {
  2175. $next_order_id = $new_order_id + 1;
  2176. } else {
  2177. $next_order_id = $new_order_id;
  2178. }
  2179. //当前审批步骤已结束
  2180. if ($is_end == 1) {
  2181. //当前审批流程是否结束
  2182. $stepInfo = $examineStepModel->getStepByOrder($flow_id, $next_order_id); //审批步骤
  2183. $next_step_user_ids = $examineStepModel->getUserByStep($stepInfo['step_id'], $user_id);
  2184. $next_user_ids = stringToArray($next_step_user_ids);
  2185. } else {
  2186. $next_user_ids = array_unique(array_filter($sub_user_ids));
  2187. }
  2188. if (!$next_user_ids && $next_order_id <= $max_order_id) {
  2189. $newRes = [];
  2190. $newRes = nextCheckData($user_id, $flow_id, $types, $types_id, $next_order_id, $check_user_id);
  2191. $next_user_ids = $newRes['next_user_ids'];
  2192. }
  2193. $data = [];
  2194. $data['order_id'] = ($next_order_id <= $max_order_id) ? $next_order_id : $max_order_id;
  2195. $data['next_user_ids'] = $next_user_ids ?: '';
  2196. return $data;
  2197. }
  2198. /**
  2199. * 解析获取php.ini 的upload_max_filesize(单位:byte)
  2200. * @param $dec int 小数位数
  2201. * @return float (单位:byte)
  2202. * */
  2203. function get_upload_max_filesize_byte($dec = 2)
  2204. {
  2205. $max_size = ini_get('upload_max_filesize');
  2206. preg_match('/(^[0-9\.]+)(\w+)/', $max_size, $info);
  2207. $size = $info[1];
  2208. $suffix = strtoupper($info[2]);
  2209. $a = array_flip(array("B", "KB", "MB", "GB", "TB", "PB"));
  2210. $b = array_flip(array("B", "K", "M", "G", "T", "P"));
  2211. $pos = $a[$suffix] && $a[$suffix] !== 0 ? $a[$suffix] : $b[$suffix];
  2212. return round($size * pow(1024, $pos), $dec);
  2213. }
  2214. /**
  2215. * 模拟post进行url请求
  2216. * @param string $url
  2217. * @param string $param
  2218. */
  2219. function curl_post($url = '', $post = array())
  2220. {
  2221. $curl = curl_init(); // 启动一个CURL会话
  2222. curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
  2223. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
  2224. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
  2225. curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
  2226. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
  2227. curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
  2228. curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
  2229. curl_setopt($curl, CURLOPT_POSTFIELDS, $post); // Post提交的数据包
  2230. curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
  2231. curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
  2232. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
  2233. $res = curl_exec($curl); // 执行操作
  2234. if (curl_errno($curl)) {
  2235. echo 'Errno' . curl_error($curl);//捕抓异常
  2236. }
  2237. curl_close($curl); // 关闭CURL会话
  2238. return $res; // 返回数据,json格式
  2239. }
  2240. /**
  2241. * 输出json字符串,用于接口调试
  2242. *
  2243. * @return void
  2244. * @author ymob
  2245. */
  2246. function vdd()
  2247. {
  2248. header('Content-Type: text/json; charset=utf-8');
  2249. $args = func_get_args();
  2250. foreach ($args as &$val) {
  2251. if ($val instanceof think\Model) {
  2252. $val = $val->getLastSql();
  2253. }
  2254. }
  2255. if (count($args) < 2) {
  2256. $args = array_shift($args);
  2257. }
  2258. die(json_encode($args));
  2259. }
  2260. /**
  2261. * 根据时间查询参数返回时间条件 (用于统计分析模块)
  2262. *
  2263. * @param array $where
  2264. * @param string $field
  2265. * @return void
  2266. * @author ymob
  2267. */
  2268. function getWhereTimeByParam(&$where, $field = 'create_time')
  2269. {
  2270. $param = request()->param();
  2271. if (empty($param['type']) && empty($param['start_time'])) {
  2272. $param['type'] = 'month';
  2273. }
  2274. if (!empty($param['start_time'])) {
  2275. $where[$field] = ['between', [$param['start_time'], $param['end_time']]];
  2276. } else {
  2277. $timeRange = getTimeByType($param['type']);
  2278. if ($timeRange) {
  2279. $where[$field] = ['between', [$timeRange[0], $timeRange[1]]];
  2280. }
  2281. }
  2282. }
  2283. /**
  2284. * 根据员工、部门查询参数返回员工、部门条件 (用于统计分析模块)
  2285. *
  2286. * @param array $where
  2287. * @param string $field
  2288. * @param string $m
  2289. * @param string $c
  2290. * @param string $a
  2291. * @return void
  2292. * @author ymob
  2293. */
  2294. function getWhereUserByParam(&$where, $field = 'owner_user_id', $m = '', $c = '', $a = '')
  2295. {
  2296. $param = request()->param();
  2297. $userModel = new UserModel();
  2298. $map_user_ids = [];
  2299. if ($param['user_id']) {
  2300. $map_user_ids = array($param['user_id']);
  2301. } elseif ($param['structure_id']) {
  2302. $map_user_ids = $userModel->getSubUserByStr($param['structure_id'], 2);
  2303. } else {
  2304. $map_user_ids = $userModel->getUserByPer($m, $c, $a);
  2305. $where[$field] = array('in', $map_user_ids);
  2306. return;
  2307. }
  2308. $perUserIds = $userModel->getUserByPer($m, $c, $a); //权限范围内userIds
  2309. $userIds = array_intersect($map_user_ids, $perUserIds); //数组交集
  2310. $where[$field] = array('in', $userIds);
  2311. }
  2312. /**
  2313. * 获取客户浏览器类型
  2314. */
  2315. function getBrowser()
  2316. {
  2317. $Browser = $_SERVER['HTTP_USER_AGENT'];
  2318. if (preg_match('/MSIE/i', $Browser)) {
  2319. $Browser = 'MSIE';
  2320. } elseif (preg_match('/Firefox/i', $Browser)) {
  2321. $Browser = 'Firefox';
  2322. } elseif (preg_match('/Chrome/i', $Browser)) {
  2323. $Browser = 'Chrome';
  2324. } elseif (preg_match('/Safari/i', $Browser)) {
  2325. $Browser = 'Safari';
  2326. } elseif (preg_match('/Opera/i', $Browser)) {
  2327. $Browser = 'Opera';
  2328. } else {
  2329. $Browser = 'Other';
  2330. }
  2331. return $Browser;
  2332. }
  2333. /**
  2334. * 获取客户端系统
  2335. */
  2336. function getOS()
  2337. {
  2338. $agent = $_SERVER['HTTP_USER_AGENT'];
  2339. if (preg_match('/win/i', $agent)) {
  2340. if (preg_match('/nt 6.1/i', $agent)) {
  2341. $OS = 'Windows 7';
  2342. } else if (preg_match('/nt 6.2/i', $agent)) {
  2343. $OS = 'Windows 8';
  2344. } else if (preg_match('/nt 10.0/i', $agent)) {
  2345. $OS = 'Windows 10';
  2346. } else {
  2347. $OS = 'Windows';
  2348. }
  2349. } elseif (preg_match('/mac/i', $agent)) {
  2350. $OS = 'MAC';
  2351. } elseif (preg_match('/linux/i', $agent)) {
  2352. $OS = 'Linux';
  2353. } elseif (preg_match('/unix/i', $agent)) {
  2354. $OS = 'Unix';
  2355. } elseif (preg_match('/bsd/i', $agent)) {
  2356. $OS = 'BSD';
  2357. } else {
  2358. $OS = 'Other';
  2359. }
  2360. return $OS;
  2361. }
  2362. /**
  2363. * 根据IP获取地址
  2364. */
  2365. function getAddress($ip)
  2366. {
  2367. $res = file_get_contents("http://ip.360.cn/IPQuery/ipquery?ip=" . $ip);
  2368. $res = json_decode($res, 1);
  2369. if ($res && $res['errno'] == 0) {
  2370. return explode("\t", $res['data'])[0];
  2371. } else {
  2372. return '';
  2373. }
  2374. }
  2375. /**
  2376. * 下载服务器文件
  2377. *
  2378. * @param string $file 文件路径
  2379. * @param string $name 下载名称
  2380. * @param boolean $del 下载后删除
  2381. * @return void
  2382. * @author Ymob
  2383. */
  2384. function download($file, $name = '', $del = false)
  2385. {
  2386. if (!file_exists($file)) {
  2387. return resultArray([
  2388. 'error' => '文件不存在',
  2389. ]);
  2390. }
  2391. // 仅允许下载 public 目录下文件
  2392. $res = strpos(realpath($file), realpath('./public'));
  2393. if ($res !== 0) {
  2394. return resultArray([
  2395. 'error' => '文件路径错误',
  2396. ]);
  2397. }
  2398. $fp = fopen($file, 'r');
  2399. $size = filesize($file);
  2400. //下载文件需要的头
  2401. header("Content-type: application/octet-stream");
  2402. header("Accept-Ranges: bytes");
  2403. header('ResponseType: blob');
  2404. header("Accept-Length: $size");
  2405. $file_name = $name != '' ? $name : pathinfo($file, PATHINFO_BASENAME);
  2406. // urlencode 处理中文乱码
  2407. header("Content-Disposition:attachment; filename=" . urlencode($file_name));
  2408. // 导出数据时 csv office Excel 需要添加bom头
  2409. if (pathinfo($file, PATHINFO_EXTENSION) == 'csv') {
  2410. echo "\xEF\xBB\xBF"; // UTF-8 BOM
  2411. }
  2412. $fileCount = 0;
  2413. $fileUnit = 1024;
  2414. while (!feof($fp) && $size - $fileCount > 0) {
  2415. $fileContent = fread($fp, $fileUnit);
  2416. echo $fileContent;
  2417. $fileCount += $fileUnit;
  2418. }
  2419. fclose($fp);
  2420. // 删除
  2421. if ($del) @unlink($file);
  2422. die();
  2423. }
  2424. /**
  2425. * 临时目录生成文件名,并返回绝对路径
  2426. *
  2427. * @param string $ext 文件类型后缀
  2428. * @param string $path 临时文件目录 默认 ./public/temp/
  2429. * @return string $file_path 文件名称绝对路径
  2430. * @author ymob
  2431. */
  2432. function tempFileName($ext = '')
  2433. {
  2434. // 临时目录
  2435. $path = TEMP_DIR . date('Ymd') . DS;
  2436. if (!file_exists($path)) {
  2437. mkdir($path, 0777, true);
  2438. }
  2439. $ext = trim($ext, '.');
  2440. do {
  2441. $temp_file = md5(time() . rand(1000, 9999));
  2442. $file_path = $path . $temp_file . '.' . $ext;
  2443. } while (file_exists($file_path));
  2444. return $file_path;
  2445. }
  2446. /**
  2447. * 递归删除目录
  2448. *
  2449. * @param string $dir
  2450. * @return void
  2451. * @author Ymob
  2452. */
  2453. function delDir($dir)
  2454. {
  2455. $dh = opendir($dir);
  2456. while ($file = readdir($dh)) {
  2457. if ($file != "." && $file != "..") {
  2458. $fullpath = $dir . "/" . $file;
  2459. if (!is_dir($fullpath)) {
  2460. @unlink($fullpath);
  2461. } else {
  2462. deldir($fullpath);
  2463. }
  2464. }
  2465. }
  2466. closedir($dh);
  2467. //删除当前文件夹:
  2468. @rmdir($dir);
  2469. }
  2470. /**
  2471. * 商业智能 查询缓存
  2472. *
  2473. * @param string $sql Sql语句
  2474. * @param int $bi_slow_query_time 慢查询时间(毫秒),默认读取Config(bi_slow_query_time)
  2475. * @return mixed
  2476. * @author Ymob
  2477. * @datetime 2019-11-21 17:36:50
  2478. */
  2479. function queryCache($sql = '', $bi_slow_query_time = null)
  2480. {
  2481. $key = 'BI_queryCache' . md5($sql);
  2482. $val = cache($key);
  2483. if (!$val) {
  2484. $start_time = microtime(true) * 1000;
  2485. $val = Db::query($sql);
  2486. $end_time = microtime(true) * 1000;
  2487. $slow_query = true;
  2488. // 是否使用系统默认设置-慢查询时间
  2489. if ($bi_slow_query_time === null) {
  2490. $bi_slow_query_time = config('bi_slow_query_time');
  2491. }
  2492. if ($bi_slow_query_time > 0) {
  2493. $slow_query = ($end_time - $start_time) > $bi_slow_query_time;
  2494. }
  2495. if ($slow_query && $val) {
  2496. cache($key, $val, config('bi_cache_time'));
  2497. }
  2498. }
  2499. return $val;
  2500. }
  2501. /**
  2502. * 图表时间范围处理,按月/天返回时间段数组
  2503. *
  2504. * @param int $start 开始时间(时间戳)
  2505. * @param int $end 结束时间(时间戳)
  2506. * @return array
  2507. * @author Ymob
  2508. * @datetime 2019-11-18 09:25:09
  2509. */
  2510. function getTimeArray($start = null, $end = null)
  2511. {
  2512. if ($start == null || $end == null) {
  2513. $param = request()->param();
  2514. switch ($param['type']) {
  2515. // 本年
  2516. case 'year':
  2517. $start = strtotime(date('Y-01-01'));
  2518. $end = strtotime('+1 year', $start) - 1;
  2519. break;
  2520. // 去年
  2521. case 'lastYear':
  2522. $start = strtotime(date(date('Y') - 1 . '-01-01'));
  2523. $end = strtotime('+1 year', $start) - 1;
  2524. break;
  2525. // 本季度、上季度
  2526. case 'quarter':
  2527. case 'lastQuarter':
  2528. $t = intval((date('m') - 1) / 3);
  2529. $start_y = ($t * 3) + 1;
  2530. $start = strtotime(date("Y-{$start_y}-01"));
  2531. if ($param['type'] == 'lastQuarter') { // 上季度
  2532. $start = strtotime('-3 month', $start);
  2533. }
  2534. $end = strtotime('+3 month', $start) - 1;
  2535. break;
  2536. // 本月、上月
  2537. case 'month':
  2538. case 'lastMonth':
  2539. $start = strtotime(date('Y-m-01'));
  2540. if ($param['type'] == 'lastMonth') {
  2541. $start = strtotime('-1 month', $start);
  2542. }
  2543. $end = strtotime('+1 month', $start) - 1;
  2544. break;
  2545. // 本周、上周
  2546. case 'week':
  2547. case 'lastWeek':
  2548. $start = strtotime('-' . (date('w') - 1) . 'day', strtotime(date('Y-m-d')));
  2549. if ($param['type'] == 'lastWeek') {
  2550. $start = strtotime('-7 day', $start);
  2551. }
  2552. $end = strtotime('+7 day', $start) - 1;
  2553. break;
  2554. // 今天、昨天
  2555. case 'today':
  2556. case 'yesterday':
  2557. $start = strtotime(date('Y-m-d'));
  2558. if ($param['type'] == 'yesterday') {
  2559. $start = strtotime('-1 day', $start);
  2560. }
  2561. $end = strtotime('+1 day', $start) - 1;
  2562. break;
  2563. default:
  2564. if ($param['start_time'] && $param['end_time']) {
  2565. $start = $param['start_time'];
  2566. $end = $param['end_time'];
  2567. } else {
  2568. // 本年
  2569. $start = strtotime(date('Y-01-01'));
  2570. $end = strtotime('+1 year', $start) - 1;
  2571. }
  2572. break;
  2573. }
  2574. }
  2575. $between = [$start, $end];
  2576. $list = [];
  2577. $len = ($end - $start) / 86400;
  2578. // 大于30天 按月统计、小于按天统计
  2579. if ($len > 31) {
  2580. $time_format = '%Y-%m';
  2581. while (true) {
  2582. $start = strtotime(date('Y-m-01', $start));
  2583. $item = [];
  2584. $item['type'] = date('Y-m', $start);
  2585. $item['start_time'] = $start;
  2586. $item['end_time'] = strtotime('+1 month', $start) - 1;
  2587. $list[] = $item;
  2588. if ($item['end_time'] >= $end) break;
  2589. $start = $item['end_time'] + 1;
  2590. }
  2591. } else {
  2592. $time_format = '%Y-%m-%d';
  2593. while (true) {
  2594. $item = [];
  2595. $item['type'] = date('Y-m-d', $start);
  2596. $item['start_time'] = $start;
  2597. $item['end_time'] = strtotime('+1 day', $start) - 1;
  2598. $list[] = $item;
  2599. if ($item['end_time'] >= $end) break;
  2600. $start = $item['end_time'] + 1;
  2601. }
  2602. }
  2603. return [
  2604. 'list' => $list, // 时间段列表
  2605. 'time_format' => $time_format, // 时间格式 mysql 格式化时间戳
  2606. 'between' => $between // 开始结束时间
  2607. ];
  2608. }
  2609. /**
  2610. * 打印程序执行时间
  2611. *
  2612. * @param integer $s
  2613. * @return void
  2614. * @author Ymob
  2615. * @datetime 2019-11-28 09:31:45
  2616. */
  2617. function tt($s = 0)
  2618. {
  2619. die((string)round(microtime(1) - ($s ?: THINK_START_TIME), 3));
  2620. }
  2621. /**
  2622. * 数据库备份
  2623. */
  2624. function DBBackup($file = '', $path = '')
  2625. {
  2626. $type = config('database.type');
  2627. $host = config('database.hostname');
  2628. $port = config('database.hostport');
  2629. $dbname = config('database.database');
  2630. $username = config('database.username');
  2631. $password = config('database.password');
  2632. $dsn = "{$type}:host={$host};dbname={$dbname};port={$port}";
  2633. if ($file == '') {
  2634. $save_path = dirname(APP_PATH) . DS . 'data' . DS . date('Ym') . DS;
  2635. if (!file_exists($save_path) && !mkdir($save_path, '0777', true)) {
  2636. return 'data目录无写入权限';
  2637. }
  2638. $file = $save_path . date('d_H_i') . '_db_backup' . '.sql';
  2639. }
  2640. if (file_exists($file)) {
  2641. return '数据库备份文件已存在(自动备份时间间隔需大于1分钟)。';
  2642. }
  2643. try {
  2644. $backup = new \com\Mysqldump($dsn, $username, $password);
  2645. $backup->start($file);
  2646. return true;
  2647. } catch (\Exception $e) {
  2648. return '备份失败,请手动备份。错误原因:' . $e->getMessage();
  2649. }
  2650. }
  2651. /**
  2652. * 根据ip获取地址
  2653. */
  2654. function getAddressById($data)
  2655. {
  2656. $ip = new IpLocation();
  2657. $ip_address = $ip->getlocation($data);
  2658. return $ip_address;
  2659. }
  2660. if (!function_exists('isSuperAdministrators')) {
  2661. /**
  2662. * 判断是否是超级管理员
  2663. *
  2664. * @param $userId
  2665. * @return bool
  2666. */
  2667. function isSuperAdministrators($userId)
  2668. {
  2669. $status = false;
  2670. $apiCommon = new \app\admin\controller\ApiCommon();
  2671. $userId = !empty($userId) ? $userId : $apiCommon->userInfo['id'];
  2672. $data = db('admin_access')->where('user_id', $userId)->column('group_id');
  2673. if ($userId == 1 || in_array(1, $data)) {
  2674. $status = true;
  2675. }
  2676. return $status;
  2677. }
  2678. }
  2679. if (!function_exists('getFieldGrantData')) {
  2680. /**
  2681. * 获取自动授权数据
  2682. *
  2683. * @return array
  2684. */
  2685. function getFieldGrantData($userId)
  2686. {
  2687. $result = [];
  2688. $apiCommon = new \app\admin\controller\ApiCommon();
  2689. $userId = !empty($userId) ? $userId : $apiCommon->userInfo['id'];
  2690. $grantData = Db::query("
  2691. SELECT
  2692. `grant`.`module`, `grant`.`column`, `grant`.`content`
  2693. FROM
  2694. `5kcrm_admin_access` AS `access`
  2695. LEFT JOIN
  2696. `5kcrm_admin_group` AS `group` ON `access`.`group_id` = `group`.`id`
  2697. LEFT JOIN
  2698. `5kcrm_admin_field_grant` AS `grant` ON `group`.`id` = `grant`.`role_id`
  2699. WHERE
  2700. `access`.`user_id` =
  2701. " . $userId);
  2702. # 存在多角色多授权的情况
  2703. foreach ($grantData as $key => $value) {
  2704. if (empty($value['module']) || empty($value['column'])) continue;
  2705. $result[$value['module'] . '_' . $value['column']][] = !empty($value['content']) ? unserialize($value['content']) : [];
  2706. }
  2707. return $result;
  2708. }
  2709. }
  2710. if (!function_exists('getFieldGrantStatus')) {
  2711. /**
  2712. * 获取字段授权状态
  2713. *
  2714. * @param $field
  2715. * @param $grantData
  2716. * @return int[]
  2717. */
  2718. function getFieldGrantStatus($field, $grantData)
  2719. {
  2720. # 默认状态都是不能查看、不能编辑,通过配置来取最大权限。
  2721. $result = ['read' => 0, 'write' => 0,'maskType'=>0];
  2722. foreach ($grantData as $key => $value) {
  2723. $fieldBool = false;
  2724. foreach ($value as $ke => $va) {
  2725. # 多个字段授权,只取最高的读权限
  2726. if ($va['field'] == $field && $result['read'] == 0) {
  2727. $result['read'] = $va['read'] > $result['read'] ? $va['read'] : $result['read'];
  2728. }
  2729. # 多个字段授权,只取最高的写权限
  2730. if ($va['field'] == $field && $result['write'] == 0) {
  2731. $result['write'] = $va['write'] > $result['write'] ? $va['write'] : $result['write'];
  2732. }
  2733. if ($va['field'] == $field && $va['maskType'] != 0) {
  2734. $result['maskType'] = !empty($va['maskType'])?$va['maskType']:0;
  2735. }
  2736. if ($va['field'] == $field) $fieldBool = true;
  2737. }
  2738. # 对于不在权限控制之内的字段,将状态都改为1。
  2739. if (!$fieldBool) {
  2740. $result['read'] = 1;
  2741. $result['write'] = 1;
  2742. }
  2743. }
  2744. return $result;
  2745. }
  2746. }
  2747. /**
  2748. * 仪表盘日志使用
  2749. * 根据类型获取开始结束时间戳数组
  2750. * @param
  2751. */
  2752. function ByDateTime($type = 'today')
  2753. {
  2754. switch ($type) {
  2755. case 'yesterday' :
  2756. $timeArr = DataTime::yesterday();
  2757. $timeArr['last_time'] = DataTime::yesterday(1);
  2758. break;
  2759. case 'week' :
  2760. $timeArr = DataTime::week();
  2761. $timeArr['last_time'] = DataTime::lastWeek();
  2762. break;
  2763. case 'lastWeek' :
  2764. $timeArr = DataTime::lastWeek();
  2765. $timeArr['last_time'] = DataTime::lastWeek(1);
  2766. break;
  2767. case 'month' :
  2768. $timeArr = DataTime::month();
  2769. $timeArr['last_time'] = DataTime::lastMonth();
  2770. break;
  2771. case 'lastMonth' :
  2772. $timeArr = DataTime::lastMonth();
  2773. $timeArr['last_time'] = DataTime::lastMonth(1);
  2774. break;
  2775. case 'quarter' :
  2776. //本季度
  2777. $month = date('m');
  2778. if ($month == 1 || $month == 2 || $month == 3) {
  2779. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  2780. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  2781. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2782. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  2783. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  2784. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2785. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  2786. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  2787. } else {
  2788. $daterange_start_time = strtotime(date('Y-10-01 00:00:00'));
  2789. $daterange_end_time = strtotime(date("Y-12-31 23:59:59"));
  2790. }
  2791. //上季度
  2792. $month = date('m');
  2793. if ($month == 1 || $month == 2 || $month == 3) {
  2794. $year = date('Y') - 1;
  2795. $daterange_start_time_last_time = strtotime(date($year . '-10-01 00:00:00'));
  2796. $daterange_end_time_last_time = strtotime(date($year . '-12-31 23:59:59'));
  2797. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2798. $daterange_start_time_last_time = strtotime(date('Y-01-01 00:00:00'));
  2799. $daterange_end_time_last_time = strtotime(date("Y-03-31 23:59:59"));
  2800. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2801. $daterange_start_time_last_time = strtotime(date('Y-04-01 00:00:00'));
  2802. $daterange_end_time_last_time = strtotime(date("Y-06-30 23:59:59"));
  2803. } else {
  2804. $daterange_start_time_last_time = strtotime(date('Y-07-01 00:00:00'));
  2805. $daterange_end_time_last_time = strtotime(date("Y-09-30 23:59:59"));
  2806. }
  2807. $timeArr = array($daterange_start_time, $daterange_end_time);
  2808. $timeArr['last_time'] = array($daterange_start_time_last_time, $daterange_end_time_last_time);
  2809. break;
  2810. case 'lastQuarter' :
  2811. //上季度
  2812. $month = date('m');
  2813. if ($month == 1 || $month == 2 || $month == 3) {
  2814. $year = date('Y') - 1;
  2815. $daterange_start_time = strtotime(date($year . '-10-01 00:00:00'));
  2816. $daterange_end_time = strtotime(date($year . '-12-31 23:59:59'));
  2817. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2818. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  2819. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  2820. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2821. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  2822. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  2823. } else {
  2824. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  2825. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  2826. }
  2827. //上季度
  2828. $month = date('m');
  2829. if ($month == 1 || $month == 2 || $month == 3) {
  2830. $year = date('Y') - 2;
  2831. $daterange_start_time_last_time = strtotime(date($year . '-10-01 00:00:00'));
  2832. $daterange_end_time_last_time = strtotime(date($year . '-12-31 23:59:59'));
  2833. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2834. $daterange_start_time_last_time = strtotime(date('Y-01-01 00:00:00'));
  2835. $daterange_end_time_last_time = strtotime(date("Y-03-31 23:59:59"));
  2836. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2837. $daterange_start_time_last_time = strtotime(date('Y-04-01 00:00:00'));
  2838. $daterange_end_time_last_time = strtotime(date("Y-06-30 23:59:59"));
  2839. } else {
  2840. $daterange_start_time_last_time = strtotime(date('Y-07-01 00:00:00'));
  2841. $daterange_end_time_last_time = strtotime(date("Y-09-30 23:59:59"));
  2842. }
  2843. $timeArr = array($daterange_start_time, $daterange_end_time);
  2844. $timeArr['last_time'] = array($daterange_start_time_last_time, $daterange_end_time_last_time);
  2845. break;
  2846. case 'year' :
  2847. $timeArr = DataTime::year();
  2848. $timeArr['last_time'] = DataTime::lastYear();
  2849. break;
  2850. case 'lastYear' :
  2851. $timeArr = DataTime::lastYear();
  2852. $timeArr['last_time'] = DataTime::lastYear(1);
  2853. break;
  2854. case 'recent60' :
  2855. $timeArr = DataTime::recent60();
  2856. break;
  2857. case 'recent30' :
  2858. $timeArr = DataTime::recent30();
  2859. break;
  2860. default :
  2861. $timeArr = DataTime::today();
  2862. $timeArr['last_time'] = DataTime::yesterday();
  2863. break;
  2864. }
  2865. return $timeArr;
  2866. }
  2867. /**
  2868. * 系统操作日志
  2869. * @param int $user_id 用户
  2870. * @param string $types 方法所属模块
  2871. * @param int $action_id 操作
  2872. * @param string $module_name 模块
  2873. * @param string $action_name 修改添加删除新建
  2874. * @param array $oldData 旧数据
  2875. * @param array $newData 新数据
  2876. * @param string $target_name 被操作对象
  2877. * @param string $content 添加时创建使用
  2878. * @author alvin guogaobo
  2879. * @version 1.0 版本号
  2880. * @since 2021/3/26 0026 15:10
  2881. */
  2882. function SystemActionLog($user_id, $types, $module_name, $action_id, $action_name, $target_name, $oldData = [], $newData = [], $content = '')
  2883. {
  2884. //action_name 修改添加删除新建 action_id 操作id client_ip ip create_time时间 content 操作记录 target_name 被操作对象 module_name 模块 系统管理 固定 user_id 用户
  2885. $data = [];
  2886. $data['user_id'] = $user_id;
  2887. $data['create_time'] = time();
  2888. $data['client_ip'] = request()->ip();
  2889. $data['action_id'] = $action_id;
  2890. $data['action_name'] = $action_name;
  2891. $data['target_name'] = $target_name;
  2892. $data['module_name'] = $module_name;
  2893. $data['controller_name'] = $types;
  2894. $data['content'] = $content;
  2895. db('admin_system_log')->insert($data);
  2896. }
  2897. /**
  2898. * 系统操作日志
  2899. * @param int $user_id 用户
  2900. * @param string $types 方法所属模块
  2901. * @param string $action_name 修改添加删除新建
  2902. * @param string $target_name 被操作对象
  2903. * @param array $oldData 旧数据
  2904. * @param array $newData 新数据
  2905. * @param string $content 添加时创建使用
  2906. * @author alvin guogaobo
  2907. * @version 1.0 版本号
  2908. * @since 2021/4/2 0026 15:10
  2909. */
  2910. function RecordActionLog($user_id, $types, $action_name, $target_name, $oldData = [], $newData = [], $content = '')
  2911. {
  2912. //action_name 修改 添加 删除 client_ip ip create_time时间 content 操作记录 target_name 被操作对象 module 模块 user_id 用户
  2913. if (is_array($oldData) && is_array($newData) && $user_id) {
  2914. $differentData = array_diff_assoc($newData, $oldData);
  2915. $fieldModel = new FieldModel();
  2916. $userModel = new UserModel();
  2917. $structureModel = new \app\admin\model\Structure();
  2918. $field_arr = $fieldModel->getField(['types' => $types, 'unFormType' => ['file', 'form']]); //获取字段属性
  2919. $newFieldArr = array();
  2920. foreach ($field_arr as $k => $v) {
  2921. $newFieldArr[$v['field']] = $v;
  2922. }
  2923. $unField = ['update_time', 'create_time']; //定义过滤字段
  2924. $message = [];
  2925. $un_form_type = ['file', 'form'];
  2926. foreach ($differentData as $k => $v) {
  2927. if ($newFieldArr[$k] && !in_array($newFieldArr[$k]['form_type'], $un_form_type)) {
  2928. $field_name = '';
  2929. $field_name = $newFieldArr[$k]['name'];
  2930. $new_value = $v ?: '空';
  2931. $old_value = $oldData[$k] ?: '空';
  2932. switch ($newFieldArr[$k]['form_type']) {
  2933. case 'datetime' :
  2934. $new_value = $v ? date('Y-m-d', $v) : '';
  2935. $old_value = date('Y-m-d', $oldData[$k]);
  2936. if (!empty($v) && !empty($oldData[$k]))
  2937. break;
  2938. case 'user' :
  2939. $new_value = $v ? implode(',', $userModel->getUserNameByArr(stringToArray($v))) : '';
  2940. $old_value = $v ? implode(',', $userModel->getUserNameByArr(stringToArray($oldData[$k]))) : '';
  2941. break;
  2942. case 'structure' :
  2943. $new_value = $v ? implode(',', $structureModel->getStructureNameByArr(stringToArray($v))) : '';
  2944. $old_value = $v ? implode(',', $structureModel->getStructureNameByArr(stringToArray($oldData[$k]))) : '';
  2945. break;
  2946. case 'business_status' :
  2947. $new_value = $v ? db('crm_business_status')->where(['status_id' => $v])->value('name') : '';
  2948. $old_value = $v ? db('crm_business_status')->where(['status_id' => $oldData[$k]])->value('name') : '';
  2949. break;
  2950. case 'business_type' :
  2951. $new_value = $v ? db('crm_business_type')->where(['type_id' => $v])->value('name') : '';
  2952. $old_value = $v ? db('crm_business_type')->where(['type_id' => $oldData[$k]])->value('name') : '';
  2953. break;
  2954. case 'customer' :
  2955. $new_value = $v ? db('crm_customer')->where(['customer_id' => $v])->value('name') : '';
  2956. $old_value = $v ? db('crm_customer')->where(['customer_id' => $oldData[$k]])->value('name') : '';
  2957. break;
  2958. case 'category' :
  2959. $new_value = $v ? db('crm_product_category')->where(['category_id' => $v])->value('name') : '';
  2960. $old_value = $v ? db('crm_product_category')->where(['category_id' => $oldData[$k]])->value('name') : '';
  2961. break;
  2962. case 'business' :
  2963. $new_value = $v ? db('crm_business')->where(['business_id' => $v])->value('name') : '';
  2964. $old_value = $v ? db('crm_business')->where(['business_id' => $oldData[$k]])->value('name') : '';
  2965. break;
  2966. case 'visit' :
  2967. $new_value = $v ? db('crm_visit')->where(['visit_id' => $v])->value('number') : '';
  2968. $old_value = $v ? db('crm_visit')->where(['visit_id' => $oldData[$k]])->value('number') : '';
  2969. break;
  2970. case 'single_user' :
  2971. $new_value = $v ? db('admin_user')->where(['id' => $v])->value('realname') : '';
  2972. $old_value = $v ? db('admin_user')->where(['id' => $oldData['owner_user_id']])->value('realname') : '';
  2973. break;
  2974. case 'floatnumber' :
  2975. $new_value = $v ? number_format($v, 2) : '';
  2976. break;
  2977. }
  2978. if ($newFieldArr[$k]['field'] == 'check_status') {
  2979. $statusArr = ['0' => '待审核', '1' => '审核中', '2' => '审核通过', '3' => '已拒绝', '4' => '已撤回', '5' => '未提交'];
  2980. $new_value = $statusArr[$v];
  2981. $old_value = $statusArr[$oldData[$k]];
  2982. }
  2983. if ($old_value != $new_value) {
  2984. $message[] = '将 ' . "'" . $field_name . "'" . ' 由 ' . $old_value . ' 修改为 ' . $new_value;
  2985. }
  2986. }
  2987. }
  2988. if ($message) {
  2989. $data = [];
  2990. $data['user_id'] = $user_id;
  2991. $data['create_time'] = time();
  2992. $data['client_ip'] = request()->ip();
  2993. $data['action_name'] = $action_name;
  2994. $data['action_id'] = 1;
  2995. $data['target_name'] = $target_name;
  2996. $data['module'] = $types; //子模块 客户线索
  2997. $data['content'] = implode(',', $message);
  2998. db('admin_operation_log')->insert($data);
  2999. }
  3000. } elseif ($content) {
  3001. $data = [];
  3002. $data['user_id'] = $user_id;
  3003. $data['create_time'] = time();
  3004. $data['client_ip'] = request()->ip();
  3005. $data['action_name'] = $action_name;
  3006. $data['target_name'] = $target_name;
  3007. $data['action_id'] = 1;
  3008. $data['module'] = $types; //子模块 客户线索
  3009. $data['content'] = $content;
  3010. db('admin_operation_log')->insert($data);
  3011. }
  3012. }
  3013. if (!function_exists('getFieldGroupOrderData')) {
  3014. /**
  3015. * 对自定义字段进行分组排序
  3016. *
  3017. * @param array $data 自定义字段数据
  3018. * @return array
  3019. * @since 2021-04-27
  3020. * @author fanqi
  3021. */
  3022. function getFieldGroupOrderData($data)
  3023. {
  3024. $formPositionEmpty = [];
  3025. $formPositionExist = [];
  3026. $result = [];
  3027. // 处理数据,将有位置信息和无位置信息的数据分开存放。
  3028. foreach ($data as $key => $value) {
  3029. if (empty($value['form_position'])) {
  3030. $formPositionEmpty[] = $value;
  3031. continue;
  3032. }
  3033. $formPositionArray = explode(',', $value['form_position']);
  3034. $x = (int)$formPositionArray[0];
  3035. $y = (int)$formPositionArray[1];
  3036. if (!isset($value['xaxis'])) $value['xaxis'] = $x;
  3037. if (!isset($value['yaxis'])) $value['yaxis'] = $y;
  3038. if ($value['form_type'] == 'date_interval' && !is_array($value['default_value'])) {
  3039. $value['default_value'] = !empty($value['default_value']) ? explode(',', $value['default_value']) : [];
  3040. }
  3041. $formPositionExist[$x][$y] = $value;
  3042. }
  3043. // 排序
  3044. ksort($formPositionExist);
  3045. // 处理有位置信息的数据
  3046. foreach ($formPositionExist as $key => $value) {
  3047. foreach ($value as $k => $v) {
  3048. if (!empty($formPositionExist[$key][$k])) $result[$key][$k] = $v;
  3049. }
  3050. $result[$key] = array_values($result[$key]);
  3051. }
  3052. // 将无位置信息的数据放置尾端
  3053. foreach ($formPositionEmpty as $key => $value) {
  3054. $result[] = [$value];
  3055. }
  3056. return array_values($result);
  3057. }
  3058. }
  3059. if (!function_exists('getPrimaryKeyName')) {
  3060. /**
  3061. * 获取主键
  3062. *
  3063. * @param string $types 栏目类型
  3064. * @return string
  3065. * @since 2021-05-18
  3066. * @author fanqi
  3067. */
  3068. function getPrimaryKeyName($types)
  3069. {
  3070. $primaryKey = '';
  3071. if ($types == 'crm_leads') $primaryKey = 'leads_id';
  3072. if ($types == 'crm_customer') $primaryKey = 'customer_id';
  3073. if ($types == 'crm_contacts') $primaryKey = 'contacts_id';
  3074. if ($types == 'crm_business') $primaryKey = 'business_id';
  3075. if ($types == 'crm_contract') $primaryKey = 'contract_id';
  3076. if ($types == 'crm_receivables') $primaryKey = 'receivables_id';
  3077. if ($types == 'crm_receivables_plan') $primaryKey = 'plan_id';
  3078. if ($types == 'crm_visit') $primaryKey = 'visit_id';
  3079. if ($types == 'crm_product') $primaryKey = 'product_id';
  3080. if ($types == 'crm_invoice') $primaryKey = 'invoice_id';
  3081. if ($types == 'oa_examine') $primaryKey = 'examine_id';
  3082. if ($types == 'jxc_product') $primaryKey = 'product_id';
  3083. if ($types == 'jxc_supplier') $primaryKey = 'supplier_id';
  3084. if ($types == 'jxc_purchase') $primaryKey = 'purchase_id';
  3085. if ($types == 'jxc_retreat') $primaryKey = 'retreat_id';
  3086. if ($types == 'jxc_sale') $primaryKey = 'sale_id';
  3087. if ($types == 'jxc_salereturn') $primaryKey = 'salereturn_id';
  3088. if ($types == 'jxc_receipt') $primaryKey = 'receipt_id';
  3089. if ($types == 'jxc_outbound') $primaryKey = 'outbound_id';
  3090. if ($types == 'jxc_payment') $primaryKey = 'payment_note_id';
  3091. if ($types == 'jxc_collection') $primaryKey = 'collection_note_id';
  3092. if ($types == 'jxc_inventory') $primaryKey = 'inventory_id';
  3093. if ($types == 'jxc_allocation') $primaryKey = 'allocation_id';
  3094. return $primaryKey;
  3095. }
  3096. }
  3097. function advancedQueryFormatForTeam($requestMap, $db, $db_id)
  3098. {
  3099. // 处理查询条件
  3100. foreach ($requestMap['team_id']['value'] as $v) {
  3101. if ($requestMap['team_id']['condition'] == 'contains') {
  3102. $date = function ($query) use ($v) {
  3103. $query->where('FIND_IN_SET("' . $v . '", ro_user_id)')
  3104. ->whereOr('FIND_IN_SET("' . $v . '", rw_user_id)');
  3105. };
  3106. } elseif ($requestMap['team_id']['condition'] == 'notContains') {
  3107. $date = function ($query) use ($v) {
  3108. $query->where('FIND_IN_SET("' . $v . '", ro_user_id)')
  3109. ->where('FIND_IN_SET("' . $v . '", rw_user_id)');
  3110. };
  3111. } elseif ($requestMap['team_id']['condition'] == 'isNull') {
  3112. $date = function ($query) {
  3113. $query->where('ro_user_id', ['eq', ''])
  3114. ->whereOr('rw_user_id', 'null');
  3115. };
  3116. } elseif ($requestMap['team_id']['condition'] == 'isNotNull') {
  3117. $date = function ($query) {
  3118. $query->where('ro_user_id', ['neq', ''])
  3119. ->where('rw_user_id', ['not null']);
  3120. };
  3121. }
  3122. $part[] = db($db)->where($date)->column($db_id);
  3123. }
  3124. $result = [];
  3125. array_walk_recursive($part, function ($value) use (&$result) {
  3126. array_push($result, $value);
  3127. });
  3128. $result = array_unique($result);
  3129. $partMap['customer.customer_id'] = ['in', trim(arrayToString($result), ',')];
  3130. return $partMap ?: [];
  3131. }