SystemConfigServices.php 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\services\system\config;
  12. use app\dao\system\config\SystemConfigDao;
  13. use app\services\agent\AgentManageServices;
  14. use app\services\BaseServices;
  15. use crmeb\exceptions\AdminException;
  16. use crmeb\services\CacheService;
  17. use crmeb\services\FileService;
  18. use crmeb\services\FormBuilder;
  19. use think\facade\Log;
  20. /**
  21. * 系统配置
  22. * Class SystemConfigServices
  23. * @package app\services\system\config
  24. * @method count(array $where = []) 获取指定条件下的count
  25. * @method save(array $data) 保存数据
  26. * @method get(int $id, ?array $field = []) 获取一条数据
  27. * @method update($id, array $data, ?string $key = null) 修改数据
  28. * @method delete(int $id, ?string $key = null) 删除数据
  29. * @method getUploadTypeList(string $configName) 获取上传配置中的上传类型
  30. */
  31. class SystemConfigServices extends BaseServices
  32. {
  33. /**
  34. * 系统配置数据访问层
  35. * @var SystemConfigDao
  36. */
  37. protected $dao;
  38. /**
  39. * form表单句柄
  40. * @var FormBuilder
  41. */
  42. protected $builder;
  43. /**
  44. * 表单数据切割符号
  45. * @var string
  46. */
  47. protected $cuttingStr = '=>';
  48. /**
  49. * 表单提交url
  50. * @var string[]
  51. */
  52. protected $postUrl = [
  53. // 基础配置
  54. 'setting' => [
  55. 'url' => '/setting/config/save_basics',
  56. 'auth' => [],
  57. ],
  58. // 服务配置
  59. 'serve' => [
  60. 'url' => '/serve/sms_config/save_basics',
  61. 'auth' => ['short_letter_switch'],
  62. ],
  63. // 运费配置
  64. 'freight' => [
  65. 'url' => '/freight/config/save_basics',
  66. 'auth' => ['express'],
  67. ],
  68. // 分销配置
  69. 'agent' => [
  70. 'url' => '/agent/config/save_basics',
  71. 'auth' => ['fenxiao'],
  72. ],
  73. // 积分配置
  74. 'marketing' => [
  75. 'url' => '/marketing/integral_config/save_basics',
  76. 'auth' => ['point'],
  77. ]
  78. ];
  79. /**
  80. * 子集控制规则联动控制,新版单个配置可以配置联动,此配置为兼容旧版数据配置,不建议使用
  81. * @var array[]
  82. */
  83. protected $relatedRule = [
  84. 'sign_status' => [
  85. 'son_type' => [
  86. 'sign_mode' => '',
  87. 'sign_remind' => [
  88. 'son_type' => [
  89. 'sign_remind_time' => '',
  90. 'sign_remind_type' => '',
  91. ],
  92. 'show_value' => 1
  93. ],
  94. 'sign_give_point' => '',
  95. 'sign_give_exp' => '',
  96. ],
  97. 'show_value' => 1
  98. ],
  99. 'brokerage_func_status' => [
  100. 'son_type' => [
  101. 'store_brokerage_statu' => [
  102. 'son_type' => ['store_brokerage_price' => ''],
  103. 'show_value' => 3
  104. ],
  105. 'brokerage_bindind' => '',
  106. 'store_brokerage_binding_status' => [
  107. 'son_type' => ['store_brokerage_binding_time' => ''],
  108. 'show_value' => 2
  109. ],
  110. 'spread_banner' => '',
  111. 'brokerage_level' => '',
  112. 'division_status' => '',
  113. 'agent_apply_open' => '',
  114. 'brokerage_window_switch' => '',
  115. ],
  116. 'show_value' => 1
  117. ],
  118. 'brokerage_user_status' => [
  119. 'son_type' => [
  120. 'uni_brokerage_price' => '',
  121. 'day_brokerage_price_upper' => '',
  122. ],
  123. 'show_value' => 1
  124. ],
  125. 'invoice_func_status' => [
  126. 'son_type' => [
  127. 'special_invoice_status' => '',
  128. ],
  129. 'show_value' => 1
  130. ],
  131. 'member_func_status' => [
  132. 'son_type' => [
  133. 'order_give_exp' => '',
  134. 'invite_user_exp' => ''
  135. ],
  136. 'show_value' => 1
  137. ],
  138. 'balance_func_status' => [
  139. 'son_type' => [
  140. 'recharge_attention' => '',
  141. 'recharge_switch' => '',
  142. 'store_user_min_recharge' => '',
  143. ],
  144. 'show_value' => 1
  145. ],
  146. 'pay_wechat_type' => [
  147. 'son_type' => [
  148. 'pay_weixin_key' => '',
  149. ],
  150. 'show_value' => 0
  151. ],
  152. 'pay_wechat_type@' => [
  153. 'son_type' => [
  154. 'pay_weixin_serial_no' => '',
  155. 'v3_transfer_scene_id' => '',
  156. 'pay_weixin_key_v3' => '',
  157. 'v3_pay_public_key' => '',
  158. 'v3_pay_public_pem' => '',
  159. ],
  160. 'show_value' => 1
  161. ],
  162. 'image_watermark_status' => [
  163. 'son_type' => [
  164. 'watermark_type' => [
  165. 'son_type' => [
  166. 'watermark_image' => '',
  167. 'watermark_opacity' => '',
  168. 'watermark_rotate' => '',
  169. ],
  170. 'show_value' => 1
  171. ],
  172. 'watermark_position' => '',
  173. 'watermark_x' => '',
  174. 'watermark_y' => '',
  175. 'watermark_type@' => [
  176. 'son_type' => [
  177. 'watermark_text' => '',
  178. 'watermark_text_size' => '',
  179. 'watermark_text_color' => '',
  180. 'watermark_text_angle' => ''
  181. ],
  182. 'show_value' => 2
  183. ],
  184. ],
  185. 'show_value' => 1
  186. ],
  187. 'customer_type' => [
  188. 'son_type' => [
  189. 'service_feedback' => '',
  190. ],
  191. 'show_value' => 0
  192. ],
  193. 'customer_type#' => [
  194. 'son_type' => [
  195. 'customer_phone' => '',
  196. ],
  197. 'show_value' => 1
  198. ],
  199. 'customer_type@' => [
  200. 'son_type' => [
  201. 'customer_url' => '',
  202. 'customer_corpId' => '',
  203. ],
  204. 'show_value' => 2
  205. ],
  206. 'pay_new_weixin_open' => [
  207. 'son_type' => [
  208. 'pay_new_weixin_mchid' => ''
  209. ],
  210. 'show_value' => 1
  211. ],
  212. 'mer_type' => [
  213. 'son_type' => [
  214. 'pay_sub_merchant_id' => '',
  215. 'sp_appid' => ''
  216. ],
  217. 'show_value' => 1
  218. ],
  219. 'member_card_status' => [
  220. 'son_type' => [
  221. 'member_price_status' => '',
  222. ],
  223. 'show_value' => 1
  224. ],
  225. ];
  226. /**
  227. * SystemConfigServices constructor.
  228. * @param SystemConfigDao $dao
  229. * @param FormBuilder $builder
  230. */
  231. public function __construct(SystemConfigDao $dao, FormBuilder $builder)
  232. {
  233. $this->dao = $dao;
  234. $this->builder = $builder;
  235. }
  236. /**
  237. * 获取单个系统配置
  238. * @param string $configName
  239. * @param null $default
  240. * @return mixed|null
  241. * @throws \ReflectionException
  242. */
  243. public function getConfigValue(string $configName, $default = null)
  244. {
  245. $value = $this->dao->getConfigValue($configName);
  246. return is_null($value) ? $default : json_decode($value, true);
  247. }
  248. /**
  249. * 获取全部配置
  250. * @param array $configName
  251. * @return array
  252. * @throws \ReflectionException
  253. */
  254. public function getConfigAll(array $configName = [])
  255. {
  256. return array_map(function ($item) {
  257. return json_decode($item, true);
  258. }, $this->dao->getConfigAll($configName));
  259. }
  260. /**
  261. * 获取配置列表搜索并分页
  262. * @param array $where
  263. * @return array
  264. * @throws \think\db\exception\DataNotFoundException
  265. * @throws \think\db\exception\DbException
  266. * @throws \think\db\exception\ModelNotFoundException
  267. */
  268. public function getConfigList(array $where)
  269. {
  270. [$page, $limit] = $this->getPageValue();
  271. $list = $this->dao->getConfigList($where, $page, $limit);
  272. $count = $this->dao->count($where);
  273. $tidy_srr = [];
  274. $configTabList = app()->make(SystemConfigTabServices::class)->getColumn([], 'title', 'id');
  275. foreach ($list as &$item) {
  276. $item['value'] = $item['value'] ? (json_decode($item['value'], true) ?: '') : '';
  277. if ($item['type'] == 'radio' || $item['type'] == 'checkbox') {
  278. $item['value'] = $this->getRadioOrCheckboxValueInfo($item['menu_name'], $item['value']);
  279. }
  280. if ($item['type'] == 'upload' && !empty($item['value'])) {
  281. if ($item['upload_type'] == 1 || $item['upload_type'] == 3) {
  282. $item['value'] = [set_file_url($item['value'])];
  283. } elseif ($item['upload_type'] == 2) {
  284. $tempValue = set_file_url($item['value']);
  285. $item['value'] = is_array($tempValue) ? $tempValue : [];
  286. }
  287. if (is_array($item['value']) && !empty($item['value'])) {
  288. foreach ($item['value'] as $key => $value) {
  289. $tidy_srr[$key]['filepath'] = $value;
  290. $tidy_srr[$key]['filename'] = basename($value);
  291. }
  292. $item['value'] = $tidy_srr;
  293. } else {
  294. $item['value'] = [];
  295. }
  296. }
  297. if ($item['level'] == 1) {
  298. $item['link_data'] = $this->getLinkData($item['link_id'], $item['link_value']);
  299. }
  300. $item['config_tab_name'] = $configTabList[$item['config_tab_id']] ?? '';
  301. }
  302. return compact('count', 'list');
  303. }
  304. /**
  305. * 配置列表页获取关联的值,展示:关联配置名称/关联值
  306. * @param $id
  307. * @param $value
  308. * @return string
  309. * @throws \think\db\exception\DataNotFoundException
  310. * @throws \think\db\exception\DbException
  311. * @throws \think\db\exception\ModelNotFoundException
  312. * @author wuhaotian
  313. * @email 442384644@qq.com
  314. * @date 2024/5/31
  315. */
  316. private function getLinkData($id, $value)
  317. {
  318. $info = $this->dao->get($id);
  319. if (!$info) return '';
  320. $parameter = explode("\n", $info['parameter']);
  321. $result = [];
  322. foreach ($parameter as $item) {
  323. $parts = explode('=>', $item);
  324. $result[$parts[0]] = $parts[1];
  325. }
  326. return $info['info'] . ':' . $result[$value].'(显示)';
  327. }
  328. /**
  329. * 配置列表页获取单选按钮或者多选按钮的显示值
  330. * @param $menu_name
  331. * @param $value
  332. * @return string
  333. * @throws \think\db\exception\DataNotFoundException
  334. * @throws \think\db\exception\ModelNotFoundException
  335. * @throws \think\exception\DbException
  336. */
  337. private function getRadioOrCheckboxValueInfo(string $menu_name, $value): string
  338. {
  339. $option = [];
  340. $config_one = $this->dao->getOne(['menu_name' => $menu_name]);
  341. if (!$config_one) {
  342. return '';
  343. }
  344. $parameter = explode("\n", $config_one['parameter']);
  345. foreach ($parameter as $k => $v) {
  346. if (isset($v) && strlen($v) > 0) {
  347. $data = explode('=>', $v);
  348. $option[$data[0]] = $data[1];
  349. }
  350. }
  351. $str = '';
  352. if (is_array($value)) {
  353. foreach ($value as $v) {
  354. $str .= $option[$v] . ',';
  355. }
  356. } else {
  357. $str .= !empty($value) ? $option[$value] ?? '' : $option[0] ?? '';
  358. }
  359. return $str;
  360. }
  361. /**
  362. * 根据配置tab id获取系统配置信息
  363. * @param int $tabId
  364. * @return array
  365. * @throws \think\db\exception\DataNotFoundException
  366. * @throws \think\db\exception\DbException
  367. * @throws \think\db\exception\ModelNotFoundException
  368. */
  369. public function getReadList(int $tabId)
  370. {
  371. $info = $this->dao->getConfigTabAllList($tabId);
  372. foreach ($info as $k => $v) {
  373. if (!is_null(json_decode($v['value'])))
  374. $info[$k]['value'] = json_decode($v['value'], true);
  375. if ($v['type'] == 'upload' && !empty($v['value'])) {
  376. if ($v['upload_type'] == 1 || $v['upload_type'] == 3) $info[$k]['value'] = explode(',', $v['value']);
  377. }
  378. }
  379. return $info;
  380. }
  381. /**
  382. * 修改字段获取form表单
  383. * @param int $id
  384. * @return array
  385. * @throws \FormBuilder\Exception\FormBuilderException
  386. * @throws \think\db\exception\DataNotFoundException
  387. * @throws \think\db\exception\DbException
  388. * @throws \think\db\exception\ModelNotFoundException
  389. */
  390. public function editFieldForm(int $id)
  391. {
  392. $menu = $this->dao->get($id)->getData();
  393. if (!$menu) {
  394. throw new AdminException('数据不存在');
  395. }
  396. /** @var SystemConfigTabServices $service */
  397. $service = app()->make(SystemConfigTabServices::class);
  398. $formbuider = [];
  399. $linkData = $this->linkData($menu['config_tab_id']);
  400. $formbuider[] = $this->builder->radio('level', '联动显示', $menu['level'])->options([['value' => 0, 'label' => '否'], ['value' => 1, 'label' => '是']])->appendRule('suffix', [
  401. 'type' => 'div',
  402. 'class' => 'tips-info',
  403. 'domProps' => ['innerHTML' => '否:默认正常展示此配置;是:此配置默认隐藏,当选中下方对应配置的值时,此配置才会显示']
  404. ])->appendControl(1, [
  405. $this->builder->cascader('link_data', '关联配置/值', [$menu['link_id'], $menu['link_value']])->options($linkData)->props(['props' => ['multiple' => false, 'checkStrictly' => false, 'emitPath' => true]])->style(['width' => '100%']),
  406. ])->requiredNum();
  407. $formbuider[] = $this->builder->input('menu_name', '字段变量', $menu['menu_name'])->disabled(1);
  408. $formbuider[] = $this->builder->hidden('type', $menu['type']);
  409. [$configTabList, $data] = $service->getConfigTabListForm((int)($menu['config_tab_id'] ?? 0));
  410. $formbuider[] = $this->builder->cascader('config_tab_id', '分类', $data)->options($configTabList)->filterable(true)->props(['props' => ['multiple' => false, 'checkStrictly' => true, 'emitPath' => true]])->style(['width' => '100%']);
  411. $formbuider[] = $this->builder->input('info', '配置名称', $menu['info'])->required('配置名称不能为空')->autofocus(1);
  412. $formbuider[] = $this->builder->input('desc', '配置简介', $menu['desc']);
  413. switch ($menu['type']) {
  414. case 'text':
  415. $menu['value'] = json_decode($menu['value'], true);
  416. $formbuider[] = $this->createTextInputTypeForm($menu, true);
  417. break;
  418. case 'textarea':
  419. $menu['value'] = json_decode($menu['value'], true);
  420. $formbuider[] = $this->builder->textarea('value', '默认值', $menu['value'])->rows(3);
  421. $formbuider[] = $this->builder->number('width', '文本框宽', (int)$menu['width'])->min(1)->max(24);
  422. $formbuider[] = $this->builder->number('high', '多行文本框高', (int)$menu['high'])->min(1);
  423. break;
  424. case 'radio':
  425. $formbuider = array_merge($formbuider, $this->createRadioForm($menu));
  426. $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'] ?? '')->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色");
  427. break;
  428. case 'upload':
  429. $formbuider = array_merge($formbuider, $this->createUploadForm((int)$menu['upload_type'], $menu, true));
  430. break;
  431. case 'checkbox':
  432. $menu['label'] = '默认值';
  433. $formbuider = array_merge($formbuider, $this->createCheckboxForm($menu));
  434. $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'] ?? '')->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色");
  435. break;
  436. case 'select':
  437. $formbuider = array_merge($formbuider, $this->createSelectForm($menu));
  438. $formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'] ?? '')->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色");
  439. break;
  440. case 'switch':
  441. $formbuider = array_merge($formbuider, $this->createSwitchForm($menu));
  442. break;
  443. }
  444. // 是否必填(支持JSON格式)
  445. $requiredData = json_decode($menu['required'], true);
  446. if ($requiredData && isset($requiredData['required'])) {
  447. $menu['required'] = $requiredData['required'] ? 1 : 0;
  448. } else {
  449. $menu['required'] = $menu['required'] ? 1 : 0;
  450. }
  451. // 非switch类型,添加是否必填字段
  452. if ($menu['type'] != 'switch') {
  453. $formbuider[] = $this->builder->radio('required', '是否必填', $menu['required'] ?? 0)->options([
  454. ['value' => 0, 'label' => '否'],
  455. ['value' => 1, 'label' => '是'],
  456. ])->requiredNum();
  457. }
  458. $formbuider[] = $this->builder->number('sort', '排序', (int)$menu['sort']);
  459. $formbuider[] = $this->builder->radio('status', '状态', $menu['status'] ?? 0)->options([
  460. ['value' => 1, 'label' => '显示'],
  461. ['value' => 0, 'label' => '隐藏'],
  462. ])->requiredNum();
  463. return create_form('编辑字段', $formbuider, $this->url('/setting/config/' . $id), 'PUT');
  464. }
  465. /**
  466. * 创建和编辑文本类型的输入类型表单
  467. * @param array $data 配置数据
  468. * @param bool $isEdit 是否为编辑模式
  469. * @return BaseForm|BaseForm[]
  470. */
  471. private function createTextInputTypeForm(array $data, bool $isEdit = false)
  472. {
  473. // 拆分必填、格式规则和数字范围(支持JSON格式)
  474. $requiredRules = $data['required'] ?? '';
  475. $requiredData = [];
  476. // 尝试解析JSON格式的验证规则
  477. if ($requiredRules && $requiredData = json_decode($requiredRules, true)) {
  478. $data['required'] = isset($requiredData['required']) && $requiredData['required'] ? 'required:true' : '';
  479. $data['regex'] = $requiredData['regex'] ?? '';
  480. $data['min'] = $requiredData['min'] ?? '';
  481. $data['max'] = $requiredData['max'] ?? '';
  482. } else {
  483. // 兼容旧格式:逗号分隔的字符串格式
  484. $data['required'] = strpos($requiredRules, 'required:true') !== false ? 'required:true' : '';
  485. $data['regex'] = '';
  486. $data['min'] = '';
  487. $data['max'] = '';
  488. // 提取 min 和 max
  489. if (preg_match('/\bmin:(-?\d+)/', $requiredRules, $minMatch)) {
  490. $data['min'] = (int)$minMatch[1];
  491. }
  492. if (preg_match('/\bmax:(-?\d+)/', $requiredRules, $maxMatch)) {
  493. $data['max'] = (int)$maxMatch[1];
  494. }
  495. // 提取正则表达式
  496. if (preg_match('/regex:(\/.+\/[gimsuy]*)/', $requiredRules, $patternMatch)) {
  497. $data['regex'] = $patternMatch[1];
  498. }
  499. }
  500. // 创建输入类型选择器
  501. $inputTypeSelect = $this->builder->select('input_type', '类型', $data['input_type'] ?? 'input')->setOptions([
  502. ['value' => 'input', 'label' => '文本框'],
  503. ['value' => 'number', 'label' => '数字'],
  504. ['value' => 'dateTime', 'label' => '日期时间'],
  505. ['value' => 'date', 'label' => '日期'],
  506. ['value' => 'time', 'label' => '时间'],
  507. ['value' => 'color', 'label' => '颜色']
  508. ])->required();
  509. // 正则表达式(输入框)
  510. $regexField = $this->builder->input('regex', '表单验证', $data['regex'] ?? '')
  511. ->placeholder('输入正则表达式,如:/^\d+$/')
  512. ->appendRule('suffix', [
  513. 'type' => 'div',
  514. 'class' => 'tips-info',
  515. 'domProps' => ['innerHTML' => '邮箱:/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/<br>手机号:/^1[3-9]\d{9}$/<br>URL:/^https?:\/\/.+/i<br>电话:/^1[3-9]\d{9}$|^0\d{2,3}-\d{7,8}$|^400-\d{3}-\d{3}$/<br>长度:/^.{6,20}$/']
  516. ]);
  517. // 宽度字段
  518. $col = isset($data['width']) && $data['width'] != 0 && $data['width'] >= 4 && $data['width'] <= 24 ? (int)$data['width'] : 13;
  519. $widthField = $this->builder->number('width', '表单框宽', $col)->min(4)->max(24);
  520. // 不同类型的默认值
  521. $inputValue = $data['input_type'] == 'input' ? ($data['value'] ?? '') : '';
  522. $inputValueField = $this->builder->input('value', '默认值', $inputValue);
  523. $numberValue = $data['input_type'] == 'number' ? ($data['value'] ?? '0') : '';
  524. $numberValueField = $this->builder->input('value', '默认值', $numberValue);
  525. $dateTimeValue = $data['input_type'] == 'dateTime' ? ($data['value'] ?? date('Y-m-d H:i:s')) : '';
  526. $dateTimeValueField = $this->builder->dateTime('value', '默认值', $dateTimeValue);
  527. $dateValue = $data['input_type'] == 'date' ? ($data['value'] ?? date('Y-m-d')) : '';
  528. $dateValueField = $this->builder->date('value', '默认值', $dateValue);
  529. $timeValue = $data['input_type'] == 'time' ? ($data['value'] ?? date('H:i:s')) : '';
  530. $timeValueField = $this->builder->time('value', '默认值', $timeValue);
  531. $colorValue = $data['input_type'] == 'color' ? ($data['value'] ?? '#000000') : '#000000';
  532. $colorValueField = $this->builder->color('value', '默认值', $colorValue);
  533. // 数字类型的最小值和最大值
  534. $numberMinField = $this->builder->input('min', '最小值', $data['min'] ?? '')->type('number');
  535. $numberMaxField = $this->builder->input('max', '最大值', $data['max'] ?? '')->type('number');
  536. // 根据类型联动显示不同的控件
  537. $inputTypeSelect->appendControl('input', [$regexField, $inputValueField, $widthField]);
  538. $inputTypeSelect->appendControl('number', [$numberMinField, $numberMaxField, $numberValueField, $widthField]);
  539. $inputTypeSelect->appendControl('dateTime', [$dateTimeValueField]);
  540. $inputTypeSelect->appendControl('date', [$dateValueField]);
  541. $inputTypeSelect->appendControl('time', [$timeValueField]);
  542. $inputTypeSelect->appendControl('color', [$colorValueField]);
  543. return $inputTypeSelect;
  544. }
  545. /**
  546. * 创建单行表单
  547. * @param string $type
  548. * @param array $data
  549. * @return array
  550. */
  551. public function createTextForm(string $type, array $data)
  552. {
  553. $formbuider = [];
  554. $inputRule = '';
  555. switch ($type) {
  556. case 'number':
  557. // 解析验证规则(支持 JSON 格式)
  558. $requiredRules = $data['required'] ?? '';
  559. $requiredData = json_decode($requiredRules, true);
  560. if ($requiredData) {
  561. // JSON 格式
  562. $data['min'] = $requiredData['min'] ?? null;
  563. $data['max'] = $requiredData['max'] ?? null;
  564. } else {
  565. // 兼容旧格式:提取 min 和 max
  566. $data['min'] = null;
  567. $data['max'] = null;
  568. if (preg_match('/\bmin:(-?\d+)/', $requiredRules, $minMatch)) {
  569. $data['min'] = (int)$minMatch[1];
  570. }
  571. if (preg_match('/\bmax:(-?\d+)/', $requiredRules, $maxMatch)) {
  572. $data['max'] = (int)$maxMatch[1];
  573. }
  574. }
  575. $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : 0;
  576. // 最小值和最大值提示(有值才显示)
  577. $minMaxTip = '';
  578. if (isset($data['min']) && $data['min'] !== null) {
  579. $minMaxTip = '<br>最小值:' . $data['min'];
  580. }
  581. if (isset($data['max']) && $data['max'] !== null) {
  582. $minMaxTip .= ($minMaxTip ? ',' : '<br>') . '最大值:' . $data['max'];
  583. }
  584. // 宽度字段
  585. $col = isset($data['width']) && $data['width'] != 0 && $data['width'] >= 4 && $data['width'] <= 24 ? (int)$data['width'] : 13;
  586. $inputRule = $this->builder->number($data['menu_name'], $data['info'], (float)$data['value'])->controls(false)->appendRule('suffix', [
  587. 'type' => 'div',
  588. 'class' => 'tips-info',
  589. 'domProps' => ['innerHTML' => $data['desc'] . $minMaxTip]
  590. ])->col($col);
  591. break;
  592. case 'dateTime':
  593. $inputRule = $this->builder->dateTime($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  594. 'type' => 'div',
  595. 'class' => 'tips-info',
  596. 'domProps' => ['innerHTML' => $data['desc']]
  597. ]);
  598. break;
  599. case 'date':
  600. $data['value'] = json_decode($data['value'], true) ?: '';
  601. $inputRule = $this->builder->date($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  602. 'type' => 'div',
  603. 'class' => 'tips-info',
  604. 'domProps' => ['innerHTML' => $data['desc']]
  605. ]);
  606. break;
  607. case 'time':
  608. $data['value'] = json_decode($data['value'], true) ?: '';
  609. $inputRule = $this->builder->time($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  610. 'type' => 'div',
  611. 'class' => 'tips-info',
  612. 'domProps' => ['innerHTML' => $data['desc']]
  613. ]);
  614. break;
  615. case 'color':
  616. $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : '';
  617. $inputRule = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  618. 'type' => 'div',
  619. 'class' => 'tips-info',
  620. 'domProps' => ['innerHTML' => $data['desc']]
  621. ]);
  622. break;
  623. default:
  624. $data['value'] = isset($data['value']) ? json_decode($data['value'], true) : '';
  625. // 如果配置项是api或routine_api,需要添加site_url,并且是只读的
  626. if ($data['menu_name'] == 'api' || $data['menu_name'] == 'routine_api') {
  627. $inputRule = $this->builder->input($data['menu_name'], $data['info'], strpos($data['value'], 'http') === false ? sys_config('site_url') . $data['value'] : $data['value'])->appendRule('suffix', [
  628. 'type' => 'div',
  629. 'class' => 'tips-info',
  630. 'domProps' => ['innerHTML' => $data['desc']]
  631. ])->col($data['width'] ?? 13)->readonly(true);
  632. } else {
  633. // 宽宽度设置
  634. $col = isset($data['width']) && $data['width'] != 0 && $data['width'] >= 4 && $data['width'] <= 24 ? (int)$data['width'] : 13;
  635. $inputRule = $this->builder->input($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  636. 'type' => 'div',
  637. 'class' => 'tips-info',
  638. 'domProps' => ['innerHTML' => $data['desc']]
  639. ])->col($col)->placeholder('请输入'.$data['info']);
  640. }
  641. break;
  642. }
  643. // 是否必填项
  644. $this->isRequired($data['required']) && $inputRule = $inputRule->required($data['info'].'不能为空');
  645. $formbuider[] = $inputRule;
  646. return $formbuider;
  647. }
  648. /**
  649. * 创建多行文本框
  650. * @param array $data
  651. * @return mixed
  652. */
  653. private function createTextareaForm(array $data)
  654. {
  655. $formbuider = [];
  656. $textareaRule = '';
  657. $data['value'] = json_decode($data['value'], true) ?: '';
  658. if ($data['menu_name'] == 'param_filter_data') $data['value'] = base64_decode($data['value']);
  659. // 宽度设置
  660. $col = isset($data['width']) && $data['width'] < 24 && $data['width'] > 4 ? $data['width'] : 13;
  661. $textareaRule = $this->builder->textarea($data['menu_name'], $data['info'], $data['value'])->placeholder($data['desc'])->appendRule('suffix', [
  662. 'type' => 'div',
  663. 'class' => 'tips-info',
  664. 'domProps' => ['innerHTML' => $data['desc']]
  665. ])->rows($data['high'] ?? 6)->col($col);
  666. // 是否必填项
  667. $this->isRequired($data['required']) && $textareaRule = $textareaRule->required($data['info'].'不能为空')->placeholder($data['desc']);
  668. $formbuider[] = $textareaRule;
  669. return $formbuider;
  670. }
  671. /**
  672. * 创建单选表单
  673. * @param array $data
  674. * @param array $control
  675. * @param array $control_two
  676. * @return array
  677. */
  678. private function createRadioForm(array $data, $control = [], $control_two = [], $control_three = [])
  679. {
  680. $formbuider = [];
  681. $value = json_decode($data['value'], true);
  682. $data['value'] = $this->normalizeOptionValue(($value === null || $value === '' || $value === false) ? '0' : $value);
  683. $parameter = explode("\n", $data['parameter']);
  684. $options = [];
  685. if ($parameter) {
  686. foreach ($parameter as $v) {
  687. if (strstr($v, $this->cuttingStr) !== false) {
  688. $pdata = explode($this->cuttingStr, $v, 2);
  689. $options[] = ['label' => trim($pdata[1]), 'value' => $this->normalizeOptionValue($pdata[0])];
  690. }
  691. }
  692. $formbuider[] = $radio = $this->builder->radio($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [
  693. 'type' => 'div',
  694. 'class' => 'tips-info',
  695. 'domProps' => ['innerHTML' => $data['desc']]
  696. ])->appendValidate([
  697. 'required' => true,
  698. 'message' => $data['info'] . '必选项',
  699. 'trigger' => 'change',
  700. ])->col(13);
  701. if ($control) {
  702. $radio->appendControl($data['show_value'] ?? 1, is_array($control) ? $control : [$control]);
  703. }
  704. if ($control_two && isset($data['show_value2'])) {
  705. $radio->appendControl($data['show_value2'] ?? 2, is_array($control_two) ? $control_two : [$control_two]);
  706. }
  707. if ($control_three && isset($data['show_value3'])) {
  708. $radio->appendControl($data['show_value3'] ?? 3, is_array($control_three) ? $control_three : [$control_three]);
  709. }
  710. return $formbuider;
  711. }
  712. }
  713. /**
  714. * 创建上传组件表单
  715. * @param int $type
  716. * @param array $data
  717. * @param bool $showTypeSelect 是否显示上传类型选择器
  718. * @return array
  719. */
  720. private function createUploadForm(int $type, array $data, bool $showTypeSelect = false)
  721. {
  722. $formbuider = [];
  723. // 单图控件
  724. if($type == 1){
  725. $singleDataValue = json_decode($data['value'], true) ?: '';
  726. if ($singleDataValue != '') $singleDataValue = set_file_url($singleDataValue);
  727. } else{
  728. $singleDataValue = '';
  729. }
  730. $singleImageField = $this->builder->frameImage($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name']], true), $singleDataValue)
  731. ->icon('el-icon-picture-outline')->width('950px')->height('560px')->Props(['footer' => false, 'modalTitle' => '预览'])->appendRule('suffix', [
  732. 'type' => 'div',
  733. 'class' => 'tips-info',
  734. 'domProps' => ['innerHTML' => $data['desc'] ?? '']
  735. ])->col(13);
  736. // 多图控件
  737. if($type == 2){
  738. $multiDataValue = json_decode($data['value'], true) ?: [];
  739. if (!empty($multiDataValue)) {
  740. $multiDataValue = set_file_url($multiDataValue);
  741. }
  742. } else{
  743. $multiDataValue = [];
  744. }
  745. $multiImageField = $this->builder->frameImages($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name'], 'type' => 'many', 'maxLength' => 5], true), $multiDataValue)
  746. ->maxLength(5)->icon('el-icon-picture-outline')->width('950px')->height('560px')->Props(['footer' => false, 'modalTitle' => '预览'])
  747. ->appendRule('suffix', [
  748. 'type' => 'div',
  749. 'class' => 'tips-info',
  750. 'domProps' => ['innerHTML' => $data['desc'] ?? '']
  751. ])->col(13);
  752. // 文件控件
  753. if($type == 3){
  754. $fileDataValue = json_decode($data['value'], true) ?: '';
  755. if ($fileDataValue != '') $fileDataValue = set_file_url($fileDataValue);
  756. } else{
  757. $fileDataValue = '';
  758. }
  759. $fileField = $this->builder->uploadFile($data['menu_name'], $data['info'], $this->url('/adminapi/file/upload/1', ['type' => 1], false, true), $fileDataValue)
  760. ->name('file')->appendRule('suffix', [
  761. 'type' => 'div',
  762. 'class' => 'tips-info',
  763. 'domProps' => ['innerHTML' => $data['desc'] ?? '']
  764. ])->col(13)->data(['menu_name' => $data['menu_name']])->headers([
  765. 'Authori-zation' => app()->request->header('Authori-zation'),
  766. ]);
  767. // 如果需要显示类型选择器(编辑模式)
  768. if ($showTypeSelect) {
  769. // 创建上传类型的radio选择器
  770. $uploadTypeSelect = $this->builder->radio('upload_type', '上传类型', $type)->options($this->uploadType());
  771. // 联动:切换类型时显示对应的上传控件
  772. $uploadTypeSelect->appendControl(1, [$singleImageField]);
  773. $uploadTypeSelect->appendControl(2, [$multiImageField]);
  774. $uploadTypeSelect->appendControl(3, [$fileField]);
  775. $uploadRule = $uploadTypeSelect;
  776. } else {
  777. // 新建模式:根据类型只显示对应的上传控件
  778. switch ($type) {
  779. case 1:
  780. // 是否必填项
  781. $this->isRequired($data['required']) && $singleImageField = $singleImageField->appendValidate((new \FormBuilder\UI\Elm\Validate(\FormBuilder\UI\Elm\Validate::TYPE_STRING))->required()->message($data['info'].'请选择图片'));
  782. $uploadRule = $singleImageField;
  783. break;
  784. case 2:
  785. // 是否必填项
  786. $this->isRequired($data['required']) && $multiImageField = $multiImageField->appendValidate((new \FormBuilder\UI\Elm\Validate(\FormBuilder\UI\Elm\Validate::TYPE_ARRAY))->required()->message($data['info'].'请选择图片'));
  787. $uploadRule = $multiImageField;
  788. break;
  789. case 3:
  790. // 是否必填项
  791. $this->isRequired($data['required']) && $fileField = $fileField->appendValidate((new \FormBuilder\UI\Elm\Validate(\FormBuilder\UI\Elm\Validate::TYPE_STRING))->required()->message($data['info'].'请选择文件'));
  792. $uploadRule = $fileField;
  793. break;
  794. }
  795. }
  796. $formbuider[] = $uploadRule;
  797. return $formbuider;
  798. }
  799. /**
  800. * 创建单选框
  801. * @param array $data
  802. * @return array
  803. * @throws \FormBuilder\Exception\FormBuilderException
  804. */
  805. private function createCheckboxForm(array $data)
  806. {
  807. $formbuider = [];
  808. $checkboxRule = null;
  809. $data['value'] = json_decode($data['value'], true) ?: [];
  810. $parameter = explode("\n", $data['parameter']);
  811. $options = [];
  812. if ($parameter) {
  813. foreach ($parameter as $v) {
  814. if (strstr($v, $this->cuttingStr) !== false) {
  815. $pdata = explode($this->cuttingStr, $v);
  816. $options[] = ['label' => $pdata[1], 'value' => $pdata[0]];
  817. }
  818. }
  819. $checkboxRule = $this->builder->checkbox($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [
  820. 'type' => 'div',
  821. 'class' => 'tips-info',
  822. 'domProps' => ['innerHTML' => $data['desc']]
  823. ])->col(13);
  824. }
  825. // 是否必填项
  826. $isRequired = $this->isRequired($data['required']);
  827. if ($isRequired) {
  828. $checkboxRule = $checkboxRule->required($data['info'].'至少选择一个');
  829. }
  830. $formbuider[] = $checkboxRule;
  831. return $formbuider;
  832. }
  833. /**
  834. * 创建选择框表单
  835. * @param array $data
  836. * @return array
  837. * @throws \FormBuilder\Exception\FormBuilderException
  838. */
  839. private function createSelectForm(array $data)
  840. {
  841. $formbuider = [];
  842. $selectRule = null;
  843. $data['value'] = json_decode($data['value'], true) ?: [];
  844. $parameter = explode("\n", $data['parameter']);
  845. $options = [];
  846. if ($parameter) {
  847. foreach ($parameter as $v) {
  848. if (strstr($v, $this->cuttingStr) !== false) {
  849. $pdata = explode($this->cuttingStr, $v);
  850. $options[] = ['label' => $pdata[1], 'value' => $pdata[0]];
  851. }
  852. }
  853. $selectRule = $this->builder->select($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [
  854. 'type' => 'div',
  855. 'class' => 'tips-info',
  856. 'domProps' => ['innerHTML' => $data['desc']]
  857. ])->col(13);
  858. }
  859. // 是否必填项
  860. $this->isRequired($data['required']) && $selectRule = $selectRule->required($data['info'].'请选择');
  861. $formbuider[] = $selectRule;
  862. return $formbuider;
  863. }
  864. /**
  865. * 开关选择
  866. * @param $data
  867. * @return array
  868. * @author: 吴汐
  869. * @email: 442384644@qq.com
  870. * @date: 2023/9/6
  871. */
  872. private function createSwitchForm($data)
  873. {
  874. $formbuider = [];
  875. $switchRule = null;
  876. $data['value'] = json_decode($data['value'], true) ?: '';
  877. $switchRule = $this->builder->switches($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  878. 'type' => 'div',
  879. 'class' => 'tips-info',
  880. 'domProps' => ['innerHTML' => $data['desc']]
  881. ])->required($data['info'].'必选项')->col(13);
  882. $formbuider[] = $switchRule;
  883. return $formbuider;
  884. }
  885. /**
  886. * 创建颜色选择器
  887. * @param array $data
  888. * @return mixed
  889. */
  890. private function createColorForm(array $data)
  891. {
  892. $data['value'] = json_decode($data['value'], true) ?: '';
  893. $formbuider[] = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
  894. 'type' => 'div',
  895. 'class' => 'tips-info',
  896. 'domProps' => ['innerHTML' => $data['desc']]
  897. ])->col(13);
  898. return $formbuider;
  899. }
  900. /**
  901. * 统一配置项选项值类型:普通数字保持数字,字符串编码保持字符串。
  902. *
  903. * @param mixed $value
  904. * @return int|string
  905. */
  906. private function normalizeOptionValue($value)
  907. {
  908. if (is_int($value)) {
  909. return $value;
  910. }
  911. if (is_string($value)) {
  912. $value = trim($value);
  913. if (preg_match('/^-?(0|[1-9]\d*)$/', $value)) {
  914. return (int)$value;
  915. }
  916. }
  917. return $value;
  918. }
  919. /**
  920. * 上传类型
  921. * @return array
  922. */
  923. private function uploadType(): array
  924. {
  925. return [
  926. ['value' => 1, 'label' => '单图']
  927. , ['value' => 2, 'label' => '多图']
  928. , ['value' => 3, 'label' => '文件']
  929. ];
  930. }
  931. /**
  932. * 根据验证规则判断是否必填项
  933. * @param string $required
  934. * @return bool
  935. */
  936. private function isRequired(string $required)
  937. {
  938. // 支持 JSON 格式
  939. $requiredData = json_decode($required, true);
  940. if ($requiredData) {
  941. return isset($requiredData['required']) && $requiredData['required'] ? true : false;
  942. }
  943. // 兼容旧格式:逗号分隔
  944. return strpos($required, 'required:true') !== false;
  945. }
  946. /**
  947. * 获取系统配置表单
  948. * @param $data
  949. * @param bool $control
  950. * @param array $controle_two
  951. * @return array
  952. * @throws \FormBuilder\Exception\FormBuilderException
  953. */
  954. public function formTypeShine($data, $control = false, $controle_two = [], $controle_three = [])
  955. {
  956. switch ($data['type']) {
  957. case 'text'://文本框
  958. return $this->createTextForm($data['input_type'], $data);
  959. case 'radio'://单选框
  960. return $this->createRadioForm($data, $control, $controle_two, $controle_three);
  961. case 'textarea'://多行文本框
  962. return $this->createTextareaForm($data);
  963. case 'upload'://文件上传
  964. return $this->createUploadForm((int)$data['upload_type'], $data,false);
  965. case 'checkbox'://多选框
  966. return $this->createCheckboxForm($data);
  967. case 'select'://多选框
  968. return $this->createSelectForm($data);
  969. // case 'color':
  970. // return $this->createColorForm($data);
  971. case 'switch'://开关
  972. return $this->createSwitchForm($data);
  973. }
  974. }
  975. /**
  976. * 根据系统多个配置自动生成form表单页面
  977. * @param array $list
  978. * @return array
  979. * @throws \FormBuilder\Exception\FormBuilderException
  980. * @throws \think\db\exception\DataNotFoundException
  981. * @throws \think\db\exception\DbException
  982. * @throws \think\db\exception\ModelNotFoundException
  983. */
  984. private function createForm(array $list)
  985. {
  986. if (!$list) return [];
  987. $list = array_combine(array_column($list, 'menu_name'), $list);
  988. $formbuider = [];
  989. $sonConfig = $this->getSonConfig();
  990. $sonConfig = array_merge($sonConfig, $this->dao->getColumn(['level' => 1], 'menu_name'));
  991. foreach ($list as $key => $data) {
  992. if (in_array($key, $sonConfig)) {
  993. continue;
  994. }
  995. switch ($data['type']) {
  996. case 'text'://文本框
  997. $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data));
  998. break;
  999. case 'radio'://单选框
  1000. $relateRule = $this->relatedRule;
  1001. $builder = [];
  1002. if (!isset($relateRule[$key])) {
  1003. $relateRule = [];
  1004. $sonData = $this->dao->getColumn(['level' => 1, 'link_id' => $data['id']], 'menu_name,link_value');
  1005. $sonValue = [];
  1006. foreach ($sonData as $sv) {
  1007. $sonValue[$sv['link_value']][] = $sv['menu_name'];
  1008. }
  1009. $i = 0;
  1010. foreach ($sonValue as $pk => $pv) {
  1011. $label = $data['menu_name'];
  1012. if ($i == 1) $label = $data['menu_name'] . '@';
  1013. if ($i == 2) $label = $data['menu_name'] . '#';
  1014. $relateRule[$label]['show_value'] = $this->normalizeOptionValue($pk);
  1015. foreach ($pv as $pvv) {
  1016. $relateRule[$label]['son_type'][$pvv] = '';
  1017. }
  1018. $i++;
  1019. }
  1020. } else {
  1021. $sonData = $this->dao->getColumn(['level' => 1, 'link_id' => $data['id']], 'menu_name,link_value');
  1022. if ($sonData) {
  1023. $sonValue = [];
  1024. foreach ($sonData as $sv) {
  1025. $sonValue[$sv['link_value']][] = $sv['menu_name'];
  1026. }
  1027. $i = 0;
  1028. foreach ($sonValue as $pk => $pv) {
  1029. $label = $data['menu_name'];
  1030. if ($i == 1) $label = $data['menu_name'] . '@';
  1031. if ($i == 2) $label = $data['menu_name'] . '#';
  1032. if (!isset($relateRule[$label])) {
  1033. $relateRule[$label]['show_value'] = $this->normalizeOptionValue($pk);
  1034. }
  1035. foreach ($pv as $pvv) {
  1036. $relateRule[$label]['son_type'][$pvv] = '';
  1037. }
  1038. $i++;
  1039. }
  1040. }
  1041. }
  1042. if (isset($relateRule[$key])) {
  1043. $role = $relateRule[$key];
  1044. $data['show_value'] = $role['show_value'];
  1045. foreach ($role['son_type'] as $sk => $sv) {
  1046. if (isset($list[$sk])) {
  1047. $son_data = $list[$sk];
  1048. $son_data['show_value'] = $role['show_value'];
  1049. $son_build = [];
  1050. if (isset($sv['son_type'])) {
  1051. foreach ($sv['son_type'] as $ssk => $ssv) {
  1052. $son_data['show_value'] = $sv['show_value'];
  1053. $son_build[] = $this->formTypeShine($list[$ssk])[0];
  1054. unset($list[$ssk]);
  1055. }
  1056. }
  1057. $son_build_two = [];
  1058. if (isset($role['son_type'][$sk . '@'])) {
  1059. $son_type_two = $role['son_type'][$sk . '@'];
  1060. $son_data['show_value2'] = $son_type_two['show_value'];
  1061. if (isset($son_type_two['son_type'])) {
  1062. foreach ($son_type_two['son_type'] as $ssk => $ssv) {
  1063. if (isset($list[$ssk]['menu_name']) && $list[$ssk]['menu_name'] == 'watermark_text_color') $list[$ssk]['type'] = 'color';
  1064. $son_build_two[] = $this->formTypeShine($list[$ssk])[0];
  1065. unset($list[$ssk]);
  1066. }
  1067. }
  1068. }
  1069. $son_build_three = [];
  1070. if (isset($role['son_type'][$sk . '#'])) {
  1071. $son_type_three = $role['son_type'][$sk . '#'];
  1072. $son_data['show_value3'] = $son_type_three['show_value'];
  1073. if (isset($son_type_three['son_type'])) {
  1074. foreach ($son_type_three['son_type'] as $ssk => $ssv) {
  1075. if (isset($list[$ssk]['menu_name']) && $list[$ssk]['menu_name'] == 'watermark_text_color') $list[$ssk]['type'] = 'color';
  1076. $son_build_three[] = $this->formTypeShine($list[$ssk])[0];
  1077. unset($list[$ssk]);
  1078. }
  1079. }
  1080. }
  1081. $builder[] = $this->formTypeShine($son_data, $son_build, $son_build_two, $son_build_three)[0];
  1082. unset($list[$sk]);
  1083. }
  1084. }
  1085. $data['show_value'] = $role['show_value'];
  1086. }
  1087. $builder_two = [];
  1088. if (isset($relateRule[$key . '@'])) {
  1089. $role = $relateRule[$key . '@'];
  1090. $data['show_value2'] = $role['show_value'];
  1091. foreach ($role['son_type'] as $sk => $sv) {
  1092. $son_data = $list[$sk];
  1093. $son_data['show_value'] = $role['show_value'];
  1094. $builder_two[] = $this->formTypeShine($son_data)[0];
  1095. }
  1096. }
  1097. $builder_three = [];
  1098. if (isset($relateRule[$key . '#'])) {
  1099. $role = $relateRule[$key . '#'];
  1100. $data['show_value3'] = $role['show_value'];
  1101. foreach ($role['son_type'] as $sk => $sv) {
  1102. $son_data = $list[$sk];
  1103. $son_data['show_value'] = $role['show_value'];
  1104. $builder_three[] = $this->formTypeShine($son_data)[0];
  1105. }
  1106. }
  1107. $formbuider = array_merge($formbuider, $this->createRadioForm($data, $builder, $builder_two, $builder_three));
  1108. break;
  1109. case 'textarea'://多行文本框
  1110. $formbuider = array_merge($formbuider, $this->createTextareaForm($data));
  1111. break;
  1112. case 'upload'://文件上传
  1113. $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data,false));
  1114. break;
  1115. case 'checkbox'://多选框
  1116. $formbuider = array_merge($formbuider, $this->createCheckboxForm($data));
  1117. break;
  1118. case 'select'://多选框
  1119. $formbuider = array_merge($formbuider, $this->createSelectForm($data));
  1120. break;
  1121. case 'switch'://开关
  1122. $formbuider = array_merge($formbuider, $this->createSwitchForm($data));
  1123. break;
  1124. }
  1125. }
  1126. return $formbuider;
  1127. }
  1128. /**
  1129. * 根据关联规则获取获取所有子配置
  1130. * @return array|int[]|string[]
  1131. * @author 吴汐
  1132. * @email 442384644@qq.com
  1133. * @date 2023/04/12
  1134. */
  1135. public function getSonConfig()
  1136. {
  1137. $sonConfig = [];
  1138. $rolateRule = $this->relatedRule;
  1139. if ($rolateRule) {
  1140. foreach ($rolateRule as $key => $value) {
  1141. $sonConfig = array_merge($sonConfig, array_keys($value['son_type']));
  1142. foreach ($value['son_type'] as $k => $v) {
  1143. if (isset($v['son_type'])) {
  1144. $sonConfig = array_merge($sonConfig, array_keys($v['son_type']));
  1145. }
  1146. }
  1147. }
  1148. }
  1149. return $sonConfig;
  1150. }
  1151. /**无组件绑定规则
  1152. * @param array $list
  1153. * @return array|bool
  1154. * @throws \FormBuilder\Exception\FormBuilderException
  1155. * @throws \think\db\exception\DataNotFoundException
  1156. * @throws \think\db\exception\DbException
  1157. * @throws \think\db\exception\ModelNotFoundException
  1158. */
  1159. public function createNoCrontrolForm(array $list)
  1160. {
  1161. if (!$list) return false;
  1162. $formbuider = [];
  1163. foreach ($list as $key => $data) {
  1164. switch ($data['type']) {
  1165. case 'text'://文本框
  1166. $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data));
  1167. break;
  1168. case 'radio'://单选框
  1169. $formbuider = array_merge($formbuider, $this->createRadioForm($data));
  1170. break;
  1171. case 'textarea'://多行文本框
  1172. $formbuider = array_merge($formbuider, $this->createTextareaForm($data));
  1173. break;
  1174. case 'upload'://文件上传
  1175. $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data, true));
  1176. break;
  1177. case 'checkbox'://多选框
  1178. $formbuider = array_merge($formbuider, $this->createCheckboxForm($data));
  1179. break;
  1180. case 'select'://多选框
  1181. $formbuider = array_merge($formbuider, $this->createSelectForm($data));
  1182. break;
  1183. case 'switch'://开关
  1184. $formbuider = array_merge($formbuider, $this->createSwitchForm($data));
  1185. break;
  1186. }
  1187. }
  1188. return $formbuider;
  1189. }
  1190. /**
  1191. * 有组件绑定规则
  1192. * @param array $list
  1193. * @param array $relatedRule
  1194. * @return array|bool
  1195. * @throws \FormBuilder\Exception\FormBuilderException
  1196. * @throws \think\db\exception\DataNotFoundException
  1197. * @throws \think\db\exception\DbException
  1198. * @throws \think\db\exception\ModelNotFoundException
  1199. */
  1200. public function createBindCrontrolForm(array $list, array $relatedRule)
  1201. {
  1202. if (!$list || !$relatedRule) return false;
  1203. $formbuider = [];
  1204. $new_data = array();
  1205. foreach ($list as $dk => $dv) {
  1206. $new_data[$dv['menu_name']] = $dv;
  1207. }
  1208. foreach ($relatedRule as $rk => $rv) {
  1209. if (isset($rv['son_type'])) {
  1210. $data = $new_data[$rk];
  1211. switch ($data['type']) {
  1212. case 'text'://文本框
  1213. $formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data));
  1214. break;
  1215. case 'radio'://单选框
  1216. $son_builder = array();
  1217. foreach ($rv['son_type'] as $sk => $sv) {
  1218. if (isset($sv['son_type'])) {
  1219. foreach ($sv['son_type'] as $ssk => $ssv) {
  1220. $son_data = $new_data[$sk];
  1221. $son_data['show_value'] = $sv['show_value'];
  1222. $son_builder[] = $this->formTypeShine($son_data, $this->formTypeShine($new_data[$ssk])[0])[0];
  1223. }
  1224. } else {
  1225. $son_data = $new_data[$sk];
  1226. $son_data['show_value'] = $rv['show_value'];
  1227. $son_builder[] = $this->formTypeShine($son_data)[0];
  1228. }
  1229. }
  1230. $formbuider = array_merge($formbuider, $this->createRadioForm($data, $son_builder));
  1231. break;
  1232. case 'textarea'://多行文本框
  1233. $formbuider = array_merge($formbuider, $this->createTextareaForm($data));
  1234. break;
  1235. case 'upload'://文件上传
  1236. $formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data, false));
  1237. break;
  1238. case 'checkbox'://多选框
  1239. $formbuider = array_merge($formbuider, $this->createCheckboxForm($data));
  1240. break;
  1241. case 'select'://多选框
  1242. $formbuider = array_merge($formbuider, $this->createSelectForm($data));
  1243. break;
  1244. case 'switch'://开关
  1245. $formbuider = array_merge($formbuider, $this->createSwitchForm($data));
  1246. break;
  1247. }
  1248. }
  1249. }
  1250. return $formbuider;
  1251. }
  1252. /**
  1253. * 根据tabid获取系统配置form表单创建
  1254. * @param $url
  1255. * @param int $tabId
  1256. * @return array
  1257. * @throws \FormBuilder\Exception\FormBuilderException
  1258. * @throws \think\db\exception\DataNotFoundException
  1259. * @throws \think\db\exception\DbException
  1260. * @throws \think\db\exception\ModelNotFoundException
  1261. */
  1262. public function getConfigForm($url, int $tabId)
  1263. {
  1264. /** @var SystemConfigTabServices $service */
  1265. $service = app()->make(SystemConfigTabServices::class);
  1266. $title = $service->value(['id' => $tabId], 'title');
  1267. $list = $this->dao->getConfigTabAllList($tabId);
  1268. $formbuider = $this->createForm($list);
  1269. $name = 'setting';
  1270. if ($url) {
  1271. $name = explode('/', $url)[2] ?? $name;
  1272. }
  1273. $postUrl = $this->postUrl[$name]['url'] ?? '/setting/config/save_basics';
  1274. return create_form($title, $formbuider, $this->url($postUrl), 'POST');
  1275. }
  1276. /**
  1277. * 新增路由增加设置项验证
  1278. * @param $url
  1279. * @param $post
  1280. * @return bool
  1281. */
  1282. public function checkParam($url, $post)
  1283. {
  1284. $name = '';
  1285. if ($url) {
  1286. $name = explode('/', $url)[2] ?? $name;
  1287. }
  1288. $auth = $this->postUrl[$name]['auth'] ?? false;
  1289. if ($auth === false) {
  1290. throw new AdminException('请求不被允许');
  1291. }
  1292. if ($auth) {
  1293. /** @var SystemConfigTabServices $systemConfigTabServices */
  1294. $systemConfigTabServices = app()->make(SystemConfigTabServices::class);
  1295. foreach ($post as $key => $value) {
  1296. $tab_ids = $systemConfigTabServices->getColumn([['eng_title', 'IN', $auth]], 'id');
  1297. if (!$tab_ids || !in_array($key, $this->dao->getColumn([['config_tab_id', 'IN', $tab_ids]], 'menu_name'))) {
  1298. throw new AdminException('设置类目不被允许');
  1299. }
  1300. }
  1301. }
  1302. return true;
  1303. }
  1304. /**
  1305. * 添加配置字段
  1306. * @param int $type
  1307. * @param int $tab_id
  1308. * @retuarr@throws \FormBuilder\Exception\FormBuilderException
  1309. * @throws \think\db\exception\DataNotFoundException
  1310. * @throws \think\db\exception\DbException
  1311. * @throws \think\db\exception\ModelNotFoundException
  1312. */
  1313. public function addFieldForm(int $type, int $tab_id): array
  1314. {
  1315. /** @var SystemConfigTabServices $service */
  1316. $service = app()->make(SystemConfigTabServices::class);
  1317. $formbuider = [];
  1318. $form_type = '';
  1319. $info_type = [];
  1320. $parameter = [];
  1321. switch ($type) {
  1322. case 0://文本框
  1323. $form_type = 'text';
  1324. $parameter[] = $this->createTextInputTypeForm(['input_type' => 'input']);
  1325. break;
  1326. case 1://多行文本框
  1327. $form_type = 'textarea';
  1328. $parameter[] = $this->builder->textarea('value', '默认值');
  1329. $parameter[] = $this->builder->number('width', '文本框宽', 100);
  1330. $parameter[] = $this->builder->number('high', '多行文本框高', 5);
  1331. break;
  1332. case 2://单选框
  1333. $form_type = 'radio';
  1334. $parameter[] = $this->builder->textarea('parameter', '配置参数', "1=>男\n2=>女\n3=>保密")->rows(3)->placeholder("参数方式例如:\n1=>男\n2=>女\n3=>保密")->required('配置参数不能为空')->appendRule('suffix', [
  1335. 'type' => 'div',
  1336. 'class' => 'tips-info',
  1337. 'domProps' => ['innerHTML' => '参数说明:=>前面是参数值,后面是参数名称,每行一个参数,=>分割符不能换,例如:<br>1=>男<br>2=>女<br>3=>保密']
  1338. ]);
  1339. $parameter[] = $this->builder->input('value', '默认值');
  1340. break;
  1341. case 3://文件上传
  1342. $form_type = 'upload';
  1343. $parameter = array_merge($parameter, $this->createUploadForm(1, ['menu_name' => 'value', 'info' => '默认值', 'value' => ''], true));
  1344. break;
  1345. case 4://多选框
  1346. $form_type = 'checkbox';
  1347. $parameter[] = $this->builder->textarea('parameter', '配置参数', "1=>白色\n2=>红色\n3=>黑色")->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色")->required('配置参数不能为空')->appendRule('suffix', [
  1348. 'type' => 'div',
  1349. 'class' => 'tips-info',
  1350. 'domProps' => ['innerHTML' => '参数说明:=>前面是参数值,后面是参数名称,每行一个参数,=>分割符不能换,例如:<br>1=>白色<br>2=>红色<br>3=>黑色']
  1351. ]);
  1352. break;
  1353. case 5://下拉框
  1354. $form_type = 'select';
  1355. $parameter[] = $this->builder->textarea('parameter', '配置参数', "1=>分类一\n2=>分类二\n3=>分类三")->rows(3)->placeholder("参数方式例如:\n1=>分类一\n2=>分类二\n3=>分类三")->required('配置参数不能为空')->appendRule('suffix', [
  1356. 'type' => 'div',
  1357. 'class' => 'tips-info',
  1358. 'domProps' => ['innerHTML' => '参数说明:=>前面是参数值,后面是参数名称,每行一个参数,=>分割符不能换,例如:<br>1=>分类一<br>2=>分类二<br>3=>分类三']
  1359. ]);
  1360. break;
  1361. case 6://开关
  1362. $form_type = 'switch';
  1363. $parameter[] = $this->builder->switches('value', '默认');
  1364. break;
  1365. }
  1366. if ($form_type) {
  1367. $formbuider[] = $this->builder->hidden('type', $form_type);
  1368. [$configTabList, $data] = $service->getConfigTabListForm((int)($tab_id ?? 0));
  1369. $linkData = $this->linkData($tab_id);
  1370. $formbuider[] = $this->builder->radio('level', '联动显示', 0)->options([['value' => 0, 'label' => '否'], ['value' => 1, 'label' => '是']])->requiredNum()->appendRule('suffix', [
  1371. 'type' => 'div',
  1372. 'class' => 'tips-info',
  1373. 'domProps' => ['innerHTML' => '否:默认正常展示此配置;是:此配置默认隐藏,当选中下方对应配置的值时,此配置才会显示']
  1374. ])->appendControl(1, [
  1375. $this->builder->cascader('link_data', '关联配置/值')->options($linkData)->props(['props' => ['multiple' => false, 'checkStrictly' => false, 'emitPath' => true]])->style(['width' => '100%']),
  1376. ]);
  1377. $formbuider[] = $this->builder->cascader('config_tab_id', '分类', $data)->options($configTabList)->filterable(true)->props(['props' => ['multiple' => false, 'checkStrictly' => true, 'emitPath' => false]])->style(['width' => '100%']);
  1378. if ($info_type) {
  1379. $formbuider[] = $info_type;
  1380. }
  1381. $formbuider[] = $this->builder->input('info', '配置名称')->required('配置名称不能为空')->autofocus(1);
  1382. $formbuider[] = $this->builder->input('menu_name', '字段变量')->required('字段变量不能为空')->placeholder('例如:site_url');
  1383. $formbuider[] = $this->builder->input('desc', '配置简介');
  1384. $formbuider = array_merge($formbuider, $parameter);
  1385. // 是否必填
  1386. if ($form_type != 'switch') {
  1387. $formbuider[] = $this->builder->radio('required', '是否必填', 0)->options([
  1388. ['value' => 0, 'label' => '否'],
  1389. ['value' => 1, 'label' => '是'],
  1390. ])->requiredNum();
  1391. }
  1392. $formbuider[] = $this->builder->number('sort', '排序', 0);
  1393. $formbuider[] = $this->builder->radio('status', '状态', 1)->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']])->requiredNum();
  1394. }
  1395. return create_form('添加字段', $formbuider, $this->url('/setting/config'), 'POST');
  1396. }
  1397. /**
  1398. * 联动选择关联配置/值
  1399. * 根据指定的标签ID,链接数据并以特定格式返回。
  1400. * @param $tab_id
  1401. * @return array
  1402. * @author wuhaotian
  1403. * @email 442384644@qq.com
  1404. * @date 2024/5/30
  1405. */
  1406. public function linkData($tab_id)
  1407. {
  1408. $linkData = $this->selectList(['config_tab_id' => $tab_id, 'type' => 'radio', 'level' => 0], 'info as label,id as value,parameter,sort', 0, 0, 'sort DESC')->toArray();
  1409. foreach ($linkData as &$item) {
  1410. $parameter = [];
  1411. $parameter = explode("\n", $item['parameter']);
  1412. foreach ($parameter as $pv) {
  1413. $pvArr = explode('=>', $pv, 2);
  1414. if (count($pvArr) < 2) {
  1415. continue;
  1416. }
  1417. $item['children'][] = [
  1418. 'label' => trim($pvArr[1]),
  1419. 'value' => $this->normalizeOptionValue($pvArr[0])
  1420. ];
  1421. }
  1422. }
  1423. return $linkData;
  1424. }
  1425. /**
  1426. * radio 和 checkbox规则的判断
  1427. * @param $data
  1428. * @return bool
  1429. */
  1430. public function valiDateRadioAndCheckbox($data)
  1431. {
  1432. $option = [];
  1433. $option_new = [];
  1434. $data['parameter'] = str_replace("\r\n", "\n", $data['parameter']);//防止不兼容
  1435. $parameter = explode("\n", $data['parameter']);
  1436. if (count($parameter) < 2) {
  1437. throw new AdminException('请输入正确格式的配置参数');
  1438. }
  1439. foreach ($parameter as $k => $v) {
  1440. if (isset($v) && !empty($v)) {
  1441. $option[$k] = explode('=>', $v);
  1442. }
  1443. }
  1444. if (count($option) < 2) {
  1445. throw new AdminException('请输入正确格式的配置参数');
  1446. }
  1447. $bool = 1;
  1448. foreach ($option as $k => $v) {
  1449. $option_new[$k] = $option[$k][0];
  1450. foreach ($v as $kk => $vv) {
  1451. $vv_num = strlen($vv);
  1452. if (!$vv_num) {
  1453. $bool = 0;
  1454. }
  1455. }
  1456. }
  1457. if (!$bool) {
  1458. throw new AdminException('请输入正确格式的配置参数');
  1459. }
  1460. $num1 = count($option_new);//提取该数组的数目
  1461. $arr2 = array_unique($option_new);//合并相同的元素
  1462. $num2 = count($arr2);//提取合并后数组个数
  1463. if ($num1 > $num2) {
  1464. throw new AdminException('请输入正确格式的配置参数');
  1465. }
  1466. return true;
  1467. }
  1468. /**
  1469. * 验证参数
  1470. * @param $data
  1471. * @return bool
  1472. */
  1473. public function valiDateValue($data)
  1474. {
  1475. // 检查数据和验证规则是否存在
  1476. if (!$data || !isset($data['required']) || !$data['required']) {
  1477. return true;
  1478. }
  1479. $name = $data['info'] ?? '';
  1480. $value = $data['value'] ?? '';
  1481. // 支持JSON格式的验证规则
  1482. $requiredData = json_decode($data['required'], true);
  1483. if ($requiredData) {
  1484. // JSON格式
  1485. if (isset($requiredData['required']) && $requiredData['required']) {
  1486. if ($value === '' || $value === null) {
  1487. throw new AdminException($name . '不能为空');
  1488. }
  1489. }
  1490. if (isset($requiredData['regex']) && $requiredData['regex']) {
  1491. if ($value && !preg_match($requiredData['regex'], $value)) {
  1492. throw new AdminException($name . '请输入正确的格式');
  1493. }
  1494. }
  1495. if (isset($requiredData['min']) && $value !== '' && $value !== null) {
  1496. if ((float)$value < $requiredData['min']) {
  1497. throw new AdminException($name . '不能小于' . $requiredData['min']);
  1498. }
  1499. }
  1500. if (isset($requiredData['max']) && $value !== '' && $value !== null) {
  1501. if ((float)$value > $requiredData['max']) {
  1502. throw new AdminException($name . '不能大于' . $requiredData['max']);
  1503. }
  1504. }
  1505. } else {
  1506. // 兼容旧格式:逗号分隔的字符串
  1507. $valids = explode(',', $data['required']);
  1508. foreach ($valids as $valid) {
  1509. $valid = explode(':', $valid);
  1510. if (isset($valid[0]) && isset($valid[1])) {
  1511. $k = strtolower(trim($valid[0]));
  1512. $v = strtolower(trim($valid[1]));
  1513. if ($v != 'true') {
  1514. continue;
  1515. }
  1516. switch ($k) {
  1517. case 'required':
  1518. if ($value === '' || $value === null) {
  1519. throw new AdminException($name . '不能为空');
  1520. }
  1521. break;
  1522. case 'regex':
  1523. if ($value && !preg_match($data['regex'], $value)) {
  1524. throw new AdminException($name . '请输入正确的格式');
  1525. }
  1526. break;
  1527. }
  1528. }
  1529. }
  1530. }
  1531. return true;
  1532. }
  1533. /**
  1534. * 保存平台电子面单打印信息
  1535. * @param array $data
  1536. * @return bool
  1537. */
  1538. public function saveExpressInfo(array $data)
  1539. {
  1540. if (!is_array($data) || !$data) return false;
  1541. // config_export_id 快递公司id
  1542. // config_export_temp_id 快递公司模板id
  1543. // config_export_com 快递公司编码
  1544. // config_export_to_name 发货人姓名
  1545. // config_export_to_tel 发货人电话
  1546. // config_export_to_address 发货人详细地址
  1547. // config_export_siid 电子面单打印机编号
  1548. foreach ($data as $key => $value) {
  1549. $this->dao->update(['menu_name' => 'config_export_' . $key], ['value' => json_encode($value)]);
  1550. }
  1551. CacheService::clear();
  1552. return true;
  1553. }
  1554. /**
  1555. * 获取分享海报 兼容方法
  1556. */
  1557. public function getSpreadBanner()
  1558. {
  1559. //配置
  1560. $banner = sys_config('spread_banner', []);
  1561. if (!$banner) {
  1562. //组合数据
  1563. $banner = sys_data('routine_spread_banner');
  1564. if ($banner) {
  1565. $banner = array_column($banner, 'pic');
  1566. $this->dao->update(['menu_name' => 'spread_banner'], ['value' => json_encode($banner)]);
  1567. CacheService::clear();
  1568. }
  1569. }
  1570. return $banner;
  1571. }
  1572. /**
  1573. * 保存wss配置
  1574. * @param int $wssOpen
  1575. * @param string $wssLocalpk
  1576. * @param string $wssLocalCert
  1577. */
  1578. public function saveSslFilePath(int $wssOpen, string $wssLocalpk, string $wssLocalCert)
  1579. {
  1580. $wssFile = root_path() . '.wss';
  1581. $content = <<<WSS
  1582. wssOpen = $wssOpen
  1583. wssLocalpk = $wssLocalpk
  1584. wssLocalCert = $wssLocalCert
  1585. WSS;
  1586. try {
  1587. file_put_contents($wssFile, $content);
  1588. } catch (\Throwable $e) {
  1589. throw new AdminException('保存wss证书失败');
  1590. }
  1591. }
  1592. /**
  1593. * 获取wss配置
  1594. * @param string $key
  1595. * @return array|false|mixed
  1596. */
  1597. public function getSslFilePath(string $key = '')
  1598. {
  1599. $wssFile = root_path() . '.wss';
  1600. try {
  1601. $content = parse_ini_file($wssFile);
  1602. } catch (\Throwable $e) {
  1603. $content = [];
  1604. }
  1605. return $content[$key] ?? $content;
  1606. }
  1607. /**
  1608. * 检测缩略图水印配置是否更改
  1609. * @param array $post
  1610. * @return bool
  1611. */
  1612. public function checkThumbParam(array $post)
  1613. {
  1614. unset($post['upload_type'], $post['image_watermark_status']);
  1615. /** @var SystemConfigTabServices $systemConfigTabServices */
  1616. $systemConfigTabServices = app()->make(SystemConfigTabServices::class);
  1617. //上传配置->基础配置
  1618. $tab_id = $systemConfigTabServices->getColumn(['eng_title' => 'base_config'], 'id');
  1619. if ($tab_id) {
  1620. $all = $this->dao->getColumn(['config_tab_id' => $tab_id], 'value', 'menu_name');
  1621. if (array_intersect(array_keys($all), array_keys($post))) {
  1622. foreach ($post as $key => $item) {
  1623. //配置更改删除原来生成的缩略图
  1624. if (isset($all[$key]) && $item != json_decode($all[$key], true)) {
  1625. try {
  1626. FileService::delDir(public_path('uploads/thumb_water'));
  1627. break;
  1628. } catch (\Throwable $e) {
  1629. }
  1630. }
  1631. }
  1632. }
  1633. }
  1634. return true;
  1635. }
  1636. /**
  1637. * 变更分销绑定关系模式
  1638. * @param array $post
  1639. * @return bool
  1640. */
  1641. public function checkBrokerageBinding(array $post)
  1642. {
  1643. try {
  1644. $config_data = $post['store_brokerage_binding_status'];
  1645. $config_one = $this->dao->getOne(['menu_name' => 'store_brokerage_binding_status']);
  1646. $config_old = json_decode($config_one['value'], true);
  1647. if ($config_old != 2 && $config_data == 2) {
  1648. //自动解绑上级绑定
  1649. /** @var AgentManageServices $agentManage */
  1650. $agentManage = app()->make(AgentManageServices::class);
  1651. $agentManage->resetSpreadTime();
  1652. }
  1653. } catch (\Throwable $e) {
  1654. Log::error('变更分销绑定模式重置绑定时间失败,失败原因:' . $e->getMessage());
  1655. return false;
  1656. }
  1657. return true;
  1658. }
  1659. /** 停用
  1660. * 根据系统配置分类自动生成form表单页面
  1661. * @param int $tabId
  1662. * @param array $formData
  1663. * @param array $relatedRule
  1664. * @return array|bool
  1665. * @throws \think\db\exception\DataNotFoundException
  1666. * @throws \think\db\exception\DbException
  1667. * @throws \think\db\exception\ModelNotFoundException
  1668. */
  1669. public function createConfigForm(int $tabId, array $relatedRule)
  1670. {
  1671. $list = $this->dao->getConfigTabAllList($tabId);
  1672. if (!$relatedRule) {
  1673. $formbuider = $this->createNoCrontrolForm($list);
  1674. } else {
  1675. $formbuider = $this->createBindCrontrolForm($list, $relatedRule);
  1676. }
  1677. return $formbuider;
  1678. }
  1679. /** 停用
  1680. * 绑定表单数据
  1681. * @param $data
  1682. * @param $relatedRule
  1683. * @return array
  1684. */
  1685. private function bindBuilderData($data, $relatedRule)
  1686. {
  1687. if (!$data) return false;
  1688. $p_list = array();
  1689. foreach ($relatedRule as $rk => $rv) {
  1690. $p_list[$rk] = $data[$rk];
  1691. if (isset($rv['son_type']) && is_array($rv['son_type'])) {
  1692. foreach ($rv['son_type'] as $sk => $sv) {
  1693. if (is_array($sv) && isset($sv['son_type'])) {
  1694. foreach ($sv['son_type'] as $ssk => $ssv) {
  1695. $tmp = $data[$sk];
  1696. $tmp['console'] = $data[$ssk];
  1697. $p_list[$rk]['console'][] = $tmp;
  1698. }
  1699. } else {
  1700. $p_list[$rk]['console'][] = $data[$sk];
  1701. }
  1702. }
  1703. }
  1704. }
  1705. return array_values($p_list);
  1706. }
  1707. }