u
This commit is contained in:
1 parent
1da52dc4f4
commit
276644f473
223 files changed
+9609
-262
No files matched your search
+4
-4
@@ -4,7 +4,7 @@ import cn.link56.auth.code.model.AuthCodeChannel;
|
||||
import cn.link56.auth.code.model.AuthCodePurpose;
|
||||
import cn.link56.auth.code.model.dto.AuthCodeSendDTO;
|
||||
import cn.link56.auth.code.model.dto.AuthCodeVerifyDTO;
|
||||
import cn.link56.auth.code.service.VerificationCodeService;
|
||||
import cn.link56.auth.code.service.AuthVerificationCodeService;
|
||||
import cn.link56.common.Result;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -14,7 +14,7 @@ import javax.annotation.Resource;
|
||||
@RequestMapping("/auth/code")
|
||||
public class AuthCodeController {
|
||||
@Resource
|
||||
private VerificationCodeService verificationCodeService;
|
||||
private AuthVerificationCodeService authVerificationCodeService;
|
||||
|
||||
@PostMapping("/send")
|
||||
public Result<Void> send(@RequestBody AuthCodeSendDTO authCodeSendDTO) {
|
||||
@@ -22,7 +22,7 @@ public class AuthCodeController {
|
||||
AuthCodeChannel channel = authCodeSendDTO.getChannel();
|
||||
String target = authCodeSendDTO.getTarget();
|
||||
|
||||
boolean flag = verificationCodeService.sendCode(purpose, channel, target);
|
||||
boolean flag = authVerificationCodeService.sendCode(purpose, channel, target);
|
||||
|
||||
return flag ? Result.success() : Result.error();
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class AuthCodeController {
|
||||
String target = authCodeVerifyDTO.getTarget();
|
||||
String code = authCodeVerifyDTO.getCode();
|
||||
|
||||
boolean flag = verificationCodeService.verifyCode(purpose, channel, target, code);
|
||||
boolean flag = authVerificationCodeService.verifyCode(purpose, channel, target, code);
|
||||
|
||||
return flag ? Result.success() : Result.error();
|
||||
}
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ public class EmailAuthCodeSender {
|
||||
|
||||
if (purpose.equals(AuthCodePurpose.LOGIN)){
|
||||
subject = "登录";
|
||||
templateHtml = "Login.html";
|
||||
}else if(purpose.equals(AuthCodePurpose.REGISTER)){
|
||||
subject = "注册";
|
||||
templateHtml = "Register.html";
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class VerificationCodeService {
|
||||
public class AuthVerificationCodeService {
|
||||
@Resource
|
||||
private AuthCodeStore codeStore;
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ package cn.link56.auth.code.store;
|
||||
import cn.link56.auth.code.model.AuthCodeChannel;
|
||||
import cn.link56.auth.code.model.AuthCode;
|
||||
import cn.link56.auth.code.model.AuthCodePurpose;
|
||||
import cn.link56.common.exception.OperationTooFrequentException;
|
||||
import cn.link56.common.exception.BusinessException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.naming.OperationNotSupportedException;
|
||||
@@ -29,7 +29,7 @@ public class AuthCodeStore {
|
||||
AuthCode existing = store.get(key);
|
||||
if (existing != null &&
|
||||
existing.getLastSentAt().plusSeconds(MIN_INTERVAL_SECONDS).isAfter(now)) {
|
||||
throw new OperationTooFrequentException("验证码发送过于频繁,请稍后再试");
|
||||
throw new BusinessException("验证码发送过于频繁,请稍后再试");
|
||||
}
|
||||
|
||||
AuthCode code = new AuthCode(
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package cn.link56.auth.identity.controller;
|
||||
|
||||
import cn.link56.auth.identity.model.dto.AuthLoginEmailCodeDTO;
|
||||
import cn.link56.auth.identity.model.dto.AuthLoginPasswordDTO;
|
||||
import cn.link56.auth.identity.model.dto.AuthRegisterDTO;
|
||||
import cn.link56.auth.identity.model.vo.AuthLoginVO;
|
||||
import cn.link56.auth.identity.service.AuthIdentityService;
|
||||
import cn.link56.common.Result;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth/identity")
|
||||
public class AuthIdentityController {
|
||||
@Resource
|
||||
private AuthIdentityService authIdentityService;
|
||||
|
||||
@PostMapping("/register")
|
||||
public Result<Void> register(@RequestBody AuthRegisterDTO authRegisterDTO){
|
||||
authIdentityService.register(authRegisterDTO);
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@PostMapping("/login/password")
|
||||
public Result<AuthLoginVO> loginByPassword(@RequestBody @Validated AuthLoginPasswordDTO loginPasswordDTO){
|
||||
AuthLoginVO authLoginVO = authIdentityService.loginByPassword(loginPasswordDTO);
|
||||
return Result.success(authLoginVO);
|
||||
}
|
||||
|
||||
@PostMapping("/login/emailCode")
|
||||
public Result<AuthLoginVO> loginByEmailCode(@RequestBody @Validated AuthLoginEmailCodeDTO loginEmailCodeDTO){
|
||||
AuthLoginVO authLoginVO = authIdentityService.loginByEmailCode(loginEmailCodeDTO);
|
||||
return Result.success(authLoginVO);
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package cn.link56.auth.identity.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AuthLoginEmailCodeDTO {
|
||||
@NotBlank(message = "邮箱不能为空")
|
||||
@Email(message = "邮箱格式有误")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "验证码不能为空")
|
||||
private String code;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package cn.link56.auth.identity.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AuthLoginPasswordDTO {
|
||||
@NotBlank(message = "邮箱不能为空")
|
||||
@Email(message = "邮箱格式有误")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "密码不能为空")
|
||||
private String password;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package cn.link56.auth.identity.model.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AuthLoginVO {
|
||||
private Long companyId;
|
||||
private String companyLogo;
|
||||
private String companyName;
|
||||
|
||||
private Long userId;
|
||||
private Integer userRole;
|
||||
private String userName;
|
||||
private String userPosition;
|
||||
|
||||
private String token;
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package cn.link56.auth.identity.service;
|
||||
|
||||
import cn.link56.auth.code.model.AuthCodeChannel;
|
||||
import cn.link56.auth.code.model.AuthCodePurpose;
|
||||
import cn.link56.auth.code.service.AuthVerificationCodeService;
|
||||
import cn.link56.auth.identity.model.dto.AuthLoginEmailCodeDTO;
|
||||
import cn.link56.auth.identity.model.dto.AuthLoginPasswordDTO;
|
||||
import cn.link56.auth.identity.model.vo.AuthLoginVO;
|
||||
import cn.link56.auth.token.model.AuthToken;
|
||||
import cn.link56.auth.token.model.TokenPayload;
|
||||
import cn.link56.auth.token.service.AuthTokenService;
|
||||
import cn.link56.entity.BCompany;
|
||||
import cn.link56.entity.BCompanyUser;
|
||||
import cn.link56.auth.identity.model.dto.AuthRegisterDTO;
|
||||
import cn.link56.base.service.BCompanyService;
|
||||
import cn.link56.base.service.BCompanyUserService;
|
||||
import cn.link56.common.exception.BusinessException;
|
||||
import cn.link56.common.utils.snowflake.idgen.IdGenerator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class AuthIdentityService {
|
||||
@Resource
|
||||
private BCompanyService companyService;
|
||||
@Resource
|
||||
private BCompanyUserService companyUserService;
|
||||
@Resource
|
||||
private AuthTokenService tokenService;
|
||||
@Resource
|
||||
private AuthVerificationCodeService authVerificationCodeService;
|
||||
|
||||
@Transactional
|
||||
public void register(AuthRegisterDTO registerDTO) {
|
||||
AuthRegisterDTO.Company company = registerDTO.getCompany();
|
||||
AuthRegisterDTO.Admin admin = registerDTO.getAdmin();
|
||||
|
||||
if (companyService.isNameExists(company.getName())) {
|
||||
throw new BusinessException("公司名称已存在");
|
||||
}
|
||||
|
||||
if(StringUtils.isNotBlank(company.getPhone()) && companyService.isPhoneExists(company.getPhone())){
|
||||
throw new BusinessException("公司邮箱已被注册");
|
||||
}
|
||||
|
||||
if (companyUserService.isEmailExists(admin.getEmail())) {
|
||||
throw new BusinessException("管理员邮箱已被注册");
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(admin.getPhone()) && companyUserService.isPhoneExists(admin.getPhone())) {
|
||||
throw new BusinessException("管理员手机号已被注册");
|
||||
}
|
||||
|
||||
long companyId = IdGenerator.nextId();
|
||||
|
||||
companyService.save(
|
||||
new BCompany()
|
||||
.setId(companyId)
|
||||
.setName(company.getName())
|
||||
.setIndustry(company.getIndustry())
|
||||
.setAddress(company.getAddress())
|
||||
.setPhone(company.getPhone())
|
||||
.setEmail(company.getEmail())
|
||||
.setProfile(company.getProfile())
|
||||
);
|
||||
|
||||
companyUserService.save(
|
||||
new BCompanyUser()
|
||||
.setId(IdGenerator.nextId())
|
||||
.setCompanyId(companyId)
|
||||
.setName(admin.getName())
|
||||
.setEmail(admin.getEmail())
|
||||
.setPassword(admin.getPassword())
|
||||
.setPhone(admin.getPhone())
|
||||
.setPosition(admin.getPosition())
|
||||
.setRole(0)
|
||||
);
|
||||
}
|
||||
|
||||
public AuthLoginVO loginByPassword(AuthLoginPasswordDTO dto) {
|
||||
BCompanyUser user = companyUserService.loginByEmailAndPassword(dto.getEmail(), dto.getPassword());
|
||||
if (user == null) {
|
||||
throw new BusinessException("邮箱或密码错误");
|
||||
}
|
||||
return buildLoginVO(user);
|
||||
}
|
||||
|
||||
public AuthLoginVO loginByEmailCode(AuthLoginEmailCodeDTO dto) {
|
||||
String email = dto.getEmail();
|
||||
String code = dto.getCode();
|
||||
|
||||
boolean valid = authVerificationCodeService.verifyCode(
|
||||
AuthCodePurpose.LOGIN,
|
||||
AuthCodeChannel.EMAIL,
|
||||
email,
|
||||
code
|
||||
);
|
||||
|
||||
if (!valid) {
|
||||
throw new BusinessException("邮箱或验证码失效");
|
||||
}
|
||||
|
||||
BCompanyUser user = companyUserService.loginByEmail(email);
|
||||
if (user == null) {
|
||||
throw new BusinessException("邮箱不存在");
|
||||
}
|
||||
|
||||
return buildLoginVO(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共逻辑:根据用户生成 LoginVO
|
||||
*/
|
||||
private AuthLoginVO buildLoginVO(BCompanyUser user) {
|
||||
BCompany company = companyService.getById(user.getCompanyId());
|
||||
AuthToken authToken = tokenService.generateToken(new TokenPayload(user.getCompanyId(), user.getId()));
|
||||
|
||||
return new AuthLoginVO(
|
||||
company.getId(),
|
||||
company.getLogo(),
|
||||
company.getName(),
|
||||
|
||||
user.getId(),
|
||||
user.getRole(),
|
||||
user.getName(),
|
||||
user.getPosition(),
|
||||
|
||||
authToken.getToken()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -2,6 +2,7 @@ package cn.link56.base.controller;
|
||||
|
||||
import cn.link56.base.model.vo.BaseDataVO;
|
||||
import cn.link56.base.service.BaseDataService;
|
||||
import cn.link56.common.Result;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@@ -9,14 +10,13 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/base")
|
||||
@RequestMapping("/base")
|
||||
public class BaseDataController {
|
||||
@Resource
|
||||
private BaseDataService baseDataService;
|
||||
|
||||
|
||||
@GetMapping("/init")
|
||||
public BaseDataVO initBaseData() {
|
||||
return baseDataService.getBaseData();
|
||||
public Result<BaseDataVO> initBaseData() {
|
||||
return Result.success(baseDataService.getBaseData());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.link56.base.mapper;
|
||||
|
||||
import cn.link56.entity.BArea;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AreaMapper {
|
||||
/**
|
||||
* 获取所有区域信息
|
||||
* @return 区域集合
|
||||
*/
|
||||
List<BArea> listAllArea();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.link56.base.mapper;
|
||||
|
||||
import cn.link56.entity.BCompany;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BCompanyMapper extends BaseMapper<BCompany> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package cn.link56.base.mapper;
|
||||
|
||||
import cn.link56.entity.BCompanyUser;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BCompanyUserMapper extends BaseMapper<BCompanyUser> {
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.link56.base.mapper;
|
||||
|
||||
import cn.link56.base.model.BIndustry;
|
||||
import cn.link56.entity.BIndustry;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
|
||||
@@ -30,5 +30,6 @@ public class BaseDataVO {
|
||||
private Integer xh;
|
||||
private String name;
|
||||
private String fatherId;
|
||||
private List<Area> children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.link56.base.service;
|
||||
|
||||
import cn.link56.base.mapper.BCompanyMapper;
|
||||
import cn.link56.entity.BCompany;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class BCompanyService extends ServiceImpl<BCompanyMapper, BCompany> {
|
||||
@Resource
|
||||
private BCompanyMapper companyMapper;
|
||||
|
||||
/**
|
||||
* 检查公司名称是否重复
|
||||
*/
|
||||
public boolean isNameExists(String name) {
|
||||
Long count = companyMapper.selectCount(
|
||||
new LambdaQueryWrapper<BCompany>()
|
||||
.eq(BCompany::getName, name)
|
||||
);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查公司手机号是否重复
|
||||
*/
|
||||
public boolean isPhoneExists(String phone) {
|
||||
Long count = companyMapper.selectCount(
|
||||
new LambdaQueryWrapper<BCompany>()
|
||||
.eq(BCompany::getPhone, phone)
|
||||
);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package cn.link56.base.service;
|
||||
|
||||
import cn.link56.base.mapper.BCompanyUserMapper;
|
||||
import cn.link56.entity.BCompanyUser;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class BCompanyUserService extends ServiceImpl<BCompanyUserMapper, BCompanyUser> {
|
||||
|
||||
@Resource
|
||||
private BCompanyUserMapper companyUserMapper;
|
||||
|
||||
/**
|
||||
* 判断邮箱是否重复
|
||||
* @param email 用户邮箱
|
||||
* @return true 表示邮箱已存在,false 表示可用
|
||||
*/
|
||||
public boolean isEmailExists(String email) {
|
||||
long count = companyUserMapper.selectCount(
|
||||
new LambdaQueryWrapper<BCompanyUser>()
|
||||
.eq(BCompanyUser::getEmail, email)
|
||||
);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断手机号是否重复
|
||||
* @param phone 用户手机号
|
||||
* @return true 表示手机号已存在,false 表示可用
|
||||
*/
|
||||
public boolean isPhoneExists(String phone) {
|
||||
long count = companyUserMapper.selectCount(
|
||||
new LambdaQueryWrapper<BCompanyUser>()
|
||||
.eq(BCompanyUser::getPhone, phone)
|
||||
);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
public BCompanyUser loginByEmailAndPassword(String email, String password){
|
||||
LambdaQueryWrapper<BCompanyUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(BCompanyUser::getEmail,email)
|
||||
.eq(BCompanyUser::getPassword,password);
|
||||
|
||||
return companyUserMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
public BCompanyUser loginByEmail(String email){
|
||||
LambdaQueryWrapper<BCompanyUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(BCompanyUser::getEmail,email);
|
||||
|
||||
return companyUserMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
+73
-3
@@ -1,19 +1,23 @@
|
||||
package cn.link56.base.service;
|
||||
|
||||
import cn.link56.base.mapper.AreaMapper;
|
||||
import cn.link56.base.mapper.IndustryMapper;
|
||||
import cn.link56.base.model.BIndustry;
|
||||
import cn.link56.entity.BArea;
|
||||
import cn.link56.entity.BIndustry;
|
||||
import cn.link56.base.model.vo.BaseDataVO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class BaseDataService {
|
||||
@Resource
|
||||
private IndustryMapper industryMapper;
|
||||
@Resource
|
||||
private AreaMapper areaMapper;
|
||||
|
||||
public BaseDataVO getBaseData() {
|
||||
BaseDataVO baseDataVO = new BaseDataVO();
|
||||
@@ -30,9 +34,75 @@ public class BaseDataService {
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
baseDataVO.setIndustries(industries);
|
||||
|
||||
// 地区
|
||||
List<BArea> allAreas = areaMapper.listAllArea();
|
||||
List<BaseDataVO.Area> areaTree = buildAreaTree(allAreas);
|
||||
|
||||
baseDataVO.setAreas(areaTree);
|
||||
return baseDataVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* BArea → BaseDataVO.Area 树
|
||||
*/
|
||||
private List<BaseDataVO.Area> buildAreaTree(List<BArea> areas) {
|
||||
if (areas == null || areas.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// id -> VO
|
||||
Map<String, BaseDataVO.Area> map = new HashMap<>(areas.size());
|
||||
|
||||
// 1️⃣ 先全部转 VO
|
||||
for (BArea a : areas) {
|
||||
BaseDataVO.Area vo = new BaseDataVO.Area(
|
||||
a.getId(),
|
||||
a.getXh(),
|
||||
a.getName(),
|
||||
a.getFatherId(),
|
||||
new ArrayList<>()
|
||||
);
|
||||
map.put(vo.getId(), vo);
|
||||
}
|
||||
|
||||
// 2️⃣ 组装父子关系
|
||||
List<BaseDataVO.Area> roots = new ArrayList<>();
|
||||
|
||||
for (BaseDataVO.Area area : map.values()) {
|
||||
String parentId = area.getFatherId();
|
||||
if (parentId == null || "0".equals(parentId)) {
|
||||
roots.add(area);
|
||||
} else {
|
||||
BaseDataVO.Area parent = map.get(parentId);
|
||||
if (parent != null) {
|
||||
parent.getChildren().add(area);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3️⃣ 可选排序
|
||||
sortTree(roots);
|
||||
|
||||
return roots;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按 xh 排序(如果你用 order,也可以换)
|
||||
*/
|
||||
private void sortTree(List<BaseDataVO.Area> nodes) {
|
||||
if (nodes == null || nodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes.sort(Comparator.comparing(
|
||||
BaseDataVO.Area::getXh,
|
||||
Comparator.nullsLast(Integer::compareTo)
|
||||
));
|
||||
|
||||
for (BaseDataVO.Area node : nodes) {
|
||||
sortTree(node.getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,10 @@ public class Result<T> {
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String message){
|
||||
return new Result<>(ResponseStatusConstants.ERROR, message, null);
|
||||
return new Result<>(ResponseStatusConstants.BUSINESS_ERROR, message, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(){
|
||||
return new Result<>(ResponseStatusConstants.ERROR, null,null);
|
||||
return new Result<>(ResponseStatusConstants.BUSINESS_ERROR, null,null);
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package cn.link56.common.config;
|
||||
|
||||
import cn.link56.common.context.UserContext;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class AutoMetaObjectHandler implements MetaObjectHandler {
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
Long userId = UserContext.getUserId();
|
||||
|
||||
if (ObjectUtils.isNotEmpty(userId) && userId > 0){
|
||||
this.strictInsertFill(metaObject, "createBy", Long.class, userId);
|
||||
}
|
||||
|
||||
Date date = new Date();
|
||||
|
||||
this.strictInsertFill(metaObject, "createTime", Date.class, date);
|
||||
this.strictInsertFill(metaObject, "updateTime", Date.class, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
Long userId = UserContext.getUserId();
|
||||
|
||||
if (ObjectUtils.isNotEmpty(userId) && userId > 0){
|
||||
this.strictUpdateFill(metaObject, "updateBy", Long.class, userId);
|
||||
}
|
||||
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -6,10 +6,15 @@ public class ResponseStatusConstants {
|
||||
*/
|
||||
public static final Integer SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 系统内部错误
|
||||
/**
|
||||
* 系统业务错误
|
||||
*/
|
||||
public static final Integer ERROR = 500;
|
||||
public static final Integer BUSINESS_ERROR = 450;
|
||||
|
||||
/**
|
||||
* 系统服务器错误
|
||||
*/
|
||||
public static final Integer SERVER_ERROR = 500;
|
||||
|
||||
/**
|
||||
* 缺少参数,参数格式有误,请求路径有误等
|
||||
|
||||
+3
@@ -4,4 +4,7 @@ public class BusinessException extends RuntimeException {
|
||||
public BusinessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
public BusinessException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -82,8 +82,8 @@ public class GlobalExceptionHandler {
|
||||
}
|
||||
|
||||
// 自定义异常
|
||||
@ExceptionHandler(OperationTooFrequentException.class)
|
||||
public Result<Void> handleOperationTooFrequentException(OperationTooFrequentException e) {
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public Result<Void> handleOperationTooFrequentException(BusinessException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
|
||||
@@ -92,8 +92,7 @@ public class GlobalExceptionHandler {
|
||||
*/
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
public Result<Void> handleSystemException(Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("捕获到全局异常:{}",e.getMessage());
|
||||
return Result.error(e.getMessage());
|
||||
log.error("系统异常", e );
|
||||
return Result.error(ResponseStatusConstants.SERVER_ERROR,"系统异常");
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package cn.link56.common.exception;
|
||||
|
||||
public class OperationTooFrequentException extends BusinessException {
|
||||
public OperationTooFrequentException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public OperationTooFrequentException() {
|
||||
super("操作过于频繁,请稍后再试");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.link56.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class BArea {
|
||||
private String id;
|
||||
private Integer xh;
|
||||
private String name;
|
||||
private String fatherId;
|
||||
private String canuse;
|
||||
private String bz;
|
||||
private String field;
|
||||
private Integer order;
|
||||
private String visible;
|
||||
}
|
||||
+23
-9
@@ -1,5 +1,6 @@
|
||||
package cn.link56.auth.identity.model;
|
||||
package cn.link56.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -19,32 +20,45 @@ import java.util.Date;
|
||||
public class BCompany {
|
||||
@TableId(value = "b_id")
|
||||
private Long id;
|
||||
|
||||
@TableField("b_name")
|
||||
private String name;
|
||||
|
||||
@TableField("b_email")
|
||||
private String email;
|
||||
|
||||
@TableField("b_phone")
|
||||
private String phone;
|
||||
|
||||
@TableField("b_address")
|
||||
private String address;
|
||||
|
||||
@TableField("b_industry")
|
||||
private String industry;
|
||||
|
||||
@TableField("b_logo")
|
||||
private String logo;
|
||||
|
||||
@TableField("b_profile")
|
||||
private String profile;
|
||||
|
||||
@TableField("b_description")
|
||||
private String description;
|
||||
@TableField("b_create_by")
|
||||
private Long createBy;
|
||||
@TableField("b_create_time")
|
||||
|
||||
@TableField(value = "b_create_time",fill = FieldFill.INSERT)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
@TableField("b_update_by")
|
||||
private Long updateBy;
|
||||
@TableField("b_update_time")
|
||||
|
||||
@TableField(value = "b_update_time",fill = FieldFill.INSERT_UPDATE)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
@TableField("b_status")
|
||||
private Integer status;
|
||||
|
||||
@TableField("b_canuse")
|
||||
private String canuse;
|
||||
|
||||
@TableField("b_recommend")
|
||||
private String recommend;
|
||||
|
||||
@TableField("b_hot_recommend")
|
||||
private String hotRecommend;
|
||||
}
|
||||
+16
-8
@@ -1,5 +1,6 @@
|
||||
package cn.link56.auth.identity.model;
|
||||
package cn.link56.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -19,26 +20,33 @@ import java.util.Date;
|
||||
public class BCompanyUser {
|
||||
@TableId(value = "b_id")
|
||||
private Long id;
|
||||
@TableId(value = "b_company_id")
|
||||
|
||||
@TableField("b_company_id")
|
||||
private Long companyId;
|
||||
|
||||
@TableField("b_email")
|
||||
private String email;
|
||||
|
||||
@TableField("b_password")
|
||||
private String password;
|
||||
|
||||
@TableField("b_name")
|
||||
private String name;
|
||||
|
||||
@TableField("b_phone")
|
||||
private String phone;
|
||||
|
||||
@TableField("b_role")
|
||||
private Integer role;
|
||||
|
||||
@TableField("b_position")
|
||||
private String position;
|
||||
@TableField("b_create_by")
|
||||
private Long createBy;
|
||||
@TableField("b_create_time")
|
||||
|
||||
@TableField(value = "b_create_time",fill = FieldFill.INSERT)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
@TableField("b_update_by")
|
||||
private Long updateBy;
|
||||
@TableField("b_update_time")
|
||||
|
||||
@TableField(value = "b_update_time",fill = FieldFill.INSERT_UPDATE)
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.link56.base.model;
|
||||
package cn.link56.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -4,9 +4,11 @@ spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: net.sourceforge.jtds.jdbc.Driver
|
||||
url: jdbc:jtds:sqlserver://192.168.1.189:1433;databaseName=G3-Link
|
||||
# url: jdbc:jtds:sqlserver://192.168.1.189:1433;databaseName=G3-Link
|
||||
url: jdbc:jtds:sqlserver://117.72.182.135:1433;databaseName=G3-Link
|
||||
username: sa
|
||||
password: "g3soft"
|
||||
# password: "g3soft"
|
||||
password: "zhang520.."
|
||||
# druid 连接池管理
|
||||
druid:
|
||||
# 初始化时建立物理连接的个数
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.link56.base.mapper.AreaMapper">
|
||||
|
||||
<sql id="area_columns">
|
||||
b_id AS id,
|
||||
b_xh AS xh,
|
||||
b_name AS name,
|
||||
b_father_id AS fatherId,
|
||||
b_canuse AS canuse,
|
||||
b_bz AS bz,
|
||||
b_field AS field,
|
||||
b_order AS [order]
|
||||
</sql>
|
||||
|
||||
<select id="listAllArea" resultType="cn.link56.entity.BArea">
|
||||
SELECT <include refid="area_columns"/> FROM b_area_sheng WHERE b_canuse = '1'
|
||||
UNION ALL
|
||||
SELECT <include refid="area_columns"/> FROM b_area_shi WHERE b_canuse = '1'
|
||||
UNION ALL
|
||||
SELECT <include refid="area_columns"/> FROM b_area_qu WHERE b_canuse = '1'
|
||||
ORDER BY [order]
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,522 @@
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta name="supported-color-schemes" content="light dark" />
|
||||
<title></title>
|
||||
<style type="text/css" rel="stylesheet" media="all">
|
||||
/* Base ------------------------------ */
|
||||
|
||||
@import url("https://fonts.googleapis.com/css?family=Nunito+Sans:400,700&display=swap");
|
||||
|
||||
body {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3869D4;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
td {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.preheader {
|
||||
display: none !important;
|
||||
visibility: hidden;
|
||||
mso-hide: all;
|
||||
font-size: 1px;
|
||||
line-height: 1px;
|
||||
max-height: 0;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Type ------------------------------ */
|
||||
|
||||
body,
|
||||
td,
|
||||
th {
|
||||
font-family: "Nunito Sans", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
blockquote {
|
||||
margin: .4em 0 1.1875em;
|
||||
font-size: 16px;
|
||||
line-height: 1.625;
|
||||
}
|
||||
|
||||
p.sub {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Utilities ------------------------------ */
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.u-margin-bottom-none {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Buttons ------------------------------ */
|
||||
|
||||
.button {
|
||||
background-color: #3869D4;
|
||||
border-top: 10px solid #3869D4;
|
||||
border-right: 18px solid #3869D4;
|
||||
border-bottom: 10px solid #3869D4;
|
||||
border-left: 18px solid #3869D4;
|
||||
display: inline-block;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
|
||||
-webkit-text-size-adjust: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.button--green {
|
||||
background-color: #22BC66;
|
||||
border-top: 10px solid #22BC66;
|
||||
border-right: 18px solid #22BC66;
|
||||
border-bottom: 10px solid #22BC66;
|
||||
border-left: 18px solid #22BC66;
|
||||
}
|
||||
|
||||
.button--red {
|
||||
background-color: #FF6136;
|
||||
border-top: 10px solid #FF6136;
|
||||
border-right: 18px solid #FF6136;
|
||||
border-bottom: 10px solid #FF6136;
|
||||
border-left: 18px solid #FF6136;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.button {
|
||||
width: 100% !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attribute list ------------------------------ */
|
||||
|
||||
.attributes {
|
||||
margin: 0 0 21px;
|
||||
}
|
||||
|
||||
.attributes_content {
|
||||
background-color: #F4F4F7;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.attributes_item {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Related Items ------------------------------ */
|
||||
|
||||
.related {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 25px 0 0 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.related_item {
|
||||
padding: 10px 0;
|
||||
color: #CBCCCF;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.related_item-title {
|
||||
display: block;
|
||||
margin: .5em 0 0;
|
||||
}
|
||||
|
||||
.related_item-thumb {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.related_heading {
|
||||
border-top: 1px solid #CBCCCF;
|
||||
text-align: center;
|
||||
padding: 25px 0 10px;
|
||||
}
|
||||
|
||||
/* Discount Code ------------------------------ */
|
||||
|
||||
.discount {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
background-color: #F4F4F7;
|
||||
border: 2px dashed #CBCCCF;
|
||||
}
|
||||
|
||||
.discount_heading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.discount_body {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* Social Icons ------------------------------ */
|
||||
|
||||
.social {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.social td {
|
||||
padding: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.social_icon {
|
||||
height: 20px;
|
||||
margin: 0 8px 10px 8px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Data table ------------------------------ */
|
||||
|
||||
.purchase {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 35px 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.purchase_content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 25px 0 0 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.purchase_item {
|
||||
padding: 10px 0;
|
||||
color: #51545E;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.purchase_heading {
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.purchase_heading p {
|
||||
margin: 0;
|
||||
color: #85878E;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.purchase_footer {
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.purchase_total {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.purchase_total--label {
|
||||
padding: 0 15px 0 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #F2F4F6;
|
||||
color: #51545E;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #51545E;
|
||||
}
|
||||
|
||||
.email-wrapper {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
background-color: #F2F4F6;
|
||||
}
|
||||
|
||||
.email-content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
/* Masthead ----------------------- */
|
||||
|
||||
.email-masthead {
|
||||
padding: 25px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-masthead_logo {
|
||||
width: 94px;
|
||||
}
|
||||
|
||||
.email-masthead_name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #A8AAAF;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 white;
|
||||
}
|
||||
|
||||
/* Body ------------------------------ */
|
||||
|
||||
.email-body {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.email-body_inner {
|
||||
width: 570px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
-premailer-width: 570px;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.email-footer {
|
||||
width: 570px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
-premailer-width: 570px;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-footer p {
|
||||
color: #A8AAAF;
|
||||
}
|
||||
|
||||
.body-action {
|
||||
width: 100%;
|
||||
margin: 30px auto;
|
||||
padding: 0;
|
||||
font-size: 42px;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.body-sub {
|
||||
margin-top: 25px;
|
||||
padding-top: 25px;
|
||||
border-top: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.content-cell {
|
||||
padding: 45px;
|
||||
}
|
||||
|
||||
/*Media Queries ------------------------------ */
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
|
||||
.email-body_inner,
|
||||
.email-footer {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
body,
|
||||
.email-body,
|
||||
.email-body_inner,
|
||||
.email-content,
|
||||
.email-wrapper,
|
||||
.email-masthead,
|
||||
.email-footer {
|
||||
background-color: #333333 !important;
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
blockquote,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
span,
|
||||
.purchase_item {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.attributes_content,
|
||||
.discount {
|
||||
background-color: #222 !important;
|
||||
}
|
||||
|
||||
.email-masthead_name {
|
||||
text-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
supported-color-schemes: light dark;
|
||||
}
|
||||
</style>
|
||||
<!--[if mso]>
|
||||
<style type="text/css">
|
||||
.f-fallback {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for 24 hours.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="email-masthead">
|
||||
<a href="https://example.com" class="f-fallback email-masthead_name">
|
||||
link56
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Email Body -->
|
||||
<tr>
|
||||
<td class="email-body" width="570" cellpadding="0" cellspacing="0">
|
||||
<table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<!-- Body content -->
|
||||
<tr>
|
||||
<td class="content-cell">
|
||||
<div class="f-fallback">
|
||||
<h1>您好</h1>
|
||||
<p>您正在登录我们的 link56 平台,系统已为您生成了登录验证码。<strong>该验证码仅在 10 分钟内有效。</strong></p>
|
||||
|
||||
<p class="body-action">
|
||||
[[${Code}]]
|
||||
</p>
|
||||
<p>如果不是您本人操作,请忽略此邮件,或如有疑问,请 <a
|
||||
href="{{SupportUrl}}">联系客服</a>。</p>
|
||||
|
||||
<p>
|
||||
感谢,<br>
|
||||
link56 团队
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tr>
|
||||
<td class="content-cell" align="center">
|
||||
<p class="f-fallback sub align-center">
|
||||
宁波江东远通计算机有限公司
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user