子组件代码
<template>
<div class="code">
<div class="transfer_dia">
<div class="title">
<span class="icon_class">
<el-icon color="#faad14"><InfoFilled /></el-icon>
</span>
仅限完成企业的已认证已签约才能申请账期,你已完成个人认证签约,
<br />
需先解除绑定后完成企业认证签约~
</div>
</div>
<div class="confirm_box">
<strong>确认需要解除认证?将右图中看到的验证码填入下方输入框中。 </strong>
</div>
<div class="input_box" style="display: flex">
<el-form :model="cancelForm" :rules="cancelRules" ref="ruleFormRef2" class="form">
<el-form-item label="" prop="number">
<el-input
style="width: 214px; height: 40px"
placeholder="请输入验证码 (不区分大小写)"
v-model="cancelForm.number"
clearable />
</el-form-item>
</el-form>
<canvas ref="canvas" width="120" height="43" @click="refreshCaptcha"></canvas>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import black3 from '../../../../assets/home/bac_yanzhengma.png'
const showNum = ref([])
const ruleFormRef2 = ref('')
const canvas = ref(null)
const cancelForm = ref({
number: ''
})
const cancelRules = ref({
number: [
{ required: true, message: '必填项', trigger: 'blur' },
{
validator: (rule, value, callback) => {
console.log('showNum:', showNum.value.join('').toLowerCase())
console.log('value:', value.toLowerCase())
const num = showNum.value.join('').toLowerCase()
if (value.toLowerCase() === num) {
callback()
} else {
callback(new Error('您输入的验证码错误!请重新输入!'))
}
},
trigger: 'blur'
}
]
})
onMounted(() => {
const img = new Image()
img.src = black3 // 图片的URL,注意路径应适配你的项目结构
img.onload = () => {
draw(showNum, img)
}
})
// 绘制验证码图像
function draw (showNum, img) {
const aCode = 'A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0'.split(',')
const aLength = aCode.length // 验证码字符数组的长度
const context = canvas.value.getContext('2d')
context.drawImage(img, 0, 0, canvas.value.width, canvas.value.height)
// 绘制验证码文本
for (let i = 0; i <= 3; i++) {
const j = Math.floor(Math.random() * aLength)
const deg = (Math.random() * 30 * Math.PI) / 180
const txt = aCode[j]
showNum.value[i] = txt.toLowerCase()
const x = 10 + i * 20
const y = 20 + Math.random() * 8
context.font = 'bold 23px 微软雅黑'
context.translate(x, y)
context.rotate(deg)
context.fillStyle = randomColor()
context.fillText(txt, 0, 0)
context.rotate(-deg)
context.translate(-x, -y)
}
// 绘制验证码的干扰线
for (let i = 0; i <= 5; i++) {
context.strokeStyle = randomColor()
context.beginPath()
context.moveTo(Math.random() * canvas.value.width, Math.random() * canvas.value.height)
context.lineTo(Math.random() * canvas.value.width, Math.random() * canvas.value.height)
context.stroke()
}
// 绘制验证码的干扰点
for (let i = 0; i <= 30; i++) {
context.strokeStyle = randomColor()
context.beginPath()
const x = Math.random() * canvas.value.width
const y = Math.random() * canvas.value.height
context.moveTo(x, y)
context.lineTo(x + 1, y + 1)
context.stroke()
}
}
// 生成随机颜色
function randomColor () {
const r = Math.floor(Math.random() * 256)
const g = Math.floor(Math.random() * 256)
const b = Math.floor(Math.random() * 256)
return `rgb(${r},${g},${b})`
}
function refreshCaptcha () {
const img = new Image()
img.src = black3
img.onload = () => {
draw(showNum, img)
}
}
const checkCaptcha = () => {
return new Promise((resolve, reject) => {
ruleFormRef2.value.validate(async (valid, fields) => {
if (valid) {
resolve(valid)
} else {
reject(valid)
}
})
})
}
const reset = () => {
ruleFormRef2.value.resetFields()
}
defineExpose({
checkCaptcha,
reset
})
</script>
<style lang="scss" scoped>
.code {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
text-align: center;
.transfer_dia {
.title {
width: 100%;
padding: 10px;
background-color: #fffbe6;
line-height: 28px;
// padding-left: 20px;
border: 1px solid #faad14;
display: flex;
// align-items: center;
.icon_class {
margin-right: 10px;
}
}
.el_transfer {
text-align: left;
display: inline-block;
}
.left_icon {
position: absolute;
left: 195px;
top: 113px;
&.right {
left: 768px;
}
}
::v-deep .el-transfer-panel {
width: 260px;
}
}
.confirm_box {
margin-top: 20px;
margin-bottom: 10px;
}
.input_box {
display: flex;
margin-bottom: 30px;
.form {
margin-right: 20px;
}
}
#canvas {
float: right;
display: inline-block;
border: 1px solid #ccc;
border-radius: 5px;
cursor: pointer;
}
}
</style>
父组件 代码
<!-- 解除认证 -->
<MyDialog title="解除认证" width="600px" top="20vh" v-model="removeShow">
<div class="remove_content">
<CancelCertify ref="CancelCertifyRef"></CancelCertify>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="removeClose()">关闭</el-button>
<el-button @click="removeSubmit()" type="primary"> 确定 </el-button>
</div>
</template>
</MyDialog>
// 解除认证 确定
const removeSubmit = async () => {
const res = await CancelCertifyRef.value.checkCaptcha()
if (res) {
const res = await accountUserUnbind()
ElMessage.success('操作成功,即将进行跳转')
removeClose()
setTimeout(() => {
toCertify()
}, 1200)
}
}
// 解除认证 关闭
const removeClose = () => {
CancelCertifyRef.value.reset()
removeShow.value = false
}