Compare commits
No commits in common. 'main' and 'dev/2025a' have entirely different histories.
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.8 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M11 4H21V6H11V4ZM6 7V11H4V7H1L5 3L9 7H6ZM6 17H9L5 21L1 17H4V13H6V17ZM11 18H21V20H11V18ZM9 11H21V13H9V11Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 208 B |
@ -1,6 +1,6 @@
|
|||||||
.logo {
|
.logo {
|
||||||
float: left;
|
float: left;
|
||||||
height: 60px;
|
height: 68px;
|
||||||
margin: 0 6px 0 0;
|
margin: 0 6px 0 0;
|
||||||
background: rgba(255, 255, 255, 0.3);
|
background: rgba(255, 255, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
@ -1,77 +0,0 @@
|
|||||||
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 { sendNotify } from "@/utils/pagespy";
|
|
||||||
import { uploadPageSpyLog } from "@haina/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 = (
|
|
||||||
<Form
|
|
||||||
layout={"vertical"}
|
|
||||||
form={formBug}
|
|
||||||
initialValues={{ problem: '' }}
|
|
||||||
scrollToFirstError
|
|
||||||
onFinish={async (values) => {
|
|
||||||
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: ''});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Item
|
|
||||||
name="problem"
|
|
||||||
label="Need help?"
|
|
||||||
rules={[{ required: true, message: "Specify issue needing support." }]}
|
|
||||||
>
|
|
||||||
<Input.TextArea rows={3} />
|
|
||||||
</Form.Item>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
htmlType="submit"
|
|
||||||
color="cyan"
|
|
||||||
variant="solid"
|
|
||||||
block
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{contextHolder}
|
|
||||||
<Popover
|
|
||||||
content={popoverContent}
|
|
||||||
trigger={["click"]}
|
|
||||||
placement="topRight"
|
|
||||||
open={open}
|
|
||||||
onOpenChange={handleOpenChange}
|
|
||||||
fresh
|
|
||||||
destroyOnHidden
|
|
||||||
>
|
|
||||||
<FloatButton icon={<BugOutlined />} tooltip={<div>上传日志给研发部</div>} />
|
|
||||||
</Popover>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LogUploader;
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import { create } from 'zustand'
|
|
||||||
import { devtools } from 'zustand/middleware'
|
|
||||||
const useUrlStore = create(devtools((set, get) => ({
|
|
||||||
|
|
||||||
drawerOpen: false,
|
|
||||||
|
|
||||||
openDrawer: () => {
|
|
||||||
set(() => ({
|
|
||||||
drawerOpen: true
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
|
|
||||||
closeDrawer: () => {
|
|
||||||
set(() => ({
|
|
||||||
drawerOpen: false
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
|
|
||||||
}), { name: 'urlStore' }))
|
|
||||||
|
|
||||||
export default useUrlStore
|
|
||||||
@ -1,125 +1,54 @@
|
|||||||
import { loadScript } from '@haina/utils-commons'
|
import { loadScript } from '@/utils/commons'
|
||||||
import { fetchJSON } from '@haina/utils-request'
|
|
||||||
import { readWebsocketLog } from '@/utils/indexedDB'
|
import { readWebsocketLog } from '@/utils/indexedDB'
|
||||||
import { BUILD_VERSION, BUILD_DATE } from '@/config'
|
import { BUILD_VERSION, BUILD_DATE } from '@/config'
|
||||||
|
|
||||||
/**
|
export const loadPageSpy = (title) => {
|
||||||
* @deprecated
|
if (import.meta.env.DEV || window.$pageSpy) return
|
||||||
*/
|
|
||||||
// export const loadPageSpy = (title) => {
|
const PageSpyConfig = { api: 'page-spy.mycht.cn', project: 'Sales CRM', title: title + '(v' + BUILD_VERSION + ')', autoRender: false, offline: true }
|
||||||
// if (import.meta.env.DEV || window.$pageSpy) return
|
|
||||||
|
const PageSpySrc = [
|
||||||
// const PageSpyConfig = { api: 'page-spy.mycht.cn', project: 'Sales CRM', title: title + '(v' + BUILD_VERSION + ')', autoRender: false, offline: true }
|
'https://page-spy.mycht.cn/page-spy/index.min.js' + `?${BUILD_DATE}`,
|
||||||
|
'https://page-spy.mycht.cn/plugin/data-harbor/index.min.js' + `?${BUILD_DATE}`,
|
||||||
// const PageSpySrc = [
|
'https://page-spy.mycht.cn/plugin/rrweb/index.min.js' + `?${BUILD_DATE}`,
|
||||||
// 'https://page-spy.mycht.cn/page-spy/index.min.js' + `?${BUILD_DATE}`,
|
]
|
||||||
// 'https://page-spy.mycht.cn/plugin/data-harbor/index.min.js' + `?${BUILD_DATE}`,
|
Promise.all(PageSpySrc.map((src) => loadScript(src))).then(() => {
|
||||||
// 'https://page-spy.mycht.cn/plugin/rrweb/index.min.js' + `?${BUILD_DATE}`,
|
// 注册插件
|
||||||
// ]
|
window.$harbor = new DataHarborPlugin()
|
||||||
// Promise.all(PageSpySrc.map((src) => loadScript(src))).then(() => {
|
window.$rrweb = new RRWebPlugin()
|
||||||
// // 注册插件
|
;[window.$harbor, window.$rrweb].forEach((p) => {
|
||||||
// window.$harbor = new DataHarborPlugin()
|
PageSpy.registerPlugin(p)
|
||||||
// window.$rrweb = new RRWebPlugin()
|
})
|
||||||
// ;[window.$harbor, window.$rrweb].forEach((p) => {
|
window.$pageSpy = new PageSpy(PageSpyConfig)
|
||||||
// PageSpy.registerPlugin(p)
|
|
||||||
// })
|
// PageSpy.registerPlugin(new DataHarborPlugin());
|
||||||
// window.$pageSpy = new PageSpy(PageSpyConfig)
|
// PageSpy.registerPlugin(new RRWebPlugin());
|
||||||
|
// 实例化 PageSpy
|
||||||
// // PageSpy.registerPlugin(new DataHarborPlugin());
|
// window.$pageSpy = new PageSpy({ api: 'page-spy.mycht.cn', project: 'Sales CRM', title: title + '(v' + BUILD_VERSION + ')', autoRender: false, offline: true, });
|
||||||
// // PageSpy.registerPlugin(new RRWebPlugin());
|
console.log('[PageSpy]', window.$pageSpy.version)
|
||||||
// // 实例化 PageSpy
|
// window.addEventListener('beforeunload', (e) => {
|
||||||
// // window.$pageSpy = new PageSpy({ api: 'page-spy.mycht.cn', project: 'Sales CRM', title: title + '(v' + BUILD_VERSION + ')', autoRender: false, offline: true, });
|
// e.preventDefault() // If you prevent default behavior in Mozilla Firefox
|
||||||
// console.log('[PageSpy]', window.$pageSpy.version)
|
// e.returnValue = '' // Chrome requires returnValue to be set
|
||||||
// // window.addEventListener('beforeunload', (e) => {
|
|
||||||
// // e.preventDefault() // If you prevent default behavior in Mozilla Firefox
|
// window.$harbor.upload({ clearCache: false, remark: '自动上传' }) // 上传日志 { clearCache: true, remark: '' }
|
||||||
// // e.returnValue = '' // Chrome requires returnValue to be set
|
// })
|
||||||
|
window.onerror = async function (msg, url, lineNo, columnNo, error) {
|
||||||
// // window.$harbor.upload({ clearCache: false, remark: '自动上传' }) // 上传日志 { clearCache: true, remark: '' }
|
await readWebsocketLog()
|
||||||
// // })
|
// 上传最近 3 分钟的日志
|
||||||
// window.onerror = async function (msg, url, lineNo, columnNo, error) {
|
const now = Date.now()
|
||||||
// await readWebsocketLog()
|
await window.$harbor.uploadPeriods({
|
||||||
// // 上传最近 3 分钟的日志
|
startTime: now - 3 * 60000,
|
||||||
// const now = Date.now()
|
endTime: now,
|
||||||
// await window.$harbor.uploadPeriods({
|
remark: `\`onerror\`自动上传. ${msg}`,
|
||||||
// startTime: now - 3 * 60000,
|
})
|
||||||
// endTime: now,
|
|
||||||
// remark: `\`onerror\`自动上传. ${msg}`,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
// export const uploadPageSpyLog = async () => {
|
|
||||||
// // 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) {
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
export const uploadPageSpyLog = async () => {
|
||||||
* @deprecated
|
await readWebsocketLog()
|
||||||
*/
|
// window.$pageSpy.triggerPlugins('onOfflineLog', 'upload');
|
||||||
// const uploadLog = async () => {
|
if (window.$pageSpy) {
|
||||||
// await readWebsocketLog()
|
await window.$harbor.upload() // 上传日志 { clearCache: true, remark: '' }
|
||||||
// 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')
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
import { createContext, useEffect, useState } from 'react'
|
|
||||||
import { Drawer } from 'antd'
|
|
||||||
import useUrlStore from '@/stores/UrlStore'
|
|
||||||
import ShorturlConversion from '@/views/accounts/ShorturlConversion'
|
|
||||||
|
|
||||||
const GenerateShorturlDrawer = ({ ...props }) => {
|
|
||||||
const [openShorturlDrawer, closeShorturlDrawer, shorturlDrawerOpen] = useUrlStore((state) => [state.openDrawer, state.closeDrawer, state.drawerOpen])
|
|
||||||
return (
|
|
||||||
<Drawer title='短链接转换' placement={'top'} onClose={() => closeShorturlDrawer()} open={shorturlDrawerOpen}>
|
|
||||||
<ShorturlConversion/>
|
|
||||||
</Drawer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default GenerateShorturlDrawer
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import { createContext, useEffect, useState } from 'react'
|
|
||||||
import { Tooltip, Button } from 'antd'
|
|
||||||
import useUrlStore from '@/stores/UrlStore'
|
|
||||||
|
|
||||||
const ShortlinkBtn = ({ type, ...props }) => {
|
|
||||||
const [openShorturlDrawer] = useUrlStore((state) => [state.openDrawer])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Tooltip title='短链接'>
|
|
||||||
{type === 'link' ? (
|
|
||||||
<Button type={'link'} onClick={() => openShorturlDrawer()}>
|
|
||||||
短链接
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button type='text' onClick={() => openShorturlDrawer()} size={'middle'} className='px-1'>
|
|
||||||
🔗
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default ShortlinkBtn
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import { SearchOutlined } from '@ant-design/icons'
|
|
||||||
import { Button, Modal, Form, Input, Radio } from 'antd'
|
|
||||||
import { searchEmailListAction } from '@/actions/EmailActions'
|
|
||||||
import useConversationStore from '@/stores/ConversationStore'
|
|
||||||
|
|
||||||
const MailListSearchModal = ({ ...props }) => {
|
|
||||||
const [currentMailboxOPI] = useConversationStore((state) => [state.currentMailboxOPI])
|
|
||||||
|
|
||||||
const [openForm, setOpenForm] = useState(false)
|
|
||||||
const [formSearch] = Form.useForm()
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
const onSubmitSearchMailList = async (values) => {
|
|
||||||
setLoading(true)
|
|
||||||
await searchEmailListAction({...values, opi_sn: currentMailboxOPI});
|
|
||||||
setLoading(false)
|
|
||||||
setOpenForm(false)
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button key={'bound'} onClick={() => setOpenForm(true)} size='small' icon={<SearchOutlined className='' />}>
|
|
||||||
查找邮件
|
|
||||||
</Button>
|
|
||||||
<Modal
|
|
||||||
width={window.innerWidth < 700 ? '95%' : 960}
|
|
||||||
open={openForm}
|
|
||||||
cancelText='关闭'
|
|
||||||
okText='查找'
|
|
||||||
confirmLoading={loading}
|
|
||||||
okButtonProps={{ autoFocus: true, htmlType: 'submit', type: 'default' }}
|
|
||||||
onCancel={() => setOpenForm(false)}
|
|
||||||
footer={null}
|
|
||||||
destroyOnHidden
|
|
||||||
modalRender={(dom) => (
|
|
||||||
<Form
|
|
||||||
layout='vertical'
|
|
||||||
form={formSearch}
|
|
||||||
name='searchmaillist_form_in_modal'
|
|
||||||
initialValues={{ mailboxtype: '' }}
|
|
||||||
clearOnDestroy
|
|
||||||
onFinish={(values) => onSubmitSearchMailList(values)}
|
|
||||||
className='[&_.ant-form-item]:m-2'>
|
|
||||||
{dom}
|
|
||||||
</Form>
|
|
||||||
)}>
|
|
||||||
<Form.Item name='mailboxtype' label='邮箱文件夹'>
|
|
||||||
<Radio.Group
|
|
||||||
options={[
|
|
||||||
{ key: 'All', value: '', label: 'All' },
|
|
||||||
{ key: '1', value: '1', label: '收件箱' },
|
|
||||||
{ key: '2', value: '2', label: '未读邮件' },
|
|
||||||
{ key: '3', value: '3', label: '已发邮件' },
|
|
||||||
{ key: '7', value: '7', label: '已处理邮件' },
|
|
||||||
]}
|
|
||||||
optionType='button'
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name='sender' label='发件人'>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name='receiver' label='收件人'>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item name='subject' label='主题'>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Button type='primary' htmlType='submit' loading={loading}>
|
|
||||||
查找
|
|
||||||
</Button>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default MailListSearchModal
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue