DiyRepository.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\common\repositories\system\diy;
  12. use app\common\dao\system\diy\DiyDao;
  13. use app\common\model\system\merchant\Merchant;
  14. use app\common\repositories\BaseRepository;
  15. use app\common\repositories\system\config\ConfigValueRepository;
  16. use app\common\repositories\system\merchant\MerchantRepository;
  17. use app\common\repositories\system\RelevanceRepository;
  18. use crmeb\services\QrcodeService;
  19. use think\exception\ValidateException;
  20. use think\facade\Cache;
  21. use think\facade\Db;
  22. /**
  23. * Diy
  24. */
  25. class DiyRepository extends BaseRepository
  26. {
  27. const IS_DEFAULT_DIY = 'is_default_diy';
  28. const IS_DIY_DIY = 1;
  29. const IS_DIY_MICRO = 0;
  30. const IS_DIY_PRODUCT = 2;
  31. public function __construct(DiyDao $dao)
  32. {
  33. $this->dao = $dao;
  34. }
  35. public function getList(array $where, int $page, int $limit )
  36. {
  37. $query = $this->dao->search($where);
  38. $count = $query->count();
  39. $list = $query->page($page,$limit)->select();
  40. return compact('count','list');
  41. }
  42. public function getThemeVar($type)
  43. {
  44. $var = [
  45. 'purple' => [
  46. 'type' => 'purple',
  47. 'theme_color' => '#905EFF',
  48. 'assist_color' => '#FDA900',
  49. 'theme' => '--view-theme: #905EFF;--view-assist:#FDA900;--view-priceColor:#905eff;--view-bgColor:rgba(144, 94, 255, 0.06);--view-minorColor:rgba(144, 94, 255,.1);--view-bntColor11:#FFC552;--view-bntColor12:#FDB000;--view-bntColor21:#905EFF;--view-bntColor22:#A764FF;'
  50. ],
  51. 'orange' => [
  52. 'type' => 'orange',
  53. 'theme_color' => '#FF5C2D',
  54. 'assist_color' => '#FDB000',
  55. 'theme' => '--view-theme: #FF5C2D;--view-assist:#FDB000;--view-priceColor:#FF5C2D;--view-bgColor:rgba(255, 92, 45, 0.06);--view-minorColor:rgba(255, 92, 45,.1);--view-bntColor11:#FDBA00;--view-bntColor12:#FFAA00;--view-bntColor21:#FF5C2D;--view-bntColor22:#FF9445;'
  56. ],
  57. 'pink' => [
  58. 'type' => 'pink',
  59. 'theme_color' => '#FF448F',
  60. 'assist_color' => '#FDB000',
  61. 'theme' => '--view-theme: #FF448F;--view-assist:#FDB000;--view-priceColor:#FF448F;--view-bgColor:rgba(255, 68, 143, 0.06);--view-minorColor:rgba(255, 68, 143,.1);--view-bntColor11:#FDBA00;--view-bntColor12:#FFAA00;--view-bntColor21:#FF67AD;--view-bntColor22:#FF448F;'
  62. ],
  63. 'default' => [
  64. 'type' => 'default',
  65. 'theme_color' => '#E93323',
  66. 'assist_color' => '#FF7612',
  67. 'theme' => '--view-theme: #E93323;--view-assist:#FF7612;--view-priceColor:#E93323;--view-bgColor:rgba(233, 51, 35, 0.06);--view-minorColor:rgba(233, 51, 35,.1);--view-bntColor11:#FEA10F;--view-bntColor12:#FA8013;--view-bntColor21:#FA6514;--view-bntColor22:#E93323;'
  68. ],
  69. 'green' => [
  70. 'type' => 'green',
  71. 'theme_color' => '#42CA4D',
  72. 'assist_color' => '#FE960F',
  73. 'theme' => '--view-theme: #42CA4D;--view-assist:#FE960F;--view-priceColor:#42ca4d;--view-bgColor:rgba(66, 202, 77, 0.06);--view-minorColor:rgba(66, 202, 77,.1);--view-bntColor11:#FDBA00;--view-bntColor12:#FFAA00;--view-bntColor21:#42CA4D;--view-bntColor22:#70E038;'
  74. ],
  75. 'blue' => [
  76. 'type' => 'blue',
  77. 'theme_color' => '#1DB0FC',
  78. 'assist_color' => '#FFB200',
  79. 'theme' => '--view-theme: #1DB0FC;--view-assist:#FFB200;--view-priceColor:#1db0fc;--view-bgColor:rgba(29, 176, 252, 0.06);--view-minorColor:rgba(29, 176, 252,.1);--view-bntColor11:#FFD652;--view-bntColor12:#FEB60F;--view-bntColor21:#40D1F4;--view-bntColor22:#1DB0FC;'
  80. ],
  81. ];
  82. return $var[$type] ?? $var['default'];
  83. }
  84. /**
  85. * 平台后台的商户默认模板列表
  86. * @param array $where
  87. * @param int $page
  88. * @param int $limit
  89. * @return array
  90. * @author Qinii
  91. * @day 2023/9/4
  92. */
  93. public function getMerDefaultList(array $where,int $page, int $limit)
  94. {
  95. $field = 'is_diy,template_name,id,title,name,type,add_time,update_time,status,is_default';
  96. $query = $this->dao->getSearch($where)->where('is_default',2)->whereOr(function($query){
  97. $query->where('type',2)->where('is_default',1);
  98. })->order('is_default DESC, status DESC, update_time DESC,add_time DESC');
  99. $count = $query->count();
  100. $list = $query->page($page, $limit)->setOption('field',[])->field($field)->select()
  101. ->each(function($item) use($where){
  102. if ($item['is_default']) {
  103. $id = merchantConfig(0, self::IS_DEFAULT_DIY) ?: 0;
  104. $item['status'] = ($id == $item['id']) ? 1 : 0;
  105. return $item;
  106. }
  107. });
  108. return compact('count','list');
  109. }
  110. /**
  111. * 获取DIY列表
  112. * @param array $where
  113. * @return array
  114. * @throws \think\db\exception\DataNotFoundException
  115. * @throws \think\db\exception\DbException
  116. * @throws \think\db\exception\ModelNotFoundException
  117. */
  118. public function getSysList(array $where,int $page, int $limit)
  119. {
  120. $field = 'is_diy,template_name,id,title,name,type,add_time,update_time,status,is_default';
  121. $query = $this->dao->getSearch($where)->order('is_default DESC, status DESC, update_time DESC,add_time DESC');
  122. $count = $query->count();
  123. $list = $query->page($page, $limit)->setOption('field',[])->field($field)->select()
  124. ->each(function($item) use($where){
  125. if ($item['is_default']) {
  126. $id = merchantConfig(0, self::IS_DEFAULT_DIY) ?: 0;
  127. $item['status'] = ($id == $item['id']) ? 1 : 0;
  128. return $item;
  129. }
  130. });
  131. return compact('count','list');
  132. }
  133. /**
  134. * 商户获取diy列表
  135. * @param array $where
  136. * @param int $page
  137. * @param int $limit
  138. * @return array
  139. * @author Qinii
  140. * @day 2023/7/14
  141. */
  142. public function getMerchantList(array $where,int $page, int $limit)
  143. {
  144. $field = 'is_diy,template_name,id,title,name,type,add_time,update_time,status,is_default';
  145. $id = merchantConfig($where['mer_id'], self::IS_DEFAULT_DIY) ?: 0;
  146. $query = $this->dao->search($where)->order('is_default DESC, status DESC, update_time DESC,add_time DESC');
  147. $count = $query->count();
  148. $list = $query->page($page, $limit)->setOption('field',[])->field($field)->select()
  149. ->each(function($item) use($id){
  150. $item['status'] = ($id == $item['id']) ? 1 : 0;
  151. return $item;
  152. });
  153. return compact('count','list');
  154. }
  155. /**
  156. * 商户获取自己的默认模板
  157. * @param array $where
  158. * @param int $page
  159. * @param int $limit
  160. * @author Qinii
  161. * @day 2023/9/4
  162. */
  163. public function getMerchantDefaultList(array $where,int $page, int $limit)
  164. {
  165. $field = 'is_diy,template_name,id,title,name,type,add_time,update_time,status,is_default';
  166. $query = $this->dao->search($where)->order('is_default DESC, status DESC, update_time DESC,add_time DESC');
  167. $count = $query->count();
  168. $list = $query->page($page, $limit)->setOption('field',[])->field($field)->select();
  169. return compact('count','list');
  170. }
  171. /**
  172. * 保存资源
  173. * @param int $id
  174. * @param array $data
  175. * @return int
  176. */
  177. public function saveData(int $id = 0, array $data)
  178. {
  179. if ($id) {
  180. if ($data['type'] === '') {
  181. unset($data['type']);
  182. }
  183. $data['update_time'] = date('Y-m-d H:i:s',time());
  184. $this->dao->update($id, $data);
  185. } else {
  186. $data['status'] = 0;
  187. $data['add_time'] = date('Y-m-d H:i:s',time());
  188. $data['update_time'] = date('Y-m-d H:i:s',time());
  189. $res = $this->dao->create($data);
  190. if (!$res) throw new ValidateException('保存失败');
  191. $id = $res->id;
  192. }
  193. $where = [
  194. 'is_diy' => 1,
  195. 'is_del' => 0,
  196. 'id' => $id
  197. ];
  198. ksort($where);
  199. $cache_unique = 'get_sys_diy_'. md5(json_encode($where));
  200. Cache::delete($cache_unique);
  201. $micro_unique = 'sys.get_sys_micro_'.$id;
  202. Cache::delete($micro_unique);
  203. return $id;
  204. }
  205. /**
  206. * 删除DIY模板
  207. * @param int $id
  208. */
  209. public function del(int $id, $merId)
  210. {
  211. $diyData = $this->dao->getWhere(['id' => $id]);
  212. if (!$diyData) throw new ValidateException('数据不存在');
  213. if ($diyData['is_default'] && $merId) throw new ValidateException('无权删除默认模板');
  214. if ($diyData['is_default']){
  215. $count = $this->dao->search(['type' => $diyData['type']])
  216. ->where('is_default','<>',0)
  217. ->where('id','<>',$id)
  218. ->count();
  219. if (!$count)throw new ValidateException('至少存在一个默认模板');
  220. }
  221. $res = $this->dao->delete($id);
  222. if (!$res) throw new ValidateException('删除失败,请稍后再试');
  223. }
  224. /**
  225. * 获取diy详细数据
  226. * @param int $id
  227. * @return array|object
  228. * @throws \think\db\exception\DataNotFoundException
  229. * @throws \think\db\exception\DbException
  230. * @throws \think\db\exception\ModelNotFoundException
  231. */
  232. public function getMicro($id)
  233. {
  234. $where = ['id' => $id,'is_diy' => 0];
  235. $data = [];
  236. $diyInfo = $this->dao->getWhere($where);
  237. if ($diyInfo) {
  238. $data = $diyInfo->toArray();
  239. $data['value'] = json_decode($diyInfo['value'], true);
  240. }
  241. return compact('data');
  242. }
  243. /**
  244. * 商城首页/商户首页/预览等调用获取diy详情
  245. * @param int $merId
  246. * @param int $id
  247. * @param int $isDiy
  248. * @return array
  249. * @author Qinii
  250. * @day 2023/7/15
  251. */
  252. public function show(int $merId, int $id,int $isDiy = 1)
  253. {
  254. $where = [
  255. 'is_diy' => $isDiy,
  256. 'is_del' => 0,
  257. ];
  258. if (!$id) {
  259. $id = merchantConfig($merId, self::IS_DEFAULT_DIY);
  260. if (!$id || ($id && !$this->dao->get($id))) {
  261. if ($merId) {
  262. $merchant = app()->make(MerchantRepository::class)->get($merId);
  263. if (empty($merchant)) throw new ValidateException('商户信息有误!');
  264. $scop = [
  265. 'mer_id' => $merId,
  266. 'type_id'=> $merchant->type_id,
  267. 'category_id'=> $merchant->category_id,
  268. 'is_trader'=> $merchant->is_trader,
  269. ];
  270. $ids = $this->dao->withMerSearch($scop);
  271. if (empty($ids)) $ids = $this->dao->search(['is_default' => 1,'type' => 2])->column('id');
  272. } else {
  273. $ids = $this->dao->search(['is_default' => 1,'type' => 1])->column('id');
  274. }
  275. if (empty($ids)) throw new ValidateException('模板获取失败,请联系管理员!');
  276. $id = $ids[array_rand($ids,1)];
  277. }
  278. }
  279. $where['id'] = $id;
  280. ksort($where);
  281. $cache_unique = 'get_sys_diy_' . md5(json_encode($where));
  282. $data = Cache::remember($cache_unique,function()use($merId,$id,$where){
  283. $diyInfo = $this->dao->getWhere($where);
  284. if ($diyInfo) {
  285. if ($diyInfo['mer_id'] != $merId && !$diyInfo['is_default']) throw new ValidateException('模板不存在或不属于您');
  286. $diyInfo = $diyInfo->toArray();
  287. $diyInfo['value'] = json_decode($diyInfo['value'], true);
  288. } else {
  289. $diyInfo = [];
  290. }
  291. return json_encode($diyInfo, JSON_UNESCAPED_UNICODE);
  292. }, 3600);
  293. $data = json_decode($data);
  294. return compact('data');
  295. }
  296. /**
  297. * 获取底部导航
  298. * @param string $template_name
  299. * @return array|mixed
  300. */
  301. public function getNavigation()
  302. {
  303. $id = merchantConfig(0, self::IS_DEFAULT_DIY);
  304. $diyInfo = $this->dao->getWhere(['id' => $id,'is_del' => 0],'value');
  305. if (!$diyInfo) {
  306. $where = ['is_default' => 1,];
  307. $diyInfo = $this->dao->getWhere($where,'value');
  308. }
  309. $navigation = [];
  310. if ($diyInfo) {
  311. $value = json_decode($diyInfo['value'], true);
  312. foreach ($value as $item) {
  313. if (isset($item['name']) && strtolower($item['name']) === 'pagefoot') {
  314. $navigation = $item;
  315. break;
  316. }
  317. }
  318. }
  319. return $navigation;
  320. }
  321. /**
  322. * 复制数据条目
  323. *
  324. * 该方法用于根据给定的ID复制一条数据记录。主要应用于需要生成类似但不完全相同的数据的情况,
  325. * 比如复制一个商品、订单或其他需要保留原始信息但又需要独立标识的数据实体。
  326. *
  327. * @param int $id 需要复制的数据的主键ID
  328. * @param int $merId 商户ID,用于标识数据是属于哪个商户的,0表示平台复制
  329. * @return array 包含新复制数据的ID的信息
  330. * @throws ValidateException 如果原数据不存在,则抛出异常
  331. */
  332. public function copy($id, $merId)
  333. {
  334. // 根据ID获取原始数据
  335. $data = $this->dao->getWhere([$this->dao->getPk() => $id]);
  336. // 如果原始数据不存在,则抛出异常
  337. if (!$data) throw new ValidateException('数据不存在');
  338. // 将查询结果转换为数组格式
  339. $data = $data->toArray();
  340. // 生成新的数据名称,标识这是一个复制的版本
  341. $data['name'] = ($merId ? '商户复制-' : '平台复制-' ).$data['name'].'-copy';
  342. // 设置新的添加时间和更新时间
  343. $data['add_time'] = date('Y-m-d H:i:s',time());
  344. $data['update_time'] = date('Y-m-d H:i:s',time());
  345. // 设置新数据的状态为0,表示未启用或待处理
  346. $data['status'] = 0;
  347. // 设置商户ID,如果$merId非0,则表示这是属于某个商户的数据
  348. $data['mer_id'] = $merId;
  349. // 设置范围类型为0,表示全局范围
  350. $data['scope_type'] = 0;
  351. // 如果是平台复制且数据类型为2,则设置为默认数据
  352. $data['is_default'] = (!$merId && $data['type'] == 2) ? 1 : 0;
  353. // 删除原始的主键ID,因为这是复制新的数据记录
  354. unset($data[$this->dao->getPk()]);
  355. // 创建新的数据记录
  356. $res = $this->dao->create($data);
  357. // 获取新创建数据的主键ID
  358. $id = $res[$this->dao->getPk()];
  359. // 返回包含新数据ID的信息
  360. return compact('id');
  361. }
  362. /**
  363. * 设置模板的使用状态。
  364. * 此方法用于将指定的模板设置为使用状态,并确保操作的模板属于当前商家或为默认模板。
  365. * 如果模板不存在或不属于当前商家且不是默认模板,将抛出异常。
  366. * 使用事务处理来确保数据库操作的一致性。
  367. *
  368. * @param int $id 模板的ID。
  369. * @param int $merId 商家的ID。
  370. * @return mixed 返回事务处理的结果。
  371. * @throws ValidateException 如果模板不存在或模板不属于当前商家且不是默认模板,则抛出此异常。
  372. */
  373. public function setUsed(int $id, int $merId)
  374. {
  375. // 根据ID获取模板信息
  376. $diyInfo = $this->dao->getWhere(['id' => $id]);
  377. // 如果模板不存在,则抛出异常
  378. if (!$diyInfo) throw new ValidateException('模板不存在');
  379. // 如果模板的商家ID不等于当前商家ID且模板不是默认模板,则抛出异常
  380. if ($diyInfo['mer_id'] != $merId && !$diyInfo['is_default']) {
  381. throw new ValidateException('模板不属于你');
  382. }
  383. // 实例化配置值仓库类
  384. $make = app()->make(ConfigValueRepository::class);
  385. // 使用事务处理来设置模板的使用状态和默认模板状态
  386. return Db::transaction(function () use($id, $merId, $make){
  387. // 设置模板为使用状态
  388. $this->dao->setUsed($id, $merId);
  389. // 设置默认模板的ID
  390. return $make->setFormData([self::IS_DEFAULT_DIY => $id ], $merId);
  391. });
  392. }
  393. /**
  394. * 根据条件获取选项数据
  395. *
  396. * 本函数旨在通过特定的条件从数据库中检索选项的标签和值。这些选项通常用于下拉列表或其他形式的选项集合中。
  397. * 使用DAO模式,它委托了实际的数据检索操作给DAO对象,保持了业务逻辑与数据访问逻辑的分离。
  398. *
  399. * @param array $where 查询条件数组,用于筛选选项数据。
  400. * @return array 返回一个数组,其中每个元素包含两个键:'label' 和 'value',分别对应选项的显示标签和实际值。
  401. */
  402. public function getOptions(array $where)
  403. {
  404. // 使用DAO对象执行查询,根据$where条件获取搜索结果,并指定返回的字段为'name'作为标签,'id'作为值。
  405. return $this->dao->getSearch($where)->field('name label, id value')->select();
  406. }
  407. /**
  408. * 获取没个模板的适用范围
  409. * @param $id
  410. * @return array|\think\Model|null
  411. * @author Qinii
  412. * @day 2023/7/15
  413. */
  414. public function getScope($id)
  415. {
  416. $res = $this->dao->getWhere(['id' => $id],'id,scope_type',['relevance']);
  417. $scope_value = [];
  418. foreach ($res['relevance'] as $item) {
  419. $scope_value[] = $item['right_id'];
  420. }
  421. unset($res['relevance']);
  422. $data['scope_type'] = is_null($res['scope_type']) ? 4 : $res['scope_type'];
  423. $data['scope_value'] = $scope_value;
  424. return $data;
  425. }
  426. /**
  427. * 保存模板的适用范围
  428. * @param $id
  429. * @param $data
  430. * @return mixed
  431. * @author Qinii
  432. * @day 2023/7/15
  433. */
  434. public function setScope($id,$data)
  435. {
  436. $rest = $this->dao->get($id);
  437. if (!$rest) throw new ValidateException('数据不存在');
  438. if ($rest->type != 2 && !$rest->is_default) throw new ValidateException('非默认模板');
  439. //DIY默认模板适用范围 0. 指定店铺、1. 指定商户分类、2. 指定店铺类型、3. 指定商户类别、4.全部店铺
  440. $relevanceRepository = app()->make(RelevanceRepository::class);
  441. $oldRelevanceType = RelevanceRepository::MER_DIY_SCOPE[$rest['scope_type']] ?? '';
  442. $relevanceType = RelevanceRepository::MER_DIY_SCOPE[$data['scope_type']] ?? '';
  443. return Db::transaction(function() use($id,$data,$relevanceRepository,$rest,$relevanceType,$oldRelevanceType) {
  444. if ($oldRelevanceType) $relevanceRepository->clear($id,$oldRelevanceType);
  445. if (!empty($data['scope_value']) && $relevanceType) {
  446. $relevanceRepository->createMany($id,$data['scope_value'],$relevanceType);
  447. }
  448. $rest->scope_type = $data['scope_type'];
  449. return $rest->save();
  450. });
  451. }
  452. /**
  453. * 生成小程序预览二维码
  454. * @param $id
  455. * @param $merId
  456. * @return bool|int|mixed|string
  457. * @author Qinii
  458. * @day 2023/9/12
  459. */
  460. public function review($id,$merId)
  461. {
  462. $name = 'view_diy_routine_'.$id.'_'.$merId.'.jpg';
  463. $qrcodeService = app()->make(QrcodeService::class);
  464. $link = 'pages/admin/storeDiy/index';
  465. $params = 'diy_id='.$id .'&id='.$merId;
  466. return $qrcodeService->getRoutineQrcodePath($name, $link, $params,'routine/diy');
  467. }
  468. public function getProductDetail()
  469. {
  470. $diyInfo = $this->dao->getWhere(['is_diy' => self::IS_DIY_PRODUCT,'is_del' => 0,'mer_id' => 0]);
  471. $data['product_detail_diy'] = json_decode($diyInfo['value'], true);
  472. return $data;
  473. }
  474. public function saveProductDetail($data)
  475. {
  476. $data['is_diy'] = self::IS_DIY_PRODUCT;
  477. $res = $this->dao->getWhere(['is_diy' => self::IS_DIY_PRODUCT,'is_del' => 0,'mer_id' => 0]);
  478. $data['value'] = json_encode($data['product_detail_diy'], JSON_UNESCAPED_UNICODE);
  479. unset($data['product_detail_diy']);
  480. if ($res) {
  481. $this->dao->update($res->id, $data);
  482. } else {
  483. $this->dao->create($data);
  484. }
  485. $key = env('APP_KEY').'_sys.get_sys_product_detail';
  486. Cache::delete($key);
  487. return true;
  488. }
  489. }