DeliveryStationRepository.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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\delivery;
  12. use app\common\dao\delivery\DeliveryStationDao;
  13. use app\common\repositories\BaseRepository;
  14. use app\common\repositories\system\config\ConfigClassifyRepository;
  15. use app\common\repositories\system\config\ConfigValueRepository;
  16. use crmeb\services\DeliverySevices;
  17. use FormBuilder\Factory\Elm;
  18. use think\Exception;
  19. use think\exception\ValidateException;
  20. use think\facade\Cache;
  21. use think\facade\Db;
  22. use think\facade\Route;
  23. /**
  24. * 同城配送门店
  25. */
  26. class DeliveryStationRepository extends BaseRepository
  27. {
  28. public function __construct(DeliveryStationDao $dao)
  29. {
  30. $this->dao = $dao;
  31. }
  32. /**
  33. * 同城配送设置表单生成方法
  34. * 该方法用于构建同城配送的配置表单,包括是否开启同城配送、选择配送类型以及相应的配置项。
  35. * 配送类型可以是达达快送或UU跑腿,每种配送类型需要不同的配置参数,如AppKey、AppSecret等。
  36. *
  37. * @return \think\response\View 返回一个包含同城配送设置表单的视图
  38. */
  39. public function deliveryForm()
  40. {
  41. // 从系统配置中获取同城配送相关的配置数据
  42. $formData = systemConfig([
  43. 'delivery_status',
  44. 'uupt_appkey',
  45. 'uupt_app_id',
  46. 'uupt_open_id',
  47. 'delivery_type',
  48. 'dada_app_key',
  49. 'dada_app_sercret',
  50. 'dada_source_id',
  51. ]);
  52. // 构建表单提交的URL
  53. $formActionUrl = Route::buildUrl('systemDeliveryConfigSave')->build();
  54. // 使用Element UI构建表单
  55. $form = Elm::createForm($formActionUrl);
  56. // 设置表单规则,包括是否开启同城配送的开关和选择配送类型的单选按钮
  57. $form->setRule([
  58. // 开关控件,用于开启或关闭同城配送
  59. Elm::switches('delivery_status', '是否开启同城配送:', $formData['delivery_status'])->activeValue(1)->inactiveValue(0)->inactiveText('关')->activeText('开'),
  60. // 单选按钮,用于选择配送服务类型:达达快送或UU跑腿
  61. Elm::radio('delivery_type', '配送类型:', $formData['delivery_type'])
  62. ->setOptions([
  63. ['value' => DeliverySevices::DELIVERY_TYPE_DADA, 'label' => '达达快送'],
  64. ['value' => DeliverySevices::DELIVERY_TYPE_UU, 'label' => 'UU跑腿'],
  65. ])
  66. ->control([
  67. // 配送类型为达达快送时的配置项:AppKey、AppSecret和商户ID
  68. [
  69. 'value' => DeliverySevices::DELIVERY_TYPE_DADA,
  70. 'rule' => [
  71. Elm::input('dada_app_key', 'AppKey (达达):')->value($formData['dada_app_key'])->placeholder('请输入AppKey (达达)')->required(),
  72. Elm::input('dada_app_sercret', 'AppSercret (达达):')->value($formData['dada_app_sercret'])->placeholder('请输入AppSercret (达达)')->required(),
  73. Elm::input('dada_source_id', '商户ID (达达):')->value($formData['dada_source_id'])->placeholder('请输入商户ID (达达)')->required(),
  74. ]
  75. ],
  76. // 配送类型为UU跑腿时的配置项:AppKey、AppId和OpenId
  77. [
  78. 'value' => DeliverySevices::DELIVERY_TYPE_UU,
  79. 'rule' => [
  80. Elm::input('uupt_appkey', 'AppKey (UU跑腿):')->value($formData['uupt_appkey'])->placeholder('请输入AppKey (UU跑腿)')->required(),
  81. Elm::input('uupt_app_id', 'AppId (UU跑腿):')->value($formData['uupt_app_id'])->placeholder('请输入AppId (UU跑腿)')->required(),
  82. Elm::input('uupt_open_id', 'OpenId (UU跑腿):')->value($formData['uupt_open_id'])->placeholder('请输入OpenId (UU跑腿)')->required(),
  83. ]
  84. ],
  85. ]),
  86. ]);
  87. // 设置表单标题
  88. $form->setTitle('同城配送设置');
  89. // 返回包含构建好的表单的视图
  90. return $form;
  91. }
  92. /**
  93. * 获取支持配送类型
  94. * @return mixed
  95. * @author Qinii
  96. */
  97. public function getBusiness()
  98. {
  99. $type = systemConfig('delivery_type');
  100. return DeliverySevices::create($type)->getBusiness();
  101. }
  102. /**
  103. * 创建门店
  104. * @param array $data
  105. * @return mixed
  106. * @author Qinii
  107. * @day 2/14/22
  108. */
  109. public function save(array $data)
  110. {
  111. return Db::transaction(function () use ($data) {
  112. $data['origin_shop_id'] = 'Deliver' . $data['mer_id'] . '_' . $this->getSn();
  113. DeliverySevices::create(systemConfig('delivery_type'))->addShop([$data]);
  114. return $this->dao->create($data);
  115. });
  116. }
  117. /**
  118. * 生成订单编号
  119. *
  120. * 本函数旨在生成一个唯一的订单编号。编号由微秒时间戳和一个随机整数组成,
  121. * 以此确保订单编号的全局唯一性。
  122. *
  123. * @return string 返回生成的订单编号
  124. */
  125. public function getSn()
  126. {
  127. // 获取当前时间的微秒和秒部分
  128. list($msec, $sec) = explode(' ', microtime());
  129. // 将微秒和秒转换为毫秒,并去掉小数点,确保编号是整数
  130. $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
  131. // 生成订单编号:毫秒时间戳后跟一个4位随机数,确保唯一性
  132. // 随机数生成范围是10000到当前毫秒时间戳转换的整数加10000,或98369之间的较大值
  133. // 这样做是为了避免在极短的时间内生成相同的订单编号
  134. $orderId = $msectime . random_int(10000, max(intval($msec * 10000) + 10000, 98369));
  135. return $orderId;
  136. }
  137. /**
  138. * 更新门店
  139. * @param $id
  140. * @param $data
  141. * @return mixed
  142. * @author Qinii
  143. * @day 2/14/22
  144. */
  145. public function edit($id, $merId, $data)
  146. {
  147. $res = $this->dao->getSearch([$this->dao->getPk() => $id, 'mer_id' => $merId])->find();
  148. if (!$res) throw new ValidateException('门店不存在或不属于您');
  149. $type = systemConfig('delivery_type');
  150. $data['origin_shop_id'] = $res['origin_shop_id'];
  151. return Db::transaction(function () use ($id, $type, $data, $res) {
  152. if ($res['type'] == 2 && $data['type'] == 1) {
  153. DeliverySevices::create($type)->addShop($data);
  154. } else {
  155. DeliverySevices::create($type)->updateShop($data);
  156. }
  157. return $this->dao->update($id, $data);
  158. });
  159. }
  160. /**
  161. * 商户门店列表
  162. * @param array $where
  163. * @param int $page
  164. * @param int $limit
  165. * @return array
  166. * @author Qinii
  167. * @day 2/17/22
  168. */
  169. public function merList(array $where, int $page, int $limit)
  170. {
  171. $query = $this->dao->getSearch($where);
  172. $count = $query->count();
  173. $list = $query->page($page, $limit)->order('create_time DESC')->select();
  174. return compact('count', 'list');
  175. }
  176. /**
  177. * 系统门店列表
  178. * @param array $where
  179. * @param int $page
  180. * @param int $limit
  181. * @return array
  182. * @author Qinii
  183. */
  184. public function sysList(array $where, int $page, int $limit)
  185. {
  186. $query = $this->dao->getSearch($where)->with([
  187. 'merchant' => function ($query) {
  188. $query->field('mer_id,mer_name');
  189. }
  190. ]);
  191. $count = $query->count();
  192. $list = $query->page($page, $limit)->order('create_time DESC')->select();
  193. return compact('count', 'list');
  194. }
  195. /**
  196. * 根据ID和商户ID获取详细信息
  197. *
  198. * 本函数用于查询指定ID和可选的商户ID对应的数据详情。特别地,它还会加载该数据关联的商户信息,
  199. * 但只包含商户的ID和名称。如果查询结果为空,则抛出一个验证异常,指出门店不存在。
  200. *
  201. * @param int $id 数据主键ID
  202. * @param int|null $merId 商户ID,可为空,表示不按商户ID过滤
  203. * @return array 查询到的数据详情
  204. * @throws ValidateException 如果未查询到数据,则抛出门店不存在的异常
  205. */
  206. public function detail(int $id, ?int $merId)
  207. {
  208. // 根据主键ID准备查询条件
  209. $where[$this->dao->getPk()] = $id;
  210. // 如果提供了商户ID,则加入查询条件
  211. if ($merId) $where['mer_id'] = $merId;
  212. // 执行查询,并加载关联的商户信息,但只包含指定的字段
  213. $res = $this->dao->getSearch($where)
  214. ->with([
  215. 'merchant' => function ($query) {
  216. // 明确指定查询商户的ID和名称
  217. $query->field('mer_id,mer_name');
  218. }
  219. ])
  220. ->find();
  221. // 如果查询结果为空,则抛出异常,指出门店不存在
  222. if (!$res) throw new ValidateException('门店不存在');
  223. // 返回查询结果
  224. return $res;
  225. }
  226. /**
  227. * 删除数据条目。
  228. *
  229. * 本函数用于根据给定的ID和商户ID删除特定的数据项。它首先通过ID和商户ID查询数据是否存在,
  230. * 如果数据不存在,则抛出一个验证异常;如果数据存在,则执行删除操作。
  231. *
  232. * @param int $id 数据项的主键ID。
  233. * @param int $merId 商户的ID,用于确定数据项所属的商户。
  234. * @return bool 返回删除操作的结果,通常是TRUE表示删除成功,FALSE表示删除失败。
  235. * @throws ValidateException 如果查询的数据项不存在,则抛出此异常。
  236. */
  237. public function destory($id, $merId)
  238. {
  239. // 根据主键ID和商户ID构建查询条件
  240. $where = [
  241. $this->dao->getPk() => $id,
  242. 'mer_id' => $merId,
  243. ];
  244. // 根据查询条件查找数据项
  245. $res = $this->dao->getSearch($where)->find();
  246. // 如果查询结果为空,即数据项不存在,则抛出异常
  247. if (!$res) throw new ValidateException('数据不存在');
  248. // 执行删除操作,并返回删除结果
  249. return $this->dao->delete($id);
  250. }
  251. /**
  252. * 标记商家订单 form 的生成方法
  253. *
  254. * 本方法用于生成一个用于商家标记订单的表单。通过传入订单ID和商家ID,
  255. * 方法检索订单的当前备注信息,并构建一个表单以允许商家添加或更新订单备注。
  256. *
  257. * @param int $id 订单ID,用于定位特定的订单。
  258. * @param int $merId 商家ID,用于确定操作订单的商家。
  259. * @return string 返回生成的表单HTML代码。
  260. */
  261. public function markForm($id, $merId)
  262. {
  263. // 根据订单ID和商家ID构建查询条件
  264. $where = [
  265. $this->dao->getPk() => $id,
  266. 'mer_id' => $merId,
  267. ];
  268. // 根据查询条件获取订单的当前备注信息
  269. $formData = $this->dao->getWhere($where);
  270. // 构建表单URL,指向处理商家订单标记的路由
  271. $formUrl = Route::buildUrl('merchantStoreDeliveryMark', ['id' => $id])->build();
  272. // 创建表单对象,并设置表单提交的URL
  273. $form = Elm::createForm($formUrl);
  274. // 设置表单的验证规则,这里仅包含一个文本输入框用于输入备注信息
  275. $form->setRule([
  276. Elm::text('mark', '备注:', $formData['mark'])->placeholder('请输入备注'),
  277. ]);
  278. // 设置表单的标题
  279. $form->setTitle('备注');
  280. // 返回生成的表单HTML代码
  281. return $form;
  282. }
  283. /**
  284. * 获取搜索选项
  285. * 该方法通过查询数据库获取搜索选项,每个选项包含value和label两个属性,分别代表选项的值和显示文本。
  286. * 这些选项通常用于下拉列表等选择控件,以提供用户友好的选择方式。
  287. *
  288. * @param string $where 查询条件,用于筛选选项。此参数应包含任何需要的条件,以限定查询的结果集。
  289. * @return array 返回一个数组,其中每个元素都是一个包含value和label属性的对象。这些对象代表了可选的搜索条件。
  290. */
  291. public function getOptions($where)
  292. {
  293. // 使用DAO层的getSearch方法查询数据,指定查询的字段为station_id和station_name,
  294. // 并按create_time降序排列。最终返回查询结果的数组。
  295. $list = $this->dao->getSearch($where)->field('station_id value, station_name label')->order('create_time DESC')
  296. ->select();
  297. return $list;
  298. }
  299. /**
  300. * 获取城市列表
  301. * @return mixed
  302. * @author Qinii
  303. */
  304. public function getCityLst()
  305. {
  306. $type = systemConfig('delivery_type');
  307. $key = 'delivery_get_city_lst_' . $type;
  308. if (!$data = Cache::get($key)) {
  309. $data = DeliverySevices::create($type)->getCity([]);
  310. Cache::set($key, $data, 3600);
  311. }
  312. return $data;
  313. }
  314. /**
  315. * 获取配送余额
  316. *
  317. * 本函数用于查询当前系统的配送余额。它首先通过系统配置确定配送方式,然后根据配送方式创建相应的配送服务对象,
  318. * 最后通过该对象获取配送余额。如果系统没有配置配送方式,则默认返回配送余额为0。
  319. *
  320. * @return array 返回一个包含配送余额的数组。如果未配置配送类型,则数组中配送余额为0。
  321. */
  322. public function getBalance()
  323. {
  324. // 通过系统配置获取配送方式
  325. $type = systemConfig('delivery_type');
  326. // 如果未配置配送方式,则直接返回配送余额为0
  327. if (!$type) return ['deliverBalance' => 0];
  328. // 根据配送方式创建配送服务对象,并调用其方法获取配送余额
  329. return DeliverySevices::create(systemConfig('delivery_type'))->getBalance([]);
  330. }
  331. /**
  332. * 获取充值方式
  333. *
  334. * 本方法通过调用DeliveryServices类的静态方法create,根据配置的配送类型创建相应的配送服务对象,
  335. * 并进一步调用该对象的getRecharge方法来获取充值方式。此方法的设计允许系统灵活地支持不同类型的配送服务,
  336. * 以及对应的充值方式获取逻辑,增强了系统的可扩展性和灵活性。
  337. *
  338. * @return array 充值方式列表
  339. */
  340. public function getRecharge()
  341. {
  342. // 根据系统配置的配送类型创建配送服务对象
  343. return DeliverySevices::create(systemConfig('delivery_type'))->getRecharge([]);
  344. }
  345. }