feat(保存和导入) 新增保存到本地和从本地导入功能

This commit is contained in:
guanpengchn
2019-06-16 15:57:49 +08:00
parent 1a2bdd3df0
commit f16b217b6e
8 changed files with 213 additions and 38 deletions

View File

@@ -1,17 +0,0 @@
language: node_js
node_js:
- '10'
branchs:
only:
- master
install:
- yarn install
script:
- yarn build
addons:
ssh_known_hosts: 39.96.191.154
before_install:
- openssl aes-256-cbc -K $encrypted_e6c41ade86ae_key -iv $encrypted_e6c41ade86ae_iv -in id_rsa.enc -out ~/.ssh/id_rsa -d
after_success:
- chmod 600 ~/.ssh/id_rsa
- ssh travis@39.96.191.154 -o StrictHostKeyChecking=no 'cd ~/markdown-resume && git pull && yarn install && yarn build'

Binary file not shown.

View File

@@ -34,6 +34,14 @@ class App extends Component {
this.props.navbar.setBtnDisable(true);
}
};
window.onbeforeunload = e => {
e = e || window.event;
if (e) {
e.returnValue = "数据目前存储在浏览器中,记得保存到本地备份!";
}
return "数据目前存储在浏览器中,记得保存到本地备份!";
};
}
componentDidUpdate() {

View File

@@ -0,0 +1,165 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import Menu from "@material-ui/core/Menu";
import Button from "@material-ui/core/Button";
import MenuItem from "@material-ui/core/MenuItem";
import Tooltip from "@material-ui/core/Tooltip";
import corner from "../../icons/corner.svg";
import { ENTER_DELAY, LEAVE_DELAY, STORAGE_LAYOUT } from "../../utils/constant";
import { downloadFile } from "../../utils/helper";
import { observer, inject } from "mobx-react";
@inject("navbar")
@inject("dialog")
@observer
class Export extends Component {
state = {
exportAnchorEl: null
};
openModeMenu = event => {
event.stopPropagation();
this.setState({ exportAnchorEl: event.currentTarget });
};
closeModeMenu = event => {
event.stopPropagation();
this.setState({ exportAnchorEl: null });
};
handleExport = event => {
event.stopPropagation();
this.props.navbar.setExported(true);
this.setState({ exportAnchorEl: null });
};
saveToLocal = event => {
event.stopPropagation();
const layout = window.localStorage.getItem(STORAGE_LAYOUT);
const filename = `markdown-resume-${new Date().getTime()}.json`;
downloadFile(filename, layout);
this.setState({ exportAnchorEl: null });
};
importFromLocal = event => {
event.stopPropagation();
const file = event.target.files[0];
this.fileReader = new FileReader();
this.fileReader.onloadend = this.handleFileRead;
this.fileReader.readAsText(file);
this.setState({ exportAnchorEl: null });
};
handleFileRead = e => {
const content = this.fileReader.result;
window.localStorage.setItem(STORAGE_LAYOUT, content);
window.location.href = "/";
};
openHelpDialog = event => {
event.stopPropagation();
this.props.dialog.setHelpOpened(true);
this.setState({ exportAnchorEl: null });
};
render() {
const { classes } = this.props;
const { exportAnchorEl } = this.state;
const exportOpen = Boolean(exportAnchorEl);
return (
<div>
<Tooltip
title="导入导出"
placement="bottom"
enterDelay={ENTER_DELAY}
leaveDelay={LEAVE_DELAY}
disableFocusListener
>
<Button
className={classes.btn}
color="primary"
variant="outlined"
onClick={this.openModeMenu}
>
导入导出
<img src={corner} alt="logo" className={classes.corner} />
</Button>
</Tooltip>
{/* 模板选择器菜单 */}
<Menu
id="template-menu"
anchorEl={exportAnchorEl}
open={exportOpen}
onClose={this.closeModeMenu}
classes={{
paper: classes.menu
}}
>
<MenuItem className={classes.menuItem} style={{ display: "none" }} />
<MenuItem className={classes.menuItem} onClick={this.handleExport}>
导出PDF
</MenuItem>
<MenuItem className={classes.menuItem} onClick={this.saveToLocal}>
保存到本地
</MenuItem>
<label htmlFor="outlined-button-file">
<MenuItem className={classes.menuItem}>
<input
accept="application/json"
className={classes.input}
id="outlined-button-file"
type="file"
onChange={this.importFromLocal}
/>
从本地导入
</MenuItem>
</label>
<MenuItem className={classes.menuItem} onClick={this.openHelpDialog}>
帮助
</MenuItem>
</Menu>
</div>
);
}
}
const styles = theme => ({
btn: {
padding: "0px 10px",
height: "100%",
width: "100px"
},
menu: {
top: "40px !important"
},
menuItem: {
fontSize: "0.95em"
},
corner: {
position: "absolute",
bottom: 2,
right: 2
},
input: {
display: "none"
},
label: {
width: "100%",
height: "100%"
}
});
Export.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(Export);

View File

@@ -61,9 +61,9 @@ class DialogHelp extends Component {
indicatorColor="primary"
textColor="primary"
>
<Tab label="注意" />
<Tab label="使用规则" />
<Tab label="Markdown语法" />
<Tab label="细节" />
</Tabs>
{value === 0 && (
<DialogContentText
@@ -75,7 +75,11 @@ class DialogHelp extends Component {
dangerouslySetInnerHTML={{ __html: this.md.render(HELP_INFO[1]) }}
/>
)}
{value === 2 && <p>Item Three</p>}
{value === 2 && (
<DialogContentText
dangerouslySetInnerHTML={{ __html: this.md.render(HELP_INFO[2]) }}
/>
)}
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">

View File

@@ -2,14 +2,15 @@ import React, { Component } from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
// import Button from "@material-ui/core/Button";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import Tooltip from "@material-ui/core/Tooltip";
// import ListItem from "@material-ui/core/ListItem";
// import Tooltip from "@material-ui/core/Tooltip";
import github from "../../icons/github.svg";
// import github from "../../icons/github.svg";
import Export from "../Button/Export"
import { ENTER_DELAY, LEAVE_DELAY } from "../../utils/constant";
// import { ENTER_DELAY, LEAVE_DELAY } from "../../utils/constant";
import { observer, inject } from "mobx-react";
@@ -17,29 +18,25 @@ import { observer, inject } from "mobx-react";
@inject("navbar")
@observer
class ListStorage extends Component {
handleSave = () => {};
handleExport = () => {
this.props.navbar.setExported(true);
this.setState({ anchorEl: null });
};
// handleSave = () => {};
render() {
const { classes } = this.props;
return (
<List className={classes.list}>
<ListItem
{/* <ListItem
className={classes.listExport}
button
onClick={this.handleExport}
>
<Button variant="outlined" color="primary" className={classes.btn}>
> */}
<Export/>
{/* <Button variant="outlined" color="primary" className={classes.btn}>
导出PDF
</Button>
</ListItem>
</Button> */}
{/* </ListItem> */}
<Tooltip
{/* <Tooltip
title="登录"
placement="bottom"
enterDelay={ENTER_DELAY}
@@ -53,7 +50,7 @@ class ListStorage extends Component {
>
<img src={github} alt="logo" />
</ListItem>
</Tooltip>
</Tooltip> */}
</List>
);
}

View File

@@ -77,6 +77,10 @@ export const HELP_MARKDOWN = `
\`\`\`
`;
export const HELP_INFO = [HELP_USE, HELP_MARKDOWN];
export const HELP_NOTICE = `
### 简历数据目前自动保存在浏览器中,如果清理浏览器将会丢失!
### 记得编辑后保存到本地备份!
`
export const HELP_INFO = [HELP_NOTICE, HELP_USE, HELP_MARKDOWN];
export const THEMES = [THEME0, THEME1, THEME2, THEME3, THEME4];

View File

@@ -224,3 +224,17 @@ const solveLine = value => {
}
return html;
};
/**
* 创建并下载文件
* @param {String} fileName 文件名
* @param {String} content 文件内容
*/
export const downloadFile = (fileName, content) => {
var aTag = document.createElement('a');
var blob = new Blob([content]);
aTag.download = fileName;
aTag.href = URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(blob);
}