Browse Source

feat(store): 新增基础数据管理功能

- 新增地址提示、行政区划、经营板块及经营种类数据接口
- 实现高德地图API工具类,支持地址提示和行政区划查询
- 添加基础数据服务层,处理业务逻辑并转换数据格式
- 提供行政区划代码查询和城市编码获取功能
- 支持根据关键词获取地址提示和附近地铁站信息- 实现经营板块和经营种类的关联查询功能
wxd 1 month ago
parent
commit
63dc4fc393

+ 74 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/BaseDataController.java

@@ -0,0 +1,74 @@
+package shop.alien.storeplatform.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.vo.StoreDictionaryVo;
+import shop.alien.storeplatform.service.BaseDataService;
+
+import java.util.List;
+
+/**
+ * web端基础数据管理 前端控制器
+ *
+ * @author ssk
+ * @since 2025-01-xx
+ */
+@Slf4j
+@Api(tags = {"web端基础数据管理"})
+@ApiSort(3)
+@CrossOrigin
+@RestController
+@RequestMapping("/baseData")
+@RequiredArgsConstructor
+public class BaseDataController {
+
+    private final BaseDataService baseDataService;
+
+    @ApiOperation("根据关键词获取地址提示")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "addressName", value = "地址关键词", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "city", value = "城市", dataType = "String", paramType = "query", required = false)
+    })
+    @GetMapping("/getAddressPrompt")
+    public R<JSONObject> getAddressPrompt(@RequestParam(value = "addressName") String addressName,
+                                           @RequestParam(value = "city", required = false) String city) {
+        log.info("BaseDataController.getAddressPrompt?addressName={}&city={}", addressName, city);
+        return baseDataService.getAddressPrompt(addressName, city);
+    }
+
+    @ApiOperation("获取行政区划数据")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "adCode", value = "行政区划代码(100000:国家, 省代码:省, 市代码:市)", dataType = "String", paramType = "query", required = false, defaultValue = "100000", example = "100000")
+    })
+    @GetMapping("/getDistrict")
+    public R<JSONObject> getDistrict(@RequestParam(value = "adCode", required = false, defaultValue = "100000") String adCode) {
+        log.info("BaseDataController.getDistrict?adCode={}", adCode);
+        return baseDataService.getDistrict(adCode);
+    }
+
+    @ApiOperation("获取经营板块基础数据")
+    @ApiOperationSupport(order = 3)
+    @GetMapping("/getBusinessSection")
+    public R<List<StoreDictionaryVo>> getBusinessSection() {
+        log.info("BaseDataController.getBusinessSection");
+        return baseDataService.getBusinessSection();
+    }
+
+    @ApiOperation("获取经营种类基础数据")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "parentId", value = "经营板块ID", dataType = "String", paramType = "query", required = true, example = "1")
+    })
+    @GetMapping("/getBusinessTypes")
+    public R<List<StoreDictionaryVo>> getBusinessTypes(@RequestParam("parentId") String parentId) {
+        log.info("BaseDataController.getBusinessTypes?parentId={}", parentId);
+        return baseDataService.getBusinessTypes(parentId);
+    }
+}
+

+ 49 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/BaseDataService.java

@@ -0,0 +1,49 @@
+package shop.alien.storeplatform.service;
+
+import com.alibaba.fastjson.JSONObject;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.vo.StoreDictionaryVo;
+
+import java.util.List;
+
+/**
+ * web端基础数据服务接口
+ *
+ * @author ssk
+ * @since 2025-01-xx
+ */
+public interface BaseDataService {
+
+    /**
+     * 根据关键词获取地址提示
+     *
+     * @param addressName 地址关键词
+     * @param city        城市
+     * @return R
+     */
+    R<JSONObject> getAddressPrompt(String addressName, String city);
+
+    /**
+     * 获取行政区划数据
+     *
+     * @param adCode 行政区划代码
+     * @return R
+     */
+    R<JSONObject> getDistrict(String adCode);
+
+    /**
+     * 获取经营板块基础数据
+     *
+     * @return R
+     */
+    R<List<StoreDictionaryVo>> getBusinessSection();
+
+    /**
+     * 获取经营种类基础数据
+     *
+     * @param parentId 经营板块ID
+     * @return R
+     */
+    R<List<StoreDictionaryVo>> getBusinessTypes(String parentId);
+}
+

+ 103 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/BaseDataServiceImpl.java

@@ -0,0 +1,103 @@
+package shop.alien.storeplatform.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StoreDictionary;
+import shop.alien.entity.store.vo.StoreDictionaryVo;
+import shop.alien.mapper.StoreDictionaryMapper;
+import shop.alien.storeplatform.service.BaseDataService;
+import shop.alien.storeplatform.util.GaoDeMapApiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * web端基础数据服务实现类
+ *
+ * @author ssk
+ * @since 2025-01-xx
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class BaseDataServiceImpl implements BaseDataService {
+
+    private final GaoDeMapApiUtil gaoDeMapApiUtil;
+
+    private final StoreDictionaryMapper storeDictionaryMapper;
+
+    @Override
+    public R<JSONObject> getAddressPrompt(String addressName, String city) {
+        log.info("BaseDataServiceImpl.getAddressPrompt?addressName={}&city={}", addressName, city);
+        JSONObject result = gaoDeMapApiUtil.getInputPrompt(addressName, city);
+        return R.data(result);
+    }
+
+    @Override
+    public R<JSONObject> getDistrict(String adCode) {
+        log.info("BaseDataServiceImpl.getDistrict?adCode={}", adCode);
+        JSONObject result = gaoDeMapApiUtil.getDistrict(adCode);
+        return R.data(result);
+    }
+
+    @Override
+    public R<List<StoreDictionaryVo>> getBusinessSection() {
+        log.info("BaseDataServiceImpl.getBusinessSection");
+        // 查询经营板块数据(排除父节点dictId=0)
+        LambdaQueryWrapper<StoreDictionary> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreDictionary::getTypeName, "business_section")
+               .ne(StoreDictionary::getDictId, 0);
+        List<StoreDictionary> businessSectionList = storeDictionaryMapper.selectList(wrapper);
+        
+        // 转换为VO
+        List<StoreDictionaryVo> voList = new ArrayList<>();
+        for (StoreDictionary storeDictionary : businessSectionList) {
+            if (storeDictionary != null) {
+                StoreDictionaryVo vo = new StoreDictionaryVo();
+                BeanUtils.copyProperties(storeDictionary, vo);
+                voList.add(vo);
+            }
+        }
+        
+        return R.data(voList);
+    }
+
+    @Override
+    public R<List<StoreDictionaryVo>> getBusinessTypes(String parentId) {
+        log.info("BaseDataServiceImpl.getBusinessTypes?parentId={}", parentId);
+        
+        // 根据parentId查询经营板块信息
+        LambdaQueryWrapper<StoreDictionary> sectionWrapper = new LambdaQueryWrapper<>();
+        sectionWrapper.eq(StoreDictionary::getTypeName, "business_section")
+                     .eq(StoreDictionary::getDictId, parentId);
+        StoreDictionary businessSection = storeDictionaryMapper.selectOne(sectionWrapper);
+        
+        if (businessSection == null) {
+            log.warn("BaseDataServiceImpl.getBusinessTypes 未找到经营板块,parentId={}", parentId);
+            return R.data(new ArrayList<>());
+        }
+        
+        // 查询该板块下的经营种类
+        LambdaQueryWrapper<StoreDictionary> typesWrapper = new LambdaQueryWrapper<>();
+        typesWrapper.eq(StoreDictionary::getParentId, businessSection.getId());
+        List<StoreDictionary> businessTypesList = storeDictionaryMapper.selectList(typesWrapper);
+        
+        // 转换为VO
+        List<StoreDictionaryVo> voList = new ArrayList<>();
+        for (StoreDictionary storeDictionary : businessTypesList) {
+            if (storeDictionary != null) {
+                StoreDictionaryVo vo = new StoreDictionaryVo();
+                BeanUtils.copyProperties(storeDictionary, vo);
+                voList.add(vo);
+            }
+        }
+        
+        return R.data(voList);
+    }
+}
+

+ 183 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/util/GaoDeMapApiUtil.java

@@ -0,0 +1,183 @@
+package shop.alien.storeplatform.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import shop.alien.entity.store.EssentialCityCode;
+import shop.alien.mapper.EssentialCityCodeMapper;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+
+/**
+ * 高德地图API工具类
+ *
+ * @author ssk
+ * @version 1.0.0
+ * @since 2025-01-xx
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class GaoDeMapApiUtil {
+
+    @Value("${gaode.key}")
+    private String key;
+
+    @Value("${gaode.geoUrl}")
+    private String geoUrl;
+
+    @Value("${gaode.geoListUrl}")
+    private String geoListUrl;
+
+    @Value("${gaode.getDistrict}")
+    private String getDistrict;
+
+    @Value("${gaode.distanceUrl}")
+    private String distanceUrl;
+
+    @Value("${gaode.distanceTypeUrl}")
+    private String distanceTypeUrl;
+
+    @Value("${gaode.nearUrl}")
+    private String nearUrl;
+
+    @Value("${gaode.subwayUrl}")
+    private String subwayUrl;
+
+    @Value("${gaode.addressUrl}")
+    private String addressUrl;
+
+    private final EssentialCityCodeMapper essentialCityCodeMapper;
+
+    /**
+     * 根据关键词获取地址提示
+     *
+     * @param address 地址关键词
+     * @param city    城市名称
+     * @return JSONObject
+     */
+    public JSONObject getInputPrompt(String address, String city) {
+        log.info("GaoDeMapApiUtil.getInputPrompt?address={}&city={}", address, city);
+        
+        // 如果按照城市查询,需要获取城市编码
+        String cityCode = "";
+        if (StringUtils.isNotEmpty(city)) {
+            LambdaQueryWrapper<EssentialCityCode> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(EssentialCityCode::getAreaName, city);
+            EssentialCityCode essentialCityCode = essentialCityCodeMapper.selectOne(wrapper);
+            if (null != essentialCityCode) {
+                cityCode = essentialCityCode.getCityCode().toString();
+            }
+        }
+        
+        // 调用高德地图输入提示接口
+        String formattedUrl = String.format(geoListUrl, address, key, cityCode);
+        JSONObject obj = getResponse(formattedUrl);
+        return obj;
+    }
+
+    /**
+     * 获取行政区划
+     *
+     * @param adCode 行政区划代码
+     * @return JSONObject
+     */
+    public JSONObject getDistrict(String adCode) {
+        log.info("GaoDeMapApiUtil.getDistrict?adCode={}", adCode);
+        
+        // 调用高德地图行政区划接口
+        String formattedUrl = String.format(getDistrict, key, adCode);
+        JSONObject obj = getResponse(formattedUrl);
+        return obj;
+    }
+
+
+    public JSONObject getNearbySubway(String longitude, String latitude) {
+        try {
+            // 使用高德地图POI搜索接口,搜索类型为地铁站(010100)
+            String encodedKeywords = URLEncoder.encode("地铁站", "UTF-8");
+            String urlString = String.format(
+                    subwayUrl,
+                    key, latitude, longitude, encodedKeywords, 1000, 150500);
+            JSONObject obj = getResponse(urlString);
+            if (null != obj && "1".equals(String.valueOf(obj.get("status")))) {
+                JSONObject pois = obj.getJSONArray("pois").getJSONObject(0);
+                return pois;
+            }
+        } catch (Exception e) {
+            log.error("GaoDeMapUtil.getNearbySubway ERROR {}", e.getMessage());
+        }
+        return new JSONObject();
+    }
+
+
+//
+//    /**
+//     * 获取附近地铁站
+//     *
+//     * @param longitude 经度
+//     * @param latitude  纬度
+//     * @return JSONObject 包含地铁站名称和位置信息
+//     */
+//    public JSONObject getNearbySubway(String longitude, String latitude) {
+//        log.info("GaoDeMapApiUtil.getNearbySubway?longitude={}&latitude={}", longitude, latitude);
+//
+//        try {
+//            // 调用高德地图周边搜索接口,查询地铁站
+//            // types=150500 表示地铁站类型
+//            String location = longitude + "," + latitude;
+//            String formattedUrl = String.format(getNearbyUrl, location, key);
+//            JSONObject response = getResponse(formattedUrl);
+//
+//            if (response != null && "1".equals(response.getString("status"))) {
+//                com.alibaba.fastjson.JSONArray pois = response.getJSONArray("pois");
+//                if (pois != null && !pois.isEmpty()) {
+//                    // 返回最近的地铁站信息
+//                    JSONObject nearestSubway = pois.getJSONObject(0);
+//                    log.info("GaoDeMapApiUtil.getNearbySubway - 找到最近地铁站: {}",
+//                            nearestSubway.getString("name"));
+//                    return nearestSubway;
+//                }
+//            }
+//
+//            log.warn("GaoDeMapApiUtil.getNearbySubway - 未找到附近地铁站");
+//            return new JSONObject();
+//        } catch (Exception e) {
+//            log.error("GaoDeMapApiUtil.getNearbySubway ERROR: {}", e.getMessage(), e);
+//            return new JSONObject();
+//        }
+//    }
+
+    /**
+     * 创建HTTP请求并获取响应
+     *
+     * @param serverUrl 请求地址
+     * @return JSONObject
+     */
+    private JSONObject getResponse(String serverUrl) {
+        StringBuilder result = new StringBuilder();
+        try {
+            URL url = new URL(serverUrl);
+            URLConnection conn = url.openConnection();
+            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+            String line;
+            while ((line = in.readLine()) != null) {
+                result.append(line);
+            }
+            in.close();
+        } catch (Exception e) {
+            log.error("GaoDeMapApiUtil.getResponse ERROR {}", e.getMessage());
+            return null;
+        }
+        return JSONObject.parseObject(result.toString());
+    }
+}
+