DiyView.php 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace app\model\web;
  11. use app\model\BaseModel;
  12. use app\model\diy\Template;
  13. use app\model\diy\Theme;
  14. use app\model\system\Addon;
  15. use app\model\system\Config as ConfigModel;
  16. use think\facade\Cache;
  17. /**
  18. * 自定义模板
  19. */
  20. class DiyView extends BaseModel
  21. {
  22. /**
  23. * 组件分类
  24. * @param $type
  25. * @return mixed
  26. */
  27. public function getTypeName($type)
  28. {
  29. $arr = [
  30. 'SYSTEM' => '基础组件', // 排序号范围:10000~20000
  31. 'PROMOTION' => '营销组件', // 排序号范围:30000~40000
  32. 'EXTEND' => '扩展组件', // 排序号范围:50000~60000
  33. ];
  34. return $arr[ $type ];
  35. }
  36. /**
  37. * 获取图标分类
  38. * @return array
  39. */
  40. public function getIconType()
  41. {
  42. $icon_type = $this->getIconAllList()[ 'type' ];
  43. return $icon_type;
  44. }
  45. /**
  46. * 获取所有图标库数据
  47. * @param array $params
  48. * @return array
  49. */
  50. private function getIconAllList($params = [])
  51. {
  52. $data = json_encode($params);
  53. $cache = Cache::get("diy_icon_getIconAllList_" . $data);
  54. if (!empty($cache)) {
  55. return $cache;
  56. }
  57. $condition = [];
  58. if (!empty($params)) {
  59. $condition[] = [ 'name', '=', $params[ 'addon_name' ] ];
  60. }
  61. $addon = new Addon();
  62. $addon_list = $addon->getAddonList($condition, 'name')[ 'data' ];
  63. $icon_list = []; // 自定义图标库列表
  64. $res = [
  65. 'component' => [], // 组件图标
  66. 'icon' => [], // 自定义图标
  67. 'type' => [] // 图标类型
  68. ];
  69. // app下的图标库
  70. $diy_view_file = 'config/diy_view.php';
  71. if (file_exists($diy_view_file)) {
  72. $diy_view = require $diy_view_file;
  73. if (isset($diy_view[ 'icon_library' ]) && !empty($diy_view[ 'icon_library' ])) {
  74. $icon_list[] = $diy_view[ 'icon_library' ];
  75. }
  76. }
  77. // 循环插件中的图标库
  78. foreach ($addon_list as $k => $v) {
  79. $diy_view_file = 'addon/' . $v[ 'name' ] . '/config/diy_view.php';
  80. if (file_exists($diy_view_file)) {
  81. $diy_view = require $diy_view_file;
  82. if (isset($diy_view[ 'icon_library' ]) && !empty($diy_view[ 'icon_library' ])) {
  83. $icon_list[] = $diy_view[ 'icon_library' ];
  84. }
  85. }
  86. }
  87. foreach ($icon_list as $k => $v) {
  88. // 组件图标
  89. if (!empty($v[ 'component' ]) && !empty($v[ 'component' ][ 'name' ]) && !empty($v[ 'component' ][ 'path' ])) {
  90. $component_name_arr = array_column($res[ 'component' ], 'name');
  91. // 检测防重复
  92. if (!empty($v[ 'component' ][ 'name' ]) && !in_array($v[ 'component' ][ 'name' ], $component_name_arr)) {
  93. $res[ 'component' ][] = $v[ 'component' ];
  94. }
  95. }
  96. // 自定义图标
  97. if (!empty($v[ 'icon' ]) && !empty($v[ 'icon' ][ 'name' ]) && !empty($v[ 'icon' ][ 'path' ])) {
  98. // 检测防重复
  99. $icon_name_arr = array_column($res[ 'icon' ], 'name');
  100. if (!empty($v[ 'icon' ][ 'name' ]) && !in_array($v[ 'icon' ][ 'name' ], $icon_name_arr)) {
  101. $res[ 'icon' ][] = $v[ 'icon' ];
  102. }
  103. }
  104. // 图标类型
  105. if (!empty($v[ 'type' ])) {
  106. $res[ 'type' ] = array_merge($res[ 'type' ], array_filter($v[ 'type' ]));
  107. }
  108. }
  109. Cache::tag("site_diy_view")->set("diy_icon_getIconAllList_" . $data, $res);
  110. return $res;
  111. }
  112. /**
  113. * 获取自定义图标库列表
  114. * @param $type
  115. * @return array
  116. */
  117. public function getIconList($type)
  118. {
  119. $icon_path = $this->getIconAllList()[ 'icon' ];
  120. $icon_list = [];
  121. foreach ($icon_path as $k => $v) {
  122. if (file_exists($v[ 'path' ])) {
  123. $fp = fopen($v[ 'path' ], "r");
  124. $str = fread($fp, filesize($v[ 'path' ])); // 指定读取大小,这里把整个文件内容读取出来
  125. $exc = '/[.](' . $type . '\S+):before{1}/';// 匹配图标,格式:.icon名字:before
  126. preg_match_all($exc, $str, $match);
  127. sort($match[ 1 ]); // 按名称正序排序
  128. foreach ($match[ 1 ] as $ck => $cv) {
  129. $match[ 1 ][ $ck ] = $v[ 'name' ] . ' ' . $cv; // 拼接字体图标名称
  130. }
  131. $icon_list = array_merge($icon_list, $match[ 1 ]);
  132. }
  133. }
  134. return $this->success($icon_list);
  135. }
  136. /**
  137. * 获取图标库文件路径
  138. * @return array
  139. */
  140. public function getIconUrl()
  141. {
  142. $icon_list = $this->getIconAllList();
  143. $component_path = $icon_list[ 'component' ]; // 组件图标
  144. $icon_path = $icon_list[ 'icon' ]; // 自定义图标
  145. $url = [];
  146. $arr = array_merge($component_path, $icon_path);
  147. foreach ($arr as $k => $v) {
  148. if (!empty($v[ 'path' ])) {
  149. $url[] = __ROOT__ . '/' . $v[ 'path' ];
  150. }
  151. }
  152. foreach ($url as $k => $v) {
  153. $url[ $k ] = '<link rel="stylesheet" type="text/css" href="' . $v . '" />';
  154. }
  155. return $this->success($url);
  156. }
  157. /**
  158. * 获取扩展组件列表
  159. * @param array $params
  160. * @return array|mixed
  161. */
  162. public function getExtendComponentList($params = [])
  163. {
  164. $data = json_encode($params);
  165. $cache = Cache::get("diy_extend_component_getExtendComponentList_" . $data);
  166. if (!empty($cache)) {
  167. return $cache;
  168. }
  169. $condition = [];
  170. if (!empty($params)) {
  171. $condition[] = [ 'name', '=', $params[ 'addon_name' ] ];
  172. }
  173. $addon = new Addon();
  174. $addon_list = $addon->getAddonList($condition, 'name')[ 'data' ];
  175. $component_list = []; // 扩展组件列表
  176. // 循环插件中的组件
  177. foreach ($addon_list as $k => $v) {
  178. $diy_view_file = 'addon/' . $v[ 'name' ] . '/config/diy_view.php';
  179. if (file_exists($diy_view_file)) {
  180. $diy_view = require $diy_view_file;
  181. if (isset($diy_view[ 'component' ]) && !empty($diy_view[ 'component' ])) {
  182. foreach ($diy_view[ 'component' ] as $ck => $cv) {
  183. if (!empty($cv[ 'name' ]) && !in_array($cv[ 'name' ], $component_list)) {
  184. $cv[ 'path' ] = 'addon/' . $v[ 'name' ] . '/uniapp/' . $cv[ 'path' ];
  185. $component_list[] = $cv;
  186. }
  187. }
  188. }
  189. }
  190. }
  191. Cache::tag("site_diy_view")->set("diy_extend_component_getExtendComponentList_" . $data, $component_list);
  192. return $component_list;
  193. }
  194. /**
  195. * 获取uni-app页面列表
  196. * @param array $params
  197. * @return array|mixed
  198. */
  199. public function getUniAppPageList($params = [])
  200. {
  201. $data = json_encode($params);
  202. $cache = Cache::get("diy_pages_getUniAppPageList_" . $data);
  203. if (!empty($cache)) {
  204. return $cache;
  205. }
  206. $condition = [];
  207. if (!empty($params)) {
  208. $condition[] = [ 'name', '=', $params[ 'addon_name' ] ];
  209. }
  210. $addon = new Addon();
  211. $addon_list = $addon->getAddonList($condition, 'name')[ 'data' ];
  212. $page_list = []; // 页面列表
  213. // 循环插件中的页面
  214. foreach ($addon_list as $k => $v) {
  215. $diy_view_file = 'addon/' . $v[ 'name' ] . '/config/diy_view.php';
  216. if (file_exists($diy_view_file)) {
  217. $diy_view = require $diy_view_file;
  218. if (isset($diy_view[ 'pages' ]) && !empty($diy_view[ 'pages' ])) {
  219. foreach ($diy_view[ 'pages' ] as $ck => $cv) {
  220. if (!empty($cv[ 'path' ]) && !in_array($cv[ 'path' ], $page_list)) {
  221. $cv[ 'route' ] = $cv[ 'path' ]; // 路由
  222. $cv[ 'path' ] = 'addon/' . $v[ 'name' ] . '/uniapp/' . $cv[ 'path' ] . '.vue'; // 源文件路径
  223. $page_list[] = $cv;
  224. }
  225. }
  226. }
  227. }
  228. }
  229. Cache::tag("site_diy_view")->set("diy_pages_getUniAppPageList_" . $data, $page_list);
  230. return $page_list;
  231. }
  232. /**
  233. * 添加组件
  234. * @param $data
  235. * @return array
  236. */
  237. public function addUtil($data)
  238. {
  239. $res = model('diy_view_util')->add($data);
  240. return $this->success($res);
  241. }
  242. /**
  243. * 添加多个组件
  244. * @param $data
  245. * @return array
  246. */
  247. public function addUtilList($data)
  248. {
  249. $res = model('diy_view_util')->addList($data);
  250. return $this->success($res);
  251. }
  252. /**
  253. * 编辑组件
  254. * @param $data
  255. * @param $condition
  256. * @return array
  257. */
  258. public function editUtil($data, $condition)
  259. {
  260. $res = model('diy_view_util')->update($data, $condition);
  261. return $this->success($res);
  262. }
  263. /**
  264. * 删除自定义组件
  265. * @param $condition
  266. * @return array
  267. */
  268. public function deleteUtil($condition)
  269. {
  270. $res = model('diy_view_util')->delete($condition);
  271. return $this->success($res);
  272. }
  273. /**
  274. * 查询组件信息
  275. * @param $condition
  276. * @param $field
  277. * @return array
  278. */
  279. public function getUtilInfo($condition, $field)
  280. {
  281. $info = model('diy_view_util')->getInfo($condition, $field);
  282. return $this->success($info);
  283. }
  284. /**
  285. * 查询组件数量
  286. * @param $condition
  287. * @return array
  288. */
  289. public function getUtilCount($condition)
  290. {
  291. $info = model('diy_view_util')->getCount($condition);
  292. return $this->success($info);
  293. }
  294. /**
  295. * 获取自定义模板组件集合
  296. * @param array $condition
  297. * @param string $field
  298. * @param string $order
  299. * @param string $limit
  300. * @return array
  301. */
  302. public function getDiyViewUtilList($condition = [], $field = 'id,name,title,type,value,addon_name,support_diy_view,max_count,is_delete,icon', $order = 'sort asc', $limit = null)
  303. {
  304. $res = model('diy_view_util')->getList($condition, $field, $order, '', '', '', $limit);
  305. return $this->success($res);
  306. }
  307. /**
  308. * 添加自定义模板
  309. * @param $data
  310. * @return array
  311. */
  312. public function addSiteDiyView($data)
  313. {
  314. // 将同类页面的默认值改为0,默认页面只有一个
  315. if (!empty($data[ 'is_default' ])) {
  316. model("site_diy_view")->update([ 'is_default' => 0 ], [ [ 'site_id', '=', $data[ 'site_id' ] ], [ 'name', '=', $data[ 'name' ] ] ]);
  317. }
  318. $data[ 'create_time' ] = time();
  319. $res = model('site_diy_view')->add($data);
  320. if ($res) {
  321. Cache::tag("site_diy_view")->clear();
  322. return $this->success($res);
  323. } else {
  324. return $this->error($res);
  325. }
  326. }
  327. /**
  328. * 添加多条自定义模板数据
  329. * @param $data
  330. * @return array
  331. */
  332. public function addSiteDiyViewList($data)
  333. {
  334. $res = model('site_diy_view')->addList($data);
  335. if ($res) {
  336. Cache::tag("site_diy_view")->clear();
  337. return $this->success($res);
  338. } else {
  339. return $this->error($res);
  340. }
  341. }
  342. /**
  343. * 修改自定义模板
  344. * @param array $data
  345. * @param array $condition
  346. * @return array
  347. */
  348. public function editSiteDiyView($data, $condition)
  349. {
  350. // 将同类页面的默认值改为0,默认页面只有一个
  351. if (!empty($data[ 'is_default' ])) {
  352. model("site_diy_view")->update([ 'is_default' => 0 ], [ [ 'site_id', '=', $data[ 'site_id' ] ], [ 'name', '=', $data[ 'name' ] ] ]);
  353. }
  354. $data[ 'modify_time' ] = time();
  355. $res = model('site_diy_view')->update($data, $condition);
  356. if ($res) {
  357. Cache::tag("site_diy_view")->clear();
  358. return $this->success($res);
  359. } else {
  360. return $this->error($res);
  361. }
  362. }
  363. /**
  364. * 删除站点微页面
  365. * @param array $condition
  366. * @return array
  367. */
  368. public function deleteSiteDiyView($condition = [])
  369. {
  370. $res = model('site_diy_view')->delete($condition);
  371. if ($res) {
  372. Cache::tag("site_diy_view")->clear();
  373. return $this->success($res);
  374. } else {
  375. return $this->error($res);
  376. }
  377. }
  378. /**
  379. * 获取自定义模板数据集合
  380. * @param array $condition
  381. * @param string $order
  382. * @param string $field
  383. * @param string $alias
  384. * @param array $join
  385. * @return array
  386. */
  387. public function getSiteDiyViewList($condition = [], $order = '', $field = '*', $alias = '', $join = [])
  388. {
  389. $res = model('site_diy_view')->getList($condition, $field, $order, $alias, $join);
  390. return $this->success($res);
  391. }
  392. /**
  393. * 获取自定义模板分页数据集合
  394. * @param array $condition
  395. * @param int $page
  396. * @param int $page_size
  397. * @param string $order
  398. * @param string $field
  399. * @return array
  400. */
  401. public function getSiteDiyViewPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
  402. {
  403. $res = model('site_diy_view')->rawPageList($condition, $field, $order, $page, $page_size);
  404. return $this->success($res);
  405. }
  406. /**
  407. * 获取自定义模板信息
  408. * @param array $condition
  409. * @param string $field
  410. * @return array
  411. */
  412. public function getSiteDiyViewInfo($condition = [], $field = 'id,site_id,name,title,value')
  413. {
  414. $data = json_encode([ $condition, $field ]);
  415. $cache = Cache::get("site_diy_view_getSiteDiyViewInfo_" . $data);
  416. if (!empty($cache)) {
  417. return $this->success($cache);
  418. }
  419. $info = model('site_diy_view')->getInfo($condition, $field);
  420. Cache::tag("site_diy_view")->set("diy_view_getSiteDiyViewInfo_" . $data, $info);
  421. return $this->success($info);
  422. }
  423. /**
  424. * 获取自定义模板详细信息
  425. * @param array $condition
  426. * @return array
  427. */
  428. public function getSiteDiyViewDetail($condition = [])
  429. {
  430. $condition = array_column($condition, 2, 0);
  431. $site_id = $condition[ 'site_id' ];
  432. $data = json_encode($condition);
  433. $cache = Cache::get("diy_view_getSiteDiyViewDetail_" . $data);
  434. if (!empty($cache)) {
  435. return $this->success($cache);
  436. }
  437. $field = 'id,site_id,name,title,template_id,template_item_id,type,type_name,value,is_default';
  438. $info = model('site_diy_view')->getInfo($condition, $field);
  439. if (!empty($info) && !empty($info[ 'value' ])) {
  440. // 查询模板页面类型
  441. $diy_template = new Template();
  442. $diy_template_info = $diy_template->getTemplateInfo([ [ 'name', '=', $info[ 'name' ] ] ], 'title,name,rule')[ 'data' ];
  443. $util_condition = [];
  444. if (!empty($diy_template_info)) {
  445. $diy_template_info[ 'rule' ] = json_decode($diy_template_info[ 'rule' ], true);
  446. // 支持的自定义页面(为空表示公共组件都支持)
  447. if (!empty($diy_template_info[ 'rule' ][ 'support' ])) {
  448. $util_condition[] = [ 'support_diy_view', 'in', $diy_template_info[ 'rule' ][ 'support' ], 'or' ];
  449. }
  450. // 组件类型
  451. if (!empty($diy_template_info[ 'rule' ][ 'util_type' ])) {
  452. $util_condition[] = [ 'type', 'in', $diy_template_info[ 'rule' ][ 'util_type' ] ];
  453. }
  454. } else {
  455. // 自定义页面,只查询公共组件
  456. $util_condition[] = [ 'support_diy_view', '=', '' ];
  457. }
  458. $json_data = json_decode($info[ 'value' ], true);
  459. foreach ($json_data[ 'value' ] as $k => $v) {
  460. if (!empty($v[ 'addonName' ])) {
  461. $is_exit = addon_is_exit($v[ 'addonName' ], $site_id);
  462. // 检查插件是否存在
  463. if ($is_exit == 0) {
  464. unset($json_data[ 'value' ][ $k ]);
  465. continue;
  466. }
  467. }
  468. // 检测页面是否支持当前组件
  469. $util = $util_condition;
  470. $util[] = [ 'name', '=', $v[ 'componentName' ] ];
  471. $count = $this->getUtilCount($util)[ 'data' ];
  472. if ($count == 0) {
  473. unset($json_data[ 'value' ][ $k ]);
  474. continue;
  475. }
  476. }
  477. $json_data[ 'value' ] = array_values($json_data[ 'value' ]);
  478. $info[ 'value' ] = json_encode($json_data);
  479. }
  480. Cache::tag("site_diy_view")->set("diy_view_getSiteDiyViewDetail_" . $data, $info);
  481. return $this->success($info);
  482. }
  483. /**
  484. * 获取自定义页面数量
  485. * @param array $condition
  486. * @return array
  487. */
  488. public function getSiteViewCount($condition = [])
  489. {
  490. $count = model('site_diy_view')->getCount($condition);
  491. return $this->success($count);
  492. }
  493. /**
  494. * 设置平台端的底部导航配置
  495. * @param $data
  496. * @param $site_id
  497. * @return array
  498. */
  499. public function setBottomNavConfig($data, $site_id)
  500. {
  501. $config = new ConfigModel();
  502. $res = $config->setConfig($data, '店铺端自定义底部导航', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'DIY_VIEW_SHOP_BOTTOM_NAV_CONFIG_SHOP_' . $site_id ] ]);
  503. return $res;
  504. }
  505. /**
  506. * 获取平台端的底部导航配置
  507. * @param $site_id
  508. * @return array
  509. */
  510. public function getBottomNavConfig($site_id)
  511. {
  512. $config = new ConfigModel();
  513. $res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'DIY_VIEW_SHOP_BOTTOM_NAV_CONFIG_SHOP_' . $site_id ] ]);
  514. if (empty($res[ 'data' ][ 'value' ])) {
  515. $res[ 'data' ][ 'value' ] = [
  516. "type" => 1,
  517. "theme" => "default",
  518. "backgroundColor" => "#FFFFFF",
  519. "textColor" => "#333333",
  520. "textHoverColor" => "#FF4D4D",
  521. "bulge" => true,
  522. "list" => [
  523. [
  524. "iconPath" => "icondiy icon-system-shouyeweixuanzhongbeifen",
  525. "selectedIconPath" => "icondiy icon-system-shouyexuanzhongbeifen2",
  526. "text" => "主页",
  527. "link" => [
  528. "name" => "INDEX",
  529. "title" => "主页",
  530. "wap_url" => "/pages/index/index",
  531. "parent" => "MALL_LINK"
  532. ],
  533. "id" => "h1lx8nhr2lc0",
  534. "imgWidth" => "40",
  535. "imgHeight" => "40",
  536. "iconClass" => "icon-system-home",
  537. "icon_type" => "icon",
  538. "selected_icon_type" => "icon",
  539. "style" => [
  540. "fontSize" => 100,
  541. "iconBgColor" => [],
  542. "iconBgColorDeg" => 0,
  543. "iconBgImg" => "",
  544. "bgRadius" => 0,
  545. "iconColor" => [ "#000000" ],
  546. "iconColorDeg" => 0
  547. ],
  548. "selected_style" => [
  549. "fontSize" => 100,
  550. "iconBgColor" => [],
  551. "iconBgColorDeg" => 0,
  552. "iconBgImg" => "",
  553. "bgRadius" => 0,
  554. "iconColor" => [ "#FF4D4D" ],
  555. "iconColorDeg" => 0
  556. ]
  557. ],
  558. [
  559. "iconPath" => "icondiy icon-system-fenleiweixuanzhongbeifen2",
  560. "selectedIconPath" => "icondiy icon-system-fenleixuanzhongbeifen1",
  561. "text" => "商品分类",
  562. "link" => [
  563. "name" => "SHOP_CATEGORY",
  564. "title" => "商品分类",
  565. "wap_url" => "/pages/goods/category",
  566. "parent" => "MALL_LINK"
  567. ],
  568. "imgWidth" => "40",
  569. "imgHeight" => "40",
  570. "id" => "1dasmaqndsyo0",
  571. "iconClass" => "icon-system-category",
  572. "icon_type" => "icon",
  573. "selected_icon_type" => "icon",
  574. "style" => [
  575. "fontSize" => 100,
  576. "iconBgColor" => [],
  577. "iconBgColorDeg" => 0,
  578. "iconBgImg" => "",
  579. "bgRadius" => 0,
  580. "iconColor" => [ "#000000" ],
  581. "iconColorDeg" => 0
  582. ],
  583. "selected_style" => [
  584. "fontSize" => 100,
  585. "iconBgColor" => [],
  586. "iconBgColorDeg" => 0,
  587. "iconBgImg" => "",
  588. "bgRadius" => 0,
  589. "iconColor" => [ "#FF4D4D" ],
  590. "iconColorDeg" => 0
  591. ]
  592. ],
  593. [
  594. "iconPath" => "icondiy icon-system-cart",
  595. "selectedIconPath" => "icondiy icon-system-cart-selected",
  596. "text" => "购物车",
  597. "link" => [
  598. "name" => "SHOPPING_TROLLEY",
  599. "title" => "购物车",
  600. "wap_url" => "/pages/goods/cart",
  601. "parent" => "MALL_LINK"
  602. ],
  603. "imgWidth" => "40",
  604. "imgHeight" => "40",
  605. "id" => "1p1pm6ebtvs00",
  606. "iconClass" => "icon-system-cart",
  607. "icon_type" => "icon",
  608. "selected_icon_type" => "icon",
  609. "style" => [
  610. "fontSize" => 100,
  611. "iconBgColor" => [],
  612. "iconBgColorDeg" => 0,
  613. "iconBgImg" => "",
  614. "bgRadius" => 0,
  615. "iconColor" => [ "#000000" ],
  616. "iconColorDeg" => 0
  617. ],
  618. "selected_style" => [
  619. "fontSize" => 100,
  620. "iconBgColor" => [],
  621. "iconBgColorDeg" => 0,
  622. "iconBgImg" => "",
  623. "bgRadius" => 0,
  624. "iconColor" => [ "#FF4D4D" ],
  625. "iconColorDeg" => 0
  626. ]
  627. ],
  628. [
  629. "iconPath" => "icondiy icon-system-my",
  630. "selectedIconPath" => "icondiy icon-system-my-selected",
  631. "text" => "我的",
  632. "link" => [
  633. "name" => "MEMBER_CENTER",
  634. "title" => "会员中心",
  635. "wap_url" => "/pages/member/index",
  636. "parent" => "MALL_LINK"
  637. ],
  638. "imgWidth" => "40",
  639. "imgHeight" => "40",
  640. "id" => "1b2tc256egsg0",
  641. "iconClass" => "icon-system-my",
  642. "icon_type" => "icon",
  643. "selected_icon_type" => "icon",
  644. "style" => [
  645. "fontSize" => 100,
  646. "iconBgColor" => [],
  647. "iconBgColorDeg" => 0,
  648. "iconBgImg" => "",
  649. "bgRadius" => 0,
  650. "iconColor" => [ "#000000" ],
  651. "iconColorDeg" => 0
  652. ],
  653. "selected_style" => [
  654. "fontSize" => 100,
  655. "iconBgColor" => [],
  656. "iconBgColorDeg" => 0,
  657. "iconBgImg" => "",
  658. "bgRadius" => 0,
  659. "iconColor" => [ "#FF4D4D" ],
  660. "iconColorDeg" => 0
  661. ]
  662. ]
  663. ],
  664. "imgType" => 2,
  665. "iconColor" => "#333333",
  666. "iconHoverColor" => "#FF4D4D"
  667. ];
  668. }
  669. return $res;
  670. }
  671. /**
  672. * 设置店铺风格配置
  673. * @param $data
  674. * @param $site_id
  675. * @return array
  676. */
  677. public function setStyleConfig($data, $site_id)
  678. {
  679. $config = new ConfigModel();
  680. $res = $config->setConfig($data, '店铺风格设置', '1', [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STYLE_CONFIG' ] ]);
  681. return $res;
  682. }
  683. /**
  684. * 获取店铺风格配置
  685. * @param $site_id
  686. * @return array
  687. */
  688. public function getStyleConfig($site_id)
  689. {
  690. $config = new ConfigModel();
  691. $res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STYLE_CONFIG' ] ]);
  692. if (empty($res[ 'data' ][ 'value' ])) {
  693. $diy_theme_model = new Theme();
  694. $theme = $diy_theme_model->getFirstTheme([], 'id,title,name,main_color,aux_color', 'id asc')[ 'data' ];
  695. $res[ 'data' ][ 'value' ] = $theme;
  696. }
  697. return $res;
  698. }
  699. /**
  700. * 推广二维码
  701. * @param $params
  702. * @return array
  703. */
  704. public function qrcode($params)
  705. {
  706. $site_id = isset($params[ 'site_id' ]) ? $params[ 'site_id' ] : 0;
  707. $app_type = isset($params[ 'app_type' ]) ? $params[ 'app_type' ] : 'all';
  708. $condition = [
  709. [ 'site_id', '=', $params[ 'site_id' ] ],
  710. ];
  711. if (isset($params[ 'id' ])) {
  712. $condition[] = [ 'id', '=', $params[ 'id' ] ];
  713. }
  714. $diy_view_info = $this->getSiteDiyViewInfo($condition, 'id,name,is_default,template_id,template_item_id')[ 'data' ];
  715. if (empty($diy_view_info)) {
  716. return $this->success();
  717. }
  718. $page_path = '/pages_tool/index/diy';
  719. if ($diy_view_info[ 'name' ] == 'DIY_VIEW_GOODS_CATEGORY') {
  720. $page_path = '/pages/goods/category'; // 商品分类页面特殊处理
  721. }
  722. if ($diy_view_info[ 'name' ] == 'DIY_VIEW_MEMBER_INDEX') {
  723. $page_path = '/pages/member/index'; // 会员中心页面特殊处理
  724. }
  725. if ($diy_view_info[ 'name' ] == 'DIY_VIEW_INDEX' || $diy_view_info[ 'name' ] == 'DIY_STORE') {
  726. $page_path = ''; // 首页、门店页面特殊处理
  727. }
  728. $data = [
  729. 'app_type' => $app_type, // all为全部
  730. 'type' => isset($params[ 'type' ]) ? $params[ 'type' ] : 'create', // 类型 create创建 get获取
  731. 'site_id' => $site_id,
  732. 'data' => [
  733. 'id' => $diy_view_info[ 'id' ],
  734. "name" => $diy_view_info[ 'name' ]
  735. ],
  736. 'page' => $page_path,
  737. 'qrcode_path' => 'upload/qrcode/diy',
  738. 'qrcode_name' => "diy_qrcode_" . $diy_view_info[ 'name' ] . '_' . $diy_view_info[ 'template_id' ] . '_' . $diy_view_info[ 'template_item_id' ] . '_' . $site_id,
  739. ];
  740. event('Qrcode', $data, true);
  741. if ($app_type == 'all') {
  742. $app_type_list = config('app_type');
  743. } else {
  744. $app_type_list = [
  745. 'h5' => []
  746. ];
  747. }
  748. $path = [];
  749. $config = new ConfigModel();
  750. foreach ($app_type_list as $k => $v) {
  751. switch ( $k ) {
  752. case 'h5':
  753. $h5_domain = getH5Domain();
  754. $path[ $k ][ 'status' ] = 1;
  755. if ($diy_view_info[ 'name' ] == 'DIY_VIEW_INDEX' || $diy_view_info[ 'name' ] == 'DIY_VIEW_GOODS_CATEGORY' || $diy_view_info[ 'name' ] == 'DIY_VIEW_MEMBER_INDEX') {
  756. $path[ $k ][ 'url' ] = $h5_domain . $page_path;
  757. if ($diy_view_info[ 'is_default' ] == 0) {
  758. $path[ $k ][ 'url' ] .= '?id=' . $diy_view_info[ 'id' ];
  759. }
  760. } else {
  761. $path[ $k ][ 'url' ] = $h5_domain . $page_path . '?name=' . $diy_view_info[ 'name' ] . '&id=' . $diy_view_info[ 'id' ];
  762. }
  763. $path[ $k ][ 'img' ] = $data[ 'qrcode_path' ] . '/' . $data[ 'qrcode_name' ] . "_" . $k . ".png?" . time();
  764. break;
  765. case 'weapp':
  766. $res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'WEAPP_CONFIG' ] ]);
  767. if (!empty($res[ 'data' ])) {
  768. if (empty($res[ 'data' ][ 'value' ][ 'qrcode' ])) {
  769. $path[ $k ][ 'status' ] = 2;
  770. $path[ $k ][ 'message' ] = '未配置微信小程序';
  771. } else {
  772. $path[ $k ][ 'status' ] = 1;
  773. $path[ $k ][ 'img' ] = $res[ 'data' ][ 'value' ][ 'qrcode' ];
  774. }
  775. } else {
  776. $path[ $k ][ 'status' ] = 2;
  777. $path[ $k ][ 'message' ] = '未配置微信小程序';
  778. }
  779. break;
  780. case 'wechat':
  781. $res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'WECHAT_CONFIG' ] ]);
  782. if (!empty($res[ 'data' ])) {
  783. if (empty($res[ 'data' ][ 'value' ][ 'qrcode' ])) {
  784. $path[ $k ][ 'status' ] = 2;
  785. $path[ $k ][ 'message' ] = '未配置微信公众号';
  786. } else {
  787. $path[ $k ][ 'status' ] = 1;
  788. $path[ $k ][ 'img' ] = $res[ 'data' ][ 'value' ][ 'qrcode' ];
  789. }
  790. } else {
  791. $path[ $k ][ 'status' ] = 2;
  792. $path[ $k ][ 'message' ] = '未配置微信公众号';
  793. }
  794. break;
  795. }
  796. }
  797. $return = [
  798. 'path' => $path
  799. ];
  800. return $this->success($return);
  801. }
  802. /**
  803. * 根据页面路径生成二维码
  804. * @param $condition
  805. * @param string $type
  806. * @return array
  807. */
  808. public function qrcodeRoute($params)
  809. {
  810. $site_id = isset($params[ 'site_id' ]) ? $params[ 'site_id' ] : 0;
  811. $app_type = isset($params[ 'app_type' ]) ? $params[ 'app_type' ] : 'all';
  812. $data = [
  813. 'app_type' => $app_type, // all为全部
  814. 'type' => isset($params[ 'type' ]) ? $params[ 'type' ] : 'create', // 类型 create创建 get获取
  815. 'site_id' => $site_id,
  816. 'data' => [
  817. "name" => $params[ 'name' ],
  818. ],
  819. 'page' => $params[ 'path' ],
  820. 'qrcode_path' => 'upload/qrcode/diy',
  821. 'qrcode_name' => "diy_qrcode_" . $params[ 'name' ] . '_' . $site_id,
  822. ];
  823. $qrcode_result = event('Qrcode', $data, true);
  824. $app_type_list = config('app_type');
  825. if (!empty($app_type) && $app_type != 'all' && in_array($app_type, [ 'h5', 'wechat', 'weapp' ])) {
  826. $app_type_list = [
  827. $app_type => []
  828. ];
  829. }
  830. $path = [];
  831. $config = new ConfigModel();
  832. foreach ($app_type_list as $k => $v) {
  833. switch ( $k ) {
  834. case 'h5':
  835. case 'wechat':
  836. $h5_domain = getH5Domain();
  837. $path[ $k ][ 'status' ] = 1;
  838. $path[ $k ][ 'url' ] = $h5_domain . $params[ 'path' ];
  839. $path[ $k ][ 'img' ] = $data[ 'qrcode_path' ] . '/' . $data[ 'qrcode_name' ] . "_" . $k . ".png?" . time();
  840. break;
  841. case 'weapp':
  842. $res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'WEAPP_CONFIG' ] ]);
  843. if (!empty($res[ 'data' ])) {
  844. if ($qrcode_result[ 'code' ] >= 0) {
  845. $path[ $k ][ 'status' ] = 1;
  846. $path[ $k ][ 'img' ] = $qrcode_result[ 'data' ][ 'path' ];
  847. } else {
  848. $path[ $k ][ 'status' ] = 2;
  849. $path[ $k ][ 'message' ] = $qrcode_result[ 'message' ];
  850. }
  851. } else {
  852. $path[ $k ][ 'status' ] = 2;
  853. $path[ $k ][ 'message' ] = '未配置微信小程序';
  854. }
  855. break;
  856. }
  857. }
  858. $return = [
  859. 'path' => $path
  860. ];
  861. return $this->success($return);
  862. }
  863. /**
  864. * 设为使用
  865. * @param $port
  866. * @param $type
  867. * @param $id
  868. * @param $site_id
  869. * @return array
  870. */
  871. public function setUse($id, $site_id)
  872. {
  873. model('site_diy_view')->startTrans();
  874. try {
  875. $info = model('site_diy_view')->getInfo([ [ 'id', '=', $id ], [ 'site_id', '=', $site_id ] ], 'name');
  876. if (empty($info)) {
  877. return $this->error('页面不存在');
  878. }
  879. model('site_diy_view')->update([ 'is_default' => 0 ], [ [ 'name', '=', $info[ 'name' ] ], [ 'site_id', '=', $site_id ] ]);
  880. model('site_diy_view')->update([ 'is_default' => 1 ], [ [ 'id', '=', $id ], [ 'site_id', '=', $site_id ] ]);
  881. Cache::tag("site_diy_view")->clear();
  882. model('site_diy_view')->commit();
  883. return $this->success();
  884. } catch (\Exception $e) {
  885. model('site_diy_view')->rollback();
  886. return $this->error($e->getMessage());
  887. }
  888. }
  889. /**
  890. * 修改微页面排序
  891. * @param $sort
  892. * @param $id
  893. * @return array
  894. */
  895. public function modifyDiyViewSort($sort, $id)
  896. {
  897. $res = model('site_diy_view')->update([ 'sort' => $sort ], [ [ 'id', '=', $id ] ]);
  898. Cache::tag("site_diy_view")->clear();
  899. return $this->success($res);
  900. }
  901. /**
  902. * 修改微页面点击量
  903. * @param $condition
  904. * @return array
  905. */
  906. public function modifyClick($condition)
  907. {
  908. model("site_diy_view")->setInc($condition, 'click_num', 1);
  909. return $this->success(1);
  910. }
  911. /**
  912. * 图标风格
  913. * @return array
  914. */
  915. public function iconStyle()
  916. {
  917. return [
  918. // [
  919. // "fontSize" => 50,
  920. // "iconBgColor" => [
  921. // "#7b00ff"
  922. // ],
  923. // "iconBgColorDeg" => 0,
  924. // "iconBgImg" => "",
  925. // "bgRadius" => 19,
  926. // "iconColor" => [
  927. // "#fff"
  928. // ],
  929. // "iconColorDeg" => 0
  930. // ],
  931. [
  932. "fontSize" => 50,
  933. "iconBgColor" => [
  934. "#0068ff"
  935. ],
  936. "iconBgColorDeg" => 0,
  937. "iconBgImg" => "",
  938. "bgRadius" => 38,
  939. "iconColor" => [
  940. "#fff"
  941. ],
  942. "iconColorDeg" => 0
  943. ],
  944. [
  945. "fontSize" => 50,
  946. "iconBgColor" => [
  947. "#ff1c1c"
  948. ],
  949. "iconBgColorDeg" => 0,
  950. "iconBgImg" => "",
  951. "bgRadius" => 50,
  952. "iconColor" => [
  953. "#fff"
  954. ],
  955. "iconColorDeg" => 0
  956. ],
  957. [
  958. "fontSize" => 50,
  959. "iconBgColor" => [
  960. "#fa6400"
  961. ],
  962. "iconBgColorDeg" => 0,
  963. "iconBgImg" => "public/static/ext/diyview/img/icon_bg/bg_01.png",
  964. "bgRadius" => 19,
  965. "iconColor" => [
  966. "#fff"
  967. ],
  968. "iconColorDeg" => 0
  969. ],
  970. [
  971. "fontSize" => 50,
  972. "iconBgColor" => [
  973. "#b620e0"
  974. ],
  975. "iconBgColorDeg" => 0,
  976. "iconBgImg" => "public/static/ext/diyview/img/icon_bg/bg_02.png",
  977. "bgRadius" => 19,
  978. "iconColor" => [
  979. "#fff"
  980. ],
  981. "iconColorDeg" => 0
  982. ],
  983. [
  984. "fontSize" => 50,
  985. "iconBgColor" => [
  986. "#ff3c5a"
  987. ],
  988. "iconBgColorDeg" => 0,
  989. "iconBgImg" => "public/static/ext/diyview/img/icon_bg/bg_03.png",
  990. "bgRadius" => 19,
  991. "iconColor" => [
  992. "#fff"
  993. ],
  994. "iconColorDeg" => 0
  995. ],
  996. [
  997. "fontSize" => 50,
  998. "iconBgColor" => [
  999. "#ff9200"
  1000. ],
  1001. "iconBgColorDeg" => 0,
  1002. "iconBgImg" => "public/static/ext/diyview/img/icon_bg/bg_04.png",
  1003. "bgRadius" => 19,
  1004. "iconColor" => [
  1005. "#fff"
  1006. ],
  1007. "iconColorDeg" => 0
  1008. ],
  1009. [
  1010. "fontSize" => 50,
  1011. "iconBgColor" => [
  1012. "#44d7b6"
  1013. ],
  1014. "iconBgColorDeg" => 0,
  1015. "iconBgImg" => "public/static/ext/diyview/img/icon_bg/bg_05.png",
  1016. "bgRadius" => 38,
  1017. "iconColor" => [
  1018. "#fff"
  1019. ],
  1020. "iconColorDeg" => 0
  1021. ],
  1022. [
  1023. "fontSize" => 50,
  1024. "iconBgColor" => [
  1025. "#ff5615"
  1026. ],
  1027. "iconBgColorDeg" => 0,
  1028. "iconBgImg" => "public/static/ext/diyview/img/icon_bg/bg_06.png",
  1029. "bgRadius" => 50,
  1030. "iconColor" => [
  1031. "#fff"
  1032. ],
  1033. "iconColorDeg" => 0
  1034. ],
  1035. [
  1036. "fontSize" => 100,
  1037. "iconBgColor" => [],
  1038. "iconBgColorDeg" => 0,
  1039. "iconBgImg" => "",
  1040. "bgRadius" => 0,
  1041. "iconColor" => [
  1042. "#be71ff",
  1043. "#8e00ff"
  1044. ],
  1045. "iconColorDeg" => 125
  1046. ]
  1047. ];
  1048. }
  1049. /**
  1050. * 编译uni-app,生成压缩包下载
  1051. * 主题风格、图标库、组件、页面、路由
  1052. * @param $params
  1053. * @return array
  1054. */
  1055. public function compileUniApp($params)
  1056. {
  1057. // 查询店铺正在使用的模板
  1058. $diy_template_model = new Template();
  1059. $site_diy_template_info = $diy_template_model->getSiteDiyTemplateInfo([
  1060. [ 'is_default', '=', 1 ],
  1061. [ 'site_id', '=', $params[ 'site_id' ] ]
  1062. ], 'name,template_goods_id,addon_name')[ 'data' ];
  1063. if (empty($site_diy_template_info)) {
  1064. return $this->error('', '没有找到正在使用的模板,请设置默认模板');
  1065. }
  1066. // 找到uni-app项目
  1067. $uniapp_path = 'upload/temp/standard_uniapp'; // uni-app文件夹
  1068. $compile_path = 'upload/temp/compile_uniapp'; // 编译后的uni-app文件夹,临时位置,生成压缩包后删除
  1069. // <= 2 是因为[ .,.. ]
  1070. if (!is_dir($uniapp_path) || count(scandir($uniapp_path)) <= 2) {
  1071. return $this->error('', '没有找到uni-app文件');
  1072. }
  1073. // 编译后的uni-app文件夹
  1074. if (is_dir($compile_path)) {
  1075. // 先将之前的文件删除
  1076. if (count(scandir($compile_path)) > 2) deleteDir($compile_path);
  1077. } else {
  1078. // 创建uni-app目录
  1079. mkdir($compile_path, intval('0777', 8), true);
  1080. }
  1081. try {
  1082. // 编译uni-app项目
  1083. $this->copyFile($uniapp_path, $compile_path, $compile_path, $site_diy_template_info);
  1084. // 编译pages页面
  1085. $this->getCompilePageCode($compile_path, $site_diy_template_info[ 'addon_name' ]);
  1086. // 编译页面路由
  1087. $this->getCompileRoutesCode($compile_path, $site_diy_template_info[ 'addon_name' ]);
  1088. // 生成压缩包文件
  1089. $file_arr = getFileMap($compile_path);
  1090. if (!empty($file_arr)) {
  1091. $zipname = 'upload/compile_uniapp_' . date('Ymd') . '.zip';
  1092. $zip = new \ZipArchive();
  1093. $res = $zip->open($zipname, \ZipArchive::CREATE);
  1094. if ($res === TRUE) {
  1095. foreach ($file_arr as $file_path => $file_name) {
  1096. if (is_dir($file_path)) {
  1097. $file_path = str_replace($compile_path . '/', '', $file_path);
  1098. $zip->addEmptyDir($file_path);
  1099. } else {
  1100. $zip_path = str_replace($compile_path . '/', '', $file_path);
  1101. $zip->addFile($file_path, $zip_path);
  1102. }
  1103. }
  1104. $zip->close();
  1105. header("Content-Type: application/zip");
  1106. header("Content-Transfer-Encoding: Binary");
  1107. header("Content-Length: " . filesize($zipname));
  1108. header("Content-Disposition: attachment; filename=\"" . basename($zipname) . "\"");
  1109. readfile($zipname);
  1110. @unlink($zipname);
  1111. deleteDir($compile_path); // 删除临时文件
  1112. deleteDir($uniapp_path); // 删除临时文件
  1113. }
  1114. }
  1115. return $this->success();
  1116. } catch (\Exception $e) {
  1117. return $this->error('', 'Error File:' . $e->getFile() . ',Line:' . $e->getLine() . ',Message:' . $e->getMessage());
  1118. }
  1119. }
  1120. /**
  1121. * 复制文件
  1122. * @param string $source_path 源文件路径
  1123. * @param string $to_path 目标位置
  1124. * @param string $compile_path 编译路径
  1125. * @param array $site_diy_template_info 店铺正在使用的模板
  1126. */
  1127. private function copyFile($source_path, $to_path, $compile_path, $site_diy_template_info)
  1128. {
  1129. $files = scandir($source_path);
  1130. foreach ($files as $path) {
  1131. if ($path != '.' && $path != '..') {
  1132. $temp_path = $source_path . '/' . $path;
  1133. if (is_dir($temp_path)) {
  1134. // 创建文件夹
  1135. mkdir($to_path . '/' . $path, intval('0777', 8), true);
  1136. $this->copyFile($temp_path, $to_path . '/' . $path, $compile_path, $site_diy_template_info);
  1137. } else {
  1138. if (file_exists($temp_path)) {
  1139. copy($temp_path, $to_path . '/' . $path);
  1140. // 找到主题风格文件 common/js/style_color.js
  1141. if (preg_match("/common\/js\/style_color.js$/", $temp_path)) {
  1142. $content = $this->getCompileThemeCode($site_diy_template_info[ 'addon_name' ]);// 写入内容
  1143. file_put_contents($to_path . '/' . $path, $content);
  1144. }
  1145. // 找到图标库文件 common/css/icon/extend.css
  1146. if (preg_match("/common\/css\/icon\/extend.css$/", $temp_path)) {
  1147. $content = $this->getCompileIconCode($compile_path, $site_diy_template_info[ 'addon_name' ]); // 写入内容
  1148. file_put_contents($to_path . '/' . $path, $content);
  1149. }
  1150. // 找到组件扩展文件 diy-comp-extend.vue
  1151. if (preg_match("/diy-comp-extend.vue$/", $temp_path)) {
  1152. $content = $this->getCompileComponentCode($compile_path, $site_diy_template_info[ 'addon_name' ]); // 写入内容
  1153. file_put_contents($to_path . '/' . $path, $content);
  1154. }
  1155. }
  1156. }
  1157. }
  1158. }
  1159. }
  1160. /**
  1161. * 获取编译主题风格代码
  1162. * 编写顺序
  1163. * 1、查询所有主题风格列表,条件:main_color、aux_color 不为空的数据
  1164. * 2、编译代码内容并返回
  1165. * @param $addon_name
  1166. * @return string
  1167. */
  1168. private function getCompileThemeCode($addon_name)
  1169. {
  1170. // 查询店铺正在使用的模板,主题风格列表,以及系统主题风格
  1171. $diy_theme_model = new Theme();
  1172. $theme_list = $diy_theme_model->getThemeList([
  1173. [ 'main_color', '<>', '' ],
  1174. [ 'aux_color', '<>', '' ],
  1175. [ 'addon_name', 'in', [ '', $addon_name ] ]
  1176. ], 'id, title, name, main_color, aux_color, value')[ 'data' ];
  1177. $content = "export default {\r\n";
  1178. foreach ($theme_list as $k => $v) {
  1179. $value = [];
  1180. if (!empty($v[ 'value' ])) {
  1181. $value = json_decode($v[ 'value' ]);
  1182. }
  1183. $content .= " '{$v['name']}' : {\r\n";
  1184. $content .= " // {$v['title']}:{$v['id']}\r\n";
  1185. $content .= " 'name' : '{$v['name']}',\r\n";
  1186. $content .= " 'main_color' : '{$v['main_color']}',\r\n";
  1187. $content .= " 'aux_color' : '{$v['aux_color']}',\r\n";
  1188. foreach ($value as $ck => $cv) {
  1189. $type = gettype($cv);
  1190. if ($type == 'string') {
  1191. $content .= " '{$ck}' : '{$cv}',\r\n";
  1192. } elseif ($type == 'object' && !empty($cv)) {
  1193. $content .= " '{$ck}' : {\r\n";
  1194. foreach ($cv as $third_k => $third_v) {
  1195. $content .= " '{$third_k}' : '{$third_v}',\r\n";
  1196. }
  1197. $content .= " },\r\n";
  1198. }
  1199. }
  1200. $content .= " },\r\n";
  1201. }
  1202. $content .= '}';
  1203. return $content;
  1204. }
  1205. /**
  1206. * 获取编译图标库代码
  1207. * 编写顺序
  1208. * 1、查询店铺正在使用的模板,图标库,以及系统图标
  1209. * 2、循环列表,找到图标文件并复制,文件名称要重命名,目的是防止文件名称重复
  1210. * 3、将文件复制到指定文件目录下,common/css/icon 文件夹下,common/css/icon/extend.css 文件中引用图标库文件
  1211. * @param $compile_path
  1212. * @param $addon_name
  1213. * @return string
  1214. */
  1215. private function getCompileIconCode($compile_path, $addon_name)
  1216. {
  1217. // 查询店铺正在使用的模板,图标库,以及系统图标
  1218. $icon_list = $this->getIconAllList([ 'addon_name' => $addon_name ])[ 'icon' ];
  1219. $content = "/* 引用扩展图标库文件 */\n";
  1220. foreach ($icon_list as $k => $v) {
  1221. // 检测文件是否存在
  1222. if (file_exists($v[ 'path' ])) {
  1223. $path_arr = explode('/', $v[ 'path' ]);
  1224. $file_name = $path_arr[ count($path_arr) - 1 ];
  1225. // 生成新文件名称,防止重复
  1226. $file_name = str_replace('.css', '_' . random_keys(5) . '.css', $file_name);
  1227. // 将文件复制到指定文件目录下
  1228. copy($v[ 'path' ], $compile_path . '/common/css/icon/' . $file_name);
  1229. $content .= "@import url('{$file_name}');\n";
  1230. }
  1231. }
  1232. return $content;
  1233. }
  1234. /**
  1235. * 获取编译组件代码
  1236. * 编写顺序
  1237. * 1、查询店铺正在使用的模板,扩展组件列表
  1238. * 2、循环列表,复制文件/文件夹,存放到对应目录下
  1239. * 3、如果是自定义组件文件,前缀开头:diy-,编写代码,写入到 diy-comp-extend.vue 文件中
  1240. * @param $compile_path
  1241. * @param $addon_name
  1242. * @return string
  1243. */
  1244. private function getCompileComponentCode($compile_path, $addon_name)
  1245. {
  1246. // 查询店铺正在使用的模板,扩展组件列表
  1247. $component_list = $this->getExtendComponentList([ 'addon_name' => $addon_name ]);
  1248. $content = <<<EOT
  1249. <template>
  1250. <view>
  1251. <!-- 扩展组件 -->\n
  1252. EOT;
  1253. foreach ($component_list as $k => $v) {
  1254. // 检查文件/文件夹是否存在
  1255. if (file_exists($v[ 'path' ])) {
  1256. $path = str_replace('addon/' . $addon_name . '/uniapp/', '', $v[ 'path' ]);
  1257. $path_arr = explode('/', $path);
  1258. $file_name = $path_arr[ count($path_arr) - 1 ];
  1259. // 文件复制
  1260. if (is_file($v[ 'path' ])) {
  1261. copy($v[ 'path' ], $compile_path . '/' . $path);
  1262. // 检测文件是否为自定义扩展组件,前缀开头:diy-
  1263. if (strpos($file_name, 'diy-') !== false) {
  1264. $file_name = str_replace('.vue', '', $file_name);
  1265. $content .= " <template v-if=\"value.componentName == '{$v['name']}'\">\n";
  1266. $content .= " <$file_name :value=\"value\"></{$file_name}>\n";
  1267. $content .= " </template>\n";
  1268. }
  1269. }
  1270. // 文件夹复制
  1271. if (is_dir($v[ 'path' ])) {
  1272. dir_copy($v[ 'path' ], $compile_path . '/' . $path);
  1273. }
  1274. }
  1275. }
  1276. $content .= <<<EOT
  1277. </view>
  1278. </template>
  1279. <script>
  1280. // 自定义扩展组件
  1281. export default {
  1282. name: 'diy-comp-extend',
  1283. props: {
  1284. value: {
  1285. type: Object
  1286. }
  1287. },
  1288. data() {
  1289. return {};
  1290. },
  1291. computed: {},
  1292. created() {},
  1293. methods: {}
  1294. };
  1295. </script>
  1296. <style></style>\n
  1297. EOT;
  1298. return $content;
  1299. }
  1300. /**
  1301. * 编译pages页面
  1302. * 编写顺序
  1303. * 1、查询店铺正在使用的模板,页面列表
  1304. * 2、循环列表,将页面文件存放到对应目录下,存在则替换
  1305. * @param $compile_path
  1306. * @param $addon_name
  1307. */
  1308. private function getCompilePageCode($compile_path, $addon_name)
  1309. {
  1310. // 查询店铺正在使用的模板,页面列表
  1311. $page_list = $this->getUniAppPageList([ 'addon_name' => $addon_name ]);
  1312. foreach ($page_list as $k => $v) {
  1313. // 检查文件是否存在
  1314. if (file_exists($v[ 'path' ])) {
  1315. $file = $compile_path . '/' . $v[ 'route' ] . '.vue';
  1316. $route = explode('/', $v[ 'route' ]);
  1317. unset($route[ count($route) - 1 ]); // 清除最后一项页面
  1318. $folder = $compile_path;
  1319. foreach ($route as $ck => $cv) {
  1320. $folder .= "/{$cv}";
  1321. // 创建uni-app目录
  1322. if (!is_dir($folder)) {
  1323. mkdir($folder, intval('0777', 8), true);
  1324. }
  1325. }
  1326. // 复制文件,存在则覆盖
  1327. copy($v[ 'path' ], $file);
  1328. }
  1329. }
  1330. }
  1331. /**
  1332. * 编译页面路由代码
  1333. * 编写顺序
  1334. * 1、查询店铺正在使用的模板,页面列表
  1335. * 2、循环【pages、pages_promotion、pages_tool】包,找到页面路由集合
  1336. * 3、分3次处理页面路由集合,编译代码内容
  1337. * 4、找到页面路由文件 pages.jon 写入内容
  1338. * @param $compile_path
  1339. * @param $addon_name
  1340. * @return bool|int
  1341. */
  1342. private function getCompileRoutesCode($compile_path, $addon_name)
  1343. {
  1344. // 查询店铺正在使用的模板,页面列表
  1345. $page_list = $this->getUniAppPageList([ 'addon_name' => $addon_name ]);
  1346. $package = [ 'pages', 'pages_promotion', 'pages_tool' ];// 主包、营销活动分包、其他分包
  1347. // 特殊页面,隐藏导航栏
  1348. $special_page = [
  1349. 'pages/index/index', 'pages/member/index',
  1350. 'pages/goods/detail', 'topics/goods_detail', 'seckill/detail',
  1351. 'pintuan/detail', 'groupbuy/detail', 'pinfan/detail', 'presale/detail',
  1352. 'pages/order/payment', 'topics/payment', 'seckill/payment', 'pintuan/payment', 'bargain/payment', 'groupbuy/payment',
  1353. 'pinfan/payment', 'presale/payment', 'bale/payment'
  1354. ];
  1355. $route_arr = []; // 路由集合
  1356. foreach ($package as $k => $v) {
  1357. $file_arr = getFileMap($compile_path . '/' . $v);
  1358. if (!empty($file_arr)) {
  1359. foreach ($file_arr as $ck => $cv) {
  1360. if (strpos($cv, '.vue') !== false) {
  1361. $route = str_replace($compile_path . '/', '', $ck);
  1362. $route = str_replace('.vue', '', $route);
  1363. $route_arr[ $v ][] = $route;
  1364. }
  1365. }
  1366. }
  1367. }
  1368. // 排序
  1369. foreach ($package as $k => $v) {
  1370. sort($route_arr[ $v ], SORT_STRING);
  1371. }
  1372. // 获取首页下标
  1373. $index_page = array_search('pages/index/index', $route_arr[ 'pages' ]);
  1374. $index_route = $route_arr[ 'pages' ][ $index_page ];
  1375. // 将首页设为启动页
  1376. $route_arr[ 'pages' ][ $index_page ] = $route_arr[ 'pages' ][ 0 ];
  1377. $route_arr[ 'pages' ][ 0 ] = $index_route;
  1378. $content = "{\n";
  1379. // 主包
  1380. $content .= " \"pages\" : [ // pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages\n";
  1381. foreach ($route_arr[ 'pages' ] as $k => $v) {
  1382. $content .= " {\n";
  1383. $content .= " \"path\" : \"{$v}\",\n";
  1384. $content .= " \"style\" : {\n";
  1385. // 找到页面 style,追加数据
  1386. $page_index = array_search($v, array_column($page_list, 'route'));
  1387. if ($page_index !== false && !empty($page_list[ $page_index ][ 'style' ])) {
  1388. $style = $page_list[ $page_index ][ 'style' ];
  1389. if (in_array($v, $special_page)) {
  1390. $content .= " \"navigationStyle\" : \"custom\",\n";
  1391. } else {
  1392. $content .= " // #ifdef H5\n";
  1393. $content .= " \"navigationStyle\" : \"custom\",\n";
  1394. $content .= " // #endif\n";
  1395. }
  1396. $style_index = 0;
  1397. foreach ($style as $style_k => $style_v) {
  1398. $content .= " \"{$style_k}\" : \"{$style_v}\"";
  1399. // 最后一个不能加逗号,
  1400. if (( count($style) - 1 ) == $style_index) {
  1401. $content .= "\n";
  1402. } else {
  1403. $content .= ",\n";
  1404. }
  1405. $style_index++;
  1406. }
  1407. } else {
  1408. if (in_array($v, $special_page)) {
  1409. $content .= " \"navigationStyle\" : \"custom\"\n";
  1410. } else {
  1411. $content .= " // #ifdef H5\n";
  1412. $content .= " \"navigationStyle\" : \"custom\"\n";
  1413. $content .= " // #endif\n";
  1414. }
  1415. }
  1416. $content .= " }\n";
  1417. // 最后一个不能加逗号,
  1418. if (( count($route_arr[ 'pages' ]) - 1 ) == $k) {
  1419. $content .= " }\n";
  1420. } else {
  1421. $content .= " },\n";
  1422. }
  1423. }
  1424. $content .= " ],\n";
  1425. // 分包
  1426. $content .= " \"subPackages\" : [\n";
  1427. // 分包——营销活动
  1428. $content .= " {\n";
  1429. $content .= " \"root\": \"pages_promotion\",\n";
  1430. $content .= " \"pages\": [\n";
  1431. foreach ($route_arr[ 'pages_promotion' ] as $k => $v) {
  1432. $path = str_replace('pages_promotion/', '', $v);
  1433. $content .= " {\n";
  1434. $content .= " \"path\": \"{$path}\",\n";
  1435. $content .= " \"style\" : {\n";
  1436. // 找到页面 style,追加数据
  1437. $page_index = array_search($v, array_column($page_list, 'route'));
  1438. if ($page_index !== false && !empty($page_list[ $page_index ][ 'style' ])) {
  1439. $style = $page_list[ $page_index ][ 'style' ];
  1440. if (in_array($path, $special_page)) {
  1441. $content .= " \"navigationStyle\" : \"custom\",\n";
  1442. } else {
  1443. $content .= " // #ifdef H5\n";
  1444. $content .= " \"navigationStyle\" : \"custom\",\n";
  1445. $content .= " // #endif\n";
  1446. }
  1447. $style_index = 0;
  1448. foreach ($style as $style_k => $style_v) {
  1449. $content .= " \"{$style_k}\" : \"{$style_v}\"";
  1450. // 最后一个不能加逗号,
  1451. if (( count($style) - 1 ) == $style_index) {
  1452. $content .= "\n";
  1453. } else {
  1454. $content .= ",\n";
  1455. }
  1456. $style_index++;
  1457. }
  1458. } else {
  1459. if (in_array($path, $special_page)) {
  1460. $content .= " \"navigationStyle\" : \"custom\"\n";
  1461. } else {
  1462. $content .= " // #ifdef H5\n";
  1463. $content .= " \"navigationStyle\" : \"custom\"\n";
  1464. $content .= " // #endif\n";
  1465. }
  1466. }
  1467. $content .= " }\n";
  1468. // 最后一个不能加逗号,
  1469. if (( count($route_arr[ 'pages_promotion' ]) - 1 ) == $k) {
  1470. $content .= " }\n";
  1471. } else {
  1472. $content .= " },\n";
  1473. }
  1474. }
  1475. $content .= " ]\n";
  1476. $content .= " },\n";
  1477. // 分包——其他
  1478. $content .= " {\n";
  1479. $content .= " \"root\": \"pages_tool\",\n";
  1480. $content .= " \"pages\": [\n";
  1481. foreach ($route_arr[ 'pages_tool' ] as $k => $v) {
  1482. $path = str_replace('pages_tool/', '', $v);
  1483. $content .= " {\n";
  1484. $content .= " \"path\": \"{$path}\",\n";
  1485. $content .= " \"style\" : {\n";
  1486. // 找到页面 style,追加数据
  1487. $page_index = array_search($v, array_column($page_list, 'route'));
  1488. if ($page_index !== false && !empty($page_list[ $page_index ][ 'style' ])) {
  1489. $style = $page_list[ $page_index ][ 'style' ];
  1490. if (in_array($path, $special_page)) {
  1491. $content .= " \"navigationStyle\" : \"custom\",\n";
  1492. } else {
  1493. $content .= " // #ifdef H5\n";
  1494. $content .= " \"navigationStyle\" : \"custom\",\n";
  1495. $content .= " // #endif\n";
  1496. }
  1497. $style_index = 0;
  1498. foreach ($style as $style_k => $style_v) {
  1499. $content .= " \"{$style_k}\" : \"{$style_v}\"";
  1500. // 最后一个不能加逗号,
  1501. if (( count($style) - 1 ) == $style_index) {
  1502. $content .= "\n";
  1503. } else {
  1504. $content .= ",\n";
  1505. }
  1506. $style_index++;
  1507. }
  1508. } else {
  1509. if (in_array($path, $special_page)) {
  1510. $content .= " \"navigationStyle\" : \"custom\"\n";
  1511. } else {
  1512. $content .= " // #ifdef H5\n";
  1513. $content .= " \"navigationStyle\" : \"custom\"\n";
  1514. $content .= " // #endif\n";
  1515. }
  1516. }
  1517. $content .= " }\n";
  1518. // 最后一个不能加逗号,
  1519. if (( count($route_arr[ 'pages_tool' ]) - 1 ) == $k) {
  1520. $content .= " }\n";
  1521. } else {
  1522. $content .= " },\n";
  1523. }
  1524. }
  1525. $content .= " ]\n";
  1526. $content .= " }\n";
  1527. $content .= " ],\n";
  1528. // globalStyle
  1529. $content .= " \"globalStyle\": {\n";
  1530. $content .= " \"navigationBarTextStyle\": \"black\",\n";
  1531. $content .= " \"navigationBarTitleText\": \"\",\n";
  1532. $content .= " \"navigationBarBackgroundColor\": \"#ffffff\",\n";
  1533. $content .= " \"backgroundColor\": \"#F7f7f7\",\n";
  1534. $content .= " \"backgroundColorTop\": \"#f7f7f7\",\n";
  1535. $content .= " \"backgroundColorBottom\": \"#f7f7f7\"\n";
  1536. $content .= " },\n";
  1537. // tabBar
  1538. $content .= " \"tabBar\": {\n";
  1539. $content .= " // #ifdef H5\n";
  1540. $content .= " \"custom\": true,\n";
  1541. $content .= " // #endif\n";
  1542. $content .= " \"color\": \"#333\",\n";
  1543. $content .= " \"selectedColor\": \"#FF0036\",\n";
  1544. $content .= " \"backgroundColor\": \"#fff\",\n";
  1545. $content .= " \"borderStyle\": \"white\",\n";
  1546. $content .= " \"list\": [\n";
  1547. $content .= " {\n";
  1548. $content .= " \"pagePath\": \"pages/index/index\",\n";
  1549. $content .= " \"text\": \"首页\"\n";
  1550. $content .= " },\n";
  1551. $content .= " {\n";
  1552. $content .= " \"pagePath\": \"pages/goods/category\",\n";
  1553. $content .= " \"text\": \"分类\"\n";
  1554. $content .= " },\n";
  1555. $content .= " {\n";
  1556. $content .= " \"pagePath\": \"pages/goods/cart\",\n";
  1557. $content .= " \"text\": \"购物车\"\n";
  1558. $content .= " },\n";
  1559. $content .= " {\n";
  1560. $content .= " \"pagePath\": \"pages/member/index\",\n";
  1561. $content .= " \"text\": \"个人中心\"\n";
  1562. $content .= " }\n";
  1563. $content .= " ]\n";
  1564. $content .= " },\n";
  1565. // easycom
  1566. $content .= " \"easycom\": {\n";
  1567. $content .= " \"diy-*(\\W.*)\": \"@/components/diy-components/diy$1.vue\"\n";
  1568. $content .= " },\n";
  1569. // preloadRule
  1570. $content .= " \"preloadRule\": {\n";
  1571. $content .= " \"pages/index/index\": {\n";
  1572. $content .= " \"network\": \"all\",\n";
  1573. $content .= " \"packages\": [\"pages_tool\"]\n";
  1574. $content .= " }\n";
  1575. $content .= " }\n";
  1576. $content .= "}\n";
  1577. // 找到页面路由文件 pages.json,写入内容
  1578. $res = file_put_contents($compile_path . '/pages.json', $content);
  1579. return $res;
  1580. }
  1581. // 处理自定义模板的非法数据
  1582. // public function handleDiyData($params)
  1583. // {
  1584. // try {
  1585. // $condition = [
  1586. // [ 'site_id', '=', $params[ 'site_id' ] ],
  1587. // ];
  1588. // $info = model('site_diy_view')->getInfo($condition, 'id,value');
  1589. // if (!empty($info) && !empty($info[ 'value' ])) {
  1590. // $value = json_decode($info[ 'value' ], true);
  1591. //
  1592. // foreach ($value[ 'value' ] as $ck => $cv) {
  1593. //
  1594. // // 公告组件
  1595. // if ($cv[ 'componentName' ] == 'Notice') {
  1596. //
  1597. //// $cv['noticeIds']
  1598. // $notice = new Notice();
  1599. // $notice->getNoticeCount();
  1600. //
  1601. // // 搜索框组件,v5.1.7新增
  1602. // if (!isset($cv[ 'searchLink' ])) {
  1603. // $value[ 'value' ][ $ck ][ 'searchLink' ] = [
  1604. // "name" => ""
  1605. // ];
  1606. // }
  1607. //
  1608. // }
  1609. // }
  1610. // }
  1611. // } catch (\Exception $e) {
  1612. // model('site_diy_view')->rollback();
  1613. // }
  1614. // }
  1615. }