package com.ylx.web.controller.massage; import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.hutool.json.JSONObject; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ylx.common.core.domain.R; import com.ylx.common.core.domain.model.LoginUser; 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; import com.ylx.common.utils.StringUtils; import com.ylx.massage.domain.MaProject; import com.ylx.massage.domain.dto.*; import com.ylx.massage.domain.dto.MaProjectSaveDto; import com.ylx.massage.domain.dto.MaProjectUpdateDto; import com.ylx.massage.domain.dto.MaTechnicianAuditQueryDTO; import com.ylx.massage.domain.dto.MaTechnicianAuditSubmitDTO; import com.ylx.massage.domain.dto.MaTechnicianMerchantAddDTO; import com.ylx.massage.domain.dto.MaTechnicianMerchantQueryDTO; import com.ylx.massage.domain.vo.*; import com.ylx.massage.service.IMaProjectService; import com.ylx.project.domain.Project; import com.ylx.servicecategory.domain.ServiceCategory; import com.ylx.servicecategory.service.ServiceCategoryService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; import com.ylx.common.annotation.Log; import com.ylx.common.core.controller.BaseController; import com.ylx.common.core.domain.AjaxResult; import com.ylx.common.enums.BusinessType; import com.ylx.massage.domain.MaTechnician; import com.ylx.massage.service.IMaTechnicianService; import com.ylx.common.utils.poi.ExcelUtil; import com.ylx.common.core.page.TableDataInfo; import org.springframework.web.multipart.MultipartFile; /** * 技师Controller * * @author ylx * @date 2024-03-22 */ @Api("技师管理") @RestController @RequestMapping("/technician/technician") public class MaTechnicianController extends BaseController { @Autowired private IMaTechnicianService maTechnicianService; @Autowired private StringRedisTemplate redisTemplate; @Autowired private SendSmsComponents sendSms; @Autowired private ServiceCategoryService serviceCategoryService; @Autowired private IMaProjectService maProjectService; public static final String PHONE_THREEUSERPARTCLIENT_CODE_KEY = "sys:threeUserPartClient:phone:"; @GetMapping("/sendMsg") @ApiOperation(value = "短信发送", notes = "短信发送") public Result sendMsg(@RequestParam String phone, HttpServletRequest request) { if (org.apache.commons.lang3.StringUtils.isEmpty(phone)) { return Result.error("手机号不能为空"); } Random rand = new Random(); // randNumber 将被赋值为一个 MIN 和 MAX 范围内的随机数 int randNumber = rand.nextInt(9999 - 1000 + 1) + 1000; // 保存验证码到redis redisTemplate.opsForValue() .set("userH5:order:phone:" + phone, String.valueOf(randNumber), 5L , TimeUnit.MINUTES); try { SMSVerificationCode smsVerificationCode = new SMSVerificationCode(String.valueOf(randNumber)); String jsonString = JSON.toJSONString(smsVerificationCode); sendSms.sendSms(phone, SendSmsEnum.SMS_220650024, jsonString); return Result.ok("发送成功"); } catch (Exception e) { e.printStackTrace(); } return Result.ok("发送失败"); } /** * 商户登录接口 * * @param thirdPartyLoginsVo * @return */ @ApiOperation(value = "商户登录", notes = "商户登录") @PostMapping(value = "/clientLogin") @Transactional public Result login(@RequestBody ThirdPartyLoginsVo thirdPartyLoginsVo) throws Exception { // 获取登录用户信息 Result result = new Result<>(); // 校验手机号是否为空 if (StringUtils.isEmpty(thirdPartyLoginsVo.getPhone())) { return result.error500("请输入手机号"); } // 校验用户是否存在且有效 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MaTechnician::getTePhone, thirdPartyLoginsVo.getPhone()); MaTechnician maTechnician = maTechnicianService.getBaseMapper().selectOne(queryWrapper); // 校验用户是否有效 if (ObjectUtils.isEmpty(maTechnician)) { return result.error500("商户不存在,请先注册"); } if (thirdPartyLoginsVo.getCodeSwitch()) { // 短信验证 String msg = redisTemplate.opsForValue().get(PHONE_THREEUSERPARTCLIENT_CODE_KEY + thirdPartyLoginsVo.getPhone()); if (StringUtils.isEmpty(msg)) { return Result.error("验证码已失效"); } if (!thirdPartyLoginsVo.getPhoneMsg().equals(msg)) { return Result.error("短信验证码不正确"); } } else { if (!thirdPartyLoginsVo.getPassWord().equals(maTechnician.getTePassword())) { 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.getPhoneMsg()); 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 (!thirdPartyLoginsVo.getPhoneMsg().equals(msg)) { return Result.error("短信验证码不正确"); } // 重置密码逻辑 LambdaUpdateWrapper 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("/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("性别不能为空"); } // 2. 调用业务层处理入驻申请 maTechnicianService.apply(req); return Result.ok("提交成功,进入审核流程"); } /** * 申请技师文件 * @param req */ @PostMapping("/applyFile") public Result applyFile(MerchantApplyFileDto req){ maTechnicianService.applyFile(req); return Result.ok("上传成功"); } /** * 技师状态切换 * * @param */ @GetMapping("/switchToOffline") public Result switchToOffline(@RequestParam Long userId, @RequestParam Boolean forceConfirm){ return maTechnicianService.switchToOffline(userId, forceConfirm); } /** * 查询商户信息接口 */ @GetMapping("/getTechnician") public Result getTechnician(@RequestParam String phone) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MaTechnician::getTePhone, phone); 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("修改成功"); } private void updateMaTechnician(MaTechnicianAppAddVo req) { LambdaUpdateWrapper 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.getOpenService()); updateWrapper.set(MaTechnician::getTeAddress, req.getTeAddress()); updateWrapper.set(MaTechnician::getTeAge, req.getTeAge()); updateWrapper.set(MaTechnician::getAvatar, req.getAvatar()); maTechnicianService.update(updateWrapper); } /** * 查询技师列表 */ @PreAuthorize("@ss.hasPermi('technician:technician:list')") @GetMapping("/list") public TableDataInfo list(MaTechnician maTechnician) { startPage(); List 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 list = maTechnicianService.selectMaTechnicianList(maTechnician); ExcelUtil util = new ExcelUtil(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 file 合同文件 * @return AjaxResult 上传结果 */ @ApiOperation("后台上传商户合同文件") @PreAuthorize("@ss.hasPermi('technician:technician:edit')") @Log(title = "商户合同", businessType = BusinessType.UPDATE) @PostMapping("/merchant/{id}/contract") public AjaxResult uploadMerchantContract(@PathVariable("id") Integer id, @RequestParam("file") MultipartFile file) { try { LoginUser loginUser = getLoginUser(); return maTechnicianService.uploadMerchantContract(id, file, loginUser); } 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> merchantAuditList(Page 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 page 分页参数 * @param dto 商户查询DTO * @return Page 商户分页列表 */ @ApiOperation("后台查询商户列表") @PreAuthorize("@ss.hasPermi('technician:technician:list')") @GetMapping("/merchant/list") public R> merchantList(Page 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 商户详情 */ @ApiOperation("后台查询商户详情") @PreAuthorize("@ss.hasPermi('technician:technician:query')") @GetMapping("/merchant/detail/{id}") public R 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 商户证照 */ @ApiOperation("后台查看商户证照") @PreAuthorize("@ss.hasPermi('technician:technician:query')") @GetMapping("/merchant/{id}/certificate") public R 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: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 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 list = maTechnicianService.selectMaTechnicianListBy(req.getUserId(), req.getAuditStatus()); if (ObjectUtils.isEmpty(list)) { List projectslist = maTechnicianService.selectTechnicianListBy(req.getTypeId()); return getDataTable(projectslist); } else { return getDataTable(list); } } /** * 查询未开通的服务项目列表 * * @param req * @return */ @PostMapping("/getNotApplyList") public Result getNotApplyList(@RequestBody MaProjectGetVo req) { return Result.ok(maTechnicianService.getNotApplyList(req.getUserId(), req.getTypeId())); } /** * 申请开通新服务 */ @PostMapping("/applyForService") public AjaxResult applyForService(@RequestBody MaProjectSaveDto 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 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("/updateMaProject") public Result updateMaProject(@RequestBody MaProjectUpdateDto req) { String message = ""; if (StringUtils.isNotEmpty(req.getProjectId())) { if (req.getIsDelete()) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(MaProject::getId, req.getProjectId()); updateWrapper.set(MaProject::getIsDelete, 1); maProjectService.update(updateWrapper); message = "删除成功"; } if (req.getIsPass()) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(MaProject::getId, req.getProjectId()); updateWrapper.set(MaProject::getProjectIsEnable, 1); maProjectService.update(updateWrapper); message = "申请下架成功"; } if (req.getProjectCurrentPrice() != null) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(MaProject::getId, req.getProjectId()); updateWrapper.set(MaProject::getProjectCurrentPrice, req.getProjectCurrentPrice()); maProjectService.update(updateWrapper); message = "修改价格完成"; } } return Result.ok(message); } }