InterfaceService.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. <?php
  2. namespace App\Services\Interface;
  3. use App\Rules\EsExistsRule;
  4. use App\Rules\EsUniqueRule;
  5. use App\Services\Login\LoginTokenService;
  6. use GuzzleHttp\Client;
  7. use Illuminate\Http\JsonResponse;
  8. use Illuminate\Support\Arr;
  9. use Illuminate\Support\Facades\DB;
  10. use Illuminate\Support\Facades\Request;
  11. use Illuminate\Support\Facades\Validator;
  12. use Illuminate\Support\Str;
  13. use App\Services\Interface\Database\DbManager;
  14. class InterfaceService
  15. {
  16. protected string $interfaceAlias;
  17. protected array $websiteInfo;
  18. protected int $websiteId;
  19. protected array $interfaceInfo;
  20. protected array $interfaceSettingInfo = [];
  21. protected array $conditionSettingsInfo = [];
  22. protected array $interfaceResultInfo = [];
  23. protected array $assembleInfo = [];
  24. protected ?array $assembleColumns = [];
  25. protected array $columnIdToCodes = [];
  26. protected string $table = '';
  27. protected array $requestData = [];
  28. protected ?array $execResultArr = [];
  29. protected $tokenInfo;
  30. protected int $userId;
  31. /**
  32. * InterfaceService constructor.
  33. *
  34. * @throws \Exception
  35. */
  36. public function __construct(string $interfaceAlias, array $websiteInfo)
  37. {
  38. if (empty($websiteInfo)) {
  39. abort(508, '管理后台配置错误,站点不存在!');
  40. }
  41. $this->interfaceAlias = $interfaceAlias;
  42. $this->websiteInfo = $websiteInfo;
  43. $this->websiteId = $this->websiteInfo['id'];
  44. // 获取接口信息
  45. $interfaceInfo = DB::table('dep_interface')->where('is_use', 1)->where('is_delete', 0)->where('website_id', $this->websiteId)->where('en_alias', $this->interfaceAlias)->first();
  46. if ($interfaceInfo) {
  47. $this->interfaceInfo = get_object_vars($interfaceInfo);
  48. // 请求参数配置
  49. $this->interfaceSettingInfo = $this->interfaceInfo['request_settings'] ? json_decode($this->interfaceInfo['request_settings'], true) : [];
  50. // 条件配置
  51. $this->conditionSettingsInfo = $this->interfaceInfo['condition_settings'] ? json_decode($this->interfaceInfo['condition_settings'], true) : [];
  52. // 请求结果配置
  53. $this->interfaceResultInfo = $this->interfaceInfo['result_settings'] ? json_decode($this->interfaceInfo['result_settings'], true) : [];
  54. // 系统接口使用
  55. if (1 == $this->interfaceInfo['category_type']) {
  56. $this->getAssembleInfo();
  57. $this->getAssembleColumn();
  58. }
  59. } else {
  60. abort(404, '接口不存在,请联系管理人员!');
  61. }
  62. }
  63. /**
  64. * 验证数据,如果有错误,则返回错误信息.
  65. */
  66. public function validator(): ?string
  67. {
  68. // 判断是否需要登录
  69. if (isset($this->interfaceInfo['is_login']) && $this->interfaceInfo['is_login']) {
  70. if (!$this->isLogin()) {
  71. return '对不起,请先登录!';
  72. }
  73. }
  74. // 如果没有配置参数,则默认验证成功
  75. if (empty($this->interfaceSettingInfo)) {
  76. return null;
  77. }
  78. $validatorAttributes = [];
  79. $ruleArr = [];
  80. // 设置的参数都要全部循环一遍,因为可能会设置固定参数,这样即使不传入参数,也可以使用
  81. foreach ($this->interfaceSettingInfo as $item) {
  82. $columnType = $item['column_type'] ?? 'input'; // 获取参数方式 Input Header Cookies Session File userId
  83. $columnType = strtolower($columnType);
  84. $column = $item['column'];
  85. $tableColumn = $item['true_column'] ?? ''; // 真实使用的表字段
  86. $ruleArr[$tableColumn ?: $column] = $item['rules'];
  87. if ($item['is_fixed']) { // 固定值
  88. $requestValue = trim($item['default']);
  89. } else {
  90. // 如果设置is_delete,则必须为固定值,防止被非法使用
  91. if ('is_delete' == $column) {
  92. return '请求参数【' . $item['title'] . '(' . $item['column'] . ')】必须是固定值,不允许动态设置!!';
  93. }
  94. // 获取请求的参数
  95. if ('input' == $columnType) {
  96. $requestValue = Request::input($column, $item['default']);
  97. } elseif ('header' == $columnType) {
  98. $requestValue = Request::header($column, $item['default']);
  99. } elseif ('cookies' == $columnType) {
  100. $requestValue = Request::cookie($column, $item['default']);
  101. } elseif ('session' == $columnType) {
  102. $requestValue = Request::session()->get($column, $item['default']);
  103. } elseif ('file' == $columnType) {
  104. $requestValue = Request::file($column, $item['default']);
  105. } elseif ('userid' == $columnType) {
  106. // 必须登录才能获取用户信息
  107. if (!$this->isLogin()) {
  108. return '对不起,请先登录!';
  109. }
  110. $requestValue = $this->userId;
  111. } else {
  112. $requestValue = Request::input($column, $item['default']);
  113. }
  114. }
  115. $this->requestData[$tableColumn ?: $column] = $requestValue;
  116. $validatorAttributes[$tableColumn ?: $column] = $item['title'];
  117. // 使用函数
  118. if (isset($item['type']) && $item['type'] && isset($item['conditions']) && $item['conditions']) {
  119. $allData = array_merge($this->requestData, ['interfaceInfo' => $this->interfaceInfo], ['websiteInfo' => $this->websiteInfo]);
  120. $this->execResult($item['conditions'], $allData);
  121. // 如果有执行失败的返回错误
  122. foreach ($this->execResultArr as $exeItem) {
  123. // 1 错误继续 2 错误退出 3 直接退出
  124. $back_type = $exeItem['back_type'];
  125. if (2 == $back_type) {
  126. if ($exeItem['error']) {
  127. return $exeItem['result']['msg'] ?? "系统错误";
  128. }
  129. } elseif ($back_type == 3) {
  130. return $exeItem['result'];
  131. }
  132. }
  133. // 处理参数返回的结果
  134. if ($backR = $this->exeRequestManage($item, $tableColumn ?: $column)) {
  135. return $backR;
  136. }
  137. }
  138. }
  139. // 如果没有设置is_delete,默认设置0,只获取没有被删除的数据
  140. if (!isset($this->requestData['is_delete'])) {
  141. $this->requestData['is_delete'] = 0;
  142. }
  143. // 获取请求的参数的验证规则
  144. list($validatorRules, $validatorMsgArr) = $this->getRequestRules($ruleArr);
  145. $validator = Validator::make($this->requestData, $validatorRules, $validatorMsgArr, $validatorAttributes);
  146. if ($validator->fails()) {
  147. return $validator->errors()->first();
  148. } else {
  149. return null;
  150. }
  151. }
  152. // 处理参数返回的结果
  153. private function exeRequestManage($item, $column)
  154. {
  155. // 获取返回的结果设置
  156. if (empty($item['return_settings']['resultIndexes'])) {
  157. return '';
  158. }
  159. $return_settings = $item['return_settings'];
  160. $resultIndexes = $return_settings['resultIndexes'];
  161. if (empty($resultIndexes)) {
  162. return '请求参数【' . $item['title'] . '(' . $item['column'] . ')】设置错误! - 请进入管理后台,重新设置!';
  163. }
  164. if (count($resultIndexes) > 1) {
  165. $exeData = [];
  166. foreach ($resultIndexes as $indexes) {
  167. // 允许设置请求别名
  168. $paramArr = explode(':', $indexes);
  169. $index = $paramArr[0];
  170. $indexAlias = $paramArr[1] ?? ''; // 别名
  171. if ($indexAlias) {
  172. $exeData[$indexAlias] = Arr::get($this->requestData, $index);
  173. } else {
  174. $exeData[] = Arr::get($this->requestData, $index);
  175. }
  176. }
  177. $this->requestData[$column] = $exeData;
  178. } else {
  179. // 允许设置请求别名
  180. $paramArr = explode(':', $resultIndexes[0]);
  181. $index = $paramArr[0];
  182. $this->requestData[$column] = Arr::get($this->requestData, $index);
  183. }
  184. }
  185. /**
  186. * 获取请求的参数的验证规则.
  187. *
  188. * @return array
  189. */
  190. private function getRequestRules(array $ruleArr)
  191. {
  192. $validatorRules = [];
  193. $validatorMsgArr = [];
  194. foreach ($ruleArr as $column => $rules) {
  195. $typeArr = [];
  196. foreach ($rules as $ruleValue) {
  197. if (isset($ruleValue['type']) && 2 === $ruleValue['type']) { // 自定义规则
  198. $typeArr[] = $this->getRuleClass($ruleValue);
  199. } else { // laravel验证规则
  200. if (isset($ruleValue['params']) && ($ruleValue['params'] || $ruleValue['params'] == 0)) {
  201. $typeArr[] = $ruleValue['rule'] . ':' . $ruleValue['params'];
  202. } else {
  203. $typeArr[] = $ruleValue['rule'];
  204. }
  205. if (!empty($ruleValue['error_msg'])) {
  206. $validatorMsgArr[$column . '.' . $ruleValue['rule']] = $ruleValue['error_msg'];
  207. }
  208. }
  209. }
  210. $validatorRules[$column] = implode('|', $typeArr);
  211. }
  212. return [$validatorRules, $validatorMsgArr];
  213. }
  214. /**
  215. * 判断是否已经登录.
  216. */
  217. public function isLogin(): bool
  218. {
  219. $loginToken = new LoginTokenService($this->websiteInfo['token_table']);
  220. $this->tokenInfo = $loginToken->checkLogin();
  221. if ($this->tokenInfo) {
  222. $this->userId = $this->tokenInfo->user_id;
  223. return true;
  224. } else {
  225. return false;
  226. }
  227. }
  228. /**
  229. * 获取当前接口信息.
  230. *
  231. * @return array
  232. */
  233. public function getInterfaceInfo(): array
  234. {
  235. return $this->interfaceInfo;
  236. }
  237. /**
  238. * 获取请求的数据.
  239. */
  240. public function getRequestData(string $key = ''): array|string
  241. {
  242. if ($key) {
  243. return $this->requestData[$key] ?? '';
  244. }
  245. return $this->requestData;
  246. }
  247. /**
  248. * 设置请求的参数 可以对请求参数进行修改.
  249. *
  250. * @return $this
  251. */
  252. public function setRequestData(array $data): self
  253. {
  254. Request::merge($data);
  255. return $this;
  256. }
  257. /**
  258. * 获取集合(表)信息.
  259. */
  260. public function getAssembleInfo(): void
  261. {
  262. $assembleInfo = DB::table('sys_assemble')->find($this->interfaceInfo['assemble_id']);
  263. $this->assembleInfo = get_object_vars($assembleInfo);
  264. $this->table = $this->assembleInfo['schema'];
  265. }
  266. /**
  267. * 获取表对应的字段列表,支持扩展表.
  268. *
  269. * @return void
  270. */
  271. public function getAssembleColumn(): void
  272. {
  273. $assembleInfo = DB::table('sys_assemble_column')->where('assemble_id', $this->interfaceInfo['assemble_id'])->where('is_delete', 0)->get();
  274. $this->assembleColumns = array_map('get_object_vars', $assembleInfo->toArray());
  275. // id 和 字段 组成的数组
  276. $idArr = array_column($this->assembleColumns, 'id');
  277. $codeArr = array_column($this->assembleColumns, 'code');
  278. $this->columnIdToCodes = array_combine($idArr, $codeArr);
  279. }
  280. /**
  281. * @throws \Exception
  282. */
  283. public function exec(): JsonResponse|null
  284. {
  285. if (1 == $this->interfaceInfo['category_type']) {
  286. return $this->interfaceSysExec();
  287. } else {
  288. return $this->interfaceCustomExec();
  289. }
  290. }
  291. /**
  292. * 系统接口.
  293. *
  294. * @throws \Exception
  295. */
  296. public function interfaceSysExec(): JsonResponse
  297. {
  298. $manager = new DbManager($this->interfaceInfo, $this->assembleInfo, $this->assembleColumns, $this->requestData, $this->columnIdToCodes);
  299. return $this->manageResult($manager->exec());
  300. }
  301. // 混合接口
  302. public function interfaceCustomExec(): JsonResponse|null
  303. {
  304. $conditionsArr = $this->interfaceInfo['conditions'];
  305. if ($conditionsArr) {
  306. $allData = $this->requestData;
  307. $this->execResult($conditionsArr, $allData);
  308. // 如果有执行失败的返回错误
  309. foreach ($this->execResultArr as $exeItem) {
  310. // 1 错误继续 2 错误退出 3 直接退出
  311. $back_type = $exeItem['back_type'];
  312. if (2 == $back_type) {
  313. if ($exeItem['error']) {
  314. return responseMessage($exeItem['result']['code'], $exeItem['result']['msg'] ?? "系统错误");
  315. }
  316. } elseif ($back_type == 3) {
  317. return responseMessage($exeItem['result']['code'], $exeItem['result']['msg'] ?? "系统错误", $exeItem['result']);
  318. }
  319. }
  320. // 处理参数返回的结果
  321. if ($backR = $this->exeRequestManage($exeItem, 'backRe')) {
  322. return responseMessage(3001, $backR);
  323. }
  324. }
  325. // 如果设置了返回值,则使用返回值
  326. if ($this->requestData['backRe']) {
  327. $result = $this->requestData['backRe'];
  328. return responseMessage(1001, '', $result);
  329. } else {
  330. return null;
  331. }
  332. }
  333. /**
  334. * 结果集,操作并返回.
  335. */
  336. public function manageResult(mixed $result): JsonResponse
  337. {
  338. if ($result instanceof JsonResponse) {
  339. return $result;
  340. }
  341. $resultInfo = $this->interfaceResultInfo;
  342. if (empty($resultInfo)) {
  343. return responseMessage(1001, '恭喜你,操作成功!', $result);
  344. }
  345. $operateType = $this->interfaceInfo['operate_type'];
  346. if (1 === $operateType) {
  347. // 关联查询
  348. if ($resultInfo['is_use_relate'] && $resultInfo['relate_interfaces']) {
  349. foreach ($resultInfo['relate_interfaces'] as $relate) {
  350. $search_type = $this->interfaceInfo['search_type'];
  351. if (1 === $search_type) { // 单条信息查询
  352. $result = $this->getChildrenInterfaceResult($result, $relate);
  353. } elseif (2 === $search_type) { // 分页查询
  354. foreach ($result['list'] as $key => $row) {
  355. $row = is_array($row) ? $row : get_object_vars($row);
  356. $result['list'][$key] = $this->getChildrenInterfaceResult($row, $relate);
  357. }
  358. } elseif (3 === $search_type) { // 列表
  359. foreach ($result as $key => $row) {
  360. $row = is_array($row) ? $row : get_object_vars($row);
  361. $result[$key] = $this->getChildrenInterfaceResult($row, $relate);
  362. }
  363. }
  364. }
  365. }
  366. }
  367. if ($result || 0 === $result || [] === $result) {
  368. // 成功的操作
  369. if (2 == $resultInfo['success']['type']) { // 有操作
  370. $conditionsArr = $resultInfo['success']['conditions'];
  371. $allData = array_merge($this->requestData, ['&result' => $result]);
  372. if ($conditionsArr) {
  373. $this->execResult($conditionsArr, $allData);
  374. // 如果有执行失败的返回错误
  375. foreach ($this->execResultArr as $exeItem) {
  376. // 1 错误继续 2 错误退出 3 直接退出
  377. $back_type = $exeItem['back_type'];
  378. if (2 == $back_type) {
  379. if ($exeItem['error']) {
  380. return responseMessage($exeItem['result']['code'], $exeItem['result']['msg'] ?? "系统错误");
  381. }
  382. } elseif ($back_type == 3) {
  383. return responseMessage($exeItem['result']['code'], $exeItem['result']['msg'] ?? "系统错误", $exeItem['result']['result']);
  384. }
  385. }
  386. // 处理参数返回的结果
  387. if ($backR = $this->exeRequestManage($resultInfo['success'], 'backRe')) {
  388. return responseMessage(3001, $backR);
  389. }
  390. }
  391. }
  392. /*
  393. * 如果查询详情,直接返回字段值
  394. * 为了方便设置参数的时候,可以直接使用返回值
  395. */
  396. if (1 == $operateType && 1 == $this->interfaceInfo['search_type']) {
  397. if (isset($resultInfo['column_only_one']) && $resultInfo['column_only_one']) {
  398. $column_id = $resultInfo['columns'];
  399. $columnName = $this->columnIdToCodes[$column_id];
  400. $result = $result[$columnName] ?? null;
  401. }
  402. }
  403. // 如果设置了返回值,则使用返回值, 不能判断返回值是否为空
  404. $result = $this->requestData['backRe'] ?? $result;
  405. return responseMessage(1001, $resultInfo['success']['msg'], $result);
  406. } else {
  407. // 失败的操作
  408. if (2 == $resultInfo['failed']['type']) { // 有操作
  409. $conditionsArr = $resultInfo['failed']['conditions'];
  410. $allData = array_merge($this->requestData, ['&result' => $result]);
  411. if ($conditionsArr) {
  412. $this->execResult($conditionsArr, $allData);
  413. // 如果有执行失败的返回错误
  414. foreach ($this->execResultArr as $exeItem) {
  415. // 1 错误继续 2 错误退出 3 直接退出
  416. $back_type = $exeItem['back_type'];
  417. if (2 == $back_type) {
  418. if ($exeItem['error']) {
  419. return responseMessage($exeItem['result']['code'], $exeItem['result']['msg'] ?? "系统错误");
  420. }
  421. } elseif ($back_type == 3) {
  422. return responseMessage($exeItem['result']['code'], $exeItem['result']['msg'] ?? "系统错误", $exeItem['result']['result']);
  423. }
  424. }
  425. // 处理参数返回的结果
  426. if ($backR = $this->exeRequestManage($resultInfo['failed'], 'backReFailed')) {
  427. return responseMessage(3001, $backR);
  428. }
  429. }
  430. }
  431. return responseMessage(2001, $resultInfo['failed']['msg'], $this->requestData['backReFailed'] ?? '');
  432. }
  433. }
  434. /**
  435. * @param array $conditionsArr
  436. * @param array $allData
  437. * @return void
  438. * @throws \GuzzleHttp\Exception\GuzzleException
  439. */
  440. private function execResult(array $conditionsArr, array $allData)
  441. {
  442. foreach ($conditionsArr as $item) {
  443. if (1 == $item['type']) { // 内容处理
  444. $expressionResult = $this->execManageCon($allData, $item);
  445. $flag_uuid = $expressionResult['flag_uuid'] ?? '';
  446. $this->execResultArr[$flag_uuid] = $expressionResult;
  447. $this->requestData[$flag_uuid] = $expressionResult['result']['result'] ?? []; // 返回的的是 backJson() [error=>0,code=>0,result=>[]]
  448. // 1 错误继续 2 错误退出 3 直接退出
  449. $back_type = $expressionResult['back_type'];
  450. if (2 == $back_type) {
  451. if ($expressionResult['error']) {
  452. break;
  453. }
  454. } elseif ($back_type == 3) {
  455. break;
  456. }
  457. } elseif (2 == $item['type']) { // 判断条件
  458. $this->checkExpression('result_type', $allData, $item['condition']);
  459. }
  460. }
  461. }
  462. // ######################################################################
  463. /**
  464. * 执行参数,判断参数的真假.
  465. *
  466. * @param string $searchOrResultType 判断是搜索内容处理,还是结果集内容管理
  467. *
  468. * @throws \GuzzleHttp\Exception\GuzzleException
  469. */
  470. private function checkExpression(string $searchOrResultType, array $data, array $condition, $find = null)
  471. {
  472. // if else 转换为代码执行
  473. foreach ($condition as $judge) {
  474. // 参数
  475. $paramsArr = $judge['params'];
  476. $resultBool = $parentCurrent = true;
  477. foreach ($paramsArr as $key => $row) {
  478. if (0 == $key) {
  479. $resultBool = $parentCurrent = $this->execExpression($data, $row);
  480. } else {
  481. if ('and' == $row['type']) {
  482. if (true === $parentCurrent) {
  483. $resultBool = $parentCurrent = $this->execExpression($data, $row);
  484. } else {
  485. $resultBool = false;
  486. break;
  487. }
  488. } elseif ('or' == $row['type']) {
  489. if (true === $parentCurrent) {
  490. $resultBool = true;
  491. break;
  492. } else {
  493. $resultBool = $parentCurrent = $this->execExpression($data, $row);
  494. }
  495. }
  496. }
  497. }
  498. if ($resultBool) { // 为真,执行内容
  499. $manageCon = $judge['manageCon'];
  500. foreach ($manageCon as $con) {
  501. $expressionResult = $this->execManageCon($data, $con);
  502. // 根据返回类型判断,有的需要直接返回,不再继续向下执行
  503. // 1 错误继续 2 错误退出 3 直接退出
  504. $back_type = $expressionResult['back_type'];
  505. $backResult = $expressionResult['result'] ?? [];
  506. $flag_uuid = $expressionResult['flag_uuid'] ?? '';
  507. $this->execResultArr[$flag_uuid] = $expressionResult;
  508. $this->requestData[$flag_uuid] = $backResult['result'];
  509. if (2 == $back_type) {
  510. if ($expressionResult['error']) { // 如果出现错误,则返回错误信息
  511. return $backResult;
  512. }
  513. } elseif (3 == $back_type) {
  514. break;
  515. }
  516. }
  517. // 停止条件语句
  518. break;
  519. }
  520. }
  521. }
  522. /**
  523. * 执行函数或表达式.
  524. */
  525. private function execExpression(array $data, array $row): bool
  526. {
  527. $operate = $row['operate'];
  528. if ($row['isUseFn']) { // 使用函数
  529. $fnName = $row['fnName'];
  530. $fnParams = $row['fnParams'];
  531. // 如果存在! 则先截取出来
  532. preg_match('/^(!*)(.*)/', $fnName, $fnArr);
  533. $flag = $fnArr[1];
  534. $fnName = $fnArr[2];
  535. foreach ($fnParams as $requestColumn) {
  536. $val = Arr::get($data, $requestColumn);
  537. if ($val) {
  538. $fParams[] = $val;
  539. } else {
  540. $fParams[] = $requestColumn;
  541. }
  542. }
  543. $result = $this->execFunc($fnName, $fParams);
  544. if ($result) {
  545. $current = true;
  546. } else {
  547. $current = false;
  548. }
  549. // ! 非操作符
  550. if ($flag) {
  551. if (1 == \strlen($flag) % 2) {
  552. $current = !$current;
  553. }
  554. }
  555. } else { // 表达式
  556. $requestVal = Arr::get($data, $row['params']);
  557. if ($requestVal || 0 === $requestVal || true === $requestVal || false === $requestVal) {
  558. $current = $this->getOperateResult($requestVal, $operate, $row['value']);
  559. } else {
  560. $current = false;
  561. }
  562. }
  563. return $current;
  564. }
  565. /**
  566. * 操作符的操作结果.
  567. */
  568. private function getOperateResult(mixed $requestVal, string $operate, mixed $value): bool
  569. {
  570. return match ($operate) {
  571. 'true' => true == $requestVal,
  572. 'false' => false == $requestVal,
  573. '==' => $requestVal == $value,
  574. '>' => $requestVal > $value,
  575. '<' => $requestVal < $value,
  576. '>=' => $requestVal >= $value,
  577. '<=' => $requestVal <= $value,
  578. '!=' => $requestVal != $value,
  579. '===' => $requestVal === $value,
  580. '!==' => $requestVal !== $value,
  581. 'in' => \in_array($value, $requestVal),
  582. default => false,
  583. };
  584. }
  585. /**
  586. * 普通查询处理.
  587. *
  588. * @throws \GuzzleHttp\Exception\GuzzleException
  589. */
  590. private function execManageCon(array $data, array $con): array|null
  591. {
  592. $success_code = (isset($con['success_code']) && $con['success_code']) ? $con['success_code'] : 1001;
  593. $success_msg = (isset($con['success_msg']) && $con['success_msg']) ? $con['success_msg'] : '恭喜你,操作成功!';
  594. $failed_code = (isset($con['failed_code']) && $con['failed_code']) ? $con['failed_code'] : 2001;
  595. $failed_msg = (isset($con['failed_msg']) && $con['failed_msg']) ? $con['failed_msg'] : '操作失败,请稍后再试!';
  596. // 返回类型为5,直接返回,终止执行
  597. if (5 == $con['back_type']) {
  598. $backResult = backJson($failed_code, $failed_msg);
  599. return ['error' => false, 'back_type' => $con['back_type'], 'result' => $backResult];
  600. }
  601. $requestParams = [];
  602. if (isset($con['column']) && $con['column']) {
  603. foreach ($con['column'] as $requestColumn) {
  604. // 允许设置请求别名
  605. $paramArr = explode(':', $requestColumn);
  606. $column = $paramArr[0];
  607. $requestColumn = $paramArr[1] ?? $column;
  608. $val = Arr::get($data, $column);
  609. $requestParams[$requestColumn] = $val;
  610. }
  611. }
  612. $param_type = $con['param_type']; // 1 接口 2 函数 3 自定义接口
  613. if (1 == $param_type) { // 接口
  614. if (empty($con['interface_id'])) { // 不允许参数为空
  615. abort(508, '结果集设置错误!- 接口地址不存在!');
  616. }
  617. $result = $this->execInterface($con['interface_id'], $requestParams);
  618. } elseif (2 == $param_type) { // 函数
  619. if (empty($con['fnName'])) { // 不允许参数为空
  620. abort(508, '结果集设置错误!- 系统函数或方法不存在!');
  621. }
  622. $result = $this->execFunc($con['fnName'], array_values($requestParams));
  623. } elseif (3 == $param_type) { // 自定义接口
  624. if (empty($con['url'])) { // 不允许参数为空
  625. abort(508, '结果集设置错误!- 系统函数或方法不存在!');
  626. }
  627. // todo 可以在前端添加一个client请求设置菜单,可以设置微信支付接口,支付宝接口,百度网盘接口等等
  628. $url = $con['url'];
  629. $method = 'POST';
  630. $options = [
  631. 'json' => $requestParams,
  632. 'timeout' => 60,
  633. 'verify' => false,
  634. ];
  635. if (!Str::startsWith($url, 'http')) {
  636. if (Str::contains($url, '/')) {
  637. $url = secure_url($url);
  638. } else {
  639. // 路由名生成一个 URL
  640. $url = route($url);
  641. }
  642. }
  643. $client = new Client();
  644. $result = $client->request($method, $url, $options);
  645. }
  646. if ($result instanceof JsonResponse) {
  647. $backResult = json_decode($result->getContent(), true);
  648. return ['error' => $backResult['error'], 'back_type' => $con['back_type'], 'flag_uuid' => $con['flag_uuid'] ?? '', 'result' => $backResult];
  649. } elseif (empty($result) || (isset($result['error']) && $result['error'])) {
  650. $backResult = backJson($result['code'] ?? $failed_code, $result['msg'] ?? $failed_msg);
  651. return ['error' => true, 'back_type' => $con['back_type'], 'result' => $backResult];
  652. } else {
  653. $backResult = backJson($success_code, $success_msg, isset($result['error']) ? $result['result'] : $result);
  654. return ['error' => false, 'back_type' => $con['back_type'], 'flag_uuid' => $con['flag_uuid'] ?? '', 'result' => $backResult];
  655. }
  656. }
  657. /**
  658. * 执行函数.
  659. */
  660. private function execFunc(string $function, array $params = []): mixed
  661. {
  662. if (empty($function)) {
  663. abort(508, '结果集设置错误!- 函数为空');
  664. }
  665. if (($flag1 = Str::contains($function, '@')) || Str::contains($function, '::')) {
  666. $arr = explode($flag1 ? '@' : '::', $function);
  667. $class = $arr[0] ?? '';
  668. $method = $arr[1] ?? 'handler';
  669. if ($class && class_exists($class)) {
  670. if ($flag1) {
  671. return \call_user_func_array([new $class($this->requestData, $this->interfaceInfo, $this->websiteInfo, $this->assembleInfo, $this->assembleColumns), $method], $params);
  672. } else {
  673. return \call_user_func_array([$class, $method], $params);
  674. }
  675. } else {
  676. abort(508, '接口参数设置错误!- 类【' . $class . '】不存在');
  677. }
  678. } elseif (\function_exists($function)) { // 如果是函数,则使用函数处理,参数:当前字段信息,接口信息,站点信息
  679. return \call_user_func_array($function, $params);
  680. }
  681. return '';
  682. }
  683. /**
  684. * 请求系统接口.
  685. *
  686. * @throws \Exception
  687. */
  688. private function execInterface(int $interfaceId, $requestParams = []): mixed
  689. {
  690. if (empty($interfaceId)) {
  691. abort(508, '结果集设置错误!- 设置的接口为空!');
  692. }
  693. // 获取接口信息
  694. $otherInterfaceInfo = DB::table('dep_interface')->find($interfaceId);
  695. if ($otherInterfaceInfo) {
  696. $interfaceService = new static($otherInterfaceInfo->en_alias, $this->websiteInfo);
  697. $interfaceService->setRequestData($requestParams); // 设置参数
  698. $errorMsg = $interfaceService->validator();
  699. if ($errorMsg) {
  700. abort(508, '结果集设置错误!- ' . $otherInterfaceInfo->en_alias . $errorMsg);
  701. } else {
  702. $response = $interfaceService->exec();
  703. return json_decode($response->getContent(), true);
  704. }
  705. } else {
  706. abort(508, '结果集设置错误!- 设置的接口不存在');
  707. }
  708. }
  709. /**
  710. * 获取字段关联的接口返回的数据.
  711. *
  712. * @throws \Exception
  713. */
  714. private function getChildrenInterfaceResult(array $row, array $relateInfo): mixed
  715. {
  716. $data = array_merge($this->requestData, ['&result' => $row]);
  717. $relateInterfaceId = $relateInfo['interface_id'] ?? '';
  718. if ($relateInterfaceId) {
  719. // 获取接口信息
  720. $interfaceInfo = DB::table('dep_interface')->find($relateInterfaceId);
  721. $interfaceAlias = $interfaceInfo->en_alias;
  722. // 参数设置
  723. $requestParams = [];
  724. foreach ($relateInfo['params'] as $item) {
  725. // 允许设置请求别名
  726. $paramArr = explode(':', $item);
  727. $column = $paramArr[0];
  728. $requestColumn = $paramArr[1] ?? $column;
  729. $val = Arr::get($data, $column);
  730. //如果没有设置别名,则正则替换 result 为 result_
  731. $requestColumn = preg_replace('/&result\./', 'result_', $requestColumn);
  732. $requestParams[$requestColumn] = $val;
  733. }
  734. // 请求接口
  735. $interfaceService = new static($interfaceAlias, $this->websiteInfo);
  736. $interfaceService->setRequestData($requestParams); // 优点,不会干扰现有的数据,除了固定参数外,其他参数允许接收,如果和固定参数有相同的key,则被覆盖
  737. $errorMsg = $interfaceService->validator();
  738. if ($errorMsg) {
  739. // 为了不干扰原有字段
  740. $row[$relateInfo['column']] = "error_" . $errorMsg;
  741. } else {
  742. $response = $interfaceService->exec();
  743. $data = json_decode($response->getContent(), true);
  744. $row[$relateInfo['column']] = $data['result'] ?? [];
  745. }
  746. }
  747. return $row;
  748. }
  749. /**
  750. * @param $ruleValue
  751. *
  752. * @return mixed
  753. */
  754. private function getRuleClass($ruleValue)
  755. {
  756. $class = ucfirst(Str::camel($ruleValue['rule']));
  757. $class = '\\App\\Rules\\' . $class . 'Rule';
  758. $ruleObj = new $class($this->table, $ruleValue, $this->websiteInfo['en_alias']);
  759. // todo 可以在前端页面,设置自定义规则
  760. if ($ruleObj instanceof EsUniqueRule) {
  761. $operateType = $this->interfaceInfo['operate_type'];
  762. if (2 === $operateType || 3 === $operateType) {
  763. return (new EsUniqueRule($this->table, $ruleValue))->ignore($this->getRequestData('id'));
  764. }
  765. } elseif ($ruleObj instanceof EsExistsRule) {
  766. return new EsExistsRule($this->table, $ruleValue);
  767. }
  768. return $ruleObj;
  769. }
  770. }