不是问题的问题
沟通(项目管理,产品经理,设计师,后台)
- 项目管理:项目完成排期,确认项目进度
- 产品经理: 对设计稿有什么疑惑直接寻找产品经理(逻辑部分)
- 设计师:(样式的更改,沟通解决),一开始就应该寻找设计师询问(生成app部分的滚动条)布局(自适应)
- 后台对接接口
笔记
- react
- 对组件的安排(整个产品里面的相似部分,尽量封装在一起,提高代码的利用率)
- 接口组的安排(不影响其他业务的条件下)
- 对接接口(后台小伙伴的沟通)
- 以下一些知识点的掌握
预览,生成二维码,颜色选择器,前端生成图片(base64转化为文件格式),进度条,弹窗,上传图片,图片的裁剪(canvas截图),路由的安排,折线图(react-highcharts(svg), react-echarts(canvas)),图片上传文件过滤, 页面的架构搭建
颜色选择器
- 颜色列表,hover的时候出现问题
|
|
createCanvas(color) {
const logo = this.logo;
const ctx = logo.getContext(‘2d’);
ctx.fillStyle = color;
ctx.fillRect(0, 0, 300, 300);
ctx.textAlign = ‘center’;
ctx.font = ‘90px Muna’;
ctx.fillStyle = ‘#FFF’;
ctx.fillText(this.state.val, 150, 110);
const dataURL = logo.toDataURL(‘image/png’);
if (this.props.onChange) {
this.props.onChange(dataURL);
}
}
|
|
const debug = {hello: “world”};
const blob = new Blob([JSON.stringify(debug, null, 2)],
{type : ‘application/json’});
console.log(blob);
export const getBlobByDataURI = (data, type) => {
const binary = window.atob(data.split(‘,’)[1]);
const array = [];
for (let i = 0; i < binary.length; i += 1) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], { type });
};
export const base64ToFile = uri => getBlobByDataURI(uri, ‘image/png’);
export const uploadImage = (file, types, ds) => new Promise((resolve, reject) => {
if (types.length && types.every(item => (file.type.indexOf(item)) === -1)) {
reject();
} else {
const formData = new FormData();
formData.append(‘file’, file);
ds.resolve(‘pp/app.pics’, {
body: formData,
mode: ‘FormData’,
}).then((res) => {
resolve(http://pic.kuaizhan.com${res.body.data.url}
);
}).catch((error) => {
console.log(error);
});
}
});
|
|
// stroke-dasharray=”0,10000” 第一个值就是填充的值,为0,第二段为不填充的长度,超过圆环的周长即可。此时进度条为0%:
const AppProgressCircle = (prop) => {
const {
percent = 0,
size = 111,
} = prop;
const circleLength = Math.floor(2 Math.PI 56);
const dashArray = ${(circleLength * percent) / 100},10000
;
return (
{percent}%
);
};
export default AppProgressCircle;
|
|
// 最后记得页面卸载的时候清除定时器
componentWillUnmount() {
clearInterval(this.timerCheckApp);
}
checkAppTimer(ds, dispatch, siteId) {
const countDown = 5; // 5分钟请求验证检查app是否生成成功
const d = new Date(1111/1/1,0:${countDown}:0
);
clearInterval(this.Timer);
// 在countDown时间间隔内进行循环的请求操作和进度条数字控制
this.timerCheckApp = setInterval(() => {
// const fast = 5000;
// const slow = 9000;
let m = d.getMinutes();
let s = d.getSeconds();
m = m < 10 ? 0${m}
: m;
s = s < 10 ? 0${s}
: s;
d.setSeconds(s - 1);
dispatch(checkAppGenerate(ds, siteId));
// 进度条的处理
this.setAppProcess();
// 定时器为0或者生成成功停止请求
if (m === ‘00’ && s === ‘00’) {
// 将最后的code赋值
this.setState({
code: this.props.appGenerate.code,
});
clearInterval(this.timerCheckApp);
this.timerCheckApp = undefined;
console.log(‘最后code’, this.props.appGenerate.code);
}
// 请求成功时清除定时器
if (this.props.appGenerate.code === 0) {
dispatch(getAppInfo(ds, siteId));
this.setAppProcess(100); // 将进度条设置为100
clearInterval(this.timerCheckApp);
}
console.log(‘定时器’, ${m}:${s}
);
}, 5000);
}
// 设置进度条的数值
setAppProcess() {
if (this.state.appProcess < 99) {
this.setState({
appProcess: this.state.appProcess + 1,
});
}
if (this.state.appProcess === 99) {
// 到达99%时候清除定时器
clearInterval(this.timerCheckApp);
this.setState({
code: 30005, // 进度条99%时候请求未成功
});
}
}
|
|
handleConfirm() {
const canvas = this.canvas;
const ctx = canvas.getContext('2d');
const image = new Image();
image.onload = () => { //注意!!!:已有图片加载完成,才绘制图片
const x = this.state.x / this.scaleRatio; // 裁剪图片的位置
const y = this.state.y / this.scaleRatio;
const width = this.state.width / this.scaleRatio; // 被裁剪图像的宽高
const height = this.state.height / this.scaleRatio;
const canvasW = this.props.scale ? this.state.width : width;
const canvasH = this.props.scale ? this.state.height : height;
canvas.height = canvasH; // 伸展或缩小图像
canvas.width = canvasW; //0,0在画布上放置图像的x,y坐标位置
ctx.drawImage(image, x, y, width, height, 0, 0, canvasW, canvasH);
this.setState({
cropped: true,
});
this.props.handleCrop(canvas.toDataURL());
};
image.src = this.props.imgsrc;
}
|
|
handleMouseMove(e) {
let offsetX = e.screenX - this.moveStartX;
let offsetY = e.screenY - this.moveStartY;
this.moveStartX = e.screenX;
this.moveStartY = e.screenY;
const lastX = this.state.x;
const lastY = this.state.y;
const lastH = this.state.height;
const lastW = this.state.width;
const imageH = this.imageH;
const imageW = this.imageW;
const minOffset = 0;
const minUnit = 10;
switch (this.direction) {
case ‘all’: {
let nowX = lastX + offsetX;
const maxX = imageW - lastW;
nowX = compare(nowX, minOffset, maxX);
let nowY = lastY + offsetY;
const maxY = imageH - lastH;
nowY = compare(nowY, minOffset, maxY);
this.setState({ x: nowX, y: nowY });
break;
}
|
|
alt=”cropper”
/>
|
|
input上传图片 uploadImage(file, types, this.context.ds)
.then((url) => {
afterUpload(url);
})
.catch(() => errorUpload('请上传合适尺寸/格式的图片'));)
export const uploadImage = (file, types, ds) => new Promise((resolve, reject) => {
if (types.length && types.every(item => (file.type.indexOf(item)) === -1)) {
reject();
} else {
const formData = new FormData();
formData.append(‘file’, file);
ds.resolve(‘pp/app.pics’, {
body: formData,
mode: ‘FormData’,
}).then((res) => {
resolve(http://pic.kuaizhan.com${res.body.data.url}
);
}).catch((error) => {
console.log(error);
});
}
});
// 定义接口组v1
ds.registerGroup(‘v1’, {
urlPrefix: conf.get(‘url_app_v1’),
requestProcessor: (req) => {
if (req.body) {
if (!req.headers) {
req.headers = {};
}
if (!(req.body instanceof FormData)) {
req.headers[‘Content-Type’] = ‘application/x-www-form-urlencoded;charset=UTF-8’;
req.body = encodeQueryString(req.body);
}
}
return req;
},
});
|
|
(ev.dataTransfer.setData(‘Text’, index))}
// 接收数据
onDragOver={(ev) => { ev.preventDefault(); }}
onDrop={(ev) => {
if (!onDrag) { return; }
onDrag(ev.dataTransfer.getData(‘Text’), index);
}
} // 调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)
alt=”图片”
className=”img”
/>
//
handleDrag(from, to) {
const imgList = […this.state.imgList];
[imgList[from], imgList[to]] = [imgList[to], imgList[from]];
this.setState({ imgList });
this.props.onDrag(imgList);
}
handleRemove(index) {
const imgList = […this.state.imgList];
imgList.splice(index, 1);
this.setState({
imgList,
});
this.props.onRemove(imgList);
}
handleReplace(index) {
this.changeIndex = index;
this.uploader.upload();
}
handleAddImg(url) {
const imgList = […this.state.imgList];
imgList[this.changeIndex] = url;
this.setState({ imgList });
this.props.onUpload(imgList);
}
handleError(error) {
this.props.errorUpload(error);
}
{
this.props.createPosition === 'createApp' ?
<AppConfigPreview
color={this.props.currentConfig.appTitle}
src={this.props.currentConfig.domainName}
previewTop={PREVIEW_POSITION.previewTop}
previewRight={PREVIEW_POSITION.previewRight}
/> :
<AppConfigPreview
color={this.props.currentConfig.appTitle}
previewTop={PREVIEW_POSITIONM.previewTop}
previewRight={PREVIEW_POSITIONM.previewRight}
/>
}
|
|