diff --git a/.gitignore b/.gitignore index 9768ad7..aee9584 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,6 @@ coverage tsconfig.app.tsbuildinfo tsconfig.node.tsbuildinfo -/public/data/ \ No newline at end of file +/public/data/ +package-lock.json +.cursor/rules/fe.mdc diff --git a/README.md b/README.md index c046b31..b741c66 100644 --- a/README.md +++ b/README.md @@ -1 +1,15 @@ -## 这是[PyWxDump](https://github.com/xaoyaoo/PyWxDump)的Web版,用于在浏览器中查看微信聊天记录。 \ No newline at end of file +# PyWxDump-UI + +这是[PyWxDump](https://github.com/xaoyaoo/PyWxDump)的Web版,用于在浏览器中查看微信聊天记录。 + +开发者朋友可以基于此项目二次开发自己的UI界面 + +## 启动UI + +``` +npm i + +npm run dev +``` + +启动后在http://localhost:8080访问 diff --git a/package-lock.json b/package-lock.json index 6f7db26..5d45d32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "wxdump_web", "version": "2.4.10", "dependencies": { + "@element-plus/icons-vue": "^2.3.1", "@types/axios": "^0.14.0", "axios": "^1.6.3", "cors": "^2.8.5", @@ -486,8 +487,9 @@ }, "node_modules/@element-plus/icons-vue": { "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==", + "license": "MIT", "peerDependencies": { "vue": "^3.2.0" } diff --git a/package.json b/package.json index 7814352..b115abe 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "type-check": "vue-tsc --build --force" }, "dependencies": { + "@element-plus/icons-vue": "^2.3.1", "@types/axios": "^0.14.0", "axios": "^1.6.3", "cors": "^2.8.5", diff --git a/src/App.vue b/src/App.vue index 87d38e7..b030c9c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -14,13 +14,13 @@ import FavoriteIcon from "@/assets/icon/FavoriteIcon.vue"; import CollapseOpenIcon from "@/assets/icon/CollapseOpenIcon.vue"; import CollapseCloseIcon from "@/assets/icon/CollapseCloseIcon.vue"; -import {RouterLink, RouterView} from 'vue-router' -import {ref, onMounted, withCtx, watch} from 'vue' +import { RouterLink, RouterView } from 'vue-router' +import { ref, onMounted, withCtx, watch } from 'vue' import router from "@/router"; -import {is_db_init, is_use_local_data} from "@/utils/common_utils"; +import { is_db_init, is_use_local_data } from "@/utils/common_utils"; import ChatRecordsMain from "@/components/chat/ChatRecordsMain.vue"; -const isCollapse = ref(true); +const isCollapse = ref(false); const is_local_data = ref(true); @@ -28,7 +28,7 @@ onMounted(() => { // localStorage.setItem('isDbInit', "t"); is_local_data.value = localStorage.getItem('isUseLocalData') === 't'; console.log("is_local_data", is_local_data.value); - if(!is_local_data.value) { + if (!is_local_data.value) { is_db_init(); } }) @@ -46,24 +46,24 @@ const handleClose = (key: string, keyPath: string[]) => { diff --git a/src/components/chat/ChatRecords.vue b/src/components/chat/ChatRecords.vue index 8b1d671..01f95ff 100644 --- a/src/components/chat/ChatRecords.vue +++ b/src/components/chat/ChatRecords.vue @@ -38,7 +38,7 @@ onMounted(() => { diff --git a/src/components/chat/ChatRecprdsHeader.vue b/src/components/chat/ChatRecprdsHeader.vue index 7a28d9e..7d073d3 100644 --- a/src/components/chat/ChatRecprdsHeader.vue +++ b/src/components/chat/ChatRecprdsHeader.vue @@ -136,66 +136,145 @@ const export_button = (val: boolean) => { \ No newline at end of file diff --git a/src/components/chat/ContactsList.vue b/src/components/chat/ContactsList.vue index a34b0f1..a749acc 100644 --- a/src/components/chat/ContactsList.vue +++ b/src/components/chat/ContactsList.vue @@ -1,10 +1,10 @@ \ No newline at end of file diff --git a/src/components/stats/DateChatHeatmapStats.vue b/src/components/stats/DateChatHeatmapStats.vue index f272946..0cef5a3 100644 --- a/src/components/stats/DateChatHeatmapStats.vue +++ b/src/components/stats/DateChatHeatmapStats.vue @@ -8,6 +8,7 @@ import DateTimeSelect from "@/components/utils/DateTimeSelect.vue"; import ColorSelect from "@/components/utils/ColorSelect.vue"; import NumberInput from "@/components/utils/NumberInput.vue"; import ChartInit from "@/components/stats/components/ChartInit.vue"; +import { ElMessage } from 'element-plus'; // https://echarts.apache.org/examples/en/editor.html @@ -173,55 +174,201 @@ const set_top_user = async (wxid: string) => { \ No newline at end of file diff --git a/src/components/stats/DateChatStats.vue b/src/components/stats/DateChatStats.vue index 8b13aa0..f292049 100644 --- a/src/components/stats/DateChatStats.vue +++ b/src/components/stats/DateChatStats.vue @@ -7,6 +7,7 @@ import {gen_show_name, type User} from "@/utils/common_utils"; import DateTimeSelect from "@/components/utils/DateTimeSelect.vue"; import ColorSelect from "@/components/utils/ColorSelect.vue"; import ChartInit from "@/components/stats/components/ChartInit.vue"; +import { ElMessage } from 'element-plus'; // https://echarts.apache.org/examples/en/editor.html @@ -270,57 +271,183 @@ const set_top_user = async (wxid: string) => { \ No newline at end of file diff --git a/src/components/utils/DbInitComponent.vue b/src/components/utils/DbInitComponent.vue index 63c9e4d..30d96ce 100644 --- a/src/components/utils/DbInitComponent.vue +++ b/src/components/utils/DbInitComponent.vue @@ -5,6 +5,7 @@ import {defineEmits, onMounted, ref, watch} from "vue"; import {ElTable, ElTableColumn, ElMessage, ElMessageBox} from "element-plus"; import type {Action} from 'element-plus' import router from "@/router"; +import { Clock, MagicStick, Setting } from '@element-plus/icons-vue' interface wxinfo { pid: string; @@ -18,10 +19,15 @@ interface wxinfo { key: string; } +interface LocalWxid { + wxid: string; +} + const percentage = ref(0); const startORstop = ref(-1); // 用于进度条的开始和停止 0表示0% 1表示100% -const init_type = ref(""); +type InitType = 'last' | 'auto' | 'custom'| ''; +const init_type = ref(''); const is_init = ref(false); const wxinfoData = ref([]); @@ -36,19 +42,34 @@ const wx_path = ref(""); const key = ref(""); const my_wxid = ref(""); -const local_wxids = ref([]); +const local_wxids = ref([]); const db_init = (init: boolean) => { if (init) { localStorage.setItem('isDbInit', "t"); - router.push('/'); + // router.push('/'); ElMessage({ type: 'success', message: '初始化成功!', + duration: 3000, }) + init_type.value = ''; } } +const showError = (error: unknown) => { + const errorMessage = error instanceof Error ? error.message : String(error); + ElMessageBox.alert(errorMessage, '错误', { + confirmButtonText: '确认', + callback: (action: Action) => { + ElMessage({ + type: 'error', + message: `操作: ${action}`, + }) + }, + }); +} + // ** 是否使用key的初始化** START const init_key = async () => { if (decryping.value) { @@ -75,15 +96,7 @@ const init_key = async () => { percentage.value = 0; // 进度条 0% isErrorShow.value = true; decryping.value = false; - ElMessageBox.alert(error, 'error', { - confirmButtonText: '确认', - callback: (action: Action) => { - ElMessage({ - type: 'error', - message: `action: ${action}`, - }) - }, - }) + showError(error); return []; } decryping.value = false; @@ -103,18 +116,11 @@ const init_nokey = async () => { } decryping.value = false; db_init(body_data.is_init); - // emits('isAutoShow', body_data.is_init); } catch (error) { percentage.value = 0; // 进度条 0% isErrorShow.value = true; decryping.value = false; - ElMessageBox.alert(error, 'error', { - confirmButtonText: '确认', - callback: (action: Action) => { - init_type.value = "";// 刷新 - }, - }) - // console.error('Error fetching data:', error); + showError(error); return []; } decryping.value = false; @@ -123,28 +129,25 @@ const init_nokey = async () => { // ** 使用上次数据部分** START const selectLastWx = async (row: wxinfo) => { - // console.log(row) my_wxid.value = row.wxid; } const get_init_last_local_wxid = async () => { try { - const body_data = await http.post('/api/ls/init_last_local_wxid'); //[ 'wx1234567890', 'wx0987654321' ] + const body_data = await http.post('/api/ls/init_last_local_wxid'); local_wxids.value = body_data.local_wxids.map((item: string) => { return {wxid: item} }); if (local_wxids.value.length === 1) { my_wxid.value = local_wxids.value[0].wxid; - // console.log("init_last") await init_last(); } } catch (error) { - console.error('Error fetching data:', error); + showError(error); return []; } } - const init_last = async () => { try { let reqdata = { @@ -158,33 +161,23 @@ const init_last = async () => { percentage.value = 100; // 进度条 100% decryping.value = false; db_init(body_data.is_init); - // emits('isAutoShow', body_data.is_init); } else { isErrorShow.value = true; decryping.value = false; - ElMessageBox.alert("未发现上次的设置数据!", 'error', { + ElMessageBox.alert("未发现上次的设置数据!", '错误', { confirmButtonText: '确认', callback: (action: Action) => { init_type.value = "";// 刷新 }, }) } - decryping.value = false; } catch (error) { - // percentage.value = 0; // 进度条 0% isErrorShow.value = true; decryping.value = false; - ElMessageBox.alert(error, 'error', { - confirmButtonText: '确认', - callback: (action: Action) => { - init_type.value = ""; - }, - }) - // console.error('Error fetching data:', error); + showError(error); return []; } - decryping.value = false; } @@ -200,7 +193,7 @@ const get_wxinfo = async () => { setTimeout(okWx, 5000); } } catch (error) { - console.error('Error fetching data:', error); + showError(error); return []; } } @@ -226,7 +219,6 @@ const okWx = () => { // **自动解密微信部分** END 查看有多少个微信正在登录 , 并调用init_key解密初始化 - // 监测isAutoShow是否为aoto,如果是则执行get_wxinfo watch(init_type, (val) => { if (val === 'auto') { @@ -235,149 +227,231 @@ watch(init_type, (val) => { // init(); } else if (val === 'last') { get_init_last_local_wxid(); - // init_last(); } }) \ No newline at end of file diff --git a/src/views/CleanupView.vue b/src/views/CleanupView.vue index c483c25..1cc3c35 100644 --- a/src/views/CleanupView.vue +++ b/src/views/CleanupView.vue @@ -3,25 +3,146 @@ import {ref} from "vue"; import HomeView from "@/views/HomeView.vue"; import ContactsList from "@/components/chat/ContactsList.vue"; import ChatExportMain from "@/components/chatBackup/ChatExportMain.vue"; - +import { ElMessage } from 'element-plus'; \ No newline at end of file diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index c82d591..354549b 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -2,29 +2,138 @@ import http from '@/utils/axios.js'; import {onMounted, ref} from "vue"; import {apiVersion} from "@/api/base"; +import { ElMessage } from 'element-plus'; const version = ref(''); // 用于显示返回值 -const getVersion = () => { - apiVersion().then((data: string) => { +const getVersion = async () => { + try { + const data = await apiVersion(); version.value = data; - }).catch((error: string) => { + } catch (error) { console.error('Error fetching API version:', error); - }); + ElMessage.error('获取版本信息失败'); + } } onMounted(getVersion); - \ No newline at end of file diff --git a/src/views/IndexView.vue b/src/views/IndexView.vue index c82d591..6b23163 100644 --- a/src/views/IndexView.vue +++ b/src/views/IndexView.vue @@ -18,13 +18,83 @@ onMounted(getVersion); \ No newline at end of file diff --git a/src/views/other/AboutView.vue b/src/views/other/AboutView.vue index fd0283f..171135e 100644 --- a/src/views/other/AboutView.vue +++ b/src/views/other/AboutView.vue @@ -1,67 +1,173 @@ + \ No newline at end of file diff --git a/src/views/other/HelpView.vue b/src/views/other/HelpView.vue index 6c3c648..a2963bd 100644 --- a/src/views/other/HelpView.vue +++ b/src/views/other/HelpView.vue @@ -1,33 +1,134 @@ - \ No newline at end of file diff --git a/src/views/other/SettingView.vue b/src/views/other/SettingView.vue index 70f66e9..38b81ea 100644 --- a/src/views/other/SettingView.vue +++ b/src/views/other/SettingView.vue @@ -1,53 +1,262 @@ \ No newline at end of file diff --git a/src/views/tools/BiasView.vue b/src/views/tools/BiasView.vue index 2cbbe4c..9314f1f 100644 --- a/src/views/tools/BiasView.vue +++ b/src/views/tools/BiasView.vue @@ -1,22 +1,24 @@ \ No newline at end of file diff --git a/src/views/tools/DecryptView.vue b/src/views/tools/DecryptView.vue index 607357f..58a7ca3 100644 --- a/src/views/tools/DecryptView.vue +++ b/src/views/tools/DecryptView.vue @@ -1,14 +1,17 @@ \ No newline at end of file diff --git a/src/views/tools/MergeView.vue b/src/views/tools/MergeView.vue index 44e87c7..3f7dddf 100644 --- a/src/views/tools/MergeView.vue +++ b/src/views/tools/MergeView.vue @@ -1,13 +1,16 @@ \ No newline at end of file diff --git a/src/views/tools/WxinfoView.vue b/src/views/tools/WxinfoView.vue index 2e93589..15f2e89 100644 --- a/src/views/tools/WxinfoView.vue +++ b/src/views/tools/WxinfoView.vue @@ -1,6 +1,6 @@ \ No newline at end of file