1
zj
2025-10-09 df30c88c2c76da0cb607bcf129446f43c9a521da
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package com.ruoyi.im.util;
 
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.HashMap;
import java.util.Map;
 
/**
 * 手机号格式校验工具类
 * 支持中国大陆手机号和国际手机号验证
 */
public class PhoneNumberValidatorUtil {
 
    // 中国大陆手机号正则表达式 (11位数字,1开头)
    private static final String CHINA_MOBILE_PATTERN = "^1[3-9]\\d{9}$";
 
    // 国际手机号正则表达式 (国家代码-号码,如+1-1234567890)
    private static final String INTERNATIONAL_PATTERN = "^\\+\\d{1,4}-\\d{4,15}$";
 
    // 常见国家/地区代码映射表
    private static final Map<String, String> COUNTRY_CODES = new HashMap<>();
 
    static {
        // 初始化常见国家/地区代码
        COUNTRY_CODES.put("1", "美国/加拿大");
        COUNTRY_CODES.put("86", "中国大陆");
        COUNTRY_CODES.put("852", "香港");
        COUNTRY_CODES.put("853", "澳门");
        COUNTRY_CODES.put("886", "台湾");
        COUNTRY_CODES.put("81", "日本");
        COUNTRY_CODES.put("82", "韩国");
        COUNTRY_CODES.put("65", "新加坡");
        COUNTRY_CODES.put("60", "马来西亚");
        COUNTRY_CODES.put("44", "英国");
        COUNTRY_CODES.put("33", "法国");
        COUNTRY_CODES.put("49", "德国");
        COUNTRY_CODES.put("61", "澳大利亚");
        // 可以继续添加更多国家/地区代码
    }
 
    /**
     * 验证手机号格式
     * @param phoneNumber 手机号码
     * @return 验证结果
     */
    public static ValidationResult validatePhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.trim().isEmpty()) {
            return new ValidationResult(false, "手机号不能为空");
        }
 
        // 去除可能存在的空格
        phoneNumber = phoneNumber.trim();
 
        // 检查是否为中国大陆手机号
        if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) {
            return new ValidationResult(true, "中国大陆手机号格式正确");
        }
 
        // 检查是否为国际手机号格式
        if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) {
            // 提取国家代码部分
            String[] parts = phoneNumber.split("-", 2);
            String countryCode = parts[0].substring(1); // 去掉+号
 
            // 验证国家代码是否有效
            if (COUNTRY_CODES.containsKey(countryCode)) {
                return new ValidationResult(true, "国际手机号格式正确 (" + COUNTRY_CODES.get(countryCode) + ")");
            } else {
                return new ValidationResult(false, "不支持的国家/地区代码: +" + countryCode);
            }
        }
 
        // 如果都不匹配,返回错误信息
        if (phoneNumber.startsWith("+")) {
            return new ValidationResult(false, "国际手机号格式不正确,请使用'+国家代码-本地号码'格式");
        } else {
            return new ValidationResult(false, "中国大陆手机号应为11位数字且以1开头");
        }
    }
 
    /**
     * 验证结果类
     */
    public static class ValidationResult {
        private final boolean valid;
        private final String message;
 
        public ValidationResult(boolean valid, String message) {
            this.valid = valid;
            this.message = message;
        }
 
        public boolean isValid() {
            return valid;
        }
 
        public String getMessage() {
            return message;
        }
 
        @Override
        public String toString() {
            return message;
        }
    }
 
    /**
     * 提取国家代码(如果是国际手机号)
     * @param phoneNumber 手机号码
     * @return 国家代码(不带+号),如果是中国大陆手机号返回"86"
     */
    public static String extractCountryCode(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.trim().isEmpty()) {
            return null;
        }
 
        phoneNumber = phoneNumber.trim();
 
        // 如果是国际手机号格式
        if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) {
            String[] parts = phoneNumber.split("-", 2);
            return parts[0].substring(1); // 去掉+号
        }
 
        // 如果是中国大陆手机号
        if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) {
            return "86";
        }
 
        return null;
    }
 
    /**
     * 提取本地号码部分
     * @param phoneNumber 手机号码
     * @return 本地号码部分
     */
    public static String extractLocalNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.trim().isEmpty()) {
            return null;
        }
 
        phoneNumber = phoneNumber.trim();
 
        // 如果是国际手机号格式
        if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) {
            String[] parts = phoneNumber.split("-", 2);
            return parts[1];
        }
 
        // 如果是中国大陆手机号
        if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) {
            return phoneNumber;
        }
 
        return null;
    }
 
    /**
     * 格式化手机号显示
     * @param phoneNumber 手机号码
     * @return 格式化后的手机号
     */
    public static String formatPhoneNumber(String phoneNumber) {
        ValidationResult result = validatePhoneNumber(phoneNumber);
        if (!result.isValid()) {
            return phoneNumber; // 如果格式不正确,返回原值
        }
 
        if (Pattern.matches(CHINA_MOBILE_PATTERN, phoneNumber)) {
            // 中国大陆手机号格式化为 3-4-4 格式
            return phoneNumber.replaceFirst("(\\d{3})(\\d{4})(\\d{4})", "$1-$2-$3");
        } else if (Pattern.matches(INTERNATIONAL_PATTERN, phoneNumber)) {
            // 国际手机号保持原格式
            return phoneNumber;
        }
 
        return phoneNumber;
    }
 
    // 测试方法
    public static void main(String[] args) {
        // 测试用例
        String[] testNumbers = {
                "13800138000",         // 中国大陆手机号
                "+1-1234567890",       // 美国手机号
                "+852-12345678",       // 香港手机号
                "12345678901",         // 无效的中国大陆手机号(不以1开头)
                "+86-13800138000",     // 带国家代码的中国大陆手机号
                "+999-1234567890",     // 不支持的国家代码
                "+1-123",              // 号码部分太短
                "abc",                 // 完全无效
                "+1-1234567890123456"  // 号码部分太长
        };
 
        for (String number : testNumbers) {
            ValidationResult result = validatePhoneNumber(number);
            System.out.println(number + " : " + result.getMessage());
 
            if (result.isValid()) {
                System.out.println("  国家代码: " + extractCountryCode(number));
                System.out.println("  本地号码: " + extractLocalNumber(number));
                System.out.println("  格式化: " + formatPhoneNumber(number));
            }
            System.out.println();
        }
    }
}