From 8557402e534d54b2d7a6775597380670f9cbfe41 Mon Sep 17 00:00:00 2001 From: LiaoYijun Date: Mon, 4 Aug 2025 10:04:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=8A=E4=BC=A0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=89=8D=E5=8F=AF=E8=BE=93=E5=85=A5=E6=8F=8F=E8=BF=B0=E6=96=87?= =?UTF-8?q?=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/LogUploader.jsx | 76 ++++++++++++++++++++++++++++++++++ src/utils/pagespy.js | 68 ++++++++++++++++++++++++++++-- src/views/AuthApp.jsx | 28 +------------ 3 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 src/components/LogUploader.jsx diff --git a/src/components/LogUploader.jsx b/src/components/LogUploader.jsx new file mode 100644 index 0000000..cd35f83 --- /dev/null +++ b/src/components/LogUploader.jsx @@ -0,0 +1,76 @@ +import { useState } from "react"; +import { Popover, message, FloatButton, Button, Form, Input } from "antd"; +import { BugOutlined } from "@ant-design/icons"; +import useAuthStore from '@/stores/AuthStore' +import { uploadPageSpyLog, sendNotify } from "@/utils/pagespy"; + +function LogUploader() { + const [open, setOpen] = useState(false); + const hide = () => { + setOpen(false); + }; + const handleOpenChange = (newOpen) => { + setOpen(newOpen); + }; + + const [loginUser] = useAuthStore((s) => [s.loginUser]); + + const [messageApi, contextHolder] = message.useMessage(); + const [formBug] = Form.useForm(); + + const popoverContent = ( +
{ + const success = await uploadPageSpyLog(); + messageApi.success("Thanks for the feedback😊"); + if (success) { + sendNotify(`${loginUser?.username}(${loginUser?.userIdStr})说:${values.problem}`); + } else { + sendNotify(`${loginUser?.username}(${loginUser?.userIdStr})上传日志失败`); + } + hide(); + formBug.setFieldsValue({problem: ''}); + }} + > + + + + +
+ ); + + return ( + <> + {contextHolder} + + } tooltip={
上传日志给研发部
} /> +
+ + ); +} + +export default LogUploader; diff --git a/src/utils/pagespy.js b/src/utils/pagespy.js index 16e6731..cd4c5b4 100644 --- a/src/utils/pagespy.js +++ b/src/utils/pagespy.js @@ -1,9 +1,10 @@ import { loadScript } from '@/utils/commons' +import { fetchJSON } from '@/utils/request' import { readWebsocketLog } from '@/utils/indexedDB' import { BUILD_VERSION, BUILD_DATE } from '@/config' export const loadPageSpy = (title) => { - if (import.meta.env.DEV || window.$pageSpy) return + // if (import.meta.env.DEV || window.$pageSpy) return const PageSpyConfig = { api: 'page-spy.mycht.cn', project: 'Sales CRM', title: title + '(v' + BUILD_VERSION + ')', autoRender: false, offline: true } @@ -46,9 +47,70 @@ export const loadPageSpy = (title) => { } export const uploadPageSpyLog = async () => { - await readWebsocketLog() // window.$pageSpy.triggerPlugins('onOfflineLog', 'upload'); + // if (window.$pageSpy) { + // await window.$harbor.upload() // 上传日志 { clearCache: true, remark: '' } + // } + + // if (import.meta.env.DEV) return true; + if (window.$pageSpy) { - await window.$harbor.upload() // 上传日志 { clearCache: true, remark: '' } + try { + await readWebsocketLog() + // await window.$harbor.upload() // 上传日志 { clearCache: true, remark: '' } + // 上传最近 1 小时的日志, 直接upload 所有日志: 413 Payload Too Large + const now = Date.now(); + await window.$harbor.uploadPeriods({ + startTime: now - 60 * 60000, + endTime: now, + }); + return true; + } catch (error) { + return false; + } + } else { + return false; } } + +export const sendNotify = async (message) => { + + const notifyUrl = 'https://p9axztuwd7x8a7.mycht.cn/dingtalk/dingtalkwork/SendMDMsgByDingRobotToGroup'; + + const params = { + groupid: 'cidFtzcIzNwNoiaGU9Q795CIg==', + msgTitle: '有人求助', + msgText: `${message}\\n\\nSales CRM (${BUILD_VERSION})`, + }; + + return fetchJSON(notifyUrl, params).then((json) => { + if (json.errcode === 0) { + console.info('发送通知成功'); + } else { + throw new Error(json?.errmsg + ': ' + json.errcode); + } + }); +}; + + const uploadLog = async () => { + await readWebsocketLog() + if (window.$pageSpy) { + // window.$pageSpy.triggerPlugins('onOfflineLog', 'upload') + try { + // await window.$harbor.upload() // 上传日志 { clearCache: true, remark: '' } + // 上传最近 1 小时的日志, 直接upload 所有日志: 413 Payload Too Large + const now = Date.now() + await window.$harbor.uploadPeriods({ + startTime: now - 60 * 60000, + endTime: now, + }) + messageApi.info('Success') + // clearWebsocketLog() + sendNotify() + } catch (error) { + messageApi.error('Failure') + } + } else { + messageApi.error('Failure') + } + } \ No newline at end of file diff --git a/src/views/AuthApp.jsx b/src/views/AuthApp.jsx index eedf3cb..f676443 100644 --- a/src/views/AuthApp.jsx +++ b/src/views/AuthApp.jsx @@ -24,12 +24,11 @@ import '@/assets/App.css' import 'react-chat-elements/dist/main.css' import EmailFetch from './Conversations/Online/Components/EmailFetch' import FetchEmailWorker from './../workers/fetchEmailWorker?worker&url' -import { readWebsocketLog } from '@/utils/indexedDB' import { useGlobalNotify } from '@/hooks/useGlobalNotify' import GeneratePaymentDrawer from './Conversations/Online/Components/GeneratePaymentDrawer' import GenerateAutoDocDrawer from './Conversations/Online/Components/GenerateAutoDocDrawer' +import LogUploader from '@/components/LogUploader' -// const fetchEmailWorkerURL = new URL('/src/workers/fetchEmailWorker.js', import.meta.url); const fetchEmailWorker = new Worker(FetchEmailWorker, { type: 'module' }); @@ -90,29 +89,6 @@ function AuthApp() { return fetchEmailWorker; } - const uploadLog = async () => { - await readWebsocketLog() - if (window.$pageSpy) { - // window.$pageSpy.triggerPlugins('onOfflineLog', 'upload') - try { - // await window.$harbor.upload() // 上传日志 { clearCache: true, remark: '' } - // 上传最近 1 小时的日志, 直接upload 所有日志: 413 Payload Too Large - const now = Date.now() - await window.$harbor.uploadPeriods({ - startTime: now - 60 * 60000, - endTime: now, - }) - messageApi.info('Success') - // clearWebsocketLog() - sendNotify() - } catch (error) { - messageApi.error('Failure') - } - } else { - messageApi.error('Failure') - } - } - // 除了路由 /p...以外都需要登陆系统 const needToLogin = loginUser.userId === -1 && href.indexOf('/p/') === -1 @@ -161,7 +137,7 @@ function AuthApp() { icon={} > - } tooltip={
上传日志给研发部
} onClick={() => uploadLog()} /> + {contextHolder}