diff --git a/app/web/app.tsx b/app/web/app.tsx
index 11fc9d1..a22e0a1 100644
--- a/app/web/app.tsx
+++ b/app/web/app.tsx
@@ -14,21 +14,12 @@ import 'ant-design-dtinsight-theme/theme/dt-theme/index.less';
declare var window: any;
const App = () => {
- const { changeLocalIp } = bindActionCreators(actions, useDispatch());
- const hotJar = () => {
- (function (h: any, o: any, t: any, j: any, a?: any, r?: any) {
- h.hj = h.hj || function () { (h.hj.q = h.hj.q || []).push(arguments) };
- h._hjSettings = { hjid: 2133522, hjsv: 6 };
- a = o.getElementsByTagName('head')[0];
- r = o.createElement('script'); r.async = 1;
- r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
- a.appendChild(r);
- })(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=');
- }
+ const { fetchLocalIp } = bindActionCreators(actions, useDispatch());
+
useEffect(() => {
- hotJar();
- changeLocalIp();
+ fetchLocalIp();
}, [])
+
return (
diff --git a/app/web/layouts/header/header.tsx b/app/web/layouts/header/header.tsx
index 8f2b8a3..6242aff 100644
--- a/app/web/layouts/header/header.tsx
+++ b/app/web/layouts/header/header.tsx
@@ -1,19 +1,28 @@
import React, { useState, useEffect } from 'react';
-import { AppstoreOutlined, CloudOutlined, DesktopOutlined, TagOutlined, SettingOutlined, QuestionCircleOutlined } from '@ant-design/icons';
-import { Layout, Menu } from 'antd';
+import { AppstoreOutlined, CloudOutlined, DesktopOutlined, TagOutlined, SettingOutlined, QuestionCircleOutlined, EditOutlined } from '@ant-design/icons';
+import { Form, Layout, Menu, Modal, FormInstance, Input, Tooltip, Popconfirm } from 'antd';
import { SyncOutlined } from '@ant-design/icons';
import { Link } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actions from '@/store/actions';
+import { API } from '@/api';
import logo from '@/asset/images/logo.png';
import config from '../../../../env.json';
import './style.scss';
const { SubMenu } = Menu;
-
const { Header } = Layout;
+const formItemLayout: any = {
+ labelCol: {
+ span: 5
+ },
+ wrapperCol: {
+ span: 18
+ }
+};
+
const navMenuList: any = [{
name: '应用中心',
path: '/page/toolbox',
@@ -40,19 +49,58 @@ const navMenuList: any = [{
icon: ,
routers: ['tags']
}]
+
const HeaderComponent = (props: any) => {
- const { location } = props;
+ const { location, proxyServer } = props;
const { localIp = '127.0.0.1' } = useSelector((state: any) => state.global);
const { pathname } = location;
const [selectedKeys, setSelectedKeys] = useState([pathname]);
- const { changeLocalIp } = bindActionCreators(actions, useDispatch());
- const handleSelectedKeys = (e: any) => {
- setSelectedKeys(e.key);
- }
+ const [visible, setVisible] = useState(false);
+ const [popconfirmOpen, setPopconfirmOpen] = useState(false);
+ const { setLocalIp } = bindActionCreators(actions, useDispatch());
+ let formRef: FormInstance = null;
+
useEffect(() => {
let current = navMenuList.filter(item => item.routers.some((ele) => pathname.indexOf(ele) > -1))
current.length && setSelectedKeys([current[0].path])
}, [pathname])
+ // 检测是否通过 VPN 访问哆啦A梦
+ useEffect(() => {
+ checkIsVPN();
+ }, [localIp]);
+
+ const handleSelectedKeys = (e: any) => {
+ setSelectedKeys(e.key);
+ }
+
+ // 刷新获取真实IP
+ const handleGetRealIp = () => {
+ API.getLocalIp().then((response: any) => {
+ const { success, data } = response;
+ if (success) {
+ formRef.setFieldsValue({ localIp: data.localIp });
+ // 记录真实IP
+ localStorage.setItem('real-localIp', data.localIp);
+ }
+ })
+ }
+
+ const handleModalOk = () => {
+ formRef.validateFields().then((values: any) => {
+ setLocalIp(values.localIp);
+ setVisible(false);
+ });
+ }
+
+ // 检测当前本地IP是否为 VPN 服务器的IP,是则代表通过 VPN 使用哆啦A梦代理,提示右上角可以进行设置自定义本地IP
+ const checkIsVPN = () => {
+ const vpnIp = config.vpnIp || [];
+ const tipTime = Number(localStorage.getItem('vpnIp-tip-time') || '');
+ console.log(111, Date.now() - tipTime - 24 * 60 * 60)
+ if ((Date.now() - tipTime - 24 * 60 * 60) > 0) {
+ setPopconfirmOpen(vpnIp.includes(localIp))
+ }
+ }
return (
@@ -85,10 +133,60 @@ const HeaderComponent = (props: any) => {
{`本机IP: ${localIp}`}
- {/* 主动更新本地IP */}
- changeLocalIp(true)} />
+ {/* 自定义本地IP */}
+ {
+ setVisible(true);
+ setPopconfirmOpen(false);
+ // 关闭提示后记录时间
+ localStorage.setItem('vpnIp-tip-time', `${Date.now()}`);
+ }}
+ onCancel={() => {
+ setPopconfirmOpen(false);
+ // 关闭提示后记录时间
+ localStorage.setItem('vpnIp-tip-time', `${Date.now()}`);
+ }}
+ >
+ {
+ !popconfirmOpen && setVisible(true);
+ }} />
+
+
+ { setVisible(false) }}
+ >
+
+
+
+
+ } />
+
+
+
);
}
diff --git a/app/web/pages/proxyServer/index.tsx b/app/web/pages/proxyServer/index.tsx
index 90e3d28..ae6d462 100644
--- a/app/web/pages/proxyServer/index.tsx
+++ b/app/web/pages/proxyServer/index.tsx
@@ -4,7 +4,6 @@ import { Input, Button, Typography, Tag, Table, message as Message, Divider, Mod
import { API } from '@/api';
import ProxyServerModal from './components/proxyServerModal';
import ProxyRuleModal from './components/proxyRuleModal';
-import Cookies from 'js-cookie';
import { connect } from 'react-redux'
import helpIcon from '@/asset/images/help-icon.png';
import config from '../../../../env.json';
@@ -17,8 +16,6 @@ const { Paragraph } = Typography;
class ProxyServer extends React.PureComponent {
state: any = {
- //代理服务
- localIp: '',
currentProxyServer: {},
proxyServerModalVisible: false,
proxyServerModalConfirmLoading: false,
@@ -61,8 +58,8 @@ class ProxyServer extends React.PureComponent {
loadMainData = () => {
this.getProxyServerList()
this.getCollectTagList()
- this.getLocalIp()
}
+
getCollectTagList = () => {
let collectTagList = []
try {
@@ -73,29 +70,6 @@ class ProxyServer extends React.PureComponent {
}
this.setState({ collectTagList })
}
- getLocalIp = () => {
- API.getLocalIp().then((response: any) => {
- const { success, data, message } = response;
- if (success) {
- const localIp = data.localIp;
- const rememberIp = Cookies.get('rememberIp') || ''
- if (rememberIp && rememberIp !== localIp) {
- notification.warning({
- message: 'IP地址变更',
- description: '您的IP地址【较上次登录时】已发生变更、请留意代理服务配置!',
- duration: 30,
- onClose: () => {
- Cookies.set('rememberIp', localIp)
- }
- });
- }
-
- this.setState({
- localIp
- })
- }
- })
- }
getProxyServerList = (checked?: boolean) => {
const { mainTableParams, collectTagList } = this.state;
this.setState({
@@ -135,7 +109,7 @@ class ProxyServer extends React.PureComponent {
}
//获取子表格数据
loadSubTableData(row: any) {
- const { localIp } = this.state;
+ const { localIp } = this.props;
const { id } = row;
const allIPChecked = localStorage.getItem(`${ localIp }-${ id }-all-ip-checked`) !== 'no'
this.setState({
@@ -438,7 +412,8 @@ class ProxyServer extends React.PureComponent {
localStorage.setItem('collection-tags', JSON.stringify(newList));
};
tableExpandedRowRender = (mainTableRow: any) => {
- const { subTableLoading, subTableData, localIp, allIPChecked } = this.state;
+ const { subTableLoading, subTableData, allIPChecked } = this.state;
+ const { localIp } = this.props;
const columns: any = [{
title: '序号',
key: 'index',
@@ -530,7 +505,7 @@ class ProxyServer extends React.PureComponent {
// 只看我的 IP (false)或者全部(true)
handleIPFilter = (allIPChecked, mainTableRow) => {
- const { localIp } = this.state;
+ const { localIp } = this.props;
localStorage.setItem(`${ localIp }-${ mainTableRow.id }-all-ip-checked`, allIPChecked ? 'yes' : 'no')
Message.success(`${ allIPChecked ? '查看全部' : '只看我的IP' }`)
this.setState({
@@ -549,8 +524,8 @@ class ProxyServer extends React.PureComponent {
})
}
render() {
+ const { localIp } = this.props;
const {
- localIp,
maintTableList,
mainTableParams,
maintTableTotal,
diff --git a/app/web/store/actions.ts b/app/web/store/actions.ts
index efcb1c3..89c07ab 100644
--- a/app/web/store/actions.ts
+++ b/app/web/store/actions.ts
@@ -1,18 +1,45 @@
-import { message } from 'antd';
-import { CHANGE_LOCAL_IP } from './constant';
+import { handleLocalIpChanged } from '@/utils/localIp';
+import config from '../../../env.json'
-export const changeLocalIp = (showMsg = false) => (dispatch: any, getState: any, { API }: any) => {
- API.getLocalIp().then((response: any) => {
- const { success, data } = response;
- if (success) {
- console.log(data);
- showMsg && message.success('刷新成功!')
+// 从接口获取本机IP
+export const fetchLocalIp = () => (dispatch: any, getState: any, { API }: any) => {
+ // 本地没有 localIp 再从接口获取
+ const localIp = localStorage.getItem('localIp');
+ if (localIp) {
dispatch({
- type: CHANGE_LOCAL_IP,
- payload: data
+ type: 'CHANGE_LOCAL_IP',
+ payload: {
+ host: `${localIp}:7001`,
+ localIp,
+ protocol: 'http'
+ }
})
+ handleLocalIpChanged(localIp);
+ } else {
+ API.getLocalIp().then((response: any) => {
+ const { success, data } = response;
+ if (success) {
+ dispatch({
+ type: 'CHANGE_LOCAL_IP',
+ payload: data
+ })
+ handleLocalIpChanged(data.localIp);
+ // 记录真实IP
+ localStorage.setItem('real-localIp', localIp);
+ }
+ });
}
- }).catch(() => {
- showMsg && message.warning('刷新失败!')
- });
+}
+
+// 自定义本机IP
+export const setLocalIp = (localIp) => (dispatch: any) => {
+ dispatch({
+ type: 'CHANGE_LOCAL_IP',
+ payload: {
+ host: `${localIp}:7001`,
+ localIp,
+ protocol: 'http'
+ }
+ })
+ handleLocalIpChanged(localIp);
}
diff --git a/app/web/store/constant.ts b/app/web/store/constant.ts
deleted file mode 100644
index b0afc10..0000000
--- a/app/web/store/constant.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const CHANGE_LOCAL_IP = 'CHANGE_LOCAL_IP';
diff --git a/app/web/store/reducer.ts b/app/web/store/reducer.ts
index 0fe52fb..a7a47aa 100644
--- a/app/web/store/reducer.ts
+++ b/app/web/store/reducer.ts
@@ -1,4 +1,3 @@
-import { CHANGE_LOCAL_IP } from './constant';
const initialState: any = {
localIp: '',
serverInfo: {
@@ -9,8 +8,9 @@ const initialState: any = {
export default (state = initialState, action: any) => {
const { type, payload } = action;
switch (type) {
- case CHANGE_LOCAL_IP:
+ case 'CHANGE_LOCAL_IP':
const { localIp, protocol, host } = payload;
+ localStorage.setItem('localIp', localIp);
return {
...state,
localIp,
diff --git a/app/web/utils/localIp.ts b/app/web/utils/localIp.ts
new file mode 100644
index 0000000..911404d
--- /dev/null
+++ b/app/web/utils/localIp.ts
@@ -0,0 +1,16 @@
+import { notification } from 'antd';
+
+// 本机IP发生变化进行提示
+export const handleLocalIpChanged = (localIp) => {
+ const rememberIp = localStorage.getItem('rememberIp');
+ if (rememberIp !== null && rememberIp !== localIp) {
+ notification.warning({
+ message: 'IP地址变更',
+ description: '您的IP地址【较上次访问时】已发生变更,请留意代理服务配置!',
+ duration: 5,
+ onClose: () => {
+ localStorage.setItem('rememberIp', localIp)
+ }
+ });
+ }
+}
diff --git a/docs/docsify/zh-cn/configuration/envConfig.md b/docs/docsify/zh-cn/configuration/envConfig.md
index 08e6dd3..6c2a28e 100644
--- a/docs/docsify/zh-cn/configuration/envConfig.md
+++ b/docs/docsify/zh-cn/configuration/envConfig.md
@@ -109,3 +109,16 @@ dingBot 的通知模板的跳转路径,默认跳转到帮助文档,可自行
}
}
```
+
+## vpnIp
+
+- 类型:string[]
+- 默认值:[]
+
+使用公司内部 VPN 时,本地地址会变成 VPN 的机器地址
+
+```json
+{
+ "vpnIp": ["127.0.0.1"]
+}
+```
diff --git a/env.json b/env.json
index 2370b40..31313be 100644
--- a/env.json
+++ b/env.json
@@ -7,5 +7,6 @@
"proxyHelpDocUrl": "https://dtstack.github.io/doraemon/docsify/#/zh-cn/guide/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1",
"mysql": {
"prod": {}
- }
+ },
+ "vpnIp": []
}