同一个系统登录还能双向选择 家政系统这么开发太香了!
项目整体架构设计思路做上门家政服务最怕的就是用户和服务者分开在两个系统来回跳体验感太差。我们可以基于前后端分离的方案用同一个域名下的不同路由区分用户端和服务端再通过JWT令牌做身份鉴别就能实现两端在同一个系统登录还能完全隔离不同身份的操作权限。核心就是在用户登录的时候根据传入的身份标识给不同的用户发放对应权限的令牌后续每个接口都会校验身份保证用户只能进用户端服务者只能进服务者后台完全不会串权限。核心登录模块代码实现先给大家放后端基于SpringBoot的核心登录接口代码已经把身份校验和令牌发放的逻辑写清楚了直接就能拿去改一改用import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.Date; import java.util.HashMap; import java.util.Map; RestController public class LoginController { // 密钥自己配置就行不要硬写在代码里这里是示例 private static final String SECRET_KEY jiazheng_service_custom_secret_key_2024; // 令牌过期时间这里设7天 private static final long EXPIRATION 1000 * 60 * 60 * 24 * 7; PostMapping(/api/system/login) public MapString, Object commonLogin(RequestBody LoginRequest loginRequest) { MapString, Object result new HashMap(); // 根据账号密码查询数据库验证身份 UserInfo user userService.checkUser(loginRequest.getAccount(), loginRequest.getPassword()); if(user null) { result.put(code, 400); result.put(msg, 账号或密码错误); return result; } // 生成token把身份类型存入令牌中后续用来区分用户还是服务者 MapString, Object claims new HashMap(); claims.put(userId, user.getId()); claims.put(role, user.getRole()); // role只有两种值user和provider claims.put(account, user.getAccount()); String token Jwts.builder() .setClaims(claims) .setExpiration(new Date(System.currentTimeMillis() EXPIRATION)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); result.put(code, 200); result.put(msg, 登录成功); result.put(token, token); result.put(role, user.getRole()); return result; } } // 登录请求实体类 class LoginRequest { private String account; private String password; private String getAccount() {return account;} public void setAccount(String account) {this.account account;} public String getPassword() {return password;} public void setPassword(String password) {this.password password;} } // 用户信息实体类 class UserInfo { private Long id; private String account; private String role; // 省略getter setter }前端这边我们用Vue做路由拦截登录拿到role之后自动跳转到对应的端页面不管是用户还是服务者都是从同一个登录页进去完全不用分开记网址体验感一下子就上来了。前端路由拦截核心代码如下router.beforeEach((to, from, next) { const token localStorage.getItem(jiazheng_token) const role localStorage.getItem(user_role) // 需要登录的页面判断 if (to.meta.requireAuth) { if (token) { // 如果是用户要去服务者页面直接拦回去 if (to.meta.role to.meta.role ! role) { if (role user) { next(/user/home) } else { next(/provider/order) } return } next() } else { next(/login) } } else { next() } })双向匹配的逻辑怎么实现用户发需求服务者抢单还是用户选服务者当然是双向都能选才最符合上门家政的场景。用户下单之后会把订单推送给对应服务类型、对应区域内的所有服务者服务者可以查看订单的地址、服务时间、用户评价选择是否接单。同时用户也可以在接单列表里看到所有接了单的服务者的资料、历史评分、过往订单的用户评价挑自己喜欢的服务者。双向选择的核心订单匹配接口代码给大家整理出来了PostMapping(/api/order/publish) public MapString, Object publishOrder(RequestBody PublishOrderRequest request, HttpServletRequest httpRequest) { // 从token拿到当前登录用户的身份肯定是用户才能发单 UserInfo currentUser TokenUtil.getCurrentUser(httpRequest); if(!currentUser.getRole().equals(user)) { Map result new HashMap(); result.put(code, 403); result.put(msg, 只有用户可以发布订单); return result; } // 保存订单信息状态设为待匹配 Order newOrder new Order(); newOrder.setUserId(currentUser.getId()); newOrder.setServiceType(request.getServiceType()); newOrder.setAddress(request.getAddress()); newOrder.setServiceTime(request.getServiceTime()); newOrder.setStatus(wait_match); orderService.save(newOrder); // 查询该区域该服务类型的所有在线服务者推送订单消息 ListProviderInfo onlineProviders providerService .findOnlineProviderByRegionAndType(request.getCity(), request.getServiceType()); for(ProviderInfo provider : onlineProviders) { messageService.pushOrderNotification(provider.getId(), newOrder.getId()); } MapString, Object result new HashMap(); result.put(code, 200); result.put(msg, 订单发布成功等待服务者接单); result.put(orderId, newOrder.getId()); return result; } // 服务者接单接口 PostMapping(/api/order/receive) public MapString, Object receiveOrder(RequestBody ReceiveOrderRequest request, HttpServletRequest httpRequest) { ProviderInfo currentProvider TokenUtil.getCurrentProvider(httpRequest); Order order orderService.getById(request.getOrderId()); if(!order.getStatus().equals(wait_match)) { Map result new HashMap(); result.put(code, 400); result.put(msg, 订单已经被接走啦); return result; } // 把接单的服务者存入接单列表 OrderReceive record new OrderReceive(); record.setOrderId(order.getId()); record.setProviderId(currentProvider.getId()); record.setCreateTime(new Date()); orderReceiveService.save(record); // 给用户推送消息告诉用户有新的服务者接单了 messageService.pushReceiveNotification(order.getUserId(), currentProvider); Map result new HashMap(); result.put(code, 200); result.put(msg, 接单成功等待用户确认); return result; } // 用户选择服务者确认订单接口 PostMapping(/api/order/confirm) public MapString, Object confirmProvider(RequestBody ConfirmRequest request, HttpServletRequest httpRequest) { Order order orderService.getById(request.getOrderId()); if(!order.getStatus().equals(wait_match)) { Map result new HashMap(); result.put(code, 400); result.put(msg, 订单已经确认过了); return result; } // 更新订单状态绑定最终服务者 order.setStatus(confirmed); order.setProviderId(request.getProviderId()); orderService.updateById(order); // 给选中的服务者发通知给其他接单的服务者发通知说订单已被选走 messageService.pushConfirmedNotification(request.getProviderId(), order); messageService.pushCancelNotification(order.getId(), request.getProviderId()); Map result new HashMap(); result.put(code, 200); result.put(msg, 订单确认成功等待服务者上门); return result; }细节优化才是体验感的关键很多家政系统做了双向选择但是体验不好就是细节没跟上。比如服务者可以设置自己的工作时段和服务区域系统就不会把非工作时间、不在服务范围内的订单推给他避免打扰也能提高匹配效率。用户还能直接根据服务价格、评分、接单时长筛选服务者不用一个个翻挑起来特别快。如果用户懒得选也可以开自动匹配系统直接把订单派给评分最高、顺路的服务者由服务者确认之后就直接成交一样能走通。对于服务者来说不仅能挑订单还能看到用户之前给其他服务者的评价碰到差评多、爽约多的用户也可以选择不接保护自己的权益这才是真正的双向选择不是只偏向某一方。整个系统开发下来同一个登录入口两端权限隔离双向选单的逻辑走通不管是用户找阿姨还是服务者接订单体验都会顺畅很多比分开做两个app、两个系统的成本低很多用户也不用下载两个东西推广起来也更容易。