|
@@ -47,3 +47,74 @@ export function displayTime(time) {
|
|
|
|
|
|
|
|
return formatTime(date, 'MM-dd HH:mm')
|
|
return formatTime(date, 'MM-dd HH:mm')
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 解密/解码 Base64 字符串为 UTF-8 字符串
|
|
|
|
|
+ * @param {string} str - Base64 编码的字符串
|
|
|
|
|
+ * @returns {string}
|
|
|
|
|
+ */
|
|
|
|
|
+export function decodeBase64(str) {
|
|
|
|
|
+ if (!str) return ''
|
|
|
|
|
+ const cleanStr = String(str).trim().replace(/\s+/g, '')
|
|
|
|
|
+ // 检查是否为 base64 格式
|
|
|
|
|
+ const isBase64 = /^[A-Za-z0-9+/=]+$/.test(cleanStr)
|
|
|
|
|
+ if (!isBase64) return str
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1. Base64 解码为二进制字符串
|
|
|
|
|
+ const atobPolyfill = (s) => {
|
|
|
|
|
+ if (typeof atob === 'function') return atob(s)
|
|
|
|
|
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
|
|
|
|
|
+ let output = ''
|
|
|
|
|
+ const clean = s.replace(/=+$/, '')
|
|
|
|
|
+ for (let bc = 0, bs, buffer, idx = 0; idx < clean.length; ) {
|
|
|
|
|
+ const char = clean.charAt(idx++)
|
|
|
|
|
+ const buffer = chars.indexOf(char)
|
|
|
|
|
+ if (buffer === -1) throw new Error('Invalid base64 character')
|
|
|
|
|
+ bs = bc % 4 ? bs * 64 + buffer : buffer
|
|
|
|
|
+ if (bc++ % 4) {
|
|
|
|
|
+ output += String.fromCharCode(255 & bs >> (-2 * bc & 6))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return output
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const decodedBinary = atobPolyfill(cleanStr)
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 将二进制字符串解码为 UTF-8 字符串
|
|
|
|
|
+ const decodeUtf8 = (bin) => {
|
|
|
|
|
+ let result = ''
|
|
|
|
|
+ let i = 0
|
|
|
|
|
+ while (i < bin.length) {
|
|
|
|
|
+ const c1 = bin.charCodeAt(i++)
|
|
|
|
|
+ if (c1 < 128) {
|
|
|
|
|
+ result += String.fromCharCode(c1)
|
|
|
|
|
+ } else if (c1 > 191 && c1 < 224) {
|
|
|
|
|
+ const c2 = bin.charCodeAt(i++)
|
|
|
|
|
+ result += String.fromCharCode(((c1 & 31) << 6) | (c2 & 63))
|
|
|
|
|
+ } else if (c1 > 223 && c1 < 240) {
|
|
|
|
|
+ const c2 = bin.charCodeAt(i++)
|
|
|
|
|
+ const c3 = bin.charCodeAt(i++)
|
|
|
|
|
+ result += String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const c2 = bin.charCodeAt(i++)
|
|
|
|
|
+ const c3 = bin.charCodeAt(i++)
|
|
|
|
|
+ const c4 = bin.charCodeAt(i++)
|
|
|
|
|
+ const codepoint = ((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)
|
|
|
|
|
+ if (codepoint > 0xffff) {
|
|
|
|
|
+ const offset = codepoint - 0x10000
|
|
|
|
|
+ result += String.fromCharCode((offset >> 10) + 0xd800, (offset & 0x3ff) + 0xdc00)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ result += String.fromCharCode(codepoint)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return result
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return decodeUtf8(decodedBinary)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('Base64 decode failed:', e)
|
|
|
|
|
+ return str
|
|
|
|
|
+ }
|
|
|
|
|
+}
|