Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
a55d7c4
Merge pull request #1 from PDKSophia/master
PDKSophia Mar 8, 2021
84a438f
[feature][what]初始化项目
Apr 23, 2021
2e4266d
Merge branch 'init' of https://github.com/PDKSophia/visResumeMook int…
Apr 23, 2021
89603ba
[feature][what]解决冲突
Apr 23, 2021
8a9f917
[feature][what]删除无用的文件夹
Apr 23, 2021
f34491b
[feature][what]Electron初始化demo
Apr 25, 2021
40921c3
[feature][what]文档更新
Apr 25, 2021
9e1ee80
Update README.md
PDKSophia Apr 25, 2021
1ce9020
[feature][what]修改文档
Apr 30, 2021
a100ff9
[feature][what]修改文档
Apr 30, 2021
c2a4dbc
[refactor][what] Electron 配置完成
May 18, 2021
afeec35
[docs][what]文档更新
May 18, 2021
3ca8584
[feature][what]添加webpack配置
May 18, 2021
0c79b69
[feature][what]完成Electron与React结合
May 18, 2021
c6de3e8
[feature][what]文档的完善
May 18, 2021
29ac01b
[feature][what]引入 ts 、eslint、prettier 配置
May 18, 2021
c5c3883
[feature][what]添加less样式配置
May 18, 2021
199fc9c
[feature][what]修复postcss报错,需要autoprefixer问题[jira]https://github.com/p…
May 18, 2021
0d462e4
[feature][what]引入styleName
May 18, 2021
a9623e2
[feature][what]添加global.d.ts和file-loader
May 18, 2021
aa584ac
[feature][what]更新README文档
May 18, 2021
b412091
[feature][what]添加首页入口与路由组件
May 19, 2021
df5e567
[feature][what]添加logo
May 19, 2021
8ba9506
[feature][what]完成基本效果
May 19, 2021
2f44d86
[feature][what]添加简历模块入口,并且完成页面点击挑战功能
May 19, 2021
525cdba
[feature][what]优化一:路径别名alias添加
May 19, 2021
a793443
[feature][what]代码优化
May 19, 2021
a25d510
[feature][what]引入 redux,撰写redux相关逻辑
May 20, 2021
154f441
[feature][what]完成主进程与渲染进程之间通信,实现持久性数据的存储
May 20, 2021
101066f
[feature][what]删除无用代码和注释补全、类型约束
May 20, 2021
344a250
[linted][feature][what]添加 classnames 库
May 24, 2021
56141b9
[linted][feature][what]封装通用按钮组件
May 24, 2021
164bd25
[linted][feature][what]封装通用内容输入MyInput组件
May 24, 2021
21cc126
[linted][feature][what]修改字段属性类型
May 24, 2021
fc699fc
[linted][feature][what]添加上传组件
May 25, 2021
c423762
[linted][feature][what]关闭eslint的no-undef规则
May 25, 2021
9e92775
[linted][feature][what]添加utils方法
May 25, 2021
85e520f
[linted][feature][what]添加图片
May 25, 2021
d8b5700
[linted][feature][what]添加弹窗组件
May 25, 2021
7d9cde5
[linted][feature][what]添加MyScrollBox组件
May 25, 2021
90c8fe5
[linted][feature][what]添加类型文件
May 25, 2021
b15d8fd
[linted][feature][what]添加resumeModel文件
May 25, 2021
fbbcb1d
[linted][feature][what]添加简历模版
May 25, 2021
f2553e4
[linted][feature][what]简历制作模块的入口文件修改
May 26, 2021
3ea0a1a
[linted][feature][what]工具条模块的完成,完成简历制作静态页面
May 26, 2021
80cd4ba
[linted][feature][what]完成工具条新增和删除逻辑
May 26, 2021
b7323c2
[linted][feature][what]添加 templateModel,实现模版简历与工具条模块的通信
May 27, 2021
cb5695c
[linted][feature][what]Messager发布订阅的实现
May 27, 2021
655f677
[linted][feature][what]完成表单弹窗组件
May 27, 2021
a94b96c
[linted][feature][what]添加所有弹窗组件
May 27, 2021
7c314be
[linted][feature][what]添加弹窗关闭方法
May 27, 2021
eeb4299
[linted][feature][what]useUpdateResumeHook的实现
May 27, 2021
3894a10
[linted][feature][what]所有简单数据录入都接入 useUpdateResumeHook
May 27, 2021
e1fb960
[linted][feature][what]添加个人评价组件
May 27, 2021
198f205
[linted][feature][what]完成弹窗显示复杂数据录入的基本功能
May 28, 2021
019f23c
[linted][feature][what]项目经验数据的录入
May 28, 2021
5970ed3
[linted][feature][what]简历连接redux数据
May 28, 2021
f55bbec
[linted][feature][what]完成在校经历功能
May 28, 2021
e2a3cc7
[linted][feature][what]新增工作经历功能
May 28, 2021
2f8ebc6
[linted][feature][what]优化逻辑
May 28, 2021
7af2354
[linted][feature][what]完成导出功能
May 29, 2021
8ca960e
[linted][feature][what]抽取导出逻辑
May 29, 2021
29947ae
[linted][feature][what]README更新
May 29, 2021
9fdb3c6
[feature][what]更新README.md文档
PDKSophia May 29, 2021
a4ba819
[fix][what]更新环境变量参数的定义[jira]https://webpack.js.org/configuration/mode/
Jun 10, 2021
1db8c28
[optimize][what]优化依赖
Jun 10, 2021
92edc10
Update htmlToPdf.ts
XYH1996 Aug 3, 2021
456021e
Merge pull request #1 from XYH1996/修复pdf导出高度计算不正确
XYH1996 Aug 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ module.exports = {
'plugin:react-hooks/recommended',
'plugin:prettier/recommended',
],
plugins: ['jest'],
env: {
'jest/globals': true,
},
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'], // 定义了该eslint文件所依赖的插件
globals: {
// 这里填入你的项目需要的全局变量
// 这里值为 false 表示这个全局变量不允许被重新赋值,比如:
//
// React: false,
// ReactDOM: false
__dirname: false,
},
rules: {
Expand Down Expand Up @@ -44,5 +39,6 @@ module.exports = {
'react/no-unsafe': 'off',
'@typescript-eslint/no-invalid-this': 'off',
'react/jsx-key': 0,
'no-undef': 0,
},
};
71 changes: 55 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,60 @@
# VisResumeMook
## Electron + React Hooks + TS 实战开发:从 0 到 1 实现简历平台

React + TS + Electron 打造可视化在线简历平台
### 开发

![](https://img.shields.io/badge/visResumeMook--resume-1.0.2-red.svg)
![](https://img.shields.io/badge/react-16.12.0-blue.svg)
![](https://img.shields.io/badge/electron-11.1.1-green.svg)
![](https://img.shields.io/badge/react_redux-7.1.3-orange.svg)
![](https://img.shields.io/badge/typescript-3.7.2-blue.svg)
![](https://img.shields.io/badge/license-MIT-orange.svg)
> 由于网络问题,往往安装 Electron 会很慢,此时可以考虑换个淘宝源

# 开发

```bash
git clone https://github.com/PDKSophia/visResumeMook.git
cd visResumeMook
npm run webpack:main
npm run webpack:render
```js
// 1.下载
npm run install
// 2. 运行
npm run start:render
npm run start:main
```

推荐使用 `vscode-beehive-extension` 插件辅助项目脚本运行~
### 更多分支

- 环境分支

- [electron-init](https://github.com/PDKSophia/visResumeMook/tree/electron-init):关于`Electron`相关的初始化配置代码,只涉及到 Electron
- [electron-react-init](https://github.com/PDKSophia/visResumeMook/tree/electron-react-init):将 `Electron + React` 结合起来的初始化配置代码

- 完整项目
- [master](https://github.com/PDKSophia/visResumeMook):简历平台应用完整项目地址
- [init-cli](https://github.com/PDKSophia/visResumeMook/tree/init-cli):完整配置的分支代码,可以基于此分支直接进行项目开发

> 支持配套学习分支,章节名对应分支名,如有疑问,请提 issues,同时欢迎提 Merge Request

### 小册章节

<img src="./cover.jpg" width=200 />

- [x] [开篇-小册介绍](https://juejin.cn/book/6950646725295996940)
- [x] [开篇-技术选型和项目结构](https://juejin.cn/book/6950646725295996940/section/6962895331667230727)
- [x] [基础篇-Electron 初步认识并掌握基础知识](https://juejin.cn/book/6950646725295996940/section/6961585436967829516)
- [x] [设计篇-需求功能设计与数据存储方案设计](https://juejin.cn/book/6950646725295996940/section/6962435230061821952)
- [x] [环境篇-动手搭建我们的简历平台](https://juejin.cn/book/6950646725295996940/section/6961586491285831720)
- [x] [🏆 500 米里程碑|环境搭建篇完成](https://juejin.cn/book/6950646725295996940/section/6962898545577820198)
- [x] [业务篇-首页开发,好的印象能加分](https://juejin.cn/book/6950646725295996940/section/6962938228357726241)
- [x] [业务篇-如何写我们的 Redux 与 jsonFile](https://juejin.cn/book/6950646725295996940/section/6962906314565484551)
- [x] [业务篇-简历制作之常用组件设计与简历数据设计](https://juejin.cn/book/6950646725295996940/section/6962895451875966989)
- [x] [业务篇-简历制作之入口页面开发](https://juejin.cn/book/6950646725295996940/section/6964550757375246366)
- [x] [业务篇-简历制作之工具条模块与简历模版之间通信](https://juejin.cn/book/6950646725295996940/section/6965876539833450503)
- [x] [业务篇-简历制作之数据的录入与展示](https://juejin.cn/book/6950646725295996940/section/6962940365221396511)
- [x] [业务篇-简历制作之导出 PDF](https://juejin.cn/book/6950646725295996940/section/6962940108383191048)
- [x] [🏆 1000 米里程碑 |简历主流程完成](https://juejin.cn/book/6950646725295996940/section/6962940484008280077)
- [x] [业务篇-首页主题换肤功能实现](https://juejin.cn/book/6950646725295996940/section/6962761759404851239)
- [x] [业务篇-简历模版列表实现与侧边栏交互效果](https://juejin.cn/book/6950646725295996940/section/6962940426999300109)
- [x] [业务篇-简历数据存档且自定义存储路径](https://juejin.cn/book/6950646725295996940/section/6962940676258398222)
- [x] [🏆 1500 米里程碑 |丰富功能](https://juejin.cn/book/6950646725295996940/section/6962939774650810380)
- [x] [优化篇-如何采用 Hooks 优化主题换肤逻辑](https://juejin.cn/book/6950646725295996940/section/6962940589528580132)
- [x] [优化篇-公共弹窗拆解优化,让职能更加单一](https://juejin.cn/book/6950646725295996940/section/6962941125426413599)
- [x] [优化篇-采用 Hooks 优化简历 Form 组件](https://juejin.cn/book/6950646725295996940/section/6962941213401939998)
- [x] [定制篇-自定义 Electron 原生应用菜单](https://juejin.cn/book/6950646725295996940/section/6962938070312157184)
- [x] [打包篇-Webpack 打包优化](https://juejin.cn/book/6950646725295996940/section/6962941321325576226)
- [x] [打包篇-Electron 打包体积优化](https://juejin.cn/book/6950646725295996940/section/6962941003858706436)
- [x] [🏆 到达目的地-应用程序发布](https://juejin.cn/book/6950646725295996940/section/6962941268389265415)
- [x] [结尾篇-行而不辍,未来可期](https://juejin.cn/book/6950646725295996940/section/6962941492159578143)
- [x] [彩蛋篇-Webpack 基础介绍与两大利器](https://juejin.cn/book/6950646725295996940/section/6962895331730620423)
- [x] [彩蛋篇-RcReduxModel 中间件开发设计](https://juejin.cn/book/6950646725295996940/section/6953057493043904549)
- [x] [期望篇-可视化自定义独特的简历模版](https://juejin.cn/editor/book/6950646725295996940/section/6953057711445671943)
16 changes: 10 additions & 6 deletions app/electron.ts → app/main/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
* @desc electron 主入口
*/
import path from 'path';
import { app, BrowserWindow } from 'electron';
import { app, BrowserWindow, ipcMain } from 'electron';

function isDev() {
// 👉 还记得我们配置中通过 webpack.DefinePlugin 定义的构建变量吗
return process.env.NODE_ENV === 'development';
}

Expand All @@ -15,24 +16,27 @@ function createWindow() {
height: 800,
webPreferences: {
devTools: true,
webSecurity: true,
nodeIntegration: true,
},
});

// 加载应用的 index.html。
if (isDev()) {
// 👇 看到了吗,在开发环境下,我们加载的是运行在 7001 端口的 React
mainWindow.loadURL(`http://127.0.0.1:7001`);
} else {
mainWindow.loadURL(`file://${path.join(__dirname, '../src/index.html')}`);
mainWindow.loadURL(`file://${path.join(__dirname, '../dist/index.html')}`);
}
}

app.whenReady().then(() => {
createWindow();
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});

const ROOT_PATH = path.join(app.getAppPath(), '../');

ipcMain.on('get-root-path', (event, arg) => {
event.reply('reply-root-path', ROOT_PATH);
});
15 changes: 15 additions & 0 deletions app/renderer/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Router from './router';
import store from './store';
import { Provider } from 'react-redux';

function App() {
return (
<Provider store={store}>
<Router />
</Provider>
);
}

ReactDOM.render(<App />, document.getElementById('root'));
36 changes: 36 additions & 0 deletions app/renderer/common/components/MyButton/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.es-button {
display: inline-block;
cursor: pointer;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 16px;
font-size: 14px;
color: rgba(0, 0, 0, 0.6);
text-align: center;
user-select: none;
opacity: 1;
&:hover {
opacity: 0.9;
}
}
.es-button-small {
width: 64px;
height: 32px;
line-height: 30px;
}
.es-button-middle {
width: 90px;
height: 36px;
line-height: 34px;
}
.es-button-big {
width: 118px;
height: 42px;
line-height: 40px;
}
.es-button-disabled {
cursor: not-allowed;
}
.es-button-border {
border: 1px solid rgba(0, 0, 0, 0.07);
}
64 changes: 64 additions & 0 deletions app/renderer/common/components/MyButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @description 按钮组件
*/
import React from 'react';
import classnames from 'classnames';
import './index.less';

export interface Button {
/**
* @description 按钮大小
*/
size?: 'middle' | 'big' | 'small';
/**
* @description 宽度
*/
width?: number;
/**
* @description 自定义样式
*/
style?: React.CSSProperties;
/**
* @description 子组件
*/
children?: React.ReactNode | any;
/**
* @description 禁止
*/
disabled?: boolean;
/**
* @description 样式名
*/
className?: string;
/**
* @description 点击事件
*/
onClick?: Function;
/**
* @description 是否显示边框
*/
border?: boolean;
}
function MyButton({ size = 'small', style, width, children, disabled, className, onClick, border = true }: Button) {
return (
<div
style={{
...style,
width: width,
}}
className={className}
styleName={classnames('es-button', {
[`es-button-${size}`]: true,
'es-button-disabled': disabled,
'es-button-border': border,
})}
onClick={() => {
onClick && onClick();
}}
>
{children}
</div>
);
}

export default MyButton;
119 changes: 119 additions & 0 deletions app/renderer/common/components/MyInput/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.my-input {
display: inline-flex;
width: 100%;
height: auto;
line-height: 16px;
font-size: 14px;
box-sizing: border-box;
color: rgba(0, 0, 0, 0.8);
border: 1px solid transparent;

&.normal {
border-radius: 8px;
background: #f8f8f8;

&:hover {
background: #f5f5f5;
}

&:active {
background: #eeeeee;
}

&.focus {
background: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.07);
box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.02);
}
}

.my-input-center {
display: flex;
align-items: center;
justify-content: center;
}

.my-input-input {
position: relative;
width: 100%;
padding: 0 15px;
line-height: 46px;

&.large {
line-height: 62px;

.my-input-clear {
top: 20px;
}
}

input {
border: none;
outline: none;
background: transparent;
width: 100%;
font-family: Arial, Helvetica, sans-serif;
&::-webkit-input-placeholder {
color: rgba(0, 0, 0, 0.2);
}
}
}

.my-input-textarea {
position: relative;
width: 100%;
padding: 12px 15px 32px 15px;
box-sizing: content-box;

&.count-true {
padding-bottom: 27px;
}

textarea {
padding: 0;
width: 100%;
height: 100%;
line-height: 1.5;
border: none;
outline: none;
resize: none;
background: transparent;
font-family: Arial, Helvetica, sans-serif;
&::-webkit-input-placeholder {
color: rgba(0, 0, 0, 0.2);
}
}

.my-input-textarea-footer {
position: absolute;
right: 16px;
bottom: 4px;
font-size: 12px;
color: rgba(0, 0, 0, 0.4);
line-height: 20px;

.max-length-text {
color: #ffab30;
}
}
}

.my-input-clear {
display: block;
position: absolute;
top: 15px;
right: 15px;
width: 16px;
height: 16px;
cursor: pointer;
background: url(../../../../../assets/icon/cancel.png) center;
background-size: cover;
}

&.allow-clear {
.my-input-input,
.my-input-textarea {
padding-right: 46px;
}
}
}
Loading