1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353
  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 响应数据
  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. if ($v['form_type'] == 'user') {
  161. if ($v['condition'] == 'is') $v['condition'] = 'contains';
  162. }
  163. if ($types == 'contract') {
  164. switch ($k) {
  165. case 'business_id' :
  166. $k = 'name';
  167. $c = 'business.';
  168. break;
  169. case 'contacts_id' :
  170. $contactsIds = [];
  171. foreach ($v['value'] AS $kk => $vv) {
  172. $contactsIdArray = db('crm_contacts')->whereLike('name', '%' . $vv . '%')->column('contacts_id');
  173. foreach ($contactsIdArray AS $kkk => $vvv) {
  174. $contactsIds[] = $vvv;
  175. }
  176. }
  177. $v['value'] = array_unique($contactsIds);
  178. break;
  179. }
  180. }
  181. if ($types == 'receivables' && $v['name'] == '合同编号') {
  182. $k = 'num';
  183. $c = 'contract.';
  184. }
  185. if ($types == 'receivables' && $k == 'plan_id') {
  186. $planIds = [];
  187. foreach ($v['value'] AS $kk => $vv) {
  188. $planIdArray = db('crm_receivables_plan')->whereLike('num', '%' . $vv . '%')->column('plan_id');
  189. foreach ($planIdArray AS $kkk => $vvv) {
  190. $planIds[] = $vvv;
  191. }
  192. }
  193. $v['value'] = array_unique($planIds);
  194. }
  195. if ($types == 'invoice' && $v['type'] == 'invoice_status') {
  196. foreach ($v['value'] AS $kk => $vv) {
  197. if ($vv == '已开票') $v['value'][$kk] = 1;
  198. if ($vv == '未开票') $v['value'][$kk] = 0;
  199. }
  200. }
  201. if ($types == 'visit' && $v['type'] == 'contract_name') {
  202. $k = 'num';
  203. $c = 'contract.';
  204. }
  205. if ($k == 'check_status' && is_array($v) && in_array($v['value'][0], $checkStatusList)) {
  206. $v['value'] = $checkStatusArray[$v['value'][0]] ?: '0';
  207. }
  208. if (is_array($v)) {
  209. if ($v['state']) {
  210. $address_where[] = '%' . $v['state'] . '%';
  211. if ($v['city']) {
  212. $address_where[] = '%' . $v['city'] . '%';
  213. if ($v['area']) {
  214. $address_where[] = '%' . $v['area'] . '%';
  215. }
  216. }
  217. if ($v['condition'] == 'not_contain') {
  218. $where[$c . $k] = ['notlike', $address_where, 'OR'];
  219. } else {
  220. $where[$c . $k] = ['like', $address_where, 'AND'];
  221. }
  222. } elseif (!empty($v['value']['state'])) {
  223. $addressWhere[] = '%' . $v['value']['state'] . '%';
  224. if (!empty($v['value']['city'])) $addressWhere[] = '%' . $v['value']['city'] . '%';
  225. if (!empty($v['value']['area'])) $addressWhere[] = '%' . $v['value']['area'] . '%';
  226. if ($v['condition'] == 'is') {
  227. $where[$c . $k] = ['like', $addressWhere, 'AND'];
  228. } else {
  229. $where[$c . $k] = ['notlike', $addressWhere, 'OR'];
  230. }
  231. } elseif (!empty($v['start']) || !empty($v['end'])) {
  232. if ($v['start'] && $v['end']) {
  233. $where[$c . $k] = ['between', [$v['start'], $v['end']]];
  234. } elseif ($v['start']) {
  235. $where[$c . $k] = ['egt', $v['start']];
  236. } else {
  237. $where[$c . $k] = ['elt', $v['end']];
  238. }
  239. } elseif (!empty($v['start_date']) || !empty($v['end_date'])) {
  240. if ($v['start_date'] && $v['end_date']) {
  241. $where[$c . $k] = ['between', [$v['start_date'], $v['end_date']]];
  242. } elseif ($v['start_date']) {
  243. $where[$c . $k] = ['egt', $v['start_date']];
  244. } else {
  245. $where[$c . $k] = ['elt', $v['end_date']];
  246. }
  247. } elseif (!empty($v['value']) || $v['value'] === '0') {
  248. if (in_array($k, $check_field_arr)) {
  249. $where[$c . $k] = field($v['value'], 'contains');
  250. } else {
  251. $where[$c . $k] = field($v['value'], $v['condition'], $k);
  252. }
  253. } elseif (in_array($v['condition'], ['isNull', 'isNotNull', 'in'])) {
  254. $where[$c . $k] = field($v['value'], $v['condition']);
  255. } else {
  256. $where[$c . $k] = $v;
  257. }
  258. } elseif (!empty($v)) {
  259. $where[$c . $k] = field($v);
  260. } else {
  261. $where[$c . $k] = $v;
  262. }
  263. }
  264. }
  265. # 商机阶段为赢单、输单、无效的值保存在is_end中,将status_id改为is_end;
  266. if (!empty($where['business.status_id']) && in_array($where['business.status_id'][1], [1,2,3])) {
  267. $where['business.is_end'] = $where['business.status_id'];
  268. unset($where['business.status_id']);
  269. }
  270. return $where ?: [];
  271. }
  272. /**
  273. * 根据搜索生成where条件
  274. *
  275. * @param string $search 搜索内容
  276. * @param $condition 搜索条件
  277. * @param $k 搜索字段
  278. * @return array|Closure|string[]
  279. */
  280. function field($search, $condition = '', $k = '')
  281. {
  282. switch (trim($condition)) {
  283. case "is" :
  284. $where = ['in', $search];
  285. break;
  286. case "isNot" :
  287. $where = ['notin', $search];
  288. break;
  289. case "contains" :
  290. $containsWhere = [];
  291. foreach ((array)$search AS $key1 => $value1) $containsWhere[] = '%' . $value1 . '%';
  292. $where = ['like', $containsWhere, 'OR'];
  293. break;
  294. case "notContains" :
  295. $containsWhere = [];
  296. foreach ((array)$search AS $key1 => $value1) $containsWhere[] = '%' . $value1 . '%';
  297. $where = ['notlike', $containsWhere, 'AND'];
  298. break;
  299. case "startWith" :
  300. $startWithWhere = [];
  301. foreach ((array)$search AS $key1 => $value1) $startWithWhere[] = $value1 . '%';
  302. $where = ['like', $startWithWhere, 'OR'];
  303. break;
  304. case "endWith" :
  305. $endWithWhere = [];
  306. foreach ((array)$search AS $key1 => $value1) $endWithWhere[] = '%' . $value1;
  307. $where = ['like', $endWithWhere, 'OR'];
  308. break;
  309. case "isNull" :
  310. $where = ['eq', ''];
  311. break;
  312. case "isNotNull" :
  313. $where = ['neq', ''];
  314. break;
  315. case "eq" :
  316. $where = function ($query) use ($search, $k) {
  317. foreach ((array)$search AS $key1 => $value1) {
  318. $query->whereOr($k, $value1);
  319. }
  320. };
  321. break;
  322. case "neq" :
  323. $where = function ($query) use ($search, $k) {
  324. foreach ((array)$search AS $key1 => $value1) {
  325. $query->whereOr($k, '<>', $value1);
  326. }
  327. };
  328. break;
  329. case "gt" :
  330. $where = function ($query) use ($search, $k) {
  331. foreach ((array)$search AS $key1 => $value1) {
  332. $query->whereOr($k, '>', $value1);
  333. }
  334. };
  335. break;
  336. case "egt" :
  337. $where = function ($query) use ($search, $k) {
  338. foreach ((array)$search AS $key1 => $value1) {
  339. $query->whereOr($k, '>=', $value1);
  340. }
  341. };
  342. break;
  343. case "lt" :
  344. $where = function ($query) use ($search, $k) {
  345. foreach ((array)$search AS $key1 => $value1) {
  346. $query->whereOr($k, '<', $value1);
  347. }
  348. };
  349. break;
  350. case "elt" :
  351. $where = function ($query) use ($search, $k) {
  352. foreach ((array)$search AS $key1 => $value1) {
  353. $query->whereOr($k, '<=', $value1);
  354. }
  355. };
  356. break;
  357. case "in" :
  358. $where = ['in', $search];
  359. break;
  360. default :
  361. $where = ['eq', $search];
  362. break;
  363. }
  364. return $where;
  365. }
  366. /**
  367. * 将单个搜索转换为高级搜索格式
  368. * @param string $value 搜索内容
  369. * @param $condition 搜索条件
  370. * @return array
  371. * @author Michael_xu
  372. */
  373. function field_arr($value, $condition = '')
  374. {
  375. if (is_array($value)) {
  376. } else {
  377. $condition = $condition ?: 'eq';
  378. $where_arr = ['value' => $value, 'condition' => $condition];
  379. }
  380. return $where_arr;
  381. }
  382. /**
  383. * 记录操作日志
  384. * @param $id array 操作对象id数组
  385. * @return
  386. * @author Michael_xu
  387. */
  388. function actionLog($id, $join_user_ids = '', $structure_ids = '', $content = '')
  389. {
  390. if (!is_array($id)) {
  391. $idArr[] = $id;
  392. } else {
  393. $idArr = $id;
  394. }
  395. $header = Request::instance()->header();
  396. $authKey = $header['authkey'];
  397. $cache = cache('Auth_'.$authKey);
  398. if (!$cache) {
  399. return false;
  400. }
  401. $userInfo = $cache['userInfo'];
  402. $category = $userInfo['id'] == 1 ? '管理员' : '员工';
  403. $request = request();
  404. $m = strtolower($request->module());
  405. $c = strtolower($request->controller());
  406. $a = strtolower($request->action());
  407. $res_action = true;
  408. foreach ($idArr as $v) {
  409. $data = [];
  410. $data['user_id'] = $userInfo['id'];
  411. $data['module_name'] = $module_name = $m;
  412. $data['controller_name'] = $controller_name = $c;
  413. $data['action_name'] = $action_name = $a;
  414. $data['action_id'] = $v;
  415. $data['create_time'] = time();
  416. $data['client_ip'] = request()->ip();
  417. $data['content'] = $content ? : lang('ACTIONLOG', [$category, $userInfo['realname'], date('Y-m-d H:i:s'), lang($action_name), $v, lang($controller_name)]);
  418. $data['join_user_ids'] = $join_user_ids ? : ''; //抄送人
  419. $data['structure_ids'] = $structure_ids ? : ''; //抄送部门
  420. if ($action_name == 'delete' || $action_name == 'commentdel') {
  421. $data['action_delete'] = 1;
  422. }
  423. if (!db('admin_action_log')->insert($data)) {
  424. $res_action = false;
  425. }
  426. # 数据操作日志
  427. db('admin_operation_log')->insert([
  428. 'user_id' => $userInfo['id'],
  429. 'client_ip' => request()->ip(),
  430. 'module' => $m . '_' . $c,
  431. 'action_id' => $v,
  432. 'content' => $content,
  433. 'create_time' => time()
  434. ]);
  435. }
  436. if ($res_action) {
  437. return true;
  438. } else {
  439. return false;
  440. }
  441. }
  442. /**
  443. * 判断操作权限
  444. * @param
  445. * @return
  446. * @author Michael_xu
  447. */
  448. function checkPerByAction($m, $c, $a)
  449. {
  450. /*获取头部信息*/
  451. $header = Request::instance()->header();
  452. $authKey = $header['authkey'];
  453. $cache = cache('Auth_' . $authKey);
  454. if (!$cache) {
  455. return false;
  456. }
  457. $userInfo = $cache['userInfo'];
  458. $adminTypes = adminGroupTypes($userInfo['id']);
  459. if (in_array(1, $adminTypes)) {
  460. return true;
  461. }
  462. if (empty($m) && empty($c) && empty($a)) {
  463. $request = Request::instance();
  464. $m = strtolower($request->module());
  465. $c = strtolower($request->controller());
  466. $a = strtolower($request->action());
  467. }
  468. $authAdapter = new AuthAdapter($authKey);
  469. $ruleName = $m . '-' . $c . '-' . $a;
  470. if (!$authAdapter->checkIntime($ruleName, $userInfo['id'])) {
  471. return false;
  472. }
  473. return true;
  474. }
  475. /**
  476. * 给树状菜单添加level并去掉没有子菜单的菜单项
  477. * @param array $data [description]
  478. * @param integer $root [description]
  479. * @param string $child [description]
  480. * @param string $level [description]
  481. */
  482. function memuLevelClear($data, $root = 1, $child = 'children', $level = 'level')
  483. {
  484. if (is_array($data)) {
  485. foreach ($data as $key => $val) {
  486. // $data[$key]['selected'] = false;
  487. $data[$key]['level'] = $root;
  488. if (!empty($val[$child]) && is_array($val[$child])) {
  489. $data[$key][$child] = memuLevelClear($val[$child], $root + 1);
  490. } else if ($root < 3 && $data[$key]['menu_type'] == 1) {
  491. unset($data[$key]);
  492. }
  493. if (empty($data[$key][$child]) && ($data[$key]['level'] == 1) && ($data[$key]['menu_type'] == 1)) {
  494. unset($data[$key]);
  495. }
  496. }
  497. return array_values($data);
  498. }
  499. return array();
  500. }
  501. /**
  502. * [rulesDeal 给树状规则表处理成 module-controller-action ]
  503. * @AuthorHTL
  504. * @DateTime
  505. * @param [array] $data [树状规则数组]
  506. * @return [array] [返回数组]
  507. */
  508. function rulesDeal($data)
  509. {
  510. if (is_array($data)) {
  511. $ret = [];
  512. foreach ($data as $k1 => $v1) {
  513. $str1 = $v1['name'];
  514. if (is_array($v1['children'])) {
  515. foreach ($v1['children'] as $k2 => $v2) {
  516. $str2 = $str1 . '-' . $v2['name'];
  517. if (is_array($v2['children'])) {
  518. foreach ($v2['children'] as $k3 => $v3) {
  519. $str3 = $str2 . '-' . $v3['name'];
  520. $ret[] = $str3;
  521. }
  522. } else {
  523. $ret[] = $str2;
  524. }
  525. }
  526. } else {
  527. $ret[] = $str1;
  528. }
  529. }
  530. return $ret;
  531. }
  532. return [];
  533. }
  534. /**
  535. * 获取下属userId
  536. * @param $self == true 包含自己
  537. * @param $type == 0 下属userid
  538. * @param $type == 1 全部userid
  539. * @param $user_id 需要查询的user_id
  540. * @author Michael_xu
  541. */
  542. function getSubUserId($self = true, $type = 0, $user_id = '')
  543. {
  544. $request = Request::instance();
  545. $header = $request->header();
  546. $authKey = $header['authkey'];
  547. $cache = cache('Auth_' . $authKey);
  548. if (!$user_id) {
  549. if (!$cache) {
  550. return false;
  551. }
  552. $userInfo = $cache['userInfo'];
  553. $user_id = $userInfo['id'];
  554. $adminTypes = adminGroupTypes($user_id);
  555. if (in_array(1, $adminTypes)) {
  556. $type = 1;
  557. }
  558. }
  559. $belowIds = [];
  560. if (empty($type)) {
  561. if ($user_id) {
  562. $belowIds = getSubUser($user_id);
  563. }
  564. } else {
  565. $belowIds = getSubUser(0);
  566. }
  567. if ($self == true) {
  568. $belowIds[] = $user_id;
  569. } else {
  570. $belowIds = $belowIds ? array_diff($belowIds, array($user_id)) : [];
  571. }
  572. return array_unique($belowIds);
  573. }
  574. /**
  575. * 获取下属userId
  576. * @author Michael_xu
  577. */
  578. function getSubUser($userId, $queried = [], $allUserList = [])
  579. {
  580. if (empty($allUserList)) {
  581. $allUserList = db('admin_user')->field('id,parent_id')->select();
  582. }
  583. foreach ($allUserList as $k=>$v) {
  584. if ($v['parent_id'] == $userId) {
  585. $sub_user[] = $v['id'];
  586. }
  587. }
  588. if ($sub_user) {
  589. foreach ($sub_user as $v) {
  590. if (in_array($v, $queried)) {
  591. continue;
  592. }
  593. $queried[] = $v;
  594. $son_user = [];
  595. $son_user = getSubUser($v, $queried, $allUserList);
  596. if (!empty($son_user)) {
  597. $sub_user = array_merge($sub_user, $son_user);
  598. }
  599. }
  600. }
  601. return $sub_user;
  602. }
  603. /**
  604. * 阿里大于短信发送
  605. * @param unknown $appkey
  606. * @param unknown $secret
  607. * @param unknown $signName 短信签名
  608. * @param unknown $smsParam
  609. * @param unknown $templateCode 短信模板
  610. * @param unknown $send_mobile 接收手机号
  611. * @param unknown $code 短信验证码
  612. * @param unknown $template_code 模板参数
  613. */
  614. function aliSmsSend($send_mobile, $code, $signName, $templateCode)
  615. {
  616. $appkey = '';
  617. $secret = '';
  618. import('alimsg.api.Sms', EXTEND_PATH);
  619. header('Content-Type: text/plain; charset=utf-8');
  620. $sms = new Sms($appkey, $secret);
  621. $template_code = array("code" => $code);
  622. $response = $sms->sendSms($signName, $templateCode, $send_mobile, $template_code);
  623. $data = object_to_array($response);
  624. if ($data['Message'] == 'OK' && $data['Code'] == "OK") {
  625. return true;
  626. } else {
  627. return false;
  628. }
  629. }
  630. /**
  631. * 发送邮件
  632. * @param unknown $toemail
  633. * @param unknown $title
  634. * @param unknown $content
  635. * @return boolean
  636. */
  637. function emailSend($email_host, $email_id, $email_pass, $email_addr, $toemail, $title, $content)
  638. {
  639. $result = false;
  640. try {
  641. $mail = new Email();
  642. $mail->setServer($email_host, $email_id, $email_pass);
  643. $mail->setFrom($email_addr);
  644. $mail->setReceiver($toemail);
  645. $mail->setMailInfo($title, $content);
  646. $result = $mail->sendMail();
  647. } catch (\Exception $e) {
  648. $result = false;
  649. }
  650. return $result;
  651. }
  652. /**
  653. * 发送站内信
  654. * @param $user_id 接收人user_id
  655. * @param $action_id 操作id
  656. * @param $sysMessage 1为系统消息
  657. * @param $content 消息内容
  658. * @return
  659. * @author Michael_xu
  660. */
  661. function sendMessage($user_id, $content, $action_id, $sysMessage = 0)
  662. {
  663. $content = trim($content);
  664. if (!$user_id) return false;
  665. if (!$content) return false;
  666. if (!is_array($user_id)) {
  667. $user_ids[] = $user_id;
  668. } else {
  669. $user_ids = $user_id;
  670. }
  671. $user_ids = array_unique(array_filter($user_ids));
  672. $request = request();
  673. $m = strtolower($request->module());
  674. $c = strtolower($request->controller());
  675. $a = strtolower($request->action());
  676. $userInfo = [];
  677. if ($sysMessage == 0) {
  678. $header = $request->header();
  679. $authkey = $header['authkey'];
  680. $cache = cache('Auth_' . $authkey);
  681. if (!$cache) {
  682. return false;
  683. }
  684. $userInfo = $cache['userInfo'];
  685. }
  686. foreach ($user_ids as $v) {
  687. $data = [];
  688. $data['content'] = $content;
  689. $data['from_user_id'] = $userInfo['id'] ? : 0;
  690. $data['to_user_id'] = $v;
  691. $data['read_time'] = 0;
  692. $data['send_time'] = time();
  693. $data['module_name'] = $m;
  694. $data['controller_name'] = $c;
  695. $data['action_name'] = $a;
  696. $data['action_id'] = $action_id;
  697. db('admin_message')->insert($data);
  698. }
  699. return true;
  700. }
  701. /**
  702. * 格式化字节大小
  703. * @param number $size 字节数
  704. * @param string $delimiter 数字和单位分隔符
  705. * @return string 格式化后的带单位的大小
  706. * @author
  707. */
  708. function format_bytes($size, $delimiter = '')
  709. {
  710. $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
  711. for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
  712. return round($size, 2) . $delimiter . $units[$i];
  713. }
  714. /**
  715. * 数据修改日志
  716. * @param $types 类型
  717. * @param $action_id 操作ID
  718. * @param $newData 新数据
  719. * @param $newData 新数据
  720. * @return
  721. * @author Michael_xu
  722. */
  723. function updateActionLog($user_id, $types, $action_id, $oldData = [], $newData = [], $content = '')
  724. {
  725. if (is_array($oldData) && is_array($newData) && $user_id) {
  726. $differentData = array_diff_assoc($newData, $oldData);
  727. $fieldModel = new FieldModel();
  728. $userModel = new UserModel();
  729. $structureModel = new \app\admin\model\Structure();
  730. $field_arr = $fieldModel->getField(['types' => $types, 'unFormType' => ['file', 'form']]); //获取字段属性
  731. $newFieldArr = array();
  732. foreach ($field_arr as $k => $v) {
  733. $newFieldArr[$v['field']] = $v;
  734. }
  735. $unField = ['update_time','create_time']; //定义过滤字段
  736. $message = [];
  737. $un_form_type = ['file', 'form'];
  738. foreach ($differentData as $k => $v) {
  739. if ($newFieldArr[$k] && !in_array($newFieldArr[$k]['form_type'], $un_form_type)) {
  740. $field_name = '';
  741. $field_name = $newFieldArr[$k]['name'];
  742. $new_value = $v;
  743. $old_value = $oldData[$k] ?: '空';
  744. if ($newFieldArr[$k]['form_type'] == 'datetime') {
  745. $new_value = $v ? date('Y-m-d', $v) : '';
  746. $old_value = date('Y-m-d', $oldData[$k]);
  747. if (empty($v) && empty($oldData[$k])) continue;
  748. } elseif ($newFieldArr[$k]['form_type'] == 'user') {
  749. $new_value = $v ? implode(',', $userModel->getUserNameByArr(stringToArray($v))) : '';
  750. $old_value = $v ? implode(',', $userModel->getUserNameByArr(stringToArray($oldData[$k]))) : '';
  751. } elseif ($newFieldArr[$k]['form_type'] == 'structure') {
  752. $new_value = $v ? implode(',', $structureModel->getStructureNameByArr(stringToArray($v))) : '';
  753. $old_value = $v ? implode(',', $structureModel->getStructureNameByArr(stringToArray($oldData[$k]))) : '';
  754. } elseif ($newFieldArr[$k]['form_type'] == 'business_status') {
  755. $new_value = $v ? db('crm_business_status')->where(['status_id' => $v])->value('name') : '';
  756. $old_value = $v ? db('crm_business_status')->where(['status_id' => $oldData[$k]])->value('name') : '';
  757. } elseif ($newFieldArr[$k]['form_type'] == 'business_type') {
  758. $new_value = $v ? db('crm_business_type')->where(['type_id' => $v])->value('name') : '';
  759. $old_value = $v ? db('crm_business_type')->where(['type_id' => $oldData[$k]])->value('name') : '';
  760. } elseif ($newFieldArr[$k]['form_type'] == 'customer') {
  761. $new_value = $v ? db('crm_customer')->where(['customer_id' => $v])->value('name') : '';
  762. $old_value = $v ? db('crm_customer')->where(['customer_id' => $oldData[$k]])->value('name') : '';
  763. } elseif ($newFieldArr[$k]['form_type'] == 'category') {
  764. $new_value = $v ? db('crm_product_category')->where(['category_id' => $v])->value('name') : '';
  765. $old_value = $v ? db('crm_product_category')->where(['category_id' => $oldData[$k]])->value('name') : '';
  766. } elseif ($newFieldArr[$k]['form_type'] == 'business') {
  767. $new_value = $v ? db('crm_business')->where(['business_id' => $v])->value('name') : '';
  768. $old_value = $v ? db('crm_business')->where(['business_id' => $oldData[$k]])->value('name') : '';
  769. } elseif ($newFieldArr[$k]['field'] == 'check_status') {
  770. $statusArr = ['0' => '待审核', '1' => '审核中', '2' => '审核通过', '3' => '已拒绝', '4' => '已撤回', '5' => '未提交'];
  771. $new_value = $statusArr[$v];
  772. $old_value = $statusArr[$oldData[$k]];
  773. } elseif ($newFieldArr[$k]['form_type'] == 'visit') {
  774. $new_value = $v ? db('crm_visit')->where(['visit_id' => $v])->value('number') : '';
  775. $old_value = $v ? db('crm_visit')->where(['visit_id' => $oldData[$k]])->value('number') : '';
  776. }
  777. $message[] = '将 ' . "'" . $field_name . "'" . ' 由 ' . $old_value . ' 修改为 ' . $new_value;
  778. }
  779. }
  780. if ($message) {
  781. $data = [];
  782. $data['user_id'] = $user_id;
  783. $data['create_time'] = time();
  784. $data['types'] = $types;
  785. $data['action_id'] = $action_id;
  786. $data['content'] = implode('.|.', $message);
  787. db('admin_action_record')->insert($data);
  788. # 数据操作日志
  789. db('admin_operation_log')->insert([
  790. 'user_id' => $user_id,
  791. 'client_ip' => request()->ip(),
  792. 'module' => $types,
  793. 'action_id' => $action_id,
  794. 'content' => implode('.|.', $message),
  795. 'create_time' => time()
  796. ]);
  797. }
  798. } elseif ($content) {
  799. $data = [];
  800. $data['user_id'] = $user_id;
  801. $data['create_time'] = time();
  802. $data['types'] = $types;
  803. $data['action_id'] = $action_id;
  804. $data['content'] = $content;
  805. db('admin_action_record')->insert($data);
  806. # 数据操作日志
  807. db('admin_operation_log')->insert([
  808. 'user_id' => $user_id,
  809. 'client_ip' => request()->ip(),
  810. 'module' => $types,
  811. 'action_id' => $action_id,
  812. 'content' => $content,
  813. 'create_time' => time()
  814. ]);
  815. }
  816. }
  817. /**
  818. * 截取字符串
  819. * @param $start 开始截取位置
  820. * @param $length 截取长度
  821. * @return
  822. * @author Michael_xu
  823. */
  824. function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true)
  825. {
  826. if (function_exists("mb_substr")) {
  827. $slice = mb_substr($str, $start, $length, $charset);
  828. } elseif (function_exists('iconv_substr')) {
  829. $slice = iconv_substr($str, $start, $length, $charset);
  830. if (false === $slice) {
  831. $slice = '';
  832. }
  833. } else {
  834. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  835. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  836. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  837. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  838. preg_match_all($re[$charset], $str, $match);
  839. $slice = join("", array_slice($match[0], $start, $length));
  840. }
  841. if (utf8_strlen($str) < $length) $suffix = false;
  842. return $suffix ? $slice . '...' : $slice;
  843. }
  844. function utf8_strlen($string = null)
  845. {
  846. preg_match_all("/./us", $string, $match);
  847. return count($match[0]);
  848. }
  849. /**
  850. * 合法性验证
  851. * @param client_sign 签名参数值,使用相同规则对提交参数进行加密验证
  852. * @return
  853. * @author Michael_xu
  854. */
  855. function checkVerify($saftCode = '5kcrm@')
  856. {
  857. $parmList = Request::instance()->post();
  858. $header = $request->header();
  859. $parmList['sessionId'] = $header['sessionId'];
  860. $authkey = $header['authKey'];
  861. $clientSign = $parmList['client_sign'];
  862. if ($clientSign) {
  863. unset($parmList['client_sign']);
  864. if (count($parmList) > 0) {
  865. // 对要签名参数按照签名格式组合
  866. foreach ($parmList as $key => $value) {
  867. if (isset($_POST[$key])) {
  868. $parame[$key] = $key . '=' . trim($_POST[$key]);
  869. } else {
  870. return false;
  871. }
  872. }
  873. ksort($parame); //参数排序
  874. $returnValue = implode("&", $parame); //拼接字符串
  875. if ($returnValue) {
  876. //base64加密
  877. $signCalc = base64_encode(hash_hmac("sha1", $returnValue, $saftCode . $authkey, $raw_output = false));
  878. // 检查参数签名是否一致
  879. if (trim($clientSign) != trim($signCalc)) {
  880. return false;
  881. } else {
  882. return true;
  883. }
  884. } else {
  885. return false;
  886. }
  887. } else {
  888. return false;
  889. }
  890. } else {
  891. //签名认证错误
  892. return false;
  893. }
  894. }
  895. /**
  896. * 数组转换字符串(以逗号隔开)
  897. * @param
  898. * @return
  899. * @author Michael_xu
  900. */
  901. function arrayToString($array)
  902. {
  903. if (!is_array($array)) {
  904. $data_arr[] = $array;
  905. } else {
  906. $data_arr = $array;
  907. }
  908. $data_arr = array_filter($data_arr); //数组去空
  909. $data_arr = array_unique($data_arr); //数组去重
  910. $data_arr = array_merge($data_arr);
  911. $string = $data_arr ? ',' . implode(',', $data_arr) . ',' : '';
  912. return $string ?: '';
  913. }
  914. /**
  915. * 字符串转换数组(以逗号隔开)
  916. * @param
  917. * @return
  918. * @author Michael_xu
  919. */
  920. function stringToArray($string)
  921. {
  922. if (is_array($string)) {
  923. $data_arr = array_unique(array_filter($string));
  924. } else {
  925. $data_arr = $string ? array_unique(array_filter(explode(',', $string))) : [];
  926. }
  927. $data_arr = $data_arr ? array_merge($data_arr) : [];
  928. return $data_arr ?: [];
  929. }
  930. /**
  931. * 根据时间戳获取星期几
  932. * @param $time 要转换的时间戳
  933. */
  934. function getTimeWeek($time, $i = 0)
  935. {
  936. $weekarray = array("日", "一", "二", "三", "四", "五", "六");
  937. $oneD = 24 * 60 * 60;
  938. return "星期" . $weekarray[date("w", $time + $oneD * $i)];
  939. }
  940. /**
  941. * 二维数组排序(选择)
  942. * @param $select 要进行排序的select结果集
  943. * @param $field 排序的字段
  944. * @param $order 排序方式1降序2升序
  945. */
  946. function sort_select($select = array(), $field, $order = 1)
  947. {
  948. $count = count($select);
  949. if ($order == 1) {
  950. for ($i = 0; $i < $count; $i++) {
  951. $k = $i;
  952. for ($j = $i; $j < $count; $j++) {
  953. if ($select[$k][$field] < $select[$j][$field]) {
  954. $k = $j;
  955. }
  956. }
  957. $temp = $select[$i];
  958. $select[$i] = $select[$k];
  959. $select[$k] = $temp;
  960. }
  961. return $select;
  962. } else {
  963. for ($i = 0; $i < $count; $i++) {
  964. $k = $i;
  965. for ($j = $i; $j < $count; $j++) {
  966. if ($select[$k][$field] > $select[$j][$field]) {
  967. $k = $j;
  968. }
  969. }
  970. $temp = $select[$i];
  971. $select[$i] = $select[$k];
  972. $select[$k] = $temp;
  973. }
  974. return $select;
  975. }
  976. }
  977. /**
  978. * 将秒数转换为时间 (年、天、小时、分、秒)
  979. * @param
  980. */
  981. function getTimeBySec($time)
  982. {
  983. if (is_numeric($time)) {
  984. $value = array(
  985. "years" => 0, "days" => 0, "hours" => 0,
  986. "minutes" => 0, "seconds" => 0,
  987. );
  988. if ($time >= 31556926) {
  989. $value["years"] = floor($time / 31556926);
  990. $time = ($time % 31556926);
  991. $t .= $value["years"] . "年";
  992. }
  993. if ($time >= 86400) {
  994. $value["days"] = floor($time / 86400);
  995. $time = ($time % 86400);
  996. $t .= $value["days"] . "天";
  997. }
  998. if ($time >= 3600) {
  999. $value["hours"] = floor($time / 3600);
  1000. $time = ($time % 3600);
  1001. $t .= $value["hours"] . "小时";
  1002. }
  1003. if ($time >= 60) {
  1004. $value["minutes"] = floor($time / 60);
  1005. $time = ($time % 60);
  1006. $t .= $value["minutes"] . "分钟";
  1007. }
  1008. if ($time < 60) {
  1009. $value["seconds"] = floor($time);
  1010. $t .= $value["seconds"] . "秒";
  1011. }
  1012. return $t;
  1013. } else {
  1014. return (bool)FALSE;
  1015. }
  1016. }
  1017. /*
  1018. *根据年月计算有几天
  1019. */
  1020. function getmonthByYM($param)
  1021. {
  1022. $month = $param['month'] ? $param['month'] : date('m', time());
  1023. $year = $param['year'] ? $param['year'] : date('Y', time());
  1024. if (in_array($month, array('1', '3', '5', '7', '8', '01', '03', '05', '07', '08', '10', '12'))) {
  1025. $days = '31';
  1026. } elseif ($month == 2) {
  1027. if ($year % 400 == 0 || ($year % 4 == 0 && $year % 100 !== 0)) {
  1028. //判断是否是闰年
  1029. $days = '29';
  1030. } else {
  1031. $days = '28';
  1032. }
  1033. } else {
  1034. $days = '30';
  1035. }
  1036. return $days;
  1037. }
  1038. /**
  1039. * 根据时间戳计算当月天数
  1040. * @param
  1041. */
  1042. function getmonthdays($time)
  1043. {
  1044. $month = date('m', $time);
  1045. $year = date('Y', $time);
  1046. if (in_array($month, array('1', '3', '5', '7', '8', '01', '03', '05', '07', '08', '10', '12'))) {
  1047. $days = '31';
  1048. } elseif ($month == 2) {
  1049. if ($year % 400 == 0 || ($year % 4 == 0 && $year % 100 !== 0)) {
  1050. //判断是否是闰年
  1051. $days = '29';
  1052. } else {
  1053. $days = '28';
  1054. }
  1055. } else {
  1056. $days = '30';
  1057. }
  1058. return $days;
  1059. }
  1060. /**
  1061. * 生成从开始时间到结束时间的日期数组
  1062. * @param type,默认时间戳格式
  1063. * @param type = 1 时,date格式
  1064. * @param type = 2 时,获取每日开始、结束时间
  1065. */
  1066. function dateList($start, $end, $type = 0)
  1067. {
  1068. if (!is_numeric($start) || !is_numeric($end) || ($end <= $start)) return '';
  1069. $i = 0;
  1070. //从开始日期到结束日期的每日时间戳数组
  1071. $d = array();
  1072. if ($type == 1) {
  1073. while ($start <= $end) {
  1074. $d[$i] = date('Y-m-d', $start);
  1075. $start = $start + 86400;
  1076. $i++;
  1077. }
  1078. } else {
  1079. while ($start <= $end) {
  1080. $d[$i] = $start;
  1081. $start = $start + 86400;
  1082. $i++;
  1083. }
  1084. }
  1085. if ($type == 2) {
  1086. $list = array();
  1087. foreach ($d as $k => $v) {
  1088. $list[$k] = getDateRange($v);
  1089. }
  1090. return $list;
  1091. } else {
  1092. return $d;
  1093. }
  1094. }
  1095. /**
  1096. * 获取指定日期开始时间与结束时间
  1097. */
  1098. function getDateRange($timestamp)
  1099. {
  1100. $ret = array();
  1101. $ret['sdate'] = strtotime(date('Y-m-d', $timestamp));
  1102. $ret['edate'] = strtotime(date('Y-m-d', $timestamp)) + 86400;
  1103. return $ret;
  1104. }
  1105. /**
  1106. * 生成从开始月份到结束月份的月份数组
  1107. * @param int $start 开始时间戳
  1108. * @param int $end 结束时间戳
  1109. */
  1110. function monthList($start, $end)
  1111. {
  1112. if (!is_numeric($start) || !is_numeric($end) || ($end <= $start)) return '';
  1113. $start = date('Y-m', $start);
  1114. $end = date('Y-m', $end);
  1115. //转为时间戳
  1116. $start = strtotime($start . '-01');
  1117. $end = strtotime($end . '-01');
  1118. $i = 0;
  1119. $d = array();
  1120. while ($start <= $end) {
  1121. //这里累加每个月的的总秒数 计算公式:上一月1号的时间戳秒数减去当前月的时间戳秒数
  1122. $d[$i] = $start;
  1123. $start += strtotime('+1 month', $start) - $start;
  1124. $i++;
  1125. }
  1126. return $d;
  1127. }
  1128. /**
  1129. * 人民币转大写
  1130. * @param
  1131. */
  1132. function cny($ns)
  1133. {
  1134. static $cnums = array("零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"),
  1135. $cnyunits = array("圆", "角", "分"),
  1136. $grees = array("拾", "佰", "仟", "万", "拾", "佰", "仟", "亿");
  1137. list($ns1, $ns2) = explode(".", $ns, 2);
  1138. $ns2 = array_filter(array($ns2[1], $ns2[0]));
  1139. $ret = array_merge($ns2, array(implode("", _cny_map_unit(str_split($ns1), $grees)), ""));
  1140. $ret = implode("", array_reverse(_cny_map_unit($ret, $cnyunits)));
  1141. return str_replace(array_keys($cnums), $cnums, $ret);
  1142. }
  1143. function _cny_map_unit($list, $units)
  1144. {
  1145. $ul = count($units);
  1146. $xs = array();
  1147. foreach (array_reverse($list) as $x) {
  1148. $l = count($xs);
  1149. if ($x != "0" || !($l % 4)) {
  1150. $n = ($x == '0' ? '' : $x) . ($units[($l - 1) % $ul]);
  1151. } else {
  1152. $n = is_numeric($xs[0][0]) ? $x : '';
  1153. }
  1154. array_unshift($xs, $n);
  1155. }
  1156. return $xs;
  1157. }
  1158. /**
  1159. * 根据类型获取上一类型时间戳数组
  1160. */
  1161. function getLstTimeByType($type = 'today')
  1162. {
  1163. switch ($type) {
  1164. case 'yesterday' :
  1165. $timeArr = Time::yesterday();
  1166. break;
  1167. case 'week' :
  1168. $timeArr = Time::week();
  1169. break;
  1170. case 'lastWeek' :
  1171. $timeArr = Time::lastWeek();
  1172. break;
  1173. case 'month' :
  1174. $timeArr = Time::month();
  1175. break;
  1176. case 'lastMonth' :
  1177. $timeArr = Time::lastMonth();
  1178. break;
  1179. case 'quarter' :
  1180. //本季度
  1181. $month = date('m');
  1182. if ($month == 1 || $month == 2 || $month == 3) {
  1183. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1184. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1185. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1186. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1187. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1188. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1189. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1190. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1191. } else {
  1192. $daterange_start_time = strtotime(date('Y-10-01 00:00:00'));
  1193. $daterange_end_time = strtotime(date("Y-12-31 23:59:59"));
  1194. }
  1195. $timeArr = array($daterange_start_time, $daterange_end_time);
  1196. break;
  1197. case 'lastQuarter' :
  1198. //上季度
  1199. $month = date('m');
  1200. if ($month == 1 || $month == 2 || $month == 3) {
  1201. $year = date('Y') - 1;
  1202. $daterange_start_time = strtotime(date($year . '-10-01 00:00:00'));
  1203. $daterange_end_time = strtotime(date($year . '-12-31 23:59:59'));
  1204. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1205. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1206. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1207. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1208. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1209. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1210. } else {
  1211. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1212. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1213. }
  1214. $timeArr = array($daterange_start_time, $daterange_end_time);
  1215. break;
  1216. case 'year' :
  1217. $timeArr = Time::year();
  1218. break;
  1219. case 'lastYear' :
  1220. $timeArr = Time::lastYear();
  1221. break;
  1222. default :
  1223. $timeArr = Time::today();
  1224. break;
  1225. }
  1226. return $timeArr;
  1227. }
  1228. /**
  1229. * 根据类型获取开始结束时间戳数组
  1230. * @param
  1231. */
  1232. function getTimeByType($type = 'today', $is_last = false)
  1233. {
  1234. $lastArr = [];
  1235. switch ($type) {
  1236. case 'yesterday' :
  1237. $timeArr = Time::yesterday();
  1238. $lastArr = Time::yesterday(1);
  1239. break;
  1240. case 'week' :
  1241. $timeArr = Time::week();
  1242. $lastArr = Time::lastWeek();
  1243. break;
  1244. case 'lastWeek' :
  1245. $timeArr = Time::lastWeek();
  1246. break;
  1247. case 'month' :
  1248. $timeArr = Time::month();
  1249. $lastArr = Time::lastMonth();
  1250. break;
  1251. case 'lastMonth' :
  1252. $timeArr = Time::lastMonth();
  1253. $lastArr = Time::lastMonth(1);
  1254. break;
  1255. case 'quarter' :
  1256. //本季度
  1257. $month = date('m');
  1258. if ($month == 1 || $month == 2 || $month == 3) {
  1259. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1260. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1261. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1262. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1263. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1264. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1265. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1266. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1267. } else {
  1268. $daterange_start_time = strtotime(date('Y-10-01 00:00:00'));
  1269. $daterange_end_time = strtotime(date("Y-12-31 23:59:59"));
  1270. }
  1271. //上季度
  1272. $month = date('m');
  1273. if ($month == 1 || $month == 2 || $month == 3) {
  1274. $year = date('Y') - 1;
  1275. $daterange_start_time_last_time = strtotime(date($year . '-10-01 00:00:00'));
  1276. $daterange_end_time_last_time = strtotime(date($year . '-12-31 23:59:59'));
  1277. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1278. $daterange_start_time_last_time = strtotime(date('Y-01-01 00:00:00'));
  1279. $daterange_end_time_last_time = strtotime(date("Y-03-31 23:59:59"));
  1280. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1281. $daterange_start_time_last_time = strtotime(date('Y-04-01 00:00:00'));
  1282. $daterange_end_time_last_time = strtotime(date("Y-06-30 23:59:59"));
  1283. } else {
  1284. $daterange_start_time_last_time = strtotime(date('Y-07-01 00:00:00'));
  1285. $daterange_end_time_last_time = strtotime(date("Y-09-30 23:59:59"));
  1286. }
  1287. $timeArr = array($daterange_start_time, $daterange_end_time);
  1288. $lastArr = array($daterange_start_time_last_time, $daterange_end_time_last_time);
  1289. break;
  1290. case 'lastQuarter' :
  1291. //上季度
  1292. $month = date('m');
  1293. if ($month == 1 || $month == 2 || $month == 3) {
  1294. $year = date('Y') - 1;
  1295. $daterange_start_time = strtotime(date($year . '-10-01 00:00:00'));
  1296. $daterange_end_time = strtotime(date($year . '-12-31 23:59:59'));
  1297. } elseif ($month == 4 || $month == 5 || $month == 6) {
  1298. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  1299. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  1300. } elseif ($month == 7 || $month == 8 || $month == 9) {
  1301. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  1302. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  1303. } else {
  1304. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  1305. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  1306. }
  1307. $timeArr = array($daterange_start_time, $daterange_end_time);
  1308. $lastArr = array($daterange_start_time_last_time, $daterange_end_time_last_time);
  1309. break;
  1310. case 'year' :
  1311. $timeArr = Time::year();
  1312. $lastArr = Time::lastYear();
  1313. break;
  1314. case 'lastYear' :
  1315. $timeArr = Time::lastYear();
  1316. $lastArr = Time::lastYear(1);
  1317. break;
  1318. default :
  1319. $timeArr = Time::today();
  1320. $lastArr = Time::yesterday();
  1321. break;
  1322. }
  1323. if ($is_last) {
  1324. return $lastArr;
  1325. } else {
  1326. return $timeArr;
  1327. }
  1328. }
  1329. /**
  1330. * 服务器附件完整路径处理
  1331. * @param
  1332. */
  1333. function getFullPath($path)
  1334. {
  1335. if ($path) {
  1336. $protocol = strpos(strtolower($_SERVER['server_protocol']), 'https') === false ? 'http' : 'https';
  1337. return $protocol . '://' . $_SERVER['HTTP_HOST'] . substr($_SERVER["SCRIPT_NAME"], 0, -10) . substr(str_replace(DS, '/', $path), 1);
  1338. } else {
  1339. return '';
  1340. }
  1341. }
  1342. /*取得文件后缀*/
  1343. function getExtension($filename)
  1344. {
  1345. $mytext = substr($filename, strrpos($filename, '.') + 1);
  1346. return $mytext;
  1347. }
  1348. /**
  1349. * 生成编号
  1350. * @param prefix 前缀
  1351. * @return
  1352. * @author Michael_xu
  1353. */
  1354. function prefixNumber($prefix, $number_id = 0, $str = 5)
  1355. {
  1356. return $prefixNumber = $prefix . str_pad($number_id, $str, 0, STR_PAD_LEFT); //填充字符串的左侧(将字符串填充为新的长度)
  1357. }
  1358. /**
  1359. * curl 模拟GET请求
  1360. * @author lee
  1361. ***/
  1362. function curl_get($url)
  1363. {
  1364. //初始化
  1365. $ch = curl_init();
  1366. //设置抓取的url
  1367. curl_setopt($ch, CURLOPT_URL, $url);
  1368. //设置获取的信息以文件流的形式返回,而不是直接输出。
  1369. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  1370. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书
  1371. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // https请求 不验证hosts
  1372. //执行命令
  1373. $output = curl_exec($ch);
  1374. curl_close($ch); //释放curl句柄
  1375. return $output;
  1376. }
  1377. /**
  1378. * 地址坐标转换
  1379. * @param prefix 前缀
  1380. * @return
  1381. * @author Michael_xu
  1382. */
  1383. function get_lng_lat($address)
  1384. {
  1385. $map_ak = config('map_ak');
  1386. $url = "http://api.map.baidu.com/geocoder/v2/?address=$address&output=json&ak=$map_ak&callback=showLocation";
  1387. $ret_script = curl_get($url);
  1388. preg_match_all("/\{.*?\}}/is", $ret_script, $matches);
  1389. $ret_arr = json_decode($matches[0][0], true);
  1390. if ($ret_arr['status'] == 0) { //成功
  1391. $location['lng'] = $ret_arr['result']['location']['lng'];
  1392. $location['lat'] = $ret_arr['result']['location']['lat'];
  1393. return $location;
  1394. } else {
  1395. return false;
  1396. }
  1397. }
  1398. /**
  1399. * 导出数据为excel表格
  1400. * @param $data 一个二维数组,结构如同从数据库查出来的数组
  1401. * @param $title excel的第一行标题,一个数组,如果为空则没有标题
  1402. * @param $filename 下载的文件名
  1403. * @param exportexcel($arr,array('id','账户','密码','昵称'),'文件名!');
  1404. */
  1405. function exportexcel($data = array(), $title = array(), $filename = 'report')
  1406. {
  1407. header("Content-type:application/octet-stream");
  1408. header("Accept-Ranges:bytes");
  1409. header("Content-type:application/vnd.ms-excel");
  1410. header("Content-Disposition:attachment;filename=" . $filename . ".xls");
  1411. header("Pragma: no-cache");
  1412. header("Expires: 0");
  1413. //导出xls 开始
  1414. if (!empty($title)) {
  1415. foreach ($title as $k => $v) {
  1416. $title[$k] = iconv("UTF-8", "GB2312", $v);
  1417. }
  1418. $title = implode("\t", $title);
  1419. echo "$title\n";
  1420. }
  1421. if (!empty($data)) {
  1422. foreach ($data as $key => $val) {
  1423. foreach ($val as $ck => $cv) {
  1424. $data[$key][$ck] = iconv("UTF-8", "GB2312", $cv);
  1425. }
  1426. $data[$key] = implode("\t", $data[$key]);
  1427. }
  1428. echo implode("\n", $data);
  1429. }
  1430. }
  1431. //根据数据库查询出来数组获取某个字段拼接字符串
  1432. function getFieldArray($array = array(), $field = '')
  1433. {
  1434. if (is_array($array) && $field) {
  1435. $ary = array();
  1436. foreach ($array as $value) {
  1437. $ary[] = $value[$field];
  1438. }
  1439. $str = implode(',', $ary);
  1440. return $str;
  1441. } else {
  1442. return false;
  1443. }
  1444. }
  1445. /**
  1446. * 检查该字段若必填,加上"*"
  1447. * @param is_null 是否为空 0否 1是
  1448. * @param name 字段名称
  1449. **/
  1450. function sign_required($is_null, $name)
  1451. {
  1452. if ($is_null == 1) {
  1453. return '*' . $name;
  1454. } else {
  1455. return $name;
  1456. }
  1457. }
  1458. /**
  1459. * [获取是否有管理员角色 adminGroupTypes]
  1460. * @param user_id 当前人ID
  1461. * @return
  1462. */
  1463. function adminGroupTypes($user_id)
  1464. {
  1465. $userModel = new UserModel();
  1466. $groupsArr = $userModel->get($user_id)->groups;
  1467. $groupids = [];
  1468. if ($groupsArr) {
  1469. foreach ($groupsArr as $key => $val) {
  1470. $groupids[] = $val['id'];
  1471. }
  1472. }
  1473. $types = db('admin_group')->where(['id' => ['in', $groupids]])->group('types')->column('types');
  1474. if ($user_id == 1) {
  1475. $types[] = 1;
  1476. }
  1477. return $types ?: [];
  1478. }
  1479. /**
  1480. * [权限数组]
  1481. * @param ruleIds 当前人权限id
  1482. * @return
  1483. */
  1484. function rulesListToArray($rulesList, $ruleIds = [])
  1485. {
  1486. $newList = [];
  1487. if (!is_array($rulesList)) {
  1488. return array();
  1489. } else {
  1490. foreach ($rulesList as $k => $v) {
  1491. if (!is_array($v['children'])) continue;
  1492. foreach ($v['children'] as $k1 => $v1) {
  1493. if (!is_array($v1['children'])) continue;
  1494. foreach ($v1['children'] as $k2 => $v2) {
  1495. $check = false;
  1496. if (in_array($v2['id'], $ruleIds)) {
  1497. $check = true;
  1498. }
  1499. $newList[$v['name']][$v1['name']][$v2['name']] = $check;
  1500. }
  1501. }
  1502. }
  1503. }
  1504. return $newList ?: [];
  1505. }
  1506. /**
  1507. * [获取下一审批信息 nextCheckData]
  1508. * @param user_id 审批申请人ID
  1509. * @param flow_id 审批流ID
  1510. * @param types 关联对象
  1511. * @param types_id 联对象ID
  1512. * @param order_id 审批排序ID
  1513. * @return
  1514. */
  1515. function nextCheckData($user_id, $flow_id, $types, $types_id, $order_id, $check_user_id)
  1516. {
  1517. $new_order_id = $order_id;
  1518. $max_order_id = db('admin_examine_step')->where(['flow_id' => $flow_id])->max('order_id'); //审批流最大排序ID
  1519. $examineStepModel = new \app\admin\model\ExamineStep();
  1520. $stepInfo = $examineStepModel->getStepByOrder($flow_id, $new_order_id); //审批步骤
  1521. $next_user_ids = [];
  1522. $is_end = 0; //审批结束
  1523. //固定流程(status 1负责人主管,2指定用户(任意一人),3指定用户(多人会签),4上一级审批人主管)
  1524. //当前步骤审批人user_id
  1525. $step_user_ids = $examineStepModel->getUserByStep($stepInfo['step_id'], $user_id);
  1526. if ($step_user_ids) {
  1527. if (!$order_id) {
  1528. //创建时使用
  1529. $sub_user_ids = stringToArray($step_user_ids);
  1530. } else {
  1531. if ($stepInfo['status'] == 3) {
  1532. //会签(并关系)
  1533. //当前步骤已审批user_id
  1534. $check_user_ids = $examineStepModel->getUserByCheck($types, $types_id, $new_order_id);
  1535. $user_ids[] = $check_user_id;
  1536. $check_user_ids = $check_user_ids ? array_merge($check_user_ids, $user_ids) : $user_ids;
  1537. //剩余审批人user_id
  1538. $sub_user_ids = $check_user_ids ? array_diff(explode(',', $step_user_ids), $check_user_ids) : $step_user_ids;
  1539. $sub_user_ids = array_unique(array_filter($sub_user_ids));
  1540. if (!$sub_user_ids) {
  1541. $is_end = 1;
  1542. }
  1543. } else {
  1544. $is_end = 1;
  1545. }
  1546. }
  1547. } else {
  1548. $is_end = 1;
  1549. }
  1550. if ($is_end == 1) {
  1551. $next_order_id = $new_order_id + 1;
  1552. } else {
  1553. $next_order_id = $new_order_id;
  1554. }
  1555. //当前审批步骤已结束
  1556. if ($is_end == 1) {
  1557. //当前审批流程是否结束
  1558. $stepInfo = $examineStepModel->getStepByOrder($flow_id, $next_order_id); //审批步骤
  1559. $next_step_user_ids = $examineStepModel->getUserByStep($stepInfo['step_id'], $user_id);
  1560. $next_user_ids = stringToArray($next_step_user_ids);
  1561. } else {
  1562. $next_user_ids = array_unique(array_filter($sub_user_ids));
  1563. }
  1564. if (!$next_user_ids && $next_order_id <= $max_order_id) {
  1565. $newRes = [];
  1566. $newRes = nextCheckData($user_id, $flow_id, $types, $types_id, $next_order_id, $check_user_id);
  1567. $next_user_ids = $newRes['next_user_ids'];
  1568. }
  1569. $data = [];
  1570. $data['order_id'] = ($next_order_id <= $max_order_id) ? $next_order_id : $max_order_id;
  1571. $data['next_user_ids'] = $next_user_ids ?: '';
  1572. return $data;
  1573. }
  1574. /**
  1575. * 解析获取php.ini 的upload_max_filesize(单位:byte)
  1576. * @param $dec int 小数位数
  1577. * @return float (单位:byte)
  1578. * */
  1579. function get_upload_max_filesize_byte($dec = 2)
  1580. {
  1581. $max_size = ini_get('upload_max_filesize');
  1582. preg_match('/(^[0-9\.]+)(\w+)/', $max_size, $info);
  1583. $size = $info[1];
  1584. $suffix = strtoupper($info[2]);
  1585. $a = array_flip(array("B", "KB", "MB", "GB", "TB", "PB"));
  1586. $b = array_flip(array("B", "K", "M", "G", "T", "P"));
  1587. $pos = $a[$suffix] && $a[$suffix] !== 0 ? $a[$suffix] : $b[$suffix];
  1588. return round($size * pow(1024, $pos), $dec);
  1589. }
  1590. /**
  1591. * 模拟post进行url请求
  1592. * @param string $url
  1593. * @param string $param
  1594. */
  1595. function curl_post($url = '', $post = array())
  1596. {
  1597. $curl = curl_init(); // 启动一个CURL会话
  1598. curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
  1599. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
  1600. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
  1601. curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
  1602. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
  1603. curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
  1604. curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
  1605. curl_setopt($curl, CURLOPT_POSTFIELDS, $post); // Post提交的数据包
  1606. curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
  1607. curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
  1608. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
  1609. $res = curl_exec($curl); // 执行操作
  1610. if (curl_errno($curl)) {
  1611. echo 'Errno' . curl_error($curl);//捕抓异常
  1612. }
  1613. curl_close($curl); // 关闭CURL会话
  1614. return $res; // 返回数据,json格式
  1615. }
  1616. /**
  1617. * 输出json字符串,用于接口调试
  1618. *
  1619. * @return void
  1620. * @author ymob
  1621. */
  1622. function vdd()
  1623. {
  1624. header('Content-Type: text/json; charset=utf-8');
  1625. $args = func_get_args();
  1626. foreach ($args as &$val) {
  1627. if ($val instanceof think\Model) {
  1628. $val = $val->getLastSql();
  1629. }
  1630. }
  1631. if (count($args) < 2) {
  1632. $args = array_shift($args);
  1633. }
  1634. die(json_encode($args));
  1635. }
  1636. /**
  1637. * 根据时间查询参数返回时间条件 (用于统计分析模块)
  1638. *
  1639. * @param array $where
  1640. * @param string $field
  1641. * @return void
  1642. * @author ymob
  1643. */
  1644. function getWhereTimeByParam(&$where, $field = 'create_time')
  1645. {
  1646. $param = request()->param();
  1647. if (empty($param['type']) && empty($param['start_time'])) {
  1648. $param['type'] = 'month';
  1649. }
  1650. if (!empty($param['start_time'])) {
  1651. $where[$field] = ['between', [$param['start_time'], $param['end_time']]];
  1652. } else {
  1653. $timeRange = getTimeByType($param['type']);
  1654. if ($timeRange) {
  1655. $where[$field] = ['between', [$timeRange[0], $timeRange[1]]];
  1656. }
  1657. }
  1658. }
  1659. /**
  1660. * 根据员工、部门查询参数返回员工、部门条件 (用于统计分析模块)
  1661. *
  1662. * @param array $where
  1663. * @param string $field
  1664. * @param string $m
  1665. * @param string $c
  1666. * @param string $a
  1667. * @return void
  1668. * @author ymob
  1669. */
  1670. function getWhereUserByParam(&$where, $field = 'owner_user_id', $m = '', $c = '', $a = '')
  1671. {
  1672. $param = request()->param();
  1673. $userModel = new UserModel();
  1674. $map_user_ids = [];
  1675. if ($param['user_id']) {
  1676. $map_user_ids = array($param['user_id']);
  1677. } elseif ($param['structure_id']) {
  1678. $map_user_ids = $userModel->getSubUserByStr($param['structure_id'], 2);
  1679. } else {
  1680. $map_user_ids = $userModel->getUserByPer($m, $c, $a);
  1681. $where[$field] = array('in', $map_user_ids);
  1682. return;
  1683. }
  1684. $perUserIds = $userModel->getUserByPer($m, $c, $a); //权限范围内userIds
  1685. $userIds = array_intersect($map_user_ids, $perUserIds); //数组交集
  1686. $where[$field] = array('in', $userIds);
  1687. }
  1688. /**
  1689. * 获取客户浏览器类型
  1690. */
  1691. function getBrowser()
  1692. {
  1693. $Browser = $_SERVER['HTTP_USER_AGENT'];
  1694. if (preg_match('/MSIE/i', $Browser)) {
  1695. $Browser = 'MSIE';
  1696. } elseif (preg_match('/Firefox/i', $Browser)) {
  1697. $Browser = 'Firefox';
  1698. } elseif (preg_match('/Chrome/i', $Browser)) {
  1699. $Browser = 'Chrome';
  1700. } elseif (preg_match('/Safari/i', $Browser)) {
  1701. $Browser = 'Safari';
  1702. } elseif (preg_match('/Opera/i', $Browser)) {
  1703. $Browser = 'Opera';
  1704. } else {
  1705. $Browser = 'Other';
  1706. }
  1707. return $Browser;
  1708. }
  1709. /**
  1710. * 获取客户端系统
  1711. */
  1712. function getOS()
  1713. {
  1714. $agent = $_SERVER['HTTP_USER_AGENT'];
  1715. if (preg_match('/win/i', $agent)) {
  1716. if (preg_match('/nt 6.1/i', $agent)) {
  1717. $OS = 'Windows 7';
  1718. } else if (preg_match('/nt 6.2/i', $agent)) {
  1719. $OS = 'Windows 8';
  1720. } else if (preg_match('/nt 10.0/i', $agent)) {
  1721. $OS = 'Windows 10';
  1722. } else {
  1723. $OS = 'Windows';
  1724. }
  1725. } elseif (preg_match('/mac/i', $agent)) {
  1726. $OS = 'MAC';
  1727. } elseif (preg_match('/linux/i', $agent)) {
  1728. $OS = 'Linux';
  1729. } elseif (preg_match('/unix/i', $agent)) {
  1730. $OS = 'Unix';
  1731. } elseif (preg_match('/bsd/i', $agent)) {
  1732. $OS = 'BSD';
  1733. } else {
  1734. $OS = 'Other';
  1735. }
  1736. return $OS;
  1737. }
  1738. /**
  1739. * 根据IP获取地址
  1740. */
  1741. function getAddress($ip)
  1742. {
  1743. $res = file_get_contents("http://ip.360.cn/IPQuery/ipquery?ip=" . $ip);
  1744. $res = json_decode($res, 1);
  1745. if ($res && $res['errno'] == 0) {
  1746. return explode("\t", $res['data'])[0];
  1747. } else {
  1748. return '';
  1749. }
  1750. }
  1751. /**
  1752. * 下载服务器文件
  1753. *
  1754. * @param string $file 文件路径
  1755. * @param string $name 下载名称
  1756. * @param boolean $del 下载后删除
  1757. * @return void
  1758. * @author Ymob
  1759. */
  1760. function download($file, $name = '', $del = false)
  1761. {
  1762. if (!file_exists($file)) {
  1763. return resultArray([
  1764. 'error' => '文件不存在',
  1765. ]);
  1766. }
  1767. // 仅允许下载 public 目录下文件
  1768. $res = strpos(realpath($file), realpath('./public'));
  1769. if ($res !== 0) {
  1770. return resultArray([
  1771. 'error' => '文件路径错误',
  1772. ]);
  1773. }
  1774. $fp = fopen($file, 'r');
  1775. $size = filesize($file);
  1776. //下载文件需要的头
  1777. header("Content-type: application/octet-stream");
  1778. header("Accept-Ranges: bytes");
  1779. header('ResponseType: blob');
  1780. header("Accept-Length: $size");
  1781. $file_name = $name != '' ? $name : pathinfo($file, PATHINFO_BASENAME);
  1782. // urlencode 处理中文乱码
  1783. header("Content-Disposition:attachment; filename=" . urlencode($file_name));
  1784. // 导出数据时 csv office Excel 需要添加bom头
  1785. if (pathinfo($file, PATHINFO_EXTENSION) == 'csv') {
  1786. echo "\xEF\xBB\xBF"; // UTF-8 BOM
  1787. }
  1788. $fileCount = 0;
  1789. $fileUnit = 1024;
  1790. while (!feof($fp) && $size - $fileCount > 0) {
  1791. $fileContent = fread($fp, $fileUnit);
  1792. echo $fileContent;
  1793. $fileCount += $fileUnit;
  1794. }
  1795. fclose($fp);
  1796. // 删除
  1797. if ($del) @unlink($file);
  1798. die();
  1799. }
  1800. /**
  1801. * 临时目录生成文件名,并返回绝对路径
  1802. *
  1803. * @param string $ext 文件类型后缀
  1804. * @param string $path 临时文件目录 默认 ./public/temp/
  1805. * @return string $file_path 文件名称绝对路径
  1806. * @author ymob
  1807. */
  1808. function tempFileName($ext = '')
  1809. {
  1810. // 临时目录
  1811. $path = TEMP_DIR . date('Ymd') . DS;
  1812. if (!file_exists($path)) {
  1813. mkdir($path, 0777, true);
  1814. }
  1815. $ext = trim($ext, '.');
  1816. do {
  1817. $temp_file = md5(time() . rand(1000, 9999));
  1818. $file_path = $path . $temp_file . '.' . $ext;
  1819. } while (file_exists($file_path));
  1820. return $file_path;
  1821. }
  1822. /**
  1823. * 递归删除目录
  1824. *
  1825. * @param string $dir
  1826. * @return void
  1827. * @author Ymob
  1828. */
  1829. function delDir($dir)
  1830. {
  1831. $dh = opendir($dir);
  1832. while ($file = readdir($dh)) {
  1833. if ($file != "." && $file != "..") {
  1834. $fullpath = $dir . "/" . $file;
  1835. if (!is_dir($fullpath)) {
  1836. @unlink($fullpath);
  1837. } else {
  1838. deldir($fullpath);
  1839. }
  1840. }
  1841. }
  1842. closedir($dh);
  1843. //删除当前文件夹:
  1844. @rmdir($dir);
  1845. }
  1846. /**
  1847. * 商业智能 查询缓存
  1848. *
  1849. * @param string $sql Sql语句
  1850. * @param int $bi_slow_query_time 慢查询时间(毫秒),默认读取Config(bi_slow_query_time)
  1851. * @return mixed
  1852. * @author Ymob
  1853. * @datetime 2019-11-21 17:36:50
  1854. */
  1855. function queryCache($sql = '', $bi_slow_query_time = null)
  1856. {
  1857. $key = 'BI_queryCache' . md5($sql);
  1858. $val = cache($key);
  1859. if (!$val) {
  1860. $start_time = microtime(true) * 1000;
  1861. $val = Db::query($sql);
  1862. $end_time = microtime(true) * 1000;
  1863. $slow_query = true;
  1864. // 是否使用系统默认设置-慢查询时间
  1865. if ($bi_slow_query_time === null) {
  1866. $bi_slow_query_time = config('bi_slow_query_time');
  1867. }
  1868. if ($bi_slow_query_time > 0) {
  1869. $slow_query = ($end_time - $start_time) > $bi_slow_query_time;
  1870. }
  1871. if ($slow_query && $val) {
  1872. cache($key, $val, config('bi_cache_time'));
  1873. }
  1874. }
  1875. return $val;
  1876. }
  1877. /**
  1878. * 图表时间范围处理,按月/天返回时间段数组
  1879. *
  1880. * @param int $start 开始时间(时间戳)
  1881. * @param int $end 结束时间(时间戳)
  1882. * @return array
  1883. * @author Ymob
  1884. * @datetime 2019-11-18 09:25:09
  1885. */
  1886. function getTimeArray($start = null, $end = null)
  1887. {
  1888. if ($start == null || $end == null) {
  1889. $param = request()->param();
  1890. switch ($param['type']) {
  1891. // 本年
  1892. case 'year':
  1893. $start = strtotime(date('Y-01-01'));
  1894. $end = strtotime('+1 year', $start) - 1;
  1895. break;
  1896. // 去年
  1897. case 'lastYear':
  1898. $start = strtotime(date(date('Y') - 1 . '-01-01'));
  1899. $end = strtotime('+1 year', $start) - 1;
  1900. break;
  1901. // 本季度、上季度
  1902. case 'quarter':
  1903. case 'lastQuarter':
  1904. $t = intval((date('m') - 1) / 3);
  1905. $start_y = ($t * 3) + 1;
  1906. $start = strtotime(date("Y-{$start_y}-01"));
  1907. if ($param['type'] == 'lastQuarter') { // 上季度
  1908. $start = strtotime('-3 month', $start);
  1909. }
  1910. $end = strtotime('+3 month', $start) - 1;
  1911. break;
  1912. // 本月、上月
  1913. case 'month':
  1914. case 'lastMonth':
  1915. $start = strtotime(date('Y-m-01'));
  1916. if ($param['type'] == 'lastMonth') {
  1917. $start = strtotime('-1 month', $start);
  1918. }
  1919. $end = strtotime('+1 month', $start) - 1;
  1920. break;
  1921. // 本周、上周
  1922. case 'week':
  1923. case 'lastWeek':
  1924. $start = strtotime('-' . (date('w') - 1) . 'day', strtotime(date('Y-m-d')));
  1925. if ($param['type'] == 'lastWeek') {
  1926. $start = strtotime('-7 day', $start);
  1927. }
  1928. $end = strtotime('+7 day', $start) - 1;
  1929. break;
  1930. // 今天、昨天
  1931. case 'today':
  1932. case 'yesterday':
  1933. $start = strtotime(date('Y-m-d'));
  1934. if ($param['type'] == 'yesterday') {
  1935. $start = strtotime('-1 day', $start);
  1936. }
  1937. $end = strtotime('+1 day', $start) - 1;
  1938. break;
  1939. default:
  1940. if ($param['start_time'] && $param['end_time']) {
  1941. $start = $param['start_time'];
  1942. $end = $param['end_time'];
  1943. } else {
  1944. // 本年
  1945. $start = strtotime(date('Y-01-01'));
  1946. $end = strtotime('+1 year', $start) - 1;
  1947. }
  1948. break;
  1949. }
  1950. }
  1951. $between = [$start, $end];
  1952. $list = [];
  1953. $len = ($end - $start) / 86400;
  1954. // 大于30天 按月统计、小于按天统计
  1955. if ($len > 31) {
  1956. $time_format = '%Y-%m';
  1957. while (true) {
  1958. $start = strtotime(date('Y-m-01', $start));
  1959. $item = [];
  1960. $item['type'] = date('Y-m', $start);
  1961. $item['start_time'] = $start;
  1962. $item['end_time'] = strtotime('+1 month', $start) - 1;
  1963. $list[] = $item;
  1964. if ($item['end_time'] >= $end) break;
  1965. $start = $item['end_time'] + 1;
  1966. }
  1967. } else {
  1968. $time_format = '%Y-%m-%d';
  1969. while (true) {
  1970. $item = [];
  1971. $item['type'] = date('Y-m-d', $start);
  1972. $item['start_time'] = $start;
  1973. $item['end_time'] = strtotime('+1 day', $start) - 1;
  1974. $list[] = $item;
  1975. if ($item['end_time'] >= $end) break;
  1976. $start = $item['end_time'] + 1;
  1977. }
  1978. }
  1979. return [
  1980. 'list' => $list, // 时间段列表
  1981. 'time_format' => $time_format, // 时间格式 mysql 格式化时间戳
  1982. 'between' => $between // 开始结束时间
  1983. ];
  1984. }
  1985. /**
  1986. * 打印程序执行时间
  1987. *
  1988. * @param integer $s
  1989. * @return void
  1990. * @author Ymob
  1991. * @datetime 2019-11-28 09:31:45
  1992. */
  1993. function tt($s = 0)
  1994. {
  1995. die((string)round(microtime(1) - ($s ?: THINK_START_TIME), 3));
  1996. }
  1997. /**
  1998. * 数据库备份
  1999. */
  2000. function DBBackup($file = '', $path = '')
  2001. {
  2002. $type = config('database.type');
  2003. $host = config('database.hostname');
  2004. $port = config('database.hostport');
  2005. $dbname = config('database.database');
  2006. $username = config('database.username');
  2007. $password = config('database.password');
  2008. $dsn = "{$type}:host={$host};dbname={$dbname};port={$port}";
  2009. if ($file == '') {
  2010. $save_path = dirname(APP_PATH) . DS . 'data' . DS . date('Ym') . DS;
  2011. if (!file_exists($save_path) && !mkdir($save_path, '0777', true)) {
  2012. return 'data目录无写入权限';
  2013. }
  2014. $file = $save_path . date('d_H_i') . '_db_backup' . '.sql';
  2015. }
  2016. if (file_exists($file)) {
  2017. return '数据库备份文件已存在(自动备份时间间隔需大于1分钟)。';
  2018. }
  2019. try {
  2020. $backup = new \com\Mysqldump($dsn, $username, $password);
  2021. $backup->start($file);
  2022. return true;
  2023. } catch (\Exception $e) {
  2024. return '备份失败,请手动备份。错误原因:' . $e->getMessage();
  2025. }
  2026. }
  2027. /**
  2028. * 根据ip获取地址
  2029. */
  2030. function getAddressById($data)
  2031. {
  2032. $ip = new IpLocation();
  2033. $ip_address = $ip->getlocation($data);
  2034. return $ip_address;
  2035. }
  2036. if (!function_exists('isSuperAdministrators')) {
  2037. /**
  2038. * 判断是否是超级管理员
  2039. *
  2040. * @param $userId
  2041. * @return bool
  2042. */
  2043. function isSuperAdministrators($userId)
  2044. {
  2045. $status = false;
  2046. $apiCommon = new \app\admin\controller\ApiCommon();
  2047. $userId = !empty($userId) ? $userId : $apiCommon->userInfo['id'];
  2048. $data = db('admin_access')->where('user_id', $userId)->column('group_id');
  2049. if ($userId == 1 || in_array(1, $data)) {
  2050. $status = true;
  2051. }
  2052. return $status;
  2053. }
  2054. }
  2055. if (!function_exists('getFieldGrantData')) {
  2056. /**
  2057. * 获取自动授权数据
  2058. *
  2059. * @return array
  2060. */
  2061. function getFieldGrantData($userId)
  2062. {
  2063. $result = [];
  2064. $apiCommon = new \app\admin\controller\ApiCommon();
  2065. $userId = !empty($userId) ? $userId : $apiCommon->userInfo['id'];
  2066. $grantData = Db::query("
  2067. SELECT
  2068. `grant`.`module`, `grant`.`column`, `grant`.`content`
  2069. FROM
  2070. `5kcrm_admin_access` AS `access`
  2071. LEFT JOIN
  2072. `5kcrm_admin_group` AS `group` ON `access`.`group_id` = `group`.`id`
  2073. LEFT JOIN
  2074. `5kcrm_admin_field_grant` AS `grant` ON `group`.`id` = `grant`.`role_id`
  2075. WHERE
  2076. `access`.`user_id` =
  2077. " . $userId);
  2078. # 存在多角色多授权的情况
  2079. foreach ($grantData AS $key => $value) {
  2080. $result[$value['module'] . '_' . $value['column']][] = !empty($value['content']) ? unserialize($value['content']) : [];
  2081. }
  2082. return $result;
  2083. }
  2084. }
  2085. if (!function_exists('getFieldGrantStatus')) {
  2086. /**
  2087. * 获取字段授权状态
  2088. *
  2089. * @param $field
  2090. * @param $grantData
  2091. * @return int[]
  2092. */
  2093. function getFieldGrantStatus($field, $grantData)
  2094. {
  2095. # 默认状态都是不能查看、不能编辑,通过配置来取最大权限。
  2096. $result = ['read' => 0, 'write' => 0];
  2097. foreach ($grantData AS $key => $value) {
  2098. # 对于不在权限控制之内的字段,将状态都改为1。
  2099. $fieldBool = false;
  2100. foreach ($value AS $ke => $va) {
  2101. if ($va['field'] == $field) {
  2102. $result['read'] = $va['read'] > $result['read'] ? $va['read'] : $result['read'];
  2103. $result['write'] = $va['write'] > $result['write'] ? $va['write'] : $result['write'];
  2104. $fieldBool = true;
  2105. }
  2106. }
  2107. if (!$fieldBool) {
  2108. $result['read'] = 1;
  2109. $result['write'] = 1;
  2110. }
  2111. }
  2112. return $result;
  2113. }
  2114. /**
  2115. * 仪表盘日志使用
  2116. * 根据类型获取开始结束时间戳数组
  2117. * @param
  2118. */
  2119. function ByDateTime($type = 'today')
  2120. {
  2121. switch ($type) {
  2122. case 'yesterday' :
  2123. $timeArr = DataTime::yesterday();
  2124. $timeArr['last_time'] = DataTime::yesterday(1);
  2125. break;
  2126. case 'week' :
  2127. $timeArr = DataTime::week();
  2128. $timeArr['last_time'] = DataTime::lastWeek(1);
  2129. break;
  2130. case 'lastWeek' :
  2131. $timeArr = DataTime::lastWeek();
  2132. $timeArr['last_time'] = DataTime::lastWeek(1);
  2133. break;
  2134. case 'month' :
  2135. $timeArr = DataTime::month();
  2136. $timeArr['last_time'] = DataTime::lastMonth(1);
  2137. break;
  2138. case 'lastMonth' :
  2139. $timeArr = DataTime::lastMonth();
  2140. $timeArr['last_time'] = DataTime::lastMonth(1);
  2141. break;
  2142. case 'quarter' :
  2143. //本季度
  2144. $month = date('m');
  2145. if ($month == 1 || $month == 2 || $month == 3) {
  2146. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  2147. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  2148. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2149. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  2150. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  2151. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2152. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  2153. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  2154. } else {
  2155. $daterange_start_time = strtotime(date('Y-10-01 00:00:00'));
  2156. $daterange_end_time = strtotime(date("Y-12-31 23:59:59"));
  2157. }
  2158. //上季度
  2159. $month = date('m');
  2160. if ($month == 1 || $month == 2 || $month == 3) {
  2161. $year = date('Y') - 1;
  2162. $daterange_start_time_last_time = strtotime(date($year . '-10-01 00:00:00'));
  2163. $daterange_end_time_last_time = strtotime(date($year . '-12-31 23:59:59'));
  2164. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2165. $daterange_start_time_last_time = strtotime(date('Y-01-01 00:00:00'));
  2166. $daterange_end_time_last_time = strtotime(date("Y-03-31 23:59:59"));
  2167. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2168. $daterange_start_time_last_time = strtotime(date('Y-04-01 00:00:00'));
  2169. $daterange_end_time_last_time = strtotime(date("Y-06-30 23:59:59"));
  2170. } else {
  2171. $daterange_start_time_last_time = strtotime(date('Y-07-01 00:00:00'));
  2172. $daterange_end_time_last_time = strtotime(date("Y-09-30 23:59:59"));
  2173. }
  2174. $timeArr['last_time'] = array($daterange_start_time_last_time, $daterange_end_time_last_time);
  2175. $timeArr = array($daterange_start_time, $daterange_end_time);
  2176. break;
  2177. case 'lastQuarter' :
  2178. //上季度
  2179. $month = date('m');
  2180. if ($month == 1 || $month == 2 || $month == 3) {
  2181. $year = date('Y') - 1;
  2182. $daterange_start_time = strtotime(date($year . '-10-01 00:00:00'));
  2183. $daterange_end_time = strtotime(date($year . '-12-31 23:59:59'));
  2184. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2185. $daterange_start_time = strtotime(date('Y-01-01 00:00:00'));
  2186. $daterange_end_time = strtotime(date("Y-03-31 23:59:59"));
  2187. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2188. $daterange_start_time = strtotime(date('Y-04-01 00:00:00'));
  2189. $daterange_end_time = strtotime(date("Y-06-30 23:59:59"));
  2190. } else {
  2191. $daterange_start_time = strtotime(date('Y-07-01 00:00:00'));
  2192. $daterange_end_time = strtotime(date("Y-09-30 23:59:59"));
  2193. }
  2194. //上季度
  2195. $month = date('m');
  2196. if ($month == 1 || $month == 2 || $month == 3) {
  2197. $year = date('Y') - 2;
  2198. $daterange_start_time_last_time = strtotime(date($year . '-10-01 00:00:00'));
  2199. $daterange_end_time_last_time = strtotime(date($year . '-12-31 23:59:59'));
  2200. } elseif ($month == 4 || $month == 5 || $month == 6) {
  2201. $daterange_start_time_last_time = strtotime(date('Y-01-01 00:00:00'));
  2202. $daterange_end_time_last_time = strtotime(date("Y-03-31 23:59:59"));
  2203. } elseif ($month == 7 || $month == 8 || $month == 9) {
  2204. $daterange_start_time_last_time = strtotime(date('Y-04-01 00:00:00'));
  2205. $daterange_end_time_last_time = strtotime(date("Y-06-30 23:59:59"));
  2206. } else {
  2207. $daterange_start_time_last_time = strtotime(date('Y-07-01 00:00:00'));
  2208. $daterange_end_time_last_time = strtotime(date("Y-09-30 23:59:59"));
  2209. }
  2210. $timeArr = array($daterange_start_time, $daterange_end_time);
  2211. $timeArr['last_time'] = array($daterange_start_time_last_time, $daterange_end_time_last_time);
  2212. break;
  2213. case 'year' :
  2214. $timeArr = DataTime::year();
  2215. $timeArr['last_time'] = DataTime::lastYear(1);
  2216. break;
  2217. case 'lastYear' :
  2218. $timeArr = DataTime::lastYear();
  2219. $timeArr['last_time'] = DataTime::lastYear(1);
  2220. break;
  2221. case 'recent60' :
  2222. $timeArr = DataTime::recent60();
  2223. break;
  2224. case 'recent30' :
  2225. $timeArr = DataTime::recent30();
  2226. break;
  2227. default :
  2228. $timeArr = DataTime::today();
  2229. $timeArr['last_time'] = DataTime::yesterday(1);
  2230. break;
  2231. }
  2232. return $timeArr;
  2233. }
  2234. }