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