CityAreaRepository.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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\store;
  12. use app\common\dao\store\CityAreaDao;
  13. use app\common\repositories\BaseRepository;
  14. use FormBuilder\Factory\Elm;
  15. use think\exception\ValidateException;
  16. use think\facade\Route;
  17. /**
  18. * 省市区
  19. */
  20. class CityAreaRepository extends BaseRepository
  21. {
  22. public function __construct(CityAreaDao $dao)
  23. {
  24. $this->dao = $dao;
  25. }
  26. /**
  27. * 获取指定父ID的所有子项
  28. *
  29. * 本函数通过查询具有特定父ID的数据项来获取所有子项。
  30. * 使用了ORM模式的search方法来构建查询条件,然后通过select方法执行查询并返回结果。
  31. *
  32. * @param int $pid 父ID,用于指定要查询的子项的父项。
  33. * @return array 返回查询结果,是一个包含所有指定父ID子项的数组。
  34. */
  35. public function getChildren($pid)
  36. {
  37. // 根据$pid查询满足条件的数据,并返回所有查询结果
  38. return $this->search(['pid' => $pid])->select();
  39. }
  40. /**
  41. * 根据条件获取列表数据
  42. *
  43. * 本函数旨在通过提供的条件从数据库中检索列表数据。它使用了DAO模式来执行查询,
  44. * 并对查询结果进行了额外的处理,以包括父级数据和子级数据的相关信息。
  45. *
  46. * @param string|array $where 查询条件,可以是字符串或数组形式的SQL WHERE子句条件。
  47. * @return \Illuminate\Database\Eloquent\Collection 返回一个包含搜索结果的集合,这些结果已经包含了父级数据和子级数据的附加信息。
  48. */
  49. public function getList($where)
  50. {
  51. // 执行搜索查询,根据$where条件,带上父级数据,按ID升序排序
  52. return $this->dao->getSearch($where)
  53. ->with(['parent']) // 加载每个条目的父级数据
  54. ->order('id ASC') // 按ID升序排序结果
  55. ->select() // 执行查询并返回结果集
  56. ->append(['children','hasChildren']); // 附加'children'和'hasChildren'属性到每个条目,用于后续处理或显示
  57. }
  58. /**
  59. * 创建或编辑城市区域表单
  60. *
  61. * 本函数用于生成城市或区域的添加或编辑表单。根据传入的$id$和$parentId$,决定是进行编辑操作还是添加操作。
  62. * 如果$id$存在,则从数据库中获取相应数据进行编辑;如果$id$不存在但$parentId$存在,则以$parentId$为基准进行添加操作。
  63. * 表单中包含的字段有:上级区域ID、级别、上级区域名称、区域名称。
  64. *
  65. * @param int|null $id 区域ID,如果存在则用于编辑区域,否则用于添加区域。
  66. * @param int|null $parentId 上级区域ID,用于指定新区域的上级区域。
  67. * @return mixed 返回表单对象,包含表单的规则、标题和数据。
  68. * @throws ValidateException 如果根据$id$查询不到数据,则抛出验证异常。
  69. */
  70. public function form(?int $id, ?int $parentId)
  71. {
  72. // 定义根区域,即全国,作为默认的上级区域。
  73. $parent = ['id' => 0, 'name' => '全国', 'level' => 0,];
  74. $formData = [];
  75. // 如果$id$存在,进行编辑操作。
  76. if ($id) {
  77. // 根据$id$查询数据库,获取区域数据。
  78. $formData = $this->dao->getWhere(['id' => $id],'*',['parent'])->toArray();
  79. // 如果查询不到数据,则抛出异常。
  80. if (!$formData) throw new ValidateException('数据不存在');
  81. // 创建编辑表单,并设置表单的提交URL。
  82. $form = Elm::createForm(Route::buildUrl('systemCityAreaUpdate', ['id' => $id])->build());
  83. // 如果存在上级区域数据,则更新$parent变量。
  84. if (!is_null($formData['parent'])) $parent = $formData['parent'];
  85. } else {
  86. // 如果$id$不存在,进行添加操作。
  87. // 创建添加表单,并设置表单的提交URL。
  88. $form = Elm::createForm(Route::buildUrl('systemCityAreaCreate')->build());
  89. // 如果$parentId$存在,查询对应的上级区域数据。
  90. if ($parentId) $parent = $this->dao->getWhere(['id' => $parentId]);
  91. }
  92. // 设置表单的验证规则和默认值。
  93. $form->setRule([
  94. Elm::input('parent_id', '', $parent['id'] ?? 0)->hiddenStatus(true),
  95. Elm::input('level', '', $parent['level'] + 1)->hiddenStatus(true),
  96. Elm::input('parent_name', '上级地址:', $parent['name'])->disabled(true)->placeholder('请输入上级地址'),
  97. Elm::input('name', '地址名称:', '')->placeholder('请输入地址名称')->required(),
  98. ]);
  99. // 设置表单的标题,并返回表单对象。
  100. return $form->setTitle($id ? '编辑城市' : '添加城市')->formData($formData);
  101. }
  102. /**
  103. * 创建新记录
  104. *
  105. * 本函数用于在数据库中创建新的记录。在创建记录之前,它会检查传入的数据中是否包含父记录ID(parent_id)。
  106. * 如果父记录ID大于0,说明该记录有一个父记录,函数会先更新父记录的snum字段(可能表示子记录数)。
  107. * 最后,函数会调用DAO对象的create方法来实际创建记录。
  108. *
  109. * @param array $data 包含新记录数据的数组。数组应包含所有必要的字段,可能包括父记录ID。
  110. * @return mixed 返回DAO创建操作的结果。具体类型取决于DAO的实现。
  111. */
  112. public function create($data)
  113. {
  114. // 检查是否有父记录并更新其snum字段
  115. if($data['parent_id'] > 0){
  116. // 修改父级snum
  117. $this->dao->incField($data['parent_id'],'snum');
  118. }
  119. // 调用DAO的create方法来创建新记录
  120. return $this->dao->create($data);
  121. }
  122. /**
  123. * 添加
  124. * @param $name
  125. * @param $pid
  126. * @param $lv
  127. * @return mixed
  128. * @author Qinii
  129. * @day 2023/8/2
  130. */
  131. public function treeCreate($name,$code, $pid = 0, $lv = 1)
  132. {
  133. $type = [
  134. 1 => 'province',
  135. 2 => 'city',
  136. 3 => 'area',
  137. 4 => 'street',
  138. ];
  139. $path = '/';
  140. if ($pid){
  141. $res = $this->dao->get($pid);
  142. $path = $res['path'].$res['id'].'/';
  143. }
  144. $data = [
  145. 'type' => $type[$lv],
  146. 'parent_id' => $pid,
  147. 'level' => $lv,
  148. 'name' => $name,
  149. 'path'=> $path,
  150. 'code' => $code
  151. ];
  152. $result = $this->dao->findOrCreate($data);
  153. return $result->id;
  154. }
  155. /**
  156. * 计算子集个数
  157. * @author Qinii
  158. * @day 2023/8/2
  159. */
  160. public function sumChildren($pid = '')
  161. {
  162. $data = $this->dao->getSearch(['parent_id' => $pid])->where('level','<',4)->select();
  163. foreach ($data as $datum) {
  164. $snum = $this->dao->getSearch(['parent_id' => $datum->id])->count();
  165. $datum->snum = $snum;
  166. $datum->save();
  167. }
  168. }
  169. /**
  170. * 文件倒入,地址信息
  171. * @param $fiel
  172. * @author Qinii
  173. * @day 2024/1/19
  174. */
  175. public function updateCityForTxt($fiel)
  176. {
  177. $fiel = json_decode(file_get_contents($fiel));
  178. $this->tree($fiel);
  179. return true;
  180. }
  181. /**
  182. * 循环整理地址信息
  183. * @param $data
  184. * @param $pid
  185. * @param $path
  186. * @param $level
  187. * @return bool
  188. * @author Qinii
  189. * @day 2024/1/19
  190. */
  191. public function tree($data,$pid = 0,$path = '/',$level = 1)
  192. {
  193. $type = [
  194. 1 => 'province',
  195. 2 => 'city',
  196. 3 => 'area',
  197. 4 => 'street'
  198. ];
  199. foreach ($data as $k => $datum) {
  200. $_path = '';
  201. $where = [
  202. 'code' => $datum->code,
  203. 'name' => $datum->name,
  204. 'path' => $path,
  205. 'level'=> $level,
  206. 'parent_id' => $pid,
  207. 'type' => $type[$level]
  208. ];
  209. $rest = $this->dao->findOrCreate($where);
  210. if (isset($datum->children)) {
  211. $_path = $path.$rest->id.'/';
  212. $this->tree($datum->children, $rest->id, $_path, $level +1);
  213. }
  214. }
  215. return true;
  216. }
  217. /**
  218. * 删除特定ID的数据项。
  219. *
  220. * 此方法首先尝试根据给定的ID获取数据项。如果数据项不存在,则抛出一个验证异常,
  221. * 表明请求删除的数据不存在。如果数据项存在且有父项(表示它不是最顶级项),
  222. * 则递减父项的计数器(可能是表示子项数量的字段),最后删除该数据项。
  223. *
  224. * @param int $id 要删除的数据项的唯一标识符。
  225. * @return bool 返回删除操作的结果,通常是TRUE表示删除成功。
  226. * @throws ValidateException 如果尝试删除的数据项不存在,则抛出此异常。
  227. */
  228. public function delete($id)
  229. {
  230. // 尝试根据ID获取数据项。
  231. $res = $this->dao->get($id);
  232. // 如果获取的结果为空,即数据项不存在,则抛出异常。
  233. if (empty($res)) {
  234. throw new ValidateException('数据不存在');
  235. }
  236. // 如果数据项有父项(表示它不是最顶级项),则递减其父项的计数器。
  237. if ($res['parent_id'] > 0) {
  238. // 修改父级snum
  239. $this->dao->decField($res['parent_id'], 'snum');
  240. }
  241. // 执行实际的删除操作并返回结果。
  242. return $this->dao->delete($id);
  243. }
  244. }