first commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"presets": [
|
||||
["es2015", { "modules": false }],
|
||||
"stage-3"
|
||||
],
|
||||
"plugins": ["transform-runtime"],
|
||||
"comments": false,
|
||||
"env": {
|
||||
"test": {
|
||||
"plugins": [ "istanbul" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
@@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
.idea/
|
||||
@@ -0,0 +1,34 @@
|
||||
本项目源于:https://github.com/jirengu-inc/animating-resume。向作者表示深深的敬意。
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 安装Node.js环境:https://nodejs.org/
|
||||
|
||||
2. 安装git: https://git-scm.com/
|
||||
|
||||
3. 执行以下命令:
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/sitexa/anires.git
|
||||
cd anires
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## 部署方法
|
||||
|
||||
1. 编辑 config/index.js,修改第 10 行的 assetsPublicPath,值为 `项目名/public`。如果你没有修改项目名 anires,则可跳过此步骤。
|
||||
|
||||
2. 编译、上传
|
||||
|
||||
```
|
||||
bash
|
||||
npm run build
|
||||
git add .
|
||||
git commit -m "update"
|
||||
git push
|
||||
```
|
||||
|
||||
3. 开启 GitHub Pages 功能, 或者,把生成的目标文件```public/*```放在你的web服务器上。
|
||||
|
||||
4,访问地址:https://your-github-username.github.io/anires/public
|
||||
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-cayman
|
||||
@@ -0,0 +1,40 @@
|
||||
// https://github.com/shelljs/shelljs
|
||||
require('./check-versions')()
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
var ora = require('ora')
|
||||
var path = require('path')
|
||||
var chalk = require('chalk')
|
||||
var shell = require('shelljs')
|
||||
var webpack = require('webpack')
|
||||
var config = require('../config')
|
||||
var webpackConfig = require('./webpack.prod.conf')
|
||||
|
||||
var spinner = ora('building for production...')
|
||||
spinner.start()
|
||||
|
||||
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
|
||||
shell.rm('-rf', assetsPath)
|
||||
shell.mkdir('-p', assetsPath)
|
||||
shell.config.silent = true
|
||||
shell.cp('-R', 'static/*', assetsPath)
|
||||
shell.config.silent = false
|
||||
|
||||
webpack(webpackConfig, function (err, stats) {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n')
|
||||
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
))
|
||||
})
|
||||
@@ -0,0 +1,45 @@
|
||||
var chalk = require('chalk')
|
||||
var semver = require('semver')
|
||||
var packageConfig = require('../package.json')
|
||||
|
||||
function exec (cmd) {
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
}
|
||||
|
||||
var versionRequirements = [
|
||||
{
|
||||
name: 'node',
|
||||
currentVersion: semver.clean(process.version),
|
||||
versionRequirement: packageConfig.engines.node
|
||||
},
|
||||
{
|
||||
name: 'npm',
|
||||
currentVersion: exec('npm --version'),
|
||||
versionRequirement: packageConfig.engines.npm
|
||||
}
|
||||
]
|
||||
|
||||
module.exports = function () {
|
||||
var warnings = []
|
||||
for (var i = 0; i < versionRequirements.length; i++) {
|
||||
var mod = versionRequirements[i]
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log()
|
||||
for (var i = 0; i < warnings.length; i++) {
|
||||
var warning = warnings[i]
|
||||
console.log(' ' + warning)
|
||||
}
|
||||
console.log()
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* eslint-disable */
|
||||
require('eventsource-polyfill')
|
||||
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
|
||||
|
||||
hotClient.subscribe(function (event) {
|
||||
if (event.action === 'reload') {
|
||||
window.location.reload()
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,81 @@
|
||||
require('./check-versions')()
|
||||
|
||||
var config = require('../config')
|
||||
if (!process.env.NODE_ENV) {
|
||||
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
|
||||
}
|
||||
|
||||
var opn = require('opn')
|
||||
var path = require('path')
|
||||
var express = require('express')
|
||||
var webpack = require('webpack')
|
||||
var proxyMiddleware = require('http-proxy-middleware')
|
||||
var webpackConfig = require('./webpack.dev.conf')
|
||||
|
||||
// default port where dev server listens for incoming traffic
|
||||
var port = process.env.PORT || config.dev.port
|
||||
// automatically open browser, if not set will be false
|
||||
var autoOpenBrowser = !!config.dev.autoOpenBrowser
|
||||
// Define HTTP proxies to your custom API backend
|
||||
// https://github.com/chimurai/http-proxy-middleware
|
||||
var proxyTable = config.dev.proxyTable
|
||||
|
||||
var app = express()
|
||||
var compiler = webpack(webpackConfig)
|
||||
|
||||
var devMiddleware = require('webpack-dev-middleware')(compiler, {
|
||||
publicPath: webpackConfig.output.publicPath,
|
||||
quiet: true
|
||||
})
|
||||
|
||||
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
|
||||
log: () => {}
|
||||
})
|
||||
// force page reload when html-webpack-plugin template changes
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
|
||||
hotMiddleware.publish({ action: 'reload' })
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
// proxy api requests
|
||||
Object.keys(proxyTable).forEach(function (context) {
|
||||
var options = proxyTable[context]
|
||||
if (typeof options === 'string') {
|
||||
options = { target: options }
|
||||
}
|
||||
app.use(proxyMiddleware(options.filter || context, options))
|
||||
})
|
||||
|
||||
// handle fallback for HTML5 history API
|
||||
app.use(require('connect-history-api-fallback')())
|
||||
|
||||
// serve webpack bundle output
|
||||
app.use(devMiddleware)
|
||||
|
||||
// enable hot-reload and state-preserving
|
||||
// compilation error display
|
||||
app.use(hotMiddleware)
|
||||
|
||||
// serve pure static assets
|
||||
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
|
||||
app.use(staticPath, express.static('./static'))
|
||||
|
||||
var uri = 'http://localhost:' + port
|
||||
|
||||
devMiddleware.waitUntilValid(function () {
|
||||
console.log('> Listening at ' + uri + '\n')
|
||||
})
|
||||
|
||||
module.exports = app.listen(port, function (err) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
|
||||
// when env is testing, don't need open it
|
||||
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
|
||||
opn(uri)
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,64 @@
|
||||
var path = require('path')
|
||||
var config = require('../config')
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
var assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
return path.posix.join(assetsSubDirectory, _path)
|
||||
}
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
// generate loader string to be used with extract text plugin
|
||||
function generateLoaders (loaders) {
|
||||
var sourceLoader = loaders.map(function (loader) {
|
||||
var extraParamChar
|
||||
if (/\?/.test(loader)) {
|
||||
loader = loader.replace(/\?/, '-loader?')
|
||||
extraParamChar = '&'
|
||||
} else {
|
||||
loader = loader + '-loader'
|
||||
extraParamChar = '?'
|
||||
}
|
||||
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
|
||||
}).join('!')
|
||||
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract({
|
||||
use: sourceLoader,
|
||||
fallback: 'vue-style-loader'
|
||||
})
|
||||
} else {
|
||||
return ['vue-style-loader', sourceLoader].join('!')
|
||||
}
|
||||
}
|
||||
|
||||
// http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(['css']),
|
||||
postcss: generateLoaders(['css']),
|
||||
less: generateLoaders(['css', 'less']),
|
||||
sass: generateLoaders(['css', 'sass?indentedSyntax']),
|
||||
scss: generateLoaders(['css', 'sass']),
|
||||
stylus: generateLoaders(['css', 'stylus']),
|
||||
styl: generateLoaders(['css', 'stylus'])
|
||||
}
|
||||
}
|
||||
|
||||
// Generate loaders for standalone style files (outside of .vue)
|
||||
exports.styleLoaders = function (options) {
|
||||
var output = []
|
||||
var loaders = exports.cssLoaders(options)
|
||||
for (var extension in loaders) {
|
||||
var loader = loaders[extension]
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
loader: loader
|
||||
})
|
||||
}
|
||||
return output
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
var utils = require('./utils')
|
||||
var config = require('../config')
|
||||
var isProduction = process.env.NODE_ENV === 'production'
|
||||
|
||||
module.exports = {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: isProduction
|
||||
? config.build.productionSourceMap
|
||||
: config.dev.cssSourceMap,
|
||||
extract: isProduction
|
||||
}),
|
||||
postcss: [
|
||||
require('autoprefixer')({
|
||||
browsers: ['last 2 versions']
|
||||
})
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
var path = require('path')
|
||||
var utils = require('./utils')
|
||||
var config = require('../config')
|
||||
var vueLoaderConfig = require('./vue-loader.conf')
|
||||
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: './src/main.js'
|
||||
},
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: '[name].js',
|
||||
publicPath: process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue', '.json'],
|
||||
modules: [
|
||||
resolve('src'),
|
||||
resolve('node_modules')
|
||||
],
|
||||
alias: {
|
||||
'src': resolve('src'),
|
||||
'assets': resolve('src/assets'),
|
||||
'components': resolve('src/components')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
options: vueLoaderConfig
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [resolve('src'), resolve('test')]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
var utils = require('./utils')
|
||||
var webpack = require('webpack')
|
||||
var config = require('../config')
|
||||
var merge = require('webpack-merge')
|
||||
var baseWebpackConfig = require('./webpack.base.conf')
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
||||
|
||||
// add hot-reload related code to entry chunks
|
||||
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
|
||||
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
|
||||
})
|
||||
|
||||
module.exports = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
|
||||
},
|
||||
// cheap-module-eval-source-map is faster for development
|
||||
devtool: '#cheap-module-eval-source-map',
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': config.dev.env
|
||||
}),
|
||||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: 'index.html',
|
||||
inject: true
|
||||
}),
|
||||
new FriendlyErrorsPlugin()
|
||||
]
|
||||
})
|
||||
@@ -0,0 +1,102 @@
|
||||
var path = require('path')
|
||||
var utils = require('./utils')
|
||||
var webpack = require('webpack')
|
||||
var config = require('../config')
|
||||
var merge = require('webpack-merge')
|
||||
var baseWebpackConfig = require('./webpack.base.conf')
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
var env = config.build.env
|
||||
|
||||
var webpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
extract: true
|
||||
})
|
||||
},
|
||||
devtool: config.build.productionSourceMap ? '#source-map' : false,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false
|
||||
},
|
||||
sourceMap: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css')
|
||||
}),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: config.build.index,
|
||||
template: 'index.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency'
|
||||
}),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks: function (module, count) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
/\.js$/.test(module.resource) &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
)
|
||||
}
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
chunks: ['vendor']
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
if (config.build.productionGzip) {
|
||||
var CompressionWebpackPlugin = require('compression-webpack-plugin')
|
||||
|
||||
webpackConfig.plugins.push(
|
||||
new CompressionWebpackPlugin({
|
||||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (config.build.bundleAnalyzerReport) {
|
||||
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
@@ -0,0 +1,6 @@
|
||||
var merge = require('webpack-merge')
|
||||
var prodEnv = require('./prod.env')
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"'
|
||||
})
|
||||
@@ -0,0 +1,38 @@
|
||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
var path = require('path')
|
||||
|
||||
module.exports = {
|
||||
build: {
|
||||
env: require('./prod.env'),
|
||||
index: path.resolve(__dirname, '../public/index.html'),
|
||||
assetsRoot: path.resolve(__dirname, '../public'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/anires/public/',
|
||||
productionSourceMap: true,
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
// Before setting to `true`, make sure to:
|
||||
// npm install --save-dev compression-webpack-plugin
|
||||
productionGzip: false,
|
||||
productionGzipExtensions: ['js', 'css'],
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report
|
||||
},
|
||||
dev: {
|
||||
env: require('./dev.env'),
|
||||
port: 8080,
|
||||
autoOpenBrowser: true,
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {},
|
||||
// CSS Sourcemaps off by default because relative paths are "buggy"
|
||||
// with this option, according to the CSS-Loader README
|
||||
// (https://github.com/webpack/css-loader#sourcemaps)
|
||||
// In our experience, they generally work as expected,
|
||||
// just be aware of this issue when enabling this option.
|
||||
cssSourceMap: false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-Hans">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="refresh" content="0; url=https://www.sitexa.org/anires/public/" />
|
||||
<title>跳转中</title>
|
||||
</head>
|
||||
<body>
|
||||
跳转中...
|
||||
</body>
|
||||
</html>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>个人简历</title>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
Generated
+7641
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "animation-resume",
|
||||
"version": "1.0.0",
|
||||
"description": "animation resume",
|
||||
"author": " <>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "node build/dev-server.js",
|
||||
"build": "node build/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"marked": "^0.3.9",
|
||||
"prismjs": "^1.6.0",
|
||||
"vue": "^2.1.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.7.2",
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-loader": "^6.2.10",
|
||||
"babel-plugin-transform-runtime": "^6.22.0",
|
||||
"babel-preset-es2015": "^6.22.0",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-preset-stage-3": "^6.22.0",
|
||||
"babel-register": "^6.22.0",
|
||||
"chalk": "^1.1.3",
|
||||
"connect-history-api-fallback": "^1.3.0",
|
||||
"css-loader": "^0.26.1",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"express": "^4.14.1",
|
||||
"extract-text-webpack-plugin": "^2.0.0-rc.2",
|
||||
"file-loader": "^0.10.0",
|
||||
"friendly-errors-webpack-plugin": "^1.1.3",
|
||||
"function-bind": "^1.1.0",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"http-proxy-middleware": "^0.17.3",
|
||||
"opn": "^4.0.2",
|
||||
"ora": "^1.1.0",
|
||||
"semver": "^5.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"url-loader": "^0.5.7",
|
||||
"vue-loader": "^10.3.0",
|
||||
"vue-style-loader": "^2.0.0",
|
||||
"vue-template-compiler": "^2.1.10",
|
||||
"webpack": "^2.2.1",
|
||||
"webpack-bundle-analyzer": "^2.2.1",
|
||||
"webpack-dev-middleware": "^1.10.0",
|
||||
"webpack-hot-middleware": "^2.16.1",
|
||||
"webpack-merge": "^2.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><title>个人简历</title><meta name=viewport content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link href=/anires/public/static/css/app.97f24077373dbd5f86744ecd100255e7.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/anires/public/static/js/manifest.22a4ae013e2ceb48b7dd.js></script><script type=text/javascript src=/anires/public/static/js/vendor.045b08f12500b7884e7e.js></script><script type=text/javascript src=/anires/public/static/js/app.c4b2e14682ed119846b5.js></script></body></html>
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
#app[data-v-22ce9519] {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
html[data-v-22ce9519] {
|
||||
min-height: 100vh;
|
||||
}
|
||||
*[data-v-22ce9519] {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
pre[data-v-35c047fd]{
|
||||
}
|
||||
@media (max-width:500px){
|
||||
pre[data-v-35c047fd]{
|
||||
}
|
||||
}
|
||||
.code[data-v-35c047fd] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width:500px){
|
||||
.resumeEditor[data-v-647e008b]{
|
||||
}
|
||||
}
|
||||
.htmlMode[data-v-647e008b] {
|
||||
animation: flip 2s;
|
||||
}
|
||||
@keyframes flip {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:500px){
|
||||
.thankEditor[data-v-29ad1df6]{
|
||||
}
|
||||
}
|
||||
.htmlMode[data-v-29ad1df6] {
|
||||
animation: flip 2s;
|
||||
}
|
||||
@keyframes flip {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
*{margin: 0; padding: 0;}
|
||||
*{box-sizing: border-box;}
|
||||
*::before{box-sizing: border-box;}
|
||||
*::after{box-sizing: border-box;}
|
||||
|
||||
#app[data-v-53c8d54c] {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
min-height: 100vh; position: relative;
|
||||
}
|
||||
html[data-v-53c8d54c] {
|
||||
min-height: 100vh;
|
||||
}
|
||||
*[data-v-53c8d54c]{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=app.97f24077373dbd5f86744ecd100255e7.css.map*/
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///./src/App.vue","webpack:///./src/components/StyleEditor.vue","webpack:///./src/components/ResumeEditor.vue","webpack:///./src/components/ThankEditor.vue","webpack:///./src/assets/reset.css","webpack:///./src/Mobile.vue"],"names":[],"mappings":";AACA;EACE,oDAAoD;EACpD,oCAAoC;EACpC,mCAAmC;CACpC;AACD;EACE,kBAAkB;CACnB;AACD;EACE,uBAAuB;CACxB;;ACVD;CACC;AACD;AACA;CACC;CACA;AACD;EACE,cAAc;CACf;;ACRD;AACA;CACC;CACA;AACD;EACE,mBAAmB;CACpB;AACD;AACA;IACI,WAAW;CACd;AACD;IACI,WAAW;CACd;CACA;;ACdD;AACA;CACC;CACA;AACD;EACE,mBAAmB;CACpB;AACD;AACA;IACI,WAAW;CACd;AACD;IACI,WAAW;CACd;CACA;ACfD,EAAE,UAAU,CAAC,WAAW,CAAC;AACzB,EAAE,uBAAuB,CAAC;AAC1B,UAAU,uBAAuB,CAAC;AAClC,SAAS,uBAAuB,CAAC;;ACFjC;EACE,oDAAoD;EACpD,oCAAoC;EACpC,mCAAmC;EACnC,kBAAkB,CAAC,mBAAmB;CACvC;AACD;EACE,kBAAkB;CACnB;AACD;EACE,uBAAuB;CACxB","file":"static/css/app.97f24077373dbd5f86744ecd100255e7.css","sourcesContent":["\n#app[data-v-22ce9519] {\n font-family: 'Avenir', Helvetica, Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\nhtml[data-v-22ce9519] {\n min-height: 100vh;\n}\n*[data-v-22ce9519] {\n box-sizing: border-box;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/App.vue","\npre[data-v-35c047fd]{\n}\n@media (max-width:500px){\npre[data-v-35c047fd]{\n}\n}\n.code[data-v-35c047fd] {\n display: none;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/StyleEditor.vue","\n@media (max-width:500px){\n.resumeEditor[data-v-647e008b]{\n}\n}\n.htmlMode[data-v-647e008b] {\n animation: flip 2s;\n}\n@keyframes flip {\nfrom {\n opacity: 0;\n}\nto {\n opacity: 1;\n}\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/ResumeEditor.vue","\n@media (max-width:500px){\n.thankEditor[data-v-29ad1df6]{\n}\n}\n.htmlMode[data-v-29ad1df6] {\n animation: flip 2s;\n}\n@keyframes flip {\nfrom {\n opacity: 0;\n}\nto {\n opacity: 1;\n}\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/ThankEditor.vue","*{margin: 0; padding: 0;}\n*{box-sizing: border-box;}\n*::before{box-sizing: border-box;}\n*::after{box-sizing: border-box;}\n\n\n\n// WEBPACK FOOTER //\n// ./src/assets/reset.css","\n#app[data-v-53c8d54c] {\n font-family: 'Avenir', Helvetica, Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n min-height: 100vh; position: relative;\n}\nhtml[data-v-53c8d54c] {\n min-height: 100vh;\n}\n*[data-v-53c8d54c]{\n box-sizing: border-box;\n}\n\n\n\n\n// WEBPACK FOOTER //\n// ./src/Mobile.vue"],"sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,f,s=0,l=[];s<t.length;s++)a=t[s],o[a]&&l.push(o[a][0]),o[a]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,i);l.length;)l.shift()();if(i)for(s=0;s<i.length;s++)f=n(n.s=i[s]);return f};var t={},o={2:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var i=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+"static/js/"+e+"."+{0:"045b08f12500b7884e7e",1:"c4b2e14682ed119846b5"}[e]+".js";var a=setTimeout(r,12e4);return u.onerror=u.onload=r,i.appendChild(u),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/anires/public/",n.oe=function(e){throw console.error(e),e}}([]);
|
||||
//# sourceMappingURL=manifest.22a4ae013e2ceb48b7dd.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+405
@@ -0,0 +1,405 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<div id="content">
|
||||
<StyleEditor ref="styleEditor" :code="currentStyle"></StyleEditor>
|
||||
<ResumeEditor ref="resumeEditor" :markdown="currentMarkdown" :enableHtml="enableHtml"></ResumeEditor>
|
||||
</div>
|
||||
<div id="foot">
|
||||
<ThankEditor ref="thankEditor" :markdown="currentThankMarkdown" :enableHtml="enableHtml"></ThankEditor>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StyleEditor from './components/StyleEditor'
|
||||
import ResumeEditor from './components/ResumeEditor'
|
||||
import ThankEditor from './components/ThankEditor'
|
||||
import './assets/reset.css'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
StyleEditor,
|
||||
ResumeEditor,
|
||||
ThankEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
interval: 5,
|
||||
currentStyle: '',
|
||||
enableHtml: false,
|
||||
fullStyle: [
|
||||
`/*
|
||||
* Inspired by http://strml.net/
|
||||
* 源码地址 https://github.com/sitexa/anires
|
||||
* 大家好,我是南方。
|
||||
* 我来写一份简历!
|
||||
*/
|
||||
|
||||
/* 给所有元素加上过渡效果 */
|
||||
* {
|
||||
transition: all .1s;
|
||||
}
|
||||
/* 设置背景颜色 */
|
||||
html {
|
||||
color: rgb(222,222,222); background: rgb(0,64,64);
|
||||
}
|
||||
#content{
|
||||
height:70vh;
|
||||
margin:0;
|
||||
}
|
||||
#foot{
|
||||
height:29vh;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
/* 设置边框 */
|
||||
.styleEditor {
|
||||
padding: .5em;
|
||||
border: 1px solid;
|
||||
margin: .5em;
|
||||
overflow: auto;
|
||||
width: 50vw; height: 70vh;
|
||||
background: rgb(20,20,20);
|
||||
}
|
||||
/* 代码高亮 */
|
||||
.token.selector{ color: rgb(130,150,0); }
|
||||
.token.property{ color: rgb(190,140,0); }
|
||||
.token.punctuation{ color: yellow; }
|
||||
.token.function{ color: rgb(40,160,150); }
|
||||
|
||||
/* 加3D效果 */
|
||||
html{
|
||||
perspective: 1000px;
|
||||
}
|
||||
.styleEditor {
|
||||
position: fixed; left: 0; top: 0;
|
||||
-webkit-transition: none;
|
||||
transition: none;
|
||||
-webkit-transform: rotateY(10deg) translateZ(-100px) ;
|
||||
transform: rotateY(10deg) translateZ(-100px) ;
|
||||
}
|
||||
|
||||
/* 准备一个编辑器 */
|
||||
.resumeEditor{
|
||||
position: fixed; right: 0; top: 0;
|
||||
padding: .5em; margin: .5em;
|
||||
width: 50vw; height: 70vh;
|
||||
border: 1px solid;
|
||||
background: rgb(200,200,200); color: #222;
|
||||
overflow: auto;
|
||||
-webkit-transition: none;
|
||||
transition: none;
|
||||
-webkit-transform: rotateY(-10deg) translateZ(-100px) ;
|
||||
transform: rotateY(-10deg) translateZ(-100px) ;
|
||||
}
|
||||
/* 开始写简历 */
|
||||
`, `
|
||||
/*将Markdown格式翻译成HTML
|
||||
*再对HTML加点样式
|
||||
*/
|
||||
.resumeEditor{
|
||||
padding: 2em;
|
||||
}
|
||||
.resumeEditor h2{
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid;
|
||||
margin: 1em 0 .5em;
|
||||
}
|
||||
.resumeEditor ul,.resumeEditor ol{
|
||||
list-style: none;
|
||||
}
|
||||
.resumeEditor ul> li::before{
|
||||
content: '•';
|
||||
margin-right: .5em;
|
||||
}
|
||||
.resumeEditor ol {
|
||||
counter-reset: section;
|
||||
}
|
||||
.resumeEditor ol li::before {
|
||||
counter-increment: section;
|
||||
content: counters(section, ".") " ";
|
||||
margin-right: .5em;
|
||||
}
|
||||
.resumeEditor blockquote {
|
||||
margin: 1em;
|
||||
padding: .5em;
|
||||
background: #ddd;
|
||||
}
|
||||
`, `/* 写封感谢信。
|
||||
* 感谢大家对我的关注。
|
||||
*/
|
||||
.styleEditor{
|
||||
width:50vw;height:70vh;
|
||||
}
|
||||
|
||||
.resumeEditor{
|
||||
width:50vw;height:70vh;
|
||||
}
|
||||
|
||||
.thankEditor{
|
||||
position: relative; left: 0; top: 0;
|
||||
background: #E9D9BB;
|
||||
color: #001C42;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.thankEditor {
|
||||
width: 99vw; height: 45vh;
|
||||
border: 1px solid #ccc;
|
||||
font-size: .9em;
|
||||
}
|
||||
`,`
|
||||
.thankEditor{
|
||||
padding: .5em; margin: .5em; margin-top:1em;
|
||||
}
|
||||
|
||||
.thankEditor ul,.thankEditor ol{
|
||||
list-style: none;
|
||||
}
|
||||
.thankEditor ul> li::before{
|
||||
content: '☞'; color: red;
|
||||
margin-right: .5em;
|
||||
}
|
||||
.thankEditor ol {
|
||||
counter-reset: section;
|
||||
}
|
||||
.thankEditor ol li::before {
|
||||
counter-increment: section;
|
||||
content: counters(section, "☞") " ";
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.thankEditor{
|
||||
width: 99vw; height: 45vh;
|
||||
-webkit-transition: none;
|
||||
transition: none;
|
||||
-webkit-transform: rotateX(-10deg) translateZ(-200px);
|
||||
transform: rotateX(-10deg) translateZ(-200px);
|
||||
}
|
||||
|
||||
`],
|
||||
currentMarkdown: '',
|
||||
currentThankMarkdown: '',
|
||||
fullMarkdown: `南方
|
||||
====
|
||||
|
||||
坐标:湖南长沙。
|
||||
|
||||
资深软件工程师,资深产品经理,高级项目经理。现为自由职业。
|
||||
|
||||
技能
|
||||
====
|
||||
|
||||
数据库设计
|
||||
----
|
||||
- 结构化数据库设计
|
||||
- noSQL设计
|
||||
|
||||
后端开发
|
||||
----
|
||||
- 用户管理
|
||||
- 单点登录
|
||||
- 第三方登录
|
||||
- 权限管理
|
||||
- 交易系统
|
||||
- 支付系统
|
||||
- 社区系统
|
||||
- 博客系统
|
||||
- 公众号开发
|
||||
- 小程序开发
|
||||
- API接口开发
|
||||
|
||||
前端开发
|
||||
----
|
||||
- Web前端开发
|
||||
- 移动终端(Native App, Hybrid App)
|
||||
|
||||
产品设计
|
||||
----
|
||||
- 智慧旅游项目
|
||||
- 运动健康云平台
|
||||
- 社区支持农业O2O项目
|
||||
- 省级环境监控平台
|
||||
- 高速公路异地处罚系统
|
||||
- 环保局办公自动化系统
|
||||
- 保险公司数据迁移项目
|
||||
- 啤酒厂供应链项目
|
||||
- 货运代理系统
|
||||
- 集装箱管理系统
|
||||
- 滞期费管理项目
|
||||
|
||||
技术及语言
|
||||
----
|
||||
- Java: SpringMVC, SpringCloud, Hibernate, iBatis, spark, sql2o, HikariCP, freemarker, okHttp, retrofit, RxJava
|
||||
- Kotlin: ktor, exposed, anko
|
||||
- Node.js: express, angular, ionic, react, cordova, meteor, electron, axios
|
||||
- Swift: Vapor, ReactiveSwift
|
||||
- Golang: hugo, beego, gorm, sqlx, matcha
|
||||
- Python: tushare, pandas, numpy, matplotlib
|
||||
- DotNet and PHP
|
||||
- DB: SQLServer, Oracle, MySQL/MariaDB, MongoDB, graphQL, redis, memcached
|
||||
- WebServer: apache, nginx, tomcat, netty, jetty
|
||||
- OS: Ubuntu, CentOS, MacOS, Windows
|
||||
- Others: Docker, git, Xmind,Axure
|
||||
|
||||
工作经历
|
||||
----
|
||||
|
||||
1. 湖南融耀健康管理有限公司
|
||||
2. 湖南三英特旅游智能技术有限公司
|
||||
3. 合肥蓝盾科技有限公司
|
||||
4. 上海易保网络有限公司
|
||||
5. 厦门海环计算机软件有限公司
|
||||
|
||||
教育经历
|
||||
----
|
||||
|
||||
1. 华东理工大学 环境工程学士
|
||||
2. 厦门大学 系统工程硕士
|
||||
|
||||
文章
|
||||
----
|
||||
|
||||
* [故土难离(我的父亲母亲)](https://www.meipian.cn/qacqfbz?uuid=d541c15eef694065bc9d1ac9a07925a2)
|
||||
* [油腻腻的中年(小诗)](https://www.meipian.cn/wjaz3zh?uuid=ca1cd053b717451da781786de44e66e7)
|
||||
* [生命(老四们的蝼蚁人生)](https://www.meipian.cn/vc4pr59?uuid=799c98f5a187405c94c86f7da7788869)
|
||||
* [大健康商业模式](http://www.sitexa.org/technology/%E5%A4%A7%E5%81%A5%E5%BA%B7%E5%95%86%E4%B8%9A%E6%A8%A1%E5%BC%8F.html)
|
||||
* [社区社交商业模型](http://www.sitexa.org/other/%E7%A4%BE%E5%8C%BA%E7%A4%BE%E4%BA%A4%E5%95%86%E4%B8%9A%E6%A8%A1%E5%9E%8B.html)
|
||||
|
||||
链接
|
||||
----
|
||||
|
||||
* [GitHub](https://github.com/sitexa)
|
||||
* [技术博客](http://www.sitexa.org)
|
||||
* [南方时代](http://www.sitexa.net)
|
||||
* [神秘湘鄂西](http://www.sitexa.cn)
|
||||
* [我的简历故事(程序人生公众号文章)](https://mp.weixin.qq.com/s/5rsB956EPVm0FoFOe6xYTg)
|
||||
|
||||
勾引方式
|
||||
----
|
||||
|
||||
* 微信:xnpeng
|
||||
|
||||
`, thanksMarkdown: `
|
||||
鸣谢
|
||||
----
|
||||
|
||||
* 这段时间,我有些诚煌诚恐。我的简历被很多人关注(49842),我码的那几篇文章也有很多人点击(20095),微信好友增加了2000多人。"程序人生"公众号文章(我的简历故事)阅读量超过十万+。
|
||||
* 有很多企业向我发出了面试邀请,有很多创业团队向我伸出了橄榄枝,一些朋友给我提出非常好的建议,还有很多同学希望跟我进行技术交流,甚至有些企业问我能否承接外包业务。
|
||||
* 于是,我受命下山,到了深圳、珠海、北京、天津等地,拜访了一些老板,结识了一些新朋友,见了一些同学和老同事,感触很多,收获很大。IT行业正在发生深刻的变化,新技术、新模式、新思维、新业态,层出不穷,各种探索,各种炒作,让人眼花缭乱。
|
||||
* 我对自己也有了一个新的认识。我逐渐发现,我不是去找一份工作,而是在寻找一些机会,一些志同道合的伙伴,一份激动人心的事业。很荣幸,已经有几个朋友跟我达成了意向,准备组建团队。
|
||||
* 到底做什么项目呢?我只能简单地说,社交+电商+区块链。肯定有人要说,这个题目太大了,是蹭热度。我不这样想。我以前对社交的思考中,一个重要的因素就是信任关系,而对电商的思考中,去中心化是一个核心考量。而区块链技术不正是解决信任机制和去中心化的利器么?
|
||||
* 在此,我欢迎有兴趣的朋友加入我们,尽快推进项目的实施。(微信:xnpeng)
|
||||
|
||||
`
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.makeResume()
|
||||
},
|
||||
|
||||
methods: {
|
||||
makeResume: async function () {
|
||||
await this.progressivelyShowStyle(0);
|
||||
await this.progressivelyShowResume();
|
||||
await this.progressivelyShowStyle(1);
|
||||
await this.showHtml();
|
||||
await this.progressivelyShowStyle(2);
|
||||
await this.progressivelyShowThanks();
|
||||
await this.progressivelyShowStyle(3)
|
||||
},
|
||||
showHtml() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.enableHtml = true
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
progressivelyShowStyle(n) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let interval = this.interval
|
||||
let showStyle = (async function () {
|
||||
let style = this.fullStyle[n]
|
||||
if (!style) {
|
||||
return
|
||||
}
|
||||
// 计算前 n 个 style 的字符总数
|
||||
let length = this.fullStyle.filter((_, index) => index <= n).map((item) => item.length).reduce((p, c) => p + c, 0)
|
||||
let prefixLength = length - style.length
|
||||
if (this.currentStyle.length < length) {
|
||||
let l = this.currentStyle.length - prefixLength
|
||||
let char = style.substring(l, l + 1) || ' '
|
||||
this.currentStyle += char
|
||||
if (style.substring(l - 1, l) === '\n' && this.$refs.styleEditor) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.styleEditor.goBottom()
|
||||
})
|
||||
}
|
||||
setTimeout(showStyle, interval)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}).bind(this)
|
||||
showStyle()
|
||||
})
|
||||
},
|
||||
progressivelyShowResume() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let length = this.fullMarkdown.length
|
||||
let interval = this.interval
|
||||
let showResume = () => {
|
||||
if (this.currentMarkdown.length < length) {
|
||||
this.currentMarkdown = this.fullMarkdown.substring(0, this.currentMarkdown.length + 1)
|
||||
let lastChar = this.currentMarkdown[this.currentMarkdown.length - 1]
|
||||
let prevChar = this.currentMarkdown[this.currentMarkdown.length - 2]
|
||||
if (prevChar === '\n' && this.$refs.resumeEditor) {
|
||||
this.$nextTick(() => this.$refs.resumeEditor.goBottom())
|
||||
}
|
||||
setTimeout(showResume, interval)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
showResume()
|
||||
})
|
||||
},
|
||||
progressivelyShowThanks() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let length = this.thanksMarkdown.length
|
||||
let interval = this.interval
|
||||
let showThanks = () => {
|
||||
if (this.currentThankMarkdown.length < length) {
|
||||
this.currentThankMarkdown = this.thanksMarkdown.substring(0, this.currentThankMarkdown.length + 1)
|
||||
let lastChar = this.currentThankMarkdown[this.currentThankMarkdown.length - 1]
|
||||
let prevChar = this.currentThankMarkdown[this.currentThankMarkdown.length - 2]
|
||||
if (prevChar === '\n' && this.$refs.thankEditor) {
|
||||
this.$nextTick(() => this.$refs.thankEditor.goBottom())
|
||||
}
|
||||
setTimeout(showThanks, interval)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
showThanks()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<StyleEditor ref="styleEditor" :code="currentStyle"></StyleEditor>
|
||||
<ResumeEditor ref="resumeEditor" :markdown="currentMarkdown" :enableHtml="enableHtml"></ResumeEditor>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import StyleEditor from './components/StyleEditor'
|
||||
import ResumeEditor from './components/ResumeEditor'
|
||||
import './assets/reset.css'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
StyleEditor,
|
||||
ResumeEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
interval: 5,
|
||||
currentStyle: '',
|
||||
enableHtml: false,
|
||||
fullStyle: [
|
||||
`/*
|
||||
* Inspired by http://strml.net/
|
||||
* 源码地址 https://github.com/sitexa/anires
|
||||
* 大家好,我是南方。
|
||||
* 我来写一份简历!
|
||||
*/
|
||||
|
||||
/* 给所有元素加上过渡效果 */
|
||||
* {
|
||||
transition: all .2s;
|
||||
}
|
||||
/* 设置背景颜色 */
|
||||
html {
|
||||
color: rgb(222,222,222);
|
||||
background: rgb(0,43,54);
|
||||
}
|
||||
/* 设置边框 */
|
||||
.styleEditor {
|
||||
padding: .5em;
|
||||
border: 1px solid;
|
||||
overflow: auto;
|
||||
width: 90vw;
|
||||
margin: 2.5vh 5vw;
|
||||
height: 90vh;
|
||||
}
|
||||
/* 太高了 */
|
||||
.styleEditor {
|
||||
height: 45vh;
|
||||
}
|
||||
/* 代码高亮 */
|
||||
.token.selector{
|
||||
color: rgb(133,153,0);
|
||||
}
|
||||
.token.property{
|
||||
color: rgb(187,137,0);
|
||||
}
|
||||
.token.punctuation{
|
||||
color: yellow;
|
||||
}
|
||||
.token.function{
|
||||
color: rgb(42,161,152);
|
||||
}
|
||||
|
||||
/* 加3D效果 */
|
||||
html{
|
||||
perspective: 1000px;
|
||||
}
|
||||
.styleEditor {
|
||||
position: fixed; left: 0; top: 0;
|
||||
transform: rotateX(-10deg) translateZ(-50px) ;
|
||||
}
|
||||
|
||||
/* 准备一个编辑器 */
|
||||
.resumeEditor{
|
||||
position: fixed;
|
||||
top: 50%; left: 0;
|
||||
padding: .5em; margin: 2.5vh;
|
||||
width: 95vw; height: 45vh;
|
||||
border: 1px solid;
|
||||
background: white; color: #222;
|
||||
overflow: auto;
|
||||
}
|
||||
/* 开始写简历 */
|
||||
|
||||
|
||||
`,
|
||||
`
|
||||
/*将Markdown格式翻译成HTML
|
||||
*再对HTML加点样式
|
||||
*/
|
||||
`, `
|
||||
.resumeEditor{
|
||||
padding: 2em;
|
||||
}
|
||||
.resumeEditor h2{
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid;
|
||||
margin: 1em 0 .5em;
|
||||
}
|
||||
.resumeEditor ul,.resumeEditor ol{
|
||||
list-style: none;
|
||||
}
|
||||
.resumeEditor ul> li::before{
|
||||
content: '•';
|
||||
margin-right: .5em;
|
||||
}
|
||||
.resumeEditor ol {
|
||||
counter-reset: section;
|
||||
}
|
||||
.resumeEditor ol li::before {
|
||||
counter-increment: section;
|
||||
content: counters(section, ".") " ";
|
||||
margin-right: .5em;
|
||||
}
|
||||
.resumeEditor blockquote {
|
||||
margin: 1em;
|
||||
padding: .5em;
|
||||
background: #ddd;
|
||||
}
|
||||
`],
|
||||
currentMarkdown: '',
|
||||
fullMarkdown: `南方
|
||||
====
|
||||
坐标:湖南长沙。
|
||||
|
||||
资深软件工程师,资深产品经理,高级项目经理。现为自由职业。
|
||||
|
||||
技能
|
||||
====
|
||||
|
||||
数据库设计
|
||||
----
|
||||
- 结构化数据库设计
|
||||
- noSQL设计
|
||||
|
||||
后端开发
|
||||
----
|
||||
- 用户管理
|
||||
- 单点登录
|
||||
- 第三方登录
|
||||
- 权限管理
|
||||
- 交易系统
|
||||
- 支付系统
|
||||
- 社区系统
|
||||
- 博客系统
|
||||
- 公众号开发
|
||||
- 小程序开发
|
||||
- API接口
|
||||
|
||||
前端开发
|
||||
----
|
||||
- Web前端开发
|
||||
- 移动终端(Native App, Hybrid App)
|
||||
|
||||
产品设计
|
||||
----
|
||||
- 智慧旅游项目
|
||||
- 运动健康云平台
|
||||
- 社区支持农业O2O项目
|
||||
- 省级环境监控平台
|
||||
- 高速公路异地处罚系统
|
||||
- 环保局办公自动化系统
|
||||
- 保险公司数据迁移项目
|
||||
- 啤酒厂供应链项目
|
||||
- 货运代理系统
|
||||
- 集装箱管理系统
|
||||
- 滞期费管理项目
|
||||
|
||||
技术及语言
|
||||
----
|
||||
- Java: SpringMVC, SpringCloud, Hibernate, iBatis, spark, sql2o, HikariCP, freemarker, okHttp, retrofit, RxJava
|
||||
- Kotlin: ktor, exposed, anko
|
||||
- Node.js: express, angular, ionic, react, cordova, meteor, electron, axios
|
||||
- Swift: Vapor, ReactiveSwift
|
||||
- Golang: hugo, beego, gorm, sqlx, matcha
|
||||
- Python: tushare, pandas, numpy, matplotlib
|
||||
- DotNet and PHP
|
||||
- DB: SQLServer, Oracle, MySQL/MariaDB, MongoDB, graphQL, redis, memcached
|
||||
- WebServer: apache, nginx, tomcat, netty, jetty
|
||||
- OS: Ubuntu, CentOS, MacOS, Windows
|
||||
- Others: Docker, git, Xmind,Axure
|
||||
|
||||
工作经历
|
||||
====
|
||||
|
||||
1. 湖南融耀健康管理有限公司
|
||||
2. 湖南三英特旅游智能技术有限公司
|
||||
3. 合肥蓝盾科技有限公司
|
||||
4. 上海易保网络有限公司
|
||||
5. 厦门海环计算机软件有限公司
|
||||
|
||||
教育经历
|
||||
====
|
||||
|
||||
1. 华东理工大学 环境工程学士
|
||||
2. 厦门大学 系统工程硕士
|
||||
|
||||
文章
|
||||
====
|
||||
|
||||
* [故土难离(我的父亲母亲)](https://www.meipian.cn/qacqfbz?uuid=d541c15eef694065bc9d1ac9a07925a2)
|
||||
* [油腻腻的中年(小诗)](https://www.meipian.cn/wjaz3zh?uuid=ca1cd053b717451da781786de44e66e7)
|
||||
* [生命(老四们的蝼蚁人生)](https://www.meipian.cn/vc4pr59?uuid=799c98f5a187405c94c86f7da7788869)
|
||||
* [大健康商业模式](http://www.sitexa.org/technology/%E5%A4%A7%E5%81%A5%E5%BA%B7%E5%95%86%E4%B8%9A%E6%A8%A1%E5%BC%8F.html)
|
||||
* [社区社交商业模型](http://www.sitexa.org/other/%E7%A4%BE%E5%8C%BA%E7%A4%BE%E4%BA%A4%E5%95%86%E4%B8%9A%E6%A8%A1%E5%9E%8B.html)
|
||||
|
||||
链接
|
||||
====
|
||||
|
||||
* [GitHub](https://github.com/sitexa)
|
||||
* [技术博客](http://www.sitexa.org)
|
||||
* [南方时代](http://www.sitexa.net)
|
||||
* [神秘湘鄂西](http://www.sitexa.cn)
|
||||
* [我的简历故事(程序人生公众号文章)](https://mp.weixin.qq.com/s/5rsB956EPVm0FoFOe6xYTg)
|
||||
|
||||
勾引方式
|
||||
====
|
||||
|
||||
* 微信:xnpeng
|
||||
|
||||
鸣谢
|
||||
----
|
||||
|
||||
* 这段时间,我有些诚煌诚恐。我的简历被很多人关注(49842),我码的那几篇文章也有很多人点击(20095),微信好友增加了2000多人。"程序人生"公众号文章(我的简历故事)阅读量超过十万+。
|
||||
* 有很多企业向我发出了面试邀请,有很多创业团队向我伸出了橄榄枝,一些朋友给我提出非常好的建议,还有很多同学希望跟我进行技术交流,甚至有些企业问我能否承接外包业务。
|
||||
* 于是,我受命下山,到了深圳、珠海、北京、天津等地,拜访了一些老板,结识了一些新朋友,见了一些同学和老同事,感触很多,收获很大。IT行业正在发生深刻的变化,新技术、新模式、新思维、新业态,层出不穷,各种探索,各种炒作,让人眼花缭乱。
|
||||
* 我对自己也有了一个新的认识。我逐渐发现,我不是去找一份工作,而是在寻找一些机会,一些志同道合的伙伴,一份激动人心的事业。很荣幸,已经有几个朋友跟我达成了意向,准备组建团队。
|
||||
* 到底做什么项目呢?我只能简单地说,社交+电商+区块链。肯定有人要说,这个题目太大了,是蹭热度。我不这样想。我以前对社交的思考中,一个重要的因素就是信任关系,而对电商的思考中,去中心化是一个核心考量。而区块链技术不正是解决信任机制和去中心化的利器么?
|
||||
* 在此,我欢迎有兴趣的朋友加入我们,尽快推进项目的实施。
|
||||
|
||||
`
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.makeResume()
|
||||
},
|
||||
|
||||
methods: {
|
||||
makeResume: async function () {
|
||||
await this.progressivelyShowStyle(0)
|
||||
await this.progressivelyShowResume()
|
||||
await this.progressivelyShowStyle(1)
|
||||
await this.showHtml()
|
||||
await this.progressivelyShowStyle(2)
|
||||
},
|
||||
showHtml: function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.enableHtml = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.resumeEditor.goTop()
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
progressivelyShowStyle(n) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let interval = this.interval
|
||||
let showStyle = (async function () {
|
||||
let style = this.fullStyle[n]
|
||||
if (!style) { return }
|
||||
// 计算前 n 个 style 的字符总数
|
||||
let length = this.fullStyle.filter((_, index) => index <= n).map((item) => item.length).reduce((p, c) => p + c, 0)
|
||||
let prefixLength = length - style.length
|
||||
if (this.currentStyle.length < length) {
|
||||
let l = this.currentStyle.length - prefixLength
|
||||
let char = style.substring(l, l + 1) || ' '
|
||||
this.currentStyle += char
|
||||
if (style.substring(l - 1, l) === '\n' && this.$refs.styleEditor) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.styleEditor.goBottom()
|
||||
})
|
||||
}
|
||||
setTimeout(showStyle, interval)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}).bind(this)
|
||||
showStyle()
|
||||
})
|
||||
},
|
||||
progressivelyShowResume() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let length = this.fullMarkdown.length
|
||||
let interval = this.interval
|
||||
let showResume = () => {
|
||||
if (this.currentMarkdown.length < length) {
|
||||
this.currentMarkdown = this.fullMarkdown.substring(0, this.currentMarkdown.length + 1)
|
||||
let lastChar = this.currentMarkdown[this.currentMarkdown.length - 1]
|
||||
let prevChar = this.currentMarkdown[this.currentMarkdown.length - 2]
|
||||
if (prevChar === '\n' && this.$refs.resumeEditor) {
|
||||
this.$nextTick(() => this.$refs.resumeEditor.goBottom())
|
||||
}
|
||||
setTimeout(showResume, interval)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
showResume()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
min-height: 100vh; position: relative;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100vh;
|
||||
}
|
||||
*{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
</style>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,4 @@
|
||||
*{margin: 0; padding: 0;}
|
||||
*{box-sizing: border-box;}
|
||||
*::before{box-sizing: border-box;}
|
||||
*::after{box-sizing: border-box;}
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="resumeEditor" :class="{htmlMode:enableHtml}" ref="container">
|
||||
<div v-if="enableHtml" v-html="result"></div>
|
||||
<pre v-else>{{result}}</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import marked from 'marked'
|
||||
export default {
|
||||
props: ['markdown', 'enableHtml'],
|
||||
name: 'ResumeEditor',
|
||||
computed: {
|
||||
result: function () {
|
||||
return this.enableHtml ? marked(this.markdown) : this.markdown
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBottom: function () {
|
||||
this.$refs.container.scrollTop = 100000
|
||||
},
|
||||
goTop: function(){
|
||||
this.$refs.container.scrollTop = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@media (max-width:500px){
|
||||
.resumeEditor{
|
||||
}
|
||||
}
|
||||
.htmlMode {
|
||||
animation: flip 2s;
|
||||
}
|
||||
|
||||
@keyframes flip {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="styleEditor" ref="container">
|
||||
<div class="code" v-html="codeInStyleTag"></div>
|
||||
<pre class="" v-html="highlightedCode"></pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Prism from 'prismjs'
|
||||
export default {
|
||||
name: 'Editor',
|
||||
props: ['code'],
|
||||
computed: {
|
||||
highlightedCode: function () {
|
||||
return Prism.highlight(this.code, Prism.languages.css)
|
||||
},
|
||||
codeInStyleTag: function () {
|
||||
return `<style>${this.code}</style>`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBottom() {
|
||||
this.$refs.container.scrollTop = 100000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
pre{
|
||||
}
|
||||
@media (max-width:500px){
|
||||
pre{
|
||||
}
|
||||
}
|
||||
.code {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="thankEditor" :class="{htmlMode:enableHtml}" ref="container">
|
||||
<div v-if="enableHtml" v-html="result"></div>
|
||||
<pre v-else>{{result}}</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import marked from 'marked'
|
||||
export default {
|
||||
props: ['markdown', 'enableHtml'],
|
||||
name: 'ThankEditor',
|
||||
computed: {
|
||||
result: function () {
|
||||
return this.enableHtml ? marked(this.markdown) : this.markdown
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBottom: function () {
|
||||
this.$refs.container.scrollTop = 100000
|
||||
},
|
||||
goTop: function(){
|
||||
this.$refs.container.scrollTop = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@media (max-width:500px){
|
||||
.thankEditor{
|
||||
}
|
||||
}
|
||||
.htmlMode {
|
||||
animation: flip 2s;
|
||||
}
|
||||
|
||||
@keyframes flip {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import Mobile from './Mobile'
|
||||
|
||||
var width = document.documentElement.clientWidth
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
render: h => h(width > 500 ? App : Mobile)
|
||||
})
|
||||
Reference in New Issue
Block a user