[Image upload]
This commit is contained in:
parent
47e31499e1
commit
14021335d2
|
@ -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>
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
});
|
||||||
|
|
|
@ -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);
|
|
@ -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));
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue