我正在为我正在工作的网站实施一项新功能。基本上,有一些带有水箱清单的钻机。我添加了拆分这些储罐的功能,之后,新的拆分储罐将出现在特定钻机的储罐列表的底部。以下是我的主要组件:
export default class Drilling extends Component {
constructor(props) {
super(props);
var userID = 'tgoodell';
// call API to get default scenario
const scenario = getDrillsDataSync(userID);
console.log(`scenario rigs: ` + scenario);
//var sortByProperty = function (property) {
//return function (x, y) {
//return ((x[property] === y[property]) ? 0 : ((x[property] > y[property]) ? 1 : -1));
//};
//};
//dataset.sort(sortByProperty(`rig`));
//console.log(dataset);
const dataset = parseDrillingDefault(scenario);
console.log(`parsed scenario rigs: ` + dataset);
localStorage.setItem('rig_order', JSON.stringify(dataset));
//console.log('------retrieving from local storage------');
//console.log('rig_order='+ localStorage.getItem('rig_order'));
// construct proper formatted rigs.json
//const rigs = DrillsAdapter.getData(API.getRigsData());
const rigs = DrillsAdapter.getData(JSON.parse(dataset));
//rigs.sort(sortByProperty(`rigID`));
//console.log(rigs);
this.state = {
rigCount: rigs.length,
rigs: [...rigs, { rigID: 'hold', tanks: [] }],
loading: false,
texts: [],
numWells: 0,
splitTankCount: 0
};
//Possible tank color implementation
// this.state.rigs.find(e => e.rigID === 'hold').tanks.map((tank, i) => {
// tankMap.set(tank.drill_tank, colors.pop());
// });
// this.state.rigs.find(e => e.rigID !== 'hold').tanks.map((tank, i) => {
// tankMap.set(tank.drill_tank, colors.pop());
// });
this.onRun = this.onRun.bind(this);
this.handleNewSplitTank = this.handleNewSplitTank.bind(this);
this.addNewRig = this.addNewRig.bind(this);
console.log(`rigs state` + this.state.rigs);
}
addRigClick = () => {
console.log(this.state.rigs);
this.addNewRig();
this.setState({
rigs: [...this.state.rigs, { rigID: this.state.rigCount, tanks: [] }],
rigCount: this.state.rigCount + 1,
});
console.log(this.state.rigs);
};
removeRigClick = () => {
console.log(this.state.rigs);
if (this.state.rigs[this.state.rigCount].tanks.length == 0) {
var element = this.state.rigs.pop();
this.setState({
rigs: this.state.rigs,
rigCount: this.state.rigCount - 1
});
}
console.log(this.state.rigs);
};
addNewRig() {
let xhr = new XMLHttpRequest();
xhr.open('POST', `${options.url}/add_new_rig`, false);
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
let userId = prompt("UserID:");
let rigName = prompt("Rig Name:");
let rigStartDate = prompt("Rig start date");
let queryStr = "userIDStr=" + userId + "&rigNameStr=" + rigName + "&rigStartDateStr=" + rigStartDate;
try {
xhr.send(queryStr);
if (xhr.status !== 200) {
console.log(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
console.log('Success!');
alert('Success. Rig added.');
}
} catch (err) {
console.log('Request failed');
}
return xhr.response;
}
onDragEnd = (result) => {
const { source, destination } = result;
if (!destination) {
return;
}
//SPREAD IT!!
let rigsCopy = [...this.state.rigs];
// console.log(source.droppableId);
// console.log(destination.droppableId);
if (source.droppableId === destination.droppableId) {
let index = rigsCopy.findIndex(e => e.rigID == source.droppableId);
let arr = rigsCopy[index].tanks;
console.log(arr);
let temp = arr.splice(source.index, 1); //is array of 1 element
arr.splice(destination.index, 0, temp[0]);
rigsCopy[index].tanks = arr;
this.setState({ rigs: rigsCopy });
} else {//dragging to new rig
//console.log(`rigs=`+JSON.stringify(rigsCopy));
let index1 = rigsCopy.findIndex(e => e.rigID == source.droppableId);
//console.log(`index1=`+index1);
let index2 = rigsCopy.findIndex(e => e.rigID == destination.droppableId);
//console.log(`index2=`+index1);
let arr1 = [...rigsCopy[index1].tanks];
let arr2 = [...rigsCopy[index2].tanks];
let temp = arr1.splice(source.index, 1);
arr2.splice(destination.index, 0, temp[0]);
//arr2.push(temp[0]);
//console.log(`temp0=`+JSON.stringify(temp[0]));
rigsCopy[index1].tanks = arr1;
rigsCopy[index2].tanks = arr2;
this.setState({ rigs: rigsCopy });
//console.log(`rigs_after_drop=`+JSON.stringify(rigsCopy));
}
};
componentDidMount() {
//jQuery for synchronous scrolling of tanks
$('.tankListDiv').scroll(e => {
$('.timeline').scrollTop(e.target.scrollTop);
});
this.state.rigs.find(e => e.rigID === 'hold').tanks.map((tank, i) => {
if (tankMap.has(tank.drill_tank)) {
return;
}
tankMap.set(tank.drill_tank, colors[i + 100]);
});
}
onRun() {
//Display loader after button click
this.setState({ loading: true }, () => {
setTimeout(() => Run(this.state.rigs), 4000);
});
setTimeout(() => this.setState({ loading: false }), 8000);
}
handleNewSplitTank() {
this.setState({ splitTankCount: this.state.splitTankCount + 1 });
}
render() {
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<h4 id="listOfTanks"> </h4>
<div className='rigsDiv'>
<button id='updatebtn' type='button' onClick={this.handleNewSplitTank}>Update</button>
{this.state.rigs.filter(e => e.rigID !== 'hold').map((rig, i) =>
<Rig rig={rig} allRigs={this.state.rigs} index={i} splitTanks={this.state.newSplitTanks} addNew={this.handleNewSplitTank} />
)}
<Fab size="small" color="secondary" aria-label="add" className='addRigBtn'
onClick={this.addRigClick}>
<AddIcon />
</Fab>
<Fab size="small" color="secondary" aria-label="remove" className='removeRigBtn'
onClick={this.removeRigClick}>
<RemoveIcon />
</Fab>
<Button onClick={this.onRun} variant="contained" className='runBtn'>RUN</Button>
<Divisions />
</div>
<div id='spinner'><BeatLoader color='blue' css={loadStyle} loading={this.state.loading} /></div>
<Droppable droppableId='hold' className='drop'>
{(provided, snapshot) => (
<div ref={provided.innerRef} className='holder'>
{this.state.rigs.find(e => e.rigID == 'hold').tanks.map((tank, i) =>
<Tank tank={tank} index={i} />
)}
{provided.placeholder}
<TankMenu menuId='tank-menu' />
<RigMenu menuId='rig-menu' />
</div>
)}
</Droppable>
<div class='timeline'>
<Timeline />
</div>
</DragDropContext>
)
}
}
钻机组件:
function Rig(props) {
//const forceUpdate = useForceUpdate();
for (let i = 0; i < 700; ++i) {
colors.push(rainbow(700, i));
}
shuffleArray(colors);
props.rig.tanks.map((tank, i) => {
if (tankMap.has(tank.drill_tank)) {
return;
}
tankMap.set(tank.drill_tank, colors[i]);
});
const handleRigEvent = e => {
e.preventDefault();
contextMenu.show({
id: 'rig-menu',
event: e,
props: props.rig
});
}
return (
<div className='rigDiv'>
<div className='rigName' onContextMenu={handleRigEvent}>
Rig {props.rig.rigID + 1}
</div>
<Droppable droppableId={String(props.rig.rigID)}>
{(provided, snapshot) => (
<div ref={provided.innerRef} className='tankListDiv' id={props.index}>
{props.rig.tanks.map((tank, i) =>
<Tank tank={tank} index={i} rig={props} splitTanks={props.splitTanks} color={tankMap.get(tank.drill_tank)} />
)}
{provided.placeholder}
</div>
)}
</Droppable>
<button type='button' onClick={props.addNew}>Update Rigs</button>
</div>
)
}
坦克组件:
const Tank = React.memo(function Tank(props) {
let texts = [];
let numWells = 0;
props.tank.s_tanks.forEach((s_tank, i) => {
texts.push('Split Tank: \n');
texts.push(s_tank.splitted_drill_tank + "\n");
texts.push('---------------------------');
texts.push(' Wells:');
s_tank.wells.forEach(well => {
texts.push("\n" + well.well_name);
numWells++;
texts.push("\n");
});
});
//Handler to show right click menu
const handleTankEvent = e => {
e.preventDefault();
contextMenu.show({
id: 'tank-menu',
event: e,
props: props.rig
//props: props.tank
});
}
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
return (
<Draggable
key={props.tank.tankID}
draggableId={makeid(6)}
index={props.index}
>
{(provided, snapshot) => {
const style = {
height: !props.color ? unusedHeight : numWells + 2 + 'rem',
backgroundColor: props.color,
...provided.draggableProps.style,
};
return (
<div
id='tank'
className='tankdiv'
ref={provided.innerRef}
onContextMenu={handleTankEvent}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={style}
>
<div className='tooltip'>
{texts.map(e => <div>{e}</div>)}
</div>
{provided.placeholder}
{props.tank.drill_tank}
</div>
);
}}
</Draggable>
)
});
重新渲染Tank组件时,对于Tank组件中的以下代码块,我收到一条错误消息:“无法读取每个未定义的属性”:
props.tank.s_tanks.forEach((s_tank, i) => {
texts.push('Split Tank: \n');
texts.push(s_tank.splitted_drill_tank + "\n");
texts.push('---------------------------');
texts.push(' Wells:');
s_tank.wells.forEach(well => {
texts.push("\n" + well.well_name);
numWells++;
texts.push("\n");
});
});
任何帮助将不胜感激,因为这是一项关键功能。预先感谢。