wrj hai 1 ano
pai
achega
d2f5caedc0
Modificáronse 27 ficheiros con 1007 adicións e 45 borrados
  1. 267 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/PayController.java
  2. 98 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/RedisGeoController.java
  3. 13 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TCommentController.java
  4. 48 5
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TJsController.java
  5. 2 3
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TLbtController.java
  6. 20 8
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TOrderController.java
  7. 2 3
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TTxRecordController.java
  8. 132 8
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/WxController.java
  9. 13 0
      nightFragrance-admin/src/main/resources/application-dev.yml
  10. 6 0
      nightFragrance-common/pom.xml
  11. 60 0
      nightFragrance-common/src/main/java/com/ylx/common/config/WxPayConfig.java
  12. 24 0
      nightFragrance-common/src/main/java/com/ylx/common/utils/ListUtils.java
  13. 23 0
      nightFragrance-framework/src/main/java/com/ylx/framework/config/BoundGeoOperationConfig.java
  14. 3 1
      nightFragrance-framework/src/main/java/com/ylx/framework/config/SecurityConfig.java
  15. 33 0
      nightFragrance-framework/src/main/java/com/ylx/framework/config/WxMaConfiguration.java
  16. 7 0
      nightFragrance-massage/pom.xml
  17. 28 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/Location.java
  18. 4 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/TComment.java
  19. 19 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/TJs.java
  20. 4 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/TJsVo.java
  21. 23 0
      nightFragrance-massage/src/main/java/com/ylx/massage/enums/Enumproject.java
  22. 22 3
      nightFragrance-massage/src/main/java/com/ylx/massage/enums/OrderStatusEnum.java
  23. 2 1
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TJsMapper.java
  24. 2 1
      nightFragrance-massage/src/main/java/com/ylx/massage/service/TJsService.java
  25. 14 4
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TJsServiceImpl.java
  26. 123 0
      nightFragrance-massage/src/main/java/com/ylx/massage/utils/LocationUtil.java
  27. 15 8
      nightFragrance-massage/src/main/resources/mapper/massage/TJsMapper.xml

+ 267 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/PayController.java

@@ -0,0 +1,267 @@
+package com.ylx.web.controller.massage;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.io.file.FileWriter;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.ContentType;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.ijpay.core.IJPayHttpResponse;
+import com.ijpay.core.enums.AuthTypeEnum;
+import com.ijpay.core.enums.RequestMethodEnum;
+import com.ijpay.core.enums.SignType;
+import com.ijpay.core.enums.TradeType;
+import com.ijpay.core.kit.AesUtil;
+import com.ijpay.core.kit.HttpKit;
+import com.ijpay.core.kit.PayKit;
+import com.ijpay.core.kit.WxPayKit;
+import com.ijpay.core.utils.DateTimeZoneUtil;
+import com.ijpay.wxpay.WxPayApi;
+import com.ijpay.wxpay.enums.WxDomainEnum;
+import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
+import com.ijpay.wxpay.enums.v3.CertAlgorithmTypeEnum;
+import com.ijpay.wxpay.model.v3.Amount;
+import com.ijpay.wxpay.model.v3.Payer;
+import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
+import com.ylx.common.config.WxPayConfig;
+import com.ylx.common.core.domain.R;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayInputStream;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static com.ylx.common.constant.HttpStatus.SUCCESS;
+
+/**
+ * @author jianlong
+ * @date 2024-04-03 15:27
+ */
+
+@RestController
+@Slf4j
+public class PayController {
+
+
+    @Autowired
+    private WxPayConfig wxPayProperties;
+
+    String serialNo;
+    String platSerialNo;
+
+    /**
+     * 小程序微信支付的第一步,统一下单
+     */
+    @GetMapping("/pay")
+    public R createUnifiedOrder(@RequestParam(value = "openId") String openId) throws Exception {
+        String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
+        UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
+                .setAppid(wxPayProperties.getAppId())
+                .setMchid(wxPayProperties.getMchId())
+                //商品描述
+                .setDescription("充值")
+                //订单号
+                .setOut_trade_no(PayKit.generateStr())
+                //交易结束时间
+                .setTime_expire(timeExpire)
+                //附加数据
+                .setAttach("夜来香")
+                //通知地址异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为https,如果是走专线接入,使用专线NAT IP或者私有回调域名可使用http
+                //示例值:https://www.weixin.qq.com/wxpay/pay.php
+                .setNotify_url(wxPayProperties.getNotifyUrl())
+                //支付金额以分为单位
+                .setAmount(new Amount().setTotal(1))
+                //交易人
+                .setPayer(new Payer().setOpenid(""));
+
+        log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
+        IJPayHttpResponse response = WxPayApi.v3(
+                RequestMethodEnum.POST,
+                WxDomainEnum.CHINA.toString(),
+                BasePayApiEnum.JS_API_PAY.toString(),
+                wxPayProperties.getMchId(),
+                getSerialNumber(),
+                null,
+                wxPayProperties.getCertKeyPath(),
+                JSONUtil.toJsonStr(unifiedOrderModel)
+        );
+
+        log.info("统一下单响应 {}", response);
+        // 根据证书序列号查询对应的证书来验证签名结果
+        boolean verifySignature = WxPayKit.verifySignature(response, wxPayProperties.getPlatFormPath());
+        log.info("verifySignature: {}", verifySignature);
+        if (response.getStatus() == SUCCESS && verifySignature) {
+            String body = response.getBody();
+            JSONObject jsonObject = JSONUtil.parseObj(body);
+            String prepayId = jsonObject.getStr("prepay_id");
+            Map<String, String> map = WxPayKit.jsApiCreateSign(wxPayProperties.getAppId(), prepayId, wxPayProperties.getCertKeyPath());
+            log.info("唤起支付参数:{}", map);
+            return R.ok(JSONUtil.toJsonStr(map));
+        }
+        return R.ok(JSONUtil.toJsonStr(response));
+
+    }
+
+    private String getSerialNumber() {
+        if (StrUtil.isEmpty(serialNo)) {
+            // 获取证书序列号
+            X509Certificate certificate = PayKit.getCertificate(wxPayProperties.getCertPath());
+            if (null != certificate) {
+                serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
+                // 提前两天检查证书是否有效
+                boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayProperties.getMchId(), -2);
+                log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));
+            }
+//            System.out.println("输出证书信息:\n" + certificate.toString());
+//            // 输出关键信息,截取部分并进行标记
+//            System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
+//            System.out.println("版本号:" + certificate.getVersion());
+//            System.out.println("签发者:" + certificate.getIssuerDN());
+//            System.out.println("有效起始日期:" + certificate.getNotBefore());
+//            System.out.println("有效终止日期:" + certificate.getNotAfter());
+//            System.out.println("主体名:" + certificate.getSubjectDN());
+//            System.out.println("签名算法:" + certificate.getSigAlgName());
+//            System.out.println("签名:" + certificate.getSignature().toString());
+        }
+        System.out.println("serialNo:" + serialNo);
+        return serialNo;
+    }
+
+    @RequestMapping(value = "/payNotify", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET})
+    @ResponseBody
+    public void payNotify(HttpServletRequest request, HttpServletResponse response) {
+        Map<String, String> map = new HashMap<>(12);
+        try {
+            String timestamp = request.getHeader("Wechatpay-Timestamp");
+            String nonce = request.getHeader("Wechatpay-Nonce");
+            String serialNo = request.getHeader("Wechatpay-Serial");
+            String signature = request.getHeader("Wechatpay-Signature");
+
+            log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
+            String result = HttpKit.readData(request);
+            log.info("支付通知密文 {}", result);
+
+            // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
+            String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp,
+                    wxPayProperties.getMchKey(), wxPayProperties.getPlatFormPath());
+
+            log.info("支付通知明文 {}", plainText);
+
+            if (StrUtil.isNotEmpty(plainText)) {
+                response.setStatus(200);
+                map.put("code", "SUCCESS");
+                map.put("message", "SUCCESS");
+            } else {
+                response.setStatus(500);
+                map.put("code", "ERROR");
+                map.put("message", "签名错误");
+            }
+            response.setHeader("Content-type", ContentType.JSON.toString());
+            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
+            response.flushBuffer();
+        } catch (Exception e) {
+            log.error("系统异常", e);
+        }
+    }
+
+    @RequestMapping("/get")
+    @ResponseBody
+    public String v3Get() {
+        // 获取平台证书列表
+        try {
+            IJPayHttpResponse response = WxPayApi.v3(
+                    RequestMethodEnum.GET,
+                    WxDomainEnum.CHINA.toString(),
+                    CertAlgorithmTypeEnum.getCertSuffixUrl(CertAlgorithmTypeEnum.SM2.getCode()),
+                    wxPayProperties.getMchId(),
+                    getSerialNumber(),
+                    null,
+                    wxPayProperties.getCertKeyPath(),
+                    "",
+                    AuthTypeEnum.SM2.getCode()
+            );
+            Map<String, List<String>> headers = response.getHeaders();
+            log.info("请求头: {}", headers);
+            String timestamp = response.getHeader("Wechatpay-Timestamp");
+            String nonceStr = response.getHeader("Wechatpay-Nonce");
+            String serialNumber = response.getHeader("Wechatpay-Serial");
+            String signature = response.getHeader("Wechatpay-Signature");
+
+            String body = response.getBody();
+            int status = response.getStatus();
+
+            log.info("serialNumber: {}", serialNumber);
+            log.info("status: {}", status);
+            log.info("body: {}", body);
+            int isOk = 200;
+            if (status == isOk) {
+                JSONObject jsonObject = JSONUtil.parseObj(body);
+                JSONArray dataArray = jsonObject.getJSONArray("data");
+                // 默认认为只有一个平台证书
+                JSONObject encryptObject = dataArray.getJSONObject(0);
+                JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
+                String associatedData = encryptCertificate.getStr("associated_data");
+                String cipherText = encryptCertificate.getStr("ciphertext");
+                String nonce = encryptCertificate.getStr("nonce");
+                String algorithm = encryptCertificate.getStr("algorithm");
+                String serialNo = encryptObject.getStr("serial_no");
+                final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, algorithm, wxPayProperties.getPlatFormPath());
+                log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);
+                // 根据证书序列号查询对应的证书来验证签名结果
+                boolean verifySignature = WxPayKit.verifySignature(response, wxPayProperties.getPlatFormPath());
+                log.info("verifySignature:{}", verifySignature);
+            }
+            return body;
+        } catch (Exception e) {
+            log.error("获取平台证书列表异常", e);
+            return null;
+        }
+    }
+
+    private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) {
+        try {
+            String key3 = wxPayProperties.getMchKey();
+            String publicKey;
+            if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
+                publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData);
+            } else {
+                AesUtil aesUtil = new AesUtil(wxPayProperties.getMchKey().getBytes(StandardCharsets.UTF_8));
+                // 平台证书密文解密
+                // encrypt_certificate 中的  associated_data nonce  ciphertext
+                publicKey = aesUtil.decryptToString(
+                        associatedData.getBytes(StandardCharsets.UTF_8),
+                        nonce.getBytes(StandardCharsets.UTF_8),
+                        cipherText
+                );
+            }
+            if (StrUtil.isNotEmpty(publicKey)) {
+                // 保存证书
+                FileWriter writer = new FileWriter(certPath);
+                writer.write(publicKey);
+                // 获取平台证书序列号
+                X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
+                return certificate.getSerialNumber().toString(16).toUpperCase();
+            }
+            return "";
+        } catch (Exception e) {
+            log.error("保存平台证书异常", e);
+            return e.getMessage();
+        }
+    }
+
+
+
+
+
+}

+ 98 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/RedisGeoController.java

@@ -0,0 +1,98 @@
+package com.ylx.web.controller.massage;
+
+import com.ylx.common.core.domain.R;
+import com.ylx.massage.domain.Location;
+import com.ylx.massage.domain.TWxUser;
+import com.ylx.massage.utils.LocationUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.geo.*;
+import org.springframework.data.redis.connection.RedisGeoCommands;
+import org.springframework.data.redis.core.BoundGeoOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+@Slf4j
+@RestController
+@Api(tags = "redis", description = "redis控制")
+@RequestMapping("/geo")
+@AllArgsConstructor
+public class RedisGeoController {
+
+    private static final String GEO_STAGE = "cities";
+
+    private final RedisTemplate<String, String> redisTemplate;
+
+    @Resource
+    private LocationUtil locationUtil;
+    /**
+     * 初始化数据可以将职位id和经纬度存入redis,
+     * 添加职业时增加位置数据
+     * 当用户点击附近是,传入经纬度。返回id获得职位信息推送给用户
+     */
+    @GetMapping("/init")
+    @ApiOperation("初始化")
+    public void init() {
+        // 清理缓存
+        redisTemplate.delete(GEO_STAGE);
+        Map<String, Point> points = new HashMap<>();
+        points.put("shijiazhuang", new Point(114.48, 38.03));
+        points.put("xingtang", new Point(114.54, 38.42));
+        points.put("guangcheng", new Point(114.84, 38.03));
+        points.put("gaoyi", new Point(114.58, 37.62));
+        points.put("zhaoxian", new Point(114.78, 37.76));
+        points.put("jinxing", new Point(114.13, 38.03));
+        points.put("luquan", new Point(114.03, 38.08));
+        points.put("xinle", new Point(114.67, 38.33));
+        points.put("zhengding", new Point(114.56, 38.13));
+        // 添加地理信息
+        redisTemplate.boundGeoOps(GEO_STAGE).add(points);
+    }
+
+    @PostMapping("/city")
+    @ApiOperation("获得附近技师")
+    public R<GeoResults<RedisGeoCommands.GeoLocation<String>>> dis(@RequestBody Location locationBo) {
+        //设置当前位置
+        Point point = new Point(locationBo.getLongitude(), locationBo.getLatitude());
+        //设置半径范围
+        Metric metric = RedisGeoCommands.DistanceUnit.METERS;
+        Distance distance = new Distance(locationBo.getRadius(), metric);
+        Circle circle = new Circle(point, distance);
+        //设置参数 包括距离、坐标、条数
+        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands
+                .GeoRadiusCommandArgs
+                .newGeoRadiusArgs()
+                .includeDistance()
+                .includeCoordinates()
+                .sortAscending()
+                .limit(locationBo.getLimit());
+        BoundGeoOperations<String, String> stringStringBoundGeoOperations = redisTemplate.boundGeoOps(GEO_STAGE);
+        GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringStringBoundGeoOperations.radius(circle, args);
+        return R.ok(radius);
+    }
+
+    @ApiOperation("测试")
+    @RequestMapping(value = "test", method = RequestMethod.GET)
+    public List<TWxUser> test() {
+        locationUtil.geoAdd("shijiazhuang1", 114.48, 38.03);
+        locationUtil.geoAdd("shijiazhuang2", 114.48, 38.02);
+        locationUtil.geoAdd("shijiazhuang3", 114.48, 39.03);
+
+        Map<String, Double> shijiazhuang1 = locationUtil.distanceInclude("shijiazhuang1", 30000);
+
+        log.error(shijiazhuang1.toString());
+
+        return null;
+    }
+
+}
+
+

+ 13 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TCommentController.java

@@ -1,9 +1,13 @@
 package com.ylx.web.controller.massage;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.core.domain.R;
+import com.ylx.common.utils.StringUtils;
 import com.ylx.common.utils.uuid.IdUtils;
 import com.ylx.massage.domain.TComment;
+import com.ylx.massage.domain.TJs;
 import com.ylx.massage.domain.TOrder;
 import com.ylx.massage.enums.OrderStatusEnum;
 import com.ylx.massage.service.TCommentService;
@@ -54,4 +58,13 @@ public class TCommentController {
         wrapper.lambda().orderByDesc(TComment::getdTime);
         return commentService.list(wrapper);
     }
+
+    @ApiOperation("分页查询评论")
+    @RequestMapping(value = "/select", method = RequestMethod.GET)
+    public Page<TComment> select(Page<TComment> page, TComment comment) {
+        LambdaQueryWrapper<TComment> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        objectLambdaQueryWrapper.like(StringUtils.isNotBlank(comment.getName()), TComment::getName, comment.getName()).
+                orderByDesc(TComment::getdTime);
+        return commentService.page(page, objectLambdaQueryWrapper);
+    }
 }

+ 48 - 5
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TJsController.java

@@ -3,12 +3,17 @@ package com.ylx.web.controller.massage;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.annotation.Log;
+import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.R;
+import com.ylx.common.core.domain.model.WxLoginUser;
 import com.ylx.common.enums.BusinessType;
 import com.ylx.common.exception.ServiceException;
+import com.ylx.common.utils.ListUtils;
+import com.ylx.massage.domain.Location;
 import com.ylx.massage.domain.TJs;
 import com.ylx.massage.domain.vo.TJsVo;
 import com.ylx.massage.service.TJsService;
+import com.ylx.massage.utils.LocationUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -20,7 +25,10 @@ import org.springframework.web.bind.annotation.RestController;
 
 
 import javax.annotation.Resource;
+import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 技师Controller
@@ -32,10 +40,13 @@ import java.util.List;
 @RequestMapping("api/js/v1")
 @Api(tags = {"技师管理"})
 @Slf4j
-public class TJsController {
+public class TJsController extends BaseController {
     @Resource
     private TJsService jsService;
 
+    @Resource
+    private LocationUtil locationUtil;
+
     /**
      * 添加技师申请
      *
@@ -47,6 +58,8 @@ public class TJsController {
     @ApiOperation("添加技师申请")
     public R add(@RequestBody TJs js) {
         try {
+            WxLoginUser wxLoginUser = getWxLoginUser();
+            js.setcOpenId(wxLoginUser.getCOpenid());
             return R.ok(jsService.addJs(js));
         } catch (ServiceException s) {
             log.error(s.toString());
@@ -74,13 +87,43 @@ public class TJsController {
     /**
      * 微信查询
      *
-     * @param param
+     * @param
      * @return
      */
-    @RequestMapping(value = "wx/select", method = RequestMethod.POST)
+    @RequestMapping(value = "wx/select", method = RequestMethod.GET)
     @ApiOperation("微信查询")
-    public List<TJs> wxSelect(@RequestBody TJsVo param) {
-        return jsService.getAll(param);
+    public R wxSelect(Page<TJs> page, TJsVo js) {
+        try {
+            if (js.getLatitude() != null && js.getLongitude() != null) {
+                // 检查经纬度是否在合理范围内
+                Location location = new Location();
+                location.setLatitude(js.getLatitude().doubleValue());
+                location.setLongitude(js.getLongitude().doubleValue());
+                location.setLimit(100L); // 考虑将此值作为参数或配置项
+                location.setRadius(1000.00);
+                List<TJs> nearbyTechnicians = locationUtil.dis(location);
+                if (nearbyTechnicians != null) {
+                    Map<String, BigDecimal> collect = nearbyTechnicians.stream().collect(Collectors.toMap(TJs::getcOpenId, TJs::getDistance));
+                    js.setIds(nearbyTechnicians.stream().map(TJs::getcOpenId).collect(Collectors.toList()));
+                    int size = (int) page.getSize();
+                    int pageNum = (int) page.getCurrent();
+                    page.setSize(nearbyTechnicians.size());
+                    page.setCurrent(1);
+                    Page<TJs> all = jsService.getAll(page, js);
+                    all.getRecords().forEach(item -> {
+                        item.setDistance(collect.get(item.getcOpenId()));
+                    });
+                    List<TJs> objects = (List<TJs>) ListUtils.subList(all.getRecords(), size, pageNum);
+                    page.setRecords(objects);
+                    page.setSize(size);
+                }
+            }
+            return R.ok(jsService.getAll(page, js));
+        } catch (Exception e) {
+            // 异常处理
+            e.printStackTrace();
+            return R.fail("操作失败");
+        }
     }
 
 

+ 2 - 3
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TLbtController.java

@@ -40,11 +40,10 @@ public class TLbtController {
      * @return
      */
     @ApiOperation("获取轮播图")
-    @Log(title = "轮播图管理", businessType = BusinessType.OTHER)
-    @RequestMapping(value = "/getAll", method = RequestMethod.POST)
+    @RequestMapping(value = "/getAll", method = RequestMethod.GET)
     public R<List<TLbt>> getAll() {
         QueryWrapper<TLbt> wrapper = new QueryWrapper<>();
-        wrapper.lambda().eq(TLbt::getnDel, MassageConstants.INTEGER_ZERO);
+        wrapper.lambda().eq(TLbt::getnDel, MassageConstants.INTEGER_ZERO).orderByAsc(TLbt::getcSort);
         List<TLbt> list = lbtService.list(wrapper);
         return R.ok(list);
     }

+ 20 - 8
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TOrderController.java

@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.core.domain.R;
 import com.ylx.common.utils.StringUtils;
 import com.ylx.massage.domain.TOrder;
+import com.ylx.massage.enums.Enumproject;
+import com.ylx.massage.enums.OrderStatusEnum;
 import com.ylx.massage.service.TOrderService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -110,12 +112,9 @@ public class TOrderController {
      */
     @ApiOperation("获取订单信息")
     @RequestMapping(value = "wx/getOrder", method = RequestMethod.GET)
-    public List<TOrder> getOrder(@RequestBody TOrder param) {
-        Page<TOrder> page = new Page<TOrder>();
-        page.setCurrent(-1);
-        page.setSize(-1);
+    public R getOrder(Page<TOrder> page, TOrder param) {
         Page<TOrder> all = orderService.getAll(page, param);
-        return all.getRecords();
+        return R.ok(all);
     }
 
 
@@ -123,11 +122,11 @@ public class TOrderController {
      * 分页查询数据
      */
     @ApiOperation("分页查询数据")
-    @RequestMapping(value = "/select", method = RequestMethod.POST)
+    @RequestMapping(value = "/select", method = RequestMethod.GET)
     public R selectSp(Page<TOrder> page, TOrder order) {
         LambdaQueryWrapper<TOrder> tOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        tOrderLambdaQueryWrapper.eq(StringUtils.isEmpty(order.getcJsId()), TOrder::getcJsId, order.getcJsId()).
-                eq(StringUtils.isEmpty(order.getcOpenId()), TOrder::getcOpenId, order.getcOpenId()).
+        tOrderLambdaQueryWrapper.eq(StringUtils.isNotBlank(order.getcJsId()), TOrder::getcJsId, order.getcJsId()).
+                eq(StringUtils.isNotBlank(order.getcOpenId()), TOrder::getcOpenId, order.getcOpenId()).
                 eq(null != order.getnStatus(), TOrder::getnStatus, order.getnStatus());
         // 获取查询返回结果
         Page<TOrder> pageSelect = orderService.page(page, tOrderLambdaQueryWrapper);
@@ -146,4 +145,17 @@ public class TOrderController {
     public R del(@RequestBody TOrder borrow) {
         return R.ok(orderService.removeById(borrow));
     }
+
+    @ApiOperation("根据id查询")
+    @RequestMapping(value = "/getByid", method = RequestMethod.POST)
+    public R<TOrder> getByid(@RequestBody TOrder borrow) {
+        return R.ok(orderService.getById(borrow.getcId()));
+    }
+
+    @ApiOperation("订单状态")
+    @RequestMapping(value = "/getStatus", method = RequestMethod.GET)
+    public R getStatus() {
+        List<Enumproject> statusEnum = OrderStatusEnum.getStatusEnum();
+        return R.ok(statusEnum);
+    }
 }

+ 2 - 3
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TTxRecordController.java

@@ -42,10 +42,9 @@ public class TTxRecordController {
      * @return
      */
     @ApiOperation("申请提现")
-    @RequestMapping(value = "wx/add", method = RequestMethod.POST)
-    public R add(@RequestBody TTxRecord record) {
+    @RequestMapping(value = "wx/addOrUpdate", method = RequestMethod.POST)
+    public R addOrUpdate(@RequestBody TTxRecord record) {
         if (StringUtils.isBlank(record.getcId())) {
-            record.setcId(IdUtils.fastSimpleUUID());
             record.setnStatus(TTxRecordEnum.PASS_ING.getCode());
             record.setDtCreateTime(LocalDateTime.now());
             UpdateWrapper<TWxUser> businessUpdateWrapper = new UpdateWrapper<>();

+ 132 - 8
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/WxController.java

@@ -1,5 +1,11 @@
 package com.ylx.web.controller.massage;
 
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
+import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
+import cn.hutool.core.net.url.UrlBuilder;
+import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -12,6 +18,7 @@ import com.ylx.common.core.domain.R;
 
 import com.ylx.common.core.domain.model.WxLoginUser;
 import com.ylx.framework.web.service.WxTokenService;
+import com.ylx.massage.utils.LocationUtil;
 import com.ylx.massage.utils.WxQrCodeUtil;
 import com.ylx.massage.utils.WxUtil;
 import com.ylx.massage.domain.TWxUser;
@@ -19,11 +26,16 @@ import com.ylx.massage.service.TWxUserService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.error.WxErrorException;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author : YJR
@@ -48,6 +60,9 @@ public class WxController extends BaseController {
     @Resource
     private WxTokenService wxTokenService;
 
+    @Autowired
+    private WxMaService wxMaService;
+
     /**
      * 获取二维码
      *
@@ -67,8 +82,8 @@ public class WxController extends BaseController {
      * @param wxLoginUser
      * @return
      */
-    @PostMapping("/login")
-    @ApiOperation("小程序登录")
+    @PostMapping("v0/login")
+    @ApiOperation("小程序登录不用")
     public AjaxResult login(@RequestBody WxLoginUser wxLoginUser) {
         AjaxResult ajax = new AjaxResult();
         try {
@@ -78,7 +93,7 @@ public class WxController extends BaseController {
             }
 
             //todo 获取用户信息自测方法
-            WxLoginUser wxUser = wxUtil.testgetUserOpenId(wxLoginUser.getCode());
+            WxLoginUser wxUser = wxUtil.getUserOpenId(wxLoginUser.getCode());
             if (wxUser == null) {
                 return AjaxResult.error("获取用户信息失败");
             }
@@ -111,7 +126,7 @@ public class WxController extends BaseController {
     public R getPhone(@RequestBody JSONObject param) {
         String code = param.getString("code");
         String openId = param.getString("openId");
-        if (StringUtils.isBlank(code) || StringUtils.isBlank(openId)) {
+        if (StringUtils.isBlank(code)) {
             return R.fail("openId或者授权conde为空");
         }
         String phone = wxUtil.getUserPhone(openId, code);
@@ -153,10 +168,7 @@ public class WxController extends BaseController {
     }
 
 
-    @RequestMapping(value = "updateUserInfo", method = RequestMethod.POST)
-    public R updateUserInfo(@RequestBody TWxUser wxUser) {
-        return R.ok(wxUserService.saveOrUpdate(wxUser));
-    }
+
 
     /**
      * 更新用户信息
@@ -193,4 +205,116 @@ public class WxController extends BaseController {
         Page<TWxUser> pageSelect = wxUserService.page(page, objectLambdaQueryWrapper);
         return R.ok(pageSelect);
     }
+
+    /**
+     * 登录接口
+     */
+    @ApiOperation("小程序登录")
+    @PostMapping("/login")
+    public R<Object> login(@RequestParam("code") String code, @RequestParam("encryptedData") String encryptedData,
+                                @RequestParam("iv") String iv) {
+        try {
+            // 调用微信 API 获取用户的 openid 和 session_key
+            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
+            String openid = session.getOpenid();
+
+            // 调用微信 API 获取用户的手机号
+            WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNoInfo(session.getSessionKey(), encryptedData, iv);
+            String phoneNumber = phoneInfo.getPhoneNumber();
+
+            // 调用微信 API 获取用户的详细信息
+            WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(session.getSessionKey(),encryptedData,iv);
+            // 获取用户昵称
+            String nickName = userInfo.getNickName();
+            // 获取用户头像
+            String avatarUrl = userInfo.getAvatarUrl();
+            // 获取用户国家
+            String country = userInfo.getCountry();
+            // 获取用户省份
+            String province = userInfo.getProvince();
+            // 获取用户城市
+            String city = userInfo.getCity();
+
+            // 将用户信息保存到数据库中
+            TWxUser user = wxUserService.getById(openid);
+            if (user == null) {
+                user = new TWxUser();
+                user.setcOpenid(openid);
+                user.setcNickName(nickName);
+                user.setcIcon(avatarUrl);
+                user.setcPhone(phoneNumber);
+                wxUserService.save(user);
+            } else {
+                user.setcNickName(nickName);
+                user.setcIcon(avatarUrl);
+                user.setcPhone(phoneNumber);
+                wxUserService.updateById(user);
+            }
+
+            WxLoginUser wxUser = new WxLoginUser();
+            BeanUtils.copyProperties(user, wxUser);
+            // 生成并返回令牌
+            String token = wxTokenService.createToken(wxUser);
+            if (token == null || token.isEmpty()) {
+                return R.fail("生成令牌失败");
+            }
+            wxUser.setToken(token);
+            // 返回用户信息
+            return R.ok(wxUser);
+        } catch (WxErrorException e) {
+            log.error("登录失败:" + e.getMessage(), e);
+            return R.fail("登录失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 更新用户信息接口
+     */
+    @PostMapping("/update")
+    public String updateUserInfo(@RequestBody TWxUser user) {
+        if (user == null || user.getcOpenid() == null) {
+            return "用户信息不能为空";
+        }
+
+        if (wxUserService.saveOrUpdate(user)) {
+            return "更新用户信息成功";
+        } else {
+            return "更新用户信息失败";
+        }
+    }
+
+    /**
+     * 获取微信用户手机号
+     *
+     * @param code code值
+     */
+    public String getMobilePhoneByWeixin(String code) {
+        try {
+
+            String accessToken = wxMaService.getAccessToken();
+            String url = UrlBuilder
+                    .of("https://api.weixin.qq.com/wxa/business/getuserphonenumber")
+                    .addQuery("access_token", accessToken)
+                    .build();
+            Map<String, Object> paramBody = new HashMap<>(2);
+            paramBody.put("code", code);
+            String result = HttpUtil.post(url, JSON.toJSONString(paramBody));
+            JSONObject jsonObject = JSONObject.from(JSON.parseObject(result));
+            if ("40029".equals(jsonObject.getString("errcode"))) {
+                throw new RuntimeException("code无效");
+            }
+
+            if ("-1".equals(jsonObject.getString("errcode"))) {
+                throw new RuntimeException("微信系统繁忙");
+            }
+            JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
+            return phoneInfo.getString("phoneNumber");
+        } catch (WxErrorException e) {
+            e.printStackTrace();
+            throw new RuntimeException("获取手机号失败");
+        }
+    }
+
+
+
 }

+ 13 - 0
nightFragrance-admin/src/main/resources/application-dev.yml

@@ -193,7 +193,20 @@ wx:
   app-id: wxe8661ef542cd963c
   # AppSecret(小程序密钥)
   app-secret: 7439a36812c1850d060567bce51159ec
+  # 商户号
+  mch-id: ""
+  # 商户秘钥
+  mch-key: ""
+  # 异步回调地址
+  notify-url: ""
+  # 证书地址
+  cert-path: ""
+  # 证书秘钥地址
+  cert-key-path: ""
+  # 微信平台证书
+  plat-form-path: ""
 
+  msgDataFormat: JSON
 # 防止XSS攻击
 xss:
   # 过滤开关

+ 6 - 0
nightFragrance-common/pom.xml

@@ -148,6 +148,12 @@
             <version>3.5.1</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-miniapp</artifactId>
+            <version>4.1.0</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 60 - 0
nightFragrance-common/src/main/java/com/ylx/common/config/WxPayConfig.java

@@ -0,0 +1,60 @@
+package com.ylx.common.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author jianlong
+ * @date 2024-04-02 18:20
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "wx")
+public class WxPayConfig {
+
+
+    /**
+     * appid.
+     */
+    private String appId;
+
+    /**
+     * appSecret.
+     */
+    private String appSecret;
+
+    /**
+     * 微信支付商户号.
+     */
+    private String mchId;
+
+    /**
+     * 微信支付商户密钥.
+     */
+    private String mchKey;
+
+    /**
+     * 异步回调地址
+     */
+    private String notifyUrl;
+
+    /**
+     * 证书地址
+     */
+    private String certPath;
+
+    /**
+     * 证书秘钥地址
+     */
+    private String certKeyPath;
+
+    /**
+     * 微信平台证书
+     */
+    private String platFormPath;
+
+    private String msgDataFormat;
+
+
+}

+ 24 - 0
nightFragrance-common/src/main/java/com/ylx/common/utils/ListUtils.java

@@ -0,0 +1,24 @@
+package com.ylx.common.utils;
+
+import org.apache.poi.ss.formula.functions.T;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author jianlong
+ * @date 2024-04-10 11:04
+ */
+public class ListUtils {
+    public static List<?> subList(List<?> list, int pageSize, int pageNum) {
+        int count = list.size(); // 总记录数
+        // 计算总页数
+        int pages = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
+        // 起始位置
+        int start = pageNum <= 0 ? 0 : (pageNum > pages ? (pages - 1) * pageSize : (pageNum - 1) * pageSize);
+        // 终止位置
+        int end = pageNum <= 0 ? (pageSize <= count ? pageSize : count) : (pageSize * pageNum <= count ? pageSize * pageNum : count);
+        return list.subList(start, end);
+    }
+
+}

+ 23 - 0
nightFragrance-framework/src/main/java/com/ylx/framework/config/BoundGeoOperationConfig.java

@@ -0,0 +1,23 @@
+//package com.ylx.framework.config;
+//
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.data.redis.core.BoundGeoOperations;
+//import org.springframework.data.redis.core.RedisTemplate;
+//
+///**
+// * @author jianlong
+// * @date 2024-04-08 09:31
+// */
+//
+//@Configuration
+//public class BoundGeoOperationConfig {
+//    @Autowired
+//    private RedisTemplate<String, Object> redisTemplate;
+//
+//    @Bean
+//    public BoundGeoOperations<String, Object> boundGeoOperations() {
+//        return (BoundGeoOperations<String, Object>) redisTemplate.opsForGeo();
+//    }
+//}

+ 3 - 1
nightFragrance-framework/src/main/java/com/ylx/framework/config/SecurityConfig.java

@@ -111,7 +111,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 // 过滤请求
                 .authorizeRequests()
                 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
-                .antMatchers("/login", "/register", "/captchaImage","/wx/login").permitAll()
+                .antMatchers("/login", "/register", "/captchaImage","/wx/login",
+                        "/api/lbt/v1/getAll", "/api/js/v1/select", "/api/xiangmu/v1/wx/getAll", "/api/order/v1/getStatus",
+                        "/api/xiangmu/v1/getByid", "/api/js/v1/wx/getByid").permitAll()
                 // 静态资源,可匿名访问
                 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()

+ 33 - 0
nightFragrance-framework/src/main/java/com/ylx/framework/config/WxMaConfiguration.java

@@ -0,0 +1,33 @@
+package com.ylx.framework.config;
+
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
+import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
+import com.ylx.common.config.WxPayConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author jianlong
+ * @date 2024-04-08 14:53
+ */
+@Configuration
+public class WxMaConfiguration {
+
+    @Autowired
+    private WxPayConfig wxPayProperties;
+    @Bean
+    public WxMaService wxMaService() {
+        WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
+        config.setAppid(wxPayProperties.getAppId());
+        config.setSecret(wxPayProperties.getAppSecret());
+        config.setMsgDataFormat(wxPayProperties.getMsgDataFormat());
+
+        WxMaService service = new WxMaServiceImpl();
+        service.setWxMaConfig(config);
+        return service;
+    }
+
+}

+ 7 - 0
nightFragrance-massage/pom.xml

@@ -25,6 +25,13 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>nightFragrance-common</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>com.github.javen205</groupId>
+            <artifactId>IJPay-WxPay</artifactId>
+            <version>2.9.10</version>
+        </dependency>
+
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>

+ 28 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/Location.java

@@ -0,0 +1,28 @@
+package com.ylx.massage.domain;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author jianlong
+ * @date 2024-04-07 15:43
+ */
+
+@Data
+@ApiModel("位置信息")
+public class Location {
+
+    @ApiModelProperty("经度")
+    private Double longitude;
+
+    @ApiModelProperty("纬度")
+    private Double latitude;
+
+    @ApiModelProperty("半径")
+    private Double radius;
+
+    @ApiModelProperty("条数")
+    private Long limit;
+
+}

+ 4 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/TComment.java

@@ -80,6 +80,10 @@ public class TComment implements Serializable {
     @ApiModelProperty("评论时间")
     private LocalDateTime dTime;
 
+    @TableField("name")
+    @ApiModelProperty("技师姓名")
+    private String name;
+
     /**
      * 订单id
      */

+ 19 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/TJs.java

@@ -12,6 +12,7 @@ import lombok.Setter;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 /**
@@ -114,6 +115,20 @@ public class TJs implements Serializable {
     @ApiModelProperty("佣金比例")
     private Integer nBili;
 
+    /**
+     * 经度
+     */
+    @TableField("longitude")
+    @ApiModelProperty("经度")
+    private BigDecimal longitude;
+
+    /**
+     * 纬度
+     */
+    @TableField("latitude")
+    @ApiModelProperty("纬度")
+    private BigDecimal latitude;
+
     /**
      * 已服务数量
      */
@@ -186,6 +201,10 @@ public class TJs implements Serializable {
     @ApiModelProperty("收藏人员数量")
     private Integer number;
 
+    @TableField(exist = false)
+    @ApiModelProperty("技师距离")
+    private BigDecimal distance ;
+
     public String getcOpenId() {
         return cOpenId;
     }

+ 4 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/TJsVo.java

@@ -6,6 +6,8 @@ import com.ylx.massage.domain.TJs;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * @author jianlong
  * @date 2024-03-26 16:10
@@ -16,4 +18,6 @@ public class TJsVo extends TJs {
     @ApiModelProperty("昵称或电话")
     private String nameOrPhone;
 
+    private List<String> ids;
+
 }

+ 23 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/enums/Enumproject.java

@@ -0,0 +1,23 @@
+package com.ylx.massage.enums;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiOperation;
+import lombok.Data;
+
+/**
+ * @author jianlong
+ * @date 2024-04-09 10:20
+ */
+
+@Data
+@ApiModel("枚举")
+public class Enumproject {
+
+    @ApiModelProperty("code")
+    private Integer code;
+
+    @ApiModelProperty("描述")
+    private String info;
+
+}

+ 22 - 3
nightFragrance-massage/src/main/java/com/ylx/massage/enums/OrderStatusEnum.java

@@ -1,5 +1,10 @@
 package com.ylx.massage.enums;
 
+import org.apache.commons.compress.utils.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author jianlong
  * @date 2024-03-27 11:51
@@ -7,15 +12,16 @@ package com.ylx.massage.enums;
  */
 public enum OrderStatusEnum {
 
-
+    ALL(null, "全部"),
     WAIT_JD(0, "待接单"),
     SERVICE(1, "服务中"),
-    WAIT_EVALUATE(2, "待评价(已完成)"),
-    COMPLETE(3, "已完成(已评价)"),
+    WAIT_EVALUATE(2, "待评价"),
+    COMPLETE(3, "已完成"),
     WAIT_PAY(-1, "待付款"),
     CANCEL(-2, "已取消"),
     REFUSE(-3, "已拒绝");
 
+
     private final Integer code;
     private final String info;
 
@@ -24,6 +30,19 @@ public enum OrderStatusEnum {
         this.info = info;
     }
 
+    public static List<Enumproject> getStatusEnum() {
+
+        ArrayList<Enumproject> objects = Lists.newArrayList();
+        for (OrderStatusEnum value : OrderStatusEnum.values()) {
+            Enumproject enumproject = new Enumproject();
+            enumproject.setInfo(value.getInfo());
+            enumproject.setCode(value.getCode());
+            objects.add(enumproject);
+
+        }
+        return objects;
+    }
+
     public Integer getCode() {
         return code;
     }

+ 2 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TJsMapper.java

@@ -1,6 +1,7 @@
 package com.ylx.massage.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.massage.domain.vo.TJsVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -13,5 +14,5 @@ import java.util.List;
  */
 @Mapper
 public interface TJsMapper extends BaseMapper<TJs> {
-    public List<TJs> getAll(@Param("param") TJsVo param);
+    public Page<TJs> getAll(@Param("page")Page<TJs> page ,@Param("param") TJsVo param);
 }

+ 2 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/service/TJsService.java

@@ -1,5 +1,6 @@
 package com.ylx.massage.service;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ylx.massage.domain.TJs;
 import com.ylx.massage.domain.vo.TJsVo;
@@ -11,7 +12,7 @@ import java.util.List;
  * 技师表 服务类
  */
 public interface TJsService extends IService<TJs> {
-    public List<TJs> getAll(TJsVo param);
+    public Page<TJs> getAll(Page<TJs> page, TJsVo param);
 
     boolean addJs(TJs js);
 }

+ 14 - 4
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TJsServiceImpl.java

@@ -1,6 +1,7 @@
 package com.ylx.massage.service.impl;
 
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ylx.common.constant.MassageConstants;
 import com.ylx.common.exception.ServiceException;
@@ -10,6 +11,7 @@ import com.ylx.massage.domain.vo.TJsVo;
 import com.ylx.massage.enums.JsStatusEnum;
 import com.ylx.massage.mapper.TJsMapper;
 import com.ylx.massage.service.TJsService;
+import com.ylx.massage.utils.LocationUtil;
 import org.springframework.stereotype.Service;
 
 
@@ -25,18 +27,27 @@ public class TJsServiceImpl extends ServiceImpl<TJsMapper, TJs> implements TJsSe
     @Resource
     private TJsMapper mapper;
 
+    @Resource
+    private LocationUtil locationUtil;
+
     @Override
-    public List<TJs> getAll(TJsVo param) {
-        return mapper.getAll(param);
+    public Page<TJs> getAll(Page<TJs> page, TJsVo param) {
+        return mapper.getAll(page, param);
     }
 
     @Override
     public boolean addJs(TJs js) {
 
-        if(StringUtils.isBlank(js.getcPhone())){
+        if (StringUtils.isBlank(js.getcPhone())) {
             throw new ServiceException("手机号不能为空");
         }
+        //缓存技师位置
+        locationUtil.geoAdd(js.getcOpenId(), js.getLongitude().doubleValue(), js.getLatitude().doubleValue());
+        extracted(js);
+        return this.save(js);
+    }
 
+    private static void extracted(TJs js) {
         // 评分默认最高
         js.setnStar(MassageConstants.INTEGER_FIVE);
         // 已服务数量 0
@@ -53,6 +64,5 @@ public class TJsServiceImpl extends ServiceImpl<TJsMapper, TJs> implements TJsSe
         js.setnB2(MassageConstants.INTEGER_ZERO);
         js.setnB3(MassageConstants.INTEGER_ZERO);
         js.setDtCreateTime(LocalDateTime.now());
-        return this.save(js);
     }
 }

+ 123 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/utils/LocationUtil.java

@@ -0,0 +1,123 @@
+package com.ylx.massage.utils;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.ylx.common.core.domain.R;
+import com.ylx.massage.domain.Location;
+import com.ylx.massage.domain.TJs;
+import org.apache.commons.compress.utils.Lists;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.geo.*;
+import org.springframework.data.redis.connection.RedisGeoCommands;
+import org.springframework.data.redis.core.BoundGeoOperations;
+import org.springframework.data.redis.core.GeoOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+
+/**
+ * @author jianlong
+ * @date 2024-04-07 15:49
+ */
+@Component
+public class LocationUtil {
+
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
+
+    /**
+     * 作为存储经纬度列表的key值
+     */
+    private static final String GEO_KEY = "JS_POSITION";
+
+    /**
+     * 将经纬度信息添加到redis中
+     *
+     * @param certId    标识
+     * @param longitude 经度
+     * @param latitude  纬度
+     */
+    public void geoAdd(String certId, double longitude, double latitude) {
+        GeoOperations geoOperations = redisTemplate.opsForGeo();
+        Point point = new Point(longitude, latitude);
+        RedisGeoCommands.GeoLocation geoLocation = new RedisGeoCommands.GeoLocation(certId, point);
+        geoOperations.add(GEO_KEY, geoLocation);
+    }
+
+    /**
+     * 两个人之间的距离
+     *
+     * @param certId1
+     * @param certId2
+     * @return
+     */
+    public double distanceBetween(String certId1, String certId2) {
+        GeoOperations geoOperations = redisTemplate.opsForGeo();
+        Distance distance = geoOperations.distance(GEO_KEY, certId1, certId2);
+        return distance.getValue();
+    }
+
+    /**
+     * 查询距离某个人指定范围内的人,包括距离多少米
+     *
+     * @param certId
+     * @param distance
+     * @return
+     */
+    public Map<String, Double> distanceInclude(String certId, double distance) {
+        Map<String, Double> map = new LinkedHashMap<>();
+
+        GeoOperations geoOperations = redisTemplate.opsForGeo();
+        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
+        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = geoOperations.radius(GEO_KEY, certId, new Distance(distance), geoRadiusCommandArgs.includeDistance());
+        if (geoResults != null) {
+            Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = geoResults.iterator();
+            while (iterator.hasNext()) {
+                GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = iterator.next();
+                // 与目标点相距的距离信息
+                Distance geoResultDistance = geoResult.getDistance();
+                // 该点的信息
+                RedisGeoCommands.GeoLocation<String> geoResultContent = geoResult.getContent();
+                map.put(geoResultContent.getName(), geoResultDistance.getValue());
+            }
+        }
+        return map;
+    }
+
+    public List<TJs> dis(Location locationBo) {
+
+        ArrayList<TJs> js = Lists.newArrayList();
+        //设置当前位置
+        Point point = new Point(locationBo.getLongitude(), locationBo.getLatitude());
+        //设置半径范围
+        Metric metric = RedisGeoCommands.DistanceUnit.METERS;
+        Distance distance = new Distance(locationBo.getRadius(), metric);
+        Circle circle = new Circle(point, distance);
+        //设置参数 包括距离、坐标、条数
+        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands
+                .GeoRadiusCommandArgs
+                .newGeoRadiusArgs()
+                .includeDistance()
+                .includeCoordinates()
+                .sortAscending()
+                .limit(locationBo.getLimit());
+        BoundGeoOperations<String, String> stringStringBoundGeoOperations = redisTemplate.boundGeoOps(GEO_KEY);
+        GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringStringBoundGeoOperations.radius(circle, args);
+
+        if (radius == null || CollectionUtil.isEmpty(radius.getContent())) {
+            return null;
+        }
+        radius.forEach(content -> {
+            TJs tJs = new TJs();
+            tJs.setcOpenId(content.getContent().getName());
+            tJs.setDistance(BigDecimal.valueOf(content.getDistance().getValue()));
+            js.add(tJs);
+        });
+        return js;
+    }
+
+
+}

+ 15 - 8
nightFragrance-massage/src/main/resources/mapper/massage/TJsMapper.xml

@@ -96,16 +96,23 @@
             <if test="param.nTong != null">
                 and js.n_tong = #{param.nTong}
             </if>
+            <if test="param.ids != null and param.ids.size() > 0">
+                and js.c_open_id in
+                <foreach item="id" collection="param.ids" open="(" separator="," close=")">
+                    #{id}
+                </foreach>
+            </if>
+
         </where>
 
-        <if test="param.suiji == null">
-            order by
-            dt_create_time desc
-        </if>
-        <if test="param.suiji != null">
-            order by
-            RAND() LIMIT #{ param.suiji }
-        </if>
+<!--        <if test="param.suiji == null">-->
+<!--            order by-->
+<!--            dt_create_time desc-->
+<!--        </if>-->
+<!--        <if test="param.suiji != null">-->
+<!--            order by-->
+<!--            RAND() LIMIT #{ param.suiji }-->
+<!--        </if>-->
     </select>
 
 </mapper>