一个这样的组件
我直接上代码了
<template>
<t-loading size="small" :loading="loading" show-overlay>
<div class="container" @click="refresh">
<div v-if="svg" class="svg" v-html="svg" />
<img v-else class="base64" :src="base64" alt="" />
</div>
</t-loading>
</template>
<script lang="ts" setup>
import { MessagePlugin } from 'tdesign-vue-next';
import { onMounted, ref } from 'vue';
import { getCaptcha } from '@/api/login';
const emit = defineEmits(['update:modelValue', 'change']);
// base64
const base64 = ref('');
// svg2
const svg = ref('');
const loading = ref(false)
async function refresh() {
loading.value = true
await getCaptcha({ height: 40,
width: 150,
})
.then(({ captchaId, data }) => {
if (data.includes(';base64,')) {
base64.value = data;
} else {
svg.value = data;
}
emit('update:modelValue', captchaId);
emit('change', {
base64,
svg,
captchaId,
});
})
.catch((err) => {
MessagePlugin.error(err.message);
}).finally(()=>{
loading.value = false
});
}
onMounted(() => {
refresh();
});
defineExpose({
refresh,
});
</script>
<style lang="less" scoped>
.container {
height: 40px;
width: 150px;
cursor: pointer;
.svg {
height: 100%;
position: relative;
}
.base64 {
height: 100%;
}
}
</style>
组件的使用
<t-form-item class="captcha-code" name="captchaCode">
<t-input v-model="formData.captchaCode" size="large" placeholder="请输入验证码" />
<t-button size="large">
<template #content>
<captcha
ref="captchaRef"
v-model="formData.captchaId"
@change="
() => {
formData.captchaCode = '';
}
"
></captcha>
</template>
</t-button>
</t-form-item>
顺便在这里提一下 我这对接的是node 的接口 验证码是后端返回的svg 我把验证码svg 后端逻辑也说一下啊
import * as svgCaptcha from 'svg-captcha';
import * as svgToDataURL from 'mini-svg-data-uri';
这里用到了两个插件
/**
* 验证码
* @param type 图片验证码类型 svg
* @param width 宽
* @param height 高
*/
async captcha(type: string, width = 150, height = 50) {
const svg = svgCaptcha.create({
ignoreChars: 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM',
width,
height,
});
const result = {
captchaId: uuid(),
data: svg.data.replace(/"/g, "'"),
};
// 文字变白
const rpList = [
'#111',
'#222',
'#333',
'#444',
'#555',
'#666',
'#777',
'#888',
'#999',
];
rpList.forEach(rp => {
result.data = result.data['replaceAll'](rp, '#fff');
});
if (type === 'base64') {
result.data = svgToDataURL(result.data);
}
// 半小时过期
await this.cacheManager.set(
`verify:img:${result.captchaId}`,
svg.text.toLowerCase(),
{ ttl: 1800 }
);
return result;
}
以上的node 的service 接口的逻辑
这是前端收到的data