新增 下单分不同类型添加sku,下单预览图设置背景
This commit is contained in:
parent
1b221bca72
commit
ad175a2393
|
|
@ -597,7 +597,7 @@ public class FuncUtil extends StringUtils {
|
|||
return requestAttributes == null ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
}
|
||||
|
||||
public static LocalDateTime parseDate(Long timestamp) {
|
||||
public static LocalDateTime timeToLocalDate(Long timestamp) {
|
||||
if(isEmpty(timestamp)){
|
||||
return null;
|
||||
}
|
||||
|
|
@ -605,6 +605,13 @@ public class FuncUtil extends StringUtils {
|
|||
// 将 Instant 转换为 LocalDateTime
|
||||
return LocalDateTime.ofInstant(instant, java.time.ZoneId.systemDefault());
|
||||
}
|
||||
public static Long localDateToLong(LocalDateTime date) {
|
||||
if(isEmpty(date)){
|
||||
return null;
|
||||
}
|
||||
Instant instant = date.atZone(TimeZone.getDefault().toZoneId()).toInstant();
|
||||
return instant.getEpochSecond();
|
||||
}
|
||||
private static final Snowflake snowflake = IdUtil.getSnowflake();
|
||||
public static long getNextId() {
|
||||
return snowflake.nextId();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package cn.hangtag.framework.common.util.validation;
|
||||
|
||||
import cn.hangtag.framework.common.exception.ErrorCode;
|
||||
import cn.hangtag.framework.common.exception.ServiceException;
|
||||
import cn.hangtag.framework.common.util.FuncUtil;
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -28,4 +29,22 @@ public class AssertUtil {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static void isEmpty(Object field, ErrorCode errorCode) {
|
||||
if (FuncUtil.isEmpty(field)) {
|
||||
throw new ServiceException(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isNull(Object field, String errorMessage) {
|
||||
if (field == null) {
|
||||
throw new ServiceException(600,errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isNull(Object field, ErrorCode errorCode) {
|
||||
if (field == null){
|
||||
throw new ServiceException(errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package cn.hangtag.module.oms.enums.common;
|
|||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 单据状态
|
||||
* @author wwb
|
||||
|
|
@ -29,4 +32,30 @@ public enum BillStatusEnum {
|
|||
*/
|
||||
private final String name;
|
||||
|
||||
|
||||
|
||||
public static BillStatusEnum getByValue(String value) {
|
||||
for (BillStatusEnum item : BillStatusEnum.values()) {
|
||||
if (item.getValue().equals(value)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final List<String> CAN_STATUS = new ArrayList<>();;
|
||||
static {
|
||||
CAN_STATUS.add(BillStatusEnum.REJECT.getValue());
|
||||
CAN_STATUS.add(BillStatusEnum.SAVE.getValue());
|
||||
CAN_STATUS.add(BillStatusEnum.SUBMIT.getValue());
|
||||
}
|
||||
/**
|
||||
* 是否允许 编辑订单状态
|
||||
*
|
||||
* @return {@link List }<{@link String }>
|
||||
*/
|
||||
public static boolean isCanEditOrder(String status){
|
||||
return CAN_STATUS.contains(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,18 +10,12 @@ import cn.hangtag.framework.common.util.object.BeanUtils;
|
|||
import cn.hangtag.framework.excel.core.util.ExcelUtils;
|
||||
import cn.hangtag.framework.security.core.LoginUser;
|
||||
import cn.hangtag.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.hangtag.module.oms.controller.admin.productinfo.vo.ProductInfoPageReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.productinfo.vo.ProductInfoRespVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderPageReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRemarkReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRespVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderSaveReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.front.vo.SaleOrderFollowerUserVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.*;
|
||||
import cn.hangtag.module.oms.convert.saleorder.SaleOrderConvert;
|
||||
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
|
||||
import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO;
|
||||
import cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO;
|
||||
import cn.hangtag.module.oms.service.customer.CustomerService;
|
||||
import cn.hangtag.module.oms.service.productinfo.ProductInfoService;
|
||||
import cn.hangtag.module.oms.service.saleorder.SaleOrderService;
|
||||
import cn.hangtag.module.system.api.user.AdminUserApi;
|
||||
import cn.hangtag.module.system.api.user.dto.AdminUserRespDTO;
|
||||
|
|
@ -30,12 +24,10 @@ import com.alibaba.fastjson.JSONObject;
|
|||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
|
@ -189,5 +181,18 @@ public class AppSaleOrderController{
|
|||
}
|
||||
|
||||
|
||||
@GetMapping("/follower-user/{brandId}")
|
||||
@Operation(summary = "获取指定品牌跟单员")
|
||||
public CommonResult<List<SaleOrderFollowerUserVO>> getFollowerUserList(@PathVariable("brandId") String brandId) {
|
||||
List<SaleOrderFollowerUserVO> users = saleOrderService.queryFollowerUserListByBrandId(brandId);
|
||||
return success(users);
|
||||
}
|
||||
|
||||
@GetMapping("/contract-code")
|
||||
@Operation(summary = "获取销售合同号")
|
||||
public CommonResult<String> getContractCode() {
|
||||
String code = saleOrderService.getNewContractCode2();
|
||||
return success(code);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -98,6 +98,11 @@ public class ProductInfoRespVO {
|
|||
@ExcelProperty("规格材质")
|
||||
private String specMaterial;
|
||||
|
||||
/**
|
||||
* 模板类型-字典 product_draft_template_type 1有模板 2无模板 3尺码唛
|
||||
*/
|
||||
private String templateType;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@ public class ProductInfoSaveReqVO {
|
|||
@Schema(description = "规格材质")
|
||||
private String specMaterial;
|
||||
|
||||
/**
|
||||
* 模板类型-字典 product_draft_template_type 1有模板 2无模板 3尺码唛
|
||||
*/
|
||||
@Schema(description = "模板类型")
|
||||
private String templateType;
|
||||
|
||||
@Schema(description = "产品信息工艺列表")
|
||||
private List<ProductProcessSaveReqVO> productProcessList;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,5 +34,17 @@ public class SaleOrderFrontController {
|
|||
public CommonResult<Long> placeOrder(@Valid @RequestBody CreateSaleOrderDTO dto) {
|
||||
return success(saleOrderService.placeOrder(dto));
|
||||
}
|
||||
@PostMapping("/editOrder/{id}")
|
||||
@Operation(summary = "修改订单")
|
||||
public CommonResult<Long> editOrder(@PathVariable Long id,@Valid @RequestBody CreateSaleOrderDTO dto) {
|
||||
return success(saleOrderService.editOrder(id,dto));
|
||||
}
|
||||
|
||||
@GetMapping("/details/{id}")
|
||||
@Operation(summary = "编辑订单")
|
||||
public CommonResult<CreateSaleOrderDTO> placeOrder(@PathVariable Long id) {
|
||||
CreateSaleOrderDTO dto = saleOrderService.queryEditOrder(id);
|
||||
return success(dto);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import java.util.List;
|
|||
@Data
|
||||
public class CreateSaleOrderDTO implements Serializable {
|
||||
|
||||
Long id;
|
||||
|
||||
/**
|
||||
* 联系人信息
|
||||
*/
|
||||
|
|
@ -89,6 +91,10 @@ public class CreateSaleOrderDTO implements Serializable {
|
|||
*/
|
||||
private String deliveryRemark;
|
||||
|
||||
/**
|
||||
* 跟单员id system_user.id
|
||||
*/
|
||||
private String orderFollowerUser;
|
||||
|
||||
/**
|
||||
* 是否分批交货
|
||||
|
|
@ -96,7 +102,6 @@ public class CreateSaleOrderDTO implements Serializable {
|
|||
private Boolean isBatch;
|
||||
|
||||
|
||||
|
||||
private List<SaleOrderEntryItemDTO> saleOrderEntry;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
package cn.hangtag.module.oms.controller.admin.saleorder.front.dto;
|
||||
|
||||
import cn.hangtag.framework.common.util.FuncUtil;
|
||||
import cn.hangtag.module.oms.dal.dataobject.saleorderentry.SaleOrderEntryDO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
|
@ -12,6 +16,8 @@ import java.util.List;
|
|||
* @date 2024/10/02
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SaleOrderEntryItemDTO implements Serializable {
|
||||
|
||||
/**
|
||||
|
|
@ -43,10 +49,17 @@ public class SaleOrderEntryItemDTO implements Serializable {
|
|||
private String cover;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 订货数量
|
||||
*/
|
||||
private Integer orderQty;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 总数量
|
||||
*/
|
||||
|
|
@ -56,11 +69,18 @@ public class SaleOrderEntryItemDTO implements Serializable {
|
|||
*/
|
||||
private Long deliveryDate;
|
||||
|
||||
|
||||
/**
|
||||
* 产品详情
|
||||
*/
|
||||
private String details;
|
||||
/**
|
||||
* 产品sku
|
||||
*/
|
||||
List<SaleOrderSkuDTO> productSkuList;
|
||||
|
||||
|
||||
public SaleOrderEntryItemDTO(SaleOrderEntryDO entryDO) {
|
||||
this.productId = entryDO.getMaterialId();
|
||||
this.orderQty = entryDO.getQty();
|
||||
this.deliveryDate = FuncUtil.localDateToLong(entryDO.getDeliveryDate());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
package cn.hangtag.module.oms.controller.admin.saleorder.front.dto;
|
||||
|
||||
import cn.hangtag.module.oms.dal.dataobject.saleordersku.SaleOrderSkuDO;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
|
@ -12,6 +16,8 @@ import java.util.List;
|
|||
* @date 2024/10/02
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SaleOrderSkuDTO implements Serializable {
|
||||
|
||||
private String itemKey;
|
||||
|
|
@ -24,7 +30,7 @@ public class SaleOrderSkuDTO implements Serializable {
|
|||
/**
|
||||
* 订货数量
|
||||
*/
|
||||
private Long orderQty;
|
||||
private Integer orderQty;
|
||||
|
||||
/**
|
||||
* 草图设计id
|
||||
|
|
@ -47,11 +53,21 @@ public class SaleOrderSkuDTO implements Serializable {
|
|||
*/
|
||||
private String previewImage;
|
||||
|
||||
/**
|
||||
* 模板类型-字典 product_draft_template_type 1有模板 2无模板 3尺码唛
|
||||
*/
|
||||
private String productTemplateType;
|
||||
|
||||
/**
|
||||
* 动态属性json配置信息
|
||||
*/
|
||||
private String propInfo;
|
||||
|
||||
/**
|
||||
* 尺码信息
|
||||
*/
|
||||
private String labelSize;
|
||||
|
||||
/**
|
||||
* 动态属性 排序信息
|
||||
*/
|
||||
|
|
@ -63,5 +79,20 @@ public class SaleOrderSkuDTO implements Serializable {
|
|||
private SpecInfoDTO specInfo;
|
||||
|
||||
|
||||
|
||||
public SaleOrderSkuDTO(SaleOrderSkuDO saleOrderSkuDO) {
|
||||
this.itemKey = saleOrderSkuDO.getItemKey();
|
||||
this.productId = saleOrderSkuDO.getProductId();
|
||||
this.orderQty = saleOrderSkuDO.getOrderQty();
|
||||
this.draftDesignId = saleOrderSkuDO.getDraftDesignId();
|
||||
this.width = saleOrderSkuDO.getWidth().doubleValue();
|
||||
this.height = saleOrderSkuDO.getHeight().doubleValue();
|
||||
this.previewImage = saleOrderSkuDO.getPreviewImage();
|
||||
this.productTemplateType = saleOrderSkuDO.getProductTemplateType();
|
||||
this.propInfo = saleOrderSkuDO.getPropInfo();
|
||||
this.labelSize = saleOrderSkuDO.getLabelSize();
|
||||
String specInfo1 = saleOrderSkuDO.getSpecInfo();
|
||||
if(specInfo1 != null){
|
||||
this.specInfo = JSONUtil.toBean(specInfo1, SpecInfoDTO.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package cn.hangtag.module.oms.controller.admin.saleorder.front.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 销售订单跟单员vo
|
||||
*
|
||||
* @author YuanFeng
|
||||
* @date 2024/11/09
|
||||
*/
|
||||
@Data
|
||||
public class SaleOrderFollowerUserVO {
|
||||
|
||||
/**
|
||||
* system_users id
|
||||
*/
|
||||
@Schema(description = "用户Id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 跟单员名称
|
||||
* system_users username
|
||||
*/
|
||||
@Schema(description = "跟单员名称")
|
||||
private String username;
|
||||
|
||||
}
|
||||
|
|
@ -46,6 +46,9 @@ public class SaleOrderSkuSaveReqVO {
|
|||
@Schema(description = "规格 json完整信息")
|
||||
private String specInfo;
|
||||
|
||||
@Schema(description = "产品尺码")
|
||||
private String labelSize;
|
||||
|
||||
@Schema(description = "宽(mm)")
|
||||
private BigDecimal specSizeWidth;
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,11 @@ public class ProductInfoDO extends BaseDO {
|
|||
@TableField("spec_material")
|
||||
private String specMaterial;
|
||||
|
||||
/**
|
||||
* 模板类型-字典 product_draft_template_type 1有模板 2无模板 3尺码唛
|
||||
*/
|
||||
@TableField("template_type")
|
||||
private String templateType;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -159,6 +159,11 @@ public class SaleOrderDO extends BaseDO {
|
|||
*/
|
||||
private String deliveryRemark;
|
||||
|
||||
/**
|
||||
* 跟单员id system_user.id
|
||||
*/
|
||||
private String orderFollowerUser;
|
||||
|
||||
public SaleOrderDO(CreateSaleOrderDTO dto) {
|
||||
BeanUtil.copyProperties(dto, this,"bizdate","plansenddate");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,12 @@ public class SaleOrderEntryDO extends BaseDO {
|
|||
* 数量
|
||||
*/
|
||||
private Integer qty;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -72,6 +72,17 @@ public class SaleOrderSkuDO extends BaseDO {
|
|||
* 动态属性 json动态属性
|
||||
*/
|
||||
private String propInfo;
|
||||
|
||||
/**
|
||||
* 模板类型-字典 product_draft_template_type 1有模板 2无模板 3尺码唛
|
||||
*/
|
||||
private String productTemplateType;
|
||||
|
||||
/**
|
||||
* 尺码唛的 尺码信息
|
||||
*/
|
||||
private String labelSize;
|
||||
|
||||
/**
|
||||
* 规格 json完整信息
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import javax.validation.*;
|
|||
|
||||
import cn.hangtag.module.oms.controller.admin.common.vo.DataComparisonRespVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.front.dto.CreateSaleOrderDTO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.front.vo.SaleOrderFollowerUserVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.*;
|
||||
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderSummaryRespVO;
|
||||
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendReqVO;
|
||||
|
|
@ -107,9 +108,32 @@ public interface SaleOrderService {
|
|||
* @return {@link Long }
|
||||
*/
|
||||
Long placeOrder(CreateSaleOrderDTO dto);
|
||||
Long editOrder(Long id,CreateSaleOrderDTO dto);
|
||||
|
||||
public String getNewOrderCode();
|
||||
public String getNewOrderCode2();
|
||||
/**
|
||||
* 获取销售订单编码
|
||||
*
|
||||
* @return {@link String }
|
||||
*/
|
||||
String getNewOrderCode();
|
||||
|
||||
/**
|
||||
* 获取销售合同编码
|
||||
*
|
||||
* @return {@link String }
|
||||
*/
|
||||
String getNewContractCode2();
|
||||
|
||||
List<SaleOrderSkuDO> getSaleOrderSkuEntryListByEntryId(Long entryId);
|
||||
|
||||
List<SaleOrderFollowerUserVO> queryFollowerUserListByBrandId(String brandId);
|
||||
|
||||
|
||||
/**
|
||||
* 查询编辑订单
|
||||
*
|
||||
* @param id ID
|
||||
* @return {@link CreateSaleOrderDTO }
|
||||
*/
|
||||
CreateSaleOrderDTO queryEditOrder(Long id);
|
||||
}
|
||||
|
|
@ -4,14 +4,12 @@ import cn.hangtag.framework.common.exception.ServiceException;
|
|||
import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.hangtag.framework.common.pojo.PageResult;
|
||||
import cn.hangtag.framework.common.util.FuncUtil;
|
||||
import cn.hangtag.framework.common.util.http.HttpUtils;
|
||||
import cn.hangtag.framework.common.util.object.BeanUtils;
|
||||
import cn.hangtag.framework.common.util.validation.AssertUtil;
|
||||
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.hangtag.framework.security.core.LoginUser;
|
||||
import cn.hangtag.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.hangtag.module.oms.common.utils.NumberChineseFormatterUtils;
|
||||
import cn.hangtag.module.oms.common.utils.WKHtmlToPdfUtil;
|
||||
import cn.hangtag.module.oms.controller.admin.common.vo.DataComparisonRespVO;
|
||||
import cn.hangtag.module.oms.controller.admin.produceorder.vo.ProduceOrderSaveReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.product.vo.ProductPriceSaveReqVO;
|
||||
|
|
@ -19,6 +17,7 @@ import cn.hangtag.module.oms.controller.admin.salecontract.vo.SaleContractSaveRe
|
|||
import cn.hangtag.module.oms.controller.admin.saleorder.front.dto.CreateSaleOrderDTO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.front.dto.SaleOrderEntryItemDTO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.front.dto.SaleOrderSkuDTO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.front.vo.SaleOrderFollowerUserVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderPageReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRemarkReqVO;
|
||||
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderSaveReqVO;
|
||||
|
|
@ -50,6 +49,7 @@ import cn.hangtag.module.oms.service.produceorder.ProduceOrderService;
|
|||
import cn.hangtag.module.oms.service.product.ProductPriceService;
|
||||
import cn.hangtag.module.oms.service.productinfo.ProductInfoService;
|
||||
import cn.hangtag.module.oms.service.salecontract.SaleContractService;
|
||||
import cn.hangtag.module.oms.service.saleordersku.SaleOrderSkuService;
|
||||
import cn.hangtag.module.system.mq.message.mail.MailSendMessage;
|
||||
import cn.hangtag.module.system.service.mail.MailSendService;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
|
|
@ -62,6 +62,7 @@ import cn.hutool.core.util.IdUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.google.common.collect.Maps;
|
||||
|
|
@ -75,7 +76,6 @@ import org.thymeleaf.TemplateEngine;
|
|||
import org.thymeleaf.context.Context;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.*;
|
||||
|
|
@ -83,10 +83,7 @@ import java.math.BigDecimal;
|
|||
import java.net.URLEncoder;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
|
|
@ -112,6 +109,9 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
private SaleOrderEntryMapper saleOrderEntryMapper;
|
||||
@Resource
|
||||
private SaleOrderSkuMapper skuOrderSkuMapper;
|
||||
|
||||
@Resource
|
||||
private SaleOrderSkuService saleOrderSkuService;
|
||||
@Resource
|
||||
private ProduceOrderService produceOrderService;
|
||||
@Resource
|
||||
|
|
@ -638,18 +638,19 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
.materialId(itemDTO.getProductId())
|
||||
.materialName(itemDTO.getProductName())
|
||||
.qty(itemDTO.getOrderQty())
|
||||
.deliveryDate(FuncUtil.parseDate(itemDTO.getDeliveryDate())).build();
|
||||
.deliveryDate(FuncUtil.timeToLocalDate(itemDTO.getDeliveryDate())).build();
|
||||
|
||||
entryList.add(entry);
|
||||
List<SaleOrderSkuDTO> productSkuList = itemDTO.getProductSkuList();
|
||||
// sku
|
||||
for (SaleOrderSkuDTO saleOrderSkuDTO : productSkuList) {
|
||||
SaleOrderSkuDO saleOrderSkuDO = new SaleOrderSkuDO();
|
||||
BeanUtil.copyProperties(saleOrderSkuDTO,saleOrderSkuDO);
|
||||
BeanUtil.copyProperties(saleOrderSkuDTO,saleOrderSkuDO,"specInfo");
|
||||
saleOrderSkuDO.setSaleOrderId(order.getId());
|
||||
saleOrderSkuDO.setEntryId(entry.getId());
|
||||
saleOrderSkuDO.setProductTemplateType(saleOrderSkuDTO.getProductTemplateType());
|
||||
saleOrderSkuDO.setSpecInfo(JSONUtil.toJsonStr(saleOrderSkuDTO.getSpecInfo()));
|
||||
saleOrderSkuDO.setId(FuncUtil.getNextId());
|
||||
|
||||
skuList.add(saleOrderSkuDO);
|
||||
}
|
||||
|
||||
|
|
@ -662,6 +663,60 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
System.out.println(order);
|
||||
return order.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long editOrder(Long id,CreateSaleOrderDTO dto) {
|
||||
|
||||
SaleOrderDO saleOrderDO = checkEditOrder(id);
|
||||
// 校验订单
|
||||
SaleOrderDO order = new SaleOrderDO(dto);
|
||||
order.setId(saleOrderDO.getId());
|
||||
order = wrapperEntity(order, dto);
|
||||
// 不进行修改
|
||||
order.setOrderCode(saleOrderDO.getOrderCode());
|
||||
order.setContractCode(saleOrderDO.getContractCode());
|
||||
order.setBillno(saleOrderDO.getBillno());
|
||||
order.setCustomerId(saleOrderDO.getCustomerId());
|
||||
order.setBizdate(saleOrderDO.getBizdate());
|
||||
List<SaleOrderEntryItemDTO> saleOrderEntry = dto.getSaleOrderEntry();
|
||||
List<SaleOrderEntryDO> entryList = new ArrayList<>();
|
||||
List<SaleOrderSkuDO> skuList = new ArrayList<>();
|
||||
|
||||
// 删除之前的的订单条目
|
||||
deleteSaleOrderEntryByParentId(order.getId());
|
||||
saleOrderSkuService.delSkuByOrderId(order.getId());
|
||||
|
||||
// 转成订单条目
|
||||
for (SaleOrderEntryItemDTO itemDTO : saleOrderEntry) {
|
||||
SaleOrderEntryDO entry = SaleOrderEntryDO.builder()
|
||||
.id(FuncUtil.getNextId())
|
||||
.parentId(order.getId())
|
||||
.materialId(itemDTO.getProductId())
|
||||
.materialName(itemDTO.getProductName())
|
||||
.qty(itemDTO.getOrderQty())
|
||||
.deliveryDate(FuncUtil.timeToLocalDate(itemDTO.getDeliveryDate())).build();
|
||||
entryList.add(entry);
|
||||
List<SaleOrderSkuDTO> productSkuList = itemDTO.getProductSkuList();
|
||||
// sku
|
||||
for (SaleOrderSkuDTO saleOrderSkuDTO : productSkuList) {
|
||||
SaleOrderSkuDO saleOrderSkuDO = new SaleOrderSkuDO();
|
||||
BeanUtil.copyProperties(saleOrderSkuDTO,saleOrderSkuDO,"specInfo");
|
||||
saleOrderSkuDO.setSaleOrderId(order.getId());
|
||||
saleOrderSkuDO.setEntryId(entry.getId());
|
||||
saleOrderSkuDO.setProductTemplateType(saleOrderSkuDTO.getProductTemplateType());
|
||||
saleOrderSkuDO.setSpecInfo(JSONUtil.toJsonStr(saleOrderSkuDTO.getSpecInfo()));
|
||||
saleOrderSkuDO.setId(FuncUtil.getNextId());
|
||||
skuList.add(saleOrderSkuDO);
|
||||
}
|
||||
|
||||
}
|
||||
saleOrderMapper.updateById(order);
|
||||
saleOrderEntryMapper.insertBatch(entryList);
|
||||
skuOrderSkuMapper.insertBatch(skuList);
|
||||
updateCustomerInvoiceData(order);
|
||||
return order.getId();
|
||||
}
|
||||
private static final long codeId = 6L;
|
||||
private static final long saleContractCodeId = 7L;
|
||||
@Override
|
||||
|
|
@ -684,14 +739,14 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
}
|
||||
}
|
||||
@Override
|
||||
public String getNewOrderCode2() {
|
||||
public String getNewContractCode2() {
|
||||
String s = "";
|
||||
int count = 10;
|
||||
while (true){
|
||||
count --;
|
||||
try {
|
||||
s = CodingRulesUtils.generateCode(saleContractCodeId, false);
|
||||
checkCode2(null,s);
|
||||
checkSaleContractCode2(null,s);
|
||||
return s;
|
||||
}catch (ServiceException e){
|
||||
log.warn("重复或者下一个编码");
|
||||
|
|
@ -724,7 +779,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
}
|
||||
|
||||
|
||||
private void checkCode2(Long id,String code){
|
||||
private void checkSaleContractCode2(Long id, String code){
|
||||
if(FuncUtil.isNotEmpty(code)){
|
||||
LambdaQueryWrapper<SaleContractDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.select(SaleContractDO::getId,SaleContractDO::getBillno, BaseDO::getDeleted);
|
||||
|
|
@ -756,7 +811,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
order.setId(FuncUtil.getNextId());
|
||||
}
|
||||
order.setBizdate(LocalDateTime.now());
|
||||
order.setPlansenddate( FuncUtil.parseDate(dto.getPlansenddate()));
|
||||
order.setPlansenddate( FuncUtil.timeToLocalDate(dto.getPlansenddate()));
|
||||
// 设置订单状态
|
||||
order.setOrderStatus(SaleOrderStatusEnum.YXD.getValue());
|
||||
order.setBillStatus(BillStatusEnum.SUBMIT.getValue());
|
||||
|
|
@ -859,7 +914,12 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
private SaleContractSaveReqVO toSaleContractVO(SaleOrderDO saleOrder, List<SaleOrderEntryDO> entrys){
|
||||
CustomerDO customer = customerService.getCustomer(saleOrder.getCustomerId());
|
||||
SaleContractSaveReqVO saveReqVO = new SaleContractSaveReqVO();
|
||||
saveReqVO.setBillno(getNewOrderCode2());
|
||||
// 优先使用销售订单合同号
|
||||
String billno = saleOrder.getContractCode();
|
||||
if(FuncUtil.isEmpty(billno)){
|
||||
billno = getNewContractCode2();
|
||||
}
|
||||
saveReqVO.setBillno(billno);
|
||||
saveReqVO.setCustomerId(saleOrder.getCustomerId());
|
||||
saveReqVO.setCustomerName(customer.getName());
|
||||
saveReqVO.setCustomerBuyNo(saleOrder.getBillno());
|
||||
|
|
@ -896,6 +956,65 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
return skuOrderSkuMapper.selectListByEntryId(entryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SaleOrderFollowerUserVO> queryFollowerUserListByBrandId(String brandId) {
|
||||
// TODO 查询品牌下的所有跟单人员
|
||||
List<SaleOrderFollowerUserVO> res = new ArrayList<>();
|
||||
|
||||
// 测试数据
|
||||
res.add(new SaleOrderFollowerUserVO().setId(1L).setUsername("admin"));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateSaleOrderDTO queryEditOrder(Long id) {
|
||||
CreateSaleOrderDTO res = new CreateSaleOrderDTO();
|
||||
SaleOrderDO saleOrderDO = checkEditOrder(id);
|
||||
BeanUtil.copyProperties(saleOrderDO, res);
|
||||
LambdaQueryWrapper<SaleOrderEntryDO> entryQueryWrapper = new LambdaQueryWrapper<>();
|
||||
entryQueryWrapper.eq(SaleOrderEntryDO::getParentId, saleOrderDO.getId());
|
||||
entryQueryWrapper.eq(SaleOrderEntryDO::getDeleted, false);
|
||||
List<SaleOrderEntryDO> entryDOS = saleOrderEntryMapper.selectList(entryQueryWrapper);
|
||||
List<SaleOrderEntryItemDTO> saleOrderEntry = new ArrayList<>();
|
||||
for (SaleOrderEntryDO entryDO : entryDOS) {
|
||||
SaleOrderEntryItemDTO dto = new SaleOrderEntryItemDTO(entryDO);
|
||||
|
||||
// 获取产品信息
|
||||
|
||||
Long productId = dto.getProductId();
|
||||
ProductInfoDO productInfo = productInfoService.getProductInfo(productId);
|
||||
dto.setCover(productInfo.getCover());
|
||||
dto.setProductCode(productInfo.getCode());
|
||||
dto.setProductName(entryDO.getMaterialName());
|
||||
dto.setProducer(productInfo.getBrandName());
|
||||
dto.setCover(productInfo.getCover());
|
||||
dto.setDetails(productInfo.getDetails());
|
||||
dto.setUnit(entryDO.getUnit());
|
||||
// productId: row.id,
|
||||
// productCode: row.code,
|
||||
// productName: row.name,
|
||||
// producer: row.producer,
|
||||
// cover: row.cover,
|
||||
// unit: row.unit || 'pcs',
|
||||
|
||||
// sku list
|
||||
LambdaQueryWrapper<SaleOrderSkuDO> skuWrapper = new LambdaQueryWrapper<>();
|
||||
skuWrapper.eq(SaleOrderSkuDO::getSaleOrderId, saleOrderDO.getId());
|
||||
skuWrapper.eq(SaleOrderSkuDO::getDeleted, false);
|
||||
List<SaleOrderSkuDO> sukList = skuOrderSkuMapper.selectList(skuWrapper);
|
||||
List<SaleOrderSkuDTO> skus = new ArrayList<>();
|
||||
for (SaleOrderSkuDO saleOrderSkuDO : sukList) {
|
||||
SaleOrderSkuDTO toSaleOrderSkuDTO = new SaleOrderSkuDTO(saleOrderSkuDO);
|
||||
skus.add(toSaleOrderSkuDTO);
|
||||
}
|
||||
dto.setProductSkuList(skus);
|
||||
saleOrderEntry.add(dto);
|
||||
}
|
||||
res.setSaleOrderEntry(saleOrderEntry);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载ZIP压缩包(会对下载后的压缩包进行删除)
|
||||
*
|
||||
|
|
@ -933,4 +1052,16 @@ public class SaleOrderServiceImpl implements SaleOrderService {
|
|||
}
|
||||
}
|
||||
|
||||
private SaleOrderDO checkEditOrder(Long id){
|
||||
SaleOrderDO saleOrderDO = saleOrderMapper.selectById(id);
|
||||
AssertUtil.isEmpty(saleOrderDO, "订单不存在");
|
||||
String billStatus = saleOrderDO.getBillStatus();
|
||||
|
||||
boolean order1 = BillStatusEnum.isCanEditOrder(billStatus);
|
||||
BillStatusEnum byValue = BillStatusEnum.getByValue(billStatus);
|
||||
AssertUtil.isEmpty(byValue, "订单状态异常");
|
||||
AssertUtil.isTrue(!order1,byValue.getName()+"状态不允许修改" );
|
||||
return saleOrderDO;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
package cn.hangtag.module.oms.service.saleordersku;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.hangtag.module.oms.controller.admin.saleordersku.vo.*;
|
||||
import cn.hangtag.module.oms.dal.dataobject.saleordersku.SaleOrderSkuDO;
|
||||
import cn.hangtag.framework.common.pojo.PageResult;
|
||||
import cn.hangtag.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 销售订单产品属性表 Service 接口
|
||||
|
|
@ -36,6 +34,13 @@ public interface SaleOrderSkuService {
|
|||
*/
|
||||
void deleteSaleOrderSku(Long id);
|
||||
|
||||
/**
|
||||
* 通过销售订单ID删除销售订单SKU
|
||||
* oms_saleorder id
|
||||
* @param id ID
|
||||
*/
|
||||
int delSkuByOrderId(Long id);
|
||||
|
||||
/**
|
||||
* 获得销售订单产品属性表
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package cn.hangtag.module.oms.service.saleordersku;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
|
@ -55,6 +56,20 @@ public class SaleOrderSkuServiceImpl implements SaleOrderSkuService {
|
|||
saleOrderSkuMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delSkuByOrderId(Long orderId) {
|
||||
|
||||
LambdaQueryWrapper<SaleOrderSkuDO> skuWrapper = new LambdaQueryWrapper<>();
|
||||
skuWrapper.eq(SaleOrderSkuDO::getSaleOrderId, orderId);
|
||||
skuWrapper.eq(SaleOrderSkuDO::getDeleted, false);
|
||||
List<SaleOrderSkuDO> sukList = saleOrderSkuMapper.selectList(skuWrapper);
|
||||
List<Long> skus = new ArrayList<>();
|
||||
for (SaleOrderSkuDO saleOrderSkuDO : sukList) {
|
||||
skus.add(saleOrderSkuDO.getId());
|
||||
}
|
||||
return saleOrderSkuMapper.deleteBatchIds(skus);
|
||||
}
|
||||
|
||||
private void validateSaleOrderSkuExists(Long id) {
|
||||
if (saleOrderSkuMapper.selectById(id) == null) {
|
||||
throw exception(SALE_ORDER_SKU_NOT_EXISTS);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="updateVisible(false)">取 消</el-button>
|
||||
<el-button type="primary" @click="submit">批稿</el-button>
|
||||
<el-button @click="updateVisible(false)">{{t("designInfo.cancelText")}}</el-button>
|
||||
<el-button type="primary" @click="submit">{{ t("designInfo.auditSubmitText") }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
|
@ -24,7 +24,8 @@ import {ElAlert} from "element-plus";
|
|||
import {reactive, computed, watch} from 'vue'
|
||||
import {calculateVectorDifference} from "@/components/DraftDesign/utils/FuncUtil";
|
||||
import {useMessage} from "@/hooks/web/useMessage";
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
const emit = defineEmits(['update:visible', 'submit'])
|
||||
const designPropEditRef = ref();
|
||||
const that = reactive({
|
||||
|
|
@ -61,7 +62,7 @@ const previewByDraftDesignId = (id: string | number,prop={})=>{
|
|||
},100)
|
||||
}
|
||||
const submit = ()=>{
|
||||
useMessage().confirm("是否提交?").then(async (r) => {
|
||||
useMessage().confirm(t('designInfo.auditTips')).then(async (r) => {
|
||||
const res = await designPropEditRef.value.getPropInfo()
|
||||
emit("submit",res);
|
||||
updateVisible(false)
|
||||
|
|
|
|||
|
|
@ -1,88 +1,82 @@
|
|||
<!-- eslint-disable vue/this-in-template -->
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
:class ="{ 'hidden-div': that.hideCreate}"
|
||||
:id="that.svgId"
|
||||
:style="{
|
||||
width: `${imageSize.width * 6}px`,
|
||||
height: `${imageSize.height * 6}px`,
|
||||
}">
|
||||
<div v-if="that.previewUrl" v-html="that.previewUrl" >
|
||||
</div>
|
||||
</div>
|
||||
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
|
||||
<div>
|
||||
|
||||
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
|
||||
<span>
|
||||
仅供参考(for reference only)
|
||||
</span>
|
||||
<div style="padding-bottom: 4px">
|
||||
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
|
||||
<el-button
|
||||
v-show="!that.reView"
|
||||
style="margin: 8px"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="updateDesign">
|
||||
<span>更新</span>
|
||||
<span
|
||||
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
|
||||
that.changeCount > 0 ? '*' : ''
|
||||
}}</span>
|
||||
</el-button>
|
||||
<div style="padding-bottom: 4px">
|
||||
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
|
||||
<el-button
|
||||
v-show="!that.reView"
|
||||
style="margin: 8px"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="updateDesign">
|
||||
<span>更新</span>
|
||||
<span
|
||||
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
|
||||
that.changeCount > 0 ? '*' : ''
|
||||
}}</span>
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<el-alert
|
||||
title="按住鼠标左键进行拖动,按住Ctrl 滚动鼠标进行缩小放放大"
|
||||
type="info" effect="dark"/>
|
||||
</div>
|
||||
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.width}mm`">
|
||||
</div>
|
||||
<div>
|
||||
<el-alert
|
||||
title="按住鼠标左键进行拖动,按住Ctrl 滚动鼠标进行缩小放放大"
|
||||
type="info" effect="dark"/>
|
||||
</div>
|
||||
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.width}mm`">
|
||||
<span>
|
||||
宽:{{ that.sizeInfo.width }}mm 高{{ that.sizeInfo.height }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<div
|
||||
:class ="{ 'hidden-div': false }" style="width:100%;height: 580px; border: 1px solid #090805">
|
||||
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div style="display: flex;">
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<div
|
||||
:class="{ 'hidden-div': false }"
|
||||
style="width:100%;height: 580px; border: 1px solid #090805">
|
||||
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div style="display: flex;">
|
||||
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-form label-width="180px">
|
||||
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
|
||||
<div class="flex ml-3">
|
||||
<div>
|
||||
<el-select class="min-w-100" v-model="that.draftDesignId" @change="changeType">
|
||||
<el-option
|
||||
v-for="(item) in that.draftDesignList"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div style="width: 100%" v-if="that.propOrderByList && that.propOrderByList.length > 0">
|
||||
<el-scrollbar height="600px">
|
||||
<el-form label-width="180px">
|
||||
<el-form-item
|
||||
v-for="(tmp) in that.propOrderByList"
|
||||
:key="tmp.key"
|
||||
:label="getLabelName(that.propInfo[tmp.key])">
|
||||
<div
|
||||
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
|
||||
<div
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-form label-width="180px">
|
||||
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
|
||||
<div class="flex ml-3">
|
||||
<div>
|
||||
<el-select class="min-w-100" v-model="that.draftDesignId"
|
||||
@change="changeType">
|
||||
<el-option
|
||||
v-for="(item) in that.draftDesignList"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div style="width: 100%"
|
||||
v-if="that.propOrderByList && that.propOrderByList.length > 0">
|
||||
<el-scrollbar height="600px">
|
||||
<el-form label-width="180px">
|
||||
<el-form-item
|
||||
v-for="(tmp) in that.propOrderByList"
|
||||
:key="tmp.key"
|
||||
:label="getLabelName(that.propInfo[tmp.key])">
|
||||
<div
|
||||
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
|
||||
<div
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<span>
|
||||
<i
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
|
|
@ -91,56 +85,56 @@
|
|||
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
|
||||
</span>
|
||||
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(-1,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
|
||||
@change="changeData(0,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(-1,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
|
||||
@change="changeData(0,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!that.propInfo[tmp.key].isCombo">
|
||||
<div
|
||||
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index"
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<div v-else-if="!that.propInfo[tmp.key].isCombo">
|
||||
<div
|
||||
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index"
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<span>
|
||||
<i
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
|
|
@ -148,119 +142,154 @@
|
|||
style="font-size: 20px"> </i>
|
||||
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
|
||||
</span>
|
||||
<el-autocomplete
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
:fetch-suggestions="querySearch"
|
||||
clearable
|
||||
class="inline-input w-50"
|
||||
placeholder="Please Input"
|
||||
@change="changeData"
|
||||
@select="changeData"
|
||||
/>
|
||||
<el-autocomplete
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
:fetch-suggestions="querySearch"
|
||||
clearable
|
||||
class="inline-input w-50"
|
||||
placeholder="Please Input"
|
||||
@change="changeData"
|
||||
@select="changeData"
|
||||
/>
|
||||
|
||||
<el-select-v2
|
||||
v-else
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(index,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
<el-select-v2
|
||||
v-else
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(index,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
|
||||
@change="changeData(index,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
|
||||
@change="changeData(index,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
|
||||
<div
|
||||
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index" style="display: flex">
|
||||
<div class="img-box" v-if="img.url">
|
||||
<div style="display: flex">
|
||||
<img :src="img.url" width="60px" height="60px"/>
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div style="display: flex;">
|
||||
<img :src="item.url" width="30px" height="30px"/>
|
||||
<span>
|
||||
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
|
||||
<div
|
||||
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index" style="display: flex">
|
||||
<div class="img-box" v-if="img.url">
|
||||
<div style="display: flex">
|
||||
<img :src="img.url" width="60px" height="60px"/>
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div style="display: flex;">
|
||||
<img :src="item.url" width="30px" height="30px"/>
|
||||
<span>
|
||||
{{ item.label }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-select-v2>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="img.label">
|
||||
<el-input v-model="img.label" disabled/>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-select-v2>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="img.label">
|
||||
<el-input v-model="img.label" disabled/>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-col>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class ="{ 'hidden-div': that.hideCreate}"
|
||||
:id="that.svgId"
|
||||
:style="{
|
||||
position: that.hideCreate ? 'fixed' : 'relative',
|
||||
display: `flex`,
|
||||
flexDirection: `column`,
|
||||
width: `${previewSize.width}px`,
|
||||
height: `${previewSize.height}px`,
|
||||
}">
|
||||
|
||||
<div v-if="that.previewUrl"
|
||||
:style="{
|
||||
width: `${that.svgWidth+2}px`,
|
||||
height: `${that.svgHeight+2}px`,
|
||||
backgroundColor: (that.pageConfig.background && that.pageConfig.background.areaColor) || '',
|
||||
border: '1px solid #00ff00',
|
||||
position: `absolute`,
|
||||
top: `0`,
|
||||
left: `0`,
|
||||
}"
|
||||
>
|
||||
|
||||
<div>
|
||||
<div v-if="false" style="color: #ff0000;">w:{{imageSize.width}} h:{{imageSize.height}}</div>
|
||||
<span style="color: #ff0000;writing-mode: vertical-rl; text-orientation: upright;">
|
||||
*仅供参考
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="that.previewUrl" v-html="that.previewUrl" >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="DynamicPropConfig">
|
||||
|
|
@ -278,13 +307,14 @@ import {useLocaleStore} from "@/store/modules/locale";
|
|||
import {ProductInfoApi} from "@/api/oms/productinfo";
|
||||
import domtoimage from 'dom-to-image';
|
||||
import {usePageLoading} from "@/hooks/web/usePageLoading";
|
||||
const { loadStart, loadDone } = usePageLoading()
|
||||
|
||||
const {loadStart, loadDone} = usePageLoading()
|
||||
// 动态属性配置
|
||||
const localeStore = useLocaleStore()
|
||||
const emit = defineEmits(['change', 'initSucceed'])
|
||||
const draftDesignEditRef = ref()
|
||||
const that = reactive({
|
||||
svgId: "svg_"+Math.random().toString(36).substring(2),
|
||||
svgId: "svg_" + Math.random().toString(36).substring(2),
|
||||
hideCreate: true,
|
||||
pageLoading: {},
|
||||
propInfo: {
|
||||
|
|
@ -305,7 +335,7 @@ const that = reactive({
|
|||
draftDesignList: [],
|
||||
draftDesignId: '',
|
||||
reView: false,
|
||||
currentZoom: 6,
|
||||
currentZoom: 10,
|
||||
changeCount: 0,
|
||||
previewUrl: "",
|
||||
previewData: '',
|
||||
|
|
@ -318,8 +348,16 @@ const that = reactive({
|
|||
},
|
||||
data: {},
|
||||
show: false,
|
||||
svgHeight: 0,
|
||||
svgWidth: 0,
|
||||
})
|
||||
|
||||
const previewSize = computed(()=>{
|
||||
return {
|
||||
width: imageSize.value.width * 10,
|
||||
height: imageSize.value.height * 10
|
||||
}
|
||||
})
|
||||
const currentLocale = computed(() => localeStore.getCurrentLocale)
|
||||
watch(() => that.currentZoom, () => {
|
||||
showPng();
|
||||
|
|
@ -331,8 +369,8 @@ const querySearch = (queryString: string, cb: any) => {
|
|||
}) : that.ingredientInfoList
|
||||
cb(results)
|
||||
}
|
||||
const imageSize =computed(()=>{
|
||||
if(that.sizeInfo){
|
||||
const imageSize = computed(() => {
|
||||
if (that.sizeInfo) {
|
||||
return {
|
||||
width: that.sizeInfo.width,
|
||||
height: that.sizeInfo.height
|
||||
|
|
@ -383,7 +421,6 @@ const changeData = (index: number, key: string) => {
|
|||
str = ''
|
||||
}
|
||||
const value = `${mapping[j].value}`.replaceAll('${r}', str)
|
||||
console.log("value",value)
|
||||
that.propInfo[key].dataInfo[i].label = value
|
||||
break;
|
||||
}
|
||||
|
|
@ -447,27 +484,33 @@ const getIngredientInfoListByType = (type) => {
|
|||
return that.ingredientInfoList.filter(item => item.type === type)
|
||||
}
|
||||
const uploadFile = async (fileName) => {
|
||||
return new Promise((resolve, reject)=>{
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let svgElement = document.getElementById(that.svgId);
|
||||
domtoimage.toBlob(svgElement).then((blob) => {
|
||||
FileApi.updateFile({ file: blob })
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
resolve({
|
||||
...res,
|
||||
filename: fileName
|
||||
})
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
}) .catch((res) => {
|
||||
reject(res)
|
||||
})
|
||||
}).catch(function (error) {
|
||||
console.error('转换或上传过程中出现错误:', error);
|
||||
});
|
||||
});
|
||||
let svgElement = document.getElementById(that.svgId);
|
||||
domtoimage.toBlob(svgElement,{
|
||||
width: that.svgWidth+5,
|
||||
height: that.svgHeight+5,
|
||||
type: 'image/jpeg',
|
||||
quality: 1
|
||||
}).then((blob) => {
|
||||
const file = new File([blob], fileName, { type: 'image/jpeg' });
|
||||
FileApi.updateFile({file: file})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
resolve({
|
||||
...res,
|
||||
filename: fileName
|
||||
})
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
}).catch((res) => {
|
||||
reject(res)
|
||||
})
|
||||
}).catch(function (error) {
|
||||
console.error('转换或上传过程中出现错误:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const deleteList = (item, index) => {
|
||||
|
|
@ -629,7 +672,6 @@ const updateDesign = () => {
|
|||
const changeType = () => {
|
||||
previewByDraftDesignId(that.draftDesignId, that.propInfo)
|
||||
}
|
||||
|
||||
const getPropInfo = () => {
|
||||
|
||||
that.pageLoading = ElLoading.service({
|
||||
|
|
@ -643,26 +685,42 @@ const getPropInfo = () => {
|
|||
draftDesignEditRef.value.toSVGData((url) => {
|
||||
that.previewUrl = url
|
||||
that.hideCreate = false;
|
||||
// 年月日
|
||||
const date = new Date();
|
||||
const randChar = Math.random().toString(36).slice(-6);
|
||||
const fileName = `${date.getFullYear()}${ (date.getMonth() + 1)}${ date.getDate()}_${that.draftDesignId }_${randChar}_稿.png`;
|
||||
// 文件上传
|
||||
uploadFile(fileName).then(res =>{
|
||||
that.previewData = res.data;
|
||||
that.hideCreate = true;
|
||||
that.previewUrl =""
|
||||
const info = draftDesignEditRef.value.getPropInfo();
|
||||
that.pageLoading.close()
|
||||
resolve({
|
||||
draftDesignData: draftDesignEditRef.value.getJson(),
|
||||
propOrderByList: info.propOrderByList,
|
||||
// 设计稿id
|
||||
draftDesignId: that.draftDesignId,
|
||||
previewImage: that.previewData,
|
||||
propInfo: that.propInfo
|
||||
setTimeout(()=>{
|
||||
const el = document.querySelector(`#${that.svgId} g`);
|
||||
el.setAttribute("transform",'matrix(1,0,0,1,0,0)');
|
||||
|
||||
document.querySelector(`#${that.svgId} svg`).style.position = 'absolute';
|
||||
document.querySelector(`#${that.svgId} svg`).style.top = '-40%';
|
||||
|
||||
const dom = document.querySelector(`#${that.svgId} svg .x6-graph-svg-viewport`).getBoundingClientRect()
|
||||
const svgDom = document.querySelector(`#${that.svgId} svg`).getBoundingClientRect()
|
||||
that.svgHeight = dom.height;
|
||||
that.svgWidth = dom.width;
|
||||
document.querySelector(`#${that.svgId} svg`).style.left = `${svgDom.left - dom.left}px`;
|
||||
document.querySelector(`#${that.svgId} svg`).style.top = `${svgDom.top - dom.top}px`;
|
||||
// that.pageLoading.close()
|
||||
// 年月日
|
||||
const date = new Date();
|
||||
const randChar = Math.random().toString(36).slice(-6);
|
||||
const fileName = `${date.getFullYear()}${(date.getMonth() + 1)}${date.getDate()}_${that.draftDesignId}_${randChar}_稿.png`;
|
||||
// 文件上传
|
||||
uploadFile(fileName).then(res => {
|
||||
that.previewData = res.data;
|
||||
that.hideCreate = true;
|
||||
that.previewUrl = ""
|
||||
const info = draftDesignEditRef.value.getPropInfo();
|
||||
that.pageLoading.close()
|
||||
resolve({
|
||||
draftDesignData: draftDesignEditRef.value.getJson(),
|
||||
propOrderByList: info.propOrderByList,
|
||||
// 设计稿id
|
||||
draftDesignId: that.draftDesignId,
|
||||
previewImage: that.previewData,
|
||||
propInfo: that.propInfo
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
}, {
|
||||
widthScale: 6,
|
||||
heightScale: 6
|
||||
|
|
|
|||
|
|
@ -727,6 +727,7 @@ const toSVGData = (callback: (url: string) => void, options?: {
|
|||
height: number,
|
||||
widthScale: number,
|
||||
heightScale: number,
|
||||
backgroundColor: String,
|
||||
padding: {
|
||||
top: number,
|
||||
left: number,
|
||||
|
|
@ -735,23 +736,23 @@ const toSVGData = (callback: (url: string) => void, options?: {
|
|||
}
|
||||
}) => {
|
||||
|
||||
let widthScale = options && options.widthScale ? options.widthScale : 5
|
||||
let heightScale = options && options.heightScale ? options.heightScale : 5
|
||||
|
||||
let widthScale = 20 // options && options.widthScale ? options.widthScale : 5
|
||||
let heightScale = 20 // options && options.heightScale ? options.heightScale : 5
|
||||
graph.toSVG((dataUri) => {
|
||||
that.previewUrl = dataUri;
|
||||
callback(that.previewUrl)
|
||||
}, {
|
||||
copyStyles: true,
|
||||
viewBox: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: that.pageConfig.width * (widthScale/2),
|
||||
height: that.pageConfig.height * (heightScale/2),
|
||||
},
|
||||
preserveDimensions: {
|
||||
width: that.pageConfig.width * (widthScale),
|
||||
height: that.pageConfig.height * (heightScale),
|
||||
},
|
||||
preserveDimensions:{
|
||||
width: that.pageConfig.width * (widthScale),
|
||||
height: that.pageConfig.height * (heightScale),
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
const setPropList = (propDataInfo) => {
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ export enum DICT_TYPE {
|
|||
COMMON_STATUS = 'common_status',
|
||||
TERMINAL = 'terminal', // 终端
|
||||
LANGUAGE_LOCALE = 'language_locale', // 地区语言标识
|
||||
PRODUCT_DRAFT_TEMPLATE_TYPE = 'product_draft_template_type', // 地区语言标识
|
||||
BRAND_INDUSTRY_FIELD = 'brand_industry_field',
|
||||
DATE_INTERVAL = 'date_interval', // 数据间隔
|
||||
// ========== SYSTEM 模块 ==========
|
||||
|
|
|
|||
|
|
@ -90,7 +90,22 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="关联设计稿" prop="draftDesignDataId">
|
||||
<el-row>
|
||||
<el-col :span="12" :xs="24">
|
||||
<el-form-item label="模板类型" prop="templateType">
|
||||
<el-select v-model="formData.templateType" placeholder="模板类型">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.PRODUCT_DRAFT_TEMPLATE_TYPE)"
|
||||
:key="`${dict.value}`"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-form-item label="关联设计稿" v-if="formData.templateType === '1'" prop="draftDesignDataId">
|
||||
<div style="width: calc(100% - 20px);">
|
||||
<el-button @click="addRow">添加</el-button>
|
||||
<el-scrollbar max-height="400px">
|
||||
|
|
@ -98,6 +113,7 @@
|
|||
<el-table
|
||||
:data="that.draftDesignList"
|
||||
:stripe="true"
|
||||
empty-text="无设计稿,点击添加进行关联设计稿"
|
||||
:show-overflow-tooltip="true">
|
||||
<el-table-column width="55">
|
||||
<template #header>
|
||||
|
|
@ -247,6 +263,7 @@ import {ProductInfoApi, ProductInfoVO} from '@/api/oms/productinfo'
|
|||
import {ProductProcessApi} from '@/api/oms/productprocess'
|
||||
import DraftDesignDataListDialog from "@/components/Dialog/src/DraftDesignDataListDialog/index.vue";
|
||||
import BrandDataListDialog from "@/components/Dialog/src/BrandDataListDialog/index.vue";
|
||||
import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
|
||||
|
||||
/** 产品资料 表单 */
|
||||
defineOptions({name: 'ProductInfoForm'})
|
||||
|
|
@ -275,13 +292,14 @@ const formData = ref({
|
|||
specSizeHeight: 0,
|
||||
specSizeThk: 0,
|
||||
specMaterial: '',
|
||||
templateType: '1',
|
||||
})
|
||||
|
||||
const that = reactive({
|
||||
brandId: undefined,
|
||||
draftDesignList: [{
|
||||
remark: '',
|
||||
label: '',
|
||||
label: '默认',
|
||||
id: ''
|
||||
}],
|
||||
updateProcess: false,
|
||||
|
|
@ -404,10 +422,6 @@ const submitForm = async () => {
|
|||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
if (that.draftDesignList.length === 0) {
|
||||
message.error('请选择关联的设计稿')
|
||||
return;
|
||||
}
|
||||
// 校验关联设计稿
|
||||
let countInfo = {};
|
||||
let ids = [];
|
||||
|
|
@ -458,12 +472,14 @@ const submitForm = async () => {
|
|||
|
||||
data.draftDesignList = JSON.stringify(that.draftDesignList)
|
||||
// 作为默认的设计稿
|
||||
data.draftDesignDataId = ids.join(",");
|
||||
if(ids.length > 0){
|
||||
data.draftDesignDataId = ids.join(",");
|
||||
}
|
||||
if (formType.value === 'create') {
|
||||
await ProductInfoApi.createProductInfo(data as ProductInfoVO)
|
||||
await ProductInfoApi.createProductInfo(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ProductInfoApi.updateProductInfo(data as ProductInfoVO)
|
||||
await ProductInfoApi.updateProductInfo(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
|
|
@ -510,12 +526,9 @@ const resetForm = () => {
|
|||
specSizeHeight: 0,
|
||||
specSizeThk: 0,
|
||||
specMaterial: '',
|
||||
templateType: '1',
|
||||
}
|
||||
that.draftDesignList = [{
|
||||
remark: '',
|
||||
label: '默认',
|
||||
id: ''
|
||||
}]
|
||||
that.draftDesignList = []
|
||||
that.processInfoList =[{
|
||||
key: Math.random().toString(36).substring(2, 6),
|
||||
id: null, // id
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@
|
|||
v-hasPermi="['oms:product-info:update']"
|
||||
:disabled="!scope.row.draftDesignDataId"
|
||||
>
|
||||
预览稿件
|
||||
{{scope.row.draftDesignDataId ? '预览稿件' : '未使用稿件'}}
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export const SaleOrderApi = {
|
|||
return await request.get({ url: `/oms/app/sale-order/page`, params })
|
||||
},
|
||||
|
||||
|
||||
// 查询销售订单详情
|
||||
getSaleOrder: async (id: number) => {
|
||||
return await request.get({ url: `/oms/app/sale-order/get?id=` + id })
|
||||
|
|
@ -50,6 +51,15 @@ export const SaleOrderApi = {
|
|||
return await request.download({ url: `/oms/app/sale-order/export-excel`, params })
|
||||
},
|
||||
|
||||
// 获取品牌下 所有跟单员
|
||||
getFollowerUser: async (brandId:string) => {
|
||||
return await request.get({ url: `/oms/app/sale-order/follower-user/${brandId}` })
|
||||
},
|
||||
// 获取销售合同号
|
||||
getContractCode: async () => {
|
||||
return await request.get({ url: `/oms/app/sale-order/contract-code` })
|
||||
},
|
||||
|
||||
// ==================== 子表(销售订单明细) ====================
|
||||
|
||||
// 获得销售订单明细列表
|
||||
|
|
@ -109,4 +119,12 @@ export const SaleOrderApi = {
|
|||
placeOrder: async (data: any) => {
|
||||
return await request.post({ url: `/front/oms/sale-order/placeOrder`, data })
|
||||
},
|
||||
// 查询编辑订单
|
||||
queryEditById: async (id: string) => {
|
||||
return await request.get({ url: `/front/oms/sale-order/details/${id}` })
|
||||
},
|
||||
// 修改订单
|
||||
editOrder: async (id: string,data: any) => {
|
||||
return await request.post({ url: `/front/oms/sale-order/editOrder/${id}`,data})
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
import { AddressApi } from '@/api/oms/customer/address'
|
||||
import { rules, allSchemas } from './config.data'
|
||||
import {defaultProps} from "@/utils/tree";
|
||||
import {UPDATE_ADDRESS} from "@/constants/EmitEventName";
|
||||
import {UPDATE_ADDRESS_EVENT} from "@/constants/EmitEventName";
|
||||
import {useEmitt} from "@/hooks/web/useEmitt";
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
|
@ -85,7 +85,7 @@ const submitForm = async () => {
|
|||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
emitter.emit(UPDATE_ADDRESS,{
|
||||
emitter.emit(UPDATE_ADDRESS_EVENT,{
|
||||
...data
|
||||
})
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ import DataForm from './DataForm.vue'
|
|||
import {AddressApi} from "@/api/oms/customer/address";
|
||||
import {usePageLoading} from "@/hooks/web/usePageLoading";
|
||||
import {useEmitt} from "@/hooks/web/useEmitt";
|
||||
import {UPDATE_ADDRESS} from "@/constants/EmitEventName";
|
||||
import {UPDATE_ADDRESS_EVENT} from "@/constants/EmitEventName";
|
||||
|
||||
/** 稿件图片库 */
|
||||
defineOptions({name: 'AddressListDialog'})
|
||||
|
|
@ -187,7 +187,7 @@ const setDefault = (id: number)=>{
|
|||
pageLoading.loadStart();
|
||||
AddressApi.setDefaultAddress(id).then(res=>{
|
||||
useMessage().success(t('common.success'))
|
||||
emitter.emit(UPDATE_ADDRESS,{
|
||||
emitter.emit(UPDATE_ADDRESS_EVENT,{
|
||||
id: id
|
||||
})
|
||||
getList();
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="updateVisible(false)">取 消</el-button>
|
||||
<el-button type="primary" @click="submit">批稿</el-button>
|
||||
<el-button @click="updateVisible(false)">{{t("designInfo.cancelText")}}</el-button>
|
||||
<el-button type="primary" @click="submit">{{ t("designInfo.auditSubmitText") }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
|
@ -24,7 +24,8 @@ import {ElAlert} from "element-plus";
|
|||
import {reactive, computed, watch} from 'vue'
|
||||
import {calculateVectorDifference} from "@/components/DraftDesign/utils/FuncUtil";
|
||||
import {useMessage} from "@/hooks/web/useMessage";
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
const emit = defineEmits(['update:visible', 'submit'])
|
||||
const designPropEditRef = ref();
|
||||
const that = reactive({
|
||||
|
|
@ -61,7 +62,7 @@ const previewByDraftDesignId = (id: string | number,prop={})=>{
|
|||
},100)
|
||||
}
|
||||
const submit = ()=>{
|
||||
useMessage().confirm("是否提交?").then(async (r) => {
|
||||
useMessage().confirm(t('designInfo.auditTips')).then(async (r) => {
|
||||
const res = await designPropEditRef.value.getPropInfo()
|
||||
emit("submit",res);
|
||||
updateVisible(false)
|
||||
|
|
|
|||
|
|
@ -1,88 +1,82 @@
|
|||
<!-- eslint-disable vue/this-in-template -->
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
:class ="{ 'hidden-div': that.hideCreate}"
|
||||
:id="that.svgId"
|
||||
:style="{
|
||||
width: `${imageSize.width * 6}px`,
|
||||
height: `${imageSize.height * 6}px`,
|
||||
}">
|
||||
<div v-if="that.previewUrl" v-html="that.previewUrl" >
|
||||
</div>
|
||||
</div>
|
||||
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
|
||||
<div>
|
||||
|
||||
<div style="max-height: 90vh; overflow:auto;" v-loading="loading">
|
||||
<span>
|
||||
仅供参考(for reference only)
|
||||
</span>
|
||||
<div style="padding-bottom: 4px">
|
||||
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
|
||||
<el-button
|
||||
v-show="!that.reView"
|
||||
style="margin: 8px"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="updateDesign">
|
||||
<span>更新</span>
|
||||
<span
|
||||
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
|
||||
that.changeCount > 0 ? '*' : ''
|
||||
}}</span>
|
||||
</el-button>
|
||||
<div style="padding-bottom: 4px">
|
||||
<el-checkbox style="margin: 8px" v-model="that.reView">实时预览</el-checkbox>
|
||||
<el-button
|
||||
v-show="!that.reView"
|
||||
style="margin: 8px"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="updateDesign">
|
||||
<span>更新</span>
|
||||
<span
|
||||
style="color: #ff0000;font-size: 20px; padding-left: 4px">{{
|
||||
that.changeCount > 0 ? '*' : ''
|
||||
}}</span>
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<el-alert
|
||||
title="按住鼠标左键进行拖动,按住Ctrl 滚动鼠标进行缩小放放大"
|
||||
type="info" effect="dark"/>
|
||||
</div>
|
||||
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.width}mm`">
|
||||
</div>
|
||||
<div>
|
||||
<el-alert
|
||||
title="按住鼠标左键进行拖动,按住Ctrl 滚动鼠标进行缩小放放大"
|
||||
type="info" effect="dark"/>
|
||||
</div>
|
||||
<div v-if="that.sizeInfo" :title="`${that.sizeInfo.width}mm`">
|
||||
<span>
|
||||
宽:{{ that.sizeInfo.width }}mm 高{{ that.sizeInfo.height }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<div
|
||||
:class ="{ 'hidden-div': false }" style="width:100%;height: 580px; border: 1px solid #090805">
|
||||
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div style="display: flex;">
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<div
|
||||
:class="{ 'hidden-div': false }"
|
||||
style="width:100%;height: 580px; border: 1px solid #090805">
|
||||
<DraftDesign ref="draftDesignEditRef" @init-succeed="initSucceed"/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div style="display: flex;">
|
||||
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-form label-width="180px">
|
||||
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
|
||||
<div class="flex ml-3">
|
||||
<div>
|
||||
<el-select class="min-w-100" v-model="that.draftDesignId" @change="changeType">
|
||||
<el-option
|
||||
v-for="(item) in that.draftDesignList"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div style="width: 100%" v-if="that.propOrderByList && that.propOrderByList.length > 0">
|
||||
<el-scrollbar height="600px">
|
||||
<el-form label-width="180px">
|
||||
<el-form-item
|
||||
v-for="(tmp) in that.propOrderByList"
|
||||
:key="tmp.key"
|
||||
:label="getLabelName(that.propInfo[tmp.key])">
|
||||
<div
|
||||
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
|
||||
<div
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-form label-width="180px">
|
||||
<el-form-item label="风格样式" v-show="that.draftDesignList.length > 1">
|
||||
<div class="flex ml-3">
|
||||
<div>
|
||||
<el-select class="min-w-100" v-model="that.draftDesignId"
|
||||
@change="changeType">
|
||||
<el-option
|
||||
v-for="(item) in that.draftDesignList"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div style="width: 100%"
|
||||
v-if="that.propOrderByList && that.propOrderByList.length > 0">
|
||||
<el-scrollbar height="600px">
|
||||
<el-form label-width="180px">
|
||||
<el-form-item
|
||||
v-for="(tmp) in that.propOrderByList"
|
||||
:key="tmp.key"
|
||||
:label="getLabelName(that.propInfo[tmp.key])">
|
||||
<div
|
||||
v-if="that.propInfo[tmp.key].multiLanguage && that.propInfo[tmp.key].shape === ShapeType.vueTextCell">
|
||||
<div
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<span>
|
||||
<i
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
|
|
@ -91,56 +85,56 @@
|
|||
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
|
||||
</span>
|
||||
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(-1,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
|
||||
@change="changeData(0,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(-1,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].ratio"
|
||||
@change="changeData(0,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!that.propInfo[tmp.key].isCombo">
|
||||
<div
|
||||
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index"
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<div v-else-if="!that.propInfo[tmp.key].isCombo">
|
||||
<div
|
||||
v-for="(text,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index"
|
||||
style="padding: 4px">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<span>
|
||||
<i
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
|
|
@ -148,119 +142,154 @@
|
|||
style="font-size: 20px"> </i>
|
||||
<i v-else class="icon-lk_cell_add" style="font-size: 20px"> </i>
|
||||
</span>
|
||||
<el-autocomplete
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
:fetch-suggestions="querySearch"
|
||||
clearable
|
||||
class="inline-input w-50"
|
||||
placeholder="Please Input"
|
||||
@change="changeData"
|
||||
@select="changeData"
|
||||
/>
|
||||
<el-autocomplete
|
||||
v-if="that.propInfo[tmp.key].canInput"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
:fetch-suggestions="querySearch"
|
||||
clearable
|
||||
class="inline-input w-50"
|
||||
placeholder="Please Input"
|
||||
@change="changeData"
|
||||
@select="changeData"
|
||||
/>
|
||||
|
||||
<el-select-v2
|
||||
v-else
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(index,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
<el-select-v2
|
||||
v-else
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].showLabel"
|
||||
filterable
|
||||
:options="getIngredientInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeData(index,tmp.key)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
/>
|
||||
<div v-if="that.propInfo[tmp.key].groupType === '1'">
|
||||
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
|
||||
@change="changeData(index,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="display: flex;align-items: center; margin-left: 10px; width: 220px">
|
||||
<el-row>
|
||||
<el-col span="4">
|
||||
<div>占比</div>
|
||||
</el-col>
|
||||
<el-col span="14">
|
||||
<el-input-number
|
||||
:min="-1" :max="100"
|
||||
v-model="that.propInfo[tmp.key].dataInfo[index].ratio"
|
||||
@change="changeData(index,tmp.key)"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col span="4">
|
||||
<div> %</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
|
||||
<div
|
||||
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index" style="display: flex">
|
||||
<div class="img-box" v-if="img.url">
|
||||
<div style="display: flex">
|
||||
<img :src="img.url" width="60px" height="60px"/>
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div style="display: flex;">
|
||||
<img :src="item.url" width="30px" height="30px"/>
|
||||
<span>
|
||||
<div v-else-if="that.propInfo[tmp.key].shape === ShapeType.vueShapeImage">
|
||||
<div
|
||||
v-for="(img,index) in that.propInfo[tmp.key].dataInfo"
|
||||
:key="index" style="display: flex">
|
||||
<div class="img-box" v-if="img.url">
|
||||
<div style="display: flex">
|
||||
<img :src="img.url" width="60px" height="60px"/>
|
||||
<el-select-v2
|
||||
v-model="that.propInfo[tmp.key].dataInfo[0].showLabel"
|
||||
filterable
|
||||
:options="washingInfoListByType(that.propInfo[tmp.key].groupType)"
|
||||
placeholder="Please select"
|
||||
@change="changeComboData(that.propInfo[tmp.key],that.propInfo[tmp.key].dataInfo[0].showLabel)"
|
||||
size="large"
|
||||
style="min-width: 280px;width: 100%"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div style="display: flex;">
|
||||
<img :src="item.url" width="30px" height="30px"/>
|
||||
<span>
|
||||
{{ item.label }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-select-v2>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="img.label">
|
||||
<el-input v-model="img.label" disabled/>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-select-v2>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="img.label">
|
||||
<el-input v-model="img.label" disabled/>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="deleteList(that.propInfo[tmp.key],index)">
|
||||
<i class="icon-lk_delete"> </i>
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="that.propInfo[tmp.key].canChange"
|
||||
@click="appendList(that.propInfo[tmp.key])">
|
||||
添加
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-col>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div
|
||||
:class ="{ 'hidden-div': that.hideCreate}"
|
||||
:id="that.svgId"
|
||||
:style="{
|
||||
position: that.hideCreate ? 'fixed' : 'relative',
|
||||
display: `flex`,
|
||||
flexDirection: `column`,
|
||||
width: `${previewSize.width}px`,
|
||||
height: `${previewSize.height}px`,
|
||||
}">
|
||||
|
||||
<div v-if="that.previewUrl"
|
||||
:style="{
|
||||
width: `${that.svgWidth+2}px`,
|
||||
height: `${that.svgHeight+2}px`,
|
||||
backgroundColor: (that.pageConfig.background && that.pageConfig.background.areaColor) || '',
|
||||
border: '1px solid #00ff00',
|
||||
position: `absolute`,
|
||||
top: `0`,
|
||||
left: `0`,
|
||||
}"
|
||||
>
|
||||
|
||||
<div>
|
||||
<div v-if="false" style="color: #ff0000;">w:{{imageSize.width}} h:{{imageSize.height}}</div>
|
||||
<span style="color: #ff0000;writing-mode: vertical-rl; text-orientation: upright;">
|
||||
*仅供参考
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="that.previewUrl" v-html="that.previewUrl" >
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="DynamicPropConfig">
|
||||
|
|
@ -278,13 +307,14 @@ import {useLocaleStore} from "@/store/modules/locale";
|
|||
import {ProductInfoApi} from "@/api/oms/productinfo";
|
||||
import domtoimage from 'dom-to-image';
|
||||
import {usePageLoading} from "@/hooks/web/usePageLoading";
|
||||
const { loadStart, loadDone } = usePageLoading()
|
||||
|
||||
const {loadStart, loadDone} = usePageLoading()
|
||||
// 动态属性配置
|
||||
const localeStore = useLocaleStore()
|
||||
const emit = defineEmits(['change', 'initSucceed'])
|
||||
const draftDesignEditRef = ref()
|
||||
const that = reactive({
|
||||
svgId: "svg_"+Math.random().toString(36).substring(2),
|
||||
svgId: "svg_" + Math.random().toString(36).substring(2),
|
||||
hideCreate: true,
|
||||
pageLoading: {},
|
||||
propInfo: {
|
||||
|
|
@ -305,7 +335,7 @@ const that = reactive({
|
|||
draftDesignList: [],
|
||||
draftDesignId: '',
|
||||
reView: false,
|
||||
currentZoom: 6,
|
||||
currentZoom: 10,
|
||||
changeCount: 0,
|
||||
previewUrl: "",
|
||||
previewData: '',
|
||||
|
|
@ -318,8 +348,16 @@ const that = reactive({
|
|||
},
|
||||
data: {},
|
||||
show: false,
|
||||
svgHeight: 0,
|
||||
svgWidth: 0,
|
||||
})
|
||||
|
||||
const previewSize = computed(()=>{
|
||||
return {
|
||||
width: imageSize.value.width * 10,
|
||||
height: imageSize.value.height * 10
|
||||
}
|
||||
})
|
||||
const currentLocale = computed(() => localeStore.getCurrentLocale)
|
||||
watch(() => that.currentZoom, () => {
|
||||
showPng();
|
||||
|
|
@ -331,8 +369,8 @@ const querySearch = (queryString: string, cb: any) => {
|
|||
}) : that.ingredientInfoList
|
||||
cb(results)
|
||||
}
|
||||
const imageSize =computed(()=>{
|
||||
if(that.sizeInfo){
|
||||
const imageSize = computed(() => {
|
||||
if (that.sizeInfo) {
|
||||
return {
|
||||
width: that.sizeInfo.width,
|
||||
height: that.sizeInfo.height
|
||||
|
|
@ -383,7 +421,6 @@ const changeData = (index: number, key: string) => {
|
|||
str = ''
|
||||
}
|
||||
const value = `${mapping[j].value}`.replaceAll('${r}', str)
|
||||
console.log("value",value)
|
||||
that.propInfo[key].dataInfo[i].label = value
|
||||
break;
|
||||
}
|
||||
|
|
@ -447,27 +484,33 @@ const getIngredientInfoListByType = (type) => {
|
|||
return that.ingredientInfoList.filter(item => item.type === type)
|
||||
}
|
||||
const uploadFile = async (fileName) => {
|
||||
return new Promise((resolve, reject)=>{
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let svgElement = document.getElementById(that.svgId);
|
||||
domtoimage.toBlob(svgElement).then((blob) => {
|
||||
FileApi.updateFile({ file: blob })
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
resolve({
|
||||
...res,
|
||||
filename: fileName
|
||||
})
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
}) .catch((res) => {
|
||||
reject(res)
|
||||
})
|
||||
}).catch(function (error) {
|
||||
console.error('转换或上传过程中出现错误:', error);
|
||||
});
|
||||
});
|
||||
let svgElement = document.getElementById(that.svgId);
|
||||
domtoimage.toBlob(svgElement,{
|
||||
width: that.svgWidth+5,
|
||||
height: that.svgHeight+5,
|
||||
type: 'image/jpeg',
|
||||
quality: 1
|
||||
}).then((blob) => {
|
||||
const file = new File([blob], fileName, { type: 'image/jpeg' });
|
||||
FileApi.updateFile({file: file})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
resolve({
|
||||
...res,
|
||||
filename: fileName
|
||||
})
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
}).catch((res) => {
|
||||
reject(res)
|
||||
})
|
||||
}).catch(function (error) {
|
||||
console.error('转换或上传过程中出现错误:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const deleteList = (item, index) => {
|
||||
|
|
@ -629,7 +672,6 @@ const updateDesign = () => {
|
|||
const changeType = () => {
|
||||
previewByDraftDesignId(that.draftDesignId, that.propInfo)
|
||||
}
|
||||
|
||||
const getPropInfo = () => {
|
||||
|
||||
that.pageLoading = ElLoading.service({
|
||||
|
|
@ -643,26 +685,42 @@ const getPropInfo = () => {
|
|||
draftDesignEditRef.value.toSVGData((url) => {
|
||||
that.previewUrl = url
|
||||
that.hideCreate = false;
|
||||
// 年月日
|
||||
const date = new Date();
|
||||
const randChar = Math.random().toString(36).slice(-6);
|
||||
const fileName = `${date.getFullYear()}${ (date.getMonth() + 1)}${ date.getDate()}_${that.draftDesignId }_${randChar}_稿.png`;
|
||||
// 文件上传
|
||||
uploadFile(fileName).then(res =>{
|
||||
that.previewData = res.data;
|
||||
that.hideCreate = true;
|
||||
that.previewUrl =""
|
||||
const info = draftDesignEditRef.value.getPropInfo();
|
||||
that.pageLoading.close()
|
||||
resolve({
|
||||
draftDesignData: draftDesignEditRef.value.getJson(),
|
||||
propOrderByList: info.propOrderByList,
|
||||
// 设计稿id
|
||||
draftDesignId: that.draftDesignId,
|
||||
previewImage: that.previewData,
|
||||
propInfo: that.propInfo
|
||||
setTimeout(()=>{
|
||||
const el = document.querySelector(`#${that.svgId} g`);
|
||||
el.setAttribute("transform",'matrix(1,0,0,1,0,0)');
|
||||
|
||||
document.querySelector(`#${that.svgId} svg`).style.position = 'absolute';
|
||||
document.querySelector(`#${that.svgId} svg`).style.top = '-40%';
|
||||
|
||||
const dom = document.querySelector(`#${that.svgId} svg .x6-graph-svg-viewport`).getBoundingClientRect()
|
||||
const svgDom = document.querySelector(`#${that.svgId} svg`).getBoundingClientRect()
|
||||
that.svgHeight = dom.height;
|
||||
that.svgWidth = dom.width;
|
||||
document.querySelector(`#${that.svgId} svg`).style.left = `${svgDom.left - dom.left}px`;
|
||||
document.querySelector(`#${that.svgId} svg`).style.top = `${svgDom.top - dom.top}px`;
|
||||
// that.pageLoading.close()
|
||||
// 年月日
|
||||
const date = new Date();
|
||||
const randChar = Math.random().toString(36).slice(-6);
|
||||
const fileName = `${date.getFullYear()}${(date.getMonth() + 1)}${date.getDate()}_${that.draftDesignId}_${randChar}_稿.png`;
|
||||
// 文件上传
|
||||
uploadFile(fileName).then(res => {
|
||||
that.previewData = res.data;
|
||||
that.hideCreate = true;
|
||||
that.previewUrl = ""
|
||||
const info = draftDesignEditRef.value.getPropInfo();
|
||||
that.pageLoading.close()
|
||||
resolve({
|
||||
draftDesignData: draftDesignEditRef.value.getJson(),
|
||||
propOrderByList: info.propOrderByList,
|
||||
// 设计稿id
|
||||
draftDesignId: that.draftDesignId,
|
||||
previewImage: that.previewData,
|
||||
propInfo: that.propInfo
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
}, {
|
||||
widthScale: 6,
|
||||
heightScale: 6
|
||||
|
|
|
|||
|
|
@ -727,6 +727,7 @@ const toSVGData = (callback: (url: string) => void, options?: {
|
|||
height: number,
|
||||
widthScale: number,
|
||||
heightScale: number,
|
||||
backgroundColor: String,
|
||||
padding: {
|
||||
top: number,
|
||||
left: number,
|
||||
|
|
@ -735,23 +736,23 @@ const toSVGData = (callback: (url: string) => void, options?: {
|
|||
}
|
||||
}) => {
|
||||
|
||||
let widthScale = options && options.widthScale ? options.widthScale : 5
|
||||
let heightScale = options && options.heightScale ? options.heightScale : 5
|
||||
|
||||
let widthScale = 20 // options && options.widthScale ? options.widthScale : 5
|
||||
let heightScale = 20 // options && options.heightScale ? options.heightScale : 5
|
||||
graph.toSVG((dataUri) => {
|
||||
that.previewUrl = dataUri;
|
||||
callback(that.previewUrl)
|
||||
}, {
|
||||
copyStyles: true,
|
||||
viewBox: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: that.pageConfig.width * (widthScale/2),
|
||||
height: that.pageConfig.height * (heightScale/2),
|
||||
},
|
||||
preserveDimensions: {
|
||||
width: that.pageConfig.width * (widthScale),
|
||||
height: that.pageConfig.height * (heightScale),
|
||||
},
|
||||
preserveDimensions:{
|
||||
width: that.pageConfig.width * (widthScale),
|
||||
height: that.pageConfig.height * (heightScale),
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
const setPropList = (propDataInfo) => {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@
|
|||
<!-- 新增等操作按钮 -->
|
||||
<template #productTypeId="{data}">
|
||||
<div>
|
||||
<el-select class="w-full min-w-[200px]" v-model="data.productTypeId" clearable placeholder="请选择产品类型">
|
||||
<el-option v-for="item in that.typeList" :key="item.id" :label="item.label" :value="item.id" />
|
||||
<el-select class="w-full min-w-[200px]" v-model="data.productTypeId" clearable
|
||||
placeholder="请选择产品类型">
|
||||
<el-option v-for="item in that.typeList" :key="item.id" :label="item.label"
|
||||
:value="item.id"/>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -45,9 +47,18 @@
|
|||
<template #productTypeId="{row}">
|
||||
<div>{{ getLabel(row.productTypeId) }}</div>
|
||||
</template>
|
||||
<template #details="{row}">
|
||||
<template #details="{row}">
|
||||
<div v-html="row.details"></div>
|
||||
</template>
|
||||
<template #cover="{row}">
|
||||
<div v-if="row.cover">
|
||||
<el-image
|
||||
:src="row.cover"
|
||||
style="width: 38px; height: 38px"
|
||||
:preview-src-list="[row.cover]"/>
|
||||
</div>
|
||||
<div v-else>-</div>
|
||||
</template>
|
||||
|
||||
</Table>
|
||||
</ContentWrap>
|
||||
|
|
@ -126,16 +137,16 @@ const that = reactive({
|
|||
visible: false,
|
||||
keyword: '',
|
||||
typeList: [],
|
||||
selectRow:[],
|
||||
queryInfo:{
|
||||
selectRow: [],
|
||||
queryInfo: {
|
||||
productTypeId: null,
|
||||
}
|
||||
})
|
||||
|
||||
const searchRef = ref(null);
|
||||
|
||||
const getLabel = (id)=>{
|
||||
const res = that.typeList.find(item=>item.id === id);
|
||||
const getLabel = (id) => {
|
||||
const res = that.typeList.find(item => item.id === id);
|
||||
return res ? res.label : id
|
||||
}
|
||||
const openDialog = (filter = {}) => {
|
||||
|
|
@ -144,11 +155,11 @@ const openDialog = (filter = {}) => {
|
|||
...filter
|
||||
}
|
||||
updateVisible(true);
|
||||
if(that.typeList.length === 0 ){
|
||||
if (that.typeList.length === 0) {
|
||||
ProductTypeApi.getProductTypePage({
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
}).then(res=>{
|
||||
}).then(res => {
|
||||
that.typeList = res.list
|
||||
})
|
||||
}
|
||||
|
|
@ -156,15 +167,15 @@ const openDialog = (filter = {}) => {
|
|||
}
|
||||
|
||||
// 用监听属性变化无其他意义
|
||||
const tmp = computed(()=>{
|
||||
setTimeout(()=>{
|
||||
that.inputVal = toStr(props.modelValue,that.inputVal)
|
||||
const tmp = computed(() => {
|
||||
setTimeout(() => {
|
||||
that.inputVal = toStr(props.modelValue, that.inputVal)
|
||||
if (that.inputVal) {
|
||||
initInput();
|
||||
}
|
||||
},100)
|
||||
}, 100)
|
||||
return ''
|
||||
},{
|
||||
}, {
|
||||
deep: true
|
||||
})
|
||||
|
||||
|
|
@ -209,13 +220,13 @@ watch(() => props.visible, (newVal) => {
|
|||
const updateVisible = (visible: boolean, clearInput = false) => {
|
||||
that.visible = visible;
|
||||
emit("update:visible", visible)
|
||||
if(that.visible){
|
||||
setTimeout(()=>{
|
||||
searchRef.value.search()
|
||||
},100)
|
||||
if (that.visible) {
|
||||
setTimeout(() => {
|
||||
searchRef.value.search()
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
defineExpose({ openDialog})
|
||||
defineExpose({openDialog})
|
||||
|
||||
const submit = () => {
|
||||
updateValue();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
/**
|
||||
* 下单步骤完成事件
|
||||
*/
|
||||
export const STEP0_FINISH_EVENT:string = 'step0finish'
|
||||
/**
|
||||
* 更新选择地址事件
|
||||
*/
|
||||
export const UPDATE_ADDRESS_EVENT:string = 'update_address'
|
||||
|
||||
export const STEP0_FINISH:string = 'step0finish'
|
||||
export const UPDATE_ADDRESS:string = 'update_address'
|
||||
/**
|
||||
* 删除商品事件
|
||||
*/
|
||||
export const PRODUCT_DEL_ROW_EVENT:string = 'product_del_row_event'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
function defaultCloneObj(obj: any) {
|
||||
if (obj === null || typeof obj !== 'object') return obj;
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
export function useResetFields<T extends object>(value: T, clone = defaultCloneObj) {
|
||||
const state = reactive(clone(value)) as T;
|
||||
const reset = ():T => {
|
||||
Object.keys(state).forEach(key => delete state[key]);
|
||||
return Object.assign(state, clone(value))
|
||||
}
|
||||
return [ state,reset] as const;
|
||||
}
|
||||
|
|
@ -448,5 +448,10 @@ export default {
|
|||
btn_zoom_out: '缩小',
|
||||
preview: '预览'
|
||||
},
|
||||
designInfo: {
|
||||
auditSubmitText: '批稿',
|
||||
auditTips: '此稿件仅仅作为核对内容使用用,不作为最终印刷稿件;',
|
||||
cancelText: '取消',
|
||||
},
|
||||
'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<div class="card-with-badge">
|
||||
<DesignPreviewDialog ref="designPreviewDialogRef" @submit="submit"/>
|
||||
<el-card class="el-card">
|
||||
<el-card class="el-card" >
|
||||
<div class="badge" v-if="badge">{{ badge }}</div>
|
||||
<div class="edit-btn">
|
||||
<el-button link title="Edit" type="primary" @click.stop="openItem">
|
||||
|
|
@ -83,7 +83,10 @@ const designPreviewDialogRef = ref(null);
|
|||
const props = defineProps({
|
||||
productInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
required: true,
|
||||
default: () => ({
|
||||
previewImage: ''
|
||||
})
|
||||
},
|
||||
badge: {
|
||||
type: String,
|
||||
|
|
@ -145,6 +148,11 @@ const submit = (data:any) => {
|
|||
...formData.value.specInfo,
|
||||
mainColor: formData.value.draftDesignInfo.label || "默认"
|
||||
};
|
||||
// 属性没有设置使用模板的尺寸
|
||||
if(!formData.value.specInfo.specSizeWidth){
|
||||
formData.value.specInfo.specSizeWidth = data.draftDesignData.pageConfig.editArea.width;
|
||||
formData.value.specInfo.specSizeHeight = data.draftDesignData.pageConfig.editArea.height;
|
||||
}
|
||||
change();
|
||||
}
|
||||
const change = () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,355 @@
|
|||
<template>
|
||||
|
||||
<div class="card-with-badge">
|
||||
<el-card class="el-card">
|
||||
|
||||
<el-table :data="that.tableList" class="w-full" border height="400px" @selection-change="selectionChange">
|
||||
<el-table-column type="selection" width="55" :selectable="selectable" />
|
||||
<el-table-column width="80px" label="#">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
{{scope.$index + 1}}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="84px" label="主图">
|
||||
<template #default="scope">
|
||||
<div class="flex items-center">
|
||||
<el-image
|
||||
fit="contain"
|
||||
style="width: 80px;height: 80px;"
|
||||
:preview-src-list="[scope.row.previewImage]"
|
||||
:src="scope.row.previewImage"/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="300px" label="尺码">
|
||||
<template #header>
|
||||
<div class="flex">
|
||||
<div>尺码</div>
|
||||
<div>
|
||||
<el-input
|
||||
v-model="that.fullSize"
|
||||
v-show="that.tableList.length > 1"
|
||||
placeholder="多个使用空格间隔"
|
||||
@change="fullChangeSize"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
|
||||
<el-autocomplete
|
||||
v-model="scope.row.labelSize"
|
||||
:fetch-suggestions="querySearch"
|
||||
clearable
|
||||
class="inline-input w-50"
|
||||
placeholder="输入码数"
|
||||
@select="handleSelect"
|
||||
/>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="300px" label="数量">
|
||||
<template #header>
|
||||
<div class="flex">
|
||||
<div>数量<span class="text-xs">({{totalCount}})</span></div>
|
||||
<div><el-input-number v-model="that.fullCount" v-show="that.tableList.length > 1" @change="fullQty"/> </div>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-input-number v-model="scope.row.orderQty" min="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="badge" >{{ that.tableList.length }}</div>
|
||||
<div class="edit-btn">
|
||||
<el-button link title="Add" type="primary" @click.stop="addItem">
|
||||
<Icon size="24" icon="ep:plus"/>
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="del-btn" title="Delete">
|
||||
<el-button link type="danger" @click.stop="delItem">
|
||||
<Icon size="24" icon="ep:remove"/>
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="ProductItem1">
|
||||
//@ts-nocheck
|
||||
import {reactive, useModel, watch} from 'vue'
|
||||
import DesignPreviewDialog from "@/components/DraftDesign/components/DesignPreviewDialog.vue";
|
||||
import {ShapeType} from "@/components/DraftDesign/config";
|
||||
import {createImageViewer} from "@/components/ImageViewer";
|
||||
import {useI18n} from "@/hooks/web/useI18n";
|
||||
import {ElOption, ElSelect} from "element-plus";
|
||||
import {useEmitt} from "@/hooks/web/useEmitt";
|
||||
import {PRODUCT_DEL_ROW_EVENT, STEP0_FINISH_EVENT} from "@/constants/EmitEventName";
|
||||
import {useResetFields} from "@/hooks/ext";
|
||||
|
||||
const emit = defineEmits(['update:productInfo', 'delItem', 'change'])
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
productInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
badge: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const [that, resetFields] = useResetFields({
|
||||
tableList: [],
|
||||
selectRow: [],
|
||||
fullCount: 0,
|
||||
itemList:[ 'M','L','XL','XXL','XXXL'],
|
||||
fullSize:'',
|
||||
})
|
||||
const totalCount = computed(()=>{
|
||||
let count = 0;
|
||||
that.tableList.forEach(item=>{
|
||||
count += item.orderQty
|
||||
})
|
||||
return count;
|
||||
})
|
||||
watch(that.tableList, (newVal)=>{
|
||||
changeData();
|
||||
})
|
||||
|
||||
const formData = useModel(props, 'productInfo', emit)
|
||||
const delItem = () => {
|
||||
if(that.selectRow.length === 0){
|
||||
useMessage().warning("请选择要删除的项");
|
||||
return;
|
||||
}
|
||||
useMessage().confirm('确定删除吗?').then(() => {
|
||||
let key = [];
|
||||
for (let i = 0; i < that.selectRow.length; i++) {
|
||||
key.push(that.selectRow[i].key)
|
||||
}
|
||||
that.tableList = that.tableList.filter(item => !key.includes(item.key))
|
||||
changeData();
|
||||
})
|
||||
}
|
||||
const fullChangeSize = ()=>{
|
||||
const selectedValue = ref<string | number>(1); // 用于绑定选中的值
|
||||
ElMessageBox({
|
||||
title: '确定批量设置吗?',
|
||||
confirmButtonText: t('common.ok'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
type: 'warning',
|
||||
message: () =>
|
||||
h(ElSelect, {
|
||||
modelValue: selectedValue.value,
|
||||
placeholder: '请选择',
|
||||
style: { width: '300px' },
|
||||
'onUpdate:modelValue': (value: string | number) => {
|
||||
selectedValue.value = value;
|
||||
},
|
||||
}, [
|
||||
h(ElOption, { label: '填充空值行', value: 1 }),
|
||||
h(ElOption, { label: '追加', value: 2 }),
|
||||
h(ElOption, { label: '覆盖', value: 3 }),
|
||||
// 添加更多选项
|
||||
]),
|
||||
}).then(() => {
|
||||
const val = that.fullSize.split(" ")
|
||||
let index= 0;
|
||||
if(selectedValue.value === 2){
|
||||
for (let i = 0; i < val.length; i++) {
|
||||
addRow({
|
||||
labelSize: val[index],
|
||||
})
|
||||
}
|
||||
}else {
|
||||
that.tableList.forEach(item => {
|
||||
if(index < val.length){
|
||||
if(selectedValue.value === 1){
|
||||
if(!item.labelSize){
|
||||
item.labelSize = val[index]
|
||||
index++;
|
||||
}
|
||||
}else if(selectedValue.value === 3){
|
||||
item.labelSize = val[index]
|
||||
index++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}).catch(() => {
|
||||
// 用户点击取消时的处理逻辑
|
||||
});
|
||||
}
|
||||
const fullQty = (val) => {
|
||||
|
||||
const selectedValue = ref<string | number>(1); // 用于绑定选中的值
|
||||
ElMessageBox({
|
||||
title: '确定批量设置数量 ' + val + ' 吗?',
|
||||
confirmButtonText: t('common.ok'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
type: 'warning',
|
||||
message: () =>
|
||||
h(ElSelect, {
|
||||
modelValue: selectedValue.value,
|
||||
placeholder: '请选择',
|
||||
style: { width: '300px' },
|
||||
'onUpdate:modelValue': (value: string | number) => {
|
||||
selectedValue.value = value;
|
||||
},
|
||||
}, [
|
||||
h(ElOption, { label: '填充全部', value: 1 }),
|
||||
h(ElOption, { label: '追加', value: 2 }),
|
||||
h(ElOption, { label: '减少', value: 3 }),
|
||||
// 添加更多选项
|
||||
]),
|
||||
}).then(() => {
|
||||
that.tableList.forEach(item => {
|
||||
if(selectedValue.value === 1){
|
||||
item.orderQty = val
|
||||
}else if(selectedValue.value === 2){
|
||||
item.orderQty += val
|
||||
}else if(selectedValue.value === 3){
|
||||
item.orderQty -= val
|
||||
if( item.orderQty < 0){
|
||||
item.orderQty = 1
|
||||
}
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户点击取消时的处理逻辑
|
||||
});
|
||||
}
|
||||
const addItem = () => {
|
||||
addRow();
|
||||
}
|
||||
const addRow=(row={})=>{
|
||||
if(row.labelSize){
|
||||
for (let i = 0; i < that.tableList.length; i++) {
|
||||
if(that.tableList[i].labelSize === row.labelSize){
|
||||
// 重复的尺码
|
||||
useMessage().notifyWarning(`第${i}行,已跳过重复尺码${row.labelSize} `)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
that.tableList.push({
|
||||
orderQty: 1,
|
||||
labelSize: "",
|
||||
//@ts-ignore
|
||||
previewImage: formData.value.previewImage,
|
||||
draftDesignId: "",
|
||||
...formData.value,
|
||||
...row,
|
||||
key: Math.random().toString(36).substring(2),
|
||||
})
|
||||
|
||||
}
|
||||
useEmitt({
|
||||
name: PRODUCT_DEL_ROW_EVENT,
|
||||
callback: (row)=>{
|
||||
if(formData.value && that.tableList && that.tableList.length > 0
|
||||
&& formData.value.productId === that.tableList[0].productId){
|
||||
that = resetFields();
|
||||
|
||||
}
|
||||
},
|
||||
});
|
||||
const init = (list = [])=>{
|
||||
if(list){
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
addRow(list[i])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const querySearch = (queryString: string, cb: any) => {
|
||||
const results = queryString ? that.itemList.filter(t => t.toString()
|
||||
.toLocaleLowerCase()
|
||||
.indexOf(queryString.toLocaleLowerCase()) != -1) : that.itemList
|
||||
let res = [];
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
res.push({
|
||||
value: results[i],
|
||||
label: results[i],
|
||||
})
|
||||
}
|
||||
cb(res)
|
||||
}
|
||||
const handleSelect = (item: RestaurantItem) => {
|
||||
console.log(item)
|
||||
}
|
||||
|
||||
const selectable = (row:any) => {
|
||||
return true;
|
||||
}
|
||||
const selectionChange = (arr)=>{
|
||||
that.selectRow = arr;
|
||||
}
|
||||
const changeData = () => {
|
||||
emit("change", that.tableList)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.card-with-badge {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.el-card {
|
||||
padding-top: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
left: 0;
|
||||
background-color: #6bb5ff;
|
||||
color: white;
|
||||
padding: 5px 10px;
|
||||
border-radius: 50%;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.del-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 30px;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
highlight-current-row
|
||||
stripe
|
||||
:data="that.tableData"
|
||||
border
|
||||
@row-click="rowChange"
|
||||
style="width: 100%">
|
||||
<el-table-column prop="productCode" label="产品编码"/>
|
||||
|
|
@ -57,9 +58,10 @@
|
|||
<script lang="ts" setup name="ProductList">
|
||||
// @ts-nocheck
|
||||
import {useEmitt} from "@/hooks/web/useEmitt";
|
||||
import {STEP0_FINISH} from "@/constants/EmitEventName";
|
||||
import {PRODUCT_DEL_ROW_EVENT, STEP0_FINISH_EVENT} from "@/constants/EmitEventName";
|
||||
import {formatDate} from "@/utils/formatTime";
|
||||
|
||||
|
||||
const emit = defineEmits(['rowClick'])
|
||||
const tableRef = ref();
|
||||
const that = reactive({
|
||||
|
|
@ -74,20 +76,19 @@ const that = reactive({
|
|||
})
|
||||
|
||||
const handleEvent = (data:any) => {
|
||||
console.log("获取过滤条件",data);
|
||||
if(data){
|
||||
that.filterParam.brandId = data.brandId;
|
||||
that.isBatch = data.isBatch;
|
||||
that.plansenddate = data.plansenddate;
|
||||
that.planDate = formatDate(that.plansenddate);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
const {emitter} = useEmitt();
|
||||
useEmitt({
|
||||
name: STEP0_FINISH,
|
||||
name: STEP0_FINISH_EVENT,
|
||||
callback: handleEvent,
|
||||
});
|
||||
|
||||
const productInfoListRef = ref(null);
|
||||
const addProduct = () => {
|
||||
productInfoListRef.value.openDialog(that.filterParam)
|
||||
|
|
@ -96,9 +97,13 @@ const delProduct = () => {
|
|||
useMessage().confirm('确定删除吗?').then(() => {
|
||||
that.tableData = that.tableData.filter(item => item.productId !== that.selectRow.productId)
|
||||
useMessage().notifySuccess('删除成功');
|
||||
rowChange(that.tableData[that.tableData.length - 1])
|
||||
})
|
||||
emit('delRow', that.selectRow);
|
||||
emitter.emit(PRODUCT_DEL_ROW_EVENT, that.selectRow);
|
||||
if(that.tableData.length > 0){
|
||||
rowChange(that.tableData[that.tableData.length - 1]);
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
const submit = (data) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
|
|
@ -128,6 +133,7 @@ const addRow = (row) => {
|
|||
producer: row.producer,
|
||||
cover: row.cover,
|
||||
unit: row.unit || 'pcs',
|
||||
details: row.details || '',
|
||||
orderQty: row.orderQty || 0,
|
||||
totalQty: row.totalQty || 0,
|
||||
deliveryDate: row.deliveryDate,
|
||||
|
|
@ -175,9 +181,17 @@ const setSelectRow = (row) => {
|
|||
const getTableData = () => {
|
||||
return that.tableData
|
||||
}
|
||||
const init = (data) => {
|
||||
if(data && data.length > 0){
|
||||
that.tableData = data
|
||||
rowChange(data[0])
|
||||
}
|
||||
|
||||
}
|
||||
defineExpose({
|
||||
setSelectRow,
|
||||
getTableData
|
||||
getTableData,
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,32 +2,47 @@
|
|||
|
||||
<div>
|
||||
<div>
|
||||
<el-button type="primary" v-show="that.tableData.length > 0" @click="addSku">添加SKU</el-button>
|
||||
<el-button type="primary" v-show="that.templateType === '1' && that.tableData.length > 0" @click="addSku">添加SKU</el-button>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="flex flex-wrap" v-if="that.templateType === '1'">
|
||||
<template v-for="(item,index) in that.tableData" :key="item.key">
|
||||
<ProductItem1
|
||||
@change="changeItem"
|
||||
class="m-2"
|
||||
@del-item="delItem"
|
||||
:badge="`${index+1}`"
|
||||
v-model:product-info="that.tableData[index]"/>
|
||||
|
||||
v-model:product-info="that.tableData[index]" />
|
||||
</template>
|
||||
</div>
|
||||
<div class="flex" v-show="that.templateType === '2' && that.tableData.length > 0">
|
||||
<ProductItem2
|
||||
@change="changeList"
|
||||
ref="productItem2Ref"
|
||||
class="m-2"
|
||||
@del-item="delItem"
|
||||
:badge="`${1}`"
|
||||
|
||||
v-model:product-info="that.tableData[0]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="ProductSkuList">
|
||||
|
||||
import ProductItem1 from "./ProductItem1.vue"
|
||||
import ProductItem2 from "./ProductItem2.vue"
|
||||
import {ProductInfoApi} from "@/api/oms/productinfo";
|
||||
import {useResetFields} from "@/hooks/ext";
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
const that = reactive({
|
||||
const productItem2Ref = ref();
|
||||
|
||||
const [that, resetFields] = useResetFields({
|
||||
tableData: [],
|
||||
productId: '',
|
||||
listKey: '',
|
||||
cover: '',
|
||||
templateType: '2', // 1有模板 2无模板 3尺码唛
|
||||
specInfo: {
|
||||
specSizeWidth: 0,
|
||||
specSizeHeight: 0,
|
||||
|
|
@ -43,7 +58,11 @@ const addSku = () => {
|
|||
listKey: that.listKey,
|
||||
orderQty: 1,
|
||||
productId: that.productId,
|
||||
previewImage: that.cover,
|
||||
draftDesignId: '',
|
||||
labelSize: '',
|
||||
// 产品模板类型-字典 product_draft_template_type 1有模板 2无模板 3尺码唛
|
||||
productTemplateType: that.templateType,
|
||||
draftDesignInfo: {},
|
||||
width: 0, // 设计稿的宽
|
||||
height: 0, // 设计稿的高
|
||||
|
|
@ -51,30 +70,54 @@ const addSku = () => {
|
|||
specInfo: JSON.parse(JSON.stringify(that.specInfo)),
|
||||
})
|
||||
}
|
||||
const itemType =()=>{
|
||||
//
|
||||
if(that.cover){
|
||||
// 无模板
|
||||
|
||||
}
|
||||
}
|
||||
const init = (row) => {
|
||||
that.tableData = row.productSkuList;
|
||||
that.productId = row.productId
|
||||
that.listKey = row.key
|
||||
//@ts-ignore
|
||||
ProductInfoApi.getProductInfo(that.productId).then(res=>{
|
||||
|
||||
that.specInfo = {
|
||||
specSizeWidth: res.specSizeWidth,
|
||||
specSizeHeight: res.specSizeHeight,
|
||||
specSizeThk: res.specSizeThk,
|
||||
specMaterial: res.specMaterial,
|
||||
mainColor: '',
|
||||
}
|
||||
if (that.tableData.length === 0) {
|
||||
addSku();
|
||||
}
|
||||
})
|
||||
if(that.productId){
|
||||
//@ts-ignore
|
||||
ProductInfoApi.getProductInfo(that.productId).then(res=>{
|
||||
console.log("res",res)
|
||||
that.specInfo = {
|
||||
specSizeWidth: res.specSizeWidth,
|
||||
specSizeHeight: res.specSizeHeight,
|
||||
specSizeThk: res.specSizeThk,
|
||||
specMaterial: res.specMaterial,
|
||||
mainColor: '',
|
||||
}
|
||||
that.templateType = res.templateType;
|
||||
// 没有设计稿数据
|
||||
if(res.templateType !== '1'){
|
||||
that.cover = res.cover
|
||||
}
|
||||
|
||||
if (that.tableData.length === 0) {
|
||||
addSku();
|
||||
}
|
||||
if(res.templateType === '2'){
|
||||
// 初始化
|
||||
setTimeout(()=>{
|
||||
productItem2Ref.value.init(that.tableData);
|
||||
},100)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
const changeItem = (item) => {
|
||||
const changeItem = () => {
|
||||
emit("change", that.tableData)
|
||||
}
|
||||
const changeList = (tableData)=>{
|
||||
that.tableData = tableData
|
||||
changeItem();
|
||||
}
|
||||
const delItem = (item) => {
|
||||
let index = -1
|
||||
for (let i = 0; i < that.tableData.length; i++) {
|
||||
|
|
@ -92,7 +135,8 @@ const delItem = (item) => {
|
|||
emit("change", that.tableData)
|
||||
}
|
||||
defineExpose({
|
||||
init
|
||||
init,
|
||||
resetFields
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<el-scrollbar height="38vh">
|
||||
<div>
|
||||
<div class="title-border">订单产品列表</div>
|
||||
<ProductList ref="listRef" @row-click="rowClick" />
|
||||
<ProductList ref="listRef" @row-click="rowClick" @del-row="delRow"/>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
import ProductList from "./ProductList.vue";
|
||||
import ProductSkuList from "./ProductSkuList.vue";
|
||||
import {useEmitt} from "@/hooks/web/useEmitt";
|
||||
import {STEP0_FINISH} from "@/constants/EmitEventName";
|
||||
import {STEP0_FINISH_EVENT} from "@/constants/EmitEventName";
|
||||
|
||||
const skuListRef = ref(null);
|
||||
const listRef = ref(null);
|
||||
|
|
@ -30,6 +30,7 @@ const that = reactive({
|
|||
selectRow: null,
|
||||
})
|
||||
const rowClick = (row) => {
|
||||
console.log("init",row)
|
||||
that.selectRow = {
|
||||
productSkuList: [],
|
||||
...row,
|
||||
|
|
@ -37,7 +38,9 @@ const rowClick = (row) => {
|
|||
//@ts-nocheck
|
||||
skuListRef.value.init(that.selectRow)
|
||||
}
|
||||
|
||||
const delRow = (row)=>{
|
||||
skuListRef.value.resetFields();
|
||||
}
|
||||
|
||||
const changeDetails = (tableData)=>{
|
||||
that.selectRow.productSkuList = [];
|
||||
|
|
@ -48,10 +51,10 @@ const changeDetails = (tableData)=>{
|
|||
})
|
||||
}
|
||||
listRef.value.setSelectRow(that.selectRow)
|
||||
|
||||
}
|
||||
|
||||
const getTableData = () => {
|
||||
|
||||
const list = [];
|
||||
for (let i = 0; i < listRef.value.getTableData().length; i++) {
|
||||
list.push({
|
||||
|
|
@ -61,9 +64,12 @@ const getTableData = () => {
|
|||
}
|
||||
return list
|
||||
}
|
||||
|
||||
const init = (saleOrderEntry)=>{
|
||||
listRef.value.init(saleOrderEntry)
|
||||
}
|
||||
defineExpose({
|
||||
getTableData
|
||||
getTableData,
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@
|
|||
disabled
|
||||
prefix-icon=""
|
||||
style="width: 760px"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD hh:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="品牌" prop="brandId">
|
||||
<el-select v-model="formData.brandId" filterable placeholder="请选择品牌">
|
||||
<el-select :disabled="changeBrand" v-model="formData.brandId" filterable placeholder="请选择品牌">
|
||||
<el-option
|
||||
v-for="brand in brandList"
|
||||
:key="brand.id"
|
||||
|
|
@ -79,8 +79,8 @@
|
|||
:disabledDate="(time)=> { return time.getTime() < (Date.now() + 8 * 60 * 60 * 1000); }"
|
||||
v-model="that.tmpFormData.planDate"
|
||||
style="width: 760px"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="datetime"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
|
@ -149,9 +149,10 @@
|
|||
<div class="flex w-full">
|
||||
<el-input
|
||||
clearable
|
||||
:disabled="isEditState"
|
||||
v-model="formData.contractCode"
|
||||
placeholder="请填写合同号"/>
|
||||
<el-button type="primary" @click="generateContractCode">生成</el-button>
|
||||
<el-button v-show="!formData.contractCode && !isEditState" type="primary" @click="generateContractCode">获取</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
|
@ -166,6 +167,20 @@
|
|||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="业务员" prop="orderFollowerUser">
|
||||
<el-select v-model="formData.orderFollowerUser" filterable placeholder="业务员">
|
||||
<el-option
|
||||
v-for="user in that.followerUserList"
|
||||
:key="user.id"
|
||||
:label="user.username"
|
||||
:value="`${user.id}`"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-form-item label="备注" prop="remarks">
|
||||
|
|
@ -391,21 +406,23 @@ import * as BrandApi from "@/api/oms/brand";
|
|||
import {AddressApi} from "@/api/oms/customer/address";
|
||||
import {CustomerApi} from "@/api/oms/customer";
|
||||
import {SaleOrderApi} from "@/api/oms/saleorder";
|
||||
|
||||
const { push } = useRouter()
|
||||
import OrderAddProductStep from "./components/OrderAddProductStep/index.vue";
|
||||
import {useEmitt} from "@/hooks/web/useEmitt";
|
||||
import {STEP0_FINISH, UPDATE_ADDRESS} from "@/constants/EmitEventName";
|
||||
import {STEP0_FINISH_EVENT, UPDATE_ADDRESS_EVENT} from "@/constants/EmitEventName";
|
||||
import {formatDate} from "@/utils/formatTime";
|
||||
|
||||
import {ElLoading} from "element-plus";
|
||||
const route = useRoute() // 路由
|
||||
// 计算当前时间之后指定天数的日期
|
||||
const calculateDateAfterDays = (days) => {
|
||||
return formatDate(new Date(Date.now() + ((24 * 60 * 60 * 1000) * days)));
|
||||
}
|
||||
|
||||
const {emitter} = useEmitt();
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
id: null,
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: null,
|
||||
|
|
@ -423,13 +440,14 @@ const editAddress = () => {
|
|||
addressRef.value.openDialog()
|
||||
}
|
||||
useEmitt({
|
||||
name: UPDATE_ADDRESS,
|
||||
name: UPDATE_ADDRESS_EVENT,
|
||||
callback: ()=>{
|
||||
getCustomerAddressList();
|
||||
},
|
||||
});
|
||||
const that = reactive({
|
||||
formLoading: false,
|
||||
pageLoading: {},
|
||||
addressList: [],
|
||||
addressId: null,
|
||||
tmpFormData: {
|
||||
|
|
@ -437,6 +455,8 @@ const that = reactive({
|
|||
emailList: [],
|
||||
planDate: calculateDateAfterDays(7),
|
||||
},
|
||||
followerUserList:[],
|
||||
subListSize: 0,
|
||||
})
|
||||
const formData = ref({
|
||||
contactName: '',
|
||||
|
|
@ -463,12 +483,15 @@ const formData = ref({
|
|||
deliveryAddress: '',
|
||||
deliveryRemark: '',
|
||||
saleOrderEntry: [],
|
||||
orderFollowerUser: '',
|
||||
})
|
||||
const isEditState = computed(()=>{
|
||||
return route.query.id != undefined
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
contactName: [{required: true, message: '联系人不能为空', trigger: 'blur'}],
|
||||
brandId: [{required: true, message: '品牌不能为空', trigger: 'blur'}],
|
||||
contractCode: [{required: true, message: '品牌不能为空', trigger: 'blur'}],
|
||||
contractCode: [{required: true, message: '合同号不能为空', trigger: 'blur'}],
|
||||
phone: [{required: true, message: '联系人手机号不能为空', trigger: 'blur'},
|
||||
{
|
||||
pattern: /^(?:(?:\+|00)86)?1(?:3[\d]|4[5-79]|5[0-35-9]|6[5-7]|7[0-8]|8[\d]|9[189])\d{8}$/,
|
||||
|
|
@ -479,13 +502,8 @@ const formRules = reactive({
|
|||
|
||||
})
|
||||
const activeNames = ref(['1', '2', '3'])
|
||||
|
||||
const onAddEmail = () => {
|
||||
if (!that.tmpFormData.inputEmail || that.tmpFormData.inputEmail.trim() === '') {
|
||||
useMessage().warning('请输入邮箱');
|
||||
return;
|
||||
}
|
||||
const tmp = that.tmpFormData.inputEmail.trim();
|
||||
const pushEmail = (input:string)=>{
|
||||
const tmp = input.trim();
|
||||
const index = that.tmpFormData.emailList.indexOf(tmp);
|
||||
if (index != -1) {
|
||||
that.tmpFormData.emailList.splice(index, 1);
|
||||
|
|
@ -494,8 +512,16 @@ const onAddEmail = () => {
|
|||
} else {
|
||||
that.tmpFormData.emailList.push(tmp);
|
||||
}
|
||||
}
|
||||
const onAddEmail = () => {
|
||||
if (!that.tmpFormData.inputEmail || that.tmpFormData.inputEmail.trim() === '') {
|
||||
useMessage().warning('请输入邮箱');
|
||||
return;
|
||||
}
|
||||
pushEmail(that.tmpFormData.inputEmail);
|
||||
that.tmpFormData.inputEmail = ''; // 清空输入框
|
||||
}
|
||||
|
||||
const onDelEmail = () => {
|
||||
if (selectedIndex.value >= 0) {
|
||||
that.tmpFormData.emailList.splice(selectedIndex.value, 1); // 从数组中移除指定索引的元素
|
||||
|
|
@ -509,16 +535,24 @@ const onDelEmail = () => {
|
|||
const selectItem = async (index: number) => {
|
||||
selectedIndex.value = index;
|
||||
}
|
||||
const changeBrand = computed(()=>{
|
||||
return that.subListSize > 0;
|
||||
})
|
||||
const generateContractCode = () => {
|
||||
const code = `CT-${Math.floor(Date.now() / 1000) + '-' + Math.random().toString(10).substring(2, 6).padEnd(4, '0')}`;
|
||||
formData.value.contractCode = code;
|
||||
return code;
|
||||
// 后台获取合同号
|
||||
SaleOrderApi.getContractCode().then(res =>{
|
||||
formData.value.contractCode = res;
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const backStep = async () => {
|
||||
stepIndex.value = stepIndex.value - 1;
|
||||
that.subListSize = 0;
|
||||
if(stepRef.value){
|
||||
that.subListSize = stepRef.value.getTableData().length
|
||||
}
|
||||
}
|
||||
const {emitter} = useEmitt();
|
||||
const nextStep = async () => {
|
||||
if (stepIndex.value === 0) {
|
||||
formRef.value.validate().then(() => {
|
||||
|
|
@ -530,7 +564,7 @@ const nextStep = async () => {
|
|||
if (!formData.isBatch && that.tmpFormData.planDate) {
|
||||
formData.value.plansenddate = new Date(that.tmpFormData.planDate).getTime()
|
||||
}
|
||||
emitter.emit(STEP0_FINISH, {
|
||||
emitter.emit(STEP0_FINISH_EVENT, {
|
||||
...formData.value
|
||||
})
|
||||
}).catch(() => {
|
||||
|
|
@ -539,7 +573,6 @@ const nextStep = async () => {
|
|||
} else {
|
||||
stepIndex.value = stepIndex.value + 1;
|
||||
}
|
||||
|
||||
}
|
||||
const onChangeAddress = (id)=>{
|
||||
console.log(id)
|
||||
|
|
@ -549,28 +582,78 @@ const onChangeAddress = (id)=>{
|
|||
}
|
||||
}
|
||||
}
|
||||
const addNewBill = () => {
|
||||
console.log("stepRef.value.getTableData()", stepRef.value.getTableData())
|
||||
// todo 校验
|
||||
const tableData = stepRef.value.getTableData();
|
||||
if (tableData.length === 0) {
|
||||
useMessage().warning("请添加产品")
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* 提交前处理
|
||||
*/
|
||||
const submitPreHandler = (showMsg = true) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// todo 校验
|
||||
const tableData = stepRef.value.getTableData();
|
||||
if (tableData.length === 0) {
|
||||
if(showMsg){
|
||||
useMessage().warning("请添加产品")
|
||||
}
|
||||
reject("请添加产品")
|
||||
}
|
||||
if (that.tmpFormData.emailList) {
|
||||
formData.value.emails = that.tmpFormData.emailList.join(";")
|
||||
}
|
||||
if (!formData.isBatch && that.tmpFormData.planDate) {
|
||||
formData.value.plansenddate = new Date(that.tmpFormData.planDate).getTime()
|
||||
}
|
||||
formData.value.saleOrderEntry = tableData
|
||||
|
||||
for (let i = 0; i < tableData.length; i++) {
|
||||
|
||||
}
|
||||
formData.value.saleOrderEntry = tableData
|
||||
console.log("333", formData.value)
|
||||
SaleOrderApi.placeOrder({
|
||||
...formData.value
|
||||
}).then(res => {
|
||||
useMessage().success("下单成功")
|
||||
resFrom();
|
||||
stepIndex.value = 0
|
||||
if ( formData.value.bizdate) {
|
||||
formData.value.bizdate = new Date(formData.value.bizdate).getTime()
|
||||
}
|
||||
resolve(true);
|
||||
})
|
||||
}
|
||||
const addNewBill = () => {
|
||||
console.log("stepRef.value.getTableData()", stepRef.value.getTableData())
|
||||
submitPreHandler().then(res=>{
|
||||
if(formData.value.id){
|
||||
SaleOrderApi.editOrder(formData.value.id,{
|
||||
...formData.value
|
||||
}).then(res => {
|
||||
that.pageLoading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '修改成功...',
|
||||
background: 'rgba(0,0,0,0.5)'
|
||||
})
|
||||
setTimeout(()=>{
|
||||
that.pageLoading.close()
|
||||
push("/")
|
||||
},800)
|
||||
})
|
||||
}else {
|
||||
SaleOrderApi.placeOrder({
|
||||
...formData.value
|
||||
}).then(res => {
|
||||
that.pageLoading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '下单成功...',
|
||||
background: 'rgba(0,0,0,0.5)'
|
||||
})
|
||||
setTimeout(()=>{
|
||||
that.pageLoading.close()
|
||||
push("/")
|
||||
},800)
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
queryParams.id = '';
|
||||
if(route.query){
|
||||
queryParams.id = route.query.id ?? ''
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const hasLastIndex = computed(() => {
|
||||
return stepIndex.value >= 1;
|
||||
|
|
@ -578,9 +661,26 @@ const hasLastIndex = computed(() => {
|
|||
|
||||
/** 初始化 **/
|
||||
const brandList = ref<any[]>([]) // 品牌列表
|
||||
|
||||
|
||||
watch(() => formData.value.brandId, async (val)=>{
|
||||
if(val){
|
||||
const data = await SaleOrderApi.getFollowerUser(val)
|
||||
that.followerUserList = data
|
||||
if(that.followerUserList.length > 0 && !formData.value.orderFollowerUser){
|
||||
formData.value.orderFollowerUser = that.followerUserList[0].id
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
// 获取品牌列表
|
||||
brandList.value = await BrandApi.getSimpleBrandList()
|
||||
BrandApi.getSimpleBrandList().then(res =>{
|
||||
brandList.value = res
|
||||
if(res.length > 0 && !formData.value.brandId){
|
||||
formData.value.brandId = brandList.value[0].id
|
||||
}
|
||||
})
|
||||
const customerData = await CustomerApi.getCustomerInfo()
|
||||
if (customerData) {
|
||||
that.addressList = customerData.addressList;
|
||||
|
|
@ -589,6 +689,9 @@ onMounted(async () => {
|
|||
formData.value.company = customerData.company;
|
||||
formData.value.contactName = customerData.contacts;
|
||||
formData.value.phone = customerData.phone;
|
||||
if(customerData.email){
|
||||
pushEmail(customerData.email);
|
||||
}
|
||||
formData.value.invoiceCode = customerData.invoiceCode;
|
||||
formData.value.invoiceName = customerData.invoiceName;
|
||||
formData.value.invoiceAddress = customerData.invoiceAddress;
|
||||
|
|
@ -597,6 +700,19 @@ onMounted(async () => {
|
|||
that.addressId = that.addressList[0].id;
|
||||
}
|
||||
}
|
||||
// 获取订单信息
|
||||
if(queryParams.id){
|
||||
const res = await SaleOrderApi.queryEditById(queryParams.id);
|
||||
formData.value = res
|
||||
formData.value.bizdate = formatDate( new Date(res.bizdate), 'YYYY-MM-DD hh:mm:ss');
|
||||
that.tmpFormData.planDate = formatDate( new Date(res.plansenddate), 'YYYY-MM-DD');
|
||||
that.tmpFormData.emailList = res.emails.split(";")
|
||||
formData.value = {
|
||||
...formData.value,
|
||||
id: queryParams.id
|
||||
}
|
||||
stepRef.value.init(res.saleOrderEntry ?? []);
|
||||
}
|
||||
|
||||
})
|
||||
const getCustomerAddressList = async () => {
|
||||
|
|
@ -621,7 +737,7 @@ const resFrom = (init = {}) => {
|
|||
invoiceName: '',
|
||||
invoiceCode: '',
|
||||
invoiceRemarks: '',
|
||||
contractCode: '',
|
||||
contractCode: 'tmp1',
|
||||
retailerCode: '',
|
||||
remarks: '',
|
||||
isBatch: false,
|
||||
|
|
|
|||
|
|
@ -236,6 +236,16 @@
|
|||
/>
|
||||
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
|
||||
<router-link :to="'/order/createorder?id='+scope.row.id+'&_t=2'">
|
||||
<el-button
|
||||
link
|
||||
type="primary">
|
||||
<Icon icon="ep:edit" />
|
||||
修改
|
||||
</el-button>
|
||||
</router-link>
|
||||
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
ALTER TABLE oms_saleorder ADD COLUMN `order_follower_user` VARCHAR(128) DEFAULT NULL COMMENT '跟单员id system_user.id';
|
||||
|
||||
ALTER TABLE oms_product_info ADD COLUMN `template_type` VARCHAR(10) DEFAULT 1 COMMENT '模板类型-字典product_draft_template_type 1有模板 2无模板 3尺码唛';
|
||||
|
||||
|
||||
ALTER TABLE oms_sale_order_sku ADD COLUMN `product_template_type` VARCHAR(10) DEFAULT 1 COMMENT '模板类型-字典product_draft_template_type 1有模板 2无模板 3尺码唛';
|
||||
|
||||
ALTER TABLE oms_sale_order_sku ADD COLUMN `label_size` VARCHAR(64) DEFAULT NULL COMMENT '尺码唛的尺码';
|
||||
|
||||
|
||||
ALTER TABLE oms_saleorder_entry
|
||||
ADD COLUMN `unit` VARCHAR(64) DEFAULT NULL COMMENT '计量单位'
|
||||
AFTER `qty`;
|
||||
Loading…
Reference in New Issue