/*
 * @Author: housy
 * @Email: housy@guahao.com
 * @Date: 2019-05-22
 * @Description: 手机验证码
 */

<template>
    <div class="phone-code-wrapper">
        <el-input v-model.trim="formParams[name]"
                  v-bind="getMergedObject(extend, {placeholder:'请输入验证码'})"
                  v-on="extend"
                  class="code-input" />
        <el-button v-if="!materialConfig.disabled"
                   @click="() => clickBtn()"
                   v-bind="getMergedObject(button.extend, {type:'text'})"
                   v-on="extend"
                   :disabled="hasSended">
            {{ hasSended ? `${time}${button.sendedLabel || '已发送'}` : (button.label || '获取验证码') }}
        </el-button>

        <!-- 图形验证码弹窗 -->
        <el-dialog :visible.sync="dialogVisible"
                   :title="image.title || '图形验证码'"
                   append-to-body
                   width="600px">
            <div class="image-code-box">
                <bk-image-code ref="imageCode"
                               :materialConfig="image"
                               :formParams="imageParams" />
            </div>
            <span slot="footer"
                  class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button @click="() =>submitCode(formParams[targetField], imageParams)"
                           :loading="hasSended"
                           type="primary">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
import { mobileReg, getMergedObject } from 'utils/util';

export default {
    name: 'BkPhoneCode',
    props: {
        // 元件配置
        materialConfig: {
            type: Object,
            required: true
        },
        // 表单所有元件参数
        formParams: {
            type: Object,
            required: true
        }
    },
    data() {
        const { image } = this.materialConfig;
        return {
            getMergedObject,
            name: '', //  组件的唯一标识
            src: '', // 图形验证码的src
            time: 60, // 倒计时时间
            /**
             * 倒计时计时器
             */
            timeout: '',
            hasSended: false, // 是否已发送验证码状态，默认false未发送
            extend: {}, // 输入框的相关配置
            button: {}, // 发送验证码按钮的相关配置
            image: {}, // 图片验证码的相关配置
            imageParams: {
                [(image && image.name) || '']: '' // 图片的验证码
            },
            targetField: '', // 手机号对应的表单字段名
            dialogVisible: false
        };
    },
    watch: {
        dialogVisible(val) {
            if (!val) this.imageParams[this.image.name] = '';
        }
    },
    created() {
        const {
            name, extend, sendButton, image, targetField 
        } = this.materialConfig;
        this.name = name;
        this.extend = extend;
        this.button = sendButton || {};
        this.image = image || {};
        this.targetField = targetField;
    },
    methods: {
        /**
         * 点击发送验证码按钮事件
         */
        clickBtn() {
            const { targetField, imageVerify } = this.materialConfig;
            const phonenumber = this.formParams[targetField];
            const reg = mobileReg();
            if (!phonenumber) {
                this.$message.error('请填写手机号码');
                return;
            }
            if (!phonenumber.match(reg)) {
                this.$message.error('手机号码格式不正确');
                return;
            }

            // 判断是否需要做图形验证码校验
            if (!imageVerify) {
                // 直接发送验证码
                this.submitCode(phonenumber);
            } else {
                // 打开图形验证码弹窗
                this.dialogVisible = true;
                this.$nextTick(() => {
                    this.$refs.imageCode.handleImgClick(this.image);
                });
            }
        },

        /**
         * 发送验证码
         * @param {String} phonenumber  要发送的手机号
         * @param {Object} imageParams  图形验证码的对象
         */
        submitCode(phonenumber, imageParams) {
            if (this.materialConfig.imageVerify && !imageParams[this.image.name]) {
                this.$message.error('请填写图片验证码');
                this.$refs.imageCode.handleImgClick(this.image);
                return;
            }

            if (!this.hasSended) {
                const { countTime, http } = this.button;
                const {
                    url, method, params, onBefore, onSuccess, onFaild 
                } = http || {};
                const currentParams = params || { default: 'userPhone' };
               

                // 发送验证码
                if (!url) {
                    console.warn('button.http.url属性不能为空');
                    return;
                }

                // 删除加密，暂时不进行加密处理
                const encryptPhoneNumber = phonenumber;

                // 处理请求参数
                let finalParams = Object.assign(
                    {},
                    currentParams,
                    {
                        [currentParams.default]: encryptPhoneNumber
                    },
                    imageParams || {}
                );
                if (finalParams.default) delete finalParams.default;

                // 调用请求发送前函数钩子
                if (typeof onBefore === 'function') {
                    const result = onBefore(finalParams, this);
                    if (result === false) return;
                    if (typeof result === 'object') finalParams = result;
                }

                // 发送验证码
                this.$fetch({
                    url,
                    params: finalParams,
                    method: method || 'post'
                })
                    .then(res => {
                        if (!res) {
                            if (typeof onFaild === 'function') onFaild(res, this);
                            // 停止记时
                            this.time = 0; 
                            this.$refs.imageCode.handleImgClick();
                            return;
                        }
                        this.$message.success('发送成功');
                        this.hasSended = true;
                        // 重置计时时间
                        this.time = countTime || 60;
                        // 倒计时
                        this.getTimeout();
                        if (this.materialConfig.imageVerify) this.dialogVisible = false;
                        // 成功回调
                        if (typeof onSuccess === 'function') {
                            onSuccess(res, this);
                        }
                    })
                    .catch(err => {
                        // 失败回调
                        if (typeof onFaild === 'function') {
                            // 停止记时
                            this.time = 0; 
                            onFaild(err, this);
                        }
                    });
            }
        },
        getTimeout() {
            this.timeout = setTimeout(() => {
                this.time -= 1;
                if (this.time) {
                    this.getTimeout();
                } else {
                    clearTimeout(this.timeout);
                    this.hasSended = false;
                }
            }, 1000);
        }
    }
};
</script>
