mirror of
https://github.com/mdnice/markdown-resume.git
synced 2025-10-19 00:44:33 +00:00
feat(保存和导入) 新增保存到本地和从本地导入功能
This commit is contained in:
17
.travis.yml
17
.travis.yml
@@ -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'
|
|
BIN
id_rsa.enc
BIN
id_rsa.enc
Binary file not shown.
@@ -34,6 +34,14 @@ class App extends Component {
|
|||||||
this.props.navbar.setBtnDisable(true);
|
this.props.navbar.setBtnDisable(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.onbeforeunload = e => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e) {
|
||||||
|
e.returnValue = "数据目前存储在浏览器中,记得保存到本地备份!";
|
||||||
|
}
|
||||||
|
return "数据目前存储在浏览器中,记得保存到本地备份!";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
|
165
src/components/Button/Export.js
Normal file
165
src/components/Button/Export.js
Normal 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);
|
@@ -61,9 +61,9 @@ class DialogHelp extends Component {
|
|||||||
indicatorColor="primary"
|
indicatorColor="primary"
|
||||||
textColor="primary"
|
textColor="primary"
|
||||||
>
|
>
|
||||||
|
<Tab label="注意" />
|
||||||
<Tab label="使用规则" />
|
<Tab label="使用规则" />
|
||||||
<Tab label="Markdown语法" />
|
<Tab label="Markdown语法" />
|
||||||
<Tab label="细节" />
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
{value === 0 && (
|
{value === 0 && (
|
||||||
<DialogContentText
|
<DialogContentText
|
||||||
@@ -75,7 +75,11 @@ class DialogHelp extends Component {
|
|||||||
dangerouslySetInnerHTML={{ __html: this.md.render(HELP_INFO[1]) }}
|
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>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={this.handleClose} color="primary">
|
<Button onClick={this.handleClose} color="primary">
|
||||||
|
@@ -2,14 +2,15 @@ import React, { Component } from "react";
|
|||||||
|
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { withStyles } from "@material-ui/core/styles";
|
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 List from "@material-ui/core/List";
|
||||||
import ListItem from "@material-ui/core/ListItem";
|
// import ListItem from "@material-ui/core/ListItem";
|
||||||
import Tooltip from "@material-ui/core/Tooltip";
|
// 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";
|
import { observer, inject } from "mobx-react";
|
||||||
|
|
||||||
@@ -17,29 +18,25 @@ import { observer, inject } from "mobx-react";
|
|||||||
@inject("navbar")
|
@inject("navbar")
|
||||||
@observer
|
@observer
|
||||||
class ListStorage extends Component {
|
class ListStorage extends Component {
|
||||||
handleSave = () => {};
|
// handleSave = () => {};
|
||||||
|
|
||||||
handleExport = () => {
|
|
||||||
this.props.navbar.setExported(true);
|
|
||||||
this.setState({ anchorEl: null });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { classes } = this.props;
|
const { classes } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List className={classes.list}>
|
<List className={classes.list}>
|
||||||
<ListItem
|
{/* <ListItem
|
||||||
className={classes.listExport}
|
className={classes.listExport}
|
||||||
button
|
button
|
||||||
onClick={this.handleExport}
|
onClick={this.handleExport}
|
||||||
>
|
> */}
|
||||||
<Button variant="outlined" color="primary" className={classes.btn}>
|
<Export/>
|
||||||
|
{/* <Button variant="outlined" color="primary" className={classes.btn}>
|
||||||
导出PDF
|
导出PDF
|
||||||
</Button>
|
</Button> */}
|
||||||
</ListItem>
|
{/* </ListItem> */}
|
||||||
|
|
||||||
<Tooltip
|
{/* <Tooltip
|
||||||
title="登录"
|
title="登录"
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
enterDelay={ENTER_DELAY}
|
enterDelay={ENTER_DELAY}
|
||||||
@@ -53,7 +50,7 @@ class ListStorage extends Component {
|
|||||||
>
|
>
|
||||||
<img src={github} alt="logo" />
|
<img src={github} alt="logo" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</Tooltip>
|
</Tooltip> */}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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];
|
export const THEMES = [THEME0, THEME1, THEME2, THEME3, THEME4];
|
||||||
|
@@ -224,3 +224,17 @@ const solveLine = value => {
|
|||||||
}
|
}
|
||||||
return html;
|
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);
|
||||||
|
}
|
Reference in New Issue
Block a user