Commit de0be0e4 by zhaochengxiang

qiankun

parent 2be49a33
PORT=3008
\ No newline at end of file
const CracoLessPlugin = require('craco-less');
const { name } = require('./package');
module.exports = {
plugins: [
......@@ -7,11 +8,32 @@ module.exports = {
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: { },
modifyVars: {
'@ant-prefix': 'yy',
},
javascriptEnabled: true,
},
},
},
},
],
webpack: {
configure: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
globalObject: 'window',
}
}
},
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
// historyApiFallback: true,
// hot: false,
// watchContentBase: false,
// liveReload: false,
},
};
\ No newline at end of file
{
"name": "my-app",
"name": "data-govern",
"version": "0.1.0",
"private": true,
"dependencies": {
......@@ -38,7 +38,10 @@
"extends": [
"react-app",
"react-app/jest"
]
],
"rules": {
"jsx-a11y/anchor-is-valid": "off"
}
},
"browserslist": {
"production": [
......
import React from 'react';
import {
BrowserRouter as Router,
Route, Switch, Redirect
Route, Switch
} from 'react-router-dom';
import { ContextPath } from './util';
......@@ -9,18 +9,20 @@ import Signin from './view/Signin';
import Home from './view/Home';
import Manage from './view/Manage';
import Map from './view/Manage/Map';
import Model from './view/Manage/Model';
export default class App extends React.Component {
render() {
return (
<React.Fragment>
<Router>
<Router basename={window.__POWERED_BY_QIANKUN__ ? '/data-govern' : '/'}>
<Switch>
<Route path={`${ContextPath}/login`} component={Signin} exact />
<Route path={`${ContextPath}/home`} component={Home} />
<Route path={`${ContextPath}/data-map`} component={Map} exact />
<Route path={`${ContextPath}/manage`} component={Manage} />
<Route component={() => <Redirect to={`${ContextPath}/login`} />}/>
<Route path={`/center-home/view/modelmap`} component={Map} exact />
<Route path={`/center-home/view/datamodel`} component={Model} exact />
</Switch>
</Router>
</React.Fragment>
......
import "core-js/stable";
import "regenerator-runtime/runtime";
import React, { Suspense, lazy } from 'react';
import React from 'react';
import ReactDOM from 'react-dom';
import { ConfigProvider } from 'antd';
import zh_CN from 'antd/es/locale-provider/zh_CN';
import { Provider } from "react-redux";
import { store } from './model';
import App from './App'
import './index.less';
const App = lazy(() => import("./App"));
const app = (
<ConfigProvider locale={zh_CN}>
<Suspense fallback={<div className="text-center">正在加载界面...</div>}>
<Provider store={store}><App /></Provider>
</Suspense>
//解决主次应用样式冲突
//https://qiankun.umijs.org/faq#how-to-guarantee-the-main-app-stylesheet-isolated-with-sub-apps
<ConfigProvider locale={zh_CN} prefixCls="yy">
<Provider store={store}><App /></Provider>
</ConfigProvider>
);
ReactDOM.render(app, document.getElementById('root'));
\ No newline at end of file
function render(props) {
const { container } = props;
ReactDOM.render(app, container ? container.querySelector('#root') : document.querySelector('#root'));
}
function storeTest(props) {
props.onGlobalStateChange((value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev), true);
props.setGlobalState({
ignore: props.name,
user: {
name: props.name,
},
});
}
if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('[data-govern] react app bootstraped');
}
export async function mount(props) {
console.log('[data-govern] props from main framework', props);
storeTest(props);
render(props);
}
export async function unmount(props) {
const { container } = props;
ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}
\ No newline at end of file
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
......@@ -88,11 +88,8 @@ export const SetSource = function (source) {
const callback = resp => {
if (resp.status === 401) {
message.warning("session过期,请重新登录!");
if (window.parent) {
window.parent.postMessage('session invalid');
}
message.warning("session过期,请重新登录!");
window.location.href="/center-home/view/login"
return null;
}
else if (resp.status !== 200) {
......
import React from 'react';
import G6 from '@antv/g6';
import { ContextPath } from '../../../../util';
// import { ContextPath } from '../../../../util';
let graph = null;
......@@ -32,7 +32,7 @@ const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
class Org extends React.Component {
componentDidMount() {
const { type, loadMoreData, history } = this.props;
const { type, loadMoreData } = this.props;
const container = document.getElementById(`container${type||''}`);
if (!container) return;
......
import React from 'react';
import G6 from '@antv/g6';
import { ContextPath } from '../../../../util';
// import { ContextPath } from '../../../../util';
const colors = [
'#BDD2FD',
......@@ -43,7 +43,7 @@ let graph = null;
class Relation extends React.Component {
componentDidMount() {
const { type, loadMoreData , history } = this.props;
const { type, loadMoreData } = this.props;
setTimeout(() => {
const container = document.getElementById(`container${type||''}`);
......
import React from 'react';
import G6 from '@antv/g6';
import { ContextPath } from '../../../../util';
// import { ContextPath } from '../../../../util';
let graph = null;
const globalFontSize = 20;
......@@ -31,7 +31,7 @@ const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
class Tree extends React.Component {
componentDidMount() {
const { type, loadMoreData, history } = this.props;
const { type, loadMoreData } = this.props;
const container = document.getElementById(`container${type||''}`);
if (!container) return;
......
import React, { useState, useCallback, useRef } from 'react';
import { Table, Input, Form, Typography, Divider, Button, Select } from 'antd';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
const { Option } = Select;
const type = 'DragableBodyRow';
const modes = [
'主键索引',
'唯一索引',
'普通索引',
'组合索引',
'全文索引'
];
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
fileds,
record,
index,
children,
...restProps
}) => {
let inputNode = <Input />;
if (inputType==='select') {
inputNode = (
<Select>
{
modes && modes.map((mode, index) => {
return (
<Option key={mode}>{mode}</Option>
);
})
}
</Select>
)
} else if (inputType === 'select-multiple') {
inputNode = (
<Select mode="multiple">
{
fileds && fileds.map((filed, index) => {
return (
<Option key={filed}>{filed}</Option>
)
})
}
</Select>
)
}
return (
<td {...restProps}>
{editing ? (
<Form.Item
name={dataIndex}
style={{
margin: 0,
}}
rules={[
{
required: true,
message: `请输入${title}!`,
},
]}
>
{inputNode}
</Form.Item>
) : (
children
)}
</td>
);
};
const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) => {
const ref = useRef();
const [{ isOver, dropClassName }, drop] = useDrop(
() => ({
accept: type,
collect: monitor => {
const { index: dragIndex } = monitor.getItem() || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: item => {
if (moveRow) {
moveRow(item.index, index);
}
},
}),
[index],
);
const [, drag] = useDrag(
() => ({
type,
item: { index },
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
}),
[index],
);
drop(drag(ref));
return (
<tr
ref={ref}
className={`${className}${isOver ? dropClassName : ''}`}
style={{ cursor: 'move', ...style }}
{...restProps}
/>
);
};
const ImportActionIndex = (props) => {
const { data, fileds, onChange } = props;
const [form] = Form.useForm();
const [editingKey, setEditingKey] = useState('');
const [suggests, setSuggests] = useState([]);
const isEditing = (record) => record.key === editingKey;
const onAddClick = () => {
const newData = [{}, ...data];
(newData||[]).forEach((item, index) => {
item.key = index.toString();
})
onChange && onChange(newData);
edit(newData[0]);
}
const edit = (record) => {
form.setFieldsValue({
name: '',
mode: '',
fileds: [],
...record,
});
setEditingKey(record.key);
};
const remove = (record) => {
const newData = [...data];
const index = newData.findIndex((item) => record.key === item.key);
newData.splice(index, 1);
onChange && onChange(newData);
}
const cancel = () => {
const newData = [...data];
const item = newData[editingKey];
if (!item.name || item.name==='') {
newData.splice(editingKey, 1);
onChange && onChange(newData);
}
setEditingKey('');
};
const save = async () => {
try {
await form.validateFields();
const _suggests = [
{
name: '建议1'
},
{
name: '建议2'
}
];
setSuggests(_suggests)
if (_suggests.length === 0) {
constraintSave();
}
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
};
const constraintSave = async () => {
const row = await form.validateFields();
//test
row.key = '-1';
const newData = [...data];
const index = newData.findIndex((item) => editingKey === item.key);
if (index > -1) {
const item = newData[index];
newData.splice(index, 1, { ...item, ...row });
} else {
newData.push(row);
}
onChange && onChange(newData);
setEditingKey('');
setSuggests([]);
}
const columns = [
{
title: '序号',
dataIndex: 'key',
editable: false,
render: (text, record, index) => {
return (index+1).toString();
}
},
{
title: '索引名称',
dataIndex: 'name',
editable: true,
},
{
title: '索引类型',
dataIndex: 'mode',
editable: true,
},
{
title: '索引字段列表',
dataIndex: 'fileds',
editable: true,
},
{
title: '操作',
dataIndex: 'action',
render: (_, record) => {
const editable = isEditing(record);
return editable ? (
<>
<Typography.Link className='mr-3' disabled={editingKey === ''} onClick={() => save()}>
保存
</Typography.Link>
<Typography.Link disabled={editingKey === ''} onClick={() => {cancel()}}>
取消
</Typography.Link>
</>
) : (
<>
<Typography.Link className='mr-3' disabled={editingKey !== ''} onClick={() => edit(record)}>
编辑
</Typography.Link>
<Typography.Link disabled={editingKey !== ''} onClick={() => remove(record)}>
删除
</Typography.Link>
</>
);
},
},
];
const mergedColumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType: (col.dataIndex==='fileds') ? 'select-multiple' : (col.dataIndex==='mode'?'select':'text'),
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
fileds: fileds||[]
}),
};
});
const moveRow = useCallback(
(dragIndex, hoverIndex) => {
const dragRow = data[dragIndex];
const newData = update(data, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRow],
],
});
onChange && onChange(newData);
},
//eslint-disable-next-line react-hooks/exhaustive-deps
[data],
);
return (
<>
<Divider>数据表索引</Divider>
<div className='d-flex mb-3'>
<Button type="primary" onClick={onAddClick} style={{ marginLeft: 'auto' }} disabled={ editingKey!=='' } >新增行</Button>
</div>
<DndProvider backend={HTML5Backend} >
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell,
//编辑状态下不允许拖动
row: editingKey===''?DragableBodyRow:null,
},
}}
onRow={(record, index) => {
if (editingKey!=='') return null;
return {
index,
moveRow
}
}}
dataSource={data}
columns={mergedColumns}
size='small'
rowClassName="editable-row"
pagination={false}
expandable={{
expandedRowRender: record => (
<>
{
editingKey!=='' && <>
{
suggests && suggests.length>0 && (
<>
<Divider orientation="left">建议</Divider>
<div className='mb-3 ml-7'>
{
suggests && suggests.map((suggest, index) => {
return (
<div key={index} className='mt-3'>{suggest.name||''}</div>
)
})
}
</div>
<Button className='mb-3 ml-7' type='primary' onClick={constraintSave}>强制保存</Button>
</>
)
}
</>
}
</>
),
expandIcon: ({ expanded, onExpand, record }) => {
return <></>;
},
rowExpandable: record => (editingKey!==''&&(suggests||[]).length>0),
expandedRowKeys: [editingKey]
}}
/>
</Form>
</DndProvider>
</>
);
};
export default ImportActionIndex;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment