yylib-quick-mobile
Version:
yylib-quick-mobile
439 lines (431 loc) • 16.9 kB
JavaScript
/**
* Created by Dio on 2016/9/3.
*/
var React = require('react');
var DefaultParams= {};
var DefaultActions={};
var TreeUtils = require('../../utils/TreeUtils');
var ViewMeta =require('./ViewMeta') ;
var DataUtil = {};
var RUN_MODE_DESIGN = 'design';
var theme=require('./theme.less');
var {deepClone}=require('../../utils/FunctionUtil')
var JsPluginUtils=require('../../utils/JsPluginUtils');
var _ = require('lodash');
//是否存在运行参数表达式
var hasParamPatten=function(str){
var patten = new RegExp('!\{.+}', 'gm');
return patten.test(str);
};
//缓存权限按钮
var authorityButtons=function(appCode,pageCode){
return null
};
var YYCreateView = React.createClass({
statics:{
RUN_MODE_DESIGN:RUN_MODE_DESIGN//运行设计态
},
getDefaultProps:function(){
return {
appCode:null,
pageCode:null,
billTypeCode:null,
uiMeta:null,//UI元数据
uiParser:null,//UI组件解析器
uiEvent:null,//UI事件处理器
uiParams:null,//UI参数解析器
uiRunMode:null//运行模式,默认为运行态,设计态-"design"
}
}
,getInitialState:function(){
var uiParams = this._processUIParams(this.props.uiParams);
var uiParser = this._processUIParser(this.props.uiParser);
var uiEvent = this._processUIEvent(this.props.uiEvent);
var uiMeta = this._processUIMeta(this.props.uiMeta);
return {
uiParams,uiMeta,uiParser,uiEvent,
refreshTime:0//记录刷新次数
}
}
,componentWillReceiveProps(nextProps){
if(('uiParams' in nextProps)||('uiParser' in nextProps)||('uiEvent' in nextProps)||('uiMeta' in nextProps)){
var uiParams = this._processUIParams(nextProps.uiParams);
var uiParser = this._processUIParser(nextProps.uiParser);
var uiEvent = this._processUIEvent(nextProps.uiEvent);
var uiMeta = this._processUIMeta(nextProps.uiMeta);
this.setState({
uiParams,uiMeta,uiParser,uiEvent
,refreshTime:this.state.refreshTime+1
});
}
}
//性能优化,只有当refreshTime发生变更时才触发执行render方法
,shouldComponentUpdate:function(nextProps,nextState){
return this.state.refreshTime!=nextState.refreshTime;
}
,componentWillMount:function(){
var {uiMeta,uiEvent} = this.state;
JsPluginUtils.init({page:this,uiEvent:uiEvent});//初始化
this._callEvent('onViewWillMount',{uiMeta,uiEvent});
}
,componentDidMount:function(){
var {uiMeta,uiEvent} = this.state;
this._callEvent('onViewDidMount',{uiMeta,uiEvent});
}
,componentWillUpdate:function(nextProps,nextState){
var {uiMeta,uiEvent} = nextState;
this._callEvent('onViewWillUpdate',{uiMeta,uiEvent});
}
,componentDidUpdate:function(prevProps,prevState){
var {uiMeta,uiEvent} = prevState;
this._callEvent('onViewDidUpdate',{uiMeta,uiEvent});
}
//回调指定的事件
,_callEvent:function(eventName,{uiMeta,uiEvent}){
if(!uiMeta||!uiEvent)return;
for(var uikey in uiEvent){
var itemEvents = uiEvent[uikey];
if(itemEvents&&(typeof itemEvents[eventName]=="function")){
var itemUI = this._findUI({uiMeta,uikey});//匹配到组件才调用事件
if(itemUI){
try{
var _itemUI = itemEvents[eventName].call(this,{uiMeta,item:itemUI});
if(_itemUI)itemUI = _itemUI;
}catch(err){
console.error('[事件回调失败]'+uikey+'.'+eventName,err);
}
}
}
}
}
//环境参数助手方法
,_processUIParams:function(uiParams){
var _uiParams = Object.assign({},DefaultParams,uiParams);
for(var key in _uiParams){
let param = _uiParams[key];
if(param&&typeof param=="function"){//处理函数类型的动态参数
_uiParams[key]=param.call(this);
}
}
return _uiParams;
}
//元数据助手方法
,_processUIMeta:function(uiMeta){
var _uiMeta = uiMeta;
return _uiMeta;
}
//解析器助手方法
,_processUIParser:function(uiParser){
var _uiParser = Object.assign({},this.props.parserControl,uiParser);
return _uiParser;
}
//事件助手方法
,_processUIEvent:function(uiEvent){
//注意此次需要克隆,以防止引用共享
var copyDefault = {};
var copyUiEvent = deepClone(uiEvent);
var _uiEvent = Object.assign(copyDefault,copyUiEvent);
for(var uikey in _uiEvent){
var itemEvents = _uiEvent[uikey];
for(var name in itemEvents){
try{
itemEvents[name]=itemEvents[name].bind(this);
}catch(err){
console.error('[绑定事件失败]'+uikey+'.'+name+',检查是否为有效的Function',err);
}
}
}
return _uiEvent;
}
/**
* 刷新重绘页面
*/
,refresh:function(callback,state){
this.setState(Object.assign({refreshTime:this.state.refreshTime+1},state),callback);
}
/**
* 获取当前页面
*/
,getPage:function(){
var that = this;
return that;
}
/**
* 获取应用编码
*/
,getAppCode:function(){
return this.props.appCode;
}
/**
* 获取页面编码
*/
,getPageCode:function(){
return this.props.pageCode;
},
/***
* 获取页面路径
* ***/
getJsPluginUrl:function(){
return this.props.pluginUrl;
}
/**
* 获取页面单据类型
*/
,getBillTypeCode:function(){
return this.props.billTypeCode;
}
/**
* 路由到指定页面
* @param url 路由路径
* @param query URL附加的参数(显示参数)
* @param state 路由附加的参数(隐藏参数)
*/
,routeTo:function(url,query,state){
if(!this.props.router){console.error('调用routeTo失败,router不存在');return}
var location = {};
if(url)location.pathname=url;
if(query)location.query=query;
if(state)location.state=state;
//this.props.history.push(url,_params);
// this.props.history.push(location);
this.props.router.push(location); // Router版本升级修改
},
isEmpty:function(params){
if(!params||params==""){
return true;
}
return false;
}
/**
* 获取路由传递的参数值(隐藏参数)
*/
,getRouteParams:function(){
if(!this.props.location&&!this.props.params){console.error('调用getRouteParams失败,location和params均不存在');return}
return _.isEmpty(this.props.location.state)?(_.isEmpty(this.props.params)?null:this.props.params):this.props.location.state;
}
/**
* 获取路由传递的URL参数值(直接链接在URL的?后面的参数列表)(显示参数)
*/
,getRouteQuery:function(){
if(!this.props.location){console.error('调用getRouteQuery失败,location不存在');return}
return _.isEmpty(this.props.location.query)?null:this.props.location.query;
}
/**
* 后退上一个页面
*/
,goBack:function(){
if(!this.props.router){console.error('调用goBack失败,router不存在');return}
this.props.router.goBack();
}
/**
* 前进下一个页面
*/
,goForward:function(){
if(!this.props.router){console.error('调用goForward失败,router不存在');return}
this.props.router.goForward();
}
/**
* 后退或前进到第N个页面
* @param to n为正数则为前进,n为负数则为后退
*/
,goTo:function(to){
if(!this.props.router){console.error('调用goTo失败,router不存在');return}
this.props.router.go(to);
}
/**
* 通过键值查找UI对象模型
* @param uikey
*/
,findUI:function(uikey){
if(this.state.uiMeta){
var result = this._findUI({uiMeta:this.state.uiMeta,uikey:uikey});
if(!result)console.warn('[api.findUI]找不到:'+uikey);
return result;
}
return null;
}
,_findUI:function(options){
var {uiMeta,uikey}=options;
var _uiMeta = (uiMeta&&uiMeta.constructor==Array)?uiMeta:[uiMeta];
var results = TreeUtils.findWithPropName(_uiMeta,'uikey',uikey,true,true);
if(results&&results.length>0){
results[0].api=this._findByRef(results[0].nid);//扩展API对象
return results[0];
}
return null;
}
/**
* 通过类型查找UI数据模型
* @param uitype 解析器名称
*/
,findUIByType:function(uitype){
if(this.state.uiMeta){
var _uiMeta = (this.state.uiMeta&&this.state.uiMeta.constructor==Array)?this.state.uiMeta:[this.state.uiMeta];
var results = TreeUtils.findWithPropName(_uiMeta,'uitype',uitype,true,false);
if(results&&results.length>0){
var that = this;
results.forEach(function(item,index){
results[index].api=that._findByRef(item.nid);//扩展API对象
});
return results;
}
}
return null;
}
//ref值指向nid值
,_findByRef:function(ref){
//TODO 目前存在缺陷,在折叠卡片页签第一次未展开时,无法通过refs获取内部组件
return ref&&this.refs[ref]?this.refs[ref]:null;
}
/**
* 通过键值查找UI组件实例
* @param uikey
*/
,findComp:function(uikey){
if(this.state.uiMeta){
var _uiMeta = (this.state.uiMeta&&this.state.uiMeta.constructor==Array)?this.state.uiMeta:[this.state.uiMeta];
var results = TreeUtils.findWithPropName(_uiMeta,'uikey',uikey,true,true);
return this._findByRef(results.length>0?results[0].nid:null);
}
return null;
}
//环境参数替换
,_processParams:function(node){
var uiParams = this.state.uiParams;
if(this.isEmpty(uiParams))return;
if(!node)return;
var keys = [];
//过滤出包含运行参数的属性
for(var key in node) {
var value = node[key];
if(value&&typeof value=="string"&&hasParamPatten(value)){
keys.push(key);
};
}
//进行运行参数替换
if(keys.length==0)return;
for(var idx in keys){
var propName = keys[idx];
var propValue = node[propName];
if(!propValue)break;
for(let paramKey in uiParams){
node[propName] = propValue.replace(new RegExp('!\{' + paramKey+ '}', 'gm'),uiParams[paramKey]);
if(!hasParamPatten(node[propName]))break;//性能优化,如果替换一次后,就不存在需要替换的参数则跳过本次。
}
}
}
//获取解析后的视图
,_getViewContent:function(options){
//console.log('第'+this.state.refreshTime+'次进行视图解析');
var {uiMeta,uiEvent,uiParser} = options;
var views = null;
if(uiMeta){
if(uiMeta&&uiMeta.constructor==Array){
views = this._processViews(uiMeta,uiEvent,uiParser);
}else{
let offline=uiMeta.offline?true:false;
window.offline_flag=offline;//全局离线标记
views = this._processViews([uiMeta],uiEvent,uiParser,offline);
}
}
if(views&&views.length>0){
return (uiMeta&&uiMeta.constructor==Array)?views:views[0];
}else{
return null;
}
}
//解析视图
,_processViews:function(items,uiEvent,uiParser,offline,parentType){
if(items.constructor&&(!items.constructor==Array))return null;
var views=[];
var {uiRunMode,appCode,pageCode,billTypeCode} = this.props;
var that = this;
var {pageCode,RunInDesign} = this.props;
for(var i=0;i<items.length;i++){
var itemUI = items[i];
if(!itemUI||this.isEmpty(itemUI))continue;
//解析子视图
var childView = itemUI.children;
var doEachChild = (itemUI.children&&itemUI.children.constructor==Array);
if(doEachChild){
childView = this._processViews(itemUI.children,uiEvent,uiParser,offline,itemUI.uitype);
}
//解析视图事件
var itemEvents = null;
if(itemUI.uikey&&uiEvent){
itemEvents = uiEvent[itemUI.uikey];
}
//解析事件动作
if(itemUI.uievents){
if(!itemEvents)itemEvents={};
//解析绑定的所有事件
itemUI.uievents.forEach(function(uiactions,uievent){
//解析对应事件下的动作列表
itemEvents[uievent]=function(ui,event,actions){
for(var actSeq=0;actSeq<actions.length;actSeq++){
var action = actions[actSeq];
//获取动作函数
var actionFunc = DefaultActions[action.uiaction];
//执行动作处理
if(typeof actionFunc=='function'){
actionFunc.call(this,{event,action,ui});
}
}
}.bind(that,itemUI,uievent,uiactions);
});
}
//解析当前组件
var UIComponent = itemUI.uitype?uiParser[itemUI.uitype]:null;
//清理掉API对象
delete itemUI.api;
//当前组件属性
var itemProps = Object.assign({
//为所有组件追加uiorigin属性,本属性提供了界面设计器解析构建页面时的特有属性
uiorigin:{appCode,pageCode,billTypeCode},
RunInDesign:RunInDesign
},itemUI);
//环境参数替换
this._processParams(itemProps);
//标识运行模式
if(uiRunMode)itemProps.uiRunMode = uiRunMode;
//添加到视图集合,当uidisabled==true时,则不进行组件解析,返回原始数据。
if(itemUI.uidisabled==true){//不进行组件解析
views.push(itemProps);
}else if(UIComponent){//存在相关组件解析器
//将当前UI元数据绑定到组件的ui属性
var privateProps = {};
if(itemUI.nid){
privateProps.ref = itemUI.nid;
if(!itemUI.key){
privateProps.key = pageCode+"_"+itemUI.nid;
}
}
var itemView = React.createElement(UIComponent,Object.assign({findUI:this.findUI,offline:offline,parentType:parentType},itemProps,privateProps,itemEvents),childView);
//处理视图是否拥有权限
var hasAuth = this.isHasAuthorityView(itemUI.uikey);
if(hasAuth){
views.push(itemView);
}
}else{//不存在相关组件解析器则返回包含元数据的空视图组件
var viewMeta = React.createElement(ViewMeta,itemProps);
views.push(viewMeta);
}
}
return views;
}
//指定uikey键值的视图组件是否有权限
,isHasAuthorityView:function(uikey){
// var {appCode,pageCode} = this.props;
// var buttons = authorityButtons(appCode,pageCode);
// var btn = buttons&&buttons.length>0?_.find(buttons, ['btnCode', uikey]):null;
// return btn?btn.enable:true;
return true;
}
,render: function() {
var {uiMeta,uiParser,uiEvent} = this.state;
//获取解析后的视图
var viewContent = this._getViewContent({uiMeta,uiParser,uiEvent});
return viewContent;
}
});
module.exports = YYCreateView;