DiyService.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Niucloud-admin 企业快速开发的saas管理平台
  4. // +----------------------------------------------------------------------
  5. // | 官方网址:https://www.niucloud.com
  6. // +----------------------------------------------------------------------
  7. // | niucloud团队 版权所有 开源版本可自由商用
  8. // +----------------------------------------------------------------------
  9. // | Author: Niucloud Team
  10. // +----------------------------------------------------------------------
  11. namespace app\service\admin\diy;
  12. use app\dict\diy\ComponentDict;
  13. use app\dict\diy\LinkDict;
  14. use app\dict\diy\PagesDict;
  15. use app\dict\diy\TemplateDict;
  16. use app\model\diy\Diy;
  17. use app\service\admin\sys\SystemService;
  18. use core\base\BaseAdminService;
  19. use core\exception\AdminException;
  20. use Exception;
  21. use think\db\exception\DataNotFoundException;
  22. use think\db\exception\DbException;
  23. use think\db\exception\ModelNotFoundException;
  24. use think\facade\Db;
  25. /**
  26. * 自定义页面服务层
  27. * Class DiyService
  28. * @package app\service\admin\diy
  29. */
  30. class DiyService extends BaseAdminService
  31. {
  32. public function __construct()
  33. {
  34. parent::__construct();
  35. $this->model = new Diy();
  36. }
  37. /**
  38. * 获取自定义页面分页列表
  39. * @param array $where
  40. * @return array
  41. */
  42. public function getPage(array $where = [])
  43. {
  44. $where[] = [ 'site_id', '=', $this->site_id ];
  45. $field = 'id,site_id,title,page_title,name,template,type,mode,is_default,share,visit_count,create_time,update_time,value';
  46. $order = "update_time desc";
  47. $search_model = $this->model->where([ [ 'site_id', '=', $this->site_id ] ])->withSearch([ "title", "type", 'mode', 'addon_name' ], $where)->field($field)->order($order)->append([ 'type_name', 'type_page', 'addon_name' ]);
  48. return $this->pageQuery($search_model);
  49. }
  50. /**
  51. * 获取自定义页面分页列表,轮播搜索组件用
  52. * 查询微页面,数据排除存在轮播搜索组件的
  53. * @param array $where
  54. * @return array
  55. */
  56. public function getPageByCarouselSearch(array $where = [])
  57. {
  58. $where[] = [ 'site_id', '=', $this->site_id ];
  59. $field = 'id,site_id,title,page_title,name,template,type,mode,is_default,share,visit_count,create_time,update_time,value';
  60. $order = "update_time desc";
  61. $search_model = $this->model->whereOr([
  62. [
  63. [ 'type', '=', 'DIY_PAGE' ],
  64. [ 'site_id', '=', $this->site_id ],
  65. [ 'value', 'not in', [ 'top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed', 'fixed' ] ]
  66. ],
  67. [
  68. [ 'type', '<>', 'DIY_PAGE' ],
  69. [ 'site_id', '=', $this->site_id ],
  70. [ 'is_default', '=', 0 ],
  71. [ 'value', 'not in', [ 'top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed', 'fixed' ] ]
  72. ]
  73. ])->field($field)->order($order)->append([ 'type_name', 'type_page', 'addon_name' ]);
  74. return $this->pageQuery($search_model);
  75. }
  76. /**
  77. * 获取自定义页面列表
  78. * @param array $where
  79. * @param string $field
  80. * @return array
  81. * @throws DataNotFoundException
  82. * @throws DbException
  83. * @throws ModelNotFoundException
  84. */
  85. public function getList(array $where = [], $field = 'id,title,page_title,name,template,type,mode,is_default,share,visit_count,create_time,update_time')
  86. {
  87. $order = "update_time desc";
  88. return $this->model->where([ [ 'site_id', '=', $this->site_id ] ])->withSearch([ "title", "type", 'mode' ], $where)->field($field)->order($order)->select()->toArray();
  89. }
  90. /**
  91. * 获取自定义页面信息
  92. * @param int $id
  93. * @return array
  94. */
  95. public function getInfo(int $id)
  96. {
  97. $field = 'id,site_id,title,page_title,name,template,type,mode,value,is_default,is_change,share,visit_count';
  98. return $this->model->field($field)->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->findOrEmpty()->toArray();
  99. }
  100. public function getInfoByName(string $name)
  101. {
  102. $field = 'id,site_id,title,page_title,name,template,type,mode,value,is_default,is_change,share,visit_count';
  103. return $this->model->field($field)->where([ [ 'name', '=', $name ], [ 'site_id', '=', $this->site_id ], [ 'is_default', '=', 1 ] ])->findOrEmpty()->toArray();
  104. }
  105. /**
  106. * 查询数量
  107. * @param array $where
  108. * @return int
  109. * @throws DbException
  110. */
  111. public function getCount(array $where = [])
  112. {
  113. return $this->model->where([ [ 'site_id', '=', $this->site_id ] ])->withSearch([ 'type' ], $where)->count();
  114. }
  115. /**
  116. * 添加自定义页面
  117. * @param array $data
  118. * @return mixed
  119. */
  120. public function add(array $data)
  121. {
  122. $data[ 'site_id' ] = $this->site_id;
  123. $data[ 'create_time' ] = time();
  124. $data[ 'update_time' ] = time();
  125. // 添加新页面,默认为1
  126. if (!empty($data[ 'type' ]) && $data[ 'type' ] == 'DIY_PAGE') {
  127. $data[ 'is_default' ] = 1;
  128. }
  129. // 将同类型页面的默认值改为0,默认页面只有一个
  130. if (!empty($data[ 'is_default' ])) {
  131. $this->model->where([ [ 'name', '=', $data[ 'name' ] ], [ 'site_id', '=', $data[ 'site_id' ] ] ])->update([ 'is_default' => 0 ]);
  132. }
  133. $res = $this->model->create($data);
  134. return $res->id;
  135. }
  136. /**
  137. * 编辑自定义页面
  138. * @param int $id
  139. * @param array $data
  140. * @return bool
  141. */
  142. public function edit(int $id, array $data)
  143. {
  144. $data[ 'update_time' ] = time();
  145. $this->model->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->update($data);
  146. return true;
  147. }
  148. /**
  149. * 删除自定义页面
  150. * @param int $id
  151. * @return bool
  152. */
  153. public function del(int $id)
  154. {
  155. return $this->model->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->delete();
  156. }
  157. /**
  158. * 设为使用
  159. * @param int $id
  160. * @return bool
  161. * @throws Exception
  162. */
  163. public function setUse(int $id)
  164. {
  165. try {
  166. $info = $this->getInfo($id);
  167. if (empty($info)) {
  168. return false;
  169. }
  170. Db::startTrans();
  171. $this->model->where([ [ 'name', '=', $info[ 'name' ] ], [ 'site_id', '=', $this->site_id ] ])->update([ 'is_default' => 0 ]);
  172. $this->model->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->update([ 'is_default' => 1, 'update_time' => time() ]);
  173. Db::commit();
  174. return true;
  175. } catch (Exception $e) {
  176. Db::rollback();
  177. throw new AdminException($e->getMessage());
  178. }
  179. }
  180. /**
  181. * 页面加载初始化
  182. * @param array $params
  183. * @return array
  184. * @throws DbException
  185. */
  186. public function getInit(array $params = [])
  187. {
  188. $template = $this->getTemplate();
  189. $time = time();
  190. $data = [];
  191. if (!empty($params[ 'id' ])) {
  192. $data = $this->getInfo($params[ 'id' ]);
  193. } elseif (!empty($params[ 'name' ])) {
  194. $data = $this->getInfoByName($params[ 'name' ]);
  195. }
  196. if (!empty($params[ 'name' ])) {
  197. // 查询启动页配置
  198. $diy_config_service = new DiyConfigService();
  199. $start_up_page = $diy_config_service->getStartUpPageConfig($params[ 'name' ]);
  200. if (!empty($start_up_page)) {
  201. if (!empty($start_up_page[ 'parent' ]) && $start_up_page[ 'parent' ] == 'DIY_PAGE') {
  202. $id = str_replace('/app/pages/index/diy?id=', '', $start_up_page[ 'page' ]);
  203. $data = $this->getInfo($id);
  204. if (!empty($data)) {
  205. $params[ 'name' ] = $data[ 'name' ];
  206. $params[ 'type' ] = $data[ 'type' ];
  207. }
  208. }
  209. }
  210. }
  211. if (!empty($data)) {
  212. // 编辑赋值
  213. if (isset($template[ $data[ 'type' ] ])) {
  214. $page = $template[ $data[ 'type' ] ];
  215. $data[ 'type_name' ] = $page[ 'title' ];
  216. $data[ 'page' ] = $page[ 'page' ];
  217. }
  218. } else {
  219. // 新页面赋值
  220. $page_title = $params[ 'title' ] ? : '页面' . $time; // 页面标题(用于前台展示)
  221. $type = $params[ 'type' ] ? : 'DIY_PAGE';
  222. $name = $type == 'DIY_PAGE' ? 'DIY_PAGE_RANDOM_' . $time : $type;
  223. $title = $page_title;
  224. $type_name = '';
  225. $template_name = ''; // 页面模板名称
  226. $page_route = ''; // 页面路径
  227. $mode = 'diy'; // 页面模式,diy:自定义,fixed:固定
  228. $value = '';
  229. $is_default = 0;
  230. // 查询默认第一个页面模板数据
  231. if (isset($template[ $params[ 'name' ] ])) {
  232. $page = $template[ $params[ 'name' ] ];
  233. $name = $params[ 'name' ];
  234. $type = $params[ 'name' ];
  235. $page_title = $page[ 'title' ];
  236. $type_name = $page[ 'title' ];
  237. $page_route = $page[ 'page' ];
  238. $page_data = $this->getFirstPageData($type);
  239. if (!empty($page_data)) {
  240. $value = json_encode($page_data[ 'data' ], JSON_UNESCAPED_UNICODE);
  241. $is_default = 1;
  242. $template_name = $page_data[ 'template' ];
  243. $mode = $page_data[ 'mode' ];
  244. }
  245. } else if (isset($template[ $type ])) {
  246. // 查询指定页面数据
  247. $page = $template[ $type ];
  248. $type_name = $page[ 'title' ];
  249. $page_route = $page[ 'page' ];
  250. // 如果页面类型一条数据也没有,那么要默认 使用中
  251. $count = $this->getCount([ 'type' => $type ]);
  252. if ($count == 0) {
  253. $is_default = 1;
  254. }
  255. }
  256. // 页面标题(用于前台展示)
  257. if ($type != 'DIY_PAGE') {
  258. $title = $type_name;
  259. }
  260. $data = [
  261. 'name' => $name,
  262. 'page_title' => $page_title, // 页面名称(用于后台展示)
  263. 'title' => $title, // 页面标题(用于前台展示)
  264. 'type' => $type,
  265. 'type_name' => $type_name,
  266. 'template' => $template_name,
  267. 'page' => $page_route,
  268. 'mode' => $mode,
  269. 'value' => $value,
  270. 'is_default' => $is_default
  271. ];
  272. }
  273. $data[ 'component' ] = $this->getComponentList($data[ 'type' ]);
  274. $data[ 'domain_url' ] = ( new SystemService() )->getUrl();
  275. return $data;
  276. }
  277. /**
  278. * 获取组件列表
  279. * @param string $name 支持页面标识
  280. * @return array
  281. */
  282. public function getComponentList(string $name = '')
  283. {
  284. $data = ComponentDict::getComponent();
  285. foreach ($data as $k => $v) {
  286. // 查询组件支持的页面
  287. $sort_arr = [];
  288. foreach ($v[ 'list' ] as $ck => $cv) {
  289. $support_page = $cv[ 'support_page' ];
  290. if (!( count($support_page) == 0 || in_array($name, $support_page) )) {
  291. unset($data[ $k ][ 'list' ][ $ck ]);
  292. continue;
  293. }
  294. $sort_arr [] = $cv[ 'sort' ];
  295. unset($data[ $k ][ 'list' ][ $ck ][ 'sort' ], $data[ $k ][ 'list' ][ $ck ][ 'support_page' ]);
  296. }
  297. array_multisort($sort_arr, SORT_ASC, $data[ $k ][ 'list' ]); //排序,根据 sort 排序
  298. }
  299. return $data;
  300. }
  301. /**
  302. * 获取自定义链接
  303. * @return array
  304. * @throws DataNotFoundException
  305. * @throws DbException
  306. * @throws ModelNotFoundException
  307. */
  308. public function getLink()
  309. {
  310. $link = LinkDict::getLink();
  311. foreach ($link as $k => $v) {
  312. $link[ $k ][ 'name' ] = $k;
  313. if (!empty($v[ 'child_list' ])) {
  314. foreach ($v[ 'child_list' ] as $ck => $cv) {
  315. $link[ $k ][ 'child_list' ][ $ck ][ 'parent' ] = $k;
  316. }
  317. }
  318. // 查询自定义页面
  319. if ($k == 'DIY_PAGE') {
  320. $order = "update_time desc";
  321. $field = 'id,title,page_title,name,template,type,mode,is_default,share,visit_count,create_time,update_time';
  322. $list = $this->model
  323. ->whereOr([
  324. [
  325. [ 'type', '=', 'DIY_PAGE' ],
  326. [ 'site_id', '=', $this->site_id ],
  327. ],
  328. [
  329. [ 'type', '<>', 'DIY_PAGE' ],
  330. [ 'site_id', '=', $this->site_id ],
  331. [ 'is_default', '=', 0 ]
  332. ]
  333. ])->field($field)->order($order)->select()->toArray();
  334. foreach ($list as $ck => $cv) {
  335. $link[ $k ][ 'child_list' ][] = [
  336. 'name' => $cv[ 'name' ],
  337. 'title' => $cv[ 'page_title' ],
  338. 'url' => '/app/pages/index/diy?id=' . $cv[ 'id' ]
  339. ];
  340. }
  341. }
  342. if ($k == 'DIY_LINK') {
  343. $link[ $k ][ 'parent' ] = 'DIY_LINK';
  344. }
  345. }
  346. return $link;
  347. }
  348. /**
  349. * 修改分享内容
  350. * @param int $id
  351. * @param $data
  352. * @return bool
  353. */
  354. public function modifyShare(int $id, $data)
  355. {
  356. $this->model->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->update([ 'share' => $data[ 'share' ] ]);
  357. return true;
  358. }
  359. /**
  360. * 获取页面模板
  361. * @param array $params
  362. * @return array
  363. */
  364. public function getTemplate($params = [])
  365. {
  366. $page_template = TemplateDict::getTemplate($params);
  367. foreach ($page_template as $k => $v) {
  368. // 查询页面数据
  369. $page_params = [
  370. 'type' => $k, // 页面类型
  371. 'mode' => $params[ 'mode' ] ?? '' // 页面模式:diy:自定义,fixed:固定
  372. ];
  373. $page_template[ $k ][ 'template' ] = PagesDict::getPages($page_params);
  374. }
  375. return $page_template;
  376. }
  377. /**
  378. * 获取页面数据
  379. * @param $type
  380. * @param $name
  381. * @return array
  382. */
  383. public function getPageData($type, $name)
  384. {
  385. $pages = PagesDict::getPages([ 'type' => $type ]);
  386. return $pages[ $name ] ?? [];
  387. }
  388. /**
  389. * 获取默认页面数据
  390. * @param $type
  391. * @param string $addon
  392. * @return array|mixed
  393. */
  394. public function getFirstPageData($type, $addon = '')
  395. {
  396. $pages = PagesDict::getPages([ 'type' => $type, 'addon' => $addon ]);
  397. if (!empty($pages)) {
  398. $template = array_key_first($pages);
  399. $page = array_pop($pages);
  400. $page[ 'template' ] = $template;
  401. $page[ 'type' ] = $type;
  402. return $page;
  403. }
  404. return [];
  405. }
  406. /**
  407. * 获取页面装修列表
  408. * @param $params
  409. * @return array
  410. * @throws DataNotFoundException
  411. * @throws DbException
  412. * @throws ModelNotFoundException
  413. */
  414. public function getDecoratePage($params)
  415. {
  416. // 查询当前装修的页面信息
  417. $template = $this->getTemplate([ 'action' => 'decorate', 'key' => [ $params[ 'type' ] ] ])[ $params[ 'type' ] ];
  418. $template[ 'domain_url' ] = ( new SystemService() )->getUrl();
  419. // 查询默认页面数据
  420. $default_page_data = $this->getFirstPageData($params[ 'type' ]);
  421. $use_template = [
  422. 'type' => $params[ 'type' ], // 页面类型标识
  423. 'name' => '', // 链接标识
  424. 'parent' => '', // 链接标识
  425. 'title' => $default_page_data[ 'title' ] ?? '', // 模板名称
  426. 'cover' => $default_page_data[ 'cover' ] ?? '', // 封面图
  427. 'url' => '', // 自定义页面链接,实时预览效果
  428. 'page' => $template[ 'page' ], // 页面地址
  429. 'action' => $template[ 'action' ] // 是否存在操作,decorate 表示支持装修
  430. ];
  431. // 查询页面数据
  432. $info = $this->getInfoByName($params[ 'type' ]);
  433. if (!empty($info)) {
  434. $use_template[ 'id' ] = $info[ 'id' ];
  435. $use_template[ 'title' ] = $info[ 'title' ];
  436. // 查询模板页面数据
  437. $page_data = $this->getPageData($params[ 'type' ], $info[ 'template' ]);
  438. if (!empty($page_data)) {
  439. $use_template[ 'url' ] = $template[ 'page' ] . '?id=' . $info[ 'id' ];
  440. // $use_template[ 'cover' ] = $page_data[ 'cover' ]; // 默认图
  441. } else {
  442. // 自定义页面,实时预览效果
  443. $use_template[ 'url' ] = '/app/pages/index/diy?id=' . $info[ 'id' ];
  444. // 清空模板信息
  445. $use_template[ 'cover' ] = ''; // 默认图
  446. }
  447. }
  448. // 查询链接的名称标识,保证数据准确性
  449. $other_page = ( new DiyRouteService() )->getList([ 'url' => $use_template[ 'page' ] ]);
  450. if (!empty($other_page)) {
  451. $use_template[ 'title' ] = $other_page[ 0 ][ 'title' ] ?? '';
  452. $use_template[ 'name' ] = $other_page[ 0 ][ 'name' ];
  453. $use_template[ 'parent' ] = $other_page[ 0 ][ 'parent' ];
  454. $use_template[ 'action' ] = $other_page[ 0 ][ 'action' ];
  455. }
  456. // 如果没有预览图,并且没有地址,则赋值默认页面地址
  457. if (empty($use_template[ 'cover' ]) && empty($use_template[ 'url' ])) {
  458. $use_template[ 'url' ] = $template[ 'page' ];
  459. } elseif (empty($use_template[ 'url' ])) {
  460. $use_template[ 'url' ] = $template[ 'page' ];
  461. }
  462. $template[ 'use_template' ] = $use_template;
  463. return $template;
  464. }
  465. /**
  466. * 设置启动页
  467. * @param array $params
  468. * @return \app\model\sys\SysConfig|bool|\think\Model
  469. */
  470. public function changeTemplate(array $params = [])
  471. {
  472. $start_up_page_data = [
  473. 'type' => $params[ 'type' ], // 页面类型
  474. 'name' => $params[ 'name' ], // 链接名称标识
  475. 'parent' => $params[ 'parent' ], // 链接父级名称标识
  476. 'page' => $params[ 'page' ], // 链接路由
  477. 'title' => $params[ 'title' ], // 链接标题
  478. 'action' => $params[ 'action' ] // 是否存在操作,decorate 表示支持装修
  479. ];
  480. $diy_config_service = new DiyConfigService();
  481. $res = $diy_config_service->setStartUpPageConfig($start_up_page_data);
  482. return $res;
  483. }
  484. /**
  485. * 获取模板页面(存在的应用插件列表)
  486. * @return array
  487. */
  488. public function getApps()
  489. {
  490. $page_template = TemplateDict::getTemplate([
  491. 'query' => 'addon'
  492. ]);
  493. return $page_template;
  494. }
  495. }