yylib-quick-mobile
Version:
yylib-quick-mobile
615 lines (608 loc) • 23.7 kB
JavaScript
/****测试数据******/
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;