This commit is contained in:
Timi
2026-07-30 18:28:25 +08:00
parent 8b24804b22
commit f0d1090932
21 changed files with 915 additions and 268 deletions
+78 -21
View File
@@ -1,46 +1,103 @@
<template>
<img
<button
class="tui-captcha ir-pixelated"
v-if="src"
:width="width"
:height="height"
:src="src"
alt="验证码"
@click="update()"
/>
type="button"
:style="captchaStyle"
:disabled="isLoading"
:title="title"
@click="update"
>
<img v-if="src" :src="src" :alt="title" />
<span v-else v-text="placeholder" />
</button>
</template>
<script lang="ts" setup>
import Toolkit from "../../utils/Toolkit";
import {CommonAPI} from "../../api";
import type {CaptchaResult} from "../../types";
defineOptions({
name: "Captcha"
});
const props = withDefaults(defineProps<{
width: number,
height: number,
from: string,
api: string,
}>(), {});
const { width, height, from, api } = toRefs(props);
width?: number,
height?: number,
title?: string,
placeholder?: string,
}>(), {
width: 90,
height: 40,
title: "验证码",
placeholder: "刷新"
});
const emit = defineEmits<{
update: [result: CaptchaResult],
error: [error: unknown]
}>();
const { width, height, title, placeholder } = toRefs(props);
const src = ref("");
function update() {
src.value = `${api.value}?from=${from.value}&width=${width.value}&height=${height.value}&r=${Toolkit.random(0, 999999)}`;
const captchaId = ref("");
const isLoading = ref(false);
const captchaStyle = computed(() => {
return {
width: `${width.value / 16}rem`,
height: `${height.value / 16}rem`
};
});
async function update(): Promise<void> {
isLoading.value = true;
try {
const result = await CommonAPI.captcha(width.value, height.value);
captchaId.value = result.id;
src.value = result.data;
emit("update", result);
} catch (error) {
emit("error", error);
} finally {
isLoading.value = false;
}
}
onMounted(update);
onMounted(async () => {
await update();
});
defineExpose({
captchaId,
src,
isLoading,
update
});
</script>
<style lang="less" scoped>
.tui-captcha {
cursor: var(--tui-cur-pointer);
border: 1px solid gray;
display: block;
margin: 0;
border: 0;
padding: 0;
display: grid;
background: #f8fafc;
overflow: hidden;
cursor: pointer;
color: #64748b;
flex: 0 0 auto;
pointer-events: all;
place-items: center;
border-radius: .5rem;
&:disabled {
cursor: not-allowed;
opacity: .64;
}
img {
width: 100%;
height: 100%;
display: block;
}
}
</style>