diff --git a/src/pages/devtools/components/route/index.tsx b/src/pages/devtools/components/route/index.tsx index c701ad8..1428f49 100644 --- a/src/pages/devtools/components/route/index.tsx +++ b/src/pages/devtools/components/route/index.tsx @@ -40,6 +40,52 @@ class Route extends React.PureComponent { lighting: {}, }; + public componentDidMount(): void { + const { + selectInfo, + } = this.props; + if (selectInfo && selectInfo.lighting && selectInfo.lighting === '1') { + this.setState(prevState => ({ + lighting: { + ...prevState.lighting, + [selectInfo.name]: { + checked: true, + color: selectInfo.lightingColor as string, + }, + }, + })); + } + } + + public componentDidUpdate(prevProps: Readonly): void { + if (prevProps.selectInfo?.name !== this.props.selectInfo?.name && this.props.selectInfo && !this.state.lighting[this.props.selectInfo.name]) { + const checked = !!(this.props.selectInfo.lighting && this.props.selectInfo.lighting === '1'); + this.setState(prevState => ({ + lighting: { + ...prevState.lighting, + [this.props.selectInfo?.name ?? 'defaultName']: { + checked, + color: this.props.selectInfo?.lightingColor as string, + }, + }, + })); + } + if (prevProps.selectInfo && !this.props.selectInfo) { + this.setState({ + lighting: {}, + }); + const evalLabel = `JSON.stringify(function(){ + if (window.originalStyles){ + window.originalStyles = new Map(); + window.setLightingStyle = []; + } + }())`; + chrome.devtools.inspectedWindow.eval( + evalLabel, + ); + } + } + /** * 修改高亮状态 * @param checked 是否高亮 @@ -106,7 +152,7 @@ class Route extends React.PureComponent { } var appDOM = document.getElementsByName('${selectInfo.name}')[0]; if (${lighting[selectInfo.name].checked}) { - const originalStyle = appDOM.getAttribute('style'); + var originalStyle = appDOM.getAttribute('style'); if (window.setLightingStyle.indexOf('${selectInfo.name}') == -1 && !window.originalStyles.get('${selectInfo.name}')){ window.setLightingStyle.push('${selectInfo.name}'); window.originalStyles.set('${selectInfo.name}', originalStyle); @@ -115,13 +161,17 @@ class Route extends React.PureComponent { appDOM.style.display = 'block'; appDOM.style.transformOrigin = 'center'; appDOM.style.transform = 'rotate(360deg)'; + appDOM.setAttribute('data-lighting', '1'); + appDOM.setAttribute('data-lighting-color', '${color}'); } else { - const originalStyle = window.originalStyles.get('${selectInfo.name}'); + var originalStyle = window.originalStyles.get('${selectInfo.name}'); if (originalStyle) { appDOM.setAttribute('style', originalStyle); } else { appDOM.removeAttribute('style'); } + appDOM.removeAttribute('data-lighting'); + appDOM.removeAttribute('data-lighting-color'); } }())`; chrome.devtools.inspectedWindow.eval( diff --git a/src/pages/devtools/index.tsx b/src/pages/devtools/index.tsx index 27edc1f..20efcfc 100644 --- a/src/pages/devtools/index.tsx +++ b/src/pages/devtools/index.tsx @@ -73,6 +73,8 @@ class DevToolsPage extends React.PureComponent { console.log('microAppLevel返回', treeData); this.setState({ @@ -148,6 +150,14 @@ class DevToolsPage extends React.PureComponent { + this.setState({ + selectInfo: null, + }, () => { + this.getTree(); + }); + }; + public render() { const { treeData, @@ -158,7 +168,7 @@ class DevToolsPage extends React.PureComponent - } onClick={this.getTree} />}> + } onClick={this.refresh} />}> { - public state: CommunicateState = { - info: {}, - currentTab: 'getMainToSubData', // 'getMainToSubData', - showKVType: true, - dataSource: [{ - id: this.randomId(), - checked: true, - key: '', - value: '', - valueType: 'string', - }], - jsonInputError: false, - treeData: [], - selectInfo: null, - canDispatchData: [], - selectDispatchAppName: '', - lighting: {}, - init: true, - history: [], - }; - - public componentDidMount() { - this.getTree(); - } - - /** - * 获取页面微应用结构 - */ - private getTree = () => { - const { - selectInfo, - } = this.state; - getMicroAppLevel({ - key: 'name', - title: 'name', - url: 'url', - iframe: 'iframe', - version: 'version', - href: 'href', - fullPath: 'fullPath', - baseroute: 'baseroute', - tagName: 'tagName', - }).then((treeData) => { - console.log('microAppLevel返回', treeData); - this.setState({ - treeData: treeData as (FinalTreeData & { - key: string; - title: string; - })[], - info: {}, - init: false, - }, () => { - this.getCanDispatchData(); - }); - const allAppInfo = this.getAllAppInfo(treeData); - if (selectInfo) { - let inAppInfo = false; - for (const el of allAppInfo) { - if (el.name === selectInfo.name) { - inAppInfo = true; - this.setState({ - selectInfo: el.info, - }, () => { - this.loadHistory(); - }); - break; - } - } - if (!inAppInfo && allAppInfo.length > 0) { - this.setState({ - selectInfo: allAppInfo[0].info, - }, () => { - this.loadHistory(); - }); - } - } else if (allAppInfo.length > 0) { - this.setState({ - selectInfo: allAppInfo[0].info, - }, () => { - this.loadHistory(); - }); - } - if (['getMainToSubData', 'getSubToMainData'].includes(this.state.currentTab)) { - this.getData(); - } - return null; - }).catch((error: unknown) => { - console.error('err', error); - }); - }; - - /** - * 从页面获取数据 - */ - private getData = () => { - const { - currentTab, - selectInfo, - } = this.state; - let evalLabel = ''; - let domName = selectInfo?.tagName || 'micro-app'; - const appName = selectInfo?.name || ''; - if (appName) { - domName += `[name='${appName}']`; - } - evalLabel = currentTab === 'getSubToMainData' - ? `JSON.stringify(function () { - if (!document.querySelector("${domName}").getSendData){ - document.querySelector("${domName}").addEventListener('datachange', function (e) { - document.querySelector("${domName}").getSendData = e.detail.data; - document.querySelector("${domName}").onDataChange; - }) - } - return document.querySelector("${domName}").getSendData; - }())` - : `JSON.stringify(document.querySelector("${domName}").data)`; - chrome.devtools.inspectedWindow.eval( - evalLabel, - (res: string) => { - if (res && res !== 'null') { - this.setState({ - info: JSON.parse(res), - }); - if (res !== '{}') { - this.saveHistory(JSON.parse(res)); - } - } else { - this.setState({ - info: {}, - }); - } - }, - ); - }; - - /** - * 保存历史数据至localStorage - * @param content 待保存的内容 - */ - private saveHistory = (content: unknown) => { - const { - selectInfo, - currentTab, - } = this.state; - const oldHistory: string | null = localStorage.getItem(`${currentTab}_${selectInfo?.name}`); - let result: HistoryData[] = []; - if (!oldHistory) { - result = [{ - time: moment().valueOf(), - content, - type: currentTab, - }]; - } else { - let history: HistoryData[] = JSON.parse(oldHistory).filter((el: HistoryData) => JSON.stringify(el.content) !== JSON.stringify(content)); - if (history.length >= 8) { - history = history.slice(0, 7); - } - result = [{ - time: moment().valueOf(), - content, - type: currentTab, - }, ...history]; - } - localStorage.setItem(`${currentTab}_${selectInfo?.name}`, JSON.stringify(result)); - this.setState({ - history: result, - }); - }; - - /** - * 从localStorage里读取历史数据 - */ - private loadHistory = () => { - const { - currentTab, - selectInfo, - } = this.state; - const history = localStorage.getItem(`${currentTab}_${selectInfo?.name}`); - this.setState({ - history: history ? JSON.parse(history) : [], - }); - }; - - private cleanHistory = () => { - const { - selectInfo, - currentTab, - } = this.state; - localStorage.removeItem(`${currentTab}_${selectInfo?.name}`); - this.setState({ - history: [], - }); - }; - - /** - * 获取数据渲染 - */ - private getDataDOM = () => { - const { - info, - history, - } = this.state; - return ( -
-
- - - - - - - -
历史记录
- -
- )} - content={( -
- index + 1, - }, { - title: '内容', - dataIndex: 'content', - render: text => { JSON.stringify(text) }, - }, { - title: '时间', - dataIndex: 'time', - render: text => moment(text).format('YYYY-MM-DD HH:mm:ss'), - }]} - pagination={false} - dataSource={history} - locale={{ - emptyText: '暂无记录', - }} - /> - - )} - > - - - - - - ); - }; - - /** - * 生成随机ID,用于Table的key - */ - private randomId(): number { - return Math.floor(Math.random() * 10000); - } - - /** - * 修改传参数据并校验 - * @param value 待修改的数据 - */ - private changeTextAreaData = (value: string): void => { - try { - const newValue = JSON.parse(value || '{}'); - const newDataSource: KeyValueData[] = []; - for (const key of Object.keys(newValue)) { - const newDataValue = newValue[key]; - let valueType: 'string' | 'number' | 'boolean' = 'string';// TODO 动态判断数据类型 - if (typeof newDataValue === 'number') { - valueType = 'number'; - } else if (typeof newDataValue === 'boolean') { - valueType = 'boolean'; - } - newDataSource.push({ - id: this.randomId(), - checked: true, - key, - value: String(newDataValue), - valueType, - }); - } - newDataSource.push({ - id: this.randomId(), - checked: true, - key: '', - value: '', - valueType: 'string', - }); - this.setState({ - dataSource: newDataSource, - jsonInputError: false, - }); - } catch { - this.setState({ - jsonInputError: true, - }); - } - }; - - /** - * 将Table的dataSource格式数据转换成标准传输数据 - * @param dataSource Table数据 - * @returns 标准数据 - */ - private formatData = (dataSource: KeyValueData[]): { - [key: string]: string | number | boolean; - } => { - const data = {}; - for (const el of dataSource) { - if (el.checked && el.key !== '' && el.value !== '') { - switch (el.valueType) { - case 'string': - data[el.key] = String(el.value); - break; - case 'number': - data[el.key] = Number.parseFloat(el.value); - break; - case 'boolean': - data[el.key] = Boolean(el.value); - break; - default: - data[el.key] = el.value; - } - } - } - return data; - }; - - /** - * 获取能够向父应用发送数据的子应用 - * Tips:并不是所有子应用都可发数据给父应用,在iframe模式下均可以,在with模式下仅最后加载的应用可以 - */ - private getCanDispatchData = () => { - const { - selectInfo, - } = this.state; - const evalLabel = `JSON.stringify(function (){ - const rawWindow = window.__MICRO_APP_PROXY_WINDOW__?.rawWindow || []; - if (rawWindow.length == 0){ - result = [window.__MICRO_APP_PROXY_WINDOW__?.microApp?.appName]; - } else { - let result = []; - for (var i = 0; i < rawWindow.length; i++){ - const oneWindow = rawWindow[i]; - result.push(oneWindow.microApp.appName); - } - } - return result; - }())`; - chrome.devtools.inspectedWindow.eval( - evalLabel, - (res: string) => { - const canDispatchData = JSON.parse(res); - let selectDispatchAppName = ''; - if (canDispatchData.length > 0) { - selectDispatchAppName = canDispatchData[0]; - if (selectInfo && canDispatchData.includes(selectInfo.name)) { - selectDispatchAppName = selectInfo.name; - } - } - this.setState({ - canDispatchData, - selectDispatchAppName, - }); - }, - ); - }; - - /** - * 快速将历史数据填入表格 - * @param record 单条历史数据 - */ - private writeHistoryData = (record: HistoryData) => { - this.setState({ - dataSource: record.content as KeyValueData[], - }); - }; - - /** - * 发送数据渲染 - */ - private sendDataDOM = () => { - const { - showKVType, - jsonInputError, - dataSource, - history, - } = this.state; - const data = this.formatData(dataSource); - let validateStatus: '' | 'error' = ''; - if (!showKVType && jsonInputError) { - validateStatus = 'error'; - } - return ( -
- - 设置传递数据 - this.setState({ showKVType: e })} /> - - )} - validateStatus={validateStatus} - help={jsonInputError ? '请输入标准JSON格式数据' : ''} - > - { showKVType - ? ( -
( - this.changeData({ - type: 'checked', - value: e.target.checked, - record, - })} - /> - ), - }, { - title: 'Key', - dataIndex: 'key', - render: (text, record) => ( - this.changeData({ - type: 'key', - value: e.target.value, - record, - })} - /> - ), - }, { - title: 'Value', - dataIndex: 'value', - render: (text, record) => ( - this.changeData({ - type: 'value', - value: e.target.value, - record, - })} - /> - ), - }, { - title: '数据类型', - dataIndex: 'valueType', - render: (text, record) => ( - - ), - }, { - title: '操作', - dataIndex: 'edit', - render: (text, record, index) => - { - this.sendData(); - this.reloadApp(); - }, - }} - > - 发送 - - - - -
历史记录
- - - )} - content={() => { - const columns = [{ - title: '序号', - dataIndex: 'index', - render: (text: unknown, record: unknown, index: number): JSX.Element =>
{ index + 1 }
, - }, { - title: '内容', - dataIndex: 'content', - render: (text: unknown): JSX.Element => { JSON.stringify(this.formatData(text as KeyValueData[])) }, - }, { - title: '时间', - dataIndex: 'time', - render: (text: unknown): string => moment(text as number).format('YYYY-MM-DD HH:mm:ss'), - }]; - if (showKVType) { - columns.push({ - title: '操作', - dataIndex: 'edit', - render: (text: unknown, record: unknown, index: number): JSX.Element => , - }); - } - return ( -
-
- - ); - }} - > - - - - - - - ); - }; - - /** - * 删除某行数据 - * @param e 待删除的信息 - */ - private deleteOneData = (e: KeyValueData): void => { - this.setState(prevState => ({ - dataSource: prevState.dataSource.filter(el => el.id !== e.id), - })); - }; - - /** - * 将某行设置的数据转换成标准格式 - * @param e 行数据 - */ - private changeData = (e: { - type: 'key' | 'value' | 'checked' | 'valueType'; - value: string | number | boolean; - record: KeyValueData; - }): void => { - this.setState(prevState => ({ - dataSource: prevState.dataSource.map((el) => { - if (el.id === e.record.id) { - return { - ...el, - [e.type]: e.type === 'checked' ? !!e.value : e.value, - }; - } - return el; - }), - }), () => { - const lastRecord = this.state.dataSource[this.state.dataSource.length - 1]; - if (e.record.id === lastRecord.id && (lastRecord.key || lastRecord.value)) { - this.setState(prevState => ({ - dataSource: [ - ...prevState.dataSource, - { - id: this.randomId(), - checked: true, - key: '', - value: '', - valueType: 'string', - }, - ], - })); - } - }); - }; - - /** - * 从页面发送数据 - */ - private sendData = () => { - const { - currentTab, - dataSource, - selectInfo, - canDispatchData, - selectDispatchAppName, - } = this.state; - const data = this.formatData(dataSource); - const appName = selectInfo?.name || ''; - let evalLabel = ''; - if (currentTab === 'sendDataFromSubToMain') { - evalLabel = canDispatchData.length <= 1 - ? `window.__MICRO_APP_PROXY_WINDOW__.microApp.dispatch(${JSON.stringify(data)})` - : `JSON.stringify(function (){ - const rawWindow = window.__MICRO_APP_PROXY_WINDOW__?.rawWindow || []; - for (var i = 0; i < rawWindow.length; i++){ - const oneWindow = rawWindow[i]; - if (oneWindow.microApp.appName === "${selectDispatchAppName}"){ - oneWindow.microApp.dispatch(${JSON.stringify(data)}); - break; - } - } - }())`; - } else { - let domName = selectInfo?.tagName || 'micro-app'; - if (appName) { - domName += `[name='${appName}']`; - } - evalLabel = `document.querySelector("${domName}").data = ${JSON.stringify(data)}`; - } - chrome.devtools.inspectedWindow.eval( - evalLabel, - () => { - message.success('发送成功'); - this.saveHistory(dataSource); - }, - ); - }; - - /** - * 平铺递归处理微应用树形结构数据 - * @param data 树形数据 - * @returns 平铺后的数据 - */ - private getAllAppInfo = (data: FinalTreeData[]): AllAppInfoData[] => { - let result: AllAppInfoData[] = []; - for (const el of data) { - result.push({ - name: el.name, - info: el, - }); - if ((el.children as FinalTreeData[]).length > 0) { - const subResult = this.getAllAppInfo(el.children as FinalTreeData[]); - result = [...result, ...subResult]; - } - } - return result; - }; - - /** - * 选择应用 - * @param selectedKeys 已选择的key - * @param info 选择的数据 - */ - private selectTree = (selectedKeys: (string | number)[], info: { event: 'select'; selected: boolean; node: unknown; selectedNodes: unknown[]; nativeEvent: MouseEvent }) => { - const { - currentTab, - } = this.state; - if (selectedKeys.length > 0) { - this.setState({ - selectInfo: info.node as FinalTreeData, - }, () => { - this.loadHistory(); - if (['getMainToSubData', 'getSubToMainData'].includes(currentTab)) { - this.getData(); - } - }); - } - }; - - /** - * 修改高亮状态 - * @param checked 是否高亮 - */ - private changeLighting = (checked: boolean) => { - const { - selectInfo, - } = this.state; - if (selectInfo) { - this.setState(prevState => ({ - lighting: { - ...prevState.lighting, - [selectInfo.name]: { - ...prevState.lighting[selectInfo.name], - checked, - }, - }, - }), () => { - this.doLighting(); - }); - } - }; - - /** - * 修改高亮边框颜色 - * @param color 颜色 - * @param hex HEX颜色 - */ - private changeColor = (color: unknown, hex: string) => { - const { - selectInfo, - } = this.state; - if (selectInfo) { - this.setState(prevState => ({ - lighting: { - ...prevState.lighting, - [selectInfo.name]: { - ...prevState.lighting[selectInfo.name], - color: hex, - }, - }, - }), () => { - this.doLighting(); - }); - } - }; - - /** - * 页面应用标记高亮 - */ - private doLighting = () => { - const { - lighting, - selectInfo, - } = this.state; - if (selectInfo) { - const color = lighting[selectInfo.name].color || '#E2231A'; - const evalLabel = `JSON.stringify(function(){ - if (!window.originalStyles){ - window.originalStyles = new Map(); - window.setLightingStyle = []; - } - var appDOM = document.getElementsByName('${selectInfo.name}')[0]; - if (${lighting[selectInfo.name].checked}) { - const originalStyle = appDOM.getAttribute('style'); - if (window.setLightingStyle.indexOf('${selectInfo.name}') == -1 && !window.originalStyles.get('${selectInfo.name}')){ - window.setLightingStyle.push('${selectInfo.name}'); - window.originalStyles.set('${selectInfo.name}', originalStyle); - } - appDOM.style.border = '2px dashed ${color}'; - appDOM.style.display = 'block'; - appDOM.style.transformOrigin = 'center'; - appDOM.style.transform = 'rotate(360deg)'; - } else { - const originalStyle = window.originalStyles.get('${selectInfo.name}'); - if (originalStyle) { - appDOM.setAttribute('style', originalStyle); - } else { - appDOM.removeAttribute('style'); - } - } - }())`; - chrome.devtools.inspectedWindow.eval( - evalLabel, - ); - } - }; - - /** - * 重新加载微应用 - */ - private reloadApp = () => { - const { - selectInfo, - } = this.state; - let domName = selectInfo?.tagName || 'micro-app'; - const appName = selectInfo?.name || ''; - if (appName) { - domName += `[name='${appName}']`; - } - const evalLabel = `document.querySelector("${domName}").reload()`; - chrome.devtools.inspectedWindow.eval( - evalLabel, - ); - }; - - public render() { - const { - currentTab, - treeData, - selectInfo, - canDispatchData, - lighting, - init, - } = this.state; - if (!init && treeData.length === 0) { - return ( - - -
未发现MicroApp微应用
- - - )} - /> -
- ); - } - const tabItems: { - key: string; - label: string; - children?: JSX.Element; - }[] = [{ - key: 'getMainToSubData', - label: '获取父应用传递给此子应用的数据', - children: this.getDataDOM(), - }, { - key: 'getSubToMainData', - label: '获取此子应用传递给父应用的数据', - children: this.getDataDOM(), - }, { - key: 'sendDataFromMainToSub', - label: '模拟父应用向此子应用发送数据', - children: this.sendDataDOM(), - }]; - if (canDispatchData.length > 0 && selectInfo && selectInfo.name && canDispatchData.includes(selectInfo.name)) { - tabItems.push({ - key: 'sendDataFromSubToMain', - label: '模拟此子应用向父应用发送数据', - children: this.sendDataDOM(), - }); - } - tabItems.push({ - key: 'openSimulation', - label: '此子应用开发环境模拟', - }); - let href: string = ''; - if (selectInfo) { - href = selectInfo.url as string; - if (!(/^https?:\/\//u).test(href)) { - href = `http://${href}`; - } - } - return ( -
- -
- } onClick={this.getTree} />}> - - - - { selectInfo && ( - - } onClick={this.reloadApp}>重新加载}> - - { selectInfo.name } - { selectInfo.url } - { selectInfo.baseroute && { selectInfo.baseroute } } - { selectInfo.fullPath && { selectInfo.fullPath } } - - - - - - - { !(/^0\./u).test(selectInfo.version as string) && { selectInfo.iframe as string || 'false' } } - { selectInfo.version } - - - - { - if (activityTab === 'openSimulation') { - const url = (selectInfo.url as string).replace(/^(https?:)?\/\//u, ''); - let prefix = ''; - prefix = !(/^https?:\/\//u).test(selectInfo.url as string) ? 'http:' : new URL(selectInfo.url as string).protocol; - const params = { - url, - prefix: `${prefix}//`, - data: JSON.stringify([]), - ver: '1.0', - }; - if (selectInfo.version && selectInfo.version.startsWith('0')) { - params.ver = '0.8'; - } - chrome.tabs.create({ - url: `simulation.html?${encodeURIComponent(JSON.stringify(params))}`, - }); - } else { - this.setState({ - info: {}, - currentTab: activityTab, - dataSource: [{ - id: this.randomId(), - checked: true, - key: '', - value: '', - valueType: 'string', - }], - history: [], - }, () => { - this.loadHistory(); - if (activityTab === 'sendDataFromSubToMain') { - this.getCanDispatchData(); - } - if (['getMainToSubData', 'getSubToMainData'].includes(activityTab)) { - this.getData(); - } - }); - } - }} - /> - - - ) } - - - ); - } -} - -export default CommunicatePage; diff --git a/src/pages/devtoolsBackup/components/console-log/index.module.less b/src/pages/devtoolsBackup/components/console-log/index.module.less deleted file mode 100644 index d49031b..0000000 --- a/src/pages/devtoolsBackup/components/console-log/index.module.less +++ /dev/null @@ -1,21 +0,0 @@ -.table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; - display: table; - border-bottom: 1px solid var(--color-border-primary); - - tr { - border-bottom: 1px solid var(--color-border-primary); - - &:nth-child(odd) { - background-color: var(--color-background-primary-active); - } - } - - th, - td { - padding: 5px 10px; - text-align: left; - } -} diff --git a/src/pages/devtoolsBackup/components/console-log/index.tsx b/src/pages/devtoolsBackup/components/console-log/index.tsx deleted file mode 100644 index e04319e..0000000 --- a/src/pages/devtoolsBackup/components/console-log/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -import styles from './index.module.less'; - -const Console: React.FC = props => ( -
-

敬请期待~

-
-); - -export default Console; diff --git a/src/pages/devtoolsBackup/components/header-tabs/index.tsx b/src/pages/devtoolsBackup/components/header-tabs/index.tsx deleted file mode 100644 index 32e57da..0000000 --- a/src/pages/devtoolsBackup/components/header-tabs/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; - -import { HEADER_TAB_LIST } from '../../config'; -import Tabs from '../tabs'; - -interface HeaderTabsProps { - value: string; - onChange: (value: string) => void; -} - -const HeaderTabs: React.FC = props => ( - -); - -export default HeaderTabs; diff --git a/src/pages/devtoolsBackup/components/micro-app-env/index.module.less b/src/pages/devtoolsBackup/components/micro-app-env/index.module.less deleted file mode 100644 index f8e9232..0000000 --- a/src/pages/devtoolsBackup/components/micro-app-env/index.module.less +++ /dev/null @@ -1,27 +0,0 @@ -.table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; - display: table; - border-bottom: 1px solid var(--color-border-primary); - - tr { - border-bottom: 1px solid var(--color-border-primary); - - &:nth-child(odd) { - background-color: var(--color-background-primary-active); - } - } - - th, - td { - padding: 5px 10px; - text-align: left; - } -} - -.detailIcon { - margin-left: 5px; - color: inherit; - text-decoration: none; -} diff --git a/src/pages/devtoolsBackup/components/micro-app-env/index.tsx b/src/pages/devtoolsBackup/components/micro-app-env/index.tsx deleted file mode 100644 index b3d19ab..0000000 --- a/src/pages/devtoolsBackup/components/micro-app-env/index.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React, { useEffect } from 'react'; - -import { MICRO_APP_ENV_INFO } from '../../config'; -import { DevToolsInfo } from '../../types'; - -import styles from './index.module.less'; - -interface MicroAppEnvProps { - info: DevToolsInfo; -} - -const MicroAppEnv: React.FC = (props) => { - const [devInfo, setDevInfo] = React.useState({}); - useEffect(() => { - chrome.devtools.inspectedWindow.eval( - 'document.querySelector("micro-app")?.version', - (res: string) => { - if (res) { - setDevInfo(res); - } - }, - ); - }, []); - if (!props.info.currentMicroApp?.env) { - return null; - } - - const showDetailIcon = (link: string) => ( - - - - ); - - return ( -
-
- - - - - - - - - - - - - - { Object.keys(props.info.currentMicroApp?.env).map(p => ( - - - - - - )) } - -
NameValueDescribe
-
__MICRO_APP_VERSION__
-
{ JSON.stringify(devInfo) }微前端版本号
-
- { p } - { showDetailIcon(MICRO_APP_ENV_INFO[p]?.url) } -
-
{ JSON.stringify(props.info.currentMicroApp?.env[p]) || 'undefined' }{ MICRO_APP_ENV_INFO[p]?.describe }
-
-
- ); -}; - -export default MicroAppEnv; diff --git a/src/pages/devtoolsBackup/components/route-match/index.module.less b/src/pages/devtoolsBackup/components/route-match/index.module.less deleted file mode 100644 index c707233..0000000 --- a/src/pages/devtoolsBackup/components/route-match/index.module.less +++ /dev/null @@ -1,30 +0,0 @@ -.table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; - display: table; - border-bottom: 1px solid var(--color-border-primary); - - tr { - border-bottom: 1px solid var(--color-border-primary); - - &:nth-child(odd) { - background-color: var(--color-background-primary-active); - } - } - - th, - td { - padding: 5px 10px; - text-align: left; - } -} - -.btn { - background-color: #00bfff; - width: 180px; - border-radius: 5px; - border-color: #00bfff; - margin-top: 20px; - margin-left: 20px; -} diff --git a/src/pages/devtoolsBackup/components/route-match/index.tsx b/src/pages/devtoolsBackup/components/route-match/index.tsx deleted file mode 100644 index c26ec14..0000000 --- a/src/pages/devtoolsBackup/components/route-match/index.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import { Alert, Input, Space } from 'antd'; -import React from 'react'; -import { CopyToClipboard } from 'react-copy-to-clipboard'; - -import { DevToolsInfo } from '../../types'; - -import styles from './index.module.less'; - -interface RouteProps { - info: DevToolsInfo; -} - -interface RouteState { - appUrl1: string; - appUrl2: string; - appUrl3: string; - urlOrigin1: string | null; - urlOrigin2: string | null; - urlOrigin3: string | null; - subAppUrl1: string; - subAppUrl2: string; - subAppUrl3: string; - pathname: string | undefined | null; - search: string | null; - hash: string | null; - baseRoute: string | undefined; - isDecodeBaseUrl: string; -} - -class Route extends React.PureComponent { - public state: RouteState = { - appUrl1: '', - appUrl2: '', - appUrl3: '', - urlOrigin1: '', - urlOrigin2: '', - urlOrigin3: '', - subAppUrl1: '', - subAppUrl2: '', - subAppUrl3: '', - pathname: '', - search: '', - hash: '', - baseRoute: '', - isDecodeBaseUrl: '', - }; - - /** - * click get parent app data - */ - public getSubApp1() { - chrome.devtools.inspectedWindow.eval( - 'document.querySelectorAll("[name][url]")[0].appUrl', - (res: string) => { - if (res) { - const subApp1 = res; - const regex1 = /^(https?:\/\/[^/]+)/uim; - const match1 = res?.match(regex1); - this.setState({ appUrl1: subApp1, urlOrigin1: match1 && match1[1], subAppUrl1: res, appUrl2: '', appUrl3: '' }); - this.getBaseURI(); - } - }, - ); - } - - /** - * click get parent app data - */ - public getSubApp2() { - chrome.devtools.inspectedWindow.eval( - 'document.querySelectorAll("[name][url]")[1].appUrl', - (res: string) => { - if (res) { - const subApp2 = res; - const regex1 = /^(https?:\/\/[^/]+)/uim; - const match1 = res?.match(regex1); - this.setState({ appUrl2: subApp2, urlOrigin2: match1 && match1[1], subAppUrl2: res, appUrl3: '' }); - this.getBaseURI(); - this.getSubApp3(); - } - }, - ); - } - - /** - * click get parent app data - */ - public getSubApp3() { - chrome.devtools.inspectedWindow.eval( - 'document.querySelectorAll("[name][url]")[2].appUrl', - (res: string) => { - if (res) { - const subApp3 = res; - const regex1 = /^(https?:\/\/[^/]+)/uim; - const match1 = res?.match(regex1); - this.setState({ appUrl3: subApp3, urlOrigin2: match1 && match1[1], subAppUrl3: res }); - this.getBaseURI(); - } - }, - ); - } - - /** - * click get parent app data - */ - public getBaseURI() { - chrome.devtools.inspectedWindow.eval( - 'document.querySelectorAll("micro-app")[0].baseURI', - (res: string) => { - if (res) { - // 匹配父应用的pathname、search和hash - const regex = /^(?:https?:\/\/[^/]+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?$/u; - const match = res?.match(regex); - if (res.includes('%2F') || res.includes('%3F') || res.includes('%3D') || res.includes('%3A')) { - const decodedURL = JSON.parse(decodeURIComponent(JSON.stringify(res))); - const Arr = decodedURL.split('#')[1]; - const hashArr = decodedURL.includes('#') ? '#'.concat(Arr) : ''; - this.setState({ - isDecodeBaseUrl: hashArr, - hash: hashArr, - pathname: this.props.info.currentMicroApp?.env?.__MICRO_APP_PUBLIC_PATH__, - baseRoute: this.props.info.currentMicroApp?.env?.__MICRO_APP_BASE_ROUTE__, - }); - } else { - this.setState({ - isDecodeBaseUrl: res.includes('#') ? '#'.concat(res.split('#')[1]) : '', - pathname: match && match[1], - search: match && match[2], - hash: match && match[3], - baseRoute: this.props.info.currentMicroApp?.env?.__MICRO_APP_BASE_ROUTE__, - }); - } - } - }, - ); - } - - public handleUrl(urlOrigin: string | null, appUrl: string, subAppUrl: string) { - const { baseRoute, pathname, search, hash, isDecodeBaseUrl } = this.state; - const locationString = [urlOrigin, baseRoute, pathname, search, hash]; - const uniqueArray = locationString.filter((value, index, self) => self.indexOf(value) === index); - const result = baseRoute ? uniqueArray.join('') : subAppUrl; - const handleResult = JSON.stringify(isDecodeBaseUrl ? subAppUrl?.concat(hash || '') : result); - const subAppLink = handleResult.includes('undefined') ? handleResult.replace('undefined', '') : JSON.parse(handleResult); - return subAppLink; - } - - public openNewWindow(urlOrigin: string | null, appUrl: string, subAppUrl: string) { - window.open(this.handleUrl(urlOrigin, appUrl, subAppUrl) || ''); - } - - public render() { - const { appUrl1, appUrl2, appUrl3, urlOrigin1, urlOrigin2, urlOrigin3, subAppUrl1, subAppUrl2, subAppUrl3 } = this.state; - return ( -
-
-
- - - - - - - - - -
- { appUrl2 && ( -
- - - - - -
- ) } - { appUrl3 && ( -
- - - - - -
- ) } -
-
- ); - } -} - -export default Route; diff --git a/src/pages/devtoolsBackup/components/tabs/index.module.less b/src/pages/devtoolsBackup/components/tabs/index.module.less deleted file mode 100644 index 0726d10..0000000 --- a/src/pages/devtoolsBackup/components/tabs/index.module.less +++ /dev/null @@ -1,25 +0,0 @@ -.tab { - &-list { - display: flex; - border-bottom: 1px solid var(--color-border-primary); - } - - &-item { - flex: 0 0 auto; - padding: 5px 10px; - border-right: 1px solid var(--color-border-primary); - cursor: pointer; - color: var(--color-text-secondary); - user-select: none; - - &:not(&--active):hover { - color: var(--color-text-primary); - background-color: var(--color-background-primary-hover); - } - - &--active { - color: var(--color-text-primary); - background-color: var(--color-background-primary-active); - } - } -} diff --git a/src/pages/devtoolsBackup/components/tabs/index.tsx b/src/pages/devtoolsBackup/components/tabs/index.tsx deleted file mode 100644 index e280355..0000000 --- a/src/pages/devtoolsBackup/components/tabs/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; - -import styles from './index.module.less'; - -interface HeaderTabsProps { - value: string; - options: { name: string; label: string }[]; - onChange: (value: string) => void; -} - -const Tabs: React.FC = props => ( -
- { - props.options.map(p => ( -
{ props.onChange(p.name); }} - > - { p.label } -
- )) - } -
-); - -export default Tabs; diff --git a/src/pages/devtoolsBackup/components/view-app/index.module.less b/src/pages/devtoolsBackup/components/view-app/index.module.less deleted file mode 100644 index 3ed4b2f..0000000 --- a/src/pages/devtoolsBackup/components/view-app/index.module.less +++ /dev/null @@ -1,8 +0,0 @@ -.btn { - background-color: #00bfff; - width: 180px; - border-radius: 5px; - border-color: #00bfff; - margin-top: 20px; - margin-left: 20px; -} diff --git a/src/pages/devtoolsBackup/components/view-app/index.tsx b/src/pages/devtoolsBackup/components/view-app/index.tsx deleted file mode 100644 index 8ca7d1f..0000000 --- a/src/pages/devtoolsBackup/components/view-app/index.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react'; - -import styles from './index.module.less'; - -interface ViewAppProps { } -interface ViewAppState { -} -class ViewAppPage extends React.PureComponent { - public state: ViewAppState = {}; - - public render() { - return ( -
-
-
- -
-
- -
-
-
- ); - } -} - -export default ViewAppPage; diff --git a/src/pages/devtoolsBackup/config/index.ts b/src/pages/devtoolsBackup/config/index.ts deleted file mode 100644 index 80f2dc9..0000000 --- a/src/pages/devtoolsBackup/config/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable etc/no-commented-out-code */ -export const HEADER_TAB_LIST = [ - { name: 'ENV_VALUE_VIEWER', label: 'Environment' }, - { name: 'COMMUNICATE', label: 'Communicate' }, - /* - * { name: 'VIEW_APP', label: 'View' }, - * { name: 'ROUTE_MATCH', label: 'Route' }, - */ -]; - -export const MICRO_APP_ENV_INFO = { - __MICRO_APP_ENVIRONMENT__: { - describe: '判断应用是否在微前端环境中', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_environment__', - }, - __MICRO_APP_NAME__: { - describe: '应用名称', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_name__', - }, - __MICRO_APP_PUBLIC_PATH__: { - describe: '子应用的静态资源前缀', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_public_path__', - }, - __MICRO_APP_URL__: { - describe: '子应用的网址', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_base_route__', - }, - __MICRO_APP_BASE_URL__: { - describe: '子应用的基础网址', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_base_route__', - }, - __MICRO_APP_BASE_ROUTE__: { - describe: '子应用的基础路由', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_base_route__', - }, - __MICRO_APP_SANDBOX_TYPE__: { - describe: '子应用沙箱模式', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/configure?id=iframe', - }, - __MICRO_APP_UMD_MODE__: { - describe: '是否开启UMD模式', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/framework/vue?id=_1%e3%80%81%e5%bc%80%e5%90%afumd%e6%a8%a1%e5%bc%8f%ef%bc%8c%e4%bc%98%e5%8c%96%e5%86%85%e5%ad%98%e5%92%8c%e6%80%a7%e8%83%bd', - }, - __MICRO_APP_PRE_RENDER__: { - describe: '是否开启预渲染', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/router', - }, - __MICRO_APP_BASE_APPLICATION__: { - describe: '是否是主应用', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/env?id=__micro_app_base_application__', - }, - __MICRO_APP_STATE__: { - describe: '基座中获取子应用的状态', - url: 'https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/changelog?id=_100-rc3', - }, -}; diff --git a/src/pages/devtoolsBackup/index.module.less b/src/pages/devtoolsBackup/index.module.less deleted file mode 100644 index 240d183..0000000 --- a/src/pages/devtoolsBackup/index.module.less +++ /dev/null @@ -1,13 +0,0 @@ -html, -body { - margin: 0; - padding: 0; -} - -body { - background-color: var(--color-background-primary); -} - -.container { - color: var(--color-text-primary); -} diff --git a/src/pages/devtoolsBackup/index.tsx b/src/pages/devtoolsBackup/index.tsx deleted file mode 100644 index 5fe919c..0000000 --- a/src/pages/devtoolsBackup/index.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React from 'react'; - -import { decodeJSON } from '@/utils/json'; - -import Communicate from './components/communicate'; -import Console from './components/console-log'; -import HeaderTabs from './components/header-tabs'; -import MicroAppEnv from './components/micro-app-env'; -import Route from './components/route-match'; -import ViewApp from './components/view-app'; -import { HEADER_TAB_LIST } from './config'; -import { DevToolsInfo, DevToolsMicroAppInfo } from './types'; - -import styles from './index.module.less'; - -interface DevToolsPageProps { } - -interface DevToolsPageState { - activeTab: string; - info: DevToolsInfo; -} - -class DevToolsPage extends React.PureComponent { - public state = { - activeTab: HEADER_TAB_LIST[0].name, - info: {}, - }; - - private updateInfo() { - chrome.devtools.inspectedWindow.eval( - `JSON.stringify(function (){ - const thisWindow = window.__MICRO_APP_PROXY_WINDOW__ || window; - const allKey = JSON.stringify(Object.keys(thisWindow)); - let microAppInfo = {}; - for (let el of JSON.parse(allKey)){ - if (el.indexOf('__MICRO_APP') > -1 && ['__MICRO_APP_WINDOW__', '__MICRO_APP_SANDBOX__'].indexOf(el) == -1){ - microAppInfo[el] = thisWindow[el]; - } - } - return microAppInfo; - }())`, - (res: string) => { - if (res && res !== 'undefined' && res !== 'null') { - const env = decodeJSON(res); - if (env) { - this.setState({ info: { currentMicroApp: { env } } }); - } - } - }, - ); - } - - private updateColorTheme() { - if (chrome.devtools.panels.themeName === 'dark') { - window.document.documentElement.style.setProperty('--color-border-primary', '#494c50'); - window.document.documentElement.style.setProperty('--color-text-primary', '#ffffff'); - window.document.documentElement.style.setProperty('--color-text-secondary', '#9aa0a6'); - window.document.documentElement.style.setProperty('--color-background-primary', '#242424'); - window.document.documentElement.style.setProperty('--color-background-primary-active', '#000000'); - window.document.documentElement.style.setProperty('--color-background-primary-hover', '#35363a'); - } else { - window.document.documentElement.style.setProperty('--color-border-primary', '#cacdd1'); - window.document.documentElement.style.setProperty('--color-text-primary', '#000000'); - window.document.documentElement.style.setProperty('--color-text-secondary', '#5f6368'); - window.document.documentElement.style.setProperty('--color-background-primary', '#f1f3f4'); - window.document.documentElement.style.setProperty('--color-background-primary-active', '#ffffff'); - window.document.documentElement.style.setProperty('--color-background-primary-hover', '#dee1e6'); - } - } - - public componentDidMount(): void { - this.updateColorTheme(); - this.updateInfo(); - } - - public componentDidUpdate(): void { - this.updateColorTheme(); - this.updateInfo(); - } - - /* - * According to tab Switch content - * - */ - private renderContent() { - switch (this.state.activeTab) { - case 'ENV_VALUE_VIEWER': - return ; - case 'COMMUNICATE': - return ; - case 'VIEW_APP': - return ; - case 'ROUTE_MATCH': - return ; - case 'CONSOLE': - return ; - default: - return null; - } - } - - public render() { - return ( -
- { this.setState({ activeTab: value }); }} /> - { this.renderContent() } -
- ); - } -} - -export default DevToolsPage; diff --git a/src/pages/devtoolsBackup/types.ts b/src/pages/devtoolsBackup/types.ts deleted file mode 100644 index 6d0c0b3..0000000 --- a/src/pages/devtoolsBackup/types.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Micro app information for dev tools - */ -export interface DevToolsMicroAppInfo { - env: { - __MICRO_APP_ENVIRONMENT__: boolean; - __MICRO_APP_NAME__: string; - __MICRO_APP_PUBLIC_PATH__: string; - __MICRO_APP_BASE_ROUTE__: string; - __MICRO_APP_BASE_APPLICATION__: boolean; - }; -} - -/** - * Shared data and methods cross dev tools components (light redux, main bus) - */ -export interface DevToolsInfo { - currentMicroApp?: DevToolsMicroAppInfo; -} - -export interface MicroAppsInfos { - title: string; - key: string; - children: MicroAppsInfos[]; -} diff --git a/src/scripts/content/index.ts b/src/scripts/content/index.ts index 29e9332..c338984 100644 --- a/src/scripts/content/index.ts +++ b/src/scripts/content/index.ts @@ -2,6 +2,11 @@ import * as logger from '@/utils/logger'; import { printLine } from './modules/print'; +interface CustomWindow extends Window { + originalStyles: Map; + setLightingStyle: Element[]; +} + logger.debug('Content script works!'); logger.debug('Must reload extension for modifications to take effect.'); @@ -51,26 +56,34 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { } const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']; const defaultColor = 'black'; - const originalStyles = new Map(); // Initial style used to save elements + (window as unknown as CustomWindow).originalStyles = new Map(); + (window as unknown as CustomWindow).setLightingStyle = []; microApps.forEach((microApp, index) => { if (microApp) { if (request.action === 'openView') { const color = index < colors.length ? colors[index] : defaultColor; const originalStyle = microApp.getAttribute('style'); // get initial style - originalStyles.set(microApp, originalStyle); // save initial style - (microApp as HTMLElement).style.border = `2px solid ${color}`; + if (!(window as unknown as CustomWindow).setLightingStyle.includes(microApp) && !(window as unknown as CustomWindow).originalStyles.get(microApp)) { + (window as unknown as CustomWindow).setLightingStyle.push(microApp); + (window as unknown as CustomWindow).originalStyles.set(microApp, originalStyle as string); + } + (microApp as HTMLElement).style.border = `2px dashed ${color}`; // fix some parent div setting display: contents cause border colors cannot be displayed (microApp as HTMLElement).style.display = 'block'; // add transform is because some border colors cannot be displayed (microApp as HTMLElement).style.transformOrigin = 'center'; (microApp as HTMLElement).style.transform = 'rotate(360deg)'; + (microApp as HTMLElement).dataset.lighting = '1'; + (microApp as HTMLElement).dataset.lightingColor = color; } else if (request.action === 'closeView') { - const originalStyle = originalStyles.get(microApp); // get save elements + const originalStyle = (window as unknown as CustomWindow).originalStyles.get(microApp); // get save elements if (originalStyle) { microApp.setAttribute('style', originalStyle); // set save elements } else { microApp.removeAttribute('style'); // if there is no initial style, remove all inline styles } + delete (microApp as HTMLElement).dataset.lighting; + delete (microApp as HTMLElement).dataset.lightingColor; } } });