Browse Source

Merge remote-tracking branch 'origin/dev' into dev

郭子栋 1 day ago
parent
commit
2930efc20a

+ 521 - 462
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/MaTechnicianController.java

@@ -18,6 +18,7 @@ import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.AjaxResult;
 import com.ylx.common.core.domain.R;
 import com.ylx.common.core.domain.model.LoginUser;
+import com.ylx.common.core.domain.model.WxLoginUser;
 import com.ylx.common.core.domain.model.aliyun.SMSVerificationCode;
 import com.ylx.common.core.domain.model.aliyun.SendSmsComponents;
 import com.ylx.common.core.domain.model.aliyun.SendSmsEnum;
@@ -31,6 +32,7 @@ import com.ylx.common.utils.StringUtils;
 import com.ylx.common.utils.poi.ExcelUtil;
 import com.ylx.framework.manager.AsyncManager;
 import com.ylx.framework.manager.factory.AsyncFactory;
+import com.ylx.framework.web.service.WxTokenService;
 import com.ylx.massage.domain.MaProject;
 import com.ylx.massage.domain.MaTechnician;
 import com.ylx.massage.domain.dto.*;
@@ -43,6 +45,8 @@ import com.ylx.servicecategory.service.ServiceCategoryService;
 import com.ylx.system.service.ISysConfigService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -68,6 +72,8 @@ import java.util.Random;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 
+import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;
+
 /**
  * 技师Controller
  *
@@ -75,6 +81,7 @@ import java.util.regex.Pattern;
  * @date 2024-03-22
  */
 @Api("技师管理")
+@Slf4j
 @RestController
 @RequestMapping("/technician/technician")
 public class MaTechnicianController extends BaseController {
@@ -94,6 +101,8 @@ public class MaTechnicianController extends BaseController {
     private ISysConfigService configService;
     @Autowired
     private RedisCache redisCache;
+    @Autowired
+    private WxTokenService wxTokenService;
 
 
     public static final String PHONE_THREEUSERPARTCLIENT_CODE_KEY = "sys:clientLogin:phone:";
@@ -131,9 +140,9 @@ public class MaTechnicianController extends BaseController {
     @ApiOperation(value = "商户登录", notes = "商户登录")
     @PostMapping(value = "/clientLogin")
     @Transactional
-    public Result<JSONObject> login(@RequestBody ThirdPartyLoginsVo thirdPartyLoginsVo) throws Exception {
+    public Result<WxLoginUser> login(@RequestBody ThirdPartyLoginsVo thirdPartyLoginsVo) throws Exception {
         // 获取登录用户信息
-        Result<JSONObject> result = new Result<>();
+        Result<WxLoginUser> result = new Result<>();
 
         // 校验手机号是否为空
         if (StringUtils.isEmpty(thirdPartyLoginsVo.getPhone())) {
@@ -164,271 +173,320 @@ public class MaTechnicianController extends BaseController {
             // 初始化加密工具
             BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
             // 验证:比对是否匹配
-            boolean isOk = encoder.matches(thirdPartyLoginsVo.getPassWord(),maTechnician.getTePassword());
-                if (!isOk) {
-                    return Result.error("密码错误");
-                }
-
-
+            boolean isOk = encoder.matches(thirdPartyLoginsVo.getPassWord(), maTechnician.getTePassword());
+            if (!isOk) {
+                return Result.error("密码错误");
             }
 
-            // 登录成功删除验证码
-            redisTemplate.delete(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone());
-            result.success("登录成功");
-            return result;
-        }
 
-        /**
-         * 商户忘记密码接口
-         */
-        @PostMapping("/resetPassword")
-        public Result<?> resetPassword (@RequestBody ThirdPartyLoginsVo thirdPartyLoginsVo){
-            // 核心正则表达式:
-            // ^ 表示开头,$ 表示结尾
-            // [a-zA-Z0-9] 表示只能是字母或数字
-            // {8,20} 表示长度必须在8到20之间
-            String regex = "^[a-zA-Z0-9]{8,20}$";
-            boolean isMatch = Pattern.matches(regex, thirdPartyLoginsVo.getPassWord().trim());
-            if (!isMatch) {
-                // 根据需求返回指定的异常提示
-                return Result.error("请输入8-20位数字/字母组合");
-            }
-            // 短信验证
-            String msg = redisTemplate.opsForValue().get(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone());
-            if (StringUtils.isEmpty(msg)) {
-                return Result.error("验证码已失效");
-            }
-            if (msg != null && msg.startsWith("\"") && msg.endsWith("\"")) {
-                msg = msg.substring(1, msg.length() - 1);
-            }
-            if (!thirdPartyLoginsVo.getPhoneMsg().equals(msg)) {
-                return Result.error("短信验证码不正确");
-            }
-            // 重置密码逻辑
-            LambdaUpdateWrapper<MaTechnician> updateWrapper = new LambdaUpdateWrapper<>();
-            updateWrapper.eq(MaTechnician::getTePhone, thirdPartyLoginsVo.getPhone());
-            updateWrapper.set(MaTechnician::getTePassword, thirdPartyLoginsVo.getPassWord());
-            maTechnicianService.update(updateWrapper);
-            redisTemplate.delete(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone());
-            return Result.ok("重置密码成功");
         }
-
-        /**
-         * 校验图形验证码接口
-         */
-        @PostMapping("/getValidateCaptcha")
-        public Result<?> getValidateCaptcha (@RequestBody ValidateCaptchaDto req){
-            validateCaptcha(req.getPhone(), req.getCode(), req.getUuid());
-            return Result.ok("校验成功");
+        WxLoginUser wxUser = new WxLoginUser();
+        BeanUtils.copyProperties(maTechnician, wxUser);
+        // 生成并返回令牌
+        String token = wxTokenService.createToken(wxUser);
+        log.info("token的值:{}", token);
+        if (token == null || token.isEmpty()) {
+            return Result.error("生成令牌失败");
         }
-        /**
-         * 商户入驻申请接口
-         */
-        @PostMapping("/apply")
-        public Result<?> apply (@RequestBody MaTechnicianAppAddVo req){
-            // 1. 基础参数校验
-            if (StringUtils.isAnyBlank(req.getTeName(), req.getTePhone(), req.getTeAddress(), req.getAvatar())) {
-                return Result.error("必填项不能为空");
-            }
-            //校验性别不能为空
-            if (Objects.isNull(req.getTeSex())) {
-                return Result.error("性别不能为空");
-            }
-            // 短信验证
-            String msg = redisTemplate.opsForValue().get(PHONE_THREEUSERPARTCLIENT_CODE_KEY + req.getTePhone());
-            if (StringUtils.isEmpty(msg)) {
-                return Result.error("验证码已失效");
-            }
-            if (msg != null && msg.startsWith("\"") && msg.endsWith("\"")) {
-                msg = msg.substring(1, msg.length() - 1);
-            }
-            if (!req.getPhoneMsg().equals(msg)) {
-                return Result.error("短信验证码不正确");
-            }
-            if (StringUtils.isNotEmpty(req.getPhoneImgMsg())) {
-                validateCaptcha(req.getTeName(), req.getPhoneImgMsg(), req.getUuid());
-            }
-            // 2. 调用业务层处理入驻申请
-            maTechnicianService.apply(req);
-            return Result.ok("提交成功,进入审核流程");
+        //给我把token的值保存到redis中
+        redisTemplate.opsForValue().set(wxUser.getCOpenid(), token, 180, TimeUnit.MINUTES);
+        wxUser.setToken(token);
+        // 返回用户信息
+        // 记录登录信息
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxUser.getCOpenid(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        result.setResult(wxUser);
+        // 登录成功删除验证码
+        redisTemplate.delete(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone());
+
+        result.success("登录成功");
+        return result;
+    }
+
+    /**
+     * 商户忘记密码接口
+     */
+    @PostMapping("/resetPassword")
+    public Result<?> resetPassword(@RequestBody ThirdPartyLoginsVo thirdPartyLoginsVo) {
+        // 核心正则表达式:
+        // ^ 表示开头,$ 表示结尾
+        // [a-zA-Z0-9] 表示只能是字母或数字
+        // {8,20} 表示长度必须在8到20之间
+        String regex = "^[a-zA-Z0-9]{8,20}$";
+        boolean isMatch = Pattern.matches(regex, thirdPartyLoginsVo.getPassWord().trim());
+        if (!isMatch) {
+            // 根据需求返回指定的异常提示
+            return Result.error("请输入8-20位数字/字母组合");
+        }
+        // 短信验证
+        String msg = redisTemplate.opsForValue().get(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone());
+        if (StringUtils.isEmpty(msg)) {
+            return Result.error("验证码已失效");
+        }
+        if (msg != null && msg.startsWith("\"") && msg.endsWith("\"")) {
+            msg = msg.substring(1, msg.length() - 1);
+        }
+        if (!thirdPartyLoginsVo.getPhoneMsg().equals(msg)) {
+            return Result.error("短信验证码不正确");
+        }
+        // 重置密码逻辑
+        LambdaUpdateWrapper<MaTechnician> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(MaTechnician::getTePhone, thirdPartyLoginsVo.getPhone());
+        updateWrapper.set(MaTechnician::getTePassword, thirdPartyLoginsVo.getPassWord());
+        maTechnicianService.update(updateWrapper);
+        redisTemplate.delete(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone());
+        return Result.ok("重置密码成功");
+    }
+
+    /**
+     * 校验图形验证码接口
+     */
+    @PostMapping("/getValidateCaptcha")
+    public Result<?> getValidateCaptcha(@RequestBody ValidateCaptchaDto req) {
+        validateCaptcha(req.getPhone(), req.getCode(), req.getUuid());
+        return Result.ok("校验成功");
+    }
+
+    /**
+     * 商户入驻申请接口
+     */
+    @PostMapping("/apply")
+    public Result<?> apply(@RequestBody MaTechnicianAppAddVo req) {
+        // 1. 基础参数校验
+        if (StringUtils.isAnyBlank(req.getTeName(), req.getTePhone(),  req.getAvatar())) {
+            return Result.error("必填项不能为空");
         }
-        /**
-         * 校验验证码
-         *
-         * @param username 用户名
-         * @param code     验证码
-         * @param uuid     唯一标识
-         * @return 结果
-         */
-        public void validateCaptcha (String username, String code, String uuid){
-            boolean captchaEnabled = configService.selectCaptchaEnabled();
-            if (captchaEnabled) {
-                String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
-                String captcha = redisCache.getCacheObject(verifyKey);
-                redisCache.deleteObject(verifyKey);
-                if (captcha == null) {
-                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
-                    throw new CaptchaExpireException();
-                }
-                if (!code.equalsIgnoreCase(captcha)) {
-                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
-                    throw new CaptchaException();
-                }
-            }
+        //校验性别不能为空
+        if (Objects.isNull(req.getTeSex())) {
+            return Result.error("性别不能为空");
         }
-
-        /**
-         * 申请技师文件
-         * @param req
-         */
-        @PostMapping("/applyFile")
-        public Result applyFile (@RequestBody MerchantApplyFileRequestDto req) {
-            maTechnicianService.applyFile(req);
-            return Result.ok("上传成功");
+        // 短信验证
+        String msg = redisTemplate.opsForValue().get(PHONE_THREEUSERPARTCLIENT_CODE_KEY + req.getTePhone());
+        if (StringUtils.isEmpty(msg)) {
+            return Result.error("验证码已失效");
         }
-        /**
-         * 获取待接单列表:前端传技师实时经纬度筛选订单
-         */
-        @GetMapping("/wait/list")
-        public Result<List<WaitOrderDTO>> getWaitOrder (WaitOrderQueryDTO query){
-            List<WaitOrderDTO> list = maTechnicianService.listWaitOrder(query);
-            return Result.ok(list);
+        if (msg != null && msg.startsWith("\"") && msg.endsWith("\"")) {
+            msg = msg.substring(1, msg.length() - 1);
         }
-
-        /**
-         * 技师状态切换
-         *
-         * @param
-         */
-        @GetMapping("/switchToOffline")
-        public Result switchToOffline (@RequestParam Long userId, @RequestParam Boolean forceConfirm){
-            return maTechnicianService.switchToOffline(userId, forceConfirm);
+        if (!req.getPhoneMsg().equals(msg)) {
+            return Result.error("短信验证码不正确");
         }
-        /**
-         * 查询商户信息接口
-         */
-        @GetMapping("/getTechnician")
-        public Result<?> getTechnician (@RequestParam String openid){
-            LambdaQueryWrapper<MaTechnician> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(MaTechnician::getCOpenid, openid);
-            MaTechnician maTechnician = maTechnicianService.getBaseMapper().selectOne(queryWrapper);
-            return Result.ok(maTechnician);
+        if (StringUtils.isNotEmpty(req.getPhoneImgMsg())) {
+            validateCaptcha(req.getTeName(), req.getPhoneImgMsg(), req.getUuid());
         }
+        // 2. 调用业务层处理入驻申请
+        maTechnicianService.apply(req);
+        return Result.ok("提交成功,进入审核流程");
+    }
 
-        /**
-         * 修改和上传商户信息接口
-         */
-        @PostMapping("/updateTechnician")
-        public Result<?> updateTechnician (@RequestBody MaTechnicianAppAddVo req){
-            if (req.getAuditStatus() == 0 || req.getAuditStatus() == 3) {
-                //修改基本信息
-                updateMaTechnician(req);
+    /**
+     * 校验验证码
+     *
+     * @param username 用户名
+     * @param code     验证码
+     * @param uuid     唯一标识
+     * @return 结果
+     */
+    public void validateCaptcha(String username, String code, String uuid) {
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        if (captchaEnabled) {
+            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
+            String captcha = redisCache.getCacheObject(verifyKey);
+            redisCache.deleteObject(verifyKey);
+            if (captcha == null) {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
+                throw new CaptchaExpireException();
+            }
+            if (!code.equalsIgnoreCase(captcha)) {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
+                throw new CaptchaException();
             }
-            return Result.ok("修改成功");
         }
+    }
 
+    /**
+     * 申请技师文件
+     *
+     * @param req
+     */
+    @PostMapping("/applyFile")
+    public Result applyFile(@RequestBody MerchantApplyFileRequestDto req) {
+        maTechnicianService.applyFile(req);
+        return Result.ok("上传成功");
+    }
 
-        private void updateMaTechnician (MaTechnicianAppAddVo req){
-            LambdaUpdateWrapper<MaTechnician> updateWrapper = new LambdaUpdateWrapper<>();
-            updateWrapper.eq(MaTechnician::getId, req.getId());
-            updateWrapper.set(MaTechnician::getTePhone, req.getTePhone());
-            updateWrapper.set(MaTechnician::getTeName, req.getTeName());
-            updateWrapper.set(MaTechnician::getOpenService, req.getServiceTag());
-            updateWrapper.set(MaTechnician::getTeAddress, req.getTeAddress());
-            updateWrapper.set(MaTechnician::getTeAge, req.getTeAge());
-            updateWrapper.set(MaTechnician::getAvatar, req.getAvatar());
-            updateWrapper.set(MaTechnician::getTeBrief, req.getTeBrief());
-            maTechnicianService.update(updateWrapper);
-        }
+    /**
+     * 获取待接单列表:前端传技师实时经纬度筛选订单
+     */
+    @PostMapping("/wait/list")
+    public Result<List<WaitOrderDTO>> getWaitOrder(@RequestBody WaitOrderQueryDTO query) {
+        List<WaitOrderDTO> list = maTechnicianService.listWaitOrder(query);
+        return Result.ok(list);
+    }
 
-        /**
-         * 查询技师列表
-         */
-        @PreAuthorize("@ss.hasPermi('technician:technician:list')")
-        @GetMapping("/list")
-        public TableDataInfo list (MaTechnician maTechnician){
-            startPage();
-            List<MaTechnician> list = maTechnicianService.selectMaTechnicianList(maTechnician);
-            return getDataTable(list);
-        }
+    /**
+     * 滑动接单逻辑不变,
+     * 仅列表查询逻辑修正
+     */
+    @PostMapping("/accept")
+    public Result<String> acceptOrder(@RequestBody AcceptOrderReqDTO req) {
+        String tip = maTechnicianService.acceptOrder(req);
+        return Result.ok(tip);
+    }
 
-        /**
-         * 导出技师列表
-         */
-        @PreAuthorize("@ss.hasPermi('technician:technician:export')")
-        @Log(title = "技师", businessType = BusinessType.EXPORT)
-        @PostMapping("/export")
-        public void export (HttpServletResponse response, MaTechnician maTechnician){
-            List<MaTechnician> list = maTechnicianService.selectMaTechnicianList(maTechnician);
-            ExcelUtil<MaTechnician> util = new ExcelUtil<MaTechnician>(MaTechnician.class);
-            util.exportExcel(response, list, "技师数据");
-        }
+    /**
+     * 技师接单确认逻辑不变,
+     * 仅列表查询逻辑修正
+     */
+    @GetMapping("/rest/confirm")
+    public Result<String> confirmRestAccept(@RequestParam Long techId, @RequestParam Long orderId) {
+        String tip = maTechnicianService.confirmRestAccept(techId, orderId);
+        return Result.ok(tip);
+    }
 
-        /**
-         * 获取技师详细信息
-         */
-        @PreAuthorize("@ss.hasPermi('technician:technician:query')")
-        @GetMapping(value = "/{id}")
-        public AjaxResult getInfo (@PathVariable("id") Long id){
-            return success(maTechnicianService.selectMaTechnicianById(id));
-        }
+    /**
+     * 技师拒绝接单逻辑不变,
+     * 仅列表查询逻辑修正
+     */
+    @PostMapping("/refuse")
+    public Result<Void> refuseOrder(@RequestBody RefuseOrderReqDTO req) {
+        maTechnicianService.refuseOrder(req);
+        return Result.ok("拒绝成功");
+    }
+
+    /**
+     * 技师状态切换
+     *
+     * @param
+     */
+    @GetMapping("/switchToOffline")
+    public Result switchToOffline(@RequestParam Long userId, @RequestParam Boolean forceConfirm) {
+        return maTechnicianService.switchToOffline(userId, forceConfirm);
+    }
 
-        /**
-         * 新增技师
-         */
-        @ApiOperation("技师入驻")
-        @PreAuthorize("@ss.hasPermi('technician:technician:add')")
-        @Log(title = "技师", businessType = BusinessType.INSERT)
-        @PostMapping
-        public AjaxResult add (@RequestBody MaTechnicianAppAddVo maTechnicianAppAddVo){
-            return toAjax(maTechnicianService.insertMaTechnician(maTechnicianAppAddVo));
+    /**
+     * 查询商户信息接口
+     */
+    @GetMapping("/getTechnician")
+    public Result<?> getTechnician(@RequestParam String openid) {
+        LambdaQueryWrapper<MaTechnician> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(MaTechnician::getCOpenid, openid);
+        MaTechnician maTechnician = maTechnicianService.getBaseMapper().selectOne(queryWrapper);
+        return Result.ok(maTechnician);
+    }
+
+    /**
+     * 修改和上传商户信息接口
+     */
+    @PostMapping("/updateTechnician")
+    public Result<?> updateTechnician(@RequestBody MaTechnicianAppAddVo req) {
+        if (req.getAuditStatus() == 0 || req.getAuditStatus() == 3) {
+            //修改基本信息
+            updateMaTechnician(req);
         }
+        return Result.ok("修改成功");
+    }
 
-        /**
-         * 后台新增商户
-         *
-         * @param dto 商户新增DTO
-         * @return AjaxResult 结果
-         */
-        @ApiOperation("后台新增商户")
-        @PreAuthorize("@ss.hasPermi('technician:technician:add')")
-        @Log(title = "商户", businessType = BusinessType.INSERT)
-        @PostMapping("/merchant")
-        public AjaxResult addMerchant (@RequestBody MaTechnicianMerchantAddDTO dto){
-            try {
-                LoginUser loginUser = getLoginUser();
-                return toAjax(maTechnicianService.insertMerchant(dto, loginUser));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+
+    private void updateMaTechnician(MaTechnicianAppAddVo req) {
+        LambdaUpdateWrapper<MaTechnician> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(MaTechnician::getId, req.getId());
+        updateWrapper.set(MaTechnician::getTePhone, req.getTePhone());
+        updateWrapper.set(MaTechnician::getTeName, req.getTeName());
+        updateWrapper.set(MaTechnician::getOpenService, req.getServiceTag());
+        updateWrapper.set(MaTechnician::getTeAge, req.getTeAge());
+        updateWrapper.set(MaTechnician::getAvatar, req.getAvatar());
+        updateWrapper.set(MaTechnician::getTeBrief, req.getTeBrief());
+        maTechnicianService.update(updateWrapper);
+    }
+
+    /**
+     * 查询技师列表
+     */
+    @PreAuthorize("@ss.hasPermi('technician:technician:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(MaTechnician maTechnician) {
+        startPage();
+        List<MaTechnician> list = maTechnicianService.selectMaTechnicianList(maTechnician);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出技师列表
+     */
+    @PreAuthorize("@ss.hasPermi('technician:technician:export')")
+    @Log(title = "技师", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, MaTechnician maTechnician) {
+        List<MaTechnician> list = maTechnicianService.selectMaTechnicianList(maTechnician);
+        ExcelUtil<MaTechnician> util = new ExcelUtil<MaTechnician>(MaTechnician.class);
+        util.exportExcel(response, list, "技师数据");
+    }
+
+    /**
+     * 获取技师详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('technician:technician:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(maTechnicianService.selectMaTechnicianById(id));
+    }
+
+    /**
+     * 新增技师
+     */
+    @ApiOperation("技师入驻")
+    @PreAuthorize("@ss.hasPermi('technician:technician:add')")
+    @Log(title = "技师", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody MaTechnicianAppAddVo maTechnicianAppAddVo) {
+        return toAjax(maTechnicianService.insertMaTechnician(maTechnicianAppAddVo));
+    }
+
+    /**
+     * 后台新增商户
+     *
+     * @param dto 商户新增DTO
+     * @return AjaxResult 结果
+     */
+    @ApiOperation("后台新增商户")
+    @PreAuthorize("@ss.hasPermi('technician:technician:add')")
+    @Log(title = "商户", businessType = BusinessType.INSERT)
+    @PostMapping("/merchant")
+    public AjaxResult addMerchant(@RequestBody MaTechnicianMerchantAddDTO dto) {
+        try {
+            LoginUser loginUser = getLoginUser();
+            return toAjax(maTechnicianService.insertMerchant(dto, loginUser));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 后台编辑商户
-         *
-         * @param id  商户ID
-         * @param dto 商户编辑DTO
-         * @return AjaxResult 结果
-         */
-        @ApiOperation("后台编辑商户")
-        @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
-        @Log(title = "商户", businessType = BusinessType.UPDATE)
-        @PutMapping("/merchant/{id}")
-        public AjaxResult editMerchant (@PathVariable("id") Integer id, @RequestBody MaTechnicianMerchantAddDTO dto){
-            try {
-                LoginUser loginUser = getLoginUser();
-                return toAjax(maTechnicianService.updateMerchant(id, dto, loginUser));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 后台编辑商户
+     *
+     * @param id  商户ID
+     * @param dto 商户编辑DTO
+     * @return AjaxResult 结果
+     */
+    @ApiOperation("后台编辑商户")
+    @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
+    @Log(title = "商户", businessType = BusinessType.UPDATE)
+    @PutMapping("/merchant/{id}")
+    public AjaxResult editMerchant(@PathVariable("id") Integer id, @RequestBody MaTechnicianMerchantAddDTO dto) {
+        try {
+            LoginUser loginUser = getLoginUser();
+            return toAjax(maTechnicianService.updateMerchant(id, dto, loginUser));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
     /**
      * 后台上传商户合同文件
      *
-     * @param id   商户ID
+     * @param id  商户ID
      * @param map 合同文件
      * @return R 上传结果
      */
@@ -436,7 +494,7 @@ public class MaTechnicianController extends BaseController {
     @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
     @Log(title = "商户合同", businessType = BusinessType.UPDATE)
     @PostMapping("/merchant/{id}/contract")
-    public R uploadMerchantContract(@PathVariable("id") Integer id, @RequestBody Map<String,Object> map) {
+    public R uploadMerchantContract(@PathVariable("id") Integer id, @RequestBody Map<String, Object> map) {
         try {
             LoginUser loginUser = getLoginUser();
             return R.ok(maTechnicianService.uploadMerchantContract(id, map, loginUser));
@@ -446,259 +504,260 @@ public class MaTechnicianController extends BaseController {
         }
     }
 
-        /**
-         * 查询商户入驻审核列表
-         *
-         * @param page 分页参数
-         * @param dto  查询条件
-         * @return Page 商户入驻审核分页列表
-         */
-        @ApiOperation("后台查询商户入驻审核列表")
-        @PreAuthorize("@ss.hasPermi('technician:technician:list')")
-        @GetMapping("/merchant/audit/list")
-        public R<Page<MaTechnicianAuditListVO>> merchantAuditList
-        (Page < MaTechnicianAuditListVO > page, MaTechnicianAuditQueryDTO dto){
-            try {
-                return R.ok(maTechnicianService.selectMerchantAuditList(page, dto));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 查询商户入驻审核列表
+     *
+     * @param page 分页参数
+     * @param dto  查询条件
+     * @return Page 商户入驻审核分页列表
+     */
+    @ApiOperation("后台查询商户入驻审核列表")
+    @PreAuthorize("@ss.hasPermi('technician:technician:list')")
+    @GetMapping("/merchant/audit/list")
+    public R<Page<MaTechnicianAuditListVO>> merchantAuditList
+    (Page<MaTechnicianAuditListVO> page, MaTechnicianAuditQueryDTO dto) {
+        try {
+            return R.ok(maTechnicianService.selectMerchantAuditList(page, dto));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 商户入驻审核
-         *
-         * @param id  商户ID
-         * @param dto 审核提交参数
-         * @return AjaxResult 结果
-         */
-        @ApiOperation("商户入驻审核")
-        @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
-        @Log(title = "商户入驻审核", businessType = BusinessType.UPDATE)
-        @PutMapping("/merchant/audit/{id}/submit")
-        public AjaxResult submitMerchantAudit (@PathVariable("id") Integer id, @RequestBody MaTechnicianAuditSubmitDTO
-        dto){
-            try {
-                LoginUser loginUser = getLoginUser();
-                return toAjax(maTechnicianService.submitMerchantAudit(id, dto, loginUser));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 商户入驻审核
+     *
+     * @param id  商户ID
+     * @param dto 审核提交参数
+     * @return AjaxResult 结果
+     */
+    @ApiOperation("商户入驻审核")
+    @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
+    @Log(title = "商户入驻审核", businessType = BusinessType.UPDATE)
+    @PutMapping("/merchant/audit/{id}/submit")
+    public AjaxResult submitMerchantAudit(@PathVariable("id") Integer id, @RequestBody MaTechnicianAuditSubmitDTO
+                                                                                  dto) {
+        try {
+            LoginUser loginUser = getLoginUser();
+            return toAjax(maTechnicianService.submitMerchantAudit(id, dto, loginUser));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 待审核页面审核通过商户
-         *
-         * @param id  商户ID
-         * @param dto 待审核通过参数
-         * @return AjaxResult 结果
-         */
-        @ApiOperation("待审核页面审核通过商户")
-        @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
-        @Log(title = "商户待审核通过", businessType = BusinessType.UPDATE)
-        @PutMapping("/merchant/audit/{id}/approve")
-        public AjaxResult approvePendingMerchantAudit (@PathVariable("id") Integer id,
-                                                                                           @RequestBody MaTechnicianPendingAuditSubmitDTO
-        dto){
-            try {
-                LoginUser loginUser = getLoginUser();
-                return toAjax(maTechnicianService.approvePendingMerchantAudit(id, dto, loginUser));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 待审核页面审核通过商户
+     *
+     * @param id  商户ID
+     * @param dto 待审核通过参数
+     * @return AjaxResult 结果
+     */
+    @ApiOperation("待审核页面审核通过商户")
+    @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
+    @Log(title = "商户待审核通过", businessType = BusinessType.UPDATE)
+    @PutMapping("/merchant/audit/{id}/approve")
+    public AjaxResult approvePendingMerchantAudit(@PathVariable("id") Integer id,
+                                                  @RequestBody MaTechnicianPendingAuditSubmitDTO
+                                                          dto) {
+        try {
+            LoginUser loginUser = getLoginUser();
+            return toAjax(maTechnicianService.approvePendingMerchantAudit(id, dto, loginUser));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 查询商户列表
-         *
-         * @param page 分页参数
-         * @param dto  商户查询DTO
-         * @return Page 商户分页列表
-         */
-        @ApiOperation("后台查询商户列表")
-        @PreAuthorize("@ss.hasPermi('technician:technician:list')")
-        @GetMapping("/merchant/list")
-        public R<Page<MaTechnicianMerchantListVO>> merchantList
-        (Page < MaTechnicianMerchantListVO > page, MaTechnicianMerchantQueryDTO dto){
-            try {
-                return R.ok(maTechnicianService.selectMerchantList(page, dto));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 查询商户列表
+     *
+     * @param page 分页参数
+     * @param dto  商户查询DTO
+     * @return Page 商户分页列表
+     */
+    @ApiOperation("后台查询商户列表")
+    @PreAuthorize("@ss.hasPermi('technician:technician:list')")
+    @GetMapping("/merchant/list")
+    public R<Page<MaTechnicianMerchantListVO>> merchantList
+    (Page<MaTechnicianMerchantListVO> page, MaTechnicianMerchantQueryDTO dto) {
+        try {
+            return R.ok(maTechnicianService.selectMerchantList(page, dto));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 查询商户详情
-         *
-         * @param id 商户ID
-         * @return R<MaTechnicianMerchantDetailVO> 商户详情
-         */
-        @ApiOperation("后台查询商户详情")
-        @PreAuthorize("@ss.hasPermi('technician:technician:query')")
-        @GetMapping("/merchant/detail/{id}")
-        public R<MaTechnicianMerchantDetailVO> merchantDetail (@PathVariable("id") Long id){
-            try {
-                return R.ok(maTechnicianService.selectMerchantDetail(id));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 查询商户详情
+     *
+     * @param id 商户ID
+     * @return R<MaTechnicianMerchantDetailVO> 商户详情
+     */
+    @ApiOperation("后台查询商户详情")
+    @PreAuthorize("@ss.hasPermi('technician:technician:query')")
+    @GetMapping("/merchant/detail/{id}")
+    public R<MaTechnicianMerchantDetailVO> merchantDetail(@PathVariable("id") Long id) {
+        try {
+            return R.ok(maTechnicianService.selectMerchantDetail(id));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 查看商户证照
-         *
-         * @param id 商户ID
-         * @return R<MaTechnicianCertificateVO> 商户证照
-         */
-        @ApiOperation("后台查看商户证照")
-        @PreAuthorize("@ss.hasPermi('technician:technician:query')")
-        @GetMapping("/merchant/{id}/certificate")
-        public R<MaTechnicianCertificateVO> merchantCertificate (@PathVariable("id") Integer id){
-            try {
-                return R.ok(maTechnicianService.selectMerchantCertificate(id));
-            } catch (Exception e) {
-                e.printStackTrace();
-                throw new RuntimeException(e);
-            }
+    /**
+     * 查看商户证照
+     *
+     * @param id 商户ID
+     * @return R<MaTechnicianCertificateVO> 商户证照
+     */
+    @ApiOperation("后台查看商户证照")
+    @PreAuthorize("@ss.hasPermi('technician:technician:query')")
+    @GetMapping("/merchant/{id}/certificate")
+    public R<MaTechnicianCertificateVO> merchantCertificate(@PathVariable("id") Integer id) {
+        try {
+            return R.ok(maTechnicianService.selectMerchantCertificate(id));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
+    }
 
-        /**
-         * 修改技师
-         */
-        @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
-        @Log(title = "技师", businessType = BusinessType.UPDATE)
-        @PutMapping
-        public AjaxResult edit (@RequestBody MaTechnicianAppAddVo maTechnicianAppAddVo){
-            return toAjax(maTechnicianService.updateMaTechnician(maTechnicianAppAddVo));
-        }
+    /**
+     * 修改技师
+     */
+    @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
+    @Log(title = "技师", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody MaTechnicianAppAddVo maTechnicianAppAddVo) {
+        return toAjax(maTechnicianService.updateMaTechnician(maTechnicianAppAddVo));
+    }
 
-        /**
-         * 删除技师
-         */
-        @PreAuthorize("@ss.hasPermi('technician:technician:remove')")
-        @Log(title = "技师", businessType = BusinessType.DELETE)
-        @DeleteMapping("/{ids}")
-        public AjaxResult remove (@PathVariable Long[]ids){
-            return toAjax(maTechnicianService.deleteMaTechnicianByIds(ids));
-        }
+    /**
+     * 删除技师
+     */
+    @PreAuthorize("@ss.hasPermi('technician:technician:remove')")
+    @Log(title = "技师", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(maTechnicianService.deleteMaTechnicianByIds(ids));
+    }
 
-        /**
-         * 1. 获取服务类目列表 (对应图1、图3)
-         */
-        @GetMapping("/getServiceCategoryList")
-        public AjaxResult getServiceCategoryList () {
-            List<ServiceCategory> list = serviceCategoryService.listH5ServiceCategory();
-            return AjaxResult.success(list);
-        }
+    /**
+     * 1. 获取服务类目列表 (对应图1、图3)
+     */
+    @GetMapping("/getServiceCategoryList")
+    public AjaxResult getServiceCategoryList() {
+        List<ServiceCategory> list = serviceCategoryService.listH5ServiceCategory();
+        return AjaxResult.success(list);
+    }
 
-        /**
-         * 1. 获取技能列表 (对应图1、图3)
-         * 支持 Tab 切换:all(全部), active(已开通), applying(申请中), rejected(驳回)
-         */
-        @PostMapping("/getSkillList")
-        public TableDataInfo getSkillList (@RequestBody MaProjectGetVo req){
-            startPage();
-            List<MaProject> list = maTechnicianService.selectMaTechnicianListBy(req.getUserId(), req.getAuditStatus());
-            if (ObjectUtils.isEmpty(list)) {
-                List<Project> projectslist = maTechnicianService.selectTechnicianListBy(req.getTypeId());
-                return getDataTable(projectslist);
-            } else {
-                return getDataTable(list);
-            }
+    /**
+     * 1. 获取技能列表 (对应图1、图3)
+     * 支持 Tab 切换:all(全部), active(已开通), applying(申请中), rejected(驳回)
+     */
+    @PostMapping("/getSkillList")
+    public TableDataInfo getSkillList(@RequestBody MaProjectGetVo req) {
+        startPage();
+        List<MaProject> list = maTechnicianService.selectMaTechnicianListBy(req.getUserId(), req.getAuditStatus());
+        if (ObjectUtils.isEmpty(list)) {
+            List<Project> projectslist = maTechnicianService.selectTechnicianListBy(req.getTypeId());
+            return getDataTable(projectslist);
+        } else {
+            return getDataTable(list);
         }
+    }
 
-        /**
-         * 查询未开通的服务项目列表
-         *
-         * @param req
-         * @return
-         */
-        @PostMapping("/getNotApplyList")
-        public Result<?> getNotApplyList (@RequestBody MaProjectGetVo req){
+    /**
+     * 查询未开通的服务项目列表
+     *
+     * @param req
+     * @return
+     */
+    @PostMapping("/getNotApplyList")
+    public Result<?> getNotApplyList(@RequestBody MaProjectGetVo req) {
 
-            return Result.ok(maTechnicianService.getNotApplyList(req.getUserId(), req.getTypeId()));
+        return Result.ok(maTechnicianService.getNotApplyList(req.getUserId(), req.getTypeId()));
 
-        }
+    }
 
-        /**
-         * 申请开通新服务
-         */
-        @PostMapping("/applyForService")
-        public AjaxResult applyForService (@RequestBody MaProjectSaveDto dto){
+    /**
+     * 申请开通新服务
+     */
+    @PostMapping("/applyForService")
+    public AjaxResult applyForService(@RequestBody MaProjectSaveDto dto) {
+
+        return toAjax(maTechnicianService.applyForService(dto));
+    }
 
-            return toAjax(maTechnicianService.applyForService(dto));
+    /**
+     * 重新申请开通新服务
+     *
+     * @param req
+     * @return
+     */
+    @PostMapping("/updateApply")
+    public Result<?> updateApply(@RequestBody MaProjectUpdateDto req) {
+        if (StringUtils.isNotEmpty(req.getProjectId()) && StringUtils.isNotEmpty(req.getApplyReason())) {
+            LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(MaProject::getId, req.getProjectId());
+            updateWrapper.set(MaProject::getApplyReason, req.getApplyReason());
+            updateWrapper.set(MaProject::getAuditStatus, 0);
+            maProjectService.update(updateWrapper);
         }
+        return Result.ok("重新申请成功,提交到审核阶段");
 
-        /**
-         * 重新申请开通新服务
-         *
-         * @param req
-         * @return
-         */
-        @PostMapping("/updateApply")
-        public Result<?> updateApply (@RequestBody MaProjectUpdateDto req){
-            if (StringUtils.isNotEmpty(req.getProjectId()) && StringUtils.isNotEmpty(req.getApplyReason())) {
+    }
+
+    /**
+     * 申请下架,删除服务项目,编辑售价价格
+     *
+     * @param req
+     * @return
+     */
+    @PostMapping("/updateMaProject")
+    public Result<?> updateMaProject(@RequestBody MaProjectUpdateDto req) {
+        String message = "";
+        if (StringUtils.isNotEmpty(req.getProjectId())) {
+            if (req.getIsDelete()) {
+                LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
+                updateWrapper.eq(MaProject::getProjectId, req.getProjectId());
+                updateWrapper.set(MaProject::getIsDelete, 1);
+                maProjectService.update(updateWrapper);
+                message = "删除成功";
+            }
+            if (req.getIsPass()) {
                 LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
                 updateWrapper.eq(MaProject::getId, req.getProjectId());
-                updateWrapper.set(MaProject::getApplyReason, req.getApplyReason());
-                updateWrapper.set(MaProject::getAuditStatus, 0);
+                updateWrapper.set(MaProject::getProjectIsEnable, 1);
                 maProjectService.update(updateWrapper);
+                message = "申请下架成功";
             }
-            return Result.ok("重新申请成功,提交到审核阶段");
+            if (req.getProjectCurrentPrice() != null) {
 
-        }
+                LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
+                updateWrapper.eq(MaProject::getId, req.getProjectId());
+                updateWrapper.set(MaProject::getProjectCurrentPrice, req.getProjectCurrentPrice());
+                maProjectService.update(updateWrapper);
+                message = "修改价格完成";
 
-        /**
-         * 申请下架,删除服务项目,编辑售价价格
-         *
-         * @param req
-         * @return
-         */
-        @PostMapping("/updateMaProject")
-        public Result<?> updateMaProject (@RequestBody MaProjectUpdateDto req){
-            String message = "";
-            if (StringUtils.isNotEmpty(req.getProjectId())) {
-                if (req.getIsDelete()) {
-                    LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
-                    updateWrapper.eq(MaProject::getId, req.getProjectId());
-                    updateWrapper.set(MaProject::getIsDelete, 1);
-                    maProjectService.update(updateWrapper);
-                    message = "删除成功";
-                }
-                if (req.getIsPass()) {
-                    LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
-                    updateWrapper.eq(MaProject::getId, req.getProjectId());
-                    updateWrapper.set(MaProject::getProjectIsEnable, 1);
-                    maProjectService.update(updateWrapper);
-                    message = "申请下架成功";
-                }
-                if (req.getProjectCurrentPrice() != null) {
-
-                    LambdaUpdateWrapper<MaProject> updateWrapper = new LambdaUpdateWrapper<>();
-                    updateWrapper.eq(MaProject::getId, req.getProjectId());
-                    updateWrapper.set(MaProject::getProjectCurrentPrice, req.getProjectCurrentPrice());
-                    maProjectService.update(updateWrapper);
-                    message = "修改价格完成";
-
-                }
             }
-            return Result.ok(message);
-        }
-        /**
-         * 商户入住信息
-         *
-         * @param userId
-         * @return
-         */
-
-        @GetMapping("/getTechnicianList")
-        public Result<?> getTechnicianList (@RequestParam(value = "userId") Long userId){
-            return Result.ok(maTechnicianService.getTechnicianList(userId));
         }
+        return Result.ok(message);
+    }
 
+    /**
+     * 商户入住信息
+     *
+     * @param userId
+     * @return
+     */
+
+    @GetMapping("/getTechnicianList")
+    public Result<?> getTechnicianList(@RequestParam(value = "userId") Long userId) {
+        return Result.ok(maTechnicianService.getTechnicianList(userId));
     }
+
+}

+ 51 - 20
nightFragrance-massage/src/main/java/com/ylx/massage/domain/CityOperationApplication.java

@@ -6,6 +6,7 @@ import java.util.Date;
 import com.baomidou.mybatisplus.annotation.*;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.models.auth.In;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
@@ -21,36 +22,67 @@ import java.io.Serializable;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
-@TableName(value = "city_operation_application",autoResultMap = true)
-public class CityOperationApplication  implements Serializable {
-//主键ID
-@TableId(value = "id", type = IdType.AUTO)
+@TableName(value = "city_operation_application", autoResultMap = true)
+public class CityOperationApplication implements Serializable {
+    //主键ID
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
-//城市编码 (例如: 110000)
-@TableField("city_code")
+    /**
+     * 省级行政区编码 (如: 110000)
+     */
+    @TableField("province_code")
+    private String provinceCode;
+
+    /**
+     * 省级行政区名称 (如: 北京市)
+     */
+    @TableField("province_name")
+    private String provinceName;
+
+    /**
+     * 地级市编码 (如: 110100)
+     */
+    @TableField("city_code")
     private String cityCode;
-//城市名称 (冗余字段,方便查询,例如: 北京市)
-@TableField("city_name")
+
+    /**
+     * 地级市名称 (如: 北京市)
+     */
+    @TableField("city_name")
     private String cityName;
-//运营中心ID
-@TableField("operation_center_id")
-    private Long operationCenterId;
-//运营中心名称
-@TableField("operation_center_name")
+
+    /**
+     * 区/县编码 (如: 110101)
+     */
+    @TableField("district_code")
+    private String districtCode;
+
+    /**
+     * 区/县名称 (如: 东城区)
+     */
+    @TableField("district_name")
+    private String districtName;
+
+    //运营中心ID
+    @TableField("operation_center_id")
+    private Integer operationCenterId;
+    //运营中心名称
+    @TableField("operation_center_name")
     private String operationCenterName;
-//实际审批通过时间
-@TableField("actual_approval_time")
+    //实际审批通过时间
+    @TableField("actual_approval_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
     private Date actualApprovalTime;
-//申请原因 (限制500字以内)
+    //申请原因 (限制500字以内)
     @TableField("apply_reason")
     private String applyReason;
 
-//状态 (0:待审核, 1:已通过, 2:已驳回)
+    //状态 (0:待审核, 1:已通过, 2:已驳回)
     @TableField("status")
     private Integer status;
-//商户ID
+    //商户ID
     @TableField("merchant_id")
-    private String merchantId;
+    private Integer merchantId;
     /**
      * 创建时间
      */
@@ -83,6 +115,5 @@ public class CityOperationApplication  implements Serializable {
     private Integer isDelete;
 
 
-
 }
 

+ 18 - 5
nightFragrance-massage/src/main/java/com/ylx/massage/domain/MaProject.java

@@ -2,6 +2,8 @@ package com.ylx.massage.domain;
 
 import java.math.BigDecimal;
 
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import com.ylx.common.annotation.Excel;
@@ -17,7 +19,8 @@ import java.util.Date;
  */
 @ApiModel(value = "MaProject", description = "服务项目")
 @Data
-public class MaProject extends BaseEntity {
+@TableName("Ma_Project")
+public class MaProject {
     private static final long serialVersionUID = 1L;
 
     /**
@@ -30,7 +33,7 @@ public class MaProject extends BaseEntity {
      */
     @Excel(name = "项目ID")
     @ApiModelProperty("项目ID")
-    private String projectId;
+    private Long projectId;
     /**
      * 项目名称
      */
@@ -132,7 +135,7 @@ public class MaProject extends BaseEntity {
      */
     @Excel(name = "商户ID")
     @ApiModelProperty("商户ID")
-    private String merchantId;
+    private Long merchantId;
     /**
      * 审核状态:0-待审核,1-审核通过,2-审核驳回
      */
@@ -144,7 +147,7 @@ public class MaProject extends BaseEntity {
      */
     @Excel(name = "创建人")
     @ApiModelProperty("创建人")
-    private Long createUser;
+    private Long createBy;
     /** 申请时间 */
     @Excel(name = "申请时间")
     @ApiModelProperty("申请时间")
@@ -154,7 +157,7 @@ public class MaProject extends BaseEntity {
      */
     @Excel(name = "修改人")
     @ApiModelProperty("修改人")
-    private Long updateUser;
+    private Long updateBy;
 
     /**
      * 是否删除(0否1是)
@@ -162,6 +165,16 @@ public class MaProject extends BaseEntity {
     @ApiModelProperty("是否删除(0否1是)")
     @Excel(name = "是否删除(0否1是)")
     private Long isDelete;
+    /**
+     * 创建时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
 
 
 }

+ 1 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/MaProjectSaveDto.java

@@ -10,7 +10,7 @@ public class MaProjectSaveDto {
     /**
      * 商户id
      */
-    private String userId;
+    private Long userId;
     /**
      * 商户手机号
      */

+ 7 - 2
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/MaProjectUpdateDto.java

@@ -9,7 +9,10 @@ import java.util.List;
 
 @Data
 public class MaProjectUpdateDto {
-
+    /**
+     * 商家id
+     */
+    private Long merchantId;
     /**
      * 项目id列表
      */
@@ -26,6 +29,8 @@ public class MaProjectUpdateDto {
      * 是否删除
      */
     private Boolean isDelete;
-    /** 我的售价 */
+    /**
+     * 我的售价
+     */
     private BigDecimal projectCurrentPrice;
 }

+ 21 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/RefuseOrderReqDTO.java

@@ -0,0 +1,21 @@
+package com.ylx.massage.domain.dto;
+
+import lombok.Data;
+
+@Data
+public class RefuseOrderReqDTO {
+    /**
+     * 技师ID
+     */
+    private Long techId;
+
+    /**
+     * 订单ID
+     */
+    private Long orderId;
+
+    /**
+     * 拒单原因(必填)
+     */
+    private String refuseReason;
+}

+ 31 - 6
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/MaTechnicianAppAddVo.java

@@ -1,5 +1,6 @@
 package com.ylx.massage.domain.vo;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.ylx.common.annotation.Excel;
@@ -68,14 +69,38 @@ public class MaTechnicianAppAddVo {
     private String tePhone;
 
     /**
-     * 合作意向城市
+     * 省级行政区编码 (如: 110000)
      */
-    @Excel(name = "合作意向城市")
-    @ApiModelProperty("合作意向城市")
-    private String teAddress;
-    @ApiModelProperty("合作意向城市Code")
-    private String teAreaCode;
+    private String provinceCode;
 
+    /**
+     * 省级行政区名称 (如: 北京市)
+     */
+    private String provinceName;
+
+    /**
+     * 地级市编码 (如: 110100)
+     */
+    private String cityCode;
+
+    /**
+     * 地级市名称 (如: 北京市)
+     */
+    private String cityName;
+
+    /**
+     * 区/县编码 (如: 110101)
+     */
+    private String districtCode;
+
+    /**
+     * 区/县名称 (如: 东城区)
+     */
+    private String districtName;
+    //运营中心ID
+    private Integer operationCenterId;
+    //运营中心名称
+    private String operationCenterName;
     /**
      * 服务标签(1:按摩推拿 2:陪玩)
      */

+ 26 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/enums/OrderTipEnum.java

@@ -0,0 +1,26 @@
+package com.ylx.massage.enums;
+
+public enum OrderTipEnum {
+    // 1. 订单已被抢走 → 重复接单
+    REPEAT_ORDER("操作失败,请重试刷新当前页面"),
+
+    // 2. 时间冲突(你问的这个)
+    TIME_CONFLICT("当前订单服务开始时间与已有订单时间冲突,不支持接待"),
+
+    // 3. 技师休息中,确认接单
+    REST_CONFIRM("您当前处于休息中,接单后将切换为上线状态,是否确认接单"),
+
+    // 4. 接单成功
+    ALREADY_ACCEPT("已接单");
+
+    // 提示文案
+    private final String tip;
+
+    OrderTipEnum(String tip) {
+        this.tip = tip;
+    }
+
+    public String getTip() {
+        return tip;
+    }
+}

+ 23 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/service/IMaTechnicianService.java

@@ -86,7 +86,7 @@ public interface IMaTechnicianService extends IService<MaTechnician> {
      * @param loginUser 当前登录用户
      * @return 上传结果
      */
-    Integer uploadMerchantContract(Integer id, Map<String,Object> file, LoginUser loginUser);
+    Integer uploadMerchantContract(Integer id, Map<String, Object> file, LoginUser loginUser);
 
     /**
      * 后台查询商户入驻审核列表
@@ -206,6 +206,28 @@ public interface IMaTechnicianService extends IService<MaTechnician> {
      */
     List<WaitOrderDTO> listWaitOrder(WaitOrderQueryDTO query);
 
+    /**
+     * 接单
+     *
+     * @param req
+     * @return
+     */
+    String acceptOrder(AcceptOrderReqDTO req);
+    /**
+     * 技师接单确认接单
+     *
+     * @param techId
+     * @param orderId
+     * @return
+     */
+    String confirmRestAccept(Long techId, Long orderId);
+    /**
+     * 技师拒绝接单
+     *
+     * @param req
+     * @return
+     */
+    void refuseOrder(RefuseOrderReqDTO req);
     /**
      * 技师列表
      *

+ 3 - 3
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/MaProjectServiceImpl.java

@@ -87,13 +87,13 @@ public class MaProjectServiceImpl extends ServiceImpl<MaProjectMapper, MaProject
 
         if (maProjectVo.getId() == null) {
             // 新增
-            maProject.setCreateUser(loginUser.getUser().getUserId());
-            maProject.setUpdateUser(loginUser.getUser().getUserId());
+            maProject.setCreateBy(loginUser.getUser().getUserId());
+            maProject.setUpdateBy(loginUser.getUser().getUserId());
             maProject.setCreateTime(DateUtils.getNowDate());
             return maProjectMapper.insertMaProject(maProject);
         } else {
             // 修改
-            maProject.setUpdateUser(loginUser.getUser().getUserId());
+            maProject.setUpdateBy(loginUser.getUser().getUserId());
             return maProjectMapper.updateMaProject(maProject);
         }
 

+ 133 - 35
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/MaTechnicianServiceImpl.java

@@ -6,6 +6,7 @@ import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -26,6 +27,7 @@ import com.ylx.massage.controller.CityOperationApplicationController;
 import com.ylx.massage.domain.*;
 import com.ylx.massage.domain.dto.*;
 import com.ylx.massage.domain.vo.*;
+import com.ylx.massage.enums.OrderTipEnum;
 import com.ylx.massage.enums.ProjectCategoryEnum;
 import com.ylx.massage.enums.TechnicianStatusEnum;
 import com.ylx.massage.mapper.*;
@@ -116,7 +118,8 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
     private MerchantApplyFileMapper merchantApplyFileMapper;
     @Resource
     private TOrderMapper orderMapper;
-
+    @Resource
+    private  CityOperationApplicationMapper cityOperationApplicationMapper;
 
 
     /**
@@ -143,11 +146,24 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
         queryWrapper.eq(MaTechnician::getCOpenid, req.getCOpenid());
         MaTechnician maTechnician1 = maTechnicianMapper.selectOne(queryWrapper);
         if (maTechnician1 == null) {
-           throw new RuntimeException("商户不存在");
+            throw new RuntimeException("商户不存在");
         }
         LambdaUpdateWrapper<MaTechnician> updateWrapper = new LambdaUpdateWrapper<>();
         updateWrapper.eq(MaTechnician::getId, maTechnician1.getId());
         maTechnicianMapper.update(maTechnician, updateWrapper);
+        CityOperationApplication cityOperationApplication = new CityOperationApplication();
+        cityOperationApplication.setMerchantId(maTechnician1.getId());
+        cityOperationApplication.setOperationCenterId(req.getOperationCenterId());
+        cityOperationApplication.setProvinceCode(req.getProvinceCode());
+        cityOperationApplication.setProvinceName(req.getProvinceName());
+        cityOperationApplication.setCityCode(req.getCityCode());
+        cityOperationApplication.setCityName(req.getCityName());
+        cityOperationApplication.setDistrictCode(req.getDistrictCode());
+        cityOperationApplication.setDistrictName(req.getDistrictName());
+        cityOperationApplication.setOperationCenterName(req.getOperationCenterName());
+        cityOperationApplication.setCreateBy(maTechnician1.getId().toString());
+        cityOperationApplication.setUpdateBy(maTechnician1.getId().toString());
+        cityOperationApplicationMapper.insert(cityOperationApplication);
 
     }
 
@@ -394,13 +410,13 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
      * 后台上传商户合同文件
      *
      * @param id        商户ID
-     * @param file      合同文件
+     * @param
      * @param loginUser 当前登录用户
      * @return 上传结果
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Integer uploadMerchantContract(Integer id, Map<String,Object> map, LoginUser loginUser) {
+    public Integer uploadMerchantContract(Integer id, Map<String, Object> map, LoginUser loginUser) {
         if (id == null) {
             throw new ServiceException("商户ID不能为空");
         }
@@ -848,11 +864,16 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
         query.eq(MaProject::getMerchantType, typeId);
         List<MaProject> maProjectList = maProjectMapper.selectList(query);
         // 获取已申请技能ID集合
-        List<String> projectIdList = maProjectList.stream().map(MaProject::getProjectId).collect(Collectors.toList());
-        LambdaQueryWrapper<Project> query1 = new LambdaQueryWrapper<>();
-        query1.eq(Project::getType, typeId);
-        query1.notIn(Project::getId, projectIdList);
-        return projectMapper.selectList(query1);
+        List<Long> projectIdList = maProjectList.stream().map(MaProject::getProjectId).collect(Collectors.toList());
+        if (projectIdList.size() == 0) {
+            LambdaQueryWrapper<Project> query1 = new LambdaQueryWrapper<>();
+            query1.eq(Project::getType, typeId);
+            return projectMapper.selectList(query1);
+        }
+        LambdaQueryWrapper<Project> query2 = new LambdaQueryWrapper<>();
+        query2.eq(Project::getType, typeId);
+        query2.notIn(Project::getId, projectIdList);
+        return projectMapper.selectList(query2);
     }
 
     /**
@@ -901,7 +922,7 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
         List<Project> projectList = projectMapper.selectList(query);
         for (Project project : projectList) {
             MaProject maProject = new MaProject();
-            maProject.setProjectId(project.getId().toString());
+            maProject.setProjectId(project.getId().longValue());
             maProject.setProjectName(project.getTitle());
             maProject.setProjectDescribe(project.getDetail());
             maProject.setProjectDuration(project.getStandardDuration());
@@ -909,10 +930,10 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
             maProject.setProjectMaxPrice(project.getPriceMax());
             maProject.setProjectLowestPrice(project.getPriceMin());
             maProject.setCreateBy(dto.getUserId());
+            maProject.setUpdateBy(dto.getUserId());
             maProject.setMerchantId(dto.getUserId());
             maProject.setApplyTime(DateUtils.getNowDate());
             maProject.setMerchantPhone(dto.getMerchantPhone());
-            maProject.setCreateTime(DateUtils.getNowDate());
             maProjectMapper.insert(maProject);
         }
     }
@@ -1210,7 +1231,7 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
         queryWrapper.eq(TOrder::getStatus, OrderStatusEnum.WAIT_JD.getCode());
         // 1.查询所有待派未接单订单(status=待接单)
         List<TOrder> allWaitOrder = orderMapper.selectList(queryWrapper);
-        if(CollectionUtils.isEmpty(allWaitOrder)){
+        if (CollectionUtils.isEmpty(allWaitOrder)) {
             return Collections.emptyList();
         }
 
@@ -1241,9 +1262,82 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
                        .sorted(Comparator.comparing(WaitOrderDTO::getDistanceMeter))
                        .collect(Collectors.toList());
     }
+
+    /**
+     * 接单
+     *
+     * @param req
+     * @return
+     */
+    @Override
+    public String acceptOrder(AcceptOrderReqDTO req) {
+        Long techId = req.getTechId();
+        Long orderId = req.getOrderId();
+        //【校验1:订单是否已被其他技师接单】
+        TOrder order = orderMapper.selectById(orderId);
+        if (OrderStatusEnum.RECEIVED_ORDER.getCode().equals(order.getStatus())) {
+            return OrderTipEnum.REPEAT_ORDER.getTip();
+        }
+        //【校验2:时间冲突校验(该技师已有已接单订单)】
+        boolean isTimeConflict = checkOrderTimeConflict(techId, order);
+        if (isTimeConflict) {
+            String tip = String.format(OrderTipEnum.TIME_CONFLICT.getTip(),
+                    order.getStartTime().format(DateTimeFormatter.ofPattern("MM月dd日HH:mm")),
+                    order.getCompletedTime().format(DateTimeFormatter.ofPattern("MM月dd日HH:mm")));
+            return tip;
+        }
+        //【校验3:技师休息状态】
+        MaTechnician tech = maTechnicianMapper.selectById(techId);
+        if (TechnicianStatusEnum.RESTING.getCode().equals(tech.getPostState())) {
+            return OrderTipEnum.REST_CONFIRM.getTip();
+        }
+        // 正常接单,绑定技师ID到订单
+        doAcceptOrder(techId, orderId);
+        return OrderTipEnum.ALREADY_ACCEPT.getTip();
+    }
+    /**
+     * 技师接单确认接单
+     *
+     * @param techId
+     * @param orderId
+     * @return
+     */
+    @Override
+    public String confirmRestAccept(Long techId, Long orderId){
+        LambdaUpdateWrapper<MaTechnician> update = new LambdaUpdateWrapper<>();
+        update.eq(MaTechnician::getId, techId);
+        update.set(MaTechnician::getPostState, TechnicianStatusEnum.ONLINE.getCode());
+        maTechnicianMapper.update(null, update);
+        doAcceptOrder(techId, orderId);
+        return OrderTipEnum.ALREADY_ACCEPT.getTip();
+    }
+    /**
+     * 技师拒绝接单
+     *
+     * @param req
+     * @return
+     */
+    @Override
+    public void refuseOrder(RefuseOrderReqDTO req){
+        LambdaUpdateWrapper<TOrder> update = new LambdaUpdateWrapper<>();
+        update.eq(TOrder::getId, req.getOrderId());
+        update.set(TOrder::getStatus, OrderStatusEnum.REFUSE.getCode());
+        update.set(TOrder::getRejectedReason, req.getRefuseReason());
+        orderMapper.update(null, update);
+        //拒单后订单重回待接单池,其他技师可刷到
+        LambdaUpdateWrapper<TOrder> update2 = new LambdaUpdateWrapper<>();
+        update2.eq(TOrder::getId, req.getOrderId());
+        update2.set(TOrder::getStatus, OrderStatusEnum.WAIT_JD.getCode());
+        update2.set(TOrder::getMerchantId, "");
+        update2.set(TOrder::getRejectedReason, "");
+        orderMapper.update(null, update2);
+    }
     // =================工具方法=================
-    /** Haversine 计算经纬度距离 返回米 */
-    private BigDecimal calcDistance(BigDecimal lat1, BigDecimal lng1, BigDecimal lat2, BigDecimal lng2){
+
+    /**
+     * Haversine 计算经纬度距离 返回米
+     */
+    private BigDecimal calcDistance(BigDecimal lat1, BigDecimal lng1, BigDecimal lat2, BigDecimal lng2) {
         // 球面距离计算公式,地球半径6371000米
         // 可使用BigDecimal三角函数或数据库函数优化
         double latRad1 = Math.toRadians(lat1.doubleValue());
@@ -1253,31 +1347,33 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
 
         double dLat = latRad2 - latRad1;
         double dLng = lngRad2 - lngRad1;
-        double a = Math.pow(Math.sin(dLat/2),2)
-                           + Math.cos(latRad1)*Math.cos(latRad2)
-                                     * Math.pow(Math.sin(dLng/2),2);
-        double dis = 2 * 6371000 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
-        return BigDecimal.valueOf(dis).setScale(2,BigDecimal.ROUND_HALF_UP);
+        double a = Math.pow(Math.sin(dLat / 2), 2)
+                           + Math.cos(latRad1) * Math.cos(latRad2)
+                                     * Math.pow(Math.sin(dLng / 2), 2);
+        double dis = 2 * 6371000 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+        return BigDecimal.valueOf(dis).setScale(2, BigDecimal.ROUND_HALF_UP);
     }
 
-    private String getShortProjectName(String name){
-        if(name != null && name.length()>10){
-            return name.substring(0,8)+"...";
+    private String getShortProjectName(String name) {
+        if (name != null && name.length() > 10) {
+            return name.substring(0, 8) + "...";
         }
         return name;
     }
 
-    private String formatDistance(BigDecimal distanceMeter){
-        BigDecimal km = distanceMeter.divide(new BigDecimal(1000),2,BigDecimal.ROUND_HALF_UP);
-        if(km.compareTo(BigDecimal.ONE)>0){
-            return km+"km";
-        }else{
-            return distanceMeter.intValue()+"m";
+    private String formatDistance(BigDecimal distanceMeter) {
+        BigDecimal km = distanceMeter.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP);
+        if (km.compareTo(BigDecimal.ONE) > 0) {
+            return km + "km";
+        } else {
+            return distanceMeter.intValue() + "m";
         }
     }
 
-    /** 校验技师已有订单时间冲突(只查该技师已接单数据) */
-    private boolean checkOrderTimeConflict(Long techId, TOrder newOrder){
+    /**
+     * 校验技师已有订单时间冲突(只查该技师已接单数据)
+     */
+    private boolean checkOrderTimeConflict(Long techId, TOrder newOrder) {
         LambdaQueryWrapper<TOrder> query = new LambdaQueryWrapper<>();
         query.eq(TOrder::getMerchantId, techId);
         query.eq(TOrder::getStatus, OrderStatusEnum.RECEIVED_ORDER.getCode());
@@ -1286,20 +1382,22 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
         List<TOrder> acceptedOrders = orderMapper.selectList(query);
         LocalDate newOrderDate = newOrder.getStartTime().toLocalDate();
         LocalDateTime newStart = newOrder.getStartTime();
-        for(TOrder old:acceptedOrders){
-            if(!newOrderDate.isEqual(old.getCompletedTime().toLocalDate())){
+        for (TOrder old : acceptedOrders) {
+            if (!newOrderDate.isEqual(old.getCompletedTime().toLocalDate())) {
                 continue;
             }
             LocalDateTime oldEnd = old.getCompletedTime();
-            if(newStart.isBefore(oldEnd) || newStart.isEqual(oldEnd)){
+            if (newStart.isBefore(oldEnd) || newStart.isEqual(oldEnd)) {
                 return true;
             }
         }
         return false;
     }
 
-    /** 接单:给订单赋值技师ID */
-    private void doAcceptOrder(Long techId, Long orderId){
+    /**
+     * 接单:给订单赋值技师ID
+     */
+    private void doAcceptOrder(Long techId, Long orderId) {
         TOrder update = new TOrder();
         update.setId(orderId);
         update.setMerchantId(techId);