[Image box for saving]
This commit is contained in:
parent
1680f6582f
commit
403ea01769
|
@ -7,15 +7,18 @@ const auth = app.auth();
|
|||
|
||||
async function login() {
|
||||
await auth.signInAnonymously();
|
||||
// const loginState = await auth.getLoginState();
|
||||
const loginState = await auth.getLoginState();
|
||||
isLogin = loginState
|
||||
}
|
||||
|
||||
login();
|
||||
|
||||
let isLogin;
|
||||
const db = app.database();
|
||||
const _ = db.command
|
||||
|
||||
export function increaseDownloadData(value) {
|
||||
if (!isLogin) return;
|
||||
db.collection('QRCounter').where({
|
||||
value: _.eq(value)
|
||||
}).get().then(res => {
|
||||
|
@ -25,21 +28,20 @@ export function increaseDownloadData(value) {
|
|||
}).update({
|
||||
count: _.inc(1),
|
||||
date: new Date().toString()
|
||||
}).then(res => {
|
||||
})
|
||||
}).catch(console.error)
|
||||
}
|
||||
else {
|
||||
db.collection('QRCounter').add({
|
||||
value: value,
|
||||
count: 1,
|
||||
date: new Date().toString()
|
||||
}).then(res => {
|
||||
})
|
||||
}).catch(console.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function recordDownloadDetail({text, value, type, params, history}) {
|
||||
if (!isLogin) return;
|
||||
db.collection('QRDownloadData').add({
|
||||
date: new Date().toString(),
|
||||
text: text,
|
||||
|
@ -47,6 +49,5 @@ export function recordDownloadDetail({text, value, type, params, history}) {
|
|||
type: type,
|
||||
params: params,
|
||||
history: history
|
||||
}).then(res => {
|
||||
})
|
||||
}).catch(console.error)
|
||||
}
|
||||
|
|
|
@ -1,32 +1,50 @@
|
|||
import React from 'react';
|
||||
import React, {useState} from 'react';
|
||||
import './App.css';
|
||||
import DownloadSvg from "../../containers/download/DownloadSvg";
|
||||
import DownloadJpg from "../../containers/download/DownloadJpg";
|
||||
import PropTypes from 'prop-types';
|
||||
import {isWeiXin} from "../../utils/util";
|
||||
|
||||
const WxMessage = () => {
|
||||
if (isWeiXin()) {
|
||||
return <div className="note-font" id="wx-message-inner">当前客户端不支持下载,请在浏览器中打开。</div>
|
||||
return <div className="note-font" id="wx-message-inner">当前客户端不支持下载,请长按图片保存。</div>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const PartDownload = ({ value }) => (
|
||||
<div className="Qr-titled">
|
||||
const PartDownload = ({ value, onSvgDownload, onJpgDownload }) => {
|
||||
const [imgData, setImgData] = useState('');
|
||||
|
||||
return (
|
||||
<div className="Qr-titled">
|
||||
<div className="Qr-Centered title-margin">
|
||||
<div className="Qr-s-title">Downloads</div>
|
||||
<p className="Qr-s-subtitle">下载二维码 — {value}</p>
|
||||
</div>
|
||||
<div className="Qr-Centered">
|
||||
<div className="div-btn">
|
||||
<DownloadSvg/>
|
||||
<DownloadJpg/>
|
||||
<button className="dl-btn" onClick={onSvgDownload}>SVG</button>
|
||||
<button className="dl-btn" onClick={() => {
|
||||
onJpgDownload().then(res => setImgData(res));
|
||||
}}>
|
||||
JPG
|
||||
</button>
|
||||
</div>
|
||||
<div id="wx-message">
|
||||
<WxMessage/>
|
||||
</div>
|
||||
<div>
|
||||
{
|
||||
imgData.length > 0 ? <img src={imgData} width={300} height={300} alt="点击JPG下载" /> : null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
PartDownload.propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
onSvgDownload: PropTypes.func.isRequired,
|
||||
onJpgDownload: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
export default PartDownload;
|
||||
|
|
|
@ -7,14 +7,16 @@ const PartStyles = ({ setParamInfo }) => {
|
|||
useEffect(() => {
|
||||
setLoaded(true);
|
||||
}, [])
|
||||
|
||||
const styleList = React.createElement(StyleListViewer({setParamInfo}))
|
||||
console.log(loaded)
|
||||
|
||||
return (<div className="Qr-titled">
|
||||
<div className="Qr-Centered title-margin">
|
||||
<div className="Qr-s-title">Styles</div>
|
||||
<p className="Qr-s-subtitle">点击选择样式</p>
|
||||
</div>
|
||||
<div className="Qr-s">
|
||||
<div className="Qr-s" style={{visibility: loaded ? "visible" :"hidden"}}>
|
||||
{styleList}
|
||||
</div>
|
||||
</div>)
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import React from "react";
|
||||
import PropTypes from 'prop-types'
|
||||
import '../Qrcode.css';
|
||||
|
||||
const DownloadButton = ({ onClick, value }) => (
|
||||
<button className="dl-btn" onClick={onClick}>
|
||||
{value}
|
||||
</button>
|
||||
)
|
||||
|
||||
DownloadButton.propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
value: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default DownloadButton;
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import '../Qrcode.css';
|
||||
import logo from "../../qrbtf-logo.svg";
|
||||
import InputText from "../../containers/InputText";
|
||||
import InputText from "../../containers/app/InputText";
|
||||
|
||||
const logoStyle = {
|
||||
background: `url(${logo})`,
|
||||
|
|
|
@ -2,13 +2,13 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types'
|
||||
import '../Qrcode.css';
|
||||
|
||||
const ParamText = ({ rendererIndex, paramIndex, value, onBlur, onKeyPress }) => (
|
||||
const ParamText = ({ rendererIndex, paramIndex, value, info, onBlur, onKeyPress }) => (
|
||||
<input
|
||||
type="number"
|
||||
key={"input_" + rendererIndex + "_" + paramIndex}
|
||||
className="Qr-input small-input"
|
||||
placeholder={value}
|
||||
defaultValue={value}
|
||||
placeholder={info.default}
|
||||
defaultValue={String(value)}
|
||||
onBlur={onBlur}
|
||||
onKeyPress={onKeyPress}
|
||||
/>
|
||||
|
@ -17,7 +17,8 @@ const ParamText = ({ rendererIndex, paramIndex, value, onBlur, onKeyPress }) =>
|
|||
ParamText.propTypes = {
|
||||
rendererIndex: PropTypes.number.isRequired,
|
||||
paramIndex: PropTypes.number.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
value: PropTypes.number.isRequired,
|
||||
info: PropTypes.object.isRequired,
|
||||
onBlur: PropTypes.func.isRequired,
|
||||
onKeyPress: PropTypes.func.isRequired
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {connect} from 'react-redux';
|
||||
import {genQRInfo} from "../actions";
|
||||
import {genQRInfo} from "../../actions";
|
||||
import React from "react";
|
||||
|
||||
const InputText = ({dispatch}) => (
|
||||
|
@ -8,7 +8,10 @@ const InputText = ({dispatch}) => (
|
|||
placeholder="Input your URL here"
|
||||
onBlur={e => dispatch(genQRInfo(e.target.value))}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') dispatch(genQRInfo(e.target.value))
|
||||
if (e.key === 'Enter') {
|
||||
dispatch(genQRInfo(e.target.value));
|
||||
e.target.blur();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
|
@ -1,8 +1,41 @@
|
|||
import { connect } from 'react-redux';
|
||||
import PartDownload from "../../components/app/PartDownload";
|
||||
import React from "react";
|
||||
import {saveImg, saveSvg} from "../../utils/downloader";
|
||||
import ReactDOMServer from "react-dom/server";
|
||||
import {increaseDownloadData, recordDownloadDetail} from "../../api/db";
|
||||
import {getParamDetailedValue} from "../../utils/util";
|
||||
|
||||
function saveEl(state, type) {
|
||||
const el = React.createElement(state.rendererType, {
|
||||
qrcode: state.qrcode,
|
||||
params: state.paramValue[state.selectedIndex],
|
||||
setParamInfo: () => {}
|
||||
});
|
||||
increaseDownloadData(state.value)
|
||||
recordDownloadDetail({
|
||||
text: state.textUrl,
|
||||
value: state.value,
|
||||
type: type,
|
||||
params: state.paramInfo[state.selectedIndex].map((item, index) => {
|
||||
return {
|
||||
key: item.key,
|
||||
value: getParamDetailedValue(item, state.paramValue[state.selectedIndex][index])
|
||||
}
|
||||
}),
|
||||
history: state.history
|
||||
});
|
||||
return el;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
value: state.value
|
||||
value: state.value,
|
||||
onSvgDownload: () => {
|
||||
saveSvg(state.value, ReactDOMServer.renderToString(saveEl(state, 'svg')))
|
||||
},
|
||||
onJpgDownload: () => {
|
||||
return saveImg(state.value, ReactDOMServer.renderToString(saveEl(state, 'jpg')), 1500, 1500)
|
||||
}
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(PartDownload)
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import { connect } from 'react-redux';
|
||||
import React from 'react';
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import DownloadButton from "../../components/download/DownloadButton";
|
||||
import {saveImg} from "../../utils/downloader";
|
||||
import {increaseDownloadData, recordDownloadDetail} from "../../api/db";
|
||||
import {getParamDetailedValue} from "../../utils/util";
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
value: 'JPG',
|
||||
onClick: () => {
|
||||
const el = React.createElement(state.rendererType, {
|
||||
qrcode: state.qrcode,
|
||||
params: state.paramValue[state.selectedIndex],
|
||||
setParamInfo: () => {}
|
||||
});
|
||||
saveImg(state.value, ReactDOMServer.renderToString(el), 1500, 1500);
|
||||
increaseDownloadData(state.value)
|
||||
recordDownloadDetail({
|
||||
text: state.textUrl,
|
||||
value: state.value,
|
||||
type: 'jpg',
|
||||
params: state.paramInfo[state.selectedIndex].map((item, index) => {
|
||||
return {
|
||||
key: item.key,
|
||||
value: getParamDetailedValue(item, state.paramValue[state.selectedIndex][index])
|
||||
}
|
||||
}),
|
||||
history: state.history
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(DownloadButton)
|
|
@ -1,34 +0,0 @@
|
|||
import { connect } from 'react-redux';
|
||||
import React from 'react';
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import DownloadButton from "../../components/download/DownloadButton";
|
||||
import {saveSvg} from "../../utils/downloader";
|
||||
import {increaseDownloadData, recordDownloadDetail} from "../../api/db";
|
||||
import {getParamDetailedValue} from "../../utils/util";
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
value: 'SVG',
|
||||
onClick: () => {
|
||||
const el = React.createElement(state.rendererType, {
|
||||
qrcode: state.qrcode,
|
||||
params: state.paramValue[state.selectedIndex],
|
||||
setParamInfo: () => {}
|
||||
});
|
||||
saveSvg(state.value, ReactDOMServer.renderToString(el));
|
||||
increaseDownloadData(state.value)
|
||||
recordDownloadDetail({
|
||||
text: state.textUrl,
|
||||
value: state.value,
|
||||
type: 'svg',
|
||||
params: state.paramInfo[state.selectedIndex].map((item, index) => {
|
||||
return {
|
||||
key: item.key,
|
||||
value: getParamDetailedValue(item, state.paramValue[state.selectedIndex][index])
|
||||
}
|
||||
}),
|
||||
history: state.history
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(DownloadButton)
|
|
@ -5,7 +5,8 @@ import {changeParam} from "../../actions";
|
|||
const mapStateToProps = (state, ownProps) => ({
|
||||
rendererIndex: ownProps.rendererIndex,
|
||||
paramIndex: ownProps.paramIndex,
|
||||
value: String(state.paramValue[ownProps.rendererIndex][ownProps.paramIndex])
|
||||
value: state.paramValue[ownProps.rendererIndex][ownProps.paramIndex],
|
||||
info: state.paramInfo[ownProps.rendererIndex][ownProps.paramIndex]
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch, ownProps) => ({
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import {increaseDownloadData} from "../api/db";
|
||||
|
||||
const svgHead = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n " +
|
||||
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
|
||||
|
||||
|
@ -17,8 +15,6 @@ export function saveSvg(value, content) {
|
|||
a.download = filename
|
||||
a.hidden = true
|
||||
a.click()
|
||||
|
||||
increaseDownloadData(value, new Date().toString())
|
||||
}
|
||||
|
||||
export function saveImg(value, content, width, height) {
|
||||
|
@ -43,26 +39,26 @@ export function saveImg(value, content, width, height) {
|
|||
canvas.setAttribute('height', height);
|
||||
|
||||
let ctx = canvas.getContext('2d');
|
||||
|
||||
let img = document.createElement('img');
|
||||
|
||||
|
||||
img.onload = () => {
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
// `download` attr is not well supported
|
||||
// Will result in a download popup for chrome and the
|
||||
// image opening in a new tab for others.
|
||||
|
||||
let a = document.createElement('a');
|
||||
a.setAttribute('href', canvas.toDataURL('image/jpeg', 0.8))
|
||||
a.setAttribute('target', 'download')
|
||||
a.setAttribute('download', filename);
|
||||
a.click();
|
||||
};
|
||||
|
||||
img.setAttribute('src', 'data:image/svg+xml;base64,' + btoa(svgData));
|
||||
|
||||
increaseDownloadData(value, new Date().toString())
|
||||
return new Promise(resolve => {
|
||||
img.onload = () => {
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
// `download` attr is not well supported
|
||||
// Will result in a download popup for chrome and the
|
||||
// image opening in a new tab for others.
|
||||
|
||||
let a = document.createElement('a');
|
||||
let data = canvas.toDataURL('image/jpeg', 0.8);
|
||||
a.setAttribute('href', data)
|
||||
a.setAttribute('target', 'download')
|
||||
a.setAttribute('download', filename);
|
||||
a.click();
|
||||
|
||||
resolve(data)
|
||||
};
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue