mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 23:23:55 +08:00
add:登录页面和注册页面增加手机号码选项
This commit is contained in:
@@ -125,4 +125,18 @@ public class RedisKeys {
|
||||
return "sms:Validate:Code:" + phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取短信验证码最后发送时间的缓存key
|
||||
*/
|
||||
public static String getSMSLastSendTimeKey(String phone) {
|
||||
return "sms:Validate:Code:" + phone + ":last_send_time";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取短信验证码今日发送次数的缓存key
|
||||
*/
|
||||
public static String getSMSTodayCountKey(String phone) {
|
||||
return "sms:Validate:Code:" + phone + ":today_count";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package xiaozhi.common.validator;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
|
||||
@@ -49,12 +48,20 @@ public class ValidatorUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机号正则表达式
|
||||
* 国际手机号正则表达式
|
||||
* 要求必须带国际区号,格式:+[国家代码][手机号]
|
||||
* 例如:
|
||||
* - +8613800138000
|
||||
* - +12345678900
|
||||
* - +447123456789
|
||||
*/
|
||||
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
|
||||
private static final String INTERNATIONAL_PHONE_REGEX = "^\\+[1-9]\\d{0,3}[1-9]\\d{4,14}$";
|
||||
|
||||
/**
|
||||
* 校验单参数是否是正确的手机号
|
||||
* 校验手机号是否有效
|
||||
* 要求必须带国际区号,格式:+[国家代码][手机号]
|
||||
* 例如:+8613800138000
|
||||
*
|
||||
* @param phone 手机号
|
||||
* @return boolean
|
||||
*/
|
||||
@@ -62,8 +69,9 @@ public class ValidatorUtils {
|
||||
if (phone == null || phone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Pattern pattern = Pattern.compile(PHONE_REGEX);
|
||||
Matcher matcher = pattern.matcher(phone);
|
||||
return matcher.matches();
|
||||
|
||||
// 验证必须带国际区号的手机号格式
|
||||
Pattern pattern = Pattern.compile(INTERNATIONAL_PHONE_REGEX);
|
||||
return pattern.matcher(phone).matches();
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,7 @@ public class ShiroConfig {
|
||||
filterMap.put("/doc.html", "anon");
|
||||
filterMap.put("/favicon.ico", "anon");
|
||||
filterMap.put("/user/captcha", "anon");
|
||||
filterMap.put("/user/smsVerification", "anon");
|
||||
filterMap.put("/user/login", "anon");
|
||||
filterMap.put("/user/pub-config", "anon");
|
||||
filterMap.put("/user/register", "anon");
|
||||
|
||||
+34
-15
@@ -2,6 +2,7 @@ package xiaozhi.modules.security.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -24,6 +25,7 @@ import xiaozhi.common.utils.Result;
|
||||
import xiaozhi.common.validator.AssertUtils;
|
||||
import xiaozhi.common.validator.ValidatorUtils;
|
||||
import xiaozhi.modules.security.dto.LoginDTO;
|
||||
import xiaozhi.modules.security.dto.SmsVerificationDTO;
|
||||
import xiaozhi.modules.security.password.PasswordUtils;
|
||||
import xiaozhi.modules.security.service.CaptchaService;
|
||||
import xiaozhi.modules.security.service.SysUserTokenService;
|
||||
@@ -31,8 +33,10 @@ import xiaozhi.modules.security.user.SecurityUser;
|
||||
import xiaozhi.modules.sys.dto.PasswordDTO;
|
||||
import xiaozhi.modules.sys.dto.RetrievePasswordDTO;
|
||||
import xiaozhi.modules.sys.dto.SysUserDTO;
|
||||
import xiaozhi.modules.sys.service.SysDictDataService;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
import xiaozhi.modules.sys.service.SysUserService;
|
||||
import xiaozhi.modules.sys.vo.SysDictDataItem;
|
||||
|
||||
/**
|
||||
* 登录控制层
|
||||
@@ -46,6 +50,7 @@ public class LoginController {
|
||||
private final SysUserTokenService sysUserTokenService;
|
||||
private final CaptchaService captchaService;
|
||||
private final SysParamsService sysParamsService;
|
||||
private final SysDictDataService sysDictDataService;
|
||||
|
||||
@GetMapping("/captcha")
|
||||
@Operation(summary = "验证码")
|
||||
@@ -56,22 +61,31 @@ public class LoginController {
|
||||
captchaService.create(response, uuid);
|
||||
}
|
||||
|
||||
@GetMapping("/smsVerification")
|
||||
@PostMapping("/smsVerification")
|
||||
@Operation(summary = "短信验证码")
|
||||
public void smsVerification(String phone) throws IOException {
|
||||
// 手机号码不能为空
|
||||
AssertUtils.isBlank(phone, ErrorCode.PHONE_NOT_NULL);
|
||||
public Result<Void> smsVerification(@RequestBody SmsVerificationDTO dto) {
|
||||
// 验证图形验证码
|
||||
boolean validate = captchaService.validate(dto.getCaptchaId(), dto.getCaptcha(), true);
|
||||
if (!validate) {
|
||||
throw new RenException("图形验证码错误");
|
||||
}
|
||||
Boolean isMobileRegister = sysParamsService
|
||||
.getValueObject(Constant.SysMSMParam.SYSTEM_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class);
|
||||
if (!isMobileRegister) {
|
||||
throw new RenException("没有开启手机注册,没法使用短信验证码功能");
|
||||
}
|
||||
// 发送短信验证码
|
||||
captchaService.sendSMSValidateCode(phone);
|
||||
captchaService.sendSMSValidateCode(dto.getPhone());
|
||||
return new Result<>();
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
@Operation(summary = "登录")
|
||||
public Result<TokenDTO> login(@RequestBody LoginDTO login) {
|
||||
// 验证是否正确输入验证码
|
||||
boolean validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha());
|
||||
boolean validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha(), true);
|
||||
if (!validate) {
|
||||
throw new RenException("验证码错误,请重新获取");
|
||||
throw new RenException("图形验证码错误,请重新获取");
|
||||
}
|
||||
// 按照用户名获取用户
|
||||
SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername());
|
||||
@@ -103,15 +117,18 @@ public class LoginController {
|
||||
throw new RenException("用户名不是手机号码,请重新输入");
|
||||
}
|
||||
// 验证短信验证码是否正常
|
||||
validate = captchaService.validateSMSValidateCode(login.getUsername(), login.getCaptcha());
|
||||
validate = captchaService.validateSMSValidateCode(login.getUsername(), login.getMobileCaptcha(), false);
|
||||
if (!validate) {
|
||||
throw new RenException("手机验证码错误,请重新获取");
|
||||
}
|
||||
} else {
|
||||
// 验证是否正确输入验证码
|
||||
validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha());
|
||||
}
|
||||
// 判断是否通过验证
|
||||
if (!validate) {
|
||||
throw new RenException("验证码错误,请重新获取");
|
||||
validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha(), true);
|
||||
if (!validate) {
|
||||
throw new RenException("图形验证码错误,请重新获取");
|
||||
}
|
||||
}
|
||||
|
||||
// 按照用户名获取用户
|
||||
SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername());
|
||||
if (userDTO != null) {
|
||||
@@ -172,8 +189,7 @@ public class LoginController {
|
||||
throw new RenException("用户名或验证码错误");
|
||||
}
|
||||
|
||||
Long userId = SecurityUser.getUserId();
|
||||
sysUserService.changePasswordDirectly(userId, dto.getPassword());
|
||||
sysUserService.changePasswordDirectly(userDTO.getId(), dto.getPassword());
|
||||
return new Result<>();
|
||||
}
|
||||
|
||||
@@ -185,6 +201,9 @@ public class LoginController {
|
||||
.getValueObject(Constant.SysMSMParam.SYSTEM_ENABLE_MOBILE_REGISTER.getValue(), Boolean.class));
|
||||
config.put("version", Constant.VERSION);
|
||||
config.put("allowUserRegister", sysUserService.getAllowUserRegister());
|
||||
List<SysDictDataItem> list = sysDictDataService.getDictDataByType("MOBILE_AREA");
|
||||
config.put("mobileAreaList", list);
|
||||
|
||||
return new Result<Map<String, Object>>().ok(config);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,9 @@ public class LoginDTO implements Serializable {
|
||||
@NotBlank(message = "{sysuser.captcha.require}")
|
||||
private String captcha;
|
||||
|
||||
@Schema(description = "手机验证码")
|
||||
private String mobileCaptcha;
|
||||
|
||||
@Schema(description = "唯一标识")
|
||||
@NotBlank(message = "{sysuser.uuid.require}")
|
||||
private String captchaId;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package xiaozhi.modules.security.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 短信验证码请求DTO
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "短信验证码请求")
|
||||
public class SmsVerificationDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "手机号码")
|
||||
@NotBlank(message = "{sysuser.username.require}")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "验证码")
|
||||
@NotBlank(message = "{sysuser.captcha.require}")
|
||||
private String captcha;
|
||||
|
||||
@Schema(description = "唯一标识")
|
||||
@NotBlank(message = "{sysuser.uuid.require}")
|
||||
private String captchaId;
|
||||
}
|
||||
+12
-5
@@ -18,21 +18,28 @@ public interface CaptchaService {
|
||||
|
||||
/**
|
||||
* 验证码效验
|
||||
* @param uuid uuid
|
||||
* @param code 验证码
|
||||
*
|
||||
* @param uuid uuid
|
||||
* @param code 验证码
|
||||
* @param delete 是否删除验证码
|
||||
* @return true:成功 false:失败
|
||||
*/
|
||||
boolean validate(String uuid, String code);
|
||||
boolean validate(String uuid, String code, Boolean delete);
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param phone 手机
|
||||
*/
|
||||
void sendSMSValidateCode(String phone);
|
||||
|
||||
/**
|
||||
* 验证短信验证码
|
||||
* @param phone 手机
|
||||
*
|
||||
* @param phone 手机
|
||||
* @param code 验证码
|
||||
* @param delete 是否删除验证码
|
||||
* @return true:成功 false:失败
|
||||
*/
|
||||
boolean validateSMSValidateCode(String phone,String code);
|
||||
boolean validateSMSValidateCode(String phone, String code, Boolean delete);
|
||||
}
|
||||
|
||||
+63
-10
@@ -15,10 +15,13 @@ import com.wf.captcha.base.Captcha;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import xiaozhi.common.constant.Constant;
|
||||
import xiaozhi.common.exception.RenException;
|
||||
import xiaozhi.common.redis.RedisKeys;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.modules.security.service.CaptchaService;
|
||||
import xiaozhi.modules.sms.service.SmsService;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
@@ -29,6 +32,8 @@ public class CaptchaServiceImpl implements CaptchaService {
|
||||
private RedisUtils redisUtils;
|
||||
@Resource
|
||||
private SmsService smsService;
|
||||
@Resource
|
||||
private SysParamsService sysParamsService;
|
||||
@Value("${renren.redis.open}")
|
||||
private boolean open;
|
||||
/**
|
||||
@@ -55,12 +60,12 @@ public class CaptchaServiceImpl implements CaptchaService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(String uuid, String code) {
|
||||
public boolean validate(String uuid, String code, Boolean delete) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return false;
|
||||
}
|
||||
// 获取验证码
|
||||
String captcha = getCache(uuid);
|
||||
String captcha = getCache(uuid, delete);
|
||||
|
||||
// 效验成功
|
||||
if (code.equalsIgnoreCase(captcha)) {
|
||||
@@ -72,24 +77,71 @@ public class CaptchaServiceImpl implements CaptchaService {
|
||||
|
||||
@Override
|
||||
public void sendSMSValidateCode(String phone) {
|
||||
// 检查发送间隔
|
||||
String lastSendTimeKey = RedisKeys.getSMSLastSendTimeKey(phone);
|
||||
String lastSendTime = (String) redisUtils.get(lastSendTimeKey);
|
||||
if (lastSendTime != null) {
|
||||
long lastSendTimeLong = Long.parseLong(lastSendTime);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long timeDiff = currentTime - lastSendTimeLong;
|
||||
if (timeDiff < 60000) {
|
||||
throw new RenException("发送太频繁,请" + (60000 - timeDiff) / 1000 + "秒后再试");
|
||||
}
|
||||
}
|
||||
|
||||
// 检查今日发送次数
|
||||
String todayCountKey = RedisKeys.getSMSTodayCountKey(phone);
|
||||
Integer todayCount = (Integer) redisUtils.get(todayCountKey);
|
||||
if (todayCount == null) {
|
||||
todayCount = 0;
|
||||
}
|
||||
|
||||
// 获取最大发送次数限制
|
||||
Integer maxSendCount = sysParamsService.getValueObject(
|
||||
Constant.SysMSMParam.SYSTEM_SMS_MAX_SEND_COUNT.getValue(),
|
||||
Integer.class);
|
||||
if (maxSendCount == null) {
|
||||
maxSendCount = 5; // 默认值
|
||||
}
|
||||
|
||||
if (todayCount >= maxSendCount) {
|
||||
throw new RenException("今日发送次数已达上限");
|
||||
}
|
||||
|
||||
String key = RedisKeys.getSMSValidateCodeKey(phone);
|
||||
String validateCodes = generateValidateCode(6);
|
||||
setCache(key,validateCodes);
|
||||
//发送验证码短信
|
||||
smsService.sendVerificationCodeSms(phone,validateCodes);
|
||||
|
||||
// 设置验证码
|
||||
setCache(key, validateCodes);
|
||||
|
||||
// 设置最后发送时间(60秒)
|
||||
redisUtils.set(lastSendTimeKey, String.valueOf(System.currentTimeMillis()), 60);
|
||||
|
||||
// 更新今日发送次数
|
||||
if (todayCount == 0) {
|
||||
// 如果是今天第一次发送,设置24小时过期
|
||||
redisUtils.set(todayCountKey, 1, RedisUtils.DEFAULT_EXPIRE);
|
||||
} else {
|
||||
redisUtils.set(todayCountKey, todayCount + 1, RedisUtils.DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
// 发送验证码短信
|
||||
// smsService.sendVerificationCodeSms(phone, validateCodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateSMSValidateCode(String phone,String code) {
|
||||
public boolean validateSMSValidateCode(String phone, String code, Boolean delete) {
|
||||
String key = RedisKeys.getSMSValidateCodeKey(phone);
|
||||
return validate(key, code);
|
||||
return validate(key, code, delete);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成指定数量的随机数验证码
|
||||
*
|
||||
* @param length 数量
|
||||
* @return 随机码
|
||||
*/
|
||||
private String generateValidateCode(Integer length) {
|
||||
private String generateValidateCode(Integer length) {
|
||||
String chars = "0123456789"; // 字符范围可以自定义:数字
|
||||
Random random = new Random();
|
||||
StringBuilder code = new StringBuilder();
|
||||
@@ -102,18 +154,19 @@ public class CaptchaServiceImpl implements CaptchaService {
|
||||
private void setCache(String key, String value) {
|
||||
if (open) {
|
||||
key = RedisKeys.getCaptchaKey(key);
|
||||
// 设置5分钟过期
|
||||
redisUtils.set(key, value, 300);
|
||||
} else {
|
||||
localCache.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCache(String key) {
|
||||
private String getCache(String key, Boolean delete) {
|
||||
if (open) {
|
||||
key = RedisKeys.getCaptchaKey(key);
|
||||
String captcha = (String) redisUtils.get(key);
|
||||
// 删除验证码
|
||||
if (captcha != null) {
|
||||
if (captcha != null && delete) {
|
||||
redisUtils.delete(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
-- 添加手机短信注册功能的需要的参数
|
||||
delete from sys_params where id in (601, 602, 610, 611, 612, 613);
|
||||
INSERT INTO sys_params
|
||||
(id, param_code, param_value, value_type, param_type, remark, creator, create_date, updater, update_date)
|
||||
VALUES
|
||||
(601, 'system.enable_mobile_register', 'false', 'boolean', 1, '是否开启手机注册', NULL, NULL, NULL, NULL),
|
||||
(602, 'system.sms.max_send_count', '5', 'number', 1, '单号码最大短信发送条数', NULL, NULL, NULL, NULL),
|
||||
(610, 'aliyun.sms.access_key_id', '', 'string', 1, '阿里云平台access_key', NULL, NULL, NULL, NULL),
|
||||
(611, 'aliyun.sms.access_key_secret', '', 'string', 1, '阿里云平台access_key_secret', NULL, NULL, NULL, NULL),
|
||||
(612, 'aliyun.sms.sign_name', '', 'string', 1, '阿里云短信签名', NULL, NULL, NULL, NULL),
|
||||
(613, 'aliyun.sms.sms_code_template_code', '', 'string', 1, '阿里云短信模板', NULL, NULL, NULL, NULL);
|
||||
@@ -0,0 +1,59 @@
|
||||
-- 添加手机短信注册功能的需要的参数
|
||||
delete from sys_params where id in (601, 602, 610, 611, 612, 613);
|
||||
INSERT INTO sys_params
|
||||
(id, param_code, param_value, value_type, param_type, remark, creator, create_date, updater, update_date)
|
||||
VALUES
|
||||
(601, 'system.enable_mobile_register', 'false', 'boolean', 1, '是否开启手机注册', NULL, NULL, NULL, NULL),
|
||||
(602, 'system.sms.max_send_count', '10', 'number', 1, '单号码单日最大短信发送条数', NULL, NULL, NULL, NULL),
|
||||
(610, 'aliyun.sms.access_key_id', '', 'string', 1, '阿里云平台access_key', NULL, NULL, NULL, NULL),
|
||||
(611, 'aliyun.sms.access_key_secret', '', 'string', 1, '阿里云平台access_key_secret', NULL, NULL, NULL, NULL),
|
||||
(612, 'aliyun.sms.sign_name', '', 'string', 1, '阿里云短信签名', NULL, NULL, NULL, NULL),
|
||||
(613, 'aliyun.sms.sms_code_template_code', '', 'string', 1, '阿里云短信模板', NULL, NULL, NULL, NULL);
|
||||
|
||||
-- 增加手机区域字典
|
||||
-- 插入固件类型字典类型
|
||||
delete from `sys_dict_type` where `id` = 102;
|
||||
INSERT INTO `sys_dict_type` (`id`, `dict_type`, `dict_name`, `remark`, `sort`, `creator`, `create_date`, `updater`, `update_date`) VALUES
|
||||
(102, 'MOBILE_AREA', '手机区域', '手机区域字典', 0, 1, NOW(), 1, NOW());
|
||||
|
||||
-- 插入固件类型字典数据
|
||||
delete from `sys_dict_data` where `dict_type_id` = 102;
|
||||
INSERT INTO `sys_dict_data` (`id`, `dict_type_id`, `dict_label`, `dict_value`, `remark`, `sort`, `creator`, `create_date`, `updater`, `update_date`) VALUES
|
||||
(102001, 102, '中国大陆', '+86', '中国大陆', 1, 1, NOW(), 1, NOW()),
|
||||
(102002, 102, '中国香港', '+852', '中国香港', 2, 1, NOW(), 1, NOW()),
|
||||
(102003, 102, '中国澳门', '+853', '中国澳门', 3, 1, NOW(), 1, NOW()),
|
||||
(102004, 102, '中国台湾', '+886', '中国台湾', 4, 1, NOW(), 1, NOW()),
|
||||
(102005, 102, '美国/加拿大', '+1', '美国/加拿大', 5, 1, NOW(), 1, NOW()),
|
||||
(102006, 102, '英国', '+44', '英国', 6, 1, NOW(), 1, NOW()),
|
||||
(102007, 102, '法国', '+33', '法国', 7, 1, NOW(), 1, NOW()),
|
||||
(102008, 102, '意大利', '+39', '意大利', 8, 1, NOW(), 1, NOW()),
|
||||
(102009, 102, '德国', '+49', '德国', 9, 1, NOW(), 1, NOW()),
|
||||
(102010, 102, '波兰', '+48', '波兰', 10, 1, NOW(), 1, NOW()),
|
||||
(102011, 102, '瑞士', '+41', '瑞士', 11, 1, NOW(), 1, NOW()),
|
||||
(102012, 102, '西班牙', '+34', '西班牙', 12, 1, NOW(), 1, NOW()),
|
||||
(102013, 102, '丹麦', '+45', '丹麦', 13, 1, NOW(), 1, NOW()),
|
||||
(102014, 102, '马来西亚', '+60', '马来西亚', 14, 1, NOW(), 1, NOW()),
|
||||
(102015, 102, '澳大利亚', '+61', '澳大利亚', 15, 1, NOW(), 1, NOW()),
|
||||
(102016, 102, '印度尼西亚', '+62', '印度尼西亚', 16, 1, NOW(), 1, NOW()),
|
||||
(102017, 102, '菲律宾', '+63', '菲律宾', 17, 1, NOW(), 1, NOW()),
|
||||
(102018, 102, '新西兰', '+64', '新西兰', 18, 1, NOW(), 1, NOW()),
|
||||
(102019, 102, '新加坡', '+65', '新加坡', 19, 1, NOW(), 1, NOW()),
|
||||
(102020, 102, '泰国', '+66', '泰国', 20, 1, NOW(), 1, NOW()),
|
||||
(102021, 102, '日本', '+81', '日本', 21, 1, NOW(), 1, NOW()),
|
||||
(102022, 102, '韩国', '+82', '韩国', 22, 1, NOW(), 1, NOW()),
|
||||
(102023, 102, '越南', '+84', '越南', 23, 1, NOW(), 1, NOW()),
|
||||
(102024, 102, '印度', '+91', '印度', 24, 1, NOW(), 1, NOW()),
|
||||
(102025, 102, '巴基斯坦', '+92', '巴基斯坦', 25, 1, NOW(), 1, NOW()),
|
||||
(102026, 102, '尼日利亚', '+234', '尼日利亚', 26, 1, NOW(), 1, NOW()),
|
||||
(102027, 102, '孟加拉国', '+880', '孟加拉国', 27, 1, NOW(), 1, NOW()),
|
||||
(102028, 102, '沙特阿拉伯', '+966', '沙特阿拉伯', 28, 1, NOW(), 1, NOW()),
|
||||
(102029, 102, '阿联酋', '+971', '阿联酋', 29, 1, NOW(), 1, NOW()),
|
||||
(102030, 102, '巴西', '+55', '巴西', 30, 1, NOW(), 1, NOW()),
|
||||
(102031, 102, '墨西哥', '+52', '墨西哥', 31, 1, NOW(), 1, NOW()),
|
||||
(102032, 102, '智利', '+56', '智利', 32, 1, NOW(), 1, NOW()),
|
||||
(102033, 102, '阿根廷', '+54', '阿根廷', 33, 1, NOW(), 1, NOW()),
|
||||
(102034, 102, '埃及', '+20', '埃及', 34, 1, NOW(), 1, NOW()),
|
||||
(102035, 102, '南非', '+27', '南非', 35, 1, NOW(), 1, NOW()),
|
||||
(102036, 102, '肯尼亚', '+254', '肯尼亚', 36, 1, NOW(), 1, NOW()),
|
||||
(102037, 102, '坦桑尼亚', '+255', '坦桑尼亚', 37, 1, NOW(), 1, NOW()),
|
||||
(102038, 102, '哈萨克斯坦', '+7', '哈萨克斯坦', 38, 1, NOW(), 1, NOW());
|
||||
@@ -115,9 +115,9 @@ databaseChangeLog:
|
||||
encoding: utf8
|
||||
path: classpath:db/changelog/202505091409.sql
|
||||
- changeSet:
|
||||
id: 202505141130
|
||||
id: 202505141132
|
||||
author: zjy
|
||||
changes:
|
||||
- sqlFile:
|
||||
encoding: utf8
|
||||
path: classpath:db/changelog/202505141130.sql
|
||||
path: classpath:db/changelog/202505141132.sql
|
||||
Reference in New Issue
Block a user