mutants-appfx
Version:
appfx module
229 lines (211 loc) • 6.17 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import Alert from 'mutants-microfx/dist/components/Alert';
import appManager from '../AppManager';
import UILoading from '../components/UILoading';
import './style.less';
import {
findActions
} from '../controllers/eventPath';
import {
observer
} from 'mutants-microfx';
class TemplateView extends React.Component {
static propTypes = {
pid: PropTypes.string.isRequired,
sysid: PropTypes.string.isRequired,
mid: PropTypes.string.isRequired,
id: PropTypes.string,
view: PropTypes.func.isRequired,
viewModel: PropTypes.object.isRequired,
app: PropTypes.object.isRequired,
handleEvent: PropTypes.func.isRequired,
}
static childContextTypes = {
pid: PropTypes.string,
sysid: PropTypes.string,
mid: PropTypes.string,
id: PropTypes.string,
onEvent: PropTypes.func,
viewModel: PropTypes.object,
appState: PropTypes.object,
display: PropTypes.bool,
}
getChildContext() {
return {
pid: this.props.pid,
sysid: this.props.sysid,
mid: this.props.mid,
id: this.props.id,
viewModel: this.props.viewModel,
onEvent: this.props.handleEvent,
appState: this.props.app.state,
display: this.props.pid === this.props.app.pid,
};
}
render() {
const props = {
pid: this.props.pid,
sysid: this.props.sysid,
mid: this.props.mid,
id: this.props.id,
viewModel: this.props.viewModel,
onEvent: this.props.handleEvent,
appState: this.props.app.state,
display: this.props.pid === this.props.app.pid,
}
return <this.props.view {...props}/>
}
}
export default class TemplateProvider extends React.Component {
static propTypes = {
pid: PropTypes.string,
sysid: PropTypes.string,
mid: PropTypes.string.isRequired,
id: PropTypes.string,
}
state = {
loading: true
}
async openApp() {
if (this.state.sysid === this.sysid &&
this.state.mid === this.mid &&
this.state.pid === this.pid) {
return;
}
this.sysid = this.state.sysid;
this.mid = this.state.mid;
this.pid = this.state.pid;
let state;
UILoading.show();
try {
const app = await appManager.open(this.props)
state = {
loading: false,
app
}
UILoading.destroy();
} catch (err) {
console.error(err);
state = {
error: err.message,
loading: false
}
UILoading.destroy();
}
this.setState(state);
}
// static getDerivedStateFromProps(nextProps, prevState) {
// if (prevState.sysid != nextProps.sysid ||
// prevState.mid != nextProps.mid ||
// (prevState.pid != nextProps.pid)) {
// return {
// sysid: nextProps.sysid,
// mid: nextProps.mid,
// pid: nextProps.pid,
// loading: true,
// error: null,
// }
// }
// return null;
// }
constructor(props) {
super();
this.state.sysid = props.sysid;
this.state.mid = props.mid;
this.state.pid = props.pid;
}
componentWillReceiveProps(nextProps) {
if (this.state.sysid != nextProps.sysid ||
this.state.mid != nextProps.mid ||
(this.state.pid != nextProps.pid)) {
this.setState({
sysid: nextProps.sysid,
mid: nextProps.mid,
pid: nextProps.pid,
loading: true,
error: null,
})
}
}
componentDidMount() {
this.openApp().catch(err => console.error(err));
}
componentDidUpdate() {
this.openApp().catch(err => console.error(err));
}
handleEvent = async (viewitem, name, args) => {
const app = this.state.app;
if (!app) {
return;
}
const eid = await app.pushEvent(name);
try {
// 执行元数据配置的行为
const action = viewitem && viewitem[name];
if (action) {
await app.executeAction(action.name, {
...action.toJS().args,
...args
});
}
// 支持controller的eventPath
const actions = new Set(findActions(app.viewController, name).concat(findActions(app.controller, name)));
for (const it of actions) {
await app.executeAction(it, {
...args
});
}
// 触发事件规则
if (viewitem) {
await app.triggerEvent(viewitem.name + '.' + name, {
...args
});
}
await app.popEvent(eid);
} catch (err) {
await app.popEvent(eid);
throw err;
}
}
render() {
// 加载中保持界面不变,减少闪烁
const app = this.state.app;
if (!app) {
if (this.state.error) {
return <Alert message={this.state.error}/>
}
return null;
}
// const views = appManager.apps.values().reduce((views, app) => views.concat(app.views.slice().map((it, i) => ({
// ...it,
// sysid: app.module.sysid,
// mid: app.module.mid,
// viewModel: app.viewModels[i].viewModel,
// state: app.state.toJS(),
// app,
// }))), []);
// return (<div className='app'>
// {this.state.error?<Alert message={this.state.error}/>:null}
// {views.map((it)=>{
// return <div key={it.iid} id={it.mid+'_'+it.pid+'_'+it.iid} className='view' style={{display:it.iid===app.iid?'block':'none'}}>
// <TemplateView {...it.state} mid={it.mid} sysid={it.sysid} pid={it.pid} app={it.app} id={it.app.loadedId}
// viewModel={it.viewModel} view={it.view}
// handleEvent={this.handleEvent} />
// </div>
// })}
// </div>)
const views = app.views;
return (<div className='app'>
{this.state.error?<Alert message={this.state.error}/>:null}
{views.map((it,i)=>{
return <div key={it.pid+'_'+it.iid} id={it.pid+'_'+it.iid} className='view' style={{display:it.iid===app.iid?'block':'none'}}>
<TemplateView {...this.props} pid={it.pid} app={app}
viewModel={app.viewModels[i].viewModel} view={it.view}
handleEvent={this.handleEvent} />
</div>
})}
</div>)
}
}