Asset.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. <?php
  2. namespace Dcat\Admin\Layout;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Color;
  5. use Illuminate\Support\Str;
  6. class Asset
  7. {
  8. /**
  9. * 路径别名.
  10. *
  11. * @var array
  12. */
  13. protected $pathAlias = [
  14. // Dcat Admin静态资源路径别名
  15. '@admin' => 'vendors/dcat-admin',
  16. // Dcat Acmin扩展静态资源路径别名
  17. '@extension' => 'vendors/dcat-admin-extensions',
  18. ];
  19. /**
  20. * 别名.
  21. *
  22. * @var array
  23. */
  24. protected $alias = [
  25. '@adminlte' => [
  26. 'js' => [
  27. '@admin/adminlte/adminlte.js',
  28. ],
  29. 'css' => [
  30. '@admin/adminlte/adminlte.css',
  31. ],
  32. ],
  33. '@nunito' => [
  34. 'css' => ['https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,800,800i,900,900i'],
  35. ],
  36. '@montserrat' => [
  37. 'css' => ['https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600'],
  38. ],
  39. '@dcat' => [
  40. 'js' => '@admin/dcat/js/dcat-app.js',
  41. 'css' => '@admin/dcat/css/dcat-app.css',
  42. ],
  43. '@vendors' => [
  44. 'js' => '@admin/dcat/plugins/vendors.min.js',
  45. 'css' => '@admin/dcat/plugins/vendors.min.css',
  46. ],
  47. '@datatables' => [
  48. 'css' => '@admin/dcat/plugins/tables/datatable/datatables.min.css',
  49. ],
  50. '@grid-extension' => [
  51. 'js' => '@admin/dcat/extra/grid-extend.js',
  52. ],
  53. '@resource-selector' => [
  54. 'js' => '@admin/dcat/extra/resource-selector.js',
  55. ],
  56. '@select-table' => [
  57. 'js' => '@admin/dcat/extra/select-table.js',
  58. ],
  59. '@layer' => [
  60. 'js' => '@admin/dcat/plugins/layer/layer.js',
  61. ],
  62. '@tinymce' => [
  63. 'js' => '@admin/dcat/plugins/tinymce/tinymce.min.js',
  64. ],
  65. '@pjax' => [
  66. 'js' => '@admin/dcat/plugins/jquery-pjax/jquery.pjax.min.js',
  67. ],
  68. '@toastr' => [
  69. 'js' => '@admin/dcat/plugins/extensions/toastr.min.js',
  70. 'css' => '@admin/dcat/plugins/extensions/toastr.css',
  71. ],
  72. '@jquery.nestable' => [
  73. 'js' => '@admin/dcat/plugins/nestable/jquery.nestable.min.js',
  74. 'css' => '@admin/dcat/plugins/nestable/nestable.css',
  75. ],
  76. '@validator' => [
  77. 'js' => '@admin/dcat/plugins/bootstrap-validator/validator.min.js',
  78. ],
  79. '@select2' => [
  80. 'js' => '@admin/dcat/plugins/select/select2.full.min.js',
  81. 'css' => '@admin/dcat/plugins/select/select2.min.css',
  82. ],
  83. '@bootstrap-datetimepicker' => [
  84. 'js' => '@admin/dcat/plugins/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js',
  85. 'css' => '@admin/dcat/plugins/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css',
  86. ],
  87. '@moment' => [
  88. 'js' => [
  89. '@admin/dcat/plugins/moment/moment-with-locales.min.js',
  90. ],
  91. ],
  92. '@moment-timezone' => [
  93. 'js' => [
  94. '@admin/dcat/plugins/moment/moment-timezone-with-data.min.js',
  95. ],
  96. ],
  97. '@rwd-table' => [
  98. 'js' => '@admin/dcat/plugins/RWD-Table-Patterns/dist/js/rwd-table.min.js',
  99. 'css' => '@admin/dcat/plugins/RWD-Table-Patterns/dist/css/rwd-table.min.css',
  100. ],
  101. '@jstree' => [
  102. 'js' => '@admin/dcat/plugins/jstree-theme/jstree.min.js',
  103. 'css' => '@admin/dcat/plugins/jstree-theme/themes/proton/style.min.css',
  104. ],
  105. '@switchery' => [
  106. 'js' => '@admin/dcat/plugins/switchery/switchery.min.js',
  107. 'css' => '@admin/dcat/plugins/switchery/switchery.min.css',
  108. ],
  109. '@webuploader' => [
  110. 'js' => [
  111. '@admin/dcat/plugins/webuploader/webuploader.min.js',
  112. '@admin/dcat/extra/upload.js',
  113. ],
  114. 'css' => '@admin/dcat/extra/upload.css',
  115. ],
  116. '@chartjs' => [
  117. 'js' => '@admin/dcat/plugins/chart.js/chart.bundle.min.js',
  118. ],
  119. '@jquery.sparkline' => [
  120. 'js' => '@admin/dcat/plugins/jquery.sparkline/jquery.sparkline.min.js',
  121. ],
  122. '@jquery.bootstrap-duallistbox' => [
  123. 'js' => '@admin/dcat/plugins/bootstrap-duallistbox/dist/jquery.bootstrap-duallistbox.min.js',
  124. 'css' => '@admin/dcat/plugins/bootstrap-duallistbox/dist/bootstrap-duallistbox.min.css',
  125. ],
  126. '@number-input' => [
  127. 'js' => '@admin/dcat/plugins/number-input/bootstrap-number-input.js',
  128. ],
  129. '@ionslider' => [
  130. 'js' => [
  131. '@admin/dcat/plugins/ionslider/ion.rangeSlider.min.js',
  132. ],
  133. 'css' => [
  134. '@admin/dcat/plugins/ionslider/ion.rangeSlider.css',
  135. '@admin/dcat/plugins/ionslider/ion.rangeSlider.skinNice.css',
  136. ],
  137. ],
  138. '@editor-md' => [
  139. 'js' => [
  140. '@admin/dcat/plugins/editor-md/lib/raphael.min.js',
  141. '@admin/dcat/plugins/editor-md/lib/marked.min.js',
  142. '@admin/dcat/plugins/editor-md/lib/prettify.min.js',
  143. '@admin/dcat/plugins/editor-md/lib/underscore.min.js',
  144. '@admin/dcat/plugins/editor-md/lib/sequence-diagram.min.js',
  145. '@admin/dcat/plugins/editor-md/lib/flowchart.min.js',
  146. '@admin/dcat/plugins/editor-md/lib/jquery.flowchart.min.js',
  147. '@admin/dcat/plugins/editor-md/editormd.min.js',
  148. ],
  149. 'css' => [
  150. '@admin/dcat/plugins/editor-md/css/editormd.preview.min.css',
  151. '@admin/dcat/extra/markdown.css',
  152. ],
  153. ],
  154. '@markdown' => [
  155. 'js' => [
  156. '@admin/dcat/plugins/editor-md/lib/raphael.min.js',
  157. '@admin/dcat/plugins/editor-md/editormd.min.js',
  158. ],
  159. 'css' => [
  160. '@admin/dcat/plugins/editor-md/css/editormd.min.css',
  161. ],
  162. ],
  163. '@jquery.inputmask' => [
  164. 'js' => '@admin/dcat/plugins/input-mask/jquery.inputmask.bundle.min.js',
  165. ],
  166. '@apex-charts' => [
  167. 'js' => '@admin/dcat/plugins/charts/apexcharts.min.js',
  168. ],
  169. '@smart-wizard' => [
  170. 'js' => '@admin/dcat/plugins/SmartWizard/dist/js/jquery.smartWizard.min.js',
  171. 'css' => '@admin/dcat/extra/step.css',
  172. ],
  173. '@fontawesome-iconpicker' => [
  174. 'js' => '@admin/dcat/plugins/fontawesome-iconpicker/dist/js/fontawesome-iconpicker.js',
  175. 'css' => '@admin/dcat/plugins/fontawesome-iconpicker/dist/css/fontawesome-iconpicker.min.css',
  176. ],
  177. '@color' => [
  178. 'js' => '@admin/dcat/plugins/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js',
  179. 'css' => '@admin/dcat/plugins/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css',
  180. ],
  181. '@qrcode' => [
  182. 'js' => '@admin/dcat/plugins/jquery-qrcode/dist/jquery-qrcode.min.js',
  183. ],
  184. ];
  185. /**
  186. * js代码.
  187. *
  188. * @var array
  189. */
  190. public $script = [];
  191. /**
  192. * @var array
  193. */
  194. public $directScript = [];
  195. /**
  196. * css代码.
  197. *
  198. * @var array
  199. */
  200. public $style = [];
  201. /**
  202. * css脚本路径.
  203. *
  204. * @var array
  205. */
  206. public $css = [];
  207. /**
  208. * js脚本路径.
  209. *
  210. * @var array
  211. */
  212. public $js = [];
  213. /**
  214. * 在head标签内加载的js脚本.
  215. *
  216. * @var array
  217. */
  218. public $headerJs = [
  219. 'vendors' => '@vendors',
  220. 'dcat' => '@dcat',
  221. ];
  222. /**
  223. * 基础css.
  224. *
  225. * @var array
  226. */
  227. public $baseCss = [
  228. 'adminlte' => '@adminlte',
  229. 'vendors' => '@vendors',
  230. 'toastr' => '@toastr',
  231. 'datatables' => '@datatables',
  232. 'dcat' => '@dcat',
  233. ];
  234. /**
  235. * 基础js.
  236. *
  237. * @var array
  238. */
  239. public $baseJs = [
  240. 'adminlte' => '@adminlte',
  241. 'toastr' => '@toastr',
  242. 'pjax' => '@pjax',
  243. 'validator' => '@validator',
  244. 'layer' => '@layer',
  245. ];
  246. /**
  247. * @var array
  248. */
  249. public $fonts = [
  250. '@nunito',
  251. ];
  252. /**
  253. * @var bool
  254. */
  255. protected $isPjax = false;
  256. /**
  257. * Assets constructor.
  258. */
  259. public function __construct()
  260. {
  261. $this->isPjax = request()->pjax();
  262. $this->initTheme();
  263. }
  264. /**
  265. * 初始化主题样式.
  266. */
  267. protected function initTheme()
  268. {
  269. $color = Admin::color()->name();
  270. if ($color === Color::DEFAULT_COLOR) {
  271. return;
  272. }
  273. $alias = [
  274. '@adminlte',
  275. '@dcat',
  276. '@webuploader',
  277. '@smart-wizard',
  278. ];
  279. foreach ($alias as $n) {
  280. $before = (array) $this->alias[$n]['css'];
  281. $this->alias[$n]['css'] = [];
  282. foreach ($before as $css) {
  283. $this->alias[$n]['css'][] = str_replace('.css', "-{$color}.css", $css);
  284. }
  285. }
  286. }
  287. /**
  288. * 设置或获取别名.
  289. *
  290. * @param string|array $name
  291. * @param string|array $js
  292. * @param string|array $css
  293. *
  294. * @return void|array
  295. */
  296. public function alias($name, $js = null, $css = null)
  297. {
  298. if (is_array($name)) {
  299. foreach ($name as $key => $value) {
  300. $this->alias($key, $value['js'] ?? [], $value['css'] ?? []);
  301. }
  302. return;
  303. }
  304. if ($js === null && $css === null) {
  305. return $this->alias[$name] ?? [];
  306. }
  307. if (mb_strpos($name, '@') !== 0) {
  308. $name = '@'.$name;
  309. }
  310. $this->alias[$name] = [
  311. 'js' => $js,
  312. 'css' => $css,
  313. ];
  314. }
  315. /**
  316. * 根据别名设置需要载入的js和css脚本.
  317. *
  318. * @param string|array $alias
  319. */
  320. public function collect($alias)
  321. {
  322. if (is_array($alias)) {
  323. foreach ($alias as $v) {
  324. $this->collect($v);
  325. }
  326. return;
  327. }
  328. if (mb_strpos($alias, '@') !== 0) {
  329. $alias = '@'.$alias;
  330. }
  331. $this->js($this->alias[$alias]['js'] ?? null);
  332. $this->css($this->alias[$alias]['css'] ?? null);
  333. }
  334. /**
  335. * 设置需要载入的css脚本.
  336. *
  337. * @param string|array $css
  338. */
  339. public function css($css)
  340. {
  341. if (! $css) {
  342. return;
  343. }
  344. $this->css = array_merge(
  345. $this->css,
  346. (array) $css
  347. );
  348. }
  349. /**
  350. * 设置需要载入的基础css脚本.
  351. *
  352. * @param array $css
  353. */
  354. public function baseCss(array $css)
  355. {
  356. $this->baseCss = $css;
  357. }
  358. /**
  359. * 设置需要载入的js脚本.
  360. *
  361. * @param string|array $js
  362. */
  363. public function js($js)
  364. {
  365. if (! $js) {
  366. return;
  367. }
  368. $this->js = array_merge(
  369. $this->js,
  370. (array) $js
  371. );
  372. }
  373. /**
  374. * 根据别名获取资源路径.
  375. *
  376. * @param string $path
  377. * @param string $type
  378. *
  379. * @return string|array|null
  380. */
  381. public function get($path, string $type = 'js')
  382. {
  383. if (empty($this->alias[$path])) {
  384. return $this->url($path);
  385. }
  386. $paths = isset($this->alias[$path][$type]) ? (array) $this->alias[$path][$type] : null;
  387. if (! $paths) {
  388. return $paths;
  389. }
  390. foreach ($paths as &$value) {
  391. $value = $this->url($value);
  392. }
  393. return $paths;
  394. }
  395. /**
  396. * 获取静态资源完整URL.
  397. *
  398. * @param string $path
  399. *
  400. * @return string
  401. */
  402. public function url($path)
  403. {
  404. if (! $path) {
  405. return $path;
  406. }
  407. $path = $this->getRealPath($path);
  408. if (mb_strpos($path, '//') === false) {
  409. $path = config('admin.assets_server').'/'.trim($path, '/');
  410. }
  411. return (config('admin.https') || config('admin.secure')) ? secure_asset($path) : asset($path);
  412. }
  413. /**
  414. * 获取真实路径.
  415. *
  416. * @param string|null $path
  417. *
  418. * @return string|null
  419. */
  420. public function getRealPath(?string $path)
  421. {
  422. if (! $this->hasAlias($path)) {
  423. return $path;
  424. }
  425. return implode(
  426. '/',
  427. array_map(
  428. function ($v) {
  429. $v = $this->pathAlias[$v] ?? $v;
  430. if (! $this->hasAlias($v)) {
  431. return $v;
  432. }
  433. return $this->getRealPath($v);
  434. },
  435. explode('/', $path)
  436. )
  437. );
  438. }
  439. /**
  440. * 判断是否含有别名.
  441. *
  442. * @param string $value
  443. *
  444. * @return bool
  445. */
  446. protected function hasAlias($value)
  447. {
  448. return $value && mb_strpos($value, '@') === 0;
  449. }
  450. /**
  451. * 设置在head标签内加载的js.
  452. *
  453. * @param string|array $js
  454. */
  455. public function headerJs($js)
  456. {
  457. if (! $js) {
  458. return;
  459. }
  460. $this->headerJs = array_merge($this->headerJs, (array) $js);
  461. }
  462. /**
  463. * 设置基础js脚本.
  464. *
  465. * @param array $js
  466. */
  467. public function baseJs(array $js)
  468. {
  469. $this->baseJs = $js;
  470. }
  471. /**
  472. * 设置js代码.
  473. *
  474. * @param string|array $script
  475. * @param bool $direct
  476. */
  477. public function script($script, bool $direct = false)
  478. {
  479. if (! $script) {
  480. return;
  481. }
  482. if ($direct) {
  483. $this->directScript = array_merge($this->directScript, (array) $script);
  484. } else {
  485. $this->script = array_merge($this->script, (array) $script);
  486. }
  487. }
  488. /**
  489. * 设置css代码.
  490. *
  491. * @param string $style
  492. */
  493. public function style($style)
  494. {
  495. if (! $style) {
  496. return;
  497. }
  498. $this->style = array_merge($this->style, (array) $style);
  499. }
  500. /**
  501. * 字体css脚本路径.
  502. */
  503. protected function addFontCss()
  504. {
  505. $this->fonts && (
  506. $this->baseCss = array_merge(
  507. $this->baseCss,
  508. (array) $this->fonts
  509. )
  510. );
  511. }
  512. /**
  513. * 合并基础css脚本.
  514. */
  515. protected function mergeBaseCss()
  516. {
  517. if ($this->isPjax) {
  518. return;
  519. }
  520. $this->addFontCss();
  521. $this->css = array_merge($this->baseCss, $this->css);
  522. }
  523. /**
  524. * @return string
  525. */
  526. public function cssToHtml()
  527. {
  528. $this->mergeBaseCss();
  529. $html = '';
  530. foreach (array_unique($this->css) as &$v) {
  531. if (! $paths = $this->get($v, 'css')) {
  532. continue;
  533. }
  534. foreach ((array) $paths as $path) {
  535. $html .= "<link rel=\"stylesheet\" href=\"{$this->withVersionQuery($path)}\">";
  536. }
  537. }
  538. return $html;
  539. }
  540. /**
  541. * @param string $url
  542. *
  543. * @return string
  544. */
  545. public function withVersionQuery($url)
  546. {
  547. if (! Str::contains($url, '?')) {
  548. $url .= '?';
  549. }
  550. $ver = 'v'.Admin::VERSION;
  551. return Str::endsWith($url, '?') ? $url.$ver : $url.'&'.$ver;
  552. }
  553. /**
  554. * 合并基础js脚本.
  555. */
  556. protected function mergeBaseJs()
  557. {
  558. if ($this->isPjax) {
  559. return;
  560. }
  561. $this->js = array_merge($this->baseJs, $this->js);
  562. }
  563. /**
  564. * @return string
  565. */
  566. public function jsToHtml()
  567. {
  568. $this->mergeBaseJs();
  569. $html = '';
  570. foreach (array_unique($this->js) as &$v) {
  571. if (! $paths = $this->get($v, 'js')) {
  572. continue;
  573. }
  574. foreach ((array) $paths as $path) {
  575. $html .= "<script src=\"{$this->withVersionQuery($path)}\"></script>";
  576. }
  577. }
  578. return $html;
  579. }
  580. /**
  581. * @return string
  582. */
  583. public function headerJsToHtml()
  584. {
  585. $html = '';
  586. foreach (array_unique($this->headerJs) as &$v) {
  587. if (! $paths = $this->get($v, 'js')) {
  588. continue;
  589. }
  590. foreach ((array) $paths as $path) {
  591. $html .= "<script src=\"{$this->withVersionQuery($path)}\"></script>";
  592. }
  593. }
  594. return $html;
  595. }
  596. /**
  597. * @return string
  598. */
  599. public function scriptToHtml()
  600. {
  601. $script = implode(';', array_unique($this->script));
  602. $directScript = implode(';', array_unique($this->directScript));
  603. return <<<HTML
  604. <script data-exec-on-popstate>
  605. (function () {
  606. try {
  607. {$directScript}
  608. } catch (e) {
  609. console.error(e)
  610. }
  611. })();
  612. Dcat.ready(function () {
  613. try {
  614. {$script}
  615. } catch (e) {
  616. console.error(e)
  617. }
  618. })
  619. </script>
  620. HTML;
  621. }
  622. /**
  623. * @return string
  624. */
  625. public function styleToHtml()
  626. {
  627. $style = implode('', array_unique($this->style));
  628. return "<style>$style</style>";
  629. }
  630. }