2025008071805

This commit is contained in:
张潘 2025-08-18 18:23:53 +08:00
parent b2bea149f3
commit 15d561646b
15 changed files with 3650 additions and 1032 deletions

View File

@ -2779,7 +2779,7 @@ public class AppleOrderController extends BaseController {
JSONObject user = new JSONObject();
user.put("id", u.getId());
user.put("name", u.getName());
user.put("avatar", u.getAvatar());
user.put("avatar", AppletControllerUtil.buildImageUrl(u.getAvatar()));
comment.put("user", user);
}
result.put("comment", comment);
@ -4126,6 +4126,38 @@ public class AppleOrderController extends BaseController {
}
}
/**
* 小程序通过code换取手机号
* POST /api/user/phone
* 参数示例{"code":"xxxxxx"}
*/
@PostMapping(value = "/api/user/phone")
public AjaxResult getUserPhoneByCode(@RequestBody Map<String, Object> params) {
try {
if (params == null || params.get("code") == null) {
return AppletControllerUtil.appletError("code不能为空");
}
String code = String.valueOf(params.get("code")).trim();
if (code.isEmpty()) {
return AppletControllerUtil.appletError("code不能为空");
}
Map<String, Object> result = WechatApiUtil.getPhoneNumberByCode(code);
if (Boolean.TRUE.equals(result.get("success"))) {
// 返回微信接口中的 phone_info 节点
Object phoneInfo = result.get("phone_info");
return AppletControllerUtil.appletSuccess(phoneInfo != null ? phoneInfo : result);
} else {
String msg = result != null && result.get("errorMsg") != null ? String.valueOf(result.get("errorMsg")) : "获取手机号失败";
return AppletControllerUtil.appletError(msg);
}
} catch (Exception e) {
return AppletControllerUtil.appletError("获取手机号失败:" + e.getMessage());
}
}
@PostMapping("/api/workerdata/index")
public AjaxResult workerdataIndex(@RequestBody Map<String, Object> params, HttpServletRequest request) {
try {
@ -6101,6 +6133,62 @@ public class AppleOrderController extends BaseController {
return null;
}
@PostMapping(value = "/api/user/address/del")
public AjaxResult apiuseraddressdel(@RequestBody Map<String, Object> params, HttpServletRequest request) {
Long id = Long.parseLong(params.get("id").toString());
int result = userAddressService.deleteUserAddressById(id);
return AppletControllerUtil.appletSuccess("操作成功");
}
@PostMapping(value = "/api/coupon/add")
public AjaxResult apicouponadd(@RequestBody Map<String, Object> params, HttpServletRequest request) {
Long id = Long.parseLong(params.get("coupon_id").toString());
// 获取token
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
return AjaxResult.error("token不能为空");
}
// 验证用户token
Map<String, Object> userInfo = AppletLoginUtil.validateUserToken(token, usersService);
if (userInfo == null) {
return AjaxResult.error("token验证失败");
}
Users user = (Users) userInfo.get("user");
Coupons coupon = couponsService.selectCouponsById( id);
// CouponUser couponUser = couponUserService.selectCouponUserById(id);
if (coupon == null) {
AppletControllerUtil.appletWarning("优惠券不存在");
}
CouponUser couponUser = new CouponUser();
couponUser.setUid(user.getId());
couponUser.setCouponId(coupon.getId());
couponUser.setCouponTitle(coupon.getTitle());
couponUser.setCouponPrice(coupon.getPrice().intValue());
couponUser.setMinPrice(coupon.getMinPrice().longValue());
couponUser.setAddTime(new Date().getTime()/1000);
couponUser.setLoseTime(String.valueOf(coupon.getEndTime()));
couponUser.setCateId(coupon.getCateId());
couponUser.setProductId(coupon.getProductId());
couponUser.setReceiveType(String.valueOf(coupon.getReceiveType()));
couponUser.setStatus(1L);
couponUserService.insertCouponUser(couponUser);
return AppletControllerUtil.appletSuccess("操作成功");
}
/**
* 服务/商品搜索接口
*

View File

@ -1289,7 +1289,8 @@ public class ApplePayController extends BaseController {
//先微信支付微信支付成功之后再回调中把剩余的进行余额支付
payResult = wechatPayUtil.createBatchOrderAndPay(
user.getOpenid(),
payBefor.getPaycode(),
payBefor.getOrderid(),
// payBefor.getPaycode(),
new BigDecimal("0.01"),
1,
WechatPayUtil.PAY_FH + "api/order/amount/paydata/zuhenotify"

View File

@ -2016,8 +2016,9 @@ public class AppletController extends BaseController {
return AppletControllerUtil.appletSuccess(AppletControllerUtil.buildCouponUserList(couponUserDataList,serviceCateService,serviceGoodsService,productId,totalPrice));
}
}
JSONArray jsonArray = new JSONArray();
// 按is_use排序
return AjaxResult.success();
return AppletControllerUtil.appletSuccess(jsonArray);
}
/**
* 积分订单收货确认接口
@ -2490,7 +2491,7 @@ public class AppletController extends BaseController {
if (!allAddressList.isEmpty()) {
targetAddress = allAddressList.get(0);
} else {
return AppletControllerUtil.appletWarning("用户暂无收货地址");
return AppletControllerUtil.appletSuccess("用户暂无收货地址");
}
}
@ -4110,6 +4111,9 @@ public class AppletController extends BaseController {
return AppletControllerUtil.appletWarning("取消失败:" + e.getMessage());
}
}
//接单
@GetMapping("/api/worker/accept/order/{id}")
public AjaxResult workerAcceptOrder(@PathVariable("id") Long id, HttpServletRequest request) {
try {
@ -4649,7 +4653,7 @@ public class AppletController extends BaseController {
return AjaxResult.success(data);
} catch (Exception e) {
return AppletControllerUtil.appletError("查询师傅订单详情失败:" + e.getMessage());
return AppletControllerUtil.appletError("查询订单详情失败:" + e.getMessage());
}
}
@ -5487,7 +5491,7 @@ public class AppletController extends BaseController {
workerApply.setUid(user.getId());
List<WorkerApply> workerApplyList = workerApplyService.selectWorkerApplyList(workerApply);
if (workerApplyList == null || workerApplyList.isEmpty()) {
return AppletControllerUtil.appletError("用户没有申请成为师傅");
return AppletControllerUtil.appletSuccess(null);
}
return AjaxResult.success(workerApplyList.getFirst());
} catch (Exception e) {
@ -6996,25 +7000,14 @@ public class AppletController extends BaseController {
orderLog.setOrderId(orderInfo.getOrderId());
orderLog.setType(new BigDecimal(5));
List<OrderLog> orderLogList = orderLogService.selectOrderLogList(orderLog);
System.out.println("=== 开始退款处理orderLogList.getFirst().getId()2222222222订单号: " + orderLogList+ " ===");
if (!orderLogList.isEmpty()) {
System.out.println("=== 开始退款处理orderLogList.getFirst().getId()2222222222订单号: " + orderLogList.getFirst().getId()+ " ===");
orderLogService.updateOrderLogEnd(orderLogList.getFirst().getId());
// OrderLog orderLogInfo = orderLogList.getFirst();
// orderLogInfo
}
if (StringUtils.isNotBlank(shangmenprice)){
log.setPaid(1L);
log.setPrice(new BigDecimal(shangmenprice));
jsonObject.put("name","师傅提前结束订单,上门费"+shangmenprice+"");
// BigDecimal totalAmount=log.getPrice();
//
// Users userinfo = usersService.selectUsersById(orderInfo.getUid());
// PayBeforeUtil payBeforeUtil = new PayBeforeUtil();
// payBeforeUtil.createPayBefore(userinfo, totalAmount, logOrderId, log.getId(),
// null, 7L, null, null,
// null, null, null,1L,null,order.getOrderId());
}else{
jsonObject.put("name","师傅提前结束订单,无其他费用");
}
@ -7041,59 +7034,11 @@ public class AppletController extends BaseController {
//微信推送师傅设置上门费
WXsendMsgUtil.sendMsgForUserDoorMoney(userinfo.getOpenid(), orderInfo, serviceGoods);
}
// // 3.3 查询是否有上门费(type=2, paid=2)
// OrderLog doorPriceLogself = new OrderLog();
// doorPriceLogself.setOid(orderInfo.getId());
// doorPriceLogself.setType(BigDecimal.valueOf(2));
// doorPriceLogself.setPaid(2L);
// doorPriceLogself.setWorkerId(workerInfo.getId());
// OrderLog doorPriceLog = orderLogService.selectOneByOidTypeWorkerIdPaid(doorPriceLogself);
// if (doorPriceLog != null && doorPriceLog.getPrice() != null) {
// // 师傅等级信息
// //Users workerInfo = usersService.selectUsersById(workerId);
// WorkerLevel levelInfo = workerLevelService.selectWorkerLevelByLevel(Long.valueOf(workerInfo.getLevel()));
// // 更新师傅佣金
// BigDecimal price = doorPriceLog.getPrice();
// Users updateUser = new Users();
// updateUser.setId(workerInfo.getId());
// updateUser.setCommission(workerInfo.getCommission().add(price));
// updateUser.setTotalComm(workerInfo.getTotalComm().add(price));
// usersService.updateUsers(updateUser);
// // 插入师傅金额记录
// WorkerMoneyLog moneyLog = new WorkerMoneyLog();
// moneyLog.setWorkerId(workerInfo.getId());
// moneyLog.setOid(orderInfo.getId());
// moneyLog.setOrderId(orderInfo.getOrderId());
// moneyLog.setPrice(price);
// moneyLog.setType(1);
// moneyLog.setServicePrice(BigDecimal.ZERO);
// moneyLog.setReductionPrice(BigDecimal.ZERO);
// moneyLog.setCr(Math.toIntExact(levelInfo != null ? levelInfo.getCr() : null));
// moneyLog.setMergin(BigDecimal.ZERO);
// moneyLog.setDoorPrice(price);
//
// moneyLog.setStatus(1);//锁单
// moneyLog.setStatusType(0);//后台锁定
// moneyLog.setBeginlook(new Date());
// //7天锁单
// LocalDateTime ldt = LocalDateTime.now().plusDays(7);
// Date end = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
// moneyLog.setEndlook(end);
// moneyLog.setLookday(7);
// moneyLog.setLookMoney(price);
// workerMoneyLogService.insertWorkerMoneyLog(moneyLog);
//
// }
// 3.4 解绑虚拟号
if (orderInfo.getMiddlePhone() != null) {
VoiceResponseResult unbind = YunXinPhoneUtilAPI.httpsPrivacyUnbind(orderInfo.getWorkerPhone(), orderInfo.getUserPhone(), orderInfo.getMiddlePhone());
if (unbind.getResult().equals("000000")) {
// Order phoneUpdate = new Order();
// phoneUpdate.setId(orderInfo.getId());
// phoneUpdate.setMiddlePhone(null);
// phoneUpdate.setUserPhone(null);
// phoneUpdate.setWorkerPhone(null);
// orderService.updateOrder(phoneUpdate);
orderService.updateOrderPhone(orderInfo.getId());
}
}

View File

@ -17,6 +17,7 @@ import com.ruoyi.system.service.IServiceGoodsService;
import com.ruoyi.system.service.IGoodsOrderCursorService;
import com.ruoyi.system.service.IOrderService;
import com.ruoyi.system.service.ISiteConfigService;
import com.ruoyi.system.ControllerUtil.WechatApiUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -206,6 +207,8 @@ public class CoursorUtil extends BaseController {
return AppletControllerUtil.appletError("创建游标失败:" + e.getMessage());
}
}
/**
* 构建服务商品响应数据

View File

@ -1,15 +1,15 @@
package com.ruoyi.system.controller;
import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
import java.util.*;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.system.ControllerUtil.DispatchUtil;
import com.ruoyi.system.ControllerUtil.OrderUtil;
import com.ruoyi.system.ControllerUtil.VerificationResult;
import com.ruoyi.system.ControllerUtil.WXsendMsgUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.ControllerUtil.*;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.winnerlook.model.VoiceResponseResult;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -44,6 +44,11 @@ public class OrderController extends BaseController {
private IOrderService orderService;
@Autowired
private IServiceGoodsService serviceGoodsService;
@Autowired
private IUsersPayBeforService usersPayBeforService;
@Autowired
IUsersService usersService;
@Autowired
@ -54,6 +59,9 @@ public class OrderController extends BaseController {
IOrderSoundLogService orderSoundLogService;
@Autowired
IOrderSoundService orderSoundService;
@Autowired
IUserAddressService userAddressService;
@Autowired
IOrderLogService orderLogService;
@ -140,34 +148,77 @@ public class OrderController extends BaseController {
@Log(title = "服务订单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Order order) {
OrderUtil orderUtil = new OrderUtil();
//1,根据用户手机号和地址判断用户的数据数据和地址数据
//如果用户数据不存在则添加用户数据
//如果用户地址不存在则添加用户地址数据
if (order.getType() == 1) {
Map<String, Object> map = orderUtil.isUser(order.getPhone(), order.getAddress());
if (map.get("code").equals("1")) {
Users usersdata = (Users) map.get("users");
UserAddress userAddressdata = (UserAddress) map.get("UserAddress");
if (userAddressdata != null) {
order.setAddressId(userAddressdata.getId());
}
if (usersdata != null) {
order.setUid(usersdata.getId());
}
Order orderdata=new Order();
}
order.setUserPhone(order.getPhone());
Users users = usersService.selectUsersById(order.getUid());
if (users == null){
return error("用户不能为空");
}
UserAddress userAddress = userAddressService.selectUserAddressById(order.getAddressId());
if (userAddress == null){
return error("地址不能为空");
}
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
if (serviceGoods == null){
return error("服务不能为空");
}
orderdata.setType(1);
orderdata.setMainOrderId(GenerateCustomCode.generCreateOrder("HT"));
orderdata.setOrderId(GenerateCustomCode.generCreateOrder("SE"));
orderdata.setCreateType(1);
orderdata.setCreatePhone(users.getPhone());
orderdata.setUid(users.getId());
orderdata.setProductId(serviceGoods.getId());
orderdata.setName(userAddress.getName());
orderdata.setPhone(userAddress.getPhone());
orderdata.setAddress(userAddress.getAddressName());
orderdata.setMakeTime(order.getMakeTime());
orderdata.setMakeHour(order.getMakeHour());
orderdata.setNum(order.getNum());
orderdata.setTotalPrice(new BigDecimal(0));
orderdata.setGoodPrice(new BigDecimal(0));
orderdata.setPayPrice(new BigDecimal(0));
orderdata.setDeduction(new BigDecimal(0));
orderdata.setStatus(1L);
orderdata.setIsPause(1);
orderdata.setMark(order.getMark());
orderdata.setAddressId(userAddress.getId());
orderdata.setSku(order.getSku());
//orderdata.setReceiveTime();
orderdata.setIsComment(0);
orderdata.setReceiveType(3L);
orderdata.setIsAccept(0);
orderdata.setUidAdmin(String.valueOf(users.getId()));
orderdata.setAddressAdmin(String.valueOf(userAddress.getId()));
orderdata.setLogStatus(9);
JSONObject logJson=new JSONObject();
logJson.put("type",9);
orderdata.setLogJson(logJson.toJSONString());
orderdata.setJsonStatus(0);
orderdata.setFileData(order.getFileData());
orderdata.setOdertype(0);
orderdata.setReamk(order.getReamk());
orderdata.setBigtype(1);
orderdata.setAddressEn(userAddress.getAddressName());
//添加订单日志记录
int flg= orderService.insertOrder(order);
int flg= orderService.insertOrder(orderdata);
if (flg>0){
return toAjax(orderUtil.SaveOrderLog(order));
}else{
return error();
// 添加订单日志
OrderLog orderLog = new OrderLog();
orderLog.setOid(orderdata.getId());
orderLog.setOrderId(orderdata.getOrderId());
orderLog.setTitle("订单生成");
orderLog.setType(BigDecimal.valueOf(1.0));
com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
jsonObject.put("name", "后台订单创建成功");
orderLog.setContent(jsonObject.toJSONString());
orderLogService.insertOrderLog(orderLog);
}
return success("操作成功");
}
@ -462,6 +513,100 @@ public class OrderController extends BaseController {
}
}
/**
* 接单接口
*/
@PreAuthorize("@ss.hasPermi('system:Order:edit')")
@Log(title = "订单接单", businessType = BusinessType.UPDATE)
@PostMapping("/accept-order")
public AjaxResult acceptOrder(@RequestBody Map<String, Object> params) {
try {
String orderId = params.get("orderId").toString();
// Long workerId = null;
// if (params.get("workerId") != null) {
// workerId = Long.valueOf(params.get("workerId").toString());
// }
// 2. 查询订单
Order order = orderService.selectOrderByOrderId(orderId);
if (order == null) {
return error("订单不存在");
}
Long workerId =order.getWorkerId();
// 如果没有传递workerId使用订单中的workerId
// if (workerId == null) {
// workerId = order.getWorkerId();
// }
if (workerId == null) {
return error("订单未分配师傅,无法接单");
}
Users worker = usersService.selectUsersById(workerId);
if (worker == null) {
return error("工人不存在");
}
// 3. 验证订单状态允许状态1和2的订单接单
if (order.getStatus() == null || (order.getStatus() != 1L && order.getStatus() != 2L)) {
return error("当前订单状态不可接单,只有待支付或待服务状态的订单才能接单");
}
// 4. 设置接单相关字段
order.setWorkerId(worker.getId());
order.setWorkerPhone(worker.getPhone());
order.setIsPause(1); // 1:未暂停
order.setReceiveType(3L); // 3:平台派单
order.setReceiveTime(new Date());
order.setIsAccept(1); // 1:已接单
order.setJsonStatus(2); // 服务进度2=接单
order.setStatus(2L); // 设置为待服务状态
order.setLogStatus(9);
com.alibaba.fastjson2.JSONObject json = new com.alibaba.fastjson2.JSONObject();
json.put("type", 1);
order.setLogJson(json.toJSONString());
// 更新订单
int updateResult = orderService.updateOrder(order);
if (updateResult <= 0) {
return error("更新订单失败");
}
// 5. 写入日志
OrderLog orderLog = new OrderLog();
orderLog.setOid(order.getId());
orderLog.setOrderId(order.getOrderId());
orderLog.setTitle("师傅接单");
orderLog.setType(new BigDecimal(2.0));
orderLog.setCreatedAt(new Date());
com.alibaba.fastjson2.JSONObject logContent = new com.alibaba.fastjson2.JSONObject();
logContent.put("name", "同意系统配单");
orderLog.setContent(logContent.toJSONString());
orderLog.setWorkerId(order.getWorkerId());
orderLog.setWorkerLogId(order.getWorkerId());
int logResult = orderLogService.insertOrderLog(orderLog);
if (logResult <= 0) {
return error("记录接单日志失败");
}
// 6. 绑定号码如果有相关工具类
try {
Map<String, Object> bindmap = OrderBindWorkerUtil.getOrderBindWorker(order.getId());
// 这里可以处理绑定结果
} catch (Exception e) {
// 绑定失败不影响接单流程
System.out.println("绑定号码失败:" + e.getMessage());
}
return success("接单成功");
} catch (Exception e) {
return error("接单失败:" + e.getMessage());
}
}
/**
* 出发上门接口
*/
@ -470,11 +615,68 @@ public class OrderController extends BaseController {
@PostMapping("/departure")
public AjaxResult departure(@RequestBody Map<String, Object> params) {
try {
String orderId = params.get("orderId").toString();
// 参数验证
if (params == null || params.isEmpty()) {
return error("请求参数不能为空");
}
// 这里调用具体的业务逻辑您来实现
// 例如更新订单状态为出发上门记录出发时间等
String orderId = params.get("orderId") != null ? params.get("orderId").toString() : null;
if (orderId == null || orderId.trim().isEmpty()) {
return error("订单号不能为空");
}
// 查询订单信息
Order order = orderService.selectOrderByOrderId(orderId);
if (order == null) {
return error("订单不存在");
}
// 验证订单状态只有已接单状态的订单才能出发上门
if (order.getStatus() == null || order.getStatus() != 2L) {
return error("当前订单状态不可出发上门,只有已接单状态的订单才能出发上门");
}
// 验证是否已分配师傅
if (order.getWorkerId() == null) {
return error("订单未分配师傅,无法出发上门");
}
// 验证师傅是否已接单
if (order.getIsAccept() == null || order.getIsAccept() != 1) {
return error("师傅未接单,无法出发上门");
}
// if (order.getStatus() == null || order.getStatus() != 2L) {
// return AppletControllerUtil.appletWarning("订单状态不正确");
// }
// if (order.getJsonStatus() == null || order.getJsonStatus() != 3) {
// return AppletControllerUtil.appletWarning("订单进度不正确");
// }
order.setJsonStatus(4); // 出发上门
com.alibaba.fastjson2.JSONObject typeJson = new com.alibaba.fastjson2.JSONObject();
typeJson.put("type", 3);
order.setLogJson(typeJson.toJSONString());
// 5. 保存
orderService.updateOrder(order);
// 4. 写订单日志
OrderLog orderLog = new OrderLog();
orderLog.setOid(order.getId());
orderLog.setOrderId(order.getOrderId());
orderLog.setWorkerId(order.getWorkerId());
orderLog.setWorkerLogId(order.getWorkerId());
orderLog.setTitle("出发上门");
com.alibaba.fastjson2.JSONObject typeJson1 = new com.alibaba.fastjson2.JSONObject();
typeJson1.put("name", "师傅收到派单信息准备出发");
orderLog.setType(new BigDecimal("3.0"));
orderLog.setContent(typeJson1.toJSONString());
orderLogService.insertOrderLog(orderLog);
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
Users user=usersService.selectUsersById(order.getUid());
//小程序推送给用户师傅已经出发
WXsendMsgUtil.sendStartDoorMoney(user.getOpenid(), order, serviceGoods);
return success("出发上门成功");
} catch (Exception e) {
return error("出发上门失败:" + e.getMessage());
@ -489,10 +691,101 @@ public class OrderController extends BaseController {
@PostMapping("/confirm-arrival")
public AjaxResult confirmArrival(@RequestBody Map<String, Object> params) {
try {
String orderId = params.get("orderId").toString();
// 参数验证
if (params == null || params.isEmpty()) {
return error("请求参数不能为空");
}
// 这里调用具体的业务逻辑您来实现
// 例如更新订单状态为已到达记录到达时间等
String orderId = params.get("orderId") != null ? params.get("orderId").toString() : null;
if (orderId == null || orderId.trim().isEmpty()) {
return error("订单号不能为空");
}
// 查询订单信息
Order order = orderService.selectOrderByOrderId(orderId);
if (order == null) {
return error("订单不存在");
}
// 验证订单状态只有已出发上门状态的订单才能确认到达
if (order.getStatus() == null || order.getStatus() != 2L) {
return error("当前订单状态不可确认到达,只有已出发上门状态的订单才能确认到达");
}
// 验证是否已分配师傅
if (order.getWorkerId() == null) {
return error("订单未分配师傅,无法确认到达");
}
// 验证师傅是否已接单
if (order.getIsAccept() == null || order.getIsAccept() != 1) {
return error("师傅未接单,无法确认到达");
}
// 验证订单进度状态应该是出发上门状态
if (order.getJsonStatus() == null || order.getJsonStatus() != 4) {
return error("订单进度状态不正确,只有出发上门状态的订单才能确认到达");
}
order.setJsonStatus(5); // 确认到达
com.alibaba.fastjson2.JSONObject typeJson = new com.alibaba.fastjson2.JSONObject();
typeJson.put("type", 4);
order.setLogJson(typeJson.toJSONString());
// 6. 保存
orderService.updateOrder(order);
// 5. 写订单日志
//一口价直接开始服务没有报价的环节
// if (order.getOdertype()!= 0){
// OrderLog orderLog = new OrderLog();
// orderLog.setOid(order.getId());
// orderLog.setOrderId(order.getOrderId());
// orderLog.setWorkerId(workerId);
// orderLog.setLatitude(latitude);
// orderLog.setLongitude(longitude);
// orderLog.setAddressName(addressName);
// orderLog.setWorkerLogId(workerId);
// orderLog.setTitle("师傅到达");
// orderLog.setType(new BigDecimal("5.0"));
// com.alibaba.fastjson2.JSONObject content = new com.alibaba.fastjson2.JSONObject();
// content.put("name", "师傅到达服务地点,开始服务工作");
// orderLog.setContent(content.toJSONString());
// // 6. 保存
// orderLogService.insertOrderLog(orderLog);
// ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
// // WXsendMsgUtil.sendMsgForWorkerInfo(user.getOpenid(), order, serviceGoods);
// return AppletControllerUtil.appletSuccess("师傅已经上门");
// }
OrderLog orderLog = new OrderLog();
orderLog.setOid(order.getId());
orderLog.setOrderId(order.getOrderId());
orderLog.setWorkerId(order.getWorkerId());
orderLog.setWorkerLogId(order.getWorkerId());
orderLog.setTitle("师傅到达");
orderLog.setType(new BigDecimal("4.0"));
com.alibaba.fastjson2.JSONObject content = new com.alibaba.fastjson2.JSONObject();
content.put("name", "师傅到达服务地点");
orderLog.setContent(content.toJSONString());
// 6. 保存
orderLogService.insertOrderLog(orderLog);
//解绑订单虚拟号
//需要解绑原订单上原师傅和客户的虚拟号
VoiceResponseResult resultObj = YunXinPhoneUtilAPI.httpsPrivacyUnbind(order.getWorkerPhone(), order.getUserPhone(), order.getMiddlePhone());
if (resultObj.getResult().equals("000000")) {
// order.setWorkerPhone(null);
// order.setUserPhone(null);
// order.setMiddlePhone(null);
// orderService.updateOrder(order);
orderService.updateOrderPhone(order.getId());
} // 4. 更新订单状
//解绑号码
YunXinPhoneUtilAPI.httpsPrivacyUnbind(order.getWorkerPhone(), order.getUserPhone(), order.getMiddlePhone());
// 小程序推送给用户师傅已经到达
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
//师傅到达的时候给客户的微信推送
Users user = usersService.selectUsersById(order.getUid());
WXsendMsgUtil.sendWorkerIsComing(user.getOpenid(), order, serviceGoods);
return success("确认到达成功");
} catch (Exception e) {
@ -508,11 +801,103 @@ public class OrderController extends BaseController {
@PostMapping("/end-order")
public AjaxResult endOrder(@RequestBody Map<String, Object> params) {
try {
String orderId = params.get("orderId").toString();
// 这里调用具体的业务逻辑您来实现
// 例如更新订单状态为已结束记录结束时间等
// 参数校验
if (params == null || params.isEmpty()) {
return error("请求参数不能为空");
}
String orderId = params.get("orderId") != null ? params.get("orderId").toString() : null;
if (orderId == null || orderId.trim().isEmpty()) {
return error("订单号不能为空");
}
String doorFee=params.get("doorFee") != null ? params.get("doorFee").toString() : null;
// 查询订单
Order order = orderService.selectOrderByOrderId(orderId);
if (order == null) {
return error("订单不存在");
}
RefundUtil refundUtil = new RefundUtil();
// 3.1 更新订单状态为7已结束
Order updateOrder = new Order();
updateOrder.setId(order.getId());
updateOrder.setStatus(7L);
updateOrder.setServicePrice(new BigDecimal(0));
updateOrder.setGoodPrice(new BigDecimal(0));
updateOrder.setTotalPrice(new BigDecimal(0));
orderService.updateOrder(updateOrder);
String logOrderId = GenerateCustomCode.generCreateOrder("DSB");
// 3.2 插入订单日志
OrderLog log = new OrderLog();
com.alibaba.fastjson2.JSONObject jsonObject = new com.alibaba.fastjson2.JSONObject();
//1.1结束订单就要删除客户未支付的付款数据
UsersPayBefor payBefor = new UsersPayBefor();
payBefor.setLastorderid(order.getOrderId());
payBefor.setStatus(1L);
List<UsersPayBefor> payBeforList = usersPayBeforService.selectUsersPayBeforList(payBefor);
for (UsersPayBefor payBeforInfo : payBeforList) {
usersPayBeforService.deleteUsersPayBeforById(payBeforInfo.getId());
}
//1.2如果这个订单有支付数据还要给客户退回去
UsersPayBefor userpayBefor = usersPayBeforService.selectUsersPayBeforByOrderId(order.getOrderId());
if (userpayBefor != null) {
Users user = usersService.selectUsersById(order.getUid());
//退回其他对应支付时产生的金额和积分
BenefitPointsUtil.refundServiceAndConsumption(order.getId(), user, userpayBefor.getServicemoney(),userpayBefor.getShopmoney());
System.out.println("=== 开始退款处理2222222222订单号: " + userpayBefor.getStatus() + " ===");
// if (usersPayBefor.getStatus() == 2){
System.out.println("=== 开始退款处理2222222222订单号: " + order.getOrderId() + " ===");
refundUtil.refundOrder(order.getOrderId());
// }
}
//1.3找到订单日志的报价数据将报价的支付数据给抹除
OrderLog orderLog = new OrderLog();
orderLog.setOrderId(order.getOrderId());
orderLog.setType(new BigDecimal(5));
List<OrderLog> orderLogList = orderLogService.selectOrderLogList(orderLog);
if (!orderLogList.isEmpty()) {
orderLogService.updateOrderLogEnd(orderLogList.getFirst().getId());
}
if (StringUtils.isNotBlank(doorFee)&&!doorFee.equals("0")){
log.setPaid(1L);
log.setPrice(new BigDecimal(doorFee));
jsonObject.put("name","师傅提前结束订单,上门费"+doorFee+"");
}else{
jsonObject.put("name","师傅提前结束订单,无其他费用");
}
log.setLogOrderId(logOrderId);
log.setOid(order.getId());
log.setOrderId(order.getOrderId());
log.setTitle("结束订单");
log.setType(BigDecimal.valueOf(10));
log.setContent(jsonObject.toJSONString());
//Long workerId = getCurrentWorkerId(request); // 需实现
log.setWorkerId(order.getWorkerId());
log.setCreatedAt(new Date());
log.setUpdatedAt(new Date());
orderLogService.insertOrderLog(log);
if (StringUtils.isNotBlank(doorFee)){
BigDecimal totalAmount=log.getPrice();
Users userinfo = usersService.selectUsersById(order.getUid());
PayBeforeUtil payBeforeUtil = new PayBeforeUtil();
payBeforeUtil.createPayBefore(userinfo, totalAmount, logOrderId, log.getId(),
null, 7L, null, null,
null, null, null,1L,null,order.getOrderId(), null);
ServiceGoods serviceGoods = serviceGoodsService.selectServiceGoodsById(order.getProductId());
//微信推送师傅设置上门费
WXsendMsgUtil.sendMsgForUserDoorMoney(userinfo.getOpenid(), order, serviceGoods);
}
// 3.4 解绑虚拟号
if (order.getMiddlePhone() != null) {
VoiceResponseResult unbind = YunXinPhoneUtilAPI.httpsPrivacyUnbind(order.getWorkerPhone(), order.getUserPhone(), order.getMiddlePhone());
if (unbind.getResult().equals("000000")) {
orderService.updateOrderPhone(order.getId());
}
}
// return AjaxResult.success("订单结束成功");
return success("订单已结束");
} catch (Exception e) {
return error("结束订单失败:" + e.getMessage());
@ -528,7 +913,117 @@ public class OrderController extends BaseController {
public AjaxResult startService(@RequestBody Map<String, Object> params) {
try {
String orderId = params.get("orderId").toString();
String image = params.get("image").toString();
if (StringUtils.isBlank(image)) {
return error("需上传图片");
}
Order order = orderService.selectOrderByOrderId(orderId);
if (order == null) {
return error("订单不存在");
}
OrderLog newlogdata =new OrderLog();
newlogdata.setType(new BigDecimal("6.0"));
newlogdata.setOid(order.getId());
//如果没有进行服务的记录就是开启服务
List<OrderLog> logList = orderLogService.selectOrderLogList(newlogdata);
if (logList.isEmpty()){
// 2. 组装日志内容为数组格式
Map<String, Object> logItem = new LinkedHashMap<>();
logItem.put("name", "师傅开始服务");
logItem.put("image", params.get("image"));
logItem.put("type", 1);
List<Object> logArr = new ArrayList<>();
logArr.add(logItem);
String contentStr = com.alibaba.fastjson2.JSONObject.toJSONString(logArr);
// 3. 写入订单日志
OrderLog log = new OrderLog();
log.setOid(order.getId());
log.setOrderId(order.getOrderId());
log.setTitle("开始服务");
log.setType(new BigDecimal(6.0));
log.setContent(contentStr);
log.setWorkerId(order.getWorkerId());
log.setWorkerLogId(order.getWorkerId());
log.setIsPause(1);
log.setCreatedAt(new Date());
orderLogService.insertOrderLog(log);
//开始服务
// 1. 修改订单状态
order.setStatus(3L); // 服务中
order.setJsonStatus(7); // 服务中
order.setLogJson("{\"type\":6}");
order.setIsPause(1); // 服务中
order.setUpdatedAt(new Date());
int update = orderService.updateOrder(order);
return AppletControllerUtil.appletSuccess("服务已开始");
}else{
if (order.getJsonStatus() == 7) {
com.alibaba.fastjson2.JSONObject logItem = new com.alibaba.fastjson2.JSONObject();
logItem.put("name", "暂停服务");
logItem.put("image", params.get("image"));
logItem.put("reson", params.get("reson"));
logItem.put("next_time", params.get("next_time"));
logItem.put("time", new Date());
logItem.put("type", 2);
OrderLog newlogdata1 =new OrderLog();
newlogdata1.setOid(order.getId());
newlogdata1.setOrderId(order.getOrderId());
newlogdata1.setTitle("暂停服务");
newlogdata1.setIsPause(2);
newlogdata1.setContent(logItem.toJSONString());
newlogdata1.setType(new BigDecimal(6.0));
newlogdata1.setWorkerId(order.getWorkerId());
newlogdata1.setWorkerLogId(order.getWorkerId());
orderLogService.insertOrderLog(newlogdata1);
if (order != null) {
// 1. 修改订单状态
order.setStatus(3L); // 服务中
order.setJsonStatus(8); // 服务中
order.setLogJson("{\"type\":6}");
order.setIsPause(2); // 服务中
order.setUpdatedAt(new Date());
orderService.updateOrder(order);
}
return AppletControllerUtil.appletSuccess("操作成功");
}
if (order.getJsonStatus() == 8) {
com.alibaba.fastjson2.JSONObject logItem = new com.alibaba.fastjson2.JSONObject();
logItem.put("name", "继续服务");
logItem.put("image", params.get("image"));
logItem.put("time", new Date());
logItem.put("type", 1);
OrderLog newlogdata2 =new OrderLog();
newlogdata2.setOid(order.getId());
newlogdata2.setOrderId(order.getOrderId());
newlogdata2.setTitle("继续服务");
newlogdata2.setIsPause(1);
newlogdata2.setType(new BigDecimal(6.0));
newlogdata2.setWorkerId(order.getWorkerId());
newlogdata2.setWorkerLogId(order.getWorkerId());
newlogdata2.setContent(logItem.toJSONString());
orderLogService.insertOrderLog(newlogdata2);
if (order != null) {
//继续服务
order.setStatus(3L); // 服务中
order.setJsonStatus(7); // 服务中
order.setLogJson("{\"type\":6}");
order.setIsPause(1); // 服务中
order.setUpdatedAt(new Date());
orderService.updateOrder(order);
}
return AppletControllerUtil.appletSuccess("操作成功");
}
}
// 这里调用具体的业务逻辑您来实现
// 例如更新订单状态为服务中记录开始时间等

View File

@ -78,4 +78,11 @@ public interface UsersPayBeforMapper
* @return 支付明细列表
*/
public List<UsersPayBefor> selectPayDetailsByOrderId(String orderId);
/**
* 统计开票用的微信支付总额仅统计status=2且orderid或lastorderid匹配传入orderId
* @param orderId 订单ID
* @return 微信支付总额BigDecimal
*/
public java.math.BigDecimal sumWxMoneyForInvoicingByOrderId(String orderId);
}

View File

@ -78,4 +78,11 @@ public interface IUsersPayBeforService
* @return 支付明细列表
*/
public List<UsersPayBefor> selectPayDetailsByOrderId(String orderId);
/**
* 统计开票用的微信支付总额仅统计status=2且orderid或lastorderid匹配传入orderId
* @param orderId 订单ID
* @return 微信支付总额
*/
public java.math.BigDecimal sumWxMoneyForInvoicingByOrderId(String orderId);
}

View File

@ -112,4 +112,14 @@ public class UsersPayBeforServiceImpl implements IUsersPayBeforService
{
return usersPayBeforMapper.selectPayDetailsByOrderId(orderId);
}
/**
* 统计开票用的微信支付总额仅统计status=2且orderid或lastorderid匹配传入orderId
* @param orderId 订单ID
* @return 微信支付总额
*/
@Override
public java.math.BigDecimal sumWxMoneyForInvoicingByOrderId(String orderId) {
return usersPayBeforMapper.sumWxMoneyForInvoicingByOrderId(orderId);
}
}

View File

@ -96,6 +96,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by paytime desc, id desc
</select>
<!-- 统计开票用的微信支付总额status=2且orderid=或lastorderid=给定orderId -->
<select id="sumWxMoneyForInvoicingByOrderId" parameterType="String" resultType="java.math.BigDecimal">
select COALESCE(SUM(wxmoney), 0)
from users_pay_befor
where status = 2
and (orderid = #{orderId} or lastorderid = #{orderId})
</select>
<insert id="insertUsersPayBefor" parameterType="UsersPayBefor" useGeneratedKeys="true" keyProperty="id">
insert into users_pay_befor
<trim prefix="(" suffix=")" suffixOverrides=",">

Binary file not shown.

View File

@ -9,6 +9,15 @@ export function listDiyCity(query) {
})
}
// 通用城市数据列表(支持按 parentId 取下级)
export function datalist(query) {
return request({
url: '/system/DiyCity/datalist',
method: 'get',
params: query
})
}
// 查询城市详细
export function getDiyCity(id) {
return request({
@ -62,3 +71,11 @@ export function getFirstLevelCities() {
}
})
}
// 手动恢复过期的师傅暂停状态
export function manualResumeWorkerStatus() {
return request({
url: '/system/DiyCity/manualResumeWorkerStatus',
method: 'post'
})
}

View File

@ -0,0 +1,344 @@
<template>
<el-dialog
title="项目报价"
:visible.sync="visibleInner"
width="420px"
top="6vh"
append-to-body
@close="handleClose"
>
<div class="quote-wrapper" v-loading="loadingInspections">
<!-- 基检现象 -->
<section class="group">
<div class="group-title">基检现象</div>
<div class="group-sub">请和用户确认基础现象</div>
<div class="chip-list">
<el-button
v-for="opt in inspectionOptions"
:key="opt.id"
:type="selectedInspectionIds.includes(opt.id) ? 'primary' : 'default'"
size="mini"
class="chip"
@click="toggleInspection(opt.id)"
>
{{ opt.name }}
</el-button>
</div>
</section>
<!-- 服务项目 -->
<section class="group">
<div class="group-title">服务项目</div>
<div class="group-sub">请和用户确认基础项目</div>
<el-card class="slot-card" shadow="never">
<div class="slot-row">
<el-button type="text" @click="projectPickerVisible = true">
去添加服务项目
</el-button>
</div>
<div v-if="projectItems.length > 0" class="list">
<div v-for="(item, idx) in projectItems" :key="idx" class="list-item">
<span class="name">{{ item.name }}</span>
<span class="price">{{ toMoney(item.price) }}</span>
<el-button type="text" @click="removeProject(idx)">移除</el-button>
</div>
</div>
</el-card>
</section>
<!-- 所需物料 -->
<section class="group">
<div class="group-title">所需物料</div>
<div class="group-sub">如需物料请添加并向用户一并报价</div>
<el-card class="slot-card" shadow="never">
<div class="slot-row">
<el-button type="text" @click="materialPickerVisible = true">
去添加所需物料
</el-button>
</div>
<div v-if="materialItems.length > 0" class="list">
<div v-for="(item, idx) in materialItems" :key="idx" class="list-item">
<span class="name">{{ item.name }}</span>
<span class="qty">x{{ item.quantity }}</span>
<span class="price">{{ toMoney(item.price * item.quantity) }}</span>
<el-button type="text" @click="removeMaterial(idx)">移除</el-button>
</div>
</div>
</el-card>
</section>
<!-- 付款方式 -->
<section class="group">
<div class="group-title">付款方式</div>
<div class="group-sub">如需物料请添加并向用户一并报价</div>
<el-card class="slot-card" shadow="never">
<div class="pay-row">
<el-radio v-model="payType" label="stage">定金 + 尾款</el-radio>
<el-radio v-model="payType" label="once">一次性付清</el-radio>
</div>
</el-card>
</section>
<!-- 优惠 -->
<section class="group">
<el-button type="text" @click="discountVisible = !discountVisible">添加优惠</el-button>
<transition name="el-fade-in">
<div v-show="discountVisible" class="discount-box">
<el-form :model="discount" label-width="80px" size="small">
<el-form-item label="优惠类型">
<el-select v-model="discount.type" placeholder="请选择">
<el-option label="立减" value="minus" />
<el-option label="折扣(%)" value="rate" />
</el-select>
</el-form-item>
<el-form-item v-if="discount.type === 'minus'" label="立减金额">
<el-input-number v-model="discount.amount" :min="0" :step="1" />
</el-form-item>
<el-form-item v-else label="折扣比例">
<el-input-number v-model="discount.rate" :min="0" :max="100" :step="1" />
</el-form-item>
</el-form>
</div>
</transition>
</section>
<!-- 底部报价 -->
<div class="footer">
<el-button type="primary" class="btn-generate" @click="handleGenerate">
生成报价报价{{ toMoney(grandTotal) }}
</el-button>
</div>
<!-- 服务项目选择弹窗临时简化版后续替换为接口数据 -->
<el-dialog
title="添加服务项目"
:visible.sync="projectPickerVisible"
width="520px"
append-to-body
>
<el-form :model="tempProject" label-width="90px" size="small">
<el-form-item label="项目名称">
<el-input v-model="tempProject.name" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="项目单价">
<el-input-number v-model="tempProject.price" :min="0" :step="1" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="projectPickerVisible = false">取消</el-button>
<el-button type="primary" @click="addProject">添加</el-button>
</div>
</el-dialog>
<!-- 物料选择弹窗临时简化版后续替换为接口数据 -->
<el-dialog
title="添加物料"
:visible.sync="materialPickerVisible"
width="520px"
append-to-body
>
<el-form :model="tempMaterial" label-width="90px" size="small">
<el-form-item label="物料名称">
<el-input v-model="tempMaterial.name" placeholder="请输入物料名称" />
</el-form-item>
<el-form-item label="物料单价">
<el-input-number v-model="tempMaterial.price" :min="0" :step="1" />
</el-form-item>
<el-form-item label="数量">
<el-input-number v-model="tempMaterial.quantity" :min="1" :step="1" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="materialPickerVisible = false">取消</el-button>
<el-button type="primary" @click="addMaterial">添加</el-button>
</div>
</el-dialog>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose"> </el-button>
<el-button type="primary" @click="handleGenerate">生成报价</el-button>
</div>
</el-dialog>
</template>
<script>
import request from '@/utils/request'
export default {
name: 'ProjectQuoteDialog',
props: {
visible: { type: Boolean, default: false },
orderId: { type: String, default: '' },
workerId: { type: [String, Number], default: '' },
goodId: { type: [String, Number], default: '' }
},
data() {
return {
visibleInner: false,
//
inspectionOptions: [],
loadingInspections: false,
selectedInspectionIds: [],
//
projectItems: [],
materialItems: [],
//
payType: 'stage', // stage: +, once:
//
discountVisible: false,
discount: {
type: 'minus', // minus | rate
amount: 0,
rate: 0
},
//
projectPickerVisible: false,
materialPickerVisible: false,
tempProject: { name: '', price: 0 },
tempMaterial: { name: '', price: 0, quantity: 1 }
}
},
watch: {
visible: {
immediate: true,
handler(val) {
this.visibleInner = val
if (val) {
this.loadInspectionOptions()
}
}
},
workerId() { if (this.visibleInner) this.loadInspectionOptions() },
goodId() { if (this.visibleInner) this.loadInspectionOptions() }
},
computed: {
projectTotal() {
return this.projectItems.reduce((sum, it) => sum + (Number(it.price) || 0), 0)
},
materialTotal() {
return this.materialItems.reduce((sum, it) => sum + (Number(it.price) || 0) * (Number(it.quantity) || 0), 0)
},
subtotal() {
return this.projectTotal + this.materialTotal
},
discountAmount() {
if (this.discount.type === 'minus') {
return Number(this.discount.amount) || 0
}
const rate = Number(this.discount.rate) || 0
return (this.subtotal * rate) / 100
},
grandTotal() {
const val = this.subtotal - this.discountAmount
return val > 0 ? val : 0
}
},
methods: {
async loadInspectionOptions() {
if (!this.workerId || !this.goodId) {
//
return
}
try {
this.loadingInspections = true
const url = `api/worker/basic/project?id=${this.workerId}&goodid=${this.goodId}`
const res = await request.get(url)
if (res && res.code === 200 && res.data && Array.isArray(res.data.basic)) {
this.inspectionOptions = res.data.basic.map((name, idx) => ({ id: idx + 1, name }))
this.selectedInspectionIds = []
} else {
this.inspectionOptions = []
}
} catch (e) {
console.error('获取基检现象失败:', e)
this.$message.error('获取基检现象失败')
this.inspectionOptions = []
} finally {
this.loadingInspections = false
}
},
toMoney(v) {
const num = Number(v) || 0
return num.toFixed(2)
},
toggleInspection(id) {
const idx = this.selectedInspectionIds.indexOf(id)
if (idx >= 0) this.selectedInspectionIds.splice(idx, 1)
else this.selectedInspectionIds.push(id)
},
addProject() {
if (!this.tempProject.name) return this.$message.warning('请输入项目名称')
this.projectItems.push({ ...this.tempProject })
this.tempProject = { name: '', price: 0 }
this.projectPickerVisible = false
},
removeProject(index) {
this.projectItems.splice(index, 1)
},
addMaterial() {
if (!this.tempMaterial.name) return this.$message.warning('请输入物料名称')
this.materialItems.push({ ...this.tempMaterial })
this.tempMaterial = { name: '', price: 0, quantity: 1 }
this.materialPickerVisible = false
},
removeMaterial(index) {
this.materialItems.splice(index, 1)
},
handleGenerate() {
const payload = {
orderId: this.orderId,
inspections: this.selectedInspectionIds,
projects: this.projectItems,
materials: this.materialItems,
payType: this.payType,
discount: { ...this.discount },
amount: this.grandTotal
}
this.$emit('submit', payload)
this.visibleInner = false
this.$emit('update:visible', false)
},
handleClose() {
this.visibleInner = false
this.$emit('update:visible', false)
}
}
}
</script>
<style lang="scss" scoped>
.quote-wrapper {
.group { margin-bottom: 16px; }
.group-title { font-weight: 600; color: #2c3e50; margin-bottom: 4px; }
.group-sub { font-size: 12px; color: #909399; margin-bottom: 8px; }
.chip-list {
display: flex; flex-wrap: wrap; gap: 8px;
.chip { min-width: 84px; }
}
.slot-card {
background: #f7fbff;
.slot-row { padding: 6px 0; }
.list { margin-top: 8px; }
.list-item {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 0; border-bottom: 1px dashed #ebeef5;
.name { color: #303133; }
.qty { color: #606266; margin: 0 6px; }
.price { color: #409EFF; font-weight: 600; }
}
}
.pay-row { display: flex; align-items: center; gap: 12px; }
.discount-box { background: #f8f9fb; border: 1px solid #ebeef5; padding: 10px; border-radius: 6px; }
.footer { display: flex; justify-content: center; margin-top: 12px; }
.btn-generate { width: 100%; }
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -381,6 +381,7 @@
</el-dialog>
<WorkerLevelSelectDialog
v-if="workerLevelDialogVisible && workerLevelUserId != null"
:visible.sync="workerLevelDialogVisible"
:user-id="workerLevelUserId"
:user-name="workerLevelUserName"