[Image upload]

This commit is contained in:
CPunisher 2020-05-13 15:33:17 +08:00
parent 47e31499e1
commit 14021335d2
11 changed files with 185 additions and 64 deletions

View File

@ -1,9 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="JavaScriptSettings"> <component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" /> <option name="languageLevel" value="FLOW" />
</component>
<component name="ProjectPlainTextFileTypeManager">
<file url="file://$PROJECT_DIR$/src/logo.svg" />
</component> </component>
</project> </project>

View File

@ -37,6 +37,7 @@
}, },
"homepage": "./", "homepage": "./",
"devDependencies": { "devDependencies": {
"reactcss": "^1.2.3",
"redux-devtools": "^3.5.0", "redux-devtools": "^3.5.0",
"tcb-js-sdk": "^1.6.1" "tcb-js-sdk": "^1.6.1"
} }

View File

@ -6,7 +6,7 @@ const app = tcb.init({
const auth = app.auth(); const auth = app.auth();
async function login() { async function login() {
await auth.signInAnonymously(); // await auth.signInAnonymously();
// const loginState = await auth.getLoginState(); // const loginState = await auth.getLoginState();
} }

View File

@ -1,16 +1,57 @@
import React from 'react'; import React, {useState} from 'react';
import reactCSS from 'reactcss';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {SliderPicker} from 'react-color'; import {TwitterPicker} from 'react-color';
import '../Qrcode.css'; import '../Qrcode.css';
const ParamColor = ({ rendererIndex, paramIndex, value, onChange }) => ( const ParamColor = ({ rendererIndex, paramIndex, value, onChange }) => {
<SliderPicker const [displayColorPicker, setDisplay] = useState(false);
const styles = reactCSS({
'default': {
swatch: {
padding: '5px',
background: '#fff',
borderRadius: '1px',
boxShadow: '0 0 0 1px rgba(0,0,0,.1)',
display: 'inline-block',
cursor: 'pointer',
},
popover: {
position: 'absolute',
zIndex: '2',
},
cover: {
position: 'fixed',
top: '0px',
right: '0px',
bottom: '0px',
left: '0px',
},
},
});
return (
<div>
<button className="dl-btn" onClick={ () => setDisplay(!displayColorPicker) }>
点击选择颜色
</button>
{
displayColorPicker ?
<div style={styles.popover}>
<div style={styles.cover} onClick={() => setDisplay(false)} />
<TwitterPicker
key={"input_" + rendererIndex + "_" + paramIndex} key={"input_" + rendererIndex + "_" + paramIndex}
className="Qr-color-picker" triangle="hide"
color={value} color={value}
onChangeComplete={onChange} onChangeComplete={onChange}
/> />
) </div>
:
null
}
</div>
);
}
ParamColor.propTypes = { ParamColor.propTypes = {
rendererIndex: PropTypes.number.isRequired, rendererIndex: PropTypes.number.isRequired,

View File

@ -4,41 +4,28 @@ import PropTypes from "prop-types"
import ParamTextViewer from "../../containers/param/ParamTextViewer"; import ParamTextViewer from "../../containers/param/ParamTextViewer";
import ParamSelectViewer from "../../containers/param/ParamSelectViewer"; import ParamSelectViewer from "../../containers/param/ParamSelectViewer";
import ParamColorViewer from "../../containers/param/ParamColorViewer"; import ParamColorViewer from "../../containers/param/ParamColorViewer";
import ParamUploadViewer from "../../containers/param/ParamUploadViewer";
const mapTypeToComponent = ({
[ParamTypes.TEXT_EDITOR]: ParamTextViewer,
[ParamTypes.SELECTOR]: ParamSelectViewer,
[ParamTypes.COLOR_EDITOR]: ParamColorViewer,
[ParamTypes.UPLOAD_BUTTON]: ParamUploadViewer,
})
const ParamList = ({ rendererIndex, paramInfo }) => ( const ParamList = ({ rendererIndex, paramInfo }) => (
paramInfo.map((item, paramIndex) => { paramInfo.map((item, paramIndex) => {
switch (item.type) {
case ParamTypes.TEXT_EDITOR: {
return ( return (
<tr key={"tr_" + rendererIndex + "_" + paramIndex}> <tr key={"tr_" + rendererIndex + "_" + paramIndex}>
<td>{item.key}</td> <td>{item.key}</td>
<td> <td>
<ParamTextViewer rendererIndex={rendererIndex} paramIndex={paramIndex}/> {React.createElement(mapTypeToComponent[item.type], {
rendererIndex: rendererIndex,
paramIndex: paramIndex
})}
</td> </td>
</tr> </tr>
) );
}
case ParamTypes.SELECTOR: {
return (
<tr key={"tr_" + rendererIndex + "_" + paramIndex}>
<td>{item.key}</td>
<td>
<ParamSelectViewer rendererIndex={rendererIndex} paramIndex={paramIndex}/>
</td>
</tr>
)
}
case ParamTypes.COLOR_EDITOR: {
return (
<tr key={"tr_" + rendererIndex + "_" + paramIndex}>
<td>{item.key}</td>
<td>
<ParamColorViewer rendererIndex={rendererIndex} paramIndex={paramIndex}/>
</td>
</tr>
)
}
}
}) })
) )

View File

@ -0,0 +1,32 @@
import React from 'react';
import PropTypes from 'prop-types'
import '../Qrcode.css';
const ParamUpload = ({ rendererIndex, paramIndex, onChange }) => (
<React.Fragment>
<label
htmlFor="image_upload"
key={"label_" + rendererIndex + "_" + paramIndex}
className="dl-btn"
style={{textAlign: "center"}}
>
上传图片
</label>
<input
type="file"
key={"input_" + rendererIndex + "_" + paramIndex}
id="image_upload"
hidden={true}
accept=".jpg, .jpeg, .png"
onChange={onChange}
/>
</React.Fragment>
)
ParamUpload.propTypes = {
rendererIndex: PropTypes.number.isRequired,
paramIndex: PropTypes.number.isRequired,
onChange: PropTypes.func.isRequired
}
export default ParamUpload;

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
export const ParamTypes = { export const ParamTypes = ({
TEXT_EDITOR: 1, TEXT_EDITOR: 1,
SELECTOR: 2, SELECTOR: 2,
COLOR_EDITOR: 3, COLOR_EDITOR: 3,
MULTI_CHECK: 4, MULTI_CHECK: 4,
} UPLOAD_BUTTON: 5
});

View File

@ -0,0 +1,36 @@
import { connect } from 'react-redux';
import {changeParam} from "../../actions";
import ParamUpload from "../../components/param/ParamUpload";
import {toBase64} from "../../utils/util";
const fileTypes =[
'image/jpeg',
'image/pjpeg',
'image/png'
]
function validFileType(file) {
return fileTypes.includes(file.type);
}
const mapStateToProps = (state, ownProps) => ({
rendererIndex: ownProps.rendererIndex,
paramIndex: ownProps.paramIndex,
value: state.paramValue[ownProps.rendererIndex][ownProps.paramIndex],
info: state.paramInfo[ownProps.rendererIndex][ownProps.paramIndex],
})
const mapDispatchToProps = (dispatch, ownProps) => ({
onChange: (e) => {
if (e.target.files.length > 0) {
const file = e.target.files[0];
if (validFileType(file)) {
toBase64(file, 500, 500).then(res => {
dispatch(changeParam(ownProps.rendererIndex, ownProps.paramIndex, res))
})
}
}
}
})
export default connect(mapStateToProps, mapDispatchToProps)(ParamUpload);

View File

@ -41,3 +41,23 @@ export function getParamDetailedValue(item, paramValue) {
if (item.type == ParamTypes.SELECTOR) return item.choices[paramValue]; if (item.type == ParamTypes.SELECTOR) return item.choices[paramValue];
return paramValue; return paramValue;
} }
export async function toBase64(file, width, height) {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
let img = document.createElement('img');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
img.setAttribute('src', URL.createObjectURL(file));
return new Promise(resolve => {
img.onload = () => {
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, width, height)
ctx.drawImage(img, 0, 0, width, height);
resolve(canvas.toDataURL(file.type, 0.8));
};
})
}