UNPKG

yylib-quick-mobile

Version:

yylib-quick-mobile

439 lines (431 loc) 16.9 kB
/** * 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;