PageSourceSearch

https://www.processon.com/assets/js/users/phoneMailBind.js

js processon.com collected 2026-10-02 06:24:53 UTC 10,866 bytes, 281 lines download raw bytes

1window.phoneMailBind = {
2    verityCodeClick: false,
3    countDownTimer: null,
4    captchaScriptLoading: false, //验证码脚本加载锁
5    cb: function () { },
6    text: '',
7    accountType: '',
8    isSubmitting: false, // 防重复提交
9
10    init: function (cb, text) {
11        this.destroy(); // 先清理旧实例
12        this.cb = cb;
13        this.text = text || '为保证您的相关权益,请绑定手机号或邮箱';
14        this.addUI();
15    },
16    // 清理定时器 + DOM + 事件
17    destroy: function () {
18        // 清除倒计时定时器,解决定时器残留错乱
19        if (this.countDownTimer) {
20            clearInterval(this.countDownTimer);
21            this.countDownTimer = null;
22        }
23        // 全部状态重置,避免按钮、验证码锁残留
24        this.verityCodeClick = false;
25        this.isSubmitting = false;
26        this.captchaScriptLoading = false;
27        this.accountType = '';
28        $(".phone_bind_mask").remove();
29    },
30
31    addInputFocus: function () {
32        const that = this;
33        this.tencent_btn_verify_click(0);
34        // 账号输入
35        $("#bind_account_input_c")
36            .off()
37            .on('focus', () => {
38                $(".error-tip-amount").text('');
39                that.bindAccountCorrectOrError(1);
40            })
41            .on('blur', () => {
42                $("#bind_account_input_c").removeClass('inputSelect');
43            })
44            .on('input', () => {
45                const val = $.trim($("#bind_account_input_c").val());
46                if (that.isPhone(val)) {
47                    that.accountType = 'phone';
48                    that.tencent_btn_verify_click(1);
49                } else if (that.isEmail(val)) {
50                    that.accountType = 'email';
51                    that.tencent_btn_verify_click(1);
52                } else {
53                    that.accountType = '';
54                    that.tencent_btn_verify_click(0);
55                }
56            });
57
58        // 验证码输入
59        $("#bind_code_input_c")
60            .off()
61            .on('focus', () => that.bindCodeCorrectOrError(1))
62            .on('blur', () => $("#bind_code_input_c").removeClass('inputSelect'));
63        // 获取验证码
64        $(".tencent_btn_verify").off().on("click", () => {
65            if (that.verityCodeClick) that.tencentVerify();
66        });
67        // 关闭
68        $(".phone_bind_close, .pb_cancel_butt").off().on("click", () => {
69            that.cb?.();
70            that.destroy();
71        });
72        // 确认绑定
73        $(".pb_confirm_butt").off().on("click", () => {
74            that.bindAccount();
75        });
76    },
77
78    tencentVerify: function () {
79        const self = this;
80        const val = $.trim($("#bind_account_input_c").val());
81        if (!this.isPhone(val) && !this.isEmail(val)) {
82            $(".error-tip-amount").text('请输入正确的手机号或邮箱');
83            this.bindAccountCorrectOrError(0);
84            return;
85        }
86        if (this.captchaScriptLoading) return;
87        if (typeof TencentCaptcha !== "function") {
88            this.captchaScriptLoading = true;
89            const script = document.createElement('script');
90            script.src = 'https://turing.captcha.qcloud.com/TCaptcha.js';
91            script.onload = function () {
92                self.captchaScriptLoading = false;
93                self.createCaptcha();
94            };
95            script.onerror = function () {
96                self.captchaScriptLoading = false;
97                Util.globalTopTip("验证码加载失败", "top_error");
98            };
99            document.body.appendChild(script);
100        } else {
101            this.createCaptcha();
102        }
103    },
104
105    // 创建验证码实例
106    createCaptcha: function () {
107        const self = this;
108        try {
109            const captcha = new TencentCaptcha('2039741519', (res) => {
110                if (res.ret === 0) {
111                    $("#signup_ticket").val(res.ticket);
112                    $("#randstr").val(res.randstr);
113                    self.startCountDown();
114                    self.sendVerifyCode();
115                }
116            });
117            captcha.show();
118        } catch (e) {
119            Util.globalTopTip("验证码初始化失败", "top_error");
120        }
121    },
122    // 倒计时统一管理
123    startCountDown: function () {
124        let num = 60;
125        const $btn = $(".tencent_btn_verify");
126        this.verityCodeClick = false;
127        $btn.addClass('notclick').css('color', '#ccc').text(`${num}秒后重新获取`);
128        this.countDownTimer = setInterval(() => {
129            num--;
130            $btn.text(`${num}秒后重新获取`);
131            if (num <= 0) {
132                $btn.text('获取验证码').css('color', '#4386f5').removeClass('notclick');
133                this.verityCodeClick = true;
134                clearInterval(this.countDownTimer);
135                this.countDownTimer = null; // 定时器置空,防止残留
136            }
137        }, 1000);
138    },
139    // 格式校验
140    isPhone: (str) => /^1\d{10}$/.test(str),
141    isEmail: (str) => /^[A-Za-z0-9._-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(str),
142    isCode: (str) => /^\d{6}$/.test(str),
143    // 样式状态
144    bindAccountCorrectOrError: function (correct) {
145        const $el = $("#bind_account_input_c");
146        correct ? $el.removeClass("inputSelect_error").addClass("inputSelect")
147            : $el.removeClass("inputSelect").addClass("inputSelect_error");
148    },
149    bindCodeCorrectOrError: function (correct) {
150        const $el = $("#bind_code_input_c");
151        correct ? $el.removeClass("inputSelect_error").addClass("inputSelect")
152            : $el.removeClass("inputSelect").addClass("inputSelect_error");
153    },
154
155    // 按钮可用状态
156    tencent_btn_verify_click: function (canClick) {
157        const $btn = $(".tencent_btn_verify");
158        if (canClick) {
159            $btn.css("opacity", "1").css("pointer-events", "auto");
160            this.verityCodeClick = true;
161        } else {
162            $btn.css("opacity", "0.4").css("pointer-events", "none");
163            this.verityCodeClick = false;
164        }
165    },
166
167    // 发送验证码
168    sendVerifyCode: function () {
169        const accountVal = $.trim($("#bind_account_input_c").val());
170        const ticket = $('#signup_ticket').val().trim();
171        const randstr = $('#randstr').val().trim();
172        if (!ticket || !randstr) return;
173        const isPhone = this.accountType === 'phone';
174        const url = isPhone
175            ? "/api/personal/user/v3/send/phone/code"
176            : "/api/personal/user/v3/send/email/code";
177        const data = JSON.stringify(
178            isPhone
179                ? { phone: accountVal, type: "bind", signupTicket: ticket, randstr }
180                : { email: accountVal, type: "bind", signupTicket: ticket, randstr }
181        );
182        Util.ajax({
183            url,
184            data,
185            contentType: "application/json",
186            success: (e) => {
187                if (e.code === "200") {
188                    Util.globalTopTip("验证码已发送", "success", 4000, "#phone_bind_content", true);
189                } else {
190                    Util.globalTopTip(e.msg || "发送失败", "top_error");
191                }
192            },
193            error: (e) => Util.globalTopTip(e.msg || "发送失败", "top_error")
194        });
195    },
196
197    // 提交绑定
198    bindAccount: function () {
199        if (this.isSubmitting) return; // 防重复提交
200        this.isSubmitting = true;
201        const accountVal = $.trim($("#bind_account_input_c").val());
202        const codeVal = $.trim($("#bind_code_input_c").val());
203        // 前端校验(必须保留,但后端必须再次校验)
204        if (!this.isPhone(accountVal) && !this.isEmail(accountVal)) {
205            $(".error-tip-amount").text('请输入正确的手机号或邮箱');
206            this.bindAccountCorrectOrError(0);
207            this.isSubmitting = false;
208            return;
209        }
210        if (!this.isCode(codeVal)) {
211            $(".error-tip-code").text('请输入6位数字验证码');
212            this.bindCodeCorrectOrError(0);
213            this.isSubmitting = false;
214            return;
215        }
216        const isPhone = this.accountType === 'phone';
217        const url = isPhone
218            ? "/api/personal/user/setting/bindPhone"
219            : "/api/personal/user/setting/bindEmail";
220
221        const postData = isPhone
222            ? { phone: accountVal, code: codeVal }
223            : { email: accountVal, code: codeVal };
224
225        Util.ajax({
226            url,
227            data: postData,
228            success: (e) => {
229                this.cb?.(accountVal, this.accountType);
230                Util.globalTopTip("绑定成功", "success");
231                setTimeout(() => this.destroy(), 1500);
232            },
233            error: (e) => {
234                Util.globalTopTip(e.msg || "绑定失败", "top_error");
235                this.isSubmitting = false;
236            }
237        });
238    },
239
240    // 渲染DOM
241    addUI: function () {
242        const html = `
243        <div class="phone_bind_mask">
244        <div class="phone_bind_content" id="phone_bind_content">
245            <span class="phone_bind_close icons">&#xe637;</span>
246            <div class="pb_title">绑定手机号/邮箱</div>
247            <div class="pb_tip_title">${this.text}</div>
248            <div class="pb_input_content">
249                <input class="bind_input" placeholder="请输入手机号或邮箱" maxlength="50" type="text" id="bind_account_input_c" />
250                <div class="error-tip-amount"></div>
251            </div>
252            <div class="pb_input_content">
253                <div class="pb_input_code">
254                    <input class="bind_input" placeholder="请输入验证码" maxlength="6" type="text" id="bind_code_input_c" />
255                    <div class="tencent_btn_verify">获取验证码</div>
256                </div>
257                <div class="error-tip-code"></div>
258            </div>
259            <input type="hidden" id="signup_ticket">
260            <input type="hidden" id="randstr">
261            <div class="pb_buttonContent">
262                <div class="service-content">
263                    <span class="icons">&#xe6dd;</span>
264                    <span>在线客服</span>
265                    <span class="service-qr-content">
266                        <img class="service-qr" src="/assets/images/sercice_qr_rob.png" >
267                        <span class="service-qr-text">扫码咨询</span>
268                    </span>
269                </div>
270                <div class="pb_butt_right">
271                    <div class="pb_cancel_butt">暂不绑定</div>
272                    <div class="pb_confirm_butt">确认绑定</div>
273                </div>
274            </div>
275        </div>
276        </div>`;
277
278        $('body').append(html);
279        this.addInputFocus();
280    }
281};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.