<template>
	<el-form-item class="login-container" prop="verifyCode" label="验证码">
		<el-input
			v-model="captchaData.verifyCode"
			auto-complete="off"
			placeholder="请输入右侧的计算结果"
			clearable
			class="input"
			size="large"
			@change="verifyCaptcha"
			@input="setVerifyCode"
		>
		  <template #prefix>
			<svg-icon icon-class="verify_code"/>
		  </template>
		</el-input>
		<div class="captcha">
			<img :src="captchaBase64" @click="getCaptcha"/>
		</div>
	</el-form-item>
</template>

<script lang="ts" setup>

import SvgIcon from "@/components/SvgIcon/index.vue";
import { getCaptchaApi } from "@/api/auth";
import { CaptchaCheck, CaptchaControllerService } from "@/generated";

const props = defineProps({
  verifyCode: {
	type: String,
	required: true
  },
  rules: {
	type: Object,
	required: true
  }
});


const  emit  = defineEmits(['update:verifyCode']);

const setVerifyCode = (value: string) => {
  emit('update:verifyCode', value); // 发送自定义事件更新父组件的 verifyCode 值
};

watch(() => props.verifyCode, (newValue) => {
  captchaData.value.verifyCode= newValue; // 当从父组件传来的 verifyCode 值变化时,更新本地的 verifyCode 值
});

/**
 * 验证码图片Base64字符串
 */
const captchaBase64 = ref();

const captchaData = ref<CaptchaCheck>({
	verifyCode: props.verifyCode,
	verifyCodeKey: "",
});

let selfRules = ref({})
const veriflCode = [{
  validator: verifyCaptcha,
  trigger: 'blur'
}]

/**
 * 获取验证码
 */
function getCaptcha() {
	getCaptchaApi().then(({ data }) => {
		const { verifyCodeBase64, verifyCodeKey } = data;
		captchaData.value.verifyCodeKey = verifyCodeKey;
		captchaBase64.value = verifyCodeBase64;
	});
}

/**
 * 校验
 */
async function verifyCaptcha (rule: any, value: any, callback: any)  {
  if (value){
	return new Promise((resolve, reject) => {
	  CaptchaControllerService.checkCaptcha(captchaData.value)
		.then((res) => {
		  const code = res.data
		  if (code !== value){
			callback(new Error('验证码错误!'))
		  } else if(!code){
			callback(new Error('验证码超时!'))
		  }else {
			callback()
		  }
		})
		.catch((error: any) => {
		  reject(error);
		  getCaptcha();
		});
	})
  } else {
	callback(new Error('验证码不能为空!'))
  }
}

onBeforeMount(() => {
  selfRules.value = props.rules
  selfRules.value.verifyCode = veriflCode
})

onMounted(() => {
	getCaptcha();
});

</script>

<style lang="scss" scoped>
:deep(.el-form-item__content){
  display: flex;
  flex-grow: 1;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: left;
}

:deep(.el-form-item__label){
  height: 48px;
  line-height: 48px;
}

.login-container {
	width: 500px;
	//padding: 20px 35px 0;
	display: flex;
	white-space: nowrap;

	.input {
		background: transparent;
		height: 48px;
	    flex-grow: 1;

		// 子组件 scoped 无效,使用 :deep
		//:deep(.el-input__wrapper) {
		//  padding: 0;
		//  background: transparent;
		//  box-shadow: none;
		//
		//  .el-input__inner {
		//	color: #fff;
		//	background: transparent;
		//	border: 0;
		//	border-radius: 0;
		//	caret-color: #fff;
		//
		//	&:-webkit-autofill {
		//	  box-shadow: 0 0 0 1000px transparent inset !important;
		//	  -webkit-text-fill-color: #fff !important;
		//	}
		//
		//	// 设置输入框自动填充的延迟属性
		//	&:-webkit-autofill,
		//	&:-webkit-autofill:hover,
		//	&:-webkit-autofill:focus,
		//	&:-webkit-autofill:active {
		//	  transition: color 99999s ease-out, background-color 99999s ease-out;
		//	  transition-delay: 99999s;
		//	}
		//  }
		//}
	}

	.captcha {
		margin-left: 1px;

		img {
		  width: 120px;
		  height: 48px;
		  cursor: pointer;
		  display: flex;
		  align-items: center;
		}
	}
}
</style>
    

声明

作者: liyao

版权:本博客所有文章除特别声明外,均采用CCBY-NC-SA4.O许可协议。转载请注明!

最后更新于 2026-02-11 18:51 history