UNPKG

yylib-quick-mobile

Version:

yylib-quick-mobile

615 lines (608 loc) 23.7 kB
/****测试数据******/ import React from 'react'; import ReactDOM from 'react-dom'; import YYModal from '../modal/YYModal'; import YYNavBar from '../navBar/YYNavBar'; import YYFormDev from '../form/YYFormDev'; import YYIcon from '../icon/YYIcon' import {WingBlank, Flex,PullToRefresh, List, ListView ,WhiteSpace,Modal,Toast,Switch,TextareaItem,Button } from 'antd-mobile'; import classnames from 'classnames'; import './YYRepeater.less'; import _ from 'lodash'; const Item = List.Item; const Brief = Item.Brief; class YYRepeater extends React.Component { //构造函数 constructor(props){ super(props); const dataSource = new ListView.DataSource({ rowHasChanged: (row1, row2) => { return (row1 !== row2) } }); this.state={ dataSource, isLoading: true, refreshing:true, data:[], initdata:[], footer:'', formModal:false,//显示表单层 isAdd:false,//是否新增 EditRow:{},//当前编辑行 count:0, delData:[] //删除数组 } } //渲染完成事件 componentDidMount() { let {RunInDesign}=this.props; if(RunInDesign){ //设计期强加一条记录 this.setData([{}]) } //如果有渲染 则进行此操作 setTimeout(()=>{ this.setState({isLoading:false,refreshing:false}); },300) } uuid(){ return new Date().getDate()+"_"+parseInt(Math.random()*100000000); } /*****点击事件******/ clickItem(row){ if(this.props.onClick){ this.props.onClick(row); } } /**右侧滑动栏的按钮方法--end*/ /*****生成一行数据*******/ createRow(rowData, sectionID, rowID, highlightRow){ let {customDraw,children,RunInDesign}=this.props; var cloneData=_.cloneDeep(rowData); if(customDraw){ if(RunInDesign){ return (<Item arrow="horizontal" multipleLine><Brief>您需要打开自定义渲染行事件,并在此事件中返回一个可渲染的组件对象</Brief></Item>) } else if(this.props.renderRow){ return (<div onClick={this.clickItem.bind(this,rowData)}>{this.props.renderRow(cloneData, sectionID, rowID, highlightRow)}</div>) } }else{ let itemControlData=this.getItemControlData(this.props.children); /*****重新赋值nid和uikey******/ Object.keys(itemControlData).map(key=>{ itemControlData[key]["uikey"]=itemControlData[key]["uikey"]+"_"+sectionID+"_"+rowID; itemControlData[key]["nid"]=itemControlData[key]["nid"]+"_"+sectionID+"_"+rowID; itemControlData[key]["ref"]=itemControlData[key]["uikey"]; itemControlData[key]["sys_front_id"]=rowData["sys_front_id"];//所有列表内的组件都拥有了唯一标识 itemControlData[key]["listDataChange"]=this.updateData;//自动保存 itemControlData[key]["_parent_obj"]=this; if(itemControlData[key].uitype=="YYFormDev"){ itemControlData[key].autoSave=true; } }) if(this.props.renderItem){ this.props.renderItem(cloneData,itemControlData);//调用函数处理 } /****调用迭代函数后进行渲染处理****/ let itemControls=this.getRenderControl(children,itemControlData,cloneData); return (<div className="yy-reperater-item" style={{"position":"relative"}} onClick={this.clickItem.bind(this,rowData)}>{itemControls}</div>); } } saveData(){ let {EditRow:{sys_front_id:sysID},isAdd}=this.state; if(sysID){ if(this.refs.ModalForm){ this.refs.ModalForm.validateFields((errors,values)=>{ let saveValue={...values};//保存的数据 if(errors){ Toast.info("请输入必填项!") }else{ if(isAdd){ //新增状态下 this.setAppendData([saveValue]);//添加数据到实体 }else{ this.updateData(sysID,saveValue,true);//第三个参数为CRUD的标记 crud情况下 列表是不可修改的 } this.setState({formModal:false});//隐藏表单 } }) } } } /***更新数据***/ updateData(sysID,valueOptions,crud){ if(sysID){ let {data}=this.state; if(data&&data.some(item=>item.sys_front_id==sysID)){ data.map((item)=>{ if(item.sys_front_id==sysID){ var rowState={} if(item.rowState!="add"){ rowState={rowState:"edit"} } Object.assign(item,valueOptions,rowState);//非新增态的数据就是更新 } }) if(crud){ this.setData(data,true);//自动保存 }else{ this.setState({data:data}); } } } } //删除数据方法 deleteDataAlert(row){ Modal.alert( "删除", "确定要删除这条记录吗?", [{ text: '取消' },{ text: '确定', onPress:() => {this.delData(row)} }]); } /***获取数据***/ getDataBlob(data){ let dataBlob={}; if(data&&data.length){ data.map(item=>{ dataBlob[item.sys_front_id]=item; }) } return dataBlob; } /****删除数据*****/ delData(data){ let {data:alldata,delData}=this.state; if(data&&Array==data.constructor){ data.map(item=>{ if(item.sys_front_id){ alldata.map((dataItem,index)=>{ if(dataItem.sys_front_id==item.sys_front_id){ //如果是 新增状态 如果是删除的话 直接物理删除数据 否则物理删除后将数据移入删除状态 if(dataItem.rowState!="add"){ delData.push(Object.assign(dataItem,{rowState:"del"})) } alldata.splice(index,1); } }) }else{ console.log("删除的记录缺少列表的唯一标识!") } }); }else if(typeof data=="object"){ alldata.map((dataItem,index)=>{ if(dataItem.sys_front_id==data.sys_front_id){ if(dataItem.rowState!="add"){ delData.push(Object.assign(dataItem,{rowState:"del"})) } alldata.splice(index,1); } }) } let ds= this.state.dataSource.cloneWithRows(this.getDataBlob(alldata),alldata.map(dataItem=>dataItem.sys_front_id)); this.setState({dataSource:ds,data:alldata,delData:delData}) } setData(parseData,notClear){ let data=_.cloneDeep(parseData);/****深拷贝数据***/ /*****生成唯一标志******/ if(data&&data.length){ data.map(item=>{ item.sys_front_id=this.uuid(); }); } if(!notClear){ this.setState({delData:[]});//清空删除缓冲区的数据 } let ds= this.state.dataSource.cloneWithRows(this.getDataBlob(data),data.map(dataItem=>dataItem.sys_front_id)); setTimeout(()=>{ this.setState({dataSource:ds,data:data,isLoading:false,refreshing:false}) },300) } setIsLoading(flag) { this.setState({isLoading:flag}); } //删除行 removeItem(row,event){ let {RunInDesign}=this.props; if(!RunInDesign){ event.stopPropagation();//阻止事件冒泡 this.deleteDataAlert(row);//删除行 } } //编辑行 editItem(row){ this.showFormModal(row); } //取消保存 cancelSave(){ this.setState({formModal:false});//隐藏弹层 } //弹层显示 showFormModal(row,isAdd){ let {childTable}=this.props; if(childTable){ this.setState({formModal:true,EditRow:row,isAdd:isAdd}); } } /****读取数据*****/ getData(){ var {data,delData}=this.state; let current= data.map(function(item,index){ return Object.assign({},item,{sys_front_id:null}) }) return current.concat(delData); } /***** * addBefore 在数据前面插入 * ******/ setAppendData(parseData,addBefore){ let data=_.cloneDeep(parseData);/****深拷贝数据***/ let {beforeData} = this.props; if(data&&data.length){ data.map(item=>{ if(!item.sys_front_id){ item.sys_front_id=this.uuid(); } item.rowState="add"; if (beforeData) { item = Object.assign(item,beforeData); } }) } let allData; if(!addBefore){ allData= this.state.data.concat(data); }else{ allData=data.concat(this.state.data); } let ds= this.state.dataSource.cloneWithRows(this.getDataBlob(allData),allData.map(dataItem=>dataItem.sys_front_id)); this.setState({dataSource:ds,data:allData,refreshing:false,isLoading:false}) } onRefresh(event){ this.setState({refreshing:true,isLoading:true}); if(this.props.onRefresh){ this.props.onRefresh(); }else{ setTimeout(()=>{ this.setState({ dataSource:this.state.dataSource.cloneWithRows(this.state.data), refreshing:false, isLoading:false, }); },300) } } onEndReached(event) { if(!this.props.onEndReached){ return false; } setTimeout(()=>{ this.setState({isLoading:true}); this.props.onEndReached(); },300); } getRenderControl(children,info,rowData){ let controls=[]; let {childTable}=this.props;//是否在CRUD中使用 Array.prototype.slice.call(children);//伪数组转化成数组 if(children&&children.length){ children.map((item,index)=>{ let {uikey,children:child}=item.props; let childView; //如果开启了子表模式 则进入到新的渲染类型中 if(childTable&&item.props.uitype=="YYFormDev"){ controls=controls.concat(this.getReadOnlyControl(item,rowData))//合并所有的组件 }else{ if(child&&child.length){ childView=this.getRenderControl(child,info,rowData); } controls.push(React.cloneElement(item,info[uikey],childView)) } }) } return controls; } getChild(value,data) { var values = []; data.map((item,index)=>{ value.map((rowItem,indx)=>{ if (item.value==rowItem) { values.push(item.label); } }); if (item.children&&item.children.length) { var child = this.getChild(value,item.children); if (child&&child.length) { values = values.concat(child); } } }); return values; } //获取只读类的组件 只处理表单设计器下的组件 此方法会在开启子表状态下 进行调用 getReadOnlyControl(formDev,rowData){ let ItemList=[]; if(formDev&&formDev.props.children){ if(this.props.renderChildItem&&this.props.renderChildItem(rowData,this)){ return this.props.renderChildItem(rowData,this);//渲染组件行数据 } return (<Item arrow="horizontal" thumb={<YYIcon onClick={this.removeItem.bind(this,rowData)} type='Delete' color="#ff6262" size="xxs" />} multipleLine onClick={this.editItem.bind(this,rowData)} extra='子表值' > 子表项 </Item>) } return ItemList; } //获取所有的组件数据 getItemControlData(children){ let data={}; children&&children.map((item)=>{ if(item.props.uikey){ data[item.props.uikey]=Object.assign({},item.props); if(item.props.children&&item.props.children.length){ let itemChildren=item.props.children; Array.prototype.slice.call(itemChildren);//伪数组转化成数组 let childControl=this.getItemControlData(itemChildren); Object.assign(data,childControl);/***赋值给当前组件对象***/ } } }) return data; } //获取弹层中的数据 当开启子表 点击子表项时触发 getFormControl(){ var _this=this; let {EditRow:row,formModal}=this.state; if(!formModal){ return null; } if(row){ let itemControlData=this.getItemControlData(this.props.children); itemControlData=_.cloneDeep(itemControlData); Object.keys(itemControlData).map(key=>{ itemControlData[key]["sys_front_id"]=row["sys_front_id"];//所有列表内的组件都拥有了唯一标识 itemControlData[key]["_parent_obj"]=this; if(itemControlData[key].uitype=="YYFormDev"){ itemControlData[key].disabled=false; itemControlData[key].autoSave=false; itemControlData[key].ref="ModalForm"; itemControlData[key].onViewDidMount=function(obj){ _.forEach(obj.props.children, function (formItem) { if ("YYDatePicker" === formItem.props.uitype||formItem.props.uityp=="YYCalendar") { // 日期组件或者日历 if(formItem.props.uitype=="YYCalendar"){ var calendarValue={}; if(row[formItem.props.startField]){ calendarValue[formItem.props.tartField]=new Date(row[formItem.props.startField]) } if(row[formItem.props.endField]){ calendarValue[formItem.props.endField]=new Date(row[formItem.props.endField]) } row[formItem.props.field]=calendarValue; }else{ if(row[formItem.props.field]&&!(row[formItem.props.field] instanceof Date)){ row[formItem.props.field] = row[formItem.props.field]&&row[formItem.props.field].replace(/\-/g,'/'); row[formItem.props.field] = new Date(row[formItem.props.field]); } } } else if("YYPicker" === formItem.props.uitype){ var values = row[formItem.field]; if(typeof values=="string"){ row[formItem.props.field]=values.split(',');//转化成数组形式 } } else if ("YYRefer" === formItem.props.uitype) { // 选择器 var values = row[formItem.props.field]; if (_.isPlainObject(values)) { // 单选 var cvalue = _.cloneDeep(values); // 值类型为对象 if ("id" !== formItem.id) { // 取code delete cvalue['id']; row[formItem.props.field] = cvalue; } } else if (_.isArray(values)) { // 多选 var cvalue = _.cloneDeep(values); // 值类型为对象 if ("id" !== formItem.props.id) { // 取code cvalue.map(function (value) { delete value['id']; }); row[formItem.props.field] = cvalue; } } } }); obj.props.form.setFieldsValue(row); } } }) let itemControls=this.getModalControl(this.props.children,itemControlData,row); return itemControls; } } //获取弹层组件内容 getModalControl(children,info,row){ let controls=[]; let {childTable}=this.props; Array.prototype.slice.call(children);//伪数组转化成数组 if(children&&children.length){ children.map((item,index)=>{ let {uikey,children:child}=item.props; let childView; if(child&&child.length){ childView=this.dealChildControl(child,info,row); } if(info[uikey]){ if(info[uikey].uitype=="YYFormDev"){ controls.push(React.createElement(YYFormDev,info[uikey],childView)) }else{ controls.push(React.cloneElement(item,info[uikey],childView)) } } }) } return controls; } dealChildControl(children,info,rowData){ let controls=[]; let {childTable}=this.props;//是否在CRUD中使用 Array.prototype.slice.call(children);//伪数组转化成数组 if(children&&children.length){ children.map((item,index)=>{ let {uikey,children:child}=item.props; let childView; //如果开启了子表模式 则进入到新的渲染类型中 if(child&&child.length){ childView=this.dealChildControl(child,info,rowData); } if(item.props.uitype=="YYImagePicker"){ let sourceType=rowData[uikey]?rowData[uikey]:this.uuid();//获取sourceType let source={...info[uikey].source,sourceType:sourceType};//imagepicker有两个属性包含sourcetype 都需要更新 let params={...info[uikey],sourceType:sourceType,source:source,inChild:true} controls.push(React.cloneElement(item,params)) }else{ controls.push(React.cloneElement(item,info[uikey],childView)) } }) } return controls; } //显示子组件弹层 getChildModal(){ let {navBarName}=this.props; let {formModal}=this.state; if(formModal){ return ( <YYModal fill popup visible={formModal} animationType="slide-up"> <YYNavBar rightContent="保存" leftContent="取消" onLeftClick={this.cancelSave.bind(this)} onRightClick={this.saveData.bind(this)}> {navBarName} </YYNavBar> {this.getFormControl()} </YYModal>) } return null; } //获取手风琴中的高度 getAccordionPanelHeight(children,data,RunInDesign) { let {useCrud,addNavBar,showFooter}=this.props;//是否显示新增导航栏 let uitypes = ['YYInput', 'YYPicker', 'YYRefer', 'YYSwitch', 'YYDatePicker']; var height = addNavBar?45:0; let formHeight = 0; let dataLength=(data&&data.length)?data.length:0; children.map(function (item, index) { if (item.props.uitype == 'YYFormDev') { if (item.props.visible) { if(item.props.children) { item.props.children.map(function (child, index) { let {uitype,visible} = child.props; let addHeight=0; if (uitypes.some(item=>item==uitype)&&visible) formHeight+=50; if (uitype == 'YYItemText'&&visible) formHeight+=40; if (uitype == 'YYImagePicker'&&visible) formHeight+=200; if (uitype == 'YYTextareaItem'&&visible) formHeight+=140; }); } } } }); if(!RunInDesign)formHeight=formHeight*dataLength; if(showFooter) height = height+formHeight+50; else height = height+formHeight; return height; } //获取列表高度 getHeight(){ let {cutheight,children,RunInDesign,parentType}=this.props; let {data}=this.state; var height="calc(100% - "+cutheight+")"; if(parentType === 'YYAccordionPanel'){ height = this.getAccordionPanelHeight(children,data,RunInDesign); } return height; } //获取样式名称 getClassName(){ let {visible,className}=this.props; let repeaterClz = classnames('yy-repeater',(!visible&&'hidden'), className); return repeaterClz; } renderFooter() { let {footerBefore,footerAfter,showFooter,addNavBar,addChildText,childTable} = this.props; let {isLoading}=this.state; if(addNavBar&&childTable) { let buttonDom=(<Button size='small' type='ghost' onClick={this.showFormModal.bind(this,{sys_front_id:this.uuid()},true)}>{addChildText}</Button>); if(showFooter) { return( <div>{buttonDom} <div style={{ padding: 10, textAlign: 'center' }}> {isLoading?footerBefore:footerAfter} </div> </div>); }else{ return (<div>{buttonDom}</div>) } }else if(showFooter){ return(<div style={{ padding: 10, textAlign: 'center' }}> {isLoading?footerBefore:footerAfter} </div>); } return null; } render() { let {onEndReachedThreshold,onRefresh}=this.props; let {dataSource,refreshing}=this.state; return ( <ListView ref="YYRepeater" key={"YYRepeater"} renderRow={(rowData, sectionID, rowID, highlightRow)=>this.createRow(rowData, sectionID, rowID, highlightRow)} dataSource={dataSource} scrollRenderAheadDistance={500} style={{height:this.getHeight()}} onEndReachedThreshold={onEndReachedThreshold} renderFooter={this.renderFooter.bind(this)} className={this.getClassName()} onEndReached={this.onEndReached.bind(this)} pullToRefresh={onRefresh?<PullToRefresh distanceToRefresh={25} refreshing={refreshing} onRefresh={this.onRefresh.bind(this)} />:null}> {this.getChildModal()} </ListView>); } } YYRepeater.defaultProps={ data:[], appendData:[], onEndReachedhold:10, initialListSize:4, visible:true, addNavBar:false,//此属性用于CRUD模板中 循环项目列表编辑时的属性 此属性会自动新增数据 navBarName:"子表", // showFooter:true, footerBefore:"正在加载", footerAfter:"加载完成", cutheight:"0px", addChildText:"添加子表明细", navBarName:"子表明细", childTable:false, } module.exports=YYRepeater;