Region.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. namespace app\common\model\settings;
  3. use think\facade\Cache;
  4. use app\common\library\helper;
  5. use app\common\model\BaseModel;
  6. /**
  7. * 地区模型
  8. */
  9. class Region extends BaseModel
  10. {
  11. protected $name = 'region';
  12. protected $pk = 'id';
  13. protected $createTime = false;
  14. protected $updateTime = false;
  15. /**
  16. * 类型自动转换
  17. * @var array
  18. */
  19. protected $type = [
  20. 'id' => 'integer',
  21. 'pid' => 'integer',
  22. 'level' => 'integer',
  23. ];
  24. // 当前数据版本号
  25. private static $version = '1.2.6';
  26. // 县级市别名 (兼容微信端命名)
  27. private static $county = [
  28. '省直辖县级行政区划',
  29. '自治区直辖县级行政区划',
  30. ];
  31. /**
  32. * 根据id获取地区名称
  33. */
  34. public static function detail($id)
  35. {
  36. return (new static())->find($id);
  37. }
  38. /**
  39. * 根据id获取地区名称
  40. */
  41. public static function getNameById($id)
  42. {
  43. if ($id > 0) {
  44. $name = self::getCacheAll()[$id]['name'] ?? '其他';
  45. if ('其他' == $name) {
  46. $singleInfo = (new static())->withoutGlobalScope()->find($id);
  47. if (!empty($singleInfo)) {
  48. $name = ($singleInfo->toArray())['name'];
  49. }
  50. }
  51. return $name;
  52. }
  53. return '其他';
  54. }
  55. /**
  56. * 根据名称获取地区id
  57. */
  58. public static function getIdByName($name, $level = 0, $pid = 0)
  59. {
  60. // 兼容:微信端"省直辖县级行政区划"
  61. if (in_array($name, static::$county)) {
  62. $name = '直辖县级';
  63. }
  64. $data = self::getCacheAll();
  65. foreach ($data as $item) {
  66. if ($item['name'] == $name && $item['level'] == $level && $item['pid'] == $pid)
  67. return $item['id'];
  68. }
  69. return 0;
  70. }
  71. /**
  72. * 获取所有地区(树状结构)
  73. */
  74. public static function getCacheTree()
  75. {
  76. return static::getCacheData('tree');
  77. }
  78. /**
  79. * 获取所有地区列表
  80. */
  81. public static function getCacheAll()
  82. {
  83. return static::getCacheData('all');
  84. }
  85. /**
  86. * 获取所有地区的总数
  87. */
  88. public static function getCacheCounts()
  89. {
  90. return static::getCacheData('counts');
  91. }
  92. /**
  93. * 获取缓存中的数据(存入静态变量)
  94. */
  95. private static function getCacheData($item = null)
  96. {
  97. static $cacheData = [];
  98. if (empty($cacheData)) {
  99. $static = new static;
  100. $cacheData = $static->regionCache();
  101. }
  102. if (is_null($item)) {
  103. return $cacheData;
  104. }
  105. return $cacheData[$item];
  106. }
  107. /**
  108. * 获取地区缓存
  109. */
  110. private function regionCache()
  111. {
  112. // 缓存的数据
  113. $complete = Cache::get('region');
  114. // 如果存在缓存则返回缓存的数据,否则从数据库中查询
  115. // 条件1: 获取缓存数据
  116. // 条件2: 数据版本号要与当前一致
  117. if (
  118. !empty($complete)
  119. && isset($complete['version'])
  120. && $complete['version'] == self::$version
  121. ) {
  122. return $complete;
  123. }
  124. // 所有地区
  125. $allList = $tempList = $this->getAllList();
  126. // 已完成的数据
  127. $complete = [
  128. 'all' => $allList,
  129. 'tree' => $this->getTreeList($allList),
  130. 'counts' => $this->getCount($allList),
  131. 'version' => self::$version,
  132. ];
  133. // 写入缓存
  134. Cache::tag('cache')->set('region', $complete);
  135. return $complete;
  136. }
  137. private static function getCount($allList)
  138. {
  139. $counts = [
  140. 'total' => count($allList),
  141. 'province' => 0,
  142. 'city' => 0,
  143. 'region' => 0,
  144. ];
  145. $level = [1 => 'province', 2 => 'city', 3 => 'region'];
  146. foreach ($allList as $item) {
  147. $counts[$level[$item['level']]]++;
  148. }
  149. return $counts;
  150. }
  151. /**
  152. * 格式化为树状格式
  153. */
  154. private function getTreeList($allList)
  155. {
  156. $treeList = [];
  157. foreach ($allList as $pKey => $province) {
  158. if ($province['level'] == 1) { // 省份
  159. $treeList[$province['id']] = $province;
  160. unset($allList[$pKey]);
  161. foreach ($allList as $cKey => $city) {
  162. if ($city['level'] == 2 && $city['pid'] == $province['id']) { // 城市
  163. $treeList[$province['id']]['city'][$city['id']] = $city;
  164. unset($allList[$cKey]);
  165. foreach ($allList as $rKey => $region) {
  166. if ($region['level'] == 3 && $region['pid'] == $city['id']) { // 地区
  167. $treeList[$province['id']]['city'][$city['id']]['region'][$region['id']] = $region;
  168. unset($allList[$rKey]);
  169. }
  170. }
  171. }
  172. }
  173. }
  174. }
  175. return $treeList;
  176. }
  177. /**
  178. * 从数据库中获取所有地区
  179. */
  180. private function getAllList()
  181. {
  182. $list = self::withoutGlobalScope()
  183. ->field('id, pid, name, level')
  184. ->where('is_delete', 0)
  185. ->select()
  186. ->toArray();
  187. return helper::arrayColumn2Key($list, 'id');
  188. }
  189. /**
  190. * 地区组装供前端使用
  191. */
  192. public static function getRegionForApi(){
  193. $province_arr = [];
  194. $city_arr = [];
  195. $area_arr = [];
  196. $region = self::getCacheTree();
  197. foreach ($region as $province){
  198. $value = [
  199. 'label' => $province['name'],
  200. 'value' => $province['id']
  201. ];
  202. array_push($province_arr, $value);
  203. $city_arr_temp = [];
  204. $city_area_temp = [];
  205. if(!isset($province['city'])){
  206. continue;
  207. }
  208. foreach ($province['city'] as $city){
  209. $value = [
  210. 'label' => $city['name'],
  211. 'value' => $city['id']
  212. ];
  213. array_push($city_arr_temp, $value);
  214. $area_arr_temp = [];
  215. if(isset($city['region'])){
  216. foreach ($city['region'] as $area) {
  217. $value = [
  218. 'label' => $area['name'],
  219. 'value' => $area['id']
  220. ];
  221. array_push($area_arr_temp, $value);
  222. }
  223. }
  224. array_push($city_area_temp, $area_arr_temp);
  225. }
  226. array_push($area_arr, $city_area_temp);
  227. array_push($city_arr, $city_arr_temp);
  228. }
  229. return [$province_arr, $city_arr, $area_arr];
  230. }
  231. }