Asset.php 17 KB

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