dao = $dao; } /** * @param int $id * @param int $uid * @return bool * @author Qinii */ public function fieldExists(int $id,int $uid) { return $this->dao->userFieldExists($this->dao->getPk(),$id,$uid); } /** * @param int $uid * @return bool * @author Qinii */ public function defaultExists(int $uid) { return $this->dao->userFieldExists('is_default',1,$uid); } /** * @param int $id * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author Qinii */ public function checkDefault(int $id) { $res = $this->dao->getWhere([$this->dao->getPk() => $id]); return $res['is_default']; } /** * @param $province * @param $city * @return mixed * @author Qinii */ public function getCityId($province,$city) { $make = app()->make(CityRepository::class); $provinceData = $make->getWhere(['name' => $province]); $cityData = $make->getWhere(['name' => $city,'parent_id' => $provinceData['city_id']]); if(!$cityData)$cityData = $make->getWhere([['name','like','直辖'.'%'],['parent_id' ,'=', $provinceData['city_id']]]); return $cityData['city_id']; } /** * @param $uid * @param $page * @param $limit * @return array * @author Qinii */ public function getList($uid) { $list = $this->dao->getAll($uid)->order('is_default desc')->select(); foreach ($list as &$address){ $code_list = explode(',',$address['code_list']); if (isset($code_list[3])) { $address['town'] = \think\facade\Db::name('regions')->where('id', $code_list[3])->value('name'); } } return compact('list'); } /** * @param $id * @param $uid * @return array|\think\Model|null * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author Qinii */ public function get($id,$uid) { $address = $this->dao->getWhere(['address_id' => $id,'uid' => $uid]) ?? [] ; $code_list = explode(',',$address['code_list']); if (isset($code_list[3])) { $address['town'] = \think\facade\Db::name('regions')->where('id', $code_list[3])->value('name'); } return $address; } /** * 根据 地址ID 获取地址实体 * * @param $addressId * @return UserAddressEntity */ public function getAddressEntityByAddressId($addressId): UserAddressEntity { /** @var UserAddressEntity $addressEntity */ $addressEntity = $this->dao->getAddressEntityByAddressId($addressId); return $addressEntity; } /** * 阿里云市场 - 地址解析 * * 调用阿里云市场地址解析接口,将完整的地址文本解析为省/市/区/街道等结构化信息, * 并从 rrx_regions 表查询省/市/区/街道的 id 追加到返回数据中 * * 接口文档: https://market.aliyun.com/detail/cmapi00067026 * 请求方式: POST * 认证方式: Authorization:APPCODE * * @param string $address 待解析的地址文本,如 "北京市朝阳区建国路88号SOHO现代城A座1508室" * @return array 统一返回格式: * 成功 {"code":200,"msg":"成功","data":{...}} * 失败 {"code":-1,"msg":"错误信息","data":[]} */ public function parse($address) { $config = config('third_party.aliyun_address_parse'); $appCode = $config['appCode'] ?? ''; if (empty($appCode)) { $msg = '地址解析失败:未配置阿里云市场 AppCode'; Log::error($msg); return ['code' => -1, 'msg' => $msg, 'data' => []]; } if (empty($address)) { $msg = '地址解析失败:地址文本为空'; Log::error($msg); return ['code' => -2, 'msg' => $msg, 'data' => []]; } $url = rtrim($config['gatewayUrl'] ?? 'https://slyparcel.market.alicloudapi.com', '/') . ($config['apiPath'] ?? '/v2/express_address/query'); $header = ['Authorization:APPCODE ' . $appCode]; try { $res = HttpService::postRequest($url, ['rawAddress' => $address], $header); if ($res === false) { $msg = '地址解析请求失败'; Log::error($msg . ':' . $url . ',地址:' . $address); return ['code' => -3, 'msg' => $msg, 'data' => []]; } $result = json_decode($res, true); if (json_last_error() !== JSON_ERROR_NONE) { $msg = '地址解析返回数据解析失败:' . json_last_error_msg(); Log::error($msg . ',原始数据:' . $res); return ['code' => -4, 'msg' => $msg, 'data' => []]; } // 接口返回格式:{"msg":"成功","success":true,"code":200,"data":{"orderNo":"...","data":{...}}} // 提取内层 data.data 作为解析结果 if (isset($result['code']) && $result['code'] == 200 && isset($result['data']['data'])) { $data = $result['data']['data']; // 从 rrx_regions 表查询省/市/区/街道的 id $data = $this->appendRegionIds($data); return ['code' => 200, 'msg' => '成功', 'data' => $data]; } // 如果外层 code 不是 200,返回接口的错误信息 if (isset($result['code']) && $result['code'] != 200) { $msg = $result['msg'] ?? '地址解析失败'; Log::error($msg . ',原始数据:' . $res); return ['code' => $result['code'], 'msg' => $msg, 'data' => []]; } // 兜底:返回原始结果 return ['code' => 200, 'msg' => '成功', 'data' => $result]; } catch (\Throwable $e) { $msg = '地址解析异常:' . $e->getMessage(); Log::error($msg . ',文件:' . $e->getFile() . ',行号:' . $e->getLine()); return ['code' => -5, 'msg' => $msg, 'data' => []]; } } /** * 根据省/市/区/街道名称从 rrx_regions 表查询对应的 id,并追加到返回数据中 * * 注意:每次查询必须重新调用 Db::name('regions'),避免 ThinkPHP 查询构造器复用导致 where 条件叠加 * * @param array $data 接口返回的地址解析数据,包含 province/city/district/street * @return array */ private function appendRegionIds(array $data) { $provinceId = 0; $cityId = 0; $districtId = 0; $streetId = 0; // 查询省份 id (level = 1),未查到返回 0 if (!empty($data['province'])) { $province = \think\facade\Db::name('regions') ->whereLike('name', '%' . $data['province'] . '%') ->where('level', 1) ->find(); $provinceId = $province ? (int)$province['id'] : 0; } $data['province_id'] = $provinceId; // 查询城市 id (level = 2),未查到返回 0 if (!empty($data['city'])) { $city = \think\facade\Db::name('regions') ->whereLike('name', '%' . $data['city'] . '%') ->where('level', 2) ->find(); $cityId = $city ? (int)$city['id'] : 0; } $data['city_id'] = $cityId; // 查询区/县 id (level = 3),未查到返回 0 if (!empty($data['district'])) { $district = \think\facade\Db::name('regions') ->whereLike('name', '%' . $data['district'] . '%') ->where('level', 3) ->find(); $districtId = $district ? (int)$district['id'] : 0; } $data['district_id'] = $districtId; // 查询街道/乡镇 id (level = 4),未查到返回 0 if (!empty($data['street'])) { $street = \think\facade\Db::name('regions') ->whereLike('name', '%' . $data['street'] . '%') ->where('level', 4) ->find(); $streetId = $street ? (int)$street['id'] : 0; } $data['street_id'] = $streetId; // 拼接 code_list,格式:province_id,city_id,district_id,street_id $codeList = implode(',', [$provinceId, $cityId, $districtId, $streetId]); $data['code_list'] = $codeList; return $data; } }