工具完成
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
2025-06-28 22:38:49 +08:00
parent 2c668fedd0
commit 8400dbfab9
60 changed files with 23197 additions and 144 deletions

View File

@ -0,0 +1,418 @@
<template>
<div class="space-y-6">
<!-- 算法选择 -->
<div class="card p-4">
<h3 class="text-md font-medium text-primary mb-3">选择加密算法</h3>
<div class="grid grid-cols-2 md:grid-cols-6 gap-2">
<button
v-for="algorithm in algorithms"
:key="algorithm.type"
:class="[
'px-3 py-2 text-sm font-medium rounded transition-all',
activeAlgorithm === algorithm.type
? 'bg-primary text-white shadow-sm'
: 'bg-block text-secondary border hover:bg-hover'
]"
@click="setActiveAlgorithm(algorithm.type)"
>
{{ algorithm.name }}
</button>
</div>
</div>
<!-- 操作模式选择仅对支持编码/解码的算法显示 -->
<div v-if="currentAlgorithm?.isEncodeDecode" class="card p-4">
<h3 class="text-md font-medium text-primary mb-3">操作模式</h3>
<div class="flex gap-2">
<button
:class="[
'flex-1 px-4 py-2 text-sm font-medium rounded transition-all',
!isDecoding ? 'bg-primary text-white' : 'bg-block text-secondary border'
]"
@click="isDecoding = false"
>
{{ currentAlgorithm?.type === 'aes' ? '加密' : '编码' }}
</button>
<button
:class="[
'flex-1 px-4 py-2 text-sm font-medium rounded transition-all',
isDecoding ? 'bg-primary text-white' : 'bg-block text-secondary border'
]"
@click="isDecoding = true"
>
{{ currentAlgorithm?.type === 'aes' ? '解密' : '解码' }}
</button>
</div>
</div>
<!-- 输入和处理区域 -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- 输入区域 -->
<div class="card p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-md font-medium text-primary">输入内容</h3>
<div class="flex gap-2">
<button @click="loadExample" class="btn-secondary text-sm">
<FontAwesomeIcon :icon="['fas', 'redo']" class="mr-1" />
示例
</button>
<button @click="clearAll" class="btn-secondary text-sm">
<FontAwesomeIcon :icon="['fas', 'eraser']" class="mr-1" />
清空
</button>
</div>
</div>
<div class="space-y-4">
<!-- 密钥输入仅对需要密钥的算法显示 -->
<div v-if="currentAlgorithm?.needsKey">
<label class="block text-sm text-secondary font-medium mb-2">密钥</label>
<input
v-model="secretKey"
type="text"
class="input-field w-full"
placeholder="请输入加密密钥..."
/>
</div>
<!-- 文本输入 -->
<div>
<label class="block text-sm text-secondary font-medium mb-2">
{{ isDecoding && currentAlgorithm?.isEncodeDecode ? '待解密/解码内容' : '待加密/编码内容' }}
</label>
<textarea
v-model="inputText"
class="textarea-field h-36 w-full font-mono resize-y"
:placeholder="getInputPlaceholder()"
/>
</div>
<!-- 处理按钮 -->
<button
@click="processOperation"
class="btn-primary w-full flex items-center justify-center gap-2"
:disabled="!inputText.trim() || (currentAlgorithm?.needsKey && !secretKey.trim())"
>
<FontAwesomeIcon :icon="['fas', 'lock']" />
{{ getProcessButtonText() }}
</button>
</div>
</div>
<!-- 输出区域 -->
<div class="card p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-md font-medium text-primary">输出结果</h3>
<button
v-if="output"
@click="copyToClipboard"
class="btn-secondary text-sm"
:disabled="!output"
>
<FontAwesomeIcon :icon="copied ? ['fas', 'check'] : ['fas', 'copy']" class="mr-1" />
{{ copied ? '已复制' : '复制' }}
</button>
</div>
<div class="space-y-4">
<!-- 结果显示 -->
<div>
<label class="block text-sm text-secondary font-medium mb-2">
{{ isDecoding && currentAlgorithm?.isEncodeDecode ? '解密/解码结果' : '加密/编码结果' }}
</label>
<textarea
v-model="output"
readonly
class="textarea-field h-36 w-full font-mono resize-y bg-block"
placeholder="结果将在这里显示..."
/>
</div>
<!-- 结果信息 -->
<div v-if="output" class="text-sm text-tertiary">
<div>字符长度: {{ output.length }}</div>
<div v-if="currentAlgorithm?.type !== 'aes' && !isDecoding">
哈希值: {{ currentAlgorithm?.name }}
</div>
</div>
</div>
</div>
</div>
<!-- 错误和成功消息 -->
<div v-if="error" class="p-3 bg-red-900/20 border border-red-700/30 rounded-lg text-error">
<FontAwesomeIcon :icon="['fas', 'exclamation-triangle']" class="mr-2" />
{{ error }}
</div>
<div v-if="success" class="p-3 bg-green-900/20 border border-green-700/30 rounded-lg text-green-400">
<FontAwesomeIcon :icon="['fas', 'check']" class="mr-2" />
{{ success }}
</div>
<!-- 算法说明 -->
<div class="card p-4">
<h3 class="text-md font-medium text-primary mb-3">
<FontAwesomeIcon :icon="['fas', 'info-circle']" class="mr-2" />
算法说明
</h3>
<div class="text-sm text-secondary">
{{ getAlgorithmDescription() }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import CryptoJS from 'crypto-js'
// 加密算法类型
type CryptoType = 'md5' | 'sha1' | 'sha256' | 'sha512' | 'aes' | 'base64'
// 算法配置
interface AlgorithmConfig {
type: CryptoType
name: string
needsKey: boolean
isEncodeDecode: boolean
description: string
}
// 响应式状态
const activeAlgorithm = ref<CryptoType>('md5')
const inputText = ref('')
const secretKey = ref('')
const output = ref('')
const isDecoding = ref(false)
const copied = ref(false)
const error = ref<string | null>(null)
const success = ref<string | null>(null)
// 算法配置
const algorithms: AlgorithmConfig[] = [
{
type: 'md5',
name: 'MD5',
needsKey: false,
isEncodeDecode: false,
description: 'MD5是一种广泛使用的密码散列函数可以产生出一个128位16字节的散列值。常用于文件校验和密码存储。'
},
{
type: 'sha1',
name: 'SHA1',
needsKey: false,
isEncodeDecode: false,
description: 'SHA-1是一种密码散列函数可以产生一个160位20字节的散列值。比MD5更安全但现在也被认为不够安全。'
},
{
type: 'sha256',
name: 'SHA256',
needsKey: false,
isEncodeDecode: false,
description: 'SHA-256是SHA-2家族的一种可以产生一个256位32字节的散列值。目前被认为是安全的哈希算法。'
},
{
type: 'sha512',
name: 'SHA512',
needsKey: false,
isEncodeDecode: false,
description: 'SHA-512是SHA-2家族的一种可以产生一个512位64字节的散列值。比SHA-256更安全计算量也更大。'
},
{
type: 'aes',
name: 'AES',
needsKey: true,
isEncodeDecode: true,
description: 'AES高级加密标准是一种对称加密算法需要相同的密钥进行加密和解密。广泛用于数据保护。'
},
{
type: 'base64',
name: 'Base64',
needsKey: false,
isEncodeDecode: true,
description: 'Base64是一种编码方式常用于在文本环境中传输二进制数据。不是加密算法只是编码转换。'
}
]
// 当前算法配置
const currentAlgorithm = computed(() =>
algorithms.find(algo => algo.type === activeAlgorithm.value)
)
// 获取输入提示文本
const getInputPlaceholder = (): string => {
if (isDecoding.value && currentAlgorithm.value?.isEncodeDecode) {
return currentAlgorithm.value.type === 'aes'
? '请输入要解密的密文...'
: '请输入要解码的内容...'
}
return '请输入要处理的文本内容...'
}
// 获取处理按钮文本
const getProcessButtonText = (): string => {
if (!currentAlgorithm.value) return '处理'
if (currentAlgorithm.value.isEncodeDecode) {
return isDecoding.value
? (currentAlgorithm.value.type === 'aes' ? '解密' : '解码')
: (currentAlgorithm.value.type === 'aes' ? '加密' : '编码')
}
return '生成哈希'
}
// 获取算法描述
const getAlgorithmDescription = (): string => {
return currentAlgorithm.value?.description || ''
}
// 设置活动算法
const setActiveAlgorithm = (type: CryptoType) => {
activeAlgorithm.value = type
output.value = ''
error.value = null
success.value = null
// 如果不支持编码/解码,重置解码状态
if (!currentAlgorithm.value?.isEncodeDecode) {
isDecoding.value = false
}
}
// 处理操作
const processOperation = () => {
error.value = null
success.value = null
output.value = ''
if (!inputText.value.trim()) {
error.value = '请输入要处理的内容'
return
}
if (currentAlgorithm.value?.needsKey && !secretKey.value.trim()) {
error.value = '请输入密钥'
return
}
try {
let result = ''
switch (activeAlgorithm.value) {
case 'md5':
result = CryptoJS.MD5(inputText.value).toString()
break
case 'sha1':
result = CryptoJS.SHA1(inputText.value).toString()
break
case 'sha256':
result = CryptoJS.SHA256(inputText.value).toString()
break
case 'sha512':
result = CryptoJS.SHA512(inputText.value).toString()
break
case 'aes':
if (isDecoding.value) {
// 解密操作
try {
const decrypted = CryptoJS.AES.decrypt(inputText.value, secretKey.value)
result = decrypted.toString(CryptoJS.enc.Utf8)
if (!result) {
throw new Error('解密失败,请检查密文和密钥是否正确')
}
} catch {
throw new Error('解密失败,请检查密文和密钥是否正确')
}
} else {
// 加密操作
result = CryptoJS.AES.encrypt(inputText.value, secretKey.value).toString()
}
break
case 'base64':
if (isDecoding.value) {
// Base64解码
try {
result = CryptoJS.enc.Base64.parse(inputText.value).toString(CryptoJS.enc.Utf8)
} catch {
throw new Error('Base64解码失败请检查输入内容格式')
}
} else {
// Base64编码
result = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(inputText.value))
}
break
}
output.value = result
success.value = isDecoding.value ? '解密/解码成功' : '加密/编码成功'
} catch (err) {
console.error('处理错误:', err)
error.value = `处理失败: ${err instanceof Error ? err.message : '未知错误'}`
}
}
// 复制到剪贴板
const copyToClipboard = async () => {
if (!output.value) return
try {
await navigator.clipboard.writeText(output.value)
copied.value = true
setTimeout(() => {
copied.value = false
}, 2000)
} catch (err) {
console.error('复制失败:', err)
error.value = '复制失败'
}
}
// 清空所有内容
const clearAll = () => {
inputText.value = ''
secretKey.value = ''
output.value = ''
error.value = null
success.value = null
}
// 加载示例
const loadExample = () => {
const examples: Record<CryptoType, { input: string; key?: string }> = {
md5: { input: 'Hello, World!' },
sha1: { input: 'Hello, World!' },
sha256: { input: 'Hello, World!' },
sha512: { input: 'Hello, World!' },
aes: { input: 'Hello, World!', key: 'secret-key-12345' },
base64: { input: 'Hello, World!' }
}
const example = examples[activeAlgorithm.value]
inputText.value = example.input
if (example.key) {
secretKey.value = example.key
}
output.value = ''
error.value = null
success.value = null
}
// 清除状态提示的定时器
watch([error, success], () => {
if (error.value || success.value) {
setTimeout(() => {
error.value = null
success.value = null
}, 3000)
}
})
</script>