diff --git a/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/util/validation/ValidationUtils.java b/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/util/validation/ValidationUtils.java index fdb573f..a82b2ab 100644 --- a/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/util/validation/ValidationUtils.java +++ b/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/util/validation/ValidationUtils.java @@ -24,11 +24,20 @@ public class ValidationUtils { private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*"); + private static final Pattern PATTERN_EMAIL = Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"); + public static boolean isMobile(String mobile) { return StringUtils.hasText(mobile) && PATTERN_MOBILE.matcher(mobile).matches(); } + public static boolean isEmail(String email) { + + return StringUtils.hasText(email) + && PATTERN_EMAIL.matcher(email).matches(); + } + + public static boolean isURL(String url) { return StringUtils.hasText(url) && PATTERN_URL.matcher(url).matches(); diff --git a/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/validation/Email.java b/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/validation/Email.java new file mode 100644 index 0000000..fecb755 --- /dev/null +++ b/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/validation/Email.java @@ -0,0 +1,28 @@ +package cn.hangtag.framework.common.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.PARAMETER, + ElementType.TYPE_USE +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = EmailValidator.class +) +public @interface Email { + + String message() default "邮箱格式不正确"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/validation/EmailValidator.java b/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/validation/EmailValidator.java new file mode 100644 index 0000000..367aa1e --- /dev/null +++ b/hangtag-framework/hangtag-common/src/main/java/cn/hangtag/framework/common/validation/EmailValidator.java @@ -0,0 +1,25 @@ +package cn.hangtag.framework.common.validation; + +import cn.hangtag.framework.common.util.validation.ValidationUtils; +import cn.hutool.core.util.StrUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class EmailValidator implements ConstraintValidator { + + @Override + public void initialize(Email annotation) { + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 如果手机号为空,默认不校验,即校验通过 + if (StrUtil.isEmpty(value)) { + return true; + } + // 校验手机 + return ValidationUtils.isEmail(value); + } + +} diff --git a/hangtag-module-oms/hangtag-module-oms-api/src/main/java/cn/hangtag/module/oms/enums/ErrorCodeConstants.java b/hangtag-module-oms/hangtag-module-oms-api/src/main/java/cn/hangtag/module/oms/enums/ErrorCodeConstants.java index 1f50e36..9e42397 100644 --- a/hangtag-module-oms/hangtag-module-oms-api/src/main/java/cn/hangtag/module/oms/enums/ErrorCodeConstants.java +++ b/hangtag-module-oms/hangtag-module-oms-api/src/main/java/cn/hangtag/module/oms/enums/ErrorCodeConstants.java @@ -24,5 +24,6 @@ public interface ErrorCodeConstants extends cn.hangtag.module.system.enums.Erro ErrorCode PRODUCE_ORDER_IMPORT_LIST_IS_EMPTY = new ErrorCode(4003, "导入生产制单数据不能为空"); ErrorCode SALE_CONTRACT_NOT_EXISTS = new ErrorCode(5000, "OMS销售合约不存在"); ErrorCode PRODUCT_PRICE_NOT_EXISTS = new ErrorCode(600, "产品单价记录不存在"); + ErrorCode CUSTOMER_EMAIL_EXISTS = new ErrorCode(600, "已存在重复的客户邮箱号"); } diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/customer/CustomerServiceImpl.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/customer/CustomerServiceImpl.java index 31f8229..278807e 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/customer/CustomerServiceImpl.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/customer/CustomerServiceImpl.java @@ -13,6 +13,7 @@ import cn.hangtag.module.oms.controller.admin.customer.front.vo.AddressInfoVO; import cn.hangtag.module.oms.controller.admin.customer.front.vo.CustomerInfoVO; import cn.hangtag.module.oms.serialnumber.CodingRulesUtils; import cn.hangtag.module.system.controller.admin.user.vo.user.UserSaveReqVO; +import cn.hangtag.module.system.dal.dataobject.user.AdminUserDO; import cn.hangtag.module.system.service.permission.PermissionService; import cn.hangtag.module.system.service.user.AdminUserService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -74,9 +75,15 @@ public class CustomerServiceImpl implements CustomerService { customer.setNumber(getNewCode()); } + // 判断是否存在重复的邮箱账户 + AdminUserDO user = userService.getUserByMail(createReqVO.getEmail(), 999999); + if(user!=null){ + throw exception(CUSTOMER_EMAIL_EXISTS); + } + //新增用户账号 UserSaveReqVO userSaveReqVO = new UserSaveReqVO(); - userSaveReqVO.setUsername(createReqVO.getPhone()); + userSaveReqVO.setUsername(createReqVO.getEmail()); userSaveReqVO.setNickname(createReqVO.getName()); userSaveReqVO.setMobile(createReqVO.getPhone()); userSaveReqVO.setPassword(userInitPassword); @@ -94,8 +101,6 @@ public class CustomerServiceImpl implements CustomerService { // 插入子表 createCustomerAddressList(customer.getId(), createReqVO.getCustomerAddresss()); - - // 返回 return customer.getId(); } diff --git a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/MailCodeApi.java b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/MailCodeApi.java new file mode 100644 index 0000000..34be135 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/MailCodeApi.java @@ -0,0 +1,43 @@ +package cn.hangtag.module.system.api.mail; + +import cn.hangtag.framework.common.exception.ServiceException; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeSendReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeUseReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeValidateReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; + +import javax.validation.Valid; + +/** + * 短信验证码 API 接口 + * + * @author 芋道源码 + */ +public interface MailCodeApi { + + /** + * 创建邮箱验证码,并进行发送 + * + * @param reqDTO 发送请求 + */ + void sendMailCode(@Valid MailCodeSendReqDTO reqDTO); + + /** + * 验证邮箱验证码,并进行使用 + * 如果正确,则将验证码标记成已使用 + * 如果错误,则抛出 {@link ServiceException} 异常 + * + * @param reqDTO 使用请求 + */ + void useMailCode(@Valid MailCodeUseReqDTO reqDTO); + + /** + * 检查验证码是否有效 + * + * @param reqDTO 校验请求 + */ + void validateMailCode(@Valid MailCodeValidateReqDTO reqDTO); + +} diff --git a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java index fa202be..1301092 100644 --- a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java +++ b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java @@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull; import java.util.Map; /** - * 邮件发送 Request DTO + * 邮箱发送 Request DTO * * @author wangjingqi */ diff --git a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeSendReqDTO.java b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeSendReqDTO.java new file mode 100644 index 0000000..a184806 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeSendReqDTO.java @@ -0,0 +1,37 @@ +package cn.hangtag.module.system.api.mail.dto.code; + +import cn.hangtag.framework.common.validation.Email; +import cn.hangtag.framework.common.validation.InEnum; +import cn.hangtag.module.system.enums.mail.MailSceneEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 邮箱验证码的发送 Request DTO + * + * @author 芋道源码 + */ +@Data +public class MailCodeSendReqDTO { + + /** + * 邮箱 + */ + @Email + @NotEmpty(message = "邮箱不能为空") + private String mail; + /** + * 发送场景 + */ + @NotNull(message = "发送场景不能为空") + @InEnum(MailSceneEnum.class) + private Integer scene; + /** + * 发送 IP + */ + @NotEmpty(message = "发送 IP 不能为空") + private String createIp; + +} diff --git a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeUseReqDTO.java b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeUseReqDTO.java new file mode 100644 index 0000000..c40deb9 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeUseReqDTO.java @@ -0,0 +1,43 @@ +package cn.hangtag.module.system.api.mail.dto.code; + +import cn.hangtag.framework.common.validation.Email; +import cn.hangtag.framework.common.validation.InEnum; +import cn.hangtag.framework.common.validation.Mobile; +import cn.hangtag.module.system.enums.sms.SmsSceneEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 邮箱验证码的使用 Request DTO + * + * @author 芋道源码 + */ +@Data +public class MailCodeUseReqDTO { + + /** + * 邮箱 + */ + @Email + @NotEmpty(message = "邮箱不能为空") + private String mail; + /** + * 发送场景 + */ + @NotNull(message = "发送场景不能为空") + @InEnum(SmsSceneEnum.class) + private Integer scene; + /** + * 验证码 + */ + @NotEmpty(message = "验证码") + private String code; + /** + * 使用 IP + */ + @NotEmpty(message = "使用 IP 不能为空") + private String usedIp; + +} diff --git a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeValidateReqDTO.java b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeValidateReqDTO.java new file mode 100644 index 0000000..67b7bdf --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/api/mail/dto/code/MailCodeValidateReqDTO.java @@ -0,0 +1,37 @@ +package cn.hangtag.module.system.api.mail.dto.code; + +import cn.hangtag.framework.common.validation.InEnum; +import cn.hangtag.framework.common.validation.Mobile; +import cn.hangtag.module.system.enums.sms.SmsSceneEnum; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 邮箱验证码的校验 Request DTO + * + * @author 芋道源码 + */ +@Data +public class MailCodeValidateReqDTO { + + /** + * 手机号 + */ + @Mobile + @NotEmpty(message = "邮箱不能为空") + private String mail; + /** + * 发送场景 + */ + @NotNull(message = "发送场景不能为空") + @InEnum(SmsSceneEnum.class) + private Integer scene; + /** + * 验证码 + */ + @NotEmpty(message = "验证码") + private String code; + +} diff --git a/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/enums/mail/MailSceneEnum.java b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/enums/mail/MailSceneEnum.java new file mode 100644 index 0000000..36e1163 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-api/src/main/java/cn/hangtag/module/system/enums/mail/MailSceneEnum.java @@ -0,0 +1,51 @@ +package cn.hangtag.module.system.enums.mail; + +import cn.hangtag.framework.common.core.IntArrayValuable; +import cn.hutool.core.util.ArrayUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 用户邮箱验证码发送场景的枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MailSceneEnum implements IntArrayValuable { + + MEMBER_LOGIN(1, "user-mail-login", "会员用户 - 邮箱登陆"), + MEMBER_UPDATE_MOBILE(2, "user-update-mail", "会员用户 - 修改手机"), + MEMBER_UPDATE_PASSWORD(3, "user-update-password", "会员用户 - 修改密码"), + MEMBER_RESET_PASSWORD(4, "user-reset-password", "会员用户 - 忘记密码"), + + ADMIN_MEMBER_LOGIN(21, "admin-mail-login", "后台用户 - 邮箱登录"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MailSceneEnum::getScene).toArray(); + + /** + * 验证场景的编号 + */ + private final Integer scene; + /** + * 模版编码 + */ + private final String templateCode; + /** + * 描述 + */ + private final String description; + + @Override + public int[] array() { + return ARRAYS; + } + + public static MailSceneEnum getCodeByScene(Integer scene) { + return ArrayUtil.firstMatch(sceneEnum -> sceneEnum.getScene().equals(scene), + values()); + } + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/api/mail/MailCodeApiImpl.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/api/mail/MailCodeApiImpl.java new file mode 100644 index 0000000..8b6b3c4 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/api/mail/MailCodeApiImpl.java @@ -0,0 +1,44 @@ +package cn.hangtag.module.system.api.mail; + +import cn.hangtag.module.system.api.mail.dto.code.MailCodeSendReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeUseReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeValidateReqDTO; +import cn.hangtag.module.system.api.sms.SmsCodeApi; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; +import cn.hangtag.module.system.service.mail.MailCodeService; +import cn.hangtag.module.system.service.sms.SmsCodeService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +/** + * 短信验证码 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MailCodeApiImpl implements MailCodeApi { + + @Resource + private MailCodeService mailCodeService; + + @Override + public void sendMailCode(MailCodeSendReqDTO reqDTO) { + mailCodeService.sendMailCode(reqDTO); + } + + @Override + public void useMailCode(MailCodeUseReqDTO reqDTO) { + mailCodeService.useMailCode(reqDTO); + } + + @Override + public void validateMailCode(MailCodeValidateReqDTO reqDTO) { + mailCodeService.validateMailCode(reqDTO); + } + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/AuthController.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/AuthController.java index e3c4ea6..e5a1f39 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/AuthController.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/AuthController.java @@ -146,6 +146,27 @@ public class AuthController { return success(true); } + + // ========== 邮箱相关 ========== + + @PostMapping("/send-mail-code") + @PermitAll + @Operation(summary = "发送邮箱验证码") + public CommonResult sendForgetPasswordEmailCode(@RequestBody @Valid AuthMailSendReqVO reqVO) { + authService.sendMailCode(reqVO); + return success(true); + } + + @PostMapping("/mail-modifypwd") + @PermitAll + @Operation(summary = "使用邮箱验证码修改密码") + public CommonResult smsLogin(@RequestBody @Valid AuthMailModifyPwdReqVO reqVO) { + authService.mailResetPwd(reqVO); + return success(true); + } + + + // ========== 社交登录相关 ========== @GetMapping("/social-auth-redirect") diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthLoginReqVO.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthLoginReqVO.java index 2cb5522..8a02415 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthLoginReqVO.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthLoginReqVO.java @@ -23,8 +23,8 @@ public class AuthLoginReqVO { @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "hangtagyuanma") @NotEmpty(message = "登录账号不能为空") - @Length(min = 4, max = 16, message = "账号长度为 4-16 位") - @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母") + //@Length(min = 4, max = 16, message = "账号长度为 4-16 位") + //@Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母") private String username; @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthMailModifyPwdReqVO.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthMailModifyPwdReqVO.java new file mode 100644 index 0000000..ef47e05 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthMailModifyPwdReqVO.java @@ -0,0 +1,41 @@ +package cn.hangtag.module.system.controller.admin.auth.vo; + +import cn.hangtag.framework.common.validation.Email; +import cn.hangtag.framework.common.validation.Mobile; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; + +@Schema(description = "管理后台 - 邮箱验证码的重置密码 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthMailModifyPwdReqVO { + + @Schema(description = "邮箱账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxxxx@qq.com") + @NotEmpty(message = "邮箱账号不能为空") + @Email + private String mail; + + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxxxx@qq.com") + @NotEmpty(message = "密码不能为空") + private String password; + + @Schema(description = "确认密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxxxx@qq.com") + @NotEmpty(message = "确认密码不能为空") + private String checkpassword; + + @Schema(description = "短信验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "验证码不能为空") + private String code; + + @Schema(description = "账户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "账户类型不能为空") + private Integer type; + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthMailSendReqVO.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthMailSendReqVO.java new file mode 100644 index 0000000..d2d944f --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/controller/admin/auth/vo/AuthMailSendReqVO.java @@ -0,0 +1,36 @@ +package cn.hangtag.module.system.controller.admin.auth.vo; + +import cn.hangtag.framework.common.validation.Email; +import cn.hangtag.framework.common.validation.InEnum; +import cn.hangtag.framework.common.validation.Mobile; +import cn.hangtag.module.system.enums.mail.MailSceneEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 发送手机验证码 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AuthMailSendReqVO { + + @Schema(description = "邮箱账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxxxx@qq.com") + @NotEmpty(message = "邮箱账号不能为空") + @Email + private String mail; + + @Schema(description = "邮箱场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发送场景不能为空") + @InEnum(MailSceneEnum.class) + private Integer scene; + + @Schema(description = "账户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "账户类型不能为空") + private Integer type; +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/convert/auth/AuthConvert.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/convert/auth/AuthConvert.java index 940b665..b1ac883 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/convert/auth/AuthConvert.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/convert/auth/AuthConvert.java @@ -1,5 +1,7 @@ package cn.hangtag.module.system.convert.auth; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeSendReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeUseReqDTO; import cn.hutool.core.collection.CollUtil; import cn.hangtag.framework.common.util.object.BeanUtils; import cn.hangtag.module.system.api.sms.dto.code.SmsCodeSendReqDTO; @@ -85,4 +87,8 @@ public interface AuthConvert { SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp); + MailCodeSendReqDTO convert(AuthMailSendReqVO reqVO); + + MailCodeUseReqDTO convert(AuthMailModifyPwdReqVO reqVO, Integer scene, String usedIp); + } diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/dataobject/mail/MailCodeDO.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/dataobject/mail/MailCodeDO.java new file mode 100644 index 0000000..f0c70ce --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/dataobject/mail/MailCodeDO.java @@ -0,0 +1,65 @@ +package cn.hangtag.module.system.dal.dataobject.mail; + +import cn.hangtag.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 邮箱验证码 DO + * + * idx_mobile 索引:基于 {@link #mobile} 字段 + * + * @author 芋道源码 + */ +@TableName("system_mail_code") +@KeySequence("system_mail_code_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MailCodeDO extends BaseDO { + + /** + * 编号 + */ + private Long id; + /** + * 邮箱号 + */ + private String mail; + /** + * 验证码 + */ + private String code; + /** + * 发送场景 + * + * 枚举 {@link MailCodeDO} + */ + private Integer scene; + /** + * 创建 IP + */ + private String createIp; + /** + * 今日发送的第几条 + */ + private Integer todayIndex; + /** + * 是否使用 + */ + private Boolean used; + /** + * 使用时间 + */ + private LocalDateTime usedTime; + /** + * 使用 IP + */ + private String usedIp; + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/mail/MailCodeMapper.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/mail/MailCodeMapper.java new file mode 100644 index 0000000..7a64ee4 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/mail/MailCodeMapper.java @@ -0,0 +1,29 @@ +package cn.hangtag.module.system.dal.mysql.mail; + +import cn.hangtag.framework.mybatis.core.mapper.BaseMapperX; +import cn.hangtag.framework.mybatis.core.query.QueryWrapperX; +import cn.hangtag.module.system.dal.dataobject.mail.MailCodeDO; +import cn.hangtag.module.system.dal.dataobject.sms.SmsCodeDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MailCodeMapper extends BaseMapperX { + + /** + * 获得手机号的最后一个手机验证码 + * + * @param mail 手机号 + * @param scene 发送场景,选填 + * @param code 验证码 选填 + * @return 手机验证码 + */ + default MailCodeDO selectLastByMail(String mail, String code, Integer scene) { + return selectOne(new QueryWrapperX() + .eq("mail", mail) + .eqIfPresent("scene", scene) + .eqIfPresent("code", code) + .orderByDesc("id") + .limitN(1)); + } + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/user/AdminUserMapper.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/user/AdminUserMapper.java index 1a6d0f8..88be2d7 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/user/AdminUserMapper.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/dal/mysql/user/AdminUserMapper.java @@ -25,6 +25,10 @@ public interface AdminUserMapper extends BaseMapperX { return selectOne(AdminUserDO::getEmail, email); } + default AdminUserDO selectByEmail(String email,Integer type) { + return selectOne(AdminUserDO::getEmail, email,AdminUserDO::getDeptId,type); + } + default AdminUserDO selectByMobile(String mobile) { return selectOne(AdminUserDO::getMobile, mobile); } diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthService.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthService.java index a03f502..a2b2e0b 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthService.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthService.java @@ -70,4 +70,14 @@ public interface AdminAuthService { */ AuthLoginRespVO refreshToken(String refreshToken); + + /** + * 邮箱验证码发送 + * + * @param reqVO 发送请求 + */ + void sendMailCode(AuthMailSendReqVO reqVO); + + + boolean mailResetPwd(AuthMailModifyPwdReqVO reqVO); } diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthServiceImpl.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthServiceImpl.java index 81a594a..dd92152 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthServiceImpl.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/auth/AdminAuthServiceImpl.java @@ -1,5 +1,8 @@ package cn.hangtag.module.system.service.auth; +import cn.hangtag.module.system.api.mail.MailCodeApi; +import cn.hangtag.module.system.dal.mysql.user.AdminUserMapper; +import cn.hangtag.module.system.enums.mail.MailSceneEnum; import cn.hutool.core.util.ObjectUtil; import cn.hangtag.framework.common.enums.CommonStatusEnum; import cn.hangtag.framework.common.enums.UserTypeEnum; @@ -29,6 +32,7 @@ import com.xingyuv.captcha.model.vo.CaptchaVO; import com.xingyuv.captcha.service.CaptchaService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -64,6 +68,13 @@ public class AdminAuthServiceImpl implements AdminAuthService { private CaptchaService captchaService; @Resource private SmsCodeApi smsCodeApi; + @Resource + private MailCodeApi mailCodeApi; + @Resource + private PasswordEncoder passwordEncoder; + @Resource + private AdminUserMapper userMapper; + /** * 验证码的开关,默认为 true @@ -247,4 +258,43 @@ public class AdminAuthServiceImpl implements AdminAuthService { return UserTypeEnum.ADMIN; } + + @Override + public void sendMailCode(AuthMailSendReqVO reqVO) { + // 登录场景,验证是否存在 + if (userService.getUserByMail(reqVO.getMail(),reqVO.getType()) == null) { + throw exception(MAIL_ACCOUNT_NOT_EXISTS); + } + // 发送验证码 + mailCodeApi.sendMailCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP())); + } + + @Override + public boolean mailResetPwd(AuthMailModifyPwdReqVO reqVO) { + // 校验验证码 + mailCodeApi.useMailCode(AuthConvert.INSTANCE.convert(reqVO, MailSceneEnum.MEMBER_RESET_PASSWORD.getScene(), getClientIP())); + + // 获得用户信息 + AdminUserDO user = userService.getUserByMail(reqVO.getMail(),reqVO.getType()); + if (user == null) { + throw exception(USER_NOT_EXISTS); + } + // 执行更新 + user.setPassword(encodePassword(reqVO.getPassword())); // 加密密码 + int i = userMapper.updateById(user); + return true; + } + + + /** + * 对密码进行加密 + * + * @param password 密码 + * @return 加密后的密码 + */ + private String encodePassword(String password) { + return passwordEncoder.encode(password); + } + + } diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailCodeService.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailCodeService.java new file mode 100644 index 0000000..9935349 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailCodeService.java @@ -0,0 +1,42 @@ +package cn.hangtag.module.system.service.mail; + +import cn.hangtag.framework.common.exception.ServiceException; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeSendReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeUseReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeValidateReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.hangtag.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; + +import javax.validation.Valid; + +/** + * 短信验证码 Service 接口 + * + * @author 芋道源码 + */ +public interface MailCodeService { + + /** + * 创建邮件验证码,并进行发送 + * + * @param reqDTO 发送请求 + */ + void sendMailCode(@Valid MailCodeSendReqDTO reqDTO); + + /** + * 验证邮件验证码,并进行使用 + * 如果正确,则将验证码标记成已使用 + * 如果错误,则抛出 {@link ServiceException} 异常 + * + * @param reqDTO 使用请求 + */ + void useMailCode(@Valid MailCodeUseReqDTO reqDTO); + + /** + * 检查验证码是否有效 + * + * @param reqDTO 校验请求 + */ + void validateMailCode(@Valid MailCodeValidateReqDTO reqDTO); + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailCodeServiceImpl.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailCodeServiceImpl.java new file mode 100644 index 0000000..c26c7e5 --- /dev/null +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailCodeServiceImpl.java @@ -0,0 +1,122 @@ +package cn.hangtag.module.system.service.mail; + +import cn.hangtag.module.system.api.mail.dto.code.MailCodeSendReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeUseReqDTO; +import cn.hangtag.module.system.api.mail.dto.code.MailCodeValidateReqDTO; +import cn.hangtag.module.system.dal.dataobject.mail.MailCodeDO; +import cn.hangtag.module.system.dal.dataobject.sms.SmsCodeDO; +import cn.hangtag.module.system.dal.mysql.mail.MailCodeMapper; +import cn.hangtag.module.system.enums.mail.MailSceneEnum; +import cn.hangtag.module.system.enums.sms.SmsSceneEnum; +import cn.hangtag.module.system.framework.sms.config.SmsCodeProperties; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapUtil; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.LinkedHashMap; + +import static cn.hangtag.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.hangtag.framework.common.util.date.DateUtils.isToday; +import static cn.hangtag.module.system.enums.ErrorCodeConstants.*; +import static cn.hutool.core.util.RandomUtil.randomInt; + +/** + * 邮箱验证码 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MailCodeServiceImpl implements MailCodeService { + + @Resource + private SmsCodeProperties smsCodeProperties; + + @Resource + private MailCodeMapper mailCodeMapper; + + @Resource + private MailSendService mailSendService; + + @Override + public void sendMailCode(MailCodeSendReqDTO reqDTO) { + MailSceneEnum sceneEnum = MailSceneEnum.getCodeByScene(reqDTO.getScene()); + Assert.notNull(sceneEnum, "验证码场景({}) 查找不到配置", reqDTO.getScene()); + // 创建验证码 + String code = createMailCode(reqDTO.getMail(), reqDTO.getScene(), reqDTO.getCreateIp()); + + LinkedHashMap params = new LinkedHashMap<>(); + params.put("key1",reqDTO.getMail()); + params.put("key2",reqDTO.getMail()); + params.put("key3",code); + String templateCode = sceneEnum.getTemplateCode(); + + // 发送验证码 + mailSendService.sendSingleMail(reqDTO.getMail(), null, null, + sceneEnum.getTemplateCode(), params); + } + + private String createMailCode(String mobile, Integer scene, String ip) { + // 校验是否可以发送验证码,不用筛选场景 + MailCodeDO lastMailCode = mailCodeMapper.selectLastByMail(mobile, null, null); + if (lastMailCode != null) { + if (LocalDateTimeUtil.between(lastMailCode.getCreateTime(), LocalDateTime.now()).toMillis() + < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁 + throw exception(SMS_CODE_SEND_TOO_FAST); + } + if (isToday(lastMailCode.getCreateTime()) && // 必须是今天,才能计算超过当天的上限 + lastMailCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。 + throw exception(SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); + } + // TODO 芋艿:提升,每个 IP 每天可发送数量 + // TODO 芋艿:提升,每个 IP 每小时可发送数量 + } + + // 创建验证码记录 + String code = String.format("%0" + smsCodeProperties.getEndCode().toString().length() + "d", + randomInt(smsCodeProperties.getBeginCode(), smsCodeProperties.getEndCode() + 1)); + MailCodeDO newSmsCode = MailCodeDO.builder().mail(mobile).code(code).scene(scene) + .todayIndex(lastMailCode != null && isToday(lastMailCode.getCreateTime()) ? lastMailCode.getTodayIndex() + 1 : 1) + .createIp(ip).used(false).build(); + mailCodeMapper.insert(newSmsCode); + return code; + } + + @Override + public void useMailCode(MailCodeUseReqDTO reqDTO) { + // 检测验证码是否有效 + MailCodeDO lastMailCode = validateMailCode0(reqDTO.getMail(), reqDTO.getCode(), reqDTO.getScene()); + // 使用验证码 + mailCodeMapper.updateById(MailCodeDO.builder().id(lastMailCode.getId()) + .used(true).usedTime(LocalDateTime.now()).usedIp(reqDTO.getUsedIp()).build()); + } + + @Override + public void validateMailCode(MailCodeValidateReqDTO reqDTO) { + validateMailCode0(reqDTO.getMail(), reqDTO.getCode(), reqDTO.getScene()); + } + + private MailCodeDO validateMailCode0(String mobile, String code, Integer scene) { + // 校验验证码 + MailCodeDO lastMailCode = mailCodeMapper.selectLastByMail(mobile, code, scene); + // 若验证码不存在,抛出异常 + if (lastMailCode == null) { + throw exception(SMS_CODE_NOT_FOUND); + } + // 超过时间 + if (LocalDateTimeUtil.between(lastMailCode.getCreateTime(), LocalDateTime.now()).toMillis() + >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期 + throw exception(SMS_CODE_EXPIRED); + } + // 判断验证码是否已被使用 + if (Boolean.TRUE.equals(lastMailCode.getUsed())) { + throw exception(SMS_CODE_USED); + } + return lastMailCode; + } + +} diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailTemplateServiceImpl.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailTemplateServiceImpl.java index e5a7c8f..eaf12ba 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailTemplateServiceImpl.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/mail/MailTemplateServiceImpl.java @@ -12,6 +12,7 @@ import cn.hangtag.module.system.dal.mysql.mail.MailTemplateMapper; import cn.hangtag.module.system.dal.redis.RedisKeyConstants; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -41,7 +42,7 @@ public class MailTemplateServiceImpl implements MailTemplateService { /** * 正则表达式,匹配 {} 中的变量 */ - private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); + private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{\\{(.*?)}}"); @Resource private MailTemplateMapper mailTemplateMapper; @@ -122,6 +123,12 @@ public class MailTemplateServiceImpl implements MailTemplateService { @Override public String formatMailTemplateContent(String content, Map params) { + if(StringUtils.isNotBlank(content)){ +/* content = content.replaceFirst("

", "").replace("

", ""); + content = content.replaceAll("<", "<").replaceAll(">", ">"); + content = content.replaceAll(" ", "");*/ + content = content.replaceAll("\\{\\{", "{").replaceAll("}}","}"); + } return StrUtil.format(content, params); } diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserService.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserService.java index 79430fa..5e8cc85 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserService.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserService.java @@ -201,4 +201,15 @@ public interface AdminUserService { */ boolean isPasswordMatch(String rawPassword, String encodedPassword); + + + /** + * 通过邮箱号获取用户 + * + * @param mail 邮箱号 + * @return 用户对象信息 + */ + AdminUserDO getUserByMail(String mail,Integer type); + + } diff --git a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserServiceImpl.java b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserServiceImpl.java index 8df27eb..5b578b3 100644 --- a/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserServiceImpl.java +++ b/hangtag-module-system/hangtag-module-system-biz/src/main/java/cn/hangtag/module/system/service/user/AdminUserServiceImpl.java @@ -496,6 +496,11 @@ public class AdminUserServiceImpl implements AdminUserService { return passwordEncoder.matches(rawPassword, encodedPassword); } + @Override + public AdminUserDO getUserByMail(String mail,Integer type) { + return userMapper.selectByEmail(mail,type); + } + /** * 对密码进行加密 * diff --git a/hangtag-ui/hangtag-ui-admin/public/favicon.ico b/hangtag-ui/hangtag-ui-admin/public/favicon.ico index 5a7de08..b7f57f7 100644 Binary files a/hangtag-ui/hangtag-ui-admin/public/favicon.ico and b/hangtag-ui/hangtag-ui-admin/public/favicon.ico differ diff --git a/hangtag-ui/hangtag-ui-admin/public/favicon1.ico b/hangtag-ui/hangtag-ui-admin/public/favicon1.ico new file mode 100644 index 0000000..5a7de08 Binary files /dev/null and b/hangtag-ui/hangtag-ui-admin/public/favicon1.ico differ diff --git a/hangtag-ui/hangtag-ui-admin/src/assets/imgs/logo.png b/hangtag-ui/hangtag-ui-admin/src/assets/imgs/logo.png index 7e1043f..d95b8c1 100644 Binary files a/hangtag-ui/hangtag-ui-admin/src/assets/imgs/logo.png and b/hangtag-ui/hangtag-ui-admin/src/assets/imgs/logo.png differ diff --git a/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DesignPropEdit.vue b/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DesignPropEdit.vue index 2268da4..135ddb5 100644 --- a/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DesignPropEdit.vue +++ b/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DesignPropEdit.vue @@ -46,7 +46,7 @@
- +
@@ -66,7 +66,7 @@
- + + { for (let i = 0; i < infoList.length; i++) { mapping[infoList[i].label] = infoList[i].langMapping; } + that.propInfo[key].processType = findProcessTypeIndex(index); // 多语言变量替换 const allData = [...that.propInfo[key].dataInfo] const fLang = allData[0].locale; @@ -563,7 +565,7 @@ const findProcessTypeIndex = (index) => { const washingInfoListByType = (type, index = -1) => { const typeIndex = findProcessTypeIndex(index); return that.washingInfoList.filter(item => { - if (item.type === type && (typeIndex < 0 || (item.processType === `${typeIndex}`))) { + if (`${item.type}` === `${type}` && (typeIndex < 0 || (`${item.processType}` === `${typeIndex}`))) { return item } }) @@ -896,18 +898,17 @@ const checkPropInfo = (info) => { for (let i = 0; i < that.propOrderByList.length; i++) { keys.push(that.propOrderByList[i].key); } - - endloop: for (let i = 0; i < keys.length; i++) { + console.log("keys",keys) + for (let i = 0; i < keys.length; i++) { const key = keys[i]; - // 合并相同语言的文字 - let newArr = []; // 每种语言合并成一句话 const allLang = findGroupAllLang(key, newInfo2); - const firstLang = newInfo[key].dataInfo[0].locale; const linkChar = newInfo[key].linkChar || ''; const dataInfoArr = newInfo[key].dataInfo; let langList = newInfo[key].langList || []; + console.log("newInfo[key].groupType",newInfo[key]) if (newInfo[key].groupType === GroupTypeEnum.RATIO) { + // 成分比例 都进行固定语言组合 // 获取到所以的成分 let langSort = newInfo[key].langSort || []; @@ -937,6 +938,8 @@ const checkPropInfo = (info) => { for (let j = 0; j < langSort.length; j++) { const labelInfo = [] let allRatio = 0; // 累计 比例 + const langLabel = []; + let linkChar = "," for (let k = 0; k < langList.length; k++) { if (langSort[j] === langList[k].locale) { let tmpValue = `${langList[k].value}`.replaceAll('${r}', `${str}`) @@ -946,9 +949,17 @@ const checkPropInfo = (info) => { if (str === null || str === undefined || str === -1) { str = '' } - mergeLabel.push(tmpValue) + console.log("langList[k]",langList[k]) + if(langList[k].linkChar && linkChar != ','){ + linkChar = langList[k] + } + langLabel.push(tmpValue) } } + if(langLabel.length > 0){ + mergeLabel.push(langLabel.join(linkChar)) + } + let flag = false; // 校验 for (let k = 0; k < dataInfoArr.length; k++) { @@ -1006,7 +1017,6 @@ const checkPropInfo = (info) => { if (newInfo[kKey].groupName === newInfo[key].parentId) { newKey = kKey; parentStr = newInfo[kKey].dataInfo[0].label + '
' - break; } } @@ -1021,24 +1031,28 @@ const checkPropInfo = (info) => { // 语言对应自己的自动位置 if (newInfo[key].multiLanguage) { + const showLabel1 = newInfo[key].dataInfo[0].showLabel if (newInfo[key].groupType === GroupTypeEnum.ICON) { const infoList = washingInfoListByType(newInfo[key].groupType) const infos = newInfo[key].dataInfo; for (let j = 1; j < infos.length; j++) { + outerLoop: for (let i = 0; i < infoList.length; i++) { const row1 = infoList[i]; - for (let k = 0; k < row1.langMapping.length; k++) { - // 跳过icon 类型,因为没有url - if (infos[j].locale === row1.langMapping[k].locale) { - infos[j].label = row1.langMapping[k].value - break outerLoop; + if(`${row1.processType}` === `${ newInfo[key].processType}`){ + for (let k = 0; k < row1.langMapping.length; k++) { + // 跳过icon 类型,因为没有url + if (infos[j].locale === row1.langMapping[k].locale && showLabel1 === row1.value) { + infos[j].label = row1.langMapping[k].value + break outerLoop; + } } } } } console.log("newArr33",infos) newInfo[key].dataInfo = infos; - break; + }else { const infoList = washingInfoListByType(newInfo[key].groupType) const infos = newInfo[key].dataInfo; @@ -1054,41 +1068,55 @@ const checkPropInfo = (info) => { } } } - console.log("newArr33",infos) + console.log("newArr99",infos) newInfo[key].dataInfo = infos; - break; + } } else { // 多种语言组合成一句话 // 文本类型处理 if (newInfo[key].groupType === GroupTypeEnum.TEXT) { + let langSort = newInfo[key].langSort || []; if (langSort.length === 0) { langSort = allLang } let mergeLabel = []; - for (let j = 0; j < langSort.length; j++) { - const labelInfo = [] - for (let k = 0; k < langList.length; k++) { - if (langSort[j] === langList[k].locale && newInfo[key].dataInfo[k].showLabel) { - mergeLabel.push(langList[k].value) + + if(newInfo[key].canInput){ + for (let j = 0; j < dataInfoArr.length; j++) { + if (dataInfoArr[j].showLabel) { + if(mergeLabel.includes(dataInfoArr[j].showLabel)){ + useMessage().notifyWarning(`${newInfo[key].groupName}中,第${j + 1}项重复${dataInfoArr[j].showLabel}`) + } + mergeLabel.push(dataInfoArr[j].showLabel) } } - // 校验重复 - for (let k = 0; k < dataInfoArr.length; k++) { - if (langSort[j] === newInfo[key].dataInfo[k].locale) { - if (newInfo[key].dataInfo[k].showLabel) { - if (labelInfo.includes(newInfo[key].dataInfo[k].showLabel)) { - useMessage().notifyError(`${newInfo[key].groupName}中第${labelInfo.length + 1}项重复`); - that.errorList.push({ - key: `${key}_${k}`, - message: "数据重复" - }) - reject("数据重复") - return + }else { + for (let j = 0; j < langSort.length; j++) { + const labelInfo = [] + for (let k = 0; k < langList.length; k++) { + console.log("newInfo[key].dataInfo[k]",newInfo[key].dataInfo[k]) + if (langSort[j] === langList[k].locale) { + mergeLabel.push(langList[k].value) + } + } + // 校验重复 + for (let k = 0; k < dataInfoArr.length; k++) { + if (langSort[j] === newInfo[key].dataInfo[k].locale) { + if (newInfo[key].dataInfo[k].showLabel) { + if (labelInfo.includes(newInfo[key].dataInfo[k].showLabel)) { + useMessage().notifyError(`${newInfo[key].groupName}中第${labelInfo.length + 1}项重复`); + that.errorList.push({ + key: `${key}_${k}`, + message: "数据重复" + }) + reject("数据重复") + return + } + labelInfo.push(newInfo[key].dataInfo[k].showLabel) } - labelInfo.push(newInfo[key].dataInfo[k].showLabel) } } } @@ -1374,7 +1402,7 @@ defineExpose({ } .error_tip { - box-shadow: rgb(255, 0, 0) 0px 0px 2px 1px; + box-shadow: rgb(255, 0, 0) 0 0 2px 1px; } diff --git a/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DynamicPropConfig.vue b/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DynamicPropConfig.vue index 92c5f49..3c7037f 100644 --- a/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DynamicPropConfig.vue +++ b/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/components/DynamicPropConfig.vue @@ -49,7 +49,7 @@
- 允许调整数量 diff --git a/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/index.vue b/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/index.vue index a7d4e15..8a1ee6c 100644 --- a/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/index.vue +++ b/hangtag-ui/hangtag-ui-admin/src/components/DraftDesign/index.vue @@ -1462,6 +1462,7 @@ const handlerGroupList = (cells, isCombo = false, min, max) => { canChange = that.pageConfig.propList[i].canChange === true canInput = that.pageConfig.propList[i].canInput === true langSort = that.pageConfig.propList[i].langSort || [] + linkChar = that.pageConfig.propList[i].linkChar || ',' break; } } diff --git a/hangtag-ui/hangtag-ui-admin/src/views/oms/customer/CustomerForm.vue b/hangtag-ui/hangtag-ui-admin/src/views/oms/customer/CustomerForm.vue index 969fb4e..fbbb6ef 100644 --- a/hangtag-ui/hangtag-ui-admin/src/views/oms/customer/CustomerForm.vue +++ b/hangtag-ui/hangtag-ui-admin/src/views/oms/customer/CustomerForm.vue @@ -37,7 +37,7 @@ - + @@ -175,6 +175,7 @@ const formRules = reactive({ } ], email: [ + { required: true, message: '邮箱不能为空', trigger: 'blur' }, { type: 'email', message: '请输入正确的邮箱地址', diff --git a/hangtag-ui/hangtag-ui-admin/src/views/oms/produceorder/template1.js b/hangtag-ui/hangtag-ui-admin/src/views/oms/produceorder/template1.js index 6378c08..a356b1d 100644 --- a/hangtag-ui/hangtag-ui-admin/src/views/oms/produceorder/template1.js +++ b/hangtag-ui/hangtag-ui-admin/src/views/oms/produceorder/template1.js @@ -6,8 +6,24 @@ export default { "height": 296.6, "width": 210, "paperHeader": 0, - "paperFooter": 840.7559055118112, + "paperFooter": 837, "printElements": [ + { + "options": { + "left": 54, + "top": -4.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, { "options": { "left": 168, @@ -36,23 +52,27 @@ export default { "options": { "left": 258, "top": 54, - "height": 9.75, + "height": 16, "width": 200, - "title": "生产单编号", - "right": 414.74388885498047, - "bottom": 49.49592590332031, - "vCenter": 354.74388885498047, - "hCenter": 44.62092590332031, - "field": "billno", + "field": "clerk", + "testData": "XS888888888", + "fontSize": 7.75, + "fontWeight": "700", + "textAlign": "left", + "textContentVerticalAlign": "middle", + "title": "职员", + "qid": "clerk", + "right": 460.9959259033203, + "bottom": 69.997971534729, + "vCenter": 360.9959259033203, + "hCenter": 61.997971534729004, "coordinateSync": false, "widthHeightSync": false, - "fontSize": 7.5, - "fontWeight": "700", "qrCodeLevel": 0, "fixed": true }, "printElementType": { - "title": "文本", + "title": "订单编号", "type": "text" } }, @@ -61,7 +81,7 @@ export default { "left": 474, "top": 54, "height": 9.75, - "width": 120, + "width": 124, "title": "批次", "right": 587.2480087280273, "bottom": 48.741851806640625, @@ -92,7 +112,7 @@ export default { "fontWeight": "700", "textAlign": "left", "textContentVerticalAlign": "middle", - "title": "主生产单编号", + "title": "生产单编号", "qid": "billno", "coordinateSync": false, "widthHeightSync": false, @@ -156,30 +176,6 @@ export default { "type": "text" } }, - { - "options": { - "left": 258, - "top": 99.66666666666666, - "height": 9.75, - "width": 200, - "title": "生产日期", - "right": 318.74796295166016, - "bottom": 115.49387741088867, - "vCenter": 258.74796295166016, - "hCenter": 110.61887741088867, - "field": "produceDateStr", - "coordinateSync": false, - "widthHeightSync": false, - "fontSize": 7.5, - "fontWeight": "700", - "qrCodeLevel": 0, - "fixed": true - }, - "printElementType": { - "title": "文本", - "type": "text" - } - }, { "options": { "left": 13.5, @@ -204,6 +200,30 @@ export default { "type": "text" } }, + { + "options": { + "left": 258, + "top": 99.66666666666666, + "height": 9.75, + "width": 200, + "title": "生产日期", + "right": 318.74796295166016, + "bottom": 115.49387741088867, + "vCenter": 258.74796295166016, + "hCenter": 110.61887741088867, + "field": "produceDateStr", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, { "options": { "left": 474, @@ -489,38 +509,10 @@ export default { "type": "text" } }, - { - "options": { - "left": 13.5, - "top": 236.66666666666669, - "height": 16, - "width": 200, - "field": "clerk", - "testData": "XS888888888", - "fontSize": 7.75, - "fontWeight": "700", - "textAlign": "left", - "textContentVerticalAlign": "middle", - "title": "职员", - "qid": "clerk", - "right": 132.74185180664062, - "bottom": 264.24796295166016, - "vCenter": 72.74185180664062, - "hCenter": 256.24796295166016, - "coordinateSync": false, - "widthHeightSync": false, - "qrCodeLevel": 0, - "fixed": true - }, - "printElementType": { - "title": "订单编号", - "type": "text" - } - }, { "options": { "left": 258, - "top": 259.5, + "top": 237, "height": 16, "width": 200, "field": "reportTimeStr", @@ -548,7 +540,7 @@ export default { { "options": { "left": 13.5, - "top": 259.5, + "top": 237, "height": 16, "width": 200, "field": "reportDateStr", @@ -575,10 +567,10 @@ export default { }, { "options": { - "left": 13.5, - "top": 297, - "height": 16, - "width": 46.5, + "left": 15, + "top": 260, + "height": 15, + "width": 50, "fontSize": 9, "fontWeight": "700", "textAlign": "left", @@ -600,17 +592,37 @@ export default { "type": "text" } }, + { + "options": { + "left": 60, + "top": 262.5, + "height": 178.5, + "width": 532, + "right": 587.5, + "bottom": 453.7449760437012, + "vCenter": 321.5, + "hCenter": 358.4949760437012, + "field": "details", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "", + "type": "longText" + } + }, { "options": { "left": 15, - "top": 490, - "height": 43.5, - "width": 565.5, + "top": 444, + "height": 50, + "width": 575, "title": "备注", - "right": 582, - "bottom": 444.75, - "vCenter": 297.75, - "hCenter": 426, + "right": 583.5, + "bottom": 487.4950575828552, + "vCenter": 300.75, + "hCenter": 464.9950575828552, "coordinateSync": false, "widthHeightSync": false, "qrCodeLevel": 0, @@ -626,8 +638,8 @@ export default { { "options": { "left": 15, - "top": 538.5, - "height": 17, + "top": 501, + "height": 20, "width": 120, "fontSize": 9, "fontWeight": "700", @@ -652,9 +664,9 @@ export default { }, { "options": { - "left": 27, - "top": 556.5, - "height": 16, + "left": 25, + "top": 520, + "height": 20, "width": 120, "fontSize": 7.5, "fontWeight": "700", @@ -662,10 +674,10 @@ export default { "textContentVerticalAlign": "middle", "title": "设计部A", "qid": "orderId_10", - "right": 162.74388885498047, - "bottom": 564.2459487915039, - "vCenter": 102.74388885498047, - "hCenter": 556.2459487915039, + "right": 149.24574279785156, + "bottom": 481.74146270751953, + "vCenter": 89.24574279785156, + "hCenter": 473.74146270751953, "coordinateSync": false, "widthHeightSync": false, "hideTitle": true, @@ -679,10 +691,10 @@ export default { }, { "options": { - "left": 176, - "top": 573, - "height": 9.75, - "width": 120, + "left": 171, + "top": 540, + "height": 25, + "width": 100, "title": "完成数量", "right": 473.99800872802734, "bottom": 591.0000114440918, @@ -703,15 +715,15 @@ export default { }, { "options": { - "left": 325, - "top": 573, - "height": 9.75, - "width": 120, + "left": 318, + "top": 540, + "height": 25, + "width": 100, "title": "锌板用量", - "right": 505.4959487915039, - "bottom": 577.4959373474121, - "vCenter": 445.4959487915039, - "hCenter": 572.6209373474121, + "right": 416.5, + "bottom": 503.5, + "vCenter": 366.5, + "hCenter": 491, "coordinateSync": false, "widthHeightSync": false, "qrCodeLevel": 0, @@ -727,40 +739,15 @@ export default { }, { "options": { - "left": 27, - "top": 573, - "height": 9.75, - "width": 120, - "title": "生产单编号", - "right": 146.99388885498047, - "bottom": 584.2438888549805, - "vCenter": 86.99388885498047, - "hCenter": 579.3688888549805, - "field": "asdas", - "testData": "asdsa", - "coordinateSync": false, - "widthHeightSync": false, - "fontSize": 7.5, - "fontWeight": "700", - "qrCodeLevel": 0, - "fixed": true - }, - "printElementType": { - "title": "文本", - "type": "text" - } - }, - { - "options": { - "left": 474, - "top": 573, - "height": 9.75, - "width": 120, + "left": 462, + "top": 540, + "height": 25, + "width": 100, "title": "日期时间", - "right": 408.74800872802734, - "bottom": 578.2439002990723, - "vCenter": 348.74800872802734, - "hCenter": 573.3689002990723, + "right": 583.75, + "bottom": 497.75, + "vCenter": 533.75, + "hCenter": 487.75, "coordinateSync": false, "widthHeightSync": false, "qrCodeLevel": 0, @@ -776,9 +763,101 @@ export default { }, { "options": { - "left": 27, - "top": 600, - "height": 16, + "left": 25, + "top": 540, + "height": 25, + "width": 100, + "title": "生产单编号", + "right": 146.24574279785156, + "bottom": 492.99359130859375, + "vCenter": 86.24574279785156, + "hCenter": 487.99359130859375, + "field": " asdas", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 69, + "top": 550.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 354, + "top": 553.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 553.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 587.25, + "bottom": 514.25, + "vCenter": 542.25, + "hCenter": 504.25 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 555, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 558, + "height": 20, "width": 120, "fontSize": 7.5, "fontWeight": "700", @@ -786,10 +865,10 @@ export default { "textContentVerticalAlign": "middle", "title": "切纸部B", "qid": "orderId_10", - "right": 210, - "bottom": 524.5, - "vCenter": 150, - "hCenter": 516.5, + "right": 146.24507904052734, + "bottom": 580.2401466369629, + "vCenter": 86.24507904052734, + "hCenter": 570.2401466369629, "coordinateSync": false, "widthHeightSync": false, "hideTitle": true, @@ -803,10 +882,10 @@ export default { }, { "options": { - "left": 176, - "top": 617, - "height": 9.75, - "width": 120, + "left": 171, + "top": 575, + "height": 25, + "width": 100, "title": "完成数量", "right": 292.5000228881836, "bottom": 623.9918746948242, @@ -827,10 +906,10 @@ export default { }, { "options": { - "left": 325.5, - "top": 617, - "height": 9.75, - "width": 120, + "left": 318, + "top": 576.5, + "height": 25, + "width": 100, "title": "纸用量", "right": 449.9959487915039, "bottom": 624.7479858398438, @@ -851,10 +930,10 @@ export default { }, { "options": { - "left": 27, - "top": 617, - "height": 9.75, - "width": 120, + "left": 25, + "top": 577, + "height": 25, + "width": 100, "title": "生产单编号", "right": 149.99388885498047, "bottom": 625.5000228881836, @@ -875,22 +954,23 @@ export default { }, { "options": { - "left": 474, - "top": 617, - "height": 9.75, - "width": 120, + "left": 462, + "top": 577.5, + "height": 25, + "width": 100, "title": "日期时间", - "right": 616.4938888549805, - "bottom": 635.2479858398438, - "vCenter": 556.4938888549805, - "hCenter": 630.3729858398438, + "right": 615.7438888549805, + "bottom": 708.7459716796875, + "vCenter": 555.7438888549805, + "hCenter": 703.8709716796875, + "field": "asf", "coordinateSync": false, "widthHeightSync": false, - "qrCodeLevel": 0, - "field": "33", "fontSize": 7.5, "fontWeight": "700", - "fixed": true + "qrCodeLevel": 0, + "fixed": true, + "qid": "asf_2" }, "printElementType": { "title": "文本", @@ -899,9 +979,85 @@ export default { }, { "options": { - "left": 27, - "top": 643.5, - "height": 16, + "left": 69, + "top": 585, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 586.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 314.9901351928711, + "bottom": 547.2426414489746, + "vCenter": 269.9901351928711, + "hCenter": 537.2426414489746 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 354, + "top": 586.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 447.74507904052734, + "bottom": 550.9901695251465, + "vCenter": 402.74507904052734, + "hCenter": 540.9901695251465 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 586.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 705, + "bottom": 540.5, + "vCenter": 660, + "hCenter": 530.5 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 598.5, + "height": 20, "width": 120, "fontSize": 7.5, "fontWeight": "700", @@ -909,10 +1065,10 @@ export default { "textContentVerticalAlign": "middle", "title": "印刷部C", "qid": "orderId_10", - "right": 146.24388885498047, - "bottom": 650.5000228881836, - "vCenter": 86.24388885498047, - "hCenter": 642.5000228881836, + "right": 145.49752807617188, + "bottom": 620.0000114440918, + "vCenter": 85.49752807617188, + "hCenter": 610.0000114440918, "coordinateSync": false, "widthHeightSync": false, "hideTitle": true, @@ -926,34 +1082,10 @@ export default { }, { "options": { - "left": 176, - "top": 660, - "height": 9.75, - "width": 120, - "title": "完成数量", - "right": 287.2500228881836, - "bottom": 671.2439117431641, - "vCenter": 227.2500228881836, - "hCenter": 666.3689117431641, - "field": "gg", - "coordinateSync": false, - "widthHeightSync": false, - "fontSize": 7.5, - "fontWeight": "700", - "qrCodeLevel": 0, - "fixed": true - }, - "printElementType": { - "title": "文本", - "type": "text" - } - }, - { - "options": { - "left": 325, - "top": 660, - "height": 9.75, - "width": 120, + "left": 318, + "top": 611.5, + "height": 25, + "width": 100, "title": "机长", "right": 446.9918746948242, "bottom": 669.7439117431641, @@ -974,22 +1106,23 @@ export default { }, { "options": { - "left": 474, - "top": 660, - "height": 9.75, - "width": 120, + "left": 462, + "top": 613, + "height": 25, + "width": 100, "title": "日期时间", - "right": 603.7500228881836, - "bottom": 669.7500228881836, - "vCenter": 543.7500228881836, - "hCenter": 664.8750228881836, - "field": "cas", + "right": 667.75, + "bottom": 594.5, + "vCenter": 617.75, + "hCenter": 584.5, + "field": "asf", "coordinateSync": false, "widthHeightSync": false, "fontSize": 7.5, "fontWeight": "700", "qrCodeLevel": 0, - "fixed": true + "fixed": true, + "qid": "asf_3" }, "printElementType": { "title": "文本", @@ -998,10 +1131,10 @@ export default { }, { "options": { - "left": 27, - "top": 660, - "height": 9.75, - "width": 120, + "left": 25, + "top": 614.5, + "height": 25, + "width": 100, "title": "生产单编号", "right": 216.7459487915039, "bottom": 675.7459487915039, @@ -1022,15 +1155,111 @@ export default { }, { "options": { - "left": 27, - "top": 687, - "height": 16, + "left": 171, + "top": 616, + "height": 25, + "width": 100, + "title": "完成数量", + "right": 287.2500228881836, + "bottom": 671.2439117431641, + "vCenter": 227.2500228881836, + "hCenter": 666.3689117431641, + "field": "gg", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 69, + "top": 622.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 354, + "top": 625.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "right": 446.2459487915039, + "bottom": 637.4959487915039, + "vCenter": 401.2459487915039, + "hCenter": 632.9959487915039, + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 625.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "right": 609, + "bottom": 574.25, + "vCenter": 564, + "hCenter": 564.25, + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 627, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 627.75, + "height": 20, "width": 120, "fontSize": 7.5, "fontWeight": "700", "textAlign": "left", "textContentVerticalAlign": "middle", - "title": "包装部", + "title": "丝印部D", "qid": "orderId_10", "right": 174, "bottom": 579.25, @@ -1049,34 +1278,10 @@ export default { }, { "options": { - "left": 176.5, - "top": 703.5, - "height": 9.75, - "width": 120, - "title": "完成数量", - "right": 293.2500228881836, - "bottom": 711.0000457763672, - "vCenter": 233.2500228881836, - "hCenter": 706.1250457763672, - "coordinateSync": false, - "widthHeightSync": false, - "qrCodeLevel": 0, - "field": "hhh", - "fontSize": 7.5, - "fontWeight": "700", - "fixed": true - }, - "printElementType": { - "title": "文本", - "type": "text" - } - }, - { - "options": { - "left": 325.5, - "top": 703.5, - "height": 9.75, - "width": 120, + "left": 318, + "top": 646.5, + "height": 25, + "width": 100, "title": "包装员", "right": 468.0000228881836, "bottom": 767.2479858398438, @@ -1088,6 +1293,81 @@ export default { "fontSize": 7.5, "fontWeight": "700", "qrCodeLevel": 0, + "fixed": true, + "qid": "wwww_1" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 25, + "top": 646.5, + "height": 25, + "width": 100, + "title": "生产单编号", + "right": 147.74388885498047, + "bottom": 714.7418975830078, + "vCenter": 87.74388885498047, + "hCenter": 709.8668975830078, + "field": "asda", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true, + "qid": "asda_1" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 171, + "top": 648, + "height": 25, + "width": 100, + "title": "完成数量", + "right": 293.2500228881836, + "bottom": 711.0000457763672, + "vCenter": 233.2500228881836, + "hCenter": 706.1250457763672, + "coordinateSync": false, + "widthHeightSync": false, + "qrCodeLevel": 0, + "field": "hhh", + "fontSize": 7.5, + "fontWeight": "700", + "fixed": true, + "qid": "hhh_1" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 462, + "top": 648, + "height": 25, + "width": 100, + "title": "日期时间", + "right": 687.7421875, + "bottom": 630.5, + "vCenter": 637.7421875, + "hCenter": 620.5, + "field": "asf", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, "fixed": true }, "printElementType": { @@ -1097,10 +1377,562 @@ export default { }, { "options": { - "left": 27.5, - "top": 703.5, - "height": 9.75, + "left": 354, + "top": 657, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "right": 444.0000228881836, + "bottom": 677.9979858398438, + "vCenter": 399.0000228881836, + "hCenter": 673.4979858398438, + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 657, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 617.25, + "bottom": 610.25, + "vCenter": 572.25, + "hCenter": 600.25 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 658.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 69, + "top": 658.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 163.9921875, + "bottom": 605, + "vCenter": 118.9921875, + "hCenter": 595 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 663, + "height": 20, "width": 120, + "fontSize": 7.5, + "fontWeight": "700", + "textAlign": "left", + "textContentVerticalAlign": "middle", + "title": "加工部E", + "qid": "orderId_10", + "right": 174, + "bottom": 579.25, + "vCenter": 114, + "hCenter": 571.25, + "coordinateSync": false, + "widthHeightSync": false, + "hideTitle": true, + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "订单编号", + "type": "text" + } + }, + { + "options": { + "left": 318, + "top": 681.5, + "height": 25, + "width": 100, + "title": "包装员", + "right": 468.0000228881836, + "bottom": 767.2479858398438, + "vCenter": 408.0000228881836, + "hCenter": 762.3729858398438, + "field": "wwww", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true, + "qid": "wwww_2" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 25, + "top": 681.5, + "height": 25, + "width": 100, + "title": "生产单编号", + "right": 147.74388885498047, + "bottom": 714.7418975830078, + "vCenter": 87.74388885498047, + "hCenter": 709.8668975830078, + "field": "asda", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true, + "qid": "asda_2" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 462, + "top": 682.5, + "height": 25, + "width": 100, + "title": "日期时间", + "right": 584.5, + "bottom": 698, + "vCenter": 534.5, + "hCenter": 688, + "field": "cas", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 171, + "top": 683, + "height": 25, + "width": 100, + "title": "完成数量", + "right": 293.2500228881836, + "bottom": 711.0000457763672, + "vCenter": 233.2500228881836, + "hCenter": 706.1250457763672, + "coordinateSync": false, + "widthHeightSync": false, + "qrCodeLevel": 0, + "field": "hhh", + "fontSize": 7.5, + "fontWeight": "700", + "fixed": true, + "qid": "hhh_2" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 354, + "top": 691.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 691.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 616.5, + "bottom": 643.25, + "vCenter": 571.5, + "hCenter": 633.25 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 693, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 69, + "top": 693, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 155.25, + "bottom": 643.25, + "vCenter": 110.25, + "hCenter": 633.25 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 696.75, + "height": 20, + "width": 120, + "fontSize": 7.5, + "fontWeight": "700", + "textAlign": "left", + "textContentVerticalAlign": "middle", + "title": "啤机部G", + "qid": "orderId_10", + "right": 174, + "bottom": 579.25, + "vCenter": 114, + "hCenter": 571.25, + "coordinateSync": false, + "widthHeightSync": false, + "hideTitle": true, + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "订单编号", + "type": "text" + } + }, + { + "options": { + "left": 318, + "top": 716.5, + "height": 25, + "width": 100, + "title": "包装员", + "right": 468.0000228881836, + "bottom": 767.2479858398438, + "vCenter": 408.0000228881836, + "hCenter": 762.3729858398438, + "field": "wwww", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true, + "qid": "wwww_3" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 462, + "top": 716.5, + "height": 25, + "width": 100, + "title": "日期时间", + "right": 585.25, + "bottom": 692.75, + "vCenter": 535.25, + "hCenter": 682.75, + "field": "asf", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true, + "qid": "asf_1" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 25, + "top": 716.5, + "height": 25, + "width": 100, + "title": "生产单编号", + "right": 147.74388885498047, + "bottom": 714.7418975830078, + "vCenter": 87.74388885498047, + "hCenter": 709.8668975830078, + "field": "asda", + "coordinateSync": false, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true, + "qid": "asda_3" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 171, + "top": 718, + "height": 25, + "width": 100, + "title": "完成数量", + "right": 293.2500228881836, + "bottom": 711.0000457763672, + "vCenter": 233.2500228881836, + "hCenter": 706.1250457763672, + "coordinateSync": false, + "widthHeightSync": false, + "qrCodeLevel": 0, + "field": "hhh", + "fontSize": 7.5, + "fontWeight": "700", + "fixed": true, + "qid": "hhh_3" + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 354, + "top": 726, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 440.25, + "bottom": 673.25, + "vCenter": 395.25, + "hCenter": 663.25 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 726, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 623.25, + "bottom": 677, + "vCenter": 578.25, + "hCenter": 667 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 727.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 69, + "top": 727.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 162.75, + "bottom": 659.75, + "vCenter": 117.75, + "hCenter": 649.75 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 732, + "height": 20, + "width": 120, + "fontSize": 7.5, + "fontWeight": "700", + "textAlign": "left", + "textContentVerticalAlign": "middle", + "title": "包装部P", + "qid": "orderId_10", + "right": 174, + "bottom": 579.25, + "vCenter": 114, + "hCenter": 571.25, + "coordinateSync": false, + "widthHeightSync": false, + "hideTitle": true, + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "订单编号", + "type": "text" + } + }, + { + "options": { + "left": 318, + "top": 751.5, + "height": 25, + "width": 100, + "title": "包装员", + "right": 468.0000228881836, + "bottom": 767.2479858398438, + "vCenter": 408.0000228881836, + "hCenter": 762.3729858398438, + "field": "wwww", + "coordinateSync": true, + "widthHeightSync": false, + "fontSize": 7.5, + "fontWeight": "700", + "qrCodeLevel": 0, + "fixed": true + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 462, + "top": 751.5, + "height": 25, + "width": 100, + "title": "日期时间", + "right": 575.74609375, + "bottom": 724.25, + "vCenter": 525.74609375, + "hCenter": 714.25, + "coordinateSync": false, + "widthHeightSync": false, + "qrCodeLevel": 0, + "field": "33", + "fontSize": 7.5, + "fontWeight": "700", + "fixed": true + }, + "printElementType": { + "title": "文本", + "type": "text" + } + }, + { + "options": { + "left": 25, + "top": 751.5, + "height": 25, + "width": 100, "title": "生产单编号", "right": 147.74388885498047, "bottom": 714.7418975830078, @@ -1121,21 +1953,21 @@ export default { }, { "options": { - "left": 474.5, - "top": 703.5, - "height": 9.75, - "width": 120, - "title": "日期时间", - "right": 615.7438888549805, - "bottom": 708.7459716796875, - "vCenter": 555.7438888549805, - "hCenter": 703.8709716796875, - "field": "asf", + "left": 171, + "top": 753, + "height": 25, + "width": 100, + "title": "完成数量", + "right": 293.2500228881836, + "bottom": 711.0000457763672, + "vCenter": 233.2500228881836, + "hCenter": 706.1250457763672, "coordinateSync": false, "widthHeightSync": false, + "qrCodeLevel": 0, + "field": "hhh", "fontSize": 7.5, "fontWeight": "700", - "qrCodeLevel": 0, "fixed": true }, "printElementType": { @@ -1145,9 +1977,81 @@ export default { }, { "options": { - "left": 27, - "top": 730.5, - "height": 9.75, + "left": 354, + "top": 760.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 439.4926071166992, + "bottom": 714.4926414489746, + "vCenter": 394.4926071166992, + "hCenter": 704.4926414489746 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 498, + "top": 760.5, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true, + "right": 605.25, + "bottom": 715.25, + "vCenter": 560.25, + "hCenter": 705.25 + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 205.5, + "top": 762, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 69, + "top": 762, + "height": 20, + "width": 90, + "borderWidth": "0.75", + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 25, + "top": 780, + "height": 20, "width": 555, "title": "物料情况", "field": "xxx", @@ -1166,15 +2070,15 @@ export default { }, { "options": { - "left": 67.5, - "top": 741, - "height": 9, - "width": 513, + "left": 61.5, + "top": 792, + "height": 7, + "width": 530, "borderWidth": "0.75", - "right": 158.24796295166016, - "bottom": 751.4918746948242, - "vCenter": 113.24796295166016, - "hCenter": 746.9918746948242, + "right": 578.9926071166992, + "bottom": 802.4975395202637, + "vCenter": 317.9926071166992, + "hCenter": 797.9975395202637, "coordinateSync": false, "widthHeightSync": false, "fixed": true @@ -1186,66 +2090,10 @@ export default { }, { "options": { - "left": 237, - "top": 804, - "height": 9, - "width": 121.5, - "borderWidth": "0.75", - "right": 359.2418746948242, - "bottom": 797.2479629516602, - "vCenter": 299.9918746948242, - "hCenter": 792.7479629516602, - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 451.5, - "top": 804, - "height": 9, - "width": 130.5, - "borderWidth": "0.75", - "right": 569.2418746948242, - "bottom": 798.7459487915039, - "vCenter": 509.9918746948242, - "hCenter": 794.2459487915039, - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 28.5, - "top": 804, - "height": 9, - "width": 126, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 237.5, - "top": 805, - "height": 16, - "width": 120, + "left": 243, + "top": 810, + "height": 15, + "width": 150, "field": "creater", "testData": "李四", "fontSize": 8.25, @@ -1270,10 +2118,10 @@ export default { }, { "options": { - "left": 451.5, - "top": 805, - "height": 16, - "width": 120, + "left": 462, + "top": 810, + "height": 15, + "width": 150, "field": "creater", "testData": "李四", "fontSize": 8.25, @@ -1298,10 +2146,30 @@ export default { }, { "options": { - "left": 30, - "top": 805, - "height": 16, - "width": 120, + "left": 244.5, + "top": 811.5, + "height": 9, + "width": 122, + "borderWidth": "0.75", + "right": 359.2418746948242, + "bottom": 797.2479629516602, + "vCenter": 299.9918746948242, + "hCenter": 792.7479629516602, + "coordinateSync": false, + "widthHeightSync": false, + "fixed": true + }, + "printElementType": { + "title": "横线", + "type": "hline" + } + }, + { + "options": { + "left": 24, + "top": 811.5, + "height": 12, + "width": 150, "field": "creater", "testData": "李四", "fontSize": 8.25, @@ -1310,10 +2178,10 @@ export default { "textContentVerticalAlign": "middle", "title": "制作人", "qid": "creater", - "right": 150, - "bottom": 796, - "vCenter": 90, - "hCenter": 788, + "right": 178.49752807617188, + "bottom": 822.7500114440918, + "vCenter": 103.49752807617188, + "hCenter": 816.7500114440918, "coordinateSync": false, "widthHeightSync": false, "qrCodeLevel": 0, @@ -1326,11 +2194,15 @@ export default { }, { "options": { - "left": 69, - "top": 585, + "left": 462, + "top": 811.5, "height": 9, - "width": 90, + "width": 122, "borderWidth": "0.75", + "right": 569.2418746948242, + "bottom": 798.7459487915039, + "vCenter": 509.9918746948242, + "hCenter": 794.2459487915039, "coordinateSync": false, "widthHeightSync": false, "fixed": true @@ -1342,10 +2214,10 @@ export default { }, { "options": { - "left": 210, - "top": 585, - "height": 9, - "width": 90, + "left": 24, + "top": 811.5, + "height": 20, + "width": 122, "borderWidth": "0.75", "coordinateSync": false, "widthHeightSync": false, @@ -1355,262 +2227,6 @@ export default { "title": "横线", "type": "hline" } - }, - { - "options": { - "left": 357, - "top": 585, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 510, - "top": 585, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 69, - "top": 628.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 210, - "top": 628.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 355.5, - "top": 627, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "right": 446.2459487915039, - "bottom": 637.4959487915039, - "vCenter": 401.2459487915039, - "hCenter": 632.9959487915039, - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 504, - "top": 627, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "right": 599.2480087280273, - "bottom": 636.7500228881836, - "vCenter": 554.2480087280273, - "hCenter": 632.2500228881836, - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 69, - "top": 669, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 210, - "top": 669, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 355.5, - "top": 670.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "right": 444.0000228881836, - "bottom": 677.9979858398438, - "vCenter": 399.0000228881836, - "hCenter": 673.4979858398438, - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 510, - "top": 669, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 510, - "top": 712.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 354, - "top": 712.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 213, - "top": 712.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 69, - "top": 712.5, - "height": 9, - "width": 90, - "borderWidth": "0.75", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "横线", - "type": "hline" - } - }, - { - "options": { - "left": 58, - "top": 300, - "height": 190.5, - "width": 532, - "right": 586.75, - "bottom": 480.74796867370605, - "vCenter": 320.75, - "hCenter": 390.74796867370605, - "field": "details", - "coordinateSync": false, - "widthHeightSync": false, - "fixed": true - }, - "printElementType": { - "title": "", - "type": "longText" - } } ], "paperNumberLeft": 565, @@ -1622,8 +2238,3 @@ export default { } ] } - - - - - diff --git a/hangtag-ui/hangtag-ui-front/pnpm-lock.yaml b/hangtag-ui/hangtag-ui-front/pnpm-lock.yaml index b6d86b8..43f0e22 100644 --- a/hangtag-ui/hangtag-ui-front/pnpm-lock.yaml +++ b/hangtag-ui/hangtag-ui-front/pnpm-lock.yaml @@ -95,6 +95,9 @@ importers: diagram-js: specifier: ^12.8.0 version: 12.8.1 + dom-to-image: + specifier: ^2.6.0 + version: 2.6.0 driver.js: specifier: ^1.3.1 version: 1.3.1 @@ -2802,6 +2805,9 @@ packages: dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom-to-image@2.6.0: + resolution: {integrity: sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==} + dom-walk@0.1.2: resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} @@ -7410,7 +7416,7 @@ snapshots: '@types/web-bluetooth': 0.0.16 '@vueuse/metadata': 9.13.0 '@vueuse/shared': 9.13.0(vue@3.4.21(typescript@5.3.3)) - vue-demi: 0.14.7(vue@3.4.21(typescript@5.3.3)) + vue-demi: 0.14.10(vue@3.4.21(typescript@5.3.3)) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -7421,14 +7427,14 @@ snapshots: '@vueuse/shared@10.9.0(vue@3.4.21(typescript@5.3.3))': dependencies: - vue-demi: 0.14.7(vue@3.4.21(typescript@5.3.3)) + vue-demi: 0.14.10(vue@3.4.21(typescript@5.3.3)) transitivePeerDependencies: - '@vue/composition-api' - vue '@vueuse/shared@9.13.0(vue@3.4.21(typescript@5.3.3))': dependencies: - vue-demi: 0.14.7(vue@3.4.21(typescript@5.3.3)) + vue-demi: 0.14.10(vue@3.4.21(typescript@5.3.3)) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -8217,6 +8223,8 @@ snapshots: domhandler: 5.0.3 entities: 4.5.0 + dom-to-image@2.6.0: {} + dom-walk@0.1.2: {} dom7@3.0.0: diff --git a/hangtag-ui/hangtag-ui-front/public/favicon.ico b/hangtag-ui/hangtag-ui-front/public/favicon.ico index 5a7de08..b7f57f7 100644 Binary files a/hangtag-ui/hangtag-ui-front/public/favicon.ico and b/hangtag-ui/hangtag-ui-front/public/favicon.ico differ diff --git a/hangtag-ui/hangtag-ui-front/public/favicon1.ico b/hangtag-ui/hangtag-ui-front/public/favicon1.ico new file mode 100644 index 0000000..5a7de08 Binary files /dev/null and b/hangtag-ui/hangtag-ui-front/public/favicon1.ico differ diff --git a/hangtag-ui/hangtag-ui-front/src/api/login/index.ts b/hangtag-ui/hangtag-ui-front/src/api/login/index.ts index ef86563..6902853 100644 --- a/hangtag-ui/hangtag-ui-front/src/api/login/index.ts +++ b/hangtag-ui/hangtag-ui-front/src/api/login/index.ts @@ -12,6 +12,21 @@ export interface SmsLoginVO { code: string } +export interface MailCodeVO { + mail: string + scene: number + type: number +} + + +export interface MailModifyPwdVO { + mail: string + password: string + checkpassword: string + code: string + type: number +} + // 登录 export const login = (data: UserLoginVO) => { return request.post({ url: '/system/auth/login', data }) @@ -47,6 +62,16 @@ export const sendSmsCode = (data: SmsCodeVO) => { return request.post({ url: '/system/auth/send-sms-code', data }) } +//获取邮箱登录验证码 +export const sendMailCode = (data: MailCodeVO) => { + return request.post({ url: '/system/auth/send-mail-code', data }) +} + +// 邮箱码修改密码 +export const mailModifyPwd = (data: MailModifyPwdVO) => { + return request.post({ url: '/system/auth/mail-modifypwd', data }) +} + // 短信验证码登录 export const smsLogin = (data: SmsLoginVO) => { return request.post({ url: '/system/auth/sms-login', data }) diff --git a/hangtag-ui/hangtag-ui-front/src/assets/imgs/logo.png b/hangtag-ui/hangtag-ui-front/src/assets/imgs/logo.png index 7e1043f..d95b8c1 100644 Binary files a/hangtag-ui/hangtag-ui-front/src/assets/imgs/logo.png and b/hangtag-ui/hangtag-ui-front/src/assets/imgs/logo.png differ diff --git a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DesignPropEdit.vue b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DesignPropEdit.vue index 2268da4..135ddb5 100644 --- a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DesignPropEdit.vue +++ b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DesignPropEdit.vue @@ -46,7 +46,7 @@
- +
@@ -66,7 +66,7 @@
- + + { for (let i = 0; i < infoList.length; i++) { mapping[infoList[i].label] = infoList[i].langMapping; } + that.propInfo[key].processType = findProcessTypeIndex(index); // 多语言变量替换 const allData = [...that.propInfo[key].dataInfo] const fLang = allData[0].locale; @@ -563,7 +565,7 @@ const findProcessTypeIndex = (index) => { const washingInfoListByType = (type, index = -1) => { const typeIndex = findProcessTypeIndex(index); return that.washingInfoList.filter(item => { - if (item.type === type && (typeIndex < 0 || (item.processType === `${typeIndex}`))) { + if (`${item.type}` === `${type}` && (typeIndex < 0 || (`${item.processType}` === `${typeIndex}`))) { return item } }) @@ -896,18 +898,17 @@ const checkPropInfo = (info) => { for (let i = 0; i < that.propOrderByList.length; i++) { keys.push(that.propOrderByList[i].key); } - - endloop: for (let i = 0; i < keys.length; i++) { + console.log("keys",keys) + for (let i = 0; i < keys.length; i++) { const key = keys[i]; - // 合并相同语言的文字 - let newArr = []; // 每种语言合并成一句话 const allLang = findGroupAllLang(key, newInfo2); - const firstLang = newInfo[key].dataInfo[0].locale; const linkChar = newInfo[key].linkChar || ''; const dataInfoArr = newInfo[key].dataInfo; let langList = newInfo[key].langList || []; + console.log("newInfo[key].groupType",newInfo[key]) if (newInfo[key].groupType === GroupTypeEnum.RATIO) { + // 成分比例 都进行固定语言组合 // 获取到所以的成分 let langSort = newInfo[key].langSort || []; @@ -937,6 +938,8 @@ const checkPropInfo = (info) => { for (let j = 0; j < langSort.length; j++) { const labelInfo = [] let allRatio = 0; // 累计 比例 + const langLabel = []; + let linkChar = "," for (let k = 0; k < langList.length; k++) { if (langSort[j] === langList[k].locale) { let tmpValue = `${langList[k].value}`.replaceAll('${r}', `${str}`) @@ -946,9 +949,17 @@ const checkPropInfo = (info) => { if (str === null || str === undefined || str === -1) { str = '' } - mergeLabel.push(tmpValue) + console.log("langList[k]",langList[k]) + if(langList[k].linkChar && linkChar != ','){ + linkChar = langList[k] + } + langLabel.push(tmpValue) } } + if(langLabel.length > 0){ + mergeLabel.push(langLabel.join(linkChar)) + } + let flag = false; // 校验 for (let k = 0; k < dataInfoArr.length; k++) { @@ -1006,7 +1017,6 @@ const checkPropInfo = (info) => { if (newInfo[kKey].groupName === newInfo[key].parentId) { newKey = kKey; parentStr = newInfo[kKey].dataInfo[0].label + '
' - break; } } @@ -1021,24 +1031,28 @@ const checkPropInfo = (info) => { // 语言对应自己的自动位置 if (newInfo[key].multiLanguage) { + const showLabel1 = newInfo[key].dataInfo[0].showLabel if (newInfo[key].groupType === GroupTypeEnum.ICON) { const infoList = washingInfoListByType(newInfo[key].groupType) const infos = newInfo[key].dataInfo; for (let j = 1; j < infos.length; j++) { + outerLoop: for (let i = 0; i < infoList.length; i++) { const row1 = infoList[i]; - for (let k = 0; k < row1.langMapping.length; k++) { - // 跳过icon 类型,因为没有url - if (infos[j].locale === row1.langMapping[k].locale) { - infos[j].label = row1.langMapping[k].value - break outerLoop; + if(`${row1.processType}` === `${ newInfo[key].processType}`){ + for (let k = 0; k < row1.langMapping.length; k++) { + // 跳过icon 类型,因为没有url + if (infos[j].locale === row1.langMapping[k].locale && showLabel1 === row1.value) { + infos[j].label = row1.langMapping[k].value + break outerLoop; + } } } } } console.log("newArr33",infos) newInfo[key].dataInfo = infos; - break; + }else { const infoList = washingInfoListByType(newInfo[key].groupType) const infos = newInfo[key].dataInfo; @@ -1054,41 +1068,55 @@ const checkPropInfo = (info) => { } } } - console.log("newArr33",infos) + console.log("newArr99",infos) newInfo[key].dataInfo = infos; - break; + } } else { // 多种语言组合成一句话 // 文本类型处理 if (newInfo[key].groupType === GroupTypeEnum.TEXT) { + let langSort = newInfo[key].langSort || []; if (langSort.length === 0) { langSort = allLang } let mergeLabel = []; - for (let j = 0; j < langSort.length; j++) { - const labelInfo = [] - for (let k = 0; k < langList.length; k++) { - if (langSort[j] === langList[k].locale && newInfo[key].dataInfo[k].showLabel) { - mergeLabel.push(langList[k].value) + + if(newInfo[key].canInput){ + for (let j = 0; j < dataInfoArr.length; j++) { + if (dataInfoArr[j].showLabel) { + if(mergeLabel.includes(dataInfoArr[j].showLabel)){ + useMessage().notifyWarning(`${newInfo[key].groupName}中,第${j + 1}项重复${dataInfoArr[j].showLabel}`) + } + mergeLabel.push(dataInfoArr[j].showLabel) } } - // 校验重复 - for (let k = 0; k < dataInfoArr.length; k++) { - if (langSort[j] === newInfo[key].dataInfo[k].locale) { - if (newInfo[key].dataInfo[k].showLabel) { - if (labelInfo.includes(newInfo[key].dataInfo[k].showLabel)) { - useMessage().notifyError(`${newInfo[key].groupName}中第${labelInfo.length + 1}项重复`); - that.errorList.push({ - key: `${key}_${k}`, - message: "数据重复" - }) - reject("数据重复") - return + }else { + for (let j = 0; j < langSort.length; j++) { + const labelInfo = [] + for (let k = 0; k < langList.length; k++) { + console.log("newInfo[key].dataInfo[k]",newInfo[key].dataInfo[k]) + if (langSort[j] === langList[k].locale) { + mergeLabel.push(langList[k].value) + } + } + // 校验重复 + for (let k = 0; k < dataInfoArr.length; k++) { + if (langSort[j] === newInfo[key].dataInfo[k].locale) { + if (newInfo[key].dataInfo[k].showLabel) { + if (labelInfo.includes(newInfo[key].dataInfo[k].showLabel)) { + useMessage().notifyError(`${newInfo[key].groupName}中第${labelInfo.length + 1}项重复`); + that.errorList.push({ + key: `${key}_${k}`, + message: "数据重复" + }) + reject("数据重复") + return + } + labelInfo.push(newInfo[key].dataInfo[k].showLabel) } - labelInfo.push(newInfo[key].dataInfo[k].showLabel) } } } @@ -1374,7 +1402,7 @@ defineExpose({ } .error_tip { - box-shadow: rgb(255, 0, 0) 0px 0px 2px 1px; + box-shadow: rgb(255, 0, 0) 0 0 2px 1px; } diff --git a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DynamicPropConfig.vue b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DynamicPropConfig.vue index 92c5f49..3c7037f 100644 --- a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DynamicPropConfig.vue +++ b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/components/DynamicPropConfig.vue @@ -49,7 +49,7 @@
- 允许调整数量 diff --git a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue index a7d4e15..8a1ee6c 100644 --- a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue +++ b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue @@ -1462,6 +1462,7 @@ const handlerGroupList = (cells, isCombo = false, min, max) => { canChange = that.pageConfig.propList[i].canChange === true canInput = that.pageConfig.propList[i].canInput === true langSort = that.pageConfig.propList[i].langSort || [] + linkChar = that.pageConfig.propList[i].linkChar || ',' break; } } diff --git a/hangtag-ui/hangtag-ui-front/src/locales/en.ts b/hangtag-ui/hangtag-ui-front/src/locales/en.ts index 98056c8..4760a26 100644 --- a/hangtag-ui/hangtag-ui-front/src/locales/en.ts +++ b/hangtag-ui/hangtag-ui-front/src/locales/en.ts @@ -114,7 +114,7 @@ export default { }, login: { welcome: 'Welcome to the system', - message: 'Backstage management system', + message: '', tenantname: 'TenantName', username: 'Username', password: 'Password', @@ -133,14 +133,20 @@ export default { codePlaceholder: 'Please Enter Verification Code', mobileTitle: 'Mobile sign in', mobileNumber: 'Mobile Number', - mobileNumberPlaceholder: 'Plaease Enter Mobile Number', + mobileNumberPlaceholder: 'Plaease Enter Mobile Code', + emailNumberPlaceholder: 'Plaease Enter Email Code', backLogin: 'back', getSmsCode: 'Get SMS Code', + getMailCode: 'Get Mail Code', btnMobile: 'Mobile sign in', btnQRCode: 'QR code sign in', qrcode: 'Scan the QR code to log in', btnRegister: 'Sign up', - SmsSendMsg: 'code has been sent' + SmsSendMsg: 'code has been sent', + pwdResetSuccess: 'password reset success' + }, + forgetpassword: { + resetpwd: 'reset pwd', }, captcha: { verification: 'Please complete security verification', diff --git a/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts b/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts index ee2b41b..eed7a1e 100644 --- a/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts +++ b/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts @@ -134,13 +134,19 @@ export default { mobileTitle: '手机登录', mobileNumber: '手机号码', mobileNumberPlaceholder: '请输入手机号码', + emailNumberPlaceholder: '请输入邮箱号码', backLogin: '返回', getSmsCode: '获取验证码', + getMailCode: '获取验证码', btnMobile: '手机登录', btnQRCode: '二维码登录', qrcode: '扫描二维码登录', btnRegister: '注册', - SmsSendMsg: '验证码已发送' + SmsSendMsg: '验证码已发送', + pwdResetSuccess: '密码重置成功' + }, + forgetpassword: { + resetpwd: '重置密码', }, captcha: { verification: '请完成安全验证', diff --git a/hangtag-ui/hangtag-ui-front/src/views/Login/Login.vue b/hangtag-ui/hangtag-ui-front/src/views/Login/Login.vue index 904394f..1a2bb33 100644 --- a/hangtag-ui/hangtag-ui-front/src/views/Login/Login.vue +++ b/hangtag-ui/hangtag-ui-front/src/views/Login/Login.vue @@ -29,7 +29,7 @@
+ +
@@ -70,7 +72,7 @@ import { useAppStore } from '@/store/modules/app' import { ThemeSwitch } from '@/layout/components/ThemeSwitch' import { LocaleDropdown } from '@/layout/components/LocaleDropdown' -import { LoginForm, MobileForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components' +import { LoginForm, MobileForm, ForgetPasswordForm, QrCodeForm, RegisterForm, SSOLoginVue } from './components' defineOptions({ name: 'Login' }) diff --git a/hangtag-ui/hangtag-ui-front/src/views/Login/components/ForgetPasswordForm.vue b/hangtag-ui/hangtag-ui-front/src/views/Login/components/ForgetPasswordForm.vue new file mode 100644 index 0000000..a697f7b --- /dev/null +++ b/hangtag-ui/hangtag-ui-front/src/views/Login/components/ForgetPasswordForm.vue @@ -0,0 +1,264 @@ + + + + diff --git a/hangtag-ui/hangtag-ui-front/src/views/Login/components/LoginForm.vue b/hangtag-ui/hangtag-ui-front/src/views/Login/components/LoginForm.vue index 172aa96..c7fcb4d 100644 --- a/hangtag-ui/hangtag-ui-front/src/views/Login/components/LoginForm.vue +++ b/hangtag-ui/hangtag-ui-front/src/views/Login/components/LoginForm.vue @@ -58,9 +58,9 @@ {{ t('login.remember') }} - + + {{ t('login.forgetPassword') }} + diff --git a/hangtag-ui/hangtag-ui-front/src/views/Login/components/index.ts b/hangtag-ui/hangtag-ui-front/src/views/Login/components/index.ts index 204ad73..6b34ed1 100644 --- a/hangtag-ui/hangtag-ui-front/src/views/Login/components/index.ts +++ b/hangtag-ui/hangtag-ui-front/src/views/Login/components/index.ts @@ -1,8 +1,9 @@ import LoginForm from './LoginForm.vue' import MobileForm from './MobileForm.vue' +import ForgetPasswordForm from './ForgetPasswordForm.vue' import LoginFormTitle from './LoginFormTitle.vue' import RegisterForm from './RegisterForm.vue' import QrCodeForm from './QrCodeForm.vue' import SSOLoginVue from './SSOLogin.vue' -export { LoginForm, MobileForm, LoginFormTitle, RegisterForm, QrCodeForm, SSOLoginVue } +export { LoginForm, MobileForm, ForgetPasswordForm, LoginFormTitle, RegisterForm, QrCodeForm, SSOLoginVue }