diff --git a/frontend/composables/useApi.js b/frontend/composables/useApi.js
index cbf1c5f..3858c35 100644
--- a/frontend/composables/useApi.js
+++ b/frontend/composables/useApi.js
@@ -344,6 +344,20 @@ export const useApi = () => {
const url = `/wrapped/annual/cards/${safeId}` + (query.toString() ? `?${query.toString()}` : '')
return await request(url)
}
+
+ // 获取数据库解密密钥
+ const getDbKey = () => {
+ return useFetch('/api/get_db_key', {
+ method: 'GET',
+ })
+ }
+
+ // 获取图片解密密钥
+ const getImageKey = () => {
+ return useFetch('/api/get_image_key', {
+ method: 'GET',
+ })
+ }
return {
detectWechat,
@@ -375,6 +389,8 @@ export const useApi = () => {
cancelChatExport,
getWrappedAnnual,
getWrappedAnnualMeta,
- getWrappedAnnualCard
+ getWrappedAnnualCard,
+ getDbKey,
+ getImageKey,
}
}
diff --git a/frontend/package.json b/frontend/package.json
index aff4c28..b527734 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -19,5 +19,8 @@
"ogl": "^1.0.11",
"vue": "^3.5.17",
"vue-router": "^4.5.1"
+ },
+ "devDependencies": {
+ "tailwindcss": "3.4.17"
}
}
diff --git a/frontend/pages/decrypt.vue b/frontend/pages/decrypt.vue
index fb76aec..2942d26 100644
--- a/frontend/pages/decrypt.vue
+++ b/frontend/pages/decrypt.vue
@@ -26,24 +26,40 @@
-
-
-
@@ -131,6 +147,26 @@
+
+
+
手动输入或通过微信获取
+
+
+
@@ -158,7 +194,7 @@
- 使用
wx_key 获取图片密钥;AES 可选(V4-V2 需要)
+ 尝试自动获取,或使用
wx_key 获取图片密钥;AES 可选(V4-V2 需要)
@@ -367,12 +403,14 @@
import { ref, reactive, computed, onMounted } from 'vue'
import { useApi } from '~/composables/useApi'
-const { decryptDatabase, saveMediaKeys, getSavedKeys } = useApi()
+const { decryptDatabase, saveMediaKeys, getSavedKeys, getDbKey, getImageKey } = useApi()
const loading = ref(false)
const error = ref('')
const currentStep = ref(0)
const mediaAccount = ref('')
+const isGettingDbKey = ref(false)
+const isGettingImageKey = ref(false)
// 步骤定义
const steps = [
@@ -453,6 +491,84 @@ const prefillKeysForAccount = async (account) => {
}
}
+const handleGetDbKey = async () => {
+ if (isGettingDbKey.value) return
+ isGettingDbKey.value = true
+
+ error.value = ''
+
+ formErrors.key = ''
+
+ try {
+ const { data, error: fetchError } = await getDbKey()
+
+ if (fetchError.value) {
+ error.value = '请求失败: ' + fetchError.value.message
+ return
+ }
+
+ const res = data.value
+
+ if (res && (res.status === 0)) {
+ if (res.data?.db_key) {
+ formData.key = res.data.db_key
+ }
+
+ // 有错误信息且不是ok时弹出提示
+ if (res.errmsg && res.errmsg !== 'ok') {
+ error.value = res.errmsg
+ }
+ } else {
+ error.value = '获取失败: ' + (res?.errmsg || '未知错误')
+ }
+ } catch (e) {
+ console.error(e)
+ error.value = '系统错误: ' + e.message
+ } finally {
+ isGettingDbKey.value = false
+ }
+}
+
+const handleGetImageKey = async () => {
+ if (isGettingImageKey.value) return
+ isGettingImageKey.value = true
+ manualKeyErrors.xor_key = ''
+ manualKeyErrors.aes_key = ''
+
+ error.value = ''
+
+ try {
+ const { data, fetchError } = await getImageKey()
+
+ if (fetchError && fetchError.value) {
+ error.value = '请求失败: ' + fetchError.value.message
+ return
+ }
+
+ const res = data.value
+ if (res && res.status === 0) {
+ if (res.data?.aes_key) {
+ manualKeys.aes_key = res.data.aes_key
+ }
+ if (res.data?.xor_key) {
+ // 后端记得处理为16进制再返回!!!
+ manualKeys.xor_key = res.data.xor_key
+ }
+
+ if (res.errmsg && res.errmsg !== 'ok') {
+ error.value = res.errmsg
+ }
+ } else {
+ error.value = '获取失败: ' + (res?.errmsg || '未知错误')
+ }
+ } catch (e) {
+ console.error(e)
+ error.value = '系统错误: ' + e.message
+ } finally {
+ isGettingImageKey.value = false
+ }
+}
+
const applyManualKeys = () => {
manualKeyErrors.xor_key = ''
manualKeyErrors.aes_key = ''