├── .gitignore ├── README.md ├── Untitled.txt ├── api ├── management │ ├── article.js │ ├── terms.js │ ├── upload.js │ └── user.js └── user │ └── article.js ├── app.js ├── bin └── www ├── db └── mongoose.js ├── models ├── key_maps.js ├── management │ ├── article │ │ ├── list.js │ │ ├── posts.js │ │ └── terms.js │ ├── attachment │ │ └── imgs.js │ └── user │ │ └── users.js └── user │ └── posts.js ├── package.json ├── proxy.js ├── router └── router.js ├── test └── testFormatPara2Camel.html ├── tools └── tools.js ├── views ├── error.jade ├── index.jade ├── layout.jade └── user.jade └── web ├── README.md ├── assets └── js │ └── app.js ├── build ├── ZeroClipboard.swf ├── app.js ├── app.js.map ├── css │ ├── font-icons │ │ ├── fonts │ │ │ ├── material-ui-icons.eot │ │ │ ├── material-ui-icons.svg │ │ │ ├── material-ui-icons.ttf │ │ │ └── material-ui-icons.woff │ │ └── style.css │ ├── github.css │ └── main.css ├── fonts │ ├── demo.css │ ├── demo_fontclass.html │ ├── demo_symbol.html │ ├── demo_unicode.html │ ├── iconfont.css │ ├── iconfont.eot │ ├── iconfont.js │ ├── iconfont.svg │ ├── iconfont.ttf │ └── iconfont.woff ├── images │ ├── 3fuyu.png │ ├── 3fuyu_bg.jpg │ ├── 3fuyu_small.jpg │ ├── angular.jpg │ ├── banner_small.jpg │ ├── banner_small_two.jpg │ ├── electron.png │ ├── favicon.ico │ ├── gomoku.jpg │ ├── mongodb.jpg │ ├── nodejs.jpg │ ├── react.png │ ├── vue.jpg │ └── weex.png ├── index.html ├── laboratory │ └── gomoku │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── wood.jpg └── versions.json ├── gulpfile.js ├── package.json ├── src ├── .DS_Store ├── .babelrc ├── app │ ├── .DS_Store │ ├── AppRoutes.js │ ├── app.js │ ├── css │ │ ├── about.less │ │ ├── articleCategory.less │ │ ├── articleDetail.less │ │ ├── articleList.less │ │ ├── base.less │ │ ├── github-gist.css │ │ ├── home.less │ │ ├── iconfont │ │ │ ├── iconfont.css │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.svg │ │ │ ├── iconfont.ttf │ │ │ └── iconfont.woff │ │ ├── laboratory.less │ │ ├── login.less │ │ ├── main.less │ │ ├── markdown.less │ │ └── newArticle.less │ ├── fonts │ │ ├── demo.css │ │ ├── demo_fontclass.html │ │ ├── demo_symbol.html │ │ ├── demo_unicode.html │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.js │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ ├── images │ │ ├── 3fuyu_bg.jpg │ │ ├── add_pic.png │ │ ├── angular.jpg │ │ ├── banner_small_two.jpg │ │ ├── default_xz.png │ │ ├── delete_btn.png │ │ ├── electron.png │ │ ├── gomoku.jpg │ │ ├── gomoku.png │ │ ├── line.png │ │ ├── line_green.png │ │ ├── logo_small.jpg │ │ ├── mongodb.jpg │ │ ├── nodejs.jpg │ │ ├── react.png │ │ ├── select_photo.jpg │ │ ├── select_photo.png │ │ ├── vue.jpg │ │ └── weex.png │ ├── js │ │ ├── .DS_Store │ │ ├── actions │ │ │ └── actions.js │ │ ├── components │ │ │ ├── .DS_Store │ │ │ ├── index │ │ │ │ ├── About.js │ │ │ │ ├── About_power.js │ │ │ │ ├── ArticleDetail.js │ │ │ │ ├── Home.js │ │ │ │ └── Laboratory.js │ │ │ ├── lib │ │ │ │ ├── Loading.js │ │ │ │ └── upload.js │ │ │ └── management │ │ │ │ ├── AppNavDrawer.js │ │ │ │ ├── ArticleCategory.js │ │ │ │ ├── ArticleList.js │ │ │ │ ├── FullWidthSection.js │ │ │ │ ├── Login.js │ │ │ │ ├── MarkdownElement.js │ │ │ │ ├── Master.js │ │ │ │ ├── Media.js │ │ │ │ └── NewArticle.js │ │ ├── lib │ │ │ ├── ZeroClipboard.min.js │ │ │ ├── ZeroClipboard.swf │ │ │ └── changyan.js │ │ ├── reducers │ │ │ ├── reducers.js │ │ │ └── todos.js │ │ ├── service │ │ │ ├── CacheService.js │ │ │ ├── DataService.js │ │ │ ├── EnumService.js │ │ │ ├── FYToolService.js │ │ │ ├── RouterService.js │ │ │ └── StorageService.js │ │ ├── upload.html │ │ └── upload.js │ └── laboratory │ │ └── gomoku │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── wood.jpg └── www │ ├── css │ ├── font-icons │ │ ├── fonts │ │ │ ├── material-ui-icons.eot │ │ │ ├── material-ui-icons.svg │ │ │ ├── material-ui-icons.ttf │ │ │ └── material-ui-icons.woff │ │ └── style.css │ ├── github.css │ └── main.css │ ├── fonts │ ├── demo.css │ ├── demo_fontclass.html │ ├── demo_symbol.html │ ├── demo_unicode.html │ ├── iconfont.css │ ├── iconfont.eot │ ├── iconfont.js │ ├── iconfont.svg │ ├── iconfont.ttf │ └── iconfont.woff │ ├── images │ ├── 3fuyu.png │ ├── 3fuyu_bg.jpg │ ├── 3fuyu_small.jpg │ ├── angular.jpg │ ├── banner_small.jpg │ ├── banner_small_two.jpg │ ├── electron.png │ ├── favicon.ico │ ├── gomoku.jpg │ ├── mongodb.jpg │ ├── nodejs.jpg │ ├── react.png │ ├── vue.jpg │ └── weex.png │ ├── index.html │ ├── laboratory │ └── gomoku │ │ ├── index.css │ │ ├── index.html │ │ ├── index.js │ │ └── wood.jpg │ ├── management.html │ └── versions.json ├── test └── testHightlight.html ├── testHS.html ├── webpack-production.config.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ project files 2 | .idea 3 | *.iml 4 | out 5 | gen 6 | node_modules 7 | express_test/myapp/node_modules 8 | .npm-debug.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blog building... 2 | 3 | hi I'm 3fuyu 4 | 5 | want: nodejs + express + mongodb + react + redux + handlebarsjs + materail + lodash 6 | 7 | now: server is building , already have nodejs + express + mongo + react + lodash... 8 | 9 | -------------------------------------------------------------------------------- /Untitled.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/Untitled.txt -------------------------------------------------------------------------------- /api/management/article.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let express = require('express'); 4 | let postsModel = require('../../models/management/article/posts'); 5 | let keyMapsModel = require('../../models/key_maps'); 6 | let Tools = require('../../tools/tools'); 7 | let MD = require('marked'); 8 | let hljs = require('highlight.js'); 9 | 10 | let baseRoute = '/admin/article'; 11 | 12 | let postApis = [{ 13 | 14 | // 发布文章 15 | type: 'post', 16 | url: baseRoute + '/postNew', 17 | success: function (req, res, next) { 18 | let max_id = 1; 19 | MD.setOptions({ 20 | gfm: true, 21 | tables: true, 22 | breaks: false, 23 | pedantic: false, 24 | sanitize: true, // if false -> allow plain old HTML ;) 25 | smartLists: true, 26 | smartypants: false, 27 | highlight: function (code, lang) { 28 | if (lang && hljs.getLanguage(lang)) { 29 | return hljs.highlight(lang, code, true).value; 30 | } else { 31 | console.log(hljs.highlightAuto(code).value); 32 | return hljs.highlightAuto(code).value; 33 | } 34 | } 35 | }); 36 | 37 | keyMapsModel.find({post_map_key: true}, function (err, docs) { 38 | if (err) { 39 | console.error(err); 40 | } else { 41 | if (docs.length === 0) { 42 | let postMapObj = JSON.stringify({max_id: 1}); 43 | 44 | let keyMapsEntity = new keyMapsModel({ 45 | post_map_key: true, 46 | post_map_value: postMapObj 47 | }); 48 | 49 | keyMapsEntity.save(function (err, docs) { 50 | if (err) console.error(err); 51 | }); 52 | } else { 53 | max_id = parseInt(JSON.parse(docs[0].post_map_value).max_id) + 1; 54 | } 55 | 56 | // 存数据库 57 | let postEntity = new postsModel({ 58 | post_author: '3fuyu', 59 | post_content: req.body.content, 60 | post_md_content: MD(req.body.content), 61 | post_title: req.body.title, 62 | post_category_id: req.body.categoryId, 63 | post_category_name: req.body.categoryName, 64 | post_date: req.body.date || +new Date(), 65 | _id: max_id, 66 | view_count: 0 67 | }); 68 | 69 | postEntity.save(function (err, tree) { 70 | if (err) { 71 | console.error('Somthing wrong: ' + err); 72 | } else { 73 | 74 | var conditions = {post_map_key: true}; 75 | var update = {$set: {post_map_value: JSON.stringify({max_id: max_id})}}; 76 | var options = {upsert: true}; 77 | keyMapsModel.update(conditions, update, options, function (err, suc) { 78 | if (err) console.error(err); 79 | 80 | if (suc) console.log(suc); 81 | }); 82 | } 83 | }); 84 | 85 | res.send({ 86 | code: 200, 87 | description: 'success' 88 | }); 89 | } 90 | }); 91 | } 92 | }, { 93 | 94 | // 查询文章列表 95 | type: 'get', 96 | url: baseRoute + '/queryList', 97 | success: function (req, res, next) { 98 | postsModel 99 | .find({}) 100 | .sort({'post_date': 'desc'}) 101 | .exec(function (err, data) { 102 | res.send({ 103 | code: 200, 104 | description: 'success', 105 | data: Tools.para2camel(data) 106 | }); 107 | }); 108 | } 109 | }, { 110 | 111 | // 查询文章详情 112 | type: 'get', 113 | url: baseRoute + '/get', 114 | success: function (req, res, next) { 115 | postsModel 116 | .find({_id: req.query.id}, function (err, data) { 117 | res.send({ 118 | code: 200, 119 | description: 'success', 120 | data: Tools.para2camel(data) 121 | }); 122 | }); 123 | } 124 | }, { 125 | 126 | // 更新文章详情 127 | type: 'post', 128 | url: baseRoute + '/update', 129 | success: function (req, res, next) { 130 | let query = {_id: req.body.id}, 131 | update = { 132 | post_author: '3fuyu', 133 | post_content: req.body.content, 134 | post_md_content: MD(req.body.content), 135 | post_title: req.body.title, 136 | post_category_id: req.body.categoryId, 137 | post_category_name: req.body.categoryName, 138 | post_date: req.body.date || +new Date() 139 | }, 140 | options = {multi: true}; 141 | 142 | postsModel.update(query, update, options, function (err, data) { 143 | res.send({ 144 | code: 200, 145 | description: 'success', 146 | data: Tools.para2camel(data) 147 | }); 148 | }); 149 | } 150 | }, { 151 | 152 | // 删除文章 153 | type: 'post', 154 | url: baseRoute + '/del', 155 | success: function (req, res, next) { 156 | postsModel 157 | .remove({ 158 | _id: req.body.id 159 | }) 160 | .exec(function (err, data) { 161 | res.send({ 162 | code: 200, 163 | description: 'success' 164 | }); 165 | }); 166 | } 167 | }]; 168 | 169 | 170 | module.exports = postApis; 171 | -------------------------------------------------------------------------------- /api/management/terms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2016/11/20. 3 | */ 4 | 5 | "use strict"; 6 | 7 | let express = require('express'); 8 | let termsModel = require('../../models/management/article/terms'); 9 | let keyMapsModel = require('../../models/key_maps'); 10 | let Tools = require('../../tools/tools'); 11 | 12 | let baseRoute = '/admin/terms'; 13 | 14 | let termsApis = [{ 15 | // 新增分类 16 | type: 'post', 17 | url: baseRoute + '/termsNew', 18 | success: function (req, res, next) { 19 | let max_id = 1; 20 | 21 | keyMapsModel.find({terms_map_key: true}, function (err, docs) { 22 | if (err) { 23 | console.error(err); 24 | } else { 25 | if (docs.length === 0) { 26 | let termsMapKey = JSON.stringify({max_id: 1}); 27 | 28 | let keyMapsEntity = new keyMapsModel({ 29 | terms_map_key: true, 30 | terms_map_value: termsMapKey 31 | }); 32 | 33 | keyMapsEntity.save(function (err, docs) { 34 | if (err) console.error(err); 35 | }); 36 | } else { 37 | max_id = parseInt(JSON.parse(docs[0].terms_map_value).max_id) + 1; 38 | } 39 | 40 | // 存数据库 41 | let termsEntity = new termsModel({ 42 | _id: max_id, 43 | name: req.body.name, 44 | slug: req.body.slug || req.body.name, 45 | term_group: '未分组' 46 | }); 47 | 48 | termsEntity.save(function (err, docs) { 49 | if (err) { 50 | console.error('Somthing wrong: ' + err); 51 | } else { 52 | let conditions = {terms_map_key: true}; 53 | let update = {$set: {terms_map_value: JSON.stringify({max_id: max_id})}}; 54 | let options = {upsert: true}; 55 | 56 | keyMapsModel.update(conditions, update, options, function (err, suc) { 57 | if (err) console.error(err); 58 | 59 | if (suc) console.log(suc); 60 | 61 | res.send({ 62 | code: 200, 63 | description: 'success' 64 | }); 65 | }); 66 | } 67 | }); 68 | } 69 | }); 70 | } 71 | }, { 72 | // 查询分类列表 73 | type: 'get', 74 | url: baseRoute + '/queryList', 75 | success: function (req, res, next) { 76 | termsModel 77 | .find({}) 78 | .sort({'_id': 'desc'}) 79 | .exec(function (err, data) { 80 | res.send({ 81 | code: 200, 82 | description: 'success', 83 | data: Tools.para2camel(data) 84 | }); 85 | }); 86 | } 87 | }, { 88 | // 删除分类 89 | type: 'post', 90 | url: baseRoute + '/del', 91 | success: function (req, res, next) { 92 | var conditions = {'_id': req.body.id}; 93 | termsModel.remove(conditions, function (error) { 94 | if (error) { 95 | console.error(error); 96 | } else { 97 | console.log('delete ok!'); 98 | res.send({ 99 | code: 200, 100 | description: 'success' 101 | }); 102 | } 103 | }); 104 | } 105 | }]; 106 | 107 | module.exports = termsApis; -------------------------------------------------------------------------------- /api/management/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/2/14. 3 | */ 4 | 5 | "use strict"; 6 | 7 | let express = require('express'); 8 | let formidable = require('formidable'); 9 | let util = require('util'); 10 | let keyMapsModel = require('../../models/key_maps'); 11 | let imgsModel = require('../../models/management/attachment/imgs'); 12 | let fs = require('fs'); 13 | let Tools = require('../../tools/tools'); 14 | let _ = require('lodash'); 15 | 16 | let baseRoute = '/admin/upload' 17 | 18 | let uploadApis = [{ 19 | // 新增附件 20 | type: 'post', 21 | url: baseRoute + '/image', 22 | success: function (req, res) { 23 | let form = new formidable.IncomingForm(); 24 | 25 | form.keepExtensions = true; 26 | form.multiples = true; 27 | form.parse(req, function (err, fields, files) { 28 | 29 | keyMapsModel.find({imgs_map_key: true}, function (err, docs) { 30 | if (err) { 31 | console.error(err); 32 | } else { 33 | if (docs.length === 0) { 34 | let keyMapsEntity = new keyMapsModel({ 35 | imgs_map_key: true, 36 | imgs_max_id: 1 37 | }); 38 | 39 | keyMapsEntity.save(function (err, docs) { 40 | if (err) console.error(err); 41 | 42 | if (_.isArray(files.img)) { 43 | files.img.forEach(function (value, key) { 44 | setImg(res, value); 45 | }); 46 | } else { 47 | setImg(res, files.img); 48 | } 49 | 50 | res.send({ 51 | code: 200, 52 | description: 'success' 53 | }); 54 | }); 55 | } else { 56 | if (_.isArray(files.img)) { 57 | files.img.forEach(function (value, key) { 58 | setImg(res, value); 59 | }); 60 | } else { 61 | setImg(res, files.img); 62 | } 63 | 64 | res.send({ 65 | code: 200, 66 | description: 'success' 67 | }); 68 | } 69 | } 70 | }); 71 | }); 72 | } 73 | }, { 74 | // 查询附件列表 75 | type: 'get', 76 | url: baseRoute + '/queryList', 77 | success: function (req, res, next) { 78 | imgsModel 79 | .find({}) 80 | .sort({'_id': 'desc'}) 81 | .exec(function (err, data) { 82 | res.send({ 83 | code: 200, 84 | description: 'success', 85 | data: Tools.para2camel(data) 86 | }); 87 | }); 88 | } 89 | }, { 90 | // 删除分类 91 | type: 'post', 92 | url: baseRoute + '/del', 93 | success: function (req, res, next) { 94 | var conditions = {'_id': req.body.id}; 95 | imgsModel.remove(conditions, function (error) { 96 | if (error) { 97 | console.error(error); 98 | } else { 99 | console.log('delete ok!'); 100 | res.send({ 101 | code: 200, 102 | description: 'success' 103 | }); 104 | } 105 | }); 106 | } 107 | }]; 108 | 109 | function setImg(res, img) { 110 | keyMapsModel.findOneAndUpdate({imgs_map_key: true}, {$inc: {'imgs_max_id': 1}}, function (err, suc) { 111 | let name = +new Date() + '.' + img.type.split('/')[1], 112 | url = '/static/imgs/' + name; 113 | 114 | if (err) return console.log(err); 115 | 116 | // 存数据库 117 | let imgsEntity = new imgsModel({ 118 | _id: suc.imgs_max_id, 119 | name: img.name, 120 | url: url 121 | }); 122 | 123 | imgsEntity.save(function (err, docs) { 124 | fs.renameSync(img.path, './static/imgs/' + name); 125 | }); 126 | }); 127 | } 128 | 129 | 130 | module.exports = uploadApis; -------------------------------------------------------------------------------- /api/management/user.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var baseRoute = '/admin/user'; 4 | var usersModel = require('../../models/management/user/users'); 5 | var Tools = require('../../tools/tools'); 6 | 7 | var userApis = [{ 8 | 9 | type: 'get', 10 | url: baseRoute + '/getUserInfo', 11 | success: function (req, res, next) { 12 | usersModel 13 | .find({ID: req.session.user_id}) 14 | .exec(function (err, data) { 15 | var _data = Tools.para2camel(data); 16 | 17 | res.send({ 18 | code: 200, 19 | description: 'success', 20 | data: _data 21 | }); 22 | }); 23 | 24 | } 25 | }, { 26 | type: 'post', 27 | url: baseRoute + '/login', 28 | success: function (req, res, next) { 29 | usersModel 30 | .find({ID: '1'}) 31 | .exec(function (err, data) { 32 | var _data = Tools.para2camel(data); 33 | 34 | if (req.body.name === _data[0].userLogin && req.body.password === _data[0].userPass) { 35 | 36 | req.session.user_id = '1'; 37 | req.session.user = '3fuyu'; 38 | 39 | res.send({ 40 | code: 200, 41 | description: 'success' 42 | }); 43 | } else { 44 | res.send({ 45 | code: 500, 46 | description: 'name or password wrong' 47 | }); 48 | } 49 | }); 50 | } 51 | }, { 52 | type: 'post', 53 | url: baseRoute + '/logout', 54 | success: function (req, res, next) { 55 | req.session.destroy(); 56 | 57 | res.send({ 58 | code: 200, 59 | description: 'success' 60 | }); 61 | 62 | } 63 | }]; 64 | 65 | 66 | module.exports = userApis; 67 | -------------------------------------------------------------------------------- /api/user/article.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var express = require('express'); 4 | var postsModel = require('../../models/management/article/posts'); 5 | var Tools = require('../../tools/tools'); 6 | let request = require('superagent'); 7 | 8 | var baseRoute = '/article'; 9 | 10 | var postApis = [{ 11 | 12 | // 获取文章详情 13 | type: 'get', 14 | url: baseRoute + '/getDetail', 15 | success: function (req, res, next) { 16 | postsModel 17 | .find({'_id': req.query.id}) 18 | .sort({'post_date': 'desc'}) 19 | .exec(function (err, data) { 20 | 21 | if (err) { 22 | res.send(err); 23 | } else { 24 | let query = {_id: req.query.id}, 25 | update = '', 26 | options = {multi: true}; 27 | 28 | if (data[0].view_count) { 29 | // 原子操作,+1 30 | update = {$inc: {view_count: 1}}; 31 | } else { 32 | // 没有则插入该字段 33 | update = {$set: {view_count: 1}} 34 | } 35 | 36 | // 获取畅言评论数 37 | request 38 | .get('http://changyan.sohu.com/api/2/topic/count?client_id=cyt1S1w3M&topic_id=&topic_source_id=' + req.query.id + '&topic_url=') 39 | .type('form') 40 | .end(function (err, suc) { 41 | if (err) { 42 | console.log(err); 43 | } else { 44 | if (update.$set) { 45 | update.$set.comment_count = suc.body.result[req.query.id].comments; 46 | } else { 47 | update.$set = { 48 | comment_count: suc.body.result[req.query.id].comments 49 | } 50 | } 51 | 52 | postsModel.update(query, update, options, function (err, data) { 53 | }); 54 | } 55 | }); 56 | 57 | res.send({ 58 | code: 200, 59 | description: 'success', 60 | data: Tools.para2camel(data)[0] 61 | }); 62 | } 63 | 64 | }); 65 | } 66 | }, { 67 | 68 | // 获取文章详情 69 | type: 'get', 70 | url: baseRoute + '/queryList', 71 | success: function (req, res, next) { 72 | let pageIndex = parseInt(req.query.pageIndex), 73 | pageSize = parseInt(req.query.pageSize), 74 | position = parseInt(pageIndex - 1), 75 | search = {}, 76 | type = req.query.type || '', 77 | category = [], 78 | _postModel, 79 | __postModel; 80 | 81 | if (type) { 82 | switch (type) { 83 | case '1': 84 | category.push('js', 'javascript', 'angularJs', 'web前端', 'react'); 85 | break; 86 | case '2': 87 | category.push('ubuntu', 'linux'); 88 | break; 89 | default: 90 | break; 91 | } 92 | search.post_category_name = type; 93 | } 94 | 95 | if (category.length > 0) { 96 | _postModel = postsModel.where('post_category_name').in(category); 97 | // copy 一份统计数据用 98 | __postModel = postsModel.where('post_category_name').in(category); 99 | } else { 100 | _postModel = postsModel.find({}); 101 | // copy 一份统计数据用 102 | __postModel = postsModel.find({}); 103 | } 104 | 105 | _postModel 106 | .skip(position) 107 | .limit(pageSize) 108 | .sort({'post_date': 'desc'}) 109 | .exec(function (err, data) { 110 | if (err) { 111 | res.send(err); 112 | } else { 113 | __postModel.count(function (errcount, count) { 114 | if (errcount) { 115 | res.send(errcount); 116 | } else { 117 | let total = count, 118 | nextPage = pageIndex + pageSize, 119 | isFinish = total <= nextPage ? true : false; 120 | 121 | res.send({ 122 | code: 200, 123 | description: 'success', 124 | data: { 125 | data: Tools.para2camel(data), 126 | pageObj: { 127 | nextPage: nextPage, 128 | total: total, 129 | isFinish: isFinish 130 | } 131 | } 132 | }); 133 | } 134 | }); 135 | } 136 | }); 137 | } 138 | }]; 139 | 140 | 141 | module.exports = postApis; 142 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var express = require('express'); 4 | var path = require('path'); 5 | var favicon = require('serve-favicon'); 6 | var logger = require('morgan'); 7 | var cookieParser = require('cookie-parser'); 8 | var bodyParser = require('body-parser'); 9 | var proxy = require('./proxy'); 10 | var session = require ('express-session'); 11 | var router = require('./router/router'); 12 | var compression = require('compression'); 13 | var baseUrl = '/api'; 14 | var app = express(); 15 | 16 | // 设置session 17 | app.use(session({ 18 | secret: '123456', 19 | name: '3fuyu', 20 | cookie: { 21 | maxAge: 3 * 60 * 60 * 1000 + 8 * 3600 * 1000, // 0.5h 22 | path: '/' 23 | }, 24 | resave: false, 25 | saveUninitialized: true 26 | })); 27 | 28 | //设置跨域访问 29 | app.all('*', function(req, res, next) { 30 | res.header("Access-Control-Allow-Origin", "*"); 31 | res.header("Access-Control-Allow-Headers", "X-Requested-With"); 32 | res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); 33 | res.header("X-Powered-By",' 3.2.1'); 34 | next(); 35 | }); 36 | 37 | // view engine setup 38 | app.set('views', path.join(__dirname, 'views')); 39 | app.set('view engine', 'jade'); 40 | 41 | // uncomment after placing your favicon in /web 42 | //app.use(favicon(path.join(__dirname, 'web', 'favicon.ico'))); 43 | // 压缩 44 | app.use(compression()); 45 | app.use(logger('dev')); 46 | app.use(bodyParser.json()); 47 | app.use(bodyParser.urlencoded({extended: false})); 48 | app.use(cookieParser()); 49 | 50 | app.use(baseUrl, router); 51 | app.use(express.static(path.join(__dirname, 'web/build'))); 52 | app.use('/static', express.static(path.join(__dirname, 'static'))); 53 | 54 | // catch 404 and forward to error handler 55 | app.use(function (req, res, next) { 56 | var err = new Error('Not Found'); 57 | err.status = 404; 58 | next(err); 59 | }); 60 | 61 | // error handlers 62 | 63 | // development error handler 64 | // will print stacktrace 65 | if (app.get('env') === 'development') { 66 | app.use(function (err, req, res, next) { 67 | res.status(err.status || 500); 68 | res.render('error', { 69 | message: err.message, 70 | error: err 71 | }); 72 | }); 73 | } 74 | 75 | // production error handler 76 | // no stacktraces leaked to user 77 | app.use(function (err, req, res, next) { 78 | res.status(err.status || 500); 79 | res.render('error', { 80 | message: err.message, 81 | error: {} 82 | }); 83 | }); 84 | 85 | 86 | module.exports = app; 87 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('blog:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '8080'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /db/mongoose.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/11. 3 | */ 4 | 5 | var mongoose = require('mongoose'); 6 | mongoose.connect('mongodb://localhost/blog'); 7 | 8 | var db = mongoose.connection; 9 | db.on('error', console.error.bind(console, 'connection error:')); 10 | db.once('open', function (callback) { 11 | // yay! 12 | console.log.bind(console, 'connection success!'); 13 | }); 14 | 15 | module.exports = mongoose; -------------------------------------------------------------------------------- /models/key_maps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/11. 3 | */ 4 | 5 | var mongoose = require('../db/mongoose'); 6 | 7 | var mapsSchema = mongoose.Schema({ 8 | 'post_map_key' : { 9 | type: 'Boolean' 10 | }, 11 | "post_map_value" : { 12 | type: 'String' 13 | }, 14 | "post_max_id": { 15 | type: 'Number' 16 | }, 17 | 'terms_map_key': { 18 | type: 'Boolean' 19 | }, 20 | 'terms_map_value': { 21 | type: 'String' 22 | }, 23 | "terms_max_id": { 24 | type: 'Number' 25 | }, 26 | 'imgs_map_key': { 27 | type: 'Boolean' 28 | }, 29 | 'imgs_map_value': { 30 | type: 'String' 31 | }, 32 | "imgs_max_id": { 33 | type: 'Number' 34 | } 35 | }); 36 | 37 | var mapsModel = mongoose.model('key_maps', mapsSchema); 38 | 39 | module.exports = mapsModel; -------------------------------------------------------------------------------- /models/management/article/list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2016/10/13. 3 | */ 4 | 5 | "use strict"; 6 | 7 | let mongoose = require('../../../db/mongoose'); 8 | let Schema = mongoose.Schema; 9 | 10 | let listSchema = new Schema({ 11 | "_id": { 12 | type: 'Number', 13 | required: [true, '请输入id'] 14 | }, 15 | "post_author": { 16 | type: 'String', 17 | required: [true, '请输入作者名称'] 18 | }, 19 | "post_date": { 20 | type: 'String' 21 | }, 22 | "post_content": { 23 | type: 'String', 24 | required: [true, '请输入内容'] 25 | }, 26 | "post_title": { 27 | type: 'String', 28 | required: [true, '请输入标题'] 29 | }, 30 | "post_excerpt": { 31 | type: 'String', 32 | }, 33 | "post_status": { 34 | type: 'String', 35 | }, 36 | "comment_status": { 37 | type: 'String', 38 | }, 39 | "post_password": { 40 | type: 'String', 41 | }, 42 | "post_name": { 43 | type: 'String', 44 | }, 45 | "post_modified": { 46 | type: 'String', 47 | }, 48 | "post_parent": { 49 | type: 'String', 50 | }, 51 | "menu_order": { 52 | type: 'String', 53 | }, 54 | "post_type": { 55 | type: 'String', 56 | }, 57 | "comment_count": { 58 | type: 'String', 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /models/management/article/posts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/11. 3 | */ 4 | 5 | var mongoose = require('../../../db/mongoose'); 6 | var Schema = mongoose.Schema; 7 | var postsSchema = new Schema({ 8 | "_id": { 9 | type: 'Number', 10 | required: [true, '请输入id'] 11 | }, 12 | "post_author": { 13 | type: 'String', 14 | required: [true, '请输入作者名称'] 15 | }, 16 | "post_date": { 17 | type: 'Number' 18 | }, 19 | "post_category_id": { 20 | type: 'String', 21 | required: [true, '请输入分类id'] 22 | }, 23 | "post_category_name": { 24 | type: 'String', 25 | required: [true, '请输入分类名称'] 26 | }, 27 | "post_content": { 28 | type: 'String', 29 | required: [true, '请输入内容'] 30 | }, 31 | "post_md_content": { 32 | type: 'String', 33 | required: [true, '请输入内容'] 34 | }, 35 | "post_title": { 36 | type: 'String', 37 | required: [true, '请输入标题'] 38 | }, 39 | "post_excerpt": { 40 | type: 'String', 41 | }, 42 | "post_status": { 43 | type: 'String', 44 | }, 45 | "comment_status": { 46 | type: 'String', 47 | }, 48 | "post_password": { 49 | type: 'String', 50 | }, 51 | "post_name": { 52 | type: 'String', 53 | }, 54 | "post_modified": { 55 | type: 'String', 56 | }, 57 | "post_parent": { 58 | type: 'String', 59 | }, 60 | "menu_order": { 61 | type: 'String', 62 | }, 63 | "post_type": { 64 | type: 'String', 65 | }, 66 | "view_count": { 67 | type: 'Number', 68 | }, 69 | "comment_count": { 70 | type: 'Number', 71 | } 72 | }, { _id: false }); 73 | 74 | var postsModel = mongoose.model('posts', postsSchema); 75 | 76 | module.exports = postsModel; -------------------------------------------------------------------------------- /models/management/article/terms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2016/11/20. 3 | */ 4 | 5 | let mongoose = require('../../../db/mongoose'); 6 | let Schema = mongoose.Schema; 7 | let termsSchema = new Schema({ 8 | "_id": { 9 | type: 'Number', 10 | required: [true, '请输入id'] 11 | }, 12 | "name": { // 分类名 13 | type: 'String', 14 | required: [true, '请输入分类名称'] 15 | }, 16 | "slug": { // 缩略名 17 | type: 'String' 18 | }, 19 | "term_group": { // 相似的 terms 集合在一起 20 | type: 'String' 21 | } 22 | }, { _id: false }); 23 | 24 | let termsModel = mongoose.model('terms', termsSchema); 25 | 26 | module.exports = termsModel; 27 | 28 | -------------------------------------------------------------------------------- /models/management/attachment/imgs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/4/24. 3 | */ 4 | 5 | "use strict"; 6 | 7 | let mongoose = require('../../../db/mongoose'); 8 | let Schema = mongoose.Schema; 9 | 10 | let imgsSchema = new Schema({ 11 | "_id": { 12 | type: 'Number', 13 | required: [true, '请输入id'] 14 | }, 15 | "url": { 16 | type: 'String', 17 | }, 18 | "name": { 19 | type: 'String' 20 | } 21 | }, { _id: false }); 22 | 23 | let imgsModel = mongoose.model('imgs', imgsSchema); 24 | module.exports = imgsModel; -------------------------------------------------------------------------------- /models/management/user/users.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/11. 3 | */ 4 | 5 | var mongoose = require('../../../db/mongoose'); 6 | 7 | var usersSchema = mongoose.Schema({ 8 | "ID" : { 9 | type: "String" 10 | }, 11 | "user_login" : { 12 | type: "String" 13 | }, 14 | "user_pass" : { 15 | type: "String" 16 | }, 17 | "user_nicename" : { 18 | type: "String" 19 | }, 20 | "user_email" : { 21 | type: "String" 22 | }, 23 | "user_url" : { 24 | type: "String" 25 | }, 26 | "user_registered" : { 27 | type: "String" 28 | }, 29 | "user_status" : { 30 | type: "String" 31 | }, 32 | "display_name" : { 33 | type: "String" 34 | } 35 | }); 36 | 37 | var usersModel = mongoose.model('users', usersSchema); 38 | 39 | module.exports = usersModel; -------------------------------------------------------------------------------- /models/user/posts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/11. 3 | */ 4 | 5 | var mongoose = require('../../db/mongoose'); 6 | var Schema = mongoose.Schema; 7 | var postsSchema = new Schema({ 8 | "_id": { 9 | type: 'Number', 10 | required: [true, '请输入id'] 11 | }, 12 | "post_author": { 13 | type: 'String', 14 | required: [true, '请输入作者名称'] 15 | }, 16 | "post_date": { 17 | type: 'Number' 18 | }, 19 | "post_content": { 20 | type: 'String', 21 | required: [true, '请输入内容'] 22 | }, 23 | "post_title": { 24 | type: 'String', 25 | required: [true, '请输入标题'] 26 | }, 27 | "post_excerpt": { 28 | type: 'String', 29 | }, 30 | "post_status": { 31 | type: 'String', 32 | }, 33 | "comment_status": { 34 | type: 'String', 35 | }, 36 | "post_password": { 37 | type: 'String', 38 | }, 39 | "post_name": { 40 | type: 'String', 41 | }, 42 | "post_modified": { 43 | type: 'String', 44 | }, 45 | "post_parent": { 46 | type: 'String', 47 | }, 48 | "menu_order": { 49 | type: 'String', 50 | }, 51 | "post_type": { 52 | type: 'String', 53 | }, 54 | "view_count": { 55 | type: 'Number', 56 | }, 57 | "comment_count": { 58 | type: 'Number', 59 | } 60 | }, { _id: false }); 61 | 62 | var postsModel = mongoose.model('posts', postsSchema); 63 | 64 | module.exports = postsModel; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "peerDependencies": { 9 | "react": "15.0.0", 10 | "react-dom": "15.0.0", 11 | "react-tap-event-plugin": "1.0.0" 12 | }, 13 | "dependencies": { 14 | "body-parser": "1.15.1", 15 | "cookie-parser": "1.4.3", 16 | "debug": "2.2.0", 17 | "express": "4.13.4", 18 | "express-session": "1.14.2", 19 | "formidable": "1.1.1", 20 | "jade": "1.11.0", 21 | "lodash": "4.14.2", 22 | "marked": "0.3.6", 23 | "mongoose": "4.5.8", 24 | "morgan": "1.7.0", 25 | "serve-favicon": "2.3.0" 26 | }, 27 | "devDependencies": { 28 | "babel": "6.5.2", 29 | "babel-core": "6.6.4", 30 | "babel-loader": "6.2.4", 31 | "babel-polyfill": "6.7.2", 32 | "babel-preset-es2015": "6.6.0", 33 | "babel-preset-react": "6.5.0", 34 | "css-loader": "0.23.1", 35 | "fastclick": "1.0.6", 36 | "highlight.js": "9.7.0", 37 | "history": "2.0.1", 38 | "html-webpack-plugin": "2.29.0", 39 | "http-proxy": "1.15.1", 40 | "less": "2.7.1", 41 | "less-loader": "2.2.3", 42 | "material-ui": "0.15.4", 43 | "moment": "2.15.1", 44 | "path": "0.12.7", 45 | "react": "15.3.2", 46 | "react-dom": "15.3.2", 47 | "react-event-listener": "0.3.0", 48 | "react-hot-loader": "3.0.0-beta.3", 49 | "react-redux": "4.4.5", 50 | "react-router": "2.8.0", 51 | "react-tap-event-plugin": "1.0.0", 52 | "reactify": "1.1.0", 53 | "redux": "3.6.0", 54 | "simple-assign": "0.1.0", 55 | "store": "1.3.20", 56 | "style-loader": "0.13.0", 57 | "superagent": "1.8.0", 58 | "webpack": "1.12.14", 59 | "webpack-dev-server": "1.16.1" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /proxy.js: -------------------------------------------------------------------------------- 1 | var proxy = require('http-proxy').createProxyServer({}); 2 | 3 | proxy.on(function (err, req, res) { 4 | res.writeHead(500, { 5 | 'Content-Type': 'text/plain' 6 | }); 7 | }); 8 | 9 | var server = require('http').createServer(function (req, res) { 10 | var host = req.headers.host; 11 | switch (host) { 12 | case 'www.3fuyu.com': 13 | proxy.web(req, res, {target: 'http://3fuyu.com:8080'}); 14 | break; 15 | case '3fuyu.com': 16 | proxy.web(req, res, {target: 'http://3fuyu.com:8080'}); 17 | break; 18 | case '120.25.92.21': 19 | proxy.web(req, res, {target: '120.25.92.21:8080'}); 20 | break; 21 | default: 22 | res.writeHead(200, { 23 | 'Content-Type': 'text/plain' 24 | }); 25 | 26 | res.end('Welcome to my server!'); 27 | } 28 | }); 29 | console.log("listening on port 80") 30 | 31 | // 监听服务器上 80 端口 32 | server.listen(80); -------------------------------------------------------------------------------- /router/router.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/12. 3 | */ 4 | "use strict"; 5 | 6 | var express = require('express'); 7 | var router = express.Router(); 8 | var _ = require('lodash'); 9 | 10 | var adminArticle = require('../api/management/article'), 11 | user = require('../api/management/user'), 12 | article = require('../api/user/article'), 13 | terms = require('../api/management/terms'), 14 | upload = require('../api/management/upload'); 15 | 16 | // 合并api 17 | var apis = _.concat(adminArticle, article, user, terms, upload); 18 | 19 | apis.forEach(function (value, key) { 20 | if (value.type === 'get') { 21 | router.get(value.url, authorize, function (req, res, next) { 22 | req.session.lastPage = value.url; 23 | 24 | value.success(req, res); 25 | }); 26 | } else if (value.type === 'post') { 27 | router.post(value.url, authorize, function (req, res, next) { 28 | req.session.lastPage = value.url; 29 | 30 | value.success(req, res); 31 | }); 32 | } 33 | }); 34 | 35 | function authorize(req, res, next) { 36 | 37 | // debug 去掉登录态,方便开发 38 | next(); 39 | return; 40 | 41 | if (req.route.path !== '/admin/user/login' && req.route.path.indexOf('/admin/') > -1) { 42 | if (!req.session.user_id) { 43 | res.send({ 44 | code: 401, 45 | description: '用户未登录' 46 | }); 47 | } else { 48 | next(); 49 | } 50 | } else { 51 | next(); 52 | } 53 | } 54 | 55 | module.exports = router; -------------------------------------------------------------------------------- /test/testFormatPara2Camel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 104 | -------------------------------------------------------------------------------- /tools/tools.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/8/12. 3 | */ 4 | "use strict"; 5 | 6 | var _ = require('lodash'); 7 | var Tools = {}; 8 | var formatPara2CamelArray = []; 9 | 10 | function isArray(data) { 11 | if (data && (data instanceof Array) && (data.constructor === Array)) { 12 | return true; 13 | } 14 | } 15 | 16 | function isObject(data) { 17 | if (data && (data instanceof Object) && (data.constructor === Object)) { 18 | return true; 19 | } else { 20 | return false; 21 | } 22 | } 23 | 24 | function checkUnderline(key) { 25 | for (var i = 0; i < key.split('_').length; i++) { 26 | if (key.split('_')[i] !== '') { 27 | return key.split('_')[i]; 28 | } 29 | } 30 | } 31 | 32 | function formatPara2Camel(data) { 33 | // 过滤mogodb返回对象多余类型 34 | data = JSON.stringify(data); 35 | data = JSON.parse(data); 36 | if (isArray(data) || isObject(data)) { 37 | _.each(data, function (value, key) { 38 | if (isArray(value) || isObject(value)) { 39 | formatPara2Camel(value); 40 | } else { 41 | if (key.indexOf('_') > -1) { 42 | if (key.split('_')[0] === '') { 43 | var _key = checkUnderline(key); 44 | data[_key] = data[key]; 45 | delete data[key]; 46 | } else { 47 | var _key = key.replace(/_./g, function (a) {return a.split('_')[1].toUpperCase();}); 48 | data[_key] = data[key]; 49 | delete data[key]; 50 | } 51 | } 52 | } 53 | }); 54 | // 收集数据 55 | formatPara2CamelArray.push(data); 56 | } else { 57 | return data; 58 | } 59 | } 60 | 61 | Tools.para2camel = function (para) { 62 | var data = []; 63 | 64 | formatPara2Camel(para); 65 | formatPara2CamelArray.pop(); 66 | 67 | data = _.cloneDeep(formatPara2CamelArray); 68 | formatPara2CamelArray = []; 69 | 70 | return data; 71 | }; 72 | 73 | module.exports = Tools; -------------------------------------------------------------------------------- /views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /views/user.jade: -------------------------------------------------------------------------------- 1 | // 2 | Created by 3fuyu on 16/8/5. 3 | 4 | 5 | extends layout 6 | 7 | block content 8 | h1= title 9 | p Welcome to #{title} -------------------------------------------------------------------------------- /web/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 目录结构 4 | ``` 5 | +---assets //发布文件夹 6 | | +---css 7 | | +---images 8 | | \---js 9 | +---dist //发布压缩包 10 | | \---dist.zip 11 | \---src //源码 12 | +---css 13 | | \---iconfont 14 | +---images 15 | \---js 16 | +---components 17 | \---service 18 | ``` 19 | 20 | ## service介绍 21 | ``` 22 | service 23 | CacheService.js //缓存服务 24 | DataService.js //接口服务 25 | EnumService.js //枚举服务 26 | RouterService.js //路由服务 27 | StorageService.js //storage服务 28 | FuyuToolService.js //工具类服务 29 | ``` 30 | -------------------------------------------------------------------------------- /web/build/ZeroClipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/ZeroClipboard.swf -------------------------------------------------------------------------------- /web/build/css/font-icons/fonts/material-ui-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/css/font-icons/fonts/material-ui-icons.eot -------------------------------------------------------------------------------- /web/build/css/font-icons/fonts/material-ui-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /web/build/css/font-icons/fonts/material-ui-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/css/font-icons/fonts/material-ui-icons.ttf -------------------------------------------------------------------------------- /web/build/css/font-icons/fonts/material-ui-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/css/font-icons/fonts/material-ui-icons.woff -------------------------------------------------------------------------------- /web/build/css/font-icons/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'material-ui-icons'; 3 | src: url('fonts/material-ui-icons.eot'); 4 | } 5 | @font-face { 6 | font-family: 'material-ui-icons'; 7 | src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'), 8 | url(data:application/font-woff;charset=utf-8;base64,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) format('woff'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | [class^="muidocs-icon-"], [class*=" muidocs-icon-"] { 14 | font-family: 'material-ui-icons'; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | 22 | /* Better Font Rendering =========== */ 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | .muidocs-icon-communication-phone:before { 28 | content: "\e601"; 29 | } 30 | 31 | .muidocs-icon-communication-voicemail:before { 32 | content: "\e602"; 33 | } 34 | 35 | .muidocs-icon-navigation-expand-more:before { 36 | content: "\e603"; 37 | } 38 | 39 | .muidocs-icon-action-grade:before { 40 | content: "\e604"; 41 | } 42 | 43 | .muidocs-icon-action-home:before { 44 | content: "\e605"; 45 | } 46 | 47 | .muidocs-icon-action-stars:before { 48 | content: "\e606"; 49 | } 50 | 51 | .muidocs-icon-action-thumb-up:before { 52 | content: "\e607"; 53 | } 54 | 55 | .muidocs-icon-custom-sort:before { 56 | content: "\e600"; 57 | } 58 | 59 | .muidocs-icon-custom-github:before { 60 | content: "\e625"; 61 | } 62 | 63 | .muidocs-icon-custom-arrow-drop-right:before { 64 | content: "\e60b"; 65 | } 66 | 67 | .muidocs-icon-custom-pie:before { 68 | content: "\e610"; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /web/build/css/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .hljs-template_comment, 18 | .diff .hljs-header, 19 | .hljs-javadoc { 20 | color: #998; 21 | font-style: italic; 22 | } 23 | 24 | .hljs-keyword, 25 | .css .rule .hljs-keyword, 26 | .hljs-winutils, 27 | .nginx .hljs-title, 28 | .hljs-subst, 29 | .hljs-request, 30 | .hljs-status { 31 | color: #333; 32 | font-weight: bold; 33 | } 34 | 35 | .hljs-number, 36 | .hljs-hexcolor, 37 | .ruby .hljs-constant { 38 | color: #008080; 39 | } 40 | 41 | .hljs-string, 42 | .hljs-tag .hljs-value, 43 | .hljs-phpdoc, 44 | .hljs-dartdoc, 45 | .tex .hljs-formula { 46 | color: #d14; 47 | } 48 | 49 | .hljs-title, 50 | .hljs-id, 51 | .scss .hljs-preprocessor { 52 | color: #900; 53 | font-weight: bold; 54 | } 55 | 56 | .hljs-list .hljs-keyword, 57 | .hljs-subst { 58 | font-weight: normal; 59 | } 60 | 61 | .hljs-class .hljs-title, 62 | .hljs-type, 63 | .vhdl .hljs-literal, 64 | .tex .hljs-command { 65 | color: #458; 66 | font-weight: bold; 67 | } 68 | 69 | .hljs-tag, 70 | .hljs-tag .hljs-title, 71 | .hljs-rules .hljs-property, 72 | .django .hljs-tag .hljs-keyword { 73 | color: #000080; 74 | font-weight: normal; 75 | } 76 | 77 | .hljs-attribute, 78 | .hljs-variable, 79 | .lisp .hljs-body { 80 | color: #008080; 81 | } 82 | 83 | .hljs-regexp { 84 | color: #009926; 85 | } 86 | 87 | .hljs-symbol, 88 | .ruby .hljs-symbol .hljs-string, 89 | .lisp .hljs-keyword, 90 | .clojure .hljs-keyword, 91 | .scheme .hljs-keyword, 92 | .tex .hljs-special, 93 | .hljs-prompt { 94 | color: #990073; 95 | } 96 | 97 | .hljs-built_in { 98 | color: #0086b3; 99 | } 100 | 101 | .hljs-preprocessor, 102 | .hljs-pragma, 103 | .hljs-pi, 104 | .hljs-doctype, 105 | .hljs-shebang, 106 | .hljs-cdata { 107 | color: #999; 108 | font-weight: bold; 109 | } 110 | 111 | .hljs-deletion { 112 | background: #fdd; 113 | } 114 | 115 | .hljs-addition { 116 | background: #dfd; 117 | } 118 | 119 | .diff .hljs-change { 120 | background: #0086b3; 121 | } 122 | 123 | .hljs-chunk { 124 | color: #aaa; 125 | } 126 | -------------------------------------------------------------------------------- /web/build/css/main.css: -------------------------------------------------------------------------------- 1 | /* custom font icons */ 2 | @import "font-icons/style.css"; 3 | 4 | /* hightlight.js for syntax highlighting */ 5 | @import "github.css"; 6 | 7 | a { 8 | color: #ff4081; 9 | text-decoration: none; 10 | } 11 | 12 | a:hover { 13 | text-decoration: underline; 14 | } 15 | 16 | html { 17 | font-family: 'Roboto', sans-serif; 18 | -webkit-font-smoothing: antialiased; 19 | } 20 | 21 | body, h1, h2, h3, h4, h5, h6 { 22 | margin: 0; 23 | } 24 | 25 | body { 26 | font-size: 15px; 27 | line-height: 24px; 28 | } 29 | 30 | /* Used in our inline-styles.jsx as an example */ 31 | .muidocs-checkbox-example { 32 | border: 2px solid #FF9800; 33 | background-color: #4CAF50; 34 | } 35 | -------------------------------------------------------------------------------- /web/build/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/fonts/iconfont.eot -------------------------------------------------------------------------------- /web/build/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/fonts/iconfont.ttf -------------------------------------------------------------------------------- /web/build/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/fonts/iconfont.woff -------------------------------------------------------------------------------- /web/build/images/3fuyu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/3fuyu.png -------------------------------------------------------------------------------- /web/build/images/3fuyu_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/3fuyu_bg.jpg -------------------------------------------------------------------------------- /web/build/images/3fuyu_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/3fuyu_small.jpg -------------------------------------------------------------------------------- /web/build/images/angular.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/angular.jpg -------------------------------------------------------------------------------- /web/build/images/banner_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/banner_small.jpg -------------------------------------------------------------------------------- /web/build/images/banner_small_two.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/banner_small_two.jpg -------------------------------------------------------------------------------- /web/build/images/electron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/electron.png -------------------------------------------------------------------------------- /web/build/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/favicon.ico -------------------------------------------------------------------------------- /web/build/images/gomoku.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/gomoku.jpg -------------------------------------------------------------------------------- /web/build/images/mongodb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/mongodb.jpg -------------------------------------------------------------------------------- /web/build/images/nodejs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/nodejs.jpg -------------------------------------------------------------------------------- /web/build/images/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/react.png -------------------------------------------------------------------------------- /web/build/images/vue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/vue.jpg -------------------------------------------------------------------------------- /web/build/images/weex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/images/weex.png -------------------------------------------------------------------------------- /web/build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 3fuyu 8 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /web/build/laboratory/gomoku/index.css: -------------------------------------------------------------------------------- 1 | .main-content{position:relative;background-image:url(./wood.jpg);background-repeat:no-repeat;background-size:700px;margin:0 auto;height:100%;box-shadow:0 0 10px #000}.options{position:absolute;top:80px;right:50px}.options div{width:150px;height:40px;font-size:16px;border-radius:10px;cursor:pointer;box-shadow:0 1px 1px #333;line-height:40px;text-align:center}.board-content{font-size:0;width:600px;margin-left:50px;padding:55px}.board-item{display:inline-block;width:40px;height:40px;position:relative}.row{position:absolute;height:1px;width:100%;content:' ';background-color:#444;top:20px}.column{position:absolute;width:1px;height:100%;content:' ';background-color:#444;left:19px}.row-left-top{position:absolute;width:2px;height:50%;content:' ';background-color:#444;left:20px;top:20px}.column-left-top{position:absolute;height:2px;width:50%;content:' ';background-color:#444;left:20px;top:20px}.row-right-top{position:absolute;width:2px;height:50%;content:' ';background-color:#444;right:20px;top:20px}.column-right-top{position:absolute;height:2px;width:50%;content:' ';background-color:#444;right:20px;top:20px}.row-left-bottom{position:absolute;width:2px;height:50%;content:' ';background-color:#444;left:20px;bottom:20px}.column-left-bottom{position:absolute;height:2px;width:50%;content:' ';background-color:#444;left:20px;bottom:20px}.row-right-bottom{position:absolute;width:2px;height:50%;content:' ';background-color:#444;right:20px;bottom:20px}.column-right-bottom{position:absolute;height:2px;width:50%;content:' ';background-color:#444;right:20px;bottom:20px}.row-top{position:absolute;height:2px;width:100%;content:' ';background-color:#444;top:20px}.column-top{position:absolute;width:1px;height:50%;content:' ';background-color:#444;top:20px;left:19px}.row-bottom{position:absolute;height:2px;width:100%;content:' ';background-color:#444;bottom:20px}.column-bottom{position:absolute;width:1px;height:50%;content:' ';background-color:#444;bottom:20px;left:19px}.row-left{position:absolute;height:1px;width:50%;content:' ';background-color:#444;left:20px;top:20px}.column-left{position:absolute;width:2px;height:100%;content:' ';background-color:#444;left:20px}.row-right{position:absolute;height:1px;width:50%;content:' ';background-color:#444;right:20px;top:20px}.column-right{position:absolute;width:2px;height:100%;content:' ';background-color:#444;right:20px}.black:before{position:absolute;width:100%;height:100%;border-radius:1000px;content:' ';z-index:1;background:-webkit-radial-gradient(30% 25%,circle closest-corner,#777,#222);background:-moz-radial-gradient(30% 25%,circle closest-corner,#777,#222);background:-o-radial-gradient(30% 25%,circle closest-corner,#777,#222);background:-ms-radial-gradient(30% 25%,circle closest-corner,#777,#222);background:radial-gradient(30% 25%,circle closest-corner,#777,#222);-webkit-box-shadow:inset 0 -2px 15px rgba(255,255,255,.3),inset -2px -1px 40px rgba(10,10,10,.4),0 0 2px rgba(0,0,0,.5);box-shadow:inset 0 -2px 15px rgba(255,255,255,.3),inset -2px -1px 40px rgba(10,10,10,.4),0 0 2px rgba(0,0,0,.5);-webkit-transform:scale(.9);-moz-transform:scale(.9);-o-transform:scale(.9);-ms-transform:scale(.9);transform:scale(.9)}.white:before{position:absolute;width:100%;height:100%;border-radius:1000px;content:' ';z-index:1;background:-webkit-radial-gradient(30% 25%,circle closest-corner,#fff,#eee);background:-moz-radial-gradient(30% 25%,circle closest-corner,#fff,#eee);background:-o-radial-gradient(30% 25%,circle closest-corner,#fff,#eee);background:-ms-radial-gradient(30% 25%,circle closest-corner,#fff,#eee);background:radial-gradient(30% 25%,circle closest-corner,#fff,#eee);-webkit-box-shadow:inset 0 -2px 15px rgba(255,255,255,.3),inset -2px -1px 40px rgba(10,10,100,.4),0 0 2px rgba(0,0,0,.5);box-shadow:inset 0 -2px 15px rgba(255,255,255,.3),inset -2px -1px 40px rgba(10,10,100,.4),0 0 2px rgba(0,0,0,.5);-webkit-transform:scale(.9);-moz-transform:scale(.9);-o-transform:scale(.9);-ms-transform:scale(.9);transform:scale(.9)}.options>div{border:1px solid #c27426;background:#c27426;font-weight:700;color:#fff;text-shadow:0 1px 1px #444;background-image:-webkit-gradient(linear,left top,left bottom,from(#d57f29),to(#ae6822));background-image:-webkit-linear-gradient(#d57f29,#ae6822);background-image:-moz-linear-gradient(#d57f29,#ae6822);background-image:-ms-linear-gradient(#d57f29,#ae6822);background-image:-o-linear-gradient(#d57f29,#ae6822);background-image:linear-gradient(#d57f29,#ae6822);margin-bottom:30px} -------------------------------------------------------------------------------- /web/build/laboratory/gomoku/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gomoku 5 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
人机
13 |
重新开始
14 |
悔棋
15 |
16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /web/build/laboratory/gomoku/wood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/build/laboratory/gomoku/wood.jpg -------------------------------------------------------------------------------- /web/build/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "HEAD", 3 | "v0.15.4", 4 | "v0.15.3", 5 | "v0.15.2", 6 | "v0.15.1", 7 | "v0.15.0", 8 | "v0.14.4", 9 | "v0.14.3", 10 | "v0.14.2", 11 | "v0.14.1", 12 | "v0.14.0", 13 | "v0.13.4", 14 | "v0.13.3", 15 | "v0.13.2", 16 | "v0.13.1", 17 | "v0.13.0", 18 | "v0.12.5", 19 | "v0.12.4", 20 | "v0.12.3", 21 | "v0.12.2", 22 | "v0.12.1", 23 | "v0.12.0", 24 | "v0.11.1", 25 | "v0.11.0", 26 | "v0.10.4", 27 | "v0.10.3", 28 | "v0.10.2", 29 | "v0.10.1", 30 | "v0.10.0", 31 | "v0.9.2", 32 | "v0.9.1", 33 | "v0.9.0", 34 | "v0.8.0", 35 | "v0.7.5", 36 | "v0.7.2", 37 | "v0.7.1", 38 | "v0.5.0", 39 | "v0.7.4", 40 | "v0.7.3", 41 | "v0.7.0", 42 | "v0.6.1", 43 | "v0.6.0", 44 | "v0.4.1", 45 | "v0.4.0", 46 | "v0.3.3", 47 | "v0.3.2", 48 | "v0.3.1", 49 | "v0.3.0" 50 | ] 51 | -------------------------------------------------------------------------------- /web/gulpfile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/03/10. 3 | */ 4 | 5 | (function () { 6 | "use strict"; 7 | 8 | var gulp = require('gulp'), 9 | uglify = require('gulp-uglify'), 10 | zip = require('gulp-zip'), 11 | clean = require('gulp-clean'); 12 | // htmlmin = require('gulp-htmlmin'), 13 | // minify = require('gulp-minify-css'); 14 | 15 | var releaseVersion = '1-0-0'; 16 | 17 | var date = new Date(); 18 | var result = date.getFullYear() + (date.getMonth() < 9 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()); 19 | 20 | var debugVersion = releaseVersion.split('-')[0] + '-' + releaseVersion.split('-')[1] + '-' + result; 21 | 22 | var realm = 'quality'; 23 | 24 | gulp.task('default-release', ['build-release-dist', 'clean-src'], function () { 25 | //default 26 | }); 27 | 28 | gulp.task('build-release-dist', ['build-release-directory'], function () { 29 | return gulp.src([ 30 | 'dist/**' 31 | ]) 32 | .pipe(zip(realm + '-' + releaseVersion + '.zip')) 33 | .pipe(gulp.dest('dist')); 34 | 35 | }); 36 | 37 | gulp.task('build-release-directory', ['build-release-directory-index'], function () { 38 | return gulp.src([ 39 | 'assets/*/*' 40 | ]) 41 | .pipe(gulp.dest('dist/quality/assets')); 42 | }); 43 | 44 | gulp.task('build-release-directory-index',['clean-dist'], function () { 45 | return gulp.src([ 46 | 'index.html' 47 | ]) 48 | .pipe(gulp.dest('dist/quality')); 49 | }); 50 | 51 | gulp.task('build-debug-dist', function () { 52 | return gulp.src([ 53 | 'assets/*/*' 54 | ]) 55 | .pipe(zip(realm + '-' + debugVersion + '.zip')) 56 | .pipe(gulp.dest('dist')); 57 | 58 | }); 59 | 60 | gulp.task('clean-src', function () { 61 | return gulp.src([ 62 | 'dist/quality' 63 | ]) 64 | .pipe(clean()); 65 | }); 66 | 67 | gulp.task('clean-dist', function () { 68 | return gulp.src([ 69 | 'dist' 70 | ]) 71 | .pipe(clean()); 72 | }); 73 | 74 | gulp.task('html-min', function () { 75 | return gulp.src([ 76 | 'conf.index.html' 77 | ]) 78 | .pipe( 79 | htmlmin({collapseWhitespace: true}) 80 | ) 81 | .pipe(gulp.dest('dist')); 82 | }); 83 | 84 | gulp.task('css-min', function () { 85 | return gulp.src([ 86 | 'dist/conf.index.html' 87 | ]) 88 | .pipe(minify()) 89 | .pipe(gulp.dest('dist')); 90 | }); 91 | })(); -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-project", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack --colors", 8 | "start": "webpack-dev-server --config webpack.config.js --progress --colors --inline", 9 | "browser:build": "NODE_ENV=docs-production webpack --config webpack-production.config.js --progress --colors --profile" 10 | }, 11 | "author": "3fuyu", 12 | "license": "ISC", 13 | "peerDependencies": { 14 | "react": "15.3.1", 15 | "react-component": "0.0.0", 16 | "react-dom": "15.3.1", 17 | "react-redux": "4.4.5", 18 | "react-router": "2.0.0", 19 | "react-tap-event-plugin": "1.0.0", 20 | "material-ui": "0.15.4" 21 | }, 22 | "dependencies": { 23 | "babel-plugin-transform-react-constant-elements": "6.9.1", 24 | "babel-plugin-transform-react-inline-elements": "6.8.0", 25 | "babel-plugin-transform-react-remove-prop-types": "0.2.9", 26 | "babel-plugin-transform-replace-object-assign": "0.2.1", 27 | "babel-preset-stage-1": "6.13.0", 28 | "material-ui": "0.15.4", 29 | "md5": "2.2.1", 30 | "mongoose": "4.5.8", 31 | "react": "15.3.1", 32 | "react-component": "0.0.0", 33 | "react-dom": "15.3.1", 34 | "react-redux": "4.4.5", 35 | "react-router": "2.0.0" 36 | }, 37 | "devDependencies": { 38 | "autosize": "^3.0.15", 39 | "babel": "^6.5.2", 40 | "babel-core": "^6.6.4", 41 | "babel-loader": "^6.2.4", 42 | "babel-polyfill": "^6.7.2", 43 | "babel-preset-es2015": "^6.6.0", 44 | "babel-preset-react": "^6.5.0", 45 | "copy-webpack-plugin": "^3.0.1", 46 | "css-loader": "^0.23.1", 47 | "fastclick": "^1.0.6", 48 | "gulp": "^3.8.11", 49 | "gulp-browserify": "^0.5.1", 50 | "gulp-clean": "^0.3.2", 51 | "gulp-concat": "^2.5.2", 52 | "gulp-connect": "^2.2.0", 53 | "gulp-react": "^3.0.1", 54 | "gulp-uglify": "^1.5.3", 55 | "gulp-zip": "^3.2.0", 56 | "history": "^2.0.1", 57 | "jquery": "^3.1.1", 58 | "less": "^2.7.1", 59 | "less-loader": "^2.2.3", 60 | "lodash": "^3.6.0", 61 | "marked": "^0.3.6", 62 | "material-ui": "^0.15.4", 63 | "moment": "^2.15.1", 64 | "path": "^0.12.7", 65 | "react": "15.3.1", 66 | "react-addons-perf": "15.3.2", 67 | "react-dom": "15.3.2", 68 | "react-hot-loader": "3.0.0-beta.3", 69 | "react-redux": "4.4.5", 70 | "react-router": "2.8.0", 71 | "react-tap-event-plugin": "1.0.0", 72 | "react-title-component": "1.0.1", 73 | "reactify": "1.1.0", 74 | "redux": "3.6.0", 75 | "store": "1.3.20", 76 | "style-loader": "^0.13.0", 77 | "superagent": "^1.8.0", 78 | "webpack": "^1.12.14", 79 | "webpack-dev-server": "^1.14.1" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /web/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/.DS_Store -------------------------------------------------------------------------------- /web/src/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"], 3 | "plugins": [ 4 | ["transform-replace-object-assign", "simple-assign", "react-hot-loader/babel"] 5 | ], 6 | "env": { 7 | "docs-production": { 8 | "plugins": [ 9 | "transform-react-remove-prop-types", 10 | "transform-react-constant-elements", 11 | "transform-react-inline-elements", 12 | ["transform-replace-object-assign", "simple-assign"] 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/src/app/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/.DS_Store -------------------------------------------------------------------------------- /web/src/app/AppRoutes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Route, Redirect, IndexRoute} from 'react-router'; 3 | import Master from '../app/js/components/management/Master'; 4 | import Login from '../app/js/components/management/Login'; 5 | import Home from '../app/js/components/index/Home'; 6 | import ArticleDetail from '../app/js/components/index/ArticleDetail'; 7 | import NewArticle from '../app/js/components/management/NewArticle'; 8 | import ArticleList from '../app/js/components/management/ArticleList'; 9 | import ArticleCategory from '../app/js/components/management/ArticleCategory'; 10 | import Media from '../app/js/components/management/Media'; 11 | import About from '../app/js/components/index/About'; 12 | import Laboratory from '../app/js/components/index/Laboratory'; 13 | 14 | 15 | // Here we define all our material-ui ReactComponents. 16 | 17 | /** 18 | * Routes: https://github.com/rackt/react-router/blob/master/docs/api/components/Route.md 19 | * 20 | * Routes are used to declare your view hierarchy. 21 | * 22 | * Say you go to http://material-ui.com/#/components/paper 23 | * The react router will search for a route named 'paper' and will recursively render its 24 | * handler and its parent handler like so: Paper > Components > Master 25 | */ 26 | const AppRoutes = ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | 46 | export default AppRoutes; 47 | -------------------------------------------------------------------------------- /web/src/app/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {render} from 'react-dom'; 3 | import $ from 'jquery'; 4 | import {Router, useRouterHistory} from 'react-router'; 5 | import AppRoutes from './AppRoutes'; 6 | import injectTapEventPlugin from 'react-tap-event-plugin'; 7 | import {createHashHistory} from 'history'; 8 | import MuiThemeProvider from '../../node_modules/material-ui/styles/MuiThemeProvider'; 9 | // Helpers for debugging 10 | window.React = React; 11 | window.Perf = require('react-addons-perf'); 12 | window.$ = $; 13 | // Needed for onTouchTap 14 | // http://stackoverflow.com/a/34015469/988941 15 | injectTapEventPlugin(); 16 | 17 | /** 18 | * Render the main app component. You can read more about the react-router here: 19 | * https://github.com/rackt/react-router/blob/master/docs/guides/overview.md 20 | */ 21 | 22 | const App = () => ( 23 | 24 | 25 | {AppRoutes} 26 | 27 | 28 | ); 29 | 30 | render( 31 | 32 | , document.getElementById('app')); 33 | -------------------------------------------------------------------------------- /web/src/app/css/about.less: -------------------------------------------------------------------------------- 1 | #about { 2 | display: flex; 3 | color: #ef6b3a; 4 | font-weight: bold; 5 | flex-direction: column; 6 | font-size: 16px; 7 | font-family: "Microsoft YaHei", Helvetica, Arial, 'Hiragino Sans GB', '微软雅黑', sans-serif; 8 | 9 | .head { 10 | display: flex; 11 | flex-direction: column; 12 | justify-content: center; 13 | align-items: center; 14 | width: 800px; 15 | margin: 0 auto 50px; 16 | .logo { 17 | width: 300px; 18 | margin-top: 20px; 19 | } 20 | .discription { 21 | font-size: 28px; 22 | font-weight: bold; 23 | font-family: "Helvetica Neue", Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', sans-serif; 24 | } 25 | } 26 | .line { 27 | height: 1px; 28 | content: ' '; 29 | margin: 10px 0 80px; 30 | background-color: #ef6b3a; 31 | } 32 | .body { 33 | display: flex; 34 | flex-direction: column; 35 | width: 800px; 36 | margin: 0 auto 200px; 37 | 38 | .about_me { 39 | .title { 40 | font-size: 30px; 41 | font-family: "Helvetica Neue", Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', sans-serif; 42 | } 43 | } 44 | .about_power { 45 | .title { 46 | font-size: 30px; 47 | font-family: "Helvetica Neue", Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', sans-serif; 48 | span { 49 | font-size: 16px; 50 | } 51 | } 52 | .about_power_content { 53 | display: flex; 54 | flex-direction: column; 55 | align-items: center; 56 | } 57 | } 58 | .contact_me { 59 | font-family: "Helvetica Neue", Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', sans-serif; 60 | .title { 61 | font-size: 30px; 62 | } 63 | a { 64 | color: #ef6b3a; 65 | } 66 | } 67 | .attention { 68 | .title { 69 | font-size: 30px; 70 | font-family: "Helvetica Neue", Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', sans-serif; 71 | } 72 | .attention_list { 73 | display: flex; 74 | img { 75 | height: 70px; 76 | margin-right: 40px; 77 | } 78 | } 79 | } 80 | } 81 | .footer { 82 | height: 300px; 83 | width: 100%; 84 | background-color: #212121; 85 | color: #fff; 86 | font-size: 15px; 87 | .footer-content { 88 | text-align: center; 89 | padding-top: 80px; 90 | color: rgba(255, 255, 255, 0.541176); 91 | .footer-content-github { 92 | margin: 10px 0 30px 0; 93 | span { 94 | color: rgba(255, 255, 255, 0.870588) !important; 95 | } 96 | } 97 | .ICP { 98 | font-size: 12px; 99 | img { 100 | position: relative; 101 | top: 3px; 102 | margin: 0 8px; 103 | width: 14px; 104 | height: 14px; 105 | border-radius: 14px; 106 | } 107 | } 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /web/src/app/css/articleCategory.less: -------------------------------------------------------------------------------- 1 | #article-category { 2 | padding: 20px 40px; 3 | 4 | .article-category-title { 5 | margin-bottom: 40px; 6 | } 7 | 8 | .article-category-list { 9 | .article-category-list-title { 10 | } 11 | .article-categoyr-list-content { 12 | display: flex; 13 | flex-wrap: wrap; 14 | .category-label-repeat { 15 | -webkit-font-smoothing: initial; 16 | margin-right: 10px!important; 17 | margin-bottom: 15px!important; 18 | svg { 19 | opacity: 0; 20 | } 21 | span { 22 | color: #fefefe!important; 23 | font-weight: bold; 24 | } 25 | } 26 | .category-label-repeat:hover { 27 | svg { 28 | opacity: 1; 29 | } 30 | } 31 | } 32 | 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /web/src/app/css/articleDetail.less: -------------------------------------------------------------------------------- 1 | #article-detail { 2 | img { 3 | width: 100%; 4 | } 5 | .article-detail-content { 6 | display: flex; 7 | color: #2D3F50; 8 | h1 { 9 | font-size: 40px; 10 | margin: 30px 0 22px 0; 11 | } 12 | h2 { 13 | font-size: 32px; 14 | margin: 30px 0 22px 0; 15 | } 16 | h3 { 17 | font-size: 24px; 18 | margin: 30px 0 22px 0; 19 | } 20 | h4 { 21 | font-size: 16px; 22 | margin: 30px 0 22px 0; 23 | } 24 | 25 | .article-main { 26 | flex: 1; 27 | margin: 100px 50px 50px 150px; 28 | .article-title { 29 | font-size: 50px; 30 | line-height: 1.5; 31 | margin-bottom: 10px; 32 | font-weight: bold; 33 | } 34 | .article-date { 35 | font-size: 14px; 36 | margin-bottom: 20px; 37 | padding-left: 5px; 38 | color: #9EABB3; 39 | } 40 | .article-content { 41 | overflow: auto; 42 | 43 | line-height: 2; 44 | 45 | blockquote { 46 | margin: 20px 0; 47 | padding: 1px 30px; 48 | background: #F2F4F6; 49 | border-left: 10px solid #E8EDEE; 50 | } 51 | 52 | ul { 53 | padding-left: 36px; 54 | margin: 0 0 32px 20px; 55 | li { 56 | margin: 8px 0; 57 | } 58 | li::before { 59 | content: ""; 60 | display: block; 61 | position: relative; 62 | top: 19px; 63 | left: -20px; 64 | width: 6px; 65 | height: 6px; 66 | background: #3A4145; 67 | -moz-border-radius: 50px; 68 | -webkit-border-radius: 50px; 69 | border-radius: 50px; 70 | } 71 | 72 | } 73 | } 74 | #SOHUCS { 75 | margin-top: 55px; 76 | padding-top: 50px; 77 | border-top: 1px dashed #ddd; 78 | } 79 | } 80 | .article-sidebar { 81 | width: 300px; 82 | margin: 280px 20px 20px 20px; 83 | .article-sidebar-category { 84 | font-size: 20px; 85 | line-height: 20px; 86 | } 87 | .article-sidebar-tag-list { 88 | color: #fff; 89 | display: flex; 90 | justify-content: flex-start; 91 | flex-wrap: wrap; 92 | font-size: 12px; 93 | margin-top: 20px; 94 | 95 | .tag-item { 96 | padding: 1px 12px; 97 | background: rgba(0, 0, 0, 0.1); 98 | border-radius: 5px; 99 | margin: 5px 10px 5px 0; 100 | height: 24px; 101 | line-height: 22px; 102 | transition: all 1000ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; 103 | } 104 | 105 | .tag-item:hover { 106 | background-color: #1FBCD2; 107 | color: #fff; 108 | cursor: pointer; 109 | } 110 | } 111 | } 112 | pre { 113 | padding: 16px 22px; 114 | overflow: auto; 115 | font-size: 85%; 116 | line-height: 1.45; 117 | background-color: #f6f6f6; 118 | border-radius: 3px; 119 | line-height: 2; 120 | border-radius: 5px; 121 | } 122 | 123 | code, kbd, pre, samp { 124 | font-family: Monaco, Source Code Pro, Consolas, Menlo, Monaco, Courier New, monospace; 125 | } 126 | 127 | table { 128 | width: 100%; 129 | border: 1px solid #f2f2f2; 130 | padding: 0px 10px; 131 | margin: 10px 0; 132 | border-collapse: collapse; 133 | td, th { 134 | border: 1px solid #f2f2f2; 135 | padding: 0 10px 2px 10px; 136 | } 137 | } 138 | 139 | } 140 | 141 | } -------------------------------------------------------------------------------- /web/src/app/css/articleList.less: -------------------------------------------------------------------------------- 1 | #article-list { 2 | padding: 20px 40px; 3 | .list-head { 4 | th { 5 | font-size: 16px!important; 6 | color: #0e0e0e!important; 7 | } 8 | } 9 | table { 10 | border: none; 11 | th, td { 12 | border: none; 13 | } 14 | .option { 15 | width: 200px; 16 | text-align: center!important; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /web/src/app/css/base.less: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: 'Open Sans', Tahoma, Helvetica, Arial, '黑体', sans-serif!important; 4 | } 5 | 6 | .y-hide { 7 | display: none !important; 8 | } 9 | 10 | ul { 11 | outline: none; 12 | list-style: none; 13 | margin: 0; 14 | padding: 0; 15 | } 16 | 17 | h1, h2, h3, h4, h5, h6 { 18 | -webkit-font-feature-settings: 'dlig' 1, 'liga' 1, 'lnum' 1, 'kern' 1; 19 | -moz-font-feature-settings: 'dlig' 1, 'liga' 1, 'lnum' 1, 'kern' 1; 20 | -o-font-feature-settings: 'dlig' 1, 'liga' 1, 'lnum' 1, 'kern' 1; 21 | color: #2E2E2E; 22 | line-height: 1.15em; 23 | margin: 0 0 0.4em 0; 24 | font-family: "Open Sans", sans-serif; 25 | text-rendering: geometricPrecision; 26 | } 27 | 28 | h2 { 29 | font-size: 36px; 30 | letter-spacing: -1px; 31 | } 32 | 33 | html { 34 | font-family: sans-serif; 35 | -ms-text-size-adjust: 100%; 36 | -webkit-text-size-adjust: 100%; 37 | } -------------------------------------------------------------------------------- /web/src/app/css/github-gist.css: -------------------------------------------------------------------------------- 1 | /** 2 | * GitHub Gist Theme 3 | * Author : Anthony Attard - https://github.com/AnthonyAttard 4 | * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | background: white; 10 | padding: 0.5em; 11 | color: #333333; 12 | overflow-x: auto; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-meta { 17 | color: #969896; 18 | } 19 | 20 | .hljs-variable, 21 | .hljs-template-variable, 22 | .hljs-strong, 23 | .hljs-emphasis, 24 | .hljs-quote { 25 | color: #df5000; 26 | } 27 | 28 | .hljs-keyword, 29 | .hljs-selector-tag, 30 | .hljs-type { 31 | color: #d73a49; 32 | } 33 | 34 | .hljs-literal, 35 | .hljs-symbol, 36 | .hljs-bullet, 37 | .hljs-attribute { 38 | color: #0086b3; 39 | } 40 | 41 | .hljs-section, 42 | .hljs-name { 43 | color: #63a35c; 44 | } 45 | 46 | .hljs-tag { 47 | color: #333333; 48 | } 49 | 50 | .hljs-title, 51 | .hljs-attr, 52 | .hljs-selector-id, 53 | .hljs-selector-class, 54 | .hljs-selector-attr, 55 | .hljs-selector-pseudo { 56 | color: #6f42c1; 57 | } 58 | 59 | .hljs-addition { 60 | color: #55a532; 61 | background-color: #eaffea; 62 | } 63 | 64 | .hljs-deletion { 65 | color: #bd2c00; 66 | background-color: #ffecec; 67 | } 68 | 69 | .hljs-link { 70 | text-decoration: underline; 71 | } 72 | 73 | .hljs-number { 74 | color: #005cc5; 75 | } 76 | 77 | .hljs-string { 78 | color: #032f62; 79 | } 80 | -------------------------------------------------------------------------------- /web/src/app/css/iconfont/iconfont.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face {font-family: "iconfont"; 3 | src: url('iconfont.eot?t=1459136393'); /* IE9*/ 4 | src: url('iconfont.eot?t=1459136393#iefix') format('embedded-opentype'), /* IE6-IE8 */ 5 | url('iconfont.woff?t=1459136393') format('woff'), /* chrome, firefox */ 6 | url('iconfont.ttf?t=1459136393') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ 7 | url('iconfont.svg?t=1459136393#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family:"iconfont" !important; 12 | font-size:16px; 13 | font-style:normal; 14 | -webkit-font-smoothing: antialiased; 15 | -webkit-text-stroke-width: 0.2px; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | .icon-commoditymanagement01:before { content: "\e600"; } 19 | .icon-ordermanagement01:before { content: "\e601"; } 20 | .icon-groupons01:before { content: "\e602"; } 21 | .icon-richscan01:before { content: "\e603"; } 22 | .icon-refund01:before { content: "\e604"; } 23 | .icon-specialoffer01:before { content: "\e605"; } 24 | .icon-income01:before { content: "\e606"; } 25 | .icon-sitemanager01:before { content: "\e607"; } 26 | .icon-statistical01:before { content: "\e608"; } 27 | .icon-operationcofiguration01:before { content: "\e609"; } 28 | .icon-unpaiding01:before { content: "\e60a"; } 29 | .icon-unpaid01:before { content: "\e60b"; } 30 | .icon-delivered01:before { content: "\e60c"; } 31 | .icon-delivereding01:before { content: "\e60d"; } 32 | .icon-closeding01:before { content: "\e60e"; } 33 | .icon-closed01:before { content: "\e60f"; } 34 | .icon-tobeshippde01:before { content: "\e610"; } 35 | .icon-tobeshippdeing:before { content: "\e611"; } 36 | .icon-association01:before { content: "\e612"; } 37 | .icon-deblocking01:before { content: "\e613"; } 38 | .icon-privateletter01:before { content: "\e624"; } 39 | .icon-revamp01:before { content: "\e614"; } 40 | .icon-shoppingcart01:before { content: "\e615"; } 41 | .icon-sort01:before { content: "\e616"; } 42 | .icon-lockin01:before { content: "\e617"; } 43 | .icon-commoditysalesstatistics01:before { content: "\e618"; } 44 | .icon-transactionamountstatistics01:before { content: "\e619"; } 45 | .icon-transactionorderstatistics01:before { content: "\e61a"; } 46 | .icon-rob01:before { content: "\e61b"; } 47 | .icon-reverseback:before { content: "\e625"; } 48 | .icon-skip:before { content: "\e626"; } 49 | .icon-search01:before { content: "\e627"; } 50 | .icon-delete01:before { content: "\e628"; } 51 | .icon-unfold01:before { content: "\e629"; } 52 | .icon-packup01:before { content: "\e62a"; } 53 | .icon-add01:before { content: "\e61e"; } 54 | .icon-subtract01:before { content: "\e61f"; } 55 | .icon-collect01:before { content: "\e620"; } 56 | .icon-collect:before { content: "\e621"; } 57 | .icon-telephone01:before { content: "\e62b"; } 58 | .icon-time:before { content: "\e623"; } 59 | .icon-shopnotices01:before { content: "\e622"; } 60 | .icon-delete1:before { content: "\e61c"; } 61 | .icon-delete2:before { content: "\e61d"; } 62 | .icon-check:before { content: "\e62d"; } 63 | .icon-location:before { content: "\e62c"; } 64 | -------------------------------------------------------------------------------- /web/src/app/css/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/css/iconfont/iconfont.eot -------------------------------------------------------------------------------- /web/src/app/css/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/css/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /web/src/app/css/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/css/iconfont/iconfont.woff -------------------------------------------------------------------------------- /web/src/app/css/laboratory.less: -------------------------------------------------------------------------------- 1 | #laboratory { 2 | display: flex; 3 | flex-direction: column; 4 | font-size: 16px; 5 | width: 1200px; 6 | justify-content: center; 7 | align-items: center; 8 | margin: 0 auto; 9 | .top { 10 | width: 200px; 11 | text-align: center; 12 | .title { 13 | margin-top: 80px; 14 | } 15 | .discription { 16 | color: #666; 17 | margin: 0 0 50px 0; 18 | } 19 | } 20 | .list { 21 | display: flex; 22 | flex-direction: row; 23 | width: 100%; 24 | flex-wrap: wrap; 25 | margin-top: 50px; 26 | .list-item { 27 | display: flex; 28 | flex-direction: column; 29 | width: 265px; 30 | position: relative; 31 | border: 1px solid #eee; 32 | border-radius: 5px; 33 | margin-left: 15px; 34 | margin-right: 15px; 35 | margin-bottom: 30px; 36 | cursor: pointer; 37 | -webkit-transition: box-shadow 0.3s ease-in, -webkit-transform 0.2s ease-in; 38 | transition: box-shadow 0.3s ease-in, transform 0.2s ease-in; 39 | overflow: hidden; 40 | .photo { 41 | img { 42 | width: 265px; 43 | height: auto; 44 | } 45 | } 46 | .title { 47 | color: #333; 48 | font-size: 14px; 49 | margin: 0 10px; 50 | font-weight: bold; 51 | } 52 | .discription { 53 | font-size: 14px; 54 | color: #333; 55 | margin: 5px 10px 10px 10px; 56 | overflow: hidden; 57 | text-overflow: ellipsis; 58 | display: -webkit-box; 59 | -webkit-line-clamp: 2; 60 | -webkit-box-orient: vertical; 61 | } 62 | i.light { 63 | cursor: pointer; 64 | position: absolute; 65 | left: -100%; 66 | top: 0; 67 | width: 100%; 68 | height: 100%; 69 | background-image: -webkit-linear-gradient(0deg,hsla(0,0%,100%,0),hsla(0,0%,100%,.5),hsla(0,0%,100%,0)); 70 | transform: skewx(-25deg); 71 | -o-transform: skewx(-25deg); 72 | -moz-transform: skewx(-25deg); 73 | -webkit-transform: skewx(-25deg); 74 | } 75 | 76 | } 77 | .list-item:hover { 78 | -webkit-transform: translate(0, -6px); 79 | transform: translate(0, -6px); 80 | box-shadow: 0 26px 40px -24px rgba(26, 28, 31, 0.5); 81 | -webkit-box-shadow: 0 26px 40px -24px rgba(26, 28, 31, 0.5); 82 | -moz-box-shadow: 0 26px 40px -24px rgba(26, 28, 31, 0.5); 83 | background-color: white; 84 | i.light { 85 | -webkit-transition: all .3s ease; 86 | transition: all .3s ease; 87 | left: 100%; 88 | } 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /web/src/app/css/login.less: -------------------------------------------------------------------------------- 1 | #login { 2 | width: 20%; 3 | margin: 100px auto; 4 | position: absolute; 5 | left: 0; 6 | right: 0; 7 | .title { 8 | font-size: 30px; 9 | text-align: center; 10 | padding: 50px 0; 11 | } 12 | .content { 13 | input { 14 | width: 100%; 15 | } 16 | .login-btn { 17 | margin-top: 30px; 18 | } 19 | .on-login { 20 | position: relative; 21 | float: right; 22 | top: 58px; 23 | z-index: 1; 24 | i { 25 | font-size: 24px; 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /web/src/app/css/main.less: -------------------------------------------------------------------------------- 1 | //#main { 2 | // .app-bar-title { 3 | // box-shadow: none!important; 4 | // } 5 | .menu { 6 | .menu-title { 7 | background-color: #00BCD4; 8 | height: 64px; 9 | line-height: 64px; 10 | font-size: 20px; 11 | color: #fff; 12 | padding: 0 16px; 13 | } 14 | } 15 | //} 16 | 17 | .show { 18 | display: block; 19 | } 20 | 21 | .hide { 22 | display: none!important; 23 | } -------------------------------------------------------------------------------- /web/src/app/css/markdown.less: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 40px; 3 | margin: 30px 0 22px 0; 4 | } 5 | 6 | h2 { 7 | font-size: 32px; 8 | margin: 30px 0 22px 0; 9 | } 10 | 11 | h3 { 12 | font-size: 24px; 13 | margin: 30px 0 22px 0; 14 | } 15 | 16 | h4 { 17 | font-size: 16px; 18 | margin: 30px 0 22px 0; 19 | } 20 | 21 | pre { 22 | padding: 16px 22px; 23 | word-break: break-all; 24 | white-space: normal; 25 | overflow: auto; 26 | font-size: 85%; 27 | line-height: 1.45; 28 | background-color: #f6f6f6; 29 | border-radius: 3px; 30 | line-height: 2; 31 | border-radius: 5px; 32 | } 33 | 34 | code, kbd, pre, samp { 35 | font-family: Monaco, Source Code Pro, Consolas, Menlo, Monaco, Courier New, monospace; 36 | white-space: pre; 37 | } 38 | 39 | table { 40 | width: 100%; 41 | border: 1px solid #f2f2f2; 42 | padding: 0px 10px; 43 | margin: 10px 0; 44 | border-collapse: collapse; 45 | td, th { 46 | border: 1px solid #f2f2f2; 47 | padding: 0 10px 2px 10px; 48 | } 49 | } 50 | 51 | blockquote { 52 | margin: 20px 0; 53 | padding: 1px 30px; 54 | background: #F2F4F6; 55 | border-left: 10px solid #E8EDEE; 56 | } -------------------------------------------------------------------------------- /web/src/app/css/newArticle.less: -------------------------------------------------------------------------------- 1 | #new-article { 2 | padding: 20px 40px; 3 | .article-title { 4 | z-index: 99; 5 | font-size: 24px!important; 6 | hr { 7 | bottom: 0!important; 8 | } 9 | } 10 | .article-date { 11 | color: #555; 12 | font-size: 16px; 13 | padding: 20px 0 6px 0; 14 | position: relative; 15 | z-index: 99; 16 | } 17 | .article-category { 18 | color: #555; 19 | font-size: 16px; 20 | z-index: 99; 21 | } 22 | #article-editor { 23 | background: #FBFBFB; 24 | position: absolute; 25 | right: 0; 26 | top: 0; 27 | left: 256px; 28 | padding: 250px 40px; 29 | z-index: 9; 30 | height: 100%; 31 | width: 1024px; 32 | font-size: 13pt; 33 | line-height: 1.8em; 34 | resize: none; 35 | outline: none; 36 | display: block; 37 | border: none; 38 | white-space: pre-wrap; 39 | word-wrap: break-word; 40 | box-sizing: border-box; 41 | } 42 | #article-editor:focus { 43 | outline: none; 44 | } 45 | .article-submit { 46 | position: absolute; 47 | bottom: 40px; 48 | right: 40px; 49 | z-index: 99; 50 | span { 51 | color: #FFF; 52 | line-height: 56px; 53 | height: 56px; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /web/src/app/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/fonts/iconfont.eot -------------------------------------------------------------------------------- /web/src/app/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/fonts/iconfont.ttf -------------------------------------------------------------------------------- /web/src/app/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/fonts/iconfont.woff -------------------------------------------------------------------------------- /web/src/app/images/3fuyu_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/3fuyu_bg.jpg -------------------------------------------------------------------------------- /web/src/app/images/add_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/add_pic.png -------------------------------------------------------------------------------- /web/src/app/images/angular.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/angular.jpg -------------------------------------------------------------------------------- /web/src/app/images/banner_small_two.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/banner_small_two.jpg -------------------------------------------------------------------------------- /web/src/app/images/default_xz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/default_xz.png -------------------------------------------------------------------------------- /web/src/app/images/delete_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/delete_btn.png -------------------------------------------------------------------------------- /web/src/app/images/electron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/electron.png -------------------------------------------------------------------------------- /web/src/app/images/gomoku.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/gomoku.jpg -------------------------------------------------------------------------------- /web/src/app/images/gomoku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/gomoku.png -------------------------------------------------------------------------------- /web/src/app/images/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/line.png -------------------------------------------------------------------------------- /web/src/app/images/line_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/line_green.png -------------------------------------------------------------------------------- /web/src/app/images/logo_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/logo_small.jpg -------------------------------------------------------------------------------- /web/src/app/images/mongodb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/mongodb.jpg -------------------------------------------------------------------------------- /web/src/app/images/nodejs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/nodejs.jpg -------------------------------------------------------------------------------- /web/src/app/images/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/react.png -------------------------------------------------------------------------------- /web/src/app/images/select_photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/select_photo.jpg -------------------------------------------------------------------------------- /web/src/app/images/select_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/select_photo.png -------------------------------------------------------------------------------- /web/src/app/images/vue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/vue.jpg -------------------------------------------------------------------------------- /web/src/app/images/weex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/images/weex.png -------------------------------------------------------------------------------- /web/src/app/js/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/js/.DS_Store -------------------------------------------------------------------------------- /web/src/app/js/actions/actions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/9/14. 3 | */ 4 | "use strict"; 5 | 6 | /* 7 | * action 类型 8 | */ 9 | 10 | export const ADD_TODO = 'ADD_TODO'; 11 | export const COMPLETE_TODO = 'COMPLETE_TODO'; 12 | 13 | 14 | /* 15 | * action 创建函数 16 | */ 17 | 18 | export function addTodo(text) { 19 | return { type: ADD_TODO, text }; 20 | } 21 | 22 | export function completeTodo(index) { 23 | return { type: COMPLETE_TODO, index }; 24 | } -------------------------------------------------------------------------------- /web/src/app/js/components/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/js/components/.DS_Store -------------------------------------------------------------------------------- /web/src/app/js/components/index/About.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/7/7. 3 | */ 4 | 5 | import {Component} from 'react'; 6 | import Power from './About_power'; 7 | import '../../../css/about.less'; 8 | import IconButton from "../../../../../node_modules/material-ui/IconButton"; 9 | 10 | class About extends Component { 11 | componentWillMount () { 12 | document.body.scrollTop = 0; 13 | } 14 | render() { 15 | return ( 16 |
17 |
18 | 19 |

3Fuyu

20 |
21 |
22 |
23 |

About Me

24 |

       25 | 3fuyu(张宇),93年生,平常喜欢跑步,大学跑了三年,工作之后有时间就会跑,现在基本每晚四公里。另外还是Steve 26 | Jobs的狂热粉丝,自传读过不下3遍,因此也被“扭曲厂力”感染上了轻微强迫症。

27 |

       28 | 其实,我的真实身份是一枚前端攻城狮,狂热的技术爱好者。如今正是前端遍地开花的时代,一个月不吸收点新知识发发,回头再看前端就是一脸懵逼的状态。因此也提醒自己达摩克利斯之剑一直悬在头上。平常喜欢折腾技术,比如这个blog(该站建成于2017.6,基于React 29 | + Node + 30 | Mongodb,其中之前的技术文章来源于本人2014年至今用wordpress记录的文章)就是用腻了wordpress,hexo等等套路,想搞一些不仅仅限于技术文章,完全自己控制的个人站,比如Laboratory,会持续放出自己实验性的项目。

31 |
32 |
33 |

Power (随时更新)

34 |
35 | 36 |
37 |
38 |
39 |

Contact Me

40 |

Github:    3fuyu 41 |

42 |

QQ:    326141543

43 |

E-mail:    sdlgdxzhangyu@163.com

44 | {/*

Social:    segmentfault */} 45 | {/*| 知乎*/} 46 | {/*

*/} 47 |
48 |
49 |

Attention

50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
59 |
60 |
61 |
62 |
63 |
Remembering that you are going to die
64 |
Stay Hungry Stay Foolish
65 |
66 | 70 |
71 |
72 | 73 | Copyright © 2014 - {new Date().getFullYear()} ICP 16097049. All Rights Reserved. Powered By 3Fuyu. 74 |
75 |
76 |
77 |
78 | ); 79 | } 80 | } 81 | 82 | export default About; 83 | -------------------------------------------------------------------------------- /web/src/app/js/components/index/About_power.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/7/7. 3 | */ 4 | 5 | import {Component} from 'react'; 6 | 7 | let canvas, 8 | mW = 380, 9 | mH = 380, 10 | mData = [ 11 | ['es6/7', 65], 12 | ['html/html5', 82], 13 | ['react', 78], 14 | ['js', 90], 15 | ['css/css3', 81], 16 | ['nodejs', 60], 17 | ], 18 | 19 | mCount = mData.length, //边数 20 | mCenter = mW / 2, //中心点 21 | mRadius = mCenter - 50, //半径(减去的值用于给绘制的文本留空间) 22 | mAngle = Math.PI * 2 / mCount, //角度 23 | mCtx = null, 24 | mColorPolygon = '#B8B8B8', //多边形颜色 25 | mColorLines = '#B8B8B8', //顶点连线颜色 26 | mColorText = '#000000'; 27 | 28 | class About extends Component { 29 | componentDidMount() { 30 | this.initDraw(); 31 | } 32 | 33 | initDraw() { 34 | canvas = document.createElement('canvas'); 35 | document.getElementsByClassName('power')[0].appendChild(canvas); 36 | canvas.height = mH; 37 | canvas.width = mW; 38 | mCtx = canvas.getContext('2d'); 39 | 40 | this.drawPolygon(mCtx); 41 | this.drawLines(mCtx); 42 | this.drawText(mCtx); 43 | this.drawRegion(mCtx); 44 | this.drawCircle(mCtx); 45 | } 46 | 47 | drawPolygon(ctx) { 48 | ctx.save(); 49 | 50 | ctx.strokeStyle = mColorPolygon; 51 | var r = mRadius / mCount; //单位半径 52 | //画6个圈 53 | for (var i = 0; i < mCount; i++) { 54 | ctx.beginPath(); 55 | var currR = r * ( i + 1); //当前半径 56 | //画6条边 57 | for (var j = 0; j < mCount; j++) { 58 | var x = mCenter + currR * Math.cos(mAngle * j); 59 | var y = mCenter + currR * Math.sin(mAngle * j); 60 | 61 | ctx.lineTo(x, y); 62 | } 63 | ctx.closePath() 64 | ctx.stroke(); 65 | } 66 | 67 | ctx.restore(); 68 | } 69 | 70 | //顶点连线 71 | drawLines(ctx) { 72 | ctx.save(); 73 | 74 | ctx.beginPath(); 75 | ctx.strokeStyle = mColorLines; 76 | 77 | for (var i = 0; i < mCount; i++) { 78 | var x = mCenter + mRadius * Math.cos(mAngle * i); 79 | var y = mCenter + mRadius * Math.sin(mAngle * i); 80 | 81 | ctx.moveTo(mCenter, mCenter); 82 | ctx.lineTo(x, y); 83 | } 84 | 85 | ctx.stroke(); 86 | ctx.restore(); 87 | } 88 | 89 | //绘制文本 90 | drawText(ctx) { 91 | ctx.save(); 92 | 93 | var fontSize = mCenter / 12; 94 | ctx.font = fontSize + 'px Microsoft Yahei'; 95 | ctx.fillStyle = mColorText; 96 | 97 | for (var i = 0; i < mCount; i++) { 98 | var x = mCenter + mRadius * Math.cos(mAngle * i); 99 | var y = mCenter + mRadius * Math.sin(mAngle * i); 100 | 101 | if (mAngle * i >= 0 && mAngle * i <= Math.PI / 2) { 102 | ctx.fillText(mData[i][0], x, y + fontSize); 103 | } else if (mAngle * i > Math.PI / 2 && mAngle * i <= Math.PI) { 104 | ctx.fillText(mData[i][0], x - ctx.measureText(mData[i][0]).width, y + fontSize); 105 | } else if (mAngle * i > Math.PI && mAngle * i <= Math.PI * 3 / 2) { 106 | ctx.fillText(mData[i][0], x - ctx.measureText(mData[i][0]).width, y); 107 | } else { 108 | ctx.fillText(mData[i][0], x, y); 109 | } 110 | 111 | } 112 | 113 | ctx.restore(); 114 | } 115 | 116 | //绘制数据区域 117 | drawRegion(ctx) { 118 | ctx.save(); 119 | 120 | ctx.beginPath(); 121 | for (var i = 0; i < mCount; i++) { 122 | var x = mCenter + mRadius * Math.cos(mAngle * i) * mData[i][1] / 100; 123 | var y = mCenter + mRadius * Math.sin(mAngle * i) * mData[i][1] / 100; 124 | 125 | ctx.lineTo(x, y); 126 | } 127 | ctx.closePath(); 128 | ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; 129 | ctx.fill(); 130 | 131 | ctx.restore(); 132 | } 133 | 134 | //画点 135 | drawCircle(ctx) { 136 | ctx.save(); 137 | 138 | var r = mCenter / 40; 139 | for (var i = 0; i < mCount; i++) { 140 | var x = mCenter + mRadius * Math.cos(mAngle * i) * mData[i][1] / 100; 141 | var y = mCenter + mRadius * Math.sin(mAngle * i) * mData[i][1] / 100; 142 | 143 | ctx.beginPath(); 144 | ctx.arc(x, y, r, 0, Math.PI * 2); 145 | ctx.fillStyle = 'rgba(255, 0, 0, 0.8)'; 146 | ctx.fill(); 147 | } 148 | 149 | ctx.restore(); 150 | } 151 | 152 | render() { 153 | return ( 154 |
155 | ); 156 | } 157 | } 158 | 159 | export default About; 160 | -------------------------------------------------------------------------------- /web/src/app/js/components/index/ArticleDetail.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2016/10/19. 3 | */ 4 | 5 | import {Component} from "react"; 6 | import DataServicce from "../../service/DataService"; 7 | import moment from "moment"; 8 | import "../../../css/articleDetail.less"; 9 | import "../../../css/github-gist.css"; 10 | import changyan from "../../lib/changyan"; 11 | 12 | class ArticleDetail extends Component { 13 | 14 | state = { 15 | articleObj: {}, 16 | categorys: ['java', 'javascript', 'python', 'ruby', 'c', 'c++', 'c#', 'ObjectC', 'go'] 17 | }; 18 | 19 | componentWillMount() { 20 | this.loadData(); 21 | } 22 | 23 | componentDidMount() { 24 | this.initComment(); 25 | } 26 | 27 | initComment() { 28 | let t = this, 29 | hash = window.location.hash; 30 | 31 | document.getElementById('SOHUCS').setAttribute('sid', hash.split('/')[hash.split('/').length - 1]); 32 | 33 | changyan.load(); 34 | 35 | window.changyan.api.config({ 36 | appid: 'cyt1S1w3M', 37 | conf: 'prod_73f06d34400f0e589effbae941fad7d8' 38 | }); 39 | } 40 | 41 | loadData() { 42 | let t = this, 43 | id = '', 44 | hash = window.location.hash; 45 | 46 | id = hash.split('/')[hash.split('/').length - 1]; 47 | 48 | window.scrollTo(0, 0); 49 | 50 | DataServicce.getArticleDetail({ 51 | id: id 52 | }).then(function (data) { 53 | t.setState({ 54 | articleObj: data 55 | }); 56 | }); 57 | } 58 | 59 | // componentWillReceiveProps() { 60 | // this.loadData(); 61 | // } 62 | 63 | render() { 64 | return ( 65 |
66 |
67 |
68 |

{this.state.articleObj.postTitle}

69 | 70 |
71 | {moment(this.state.articleObj.postDate).format('MMMM Do YYYY')} 72 |
73 | 74 |
76 | 77 |
78 |
79 |
80 |
81 | 标签 82 |
83 |
84 | {this.state.categorys.map(function (value, key) { 85 | return ( 86 |
{value}
87 | ); 88 | })} 89 |
90 |
91 |
92 |
94 |
95 | 96 | ); 97 | } 98 | } 99 | 100 | export default ArticleDetail; 101 | -------------------------------------------------------------------------------- /web/src/app/js/components/index/Laboratory.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/7/27. 3 | */ 4 | 5 | import {Component} from 'react'; 6 | import '../../../css/laboratory.less'; 7 | 8 | class About extends Component { 9 | state = { 10 | laboratories: [{ 11 | title: '胜率很高的五子棋', 12 | pic: './images/gomoku.jpg', 13 | discription: '纯js,利用五子棋核心算法,每一步棋计算当前和下一步共196种权重可能', 14 | url: 'http://3fuyu.com/laboratory/gomoku/index.html' 15 | }] 16 | } 17 | 18 | componentWillMount () { 19 | document.body.scrollTop = 0; 20 | } 21 | goto (url) { 22 | window.open(url); 23 | } 24 | render() { 25 | let t = this; 26 | 27 | return ( 28 |
29 |
30 |

Laboratory

31 |

less but butter

32 |
33 |
    34 | {this.state.laboratories.map(function (value, key) { 35 | return ( 36 |
  • t.goto(value.url)}> 37 |
    38 |
    {value.title}
    39 |
    {value.discription}
    40 | 41 |
  • 42 | ); 43 | })} 44 |
45 |
46 | ); 47 | } 48 | } 49 | 50 | export default About; 51 | -------------------------------------------------------------------------------- /web/src/app/js/components/lib/Loading.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2016/11/3. 3 | */ 4 | 5 | import {Component} from "react"; 6 | import CircularProgress from "../../../../../node_modules/material-ui/CircularProgress"; 7 | 8 | class Loading extends Component { 9 | render() { 10 | let style = _.extend({ 11 | display: 'flex', 12 | justifyContent: 'center', 13 | flexDirection: 'column', 14 | alignItems: 'center', 15 | margin: '200px auto 800px' 16 | }, this.props.style); 17 | 18 | let contentStyle = { 19 | marginTop: '20px', 20 | color: '#1FBCD2', 21 | fontSie: '20px', 22 | fontWeight: 'bold' 23 | } 24 | 25 | return ( 26 |
27 |
28 | 29 |
30 |
Loading...
31 |
32 | ); 33 | } 34 | } 35 | 36 | export default Loading; -------------------------------------------------------------------------------- /web/src/app/js/components/lib/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/2/17. 3 | */ 4 | 5 | var FILE = { 6 | fileInput: null, //html file控件 7 | dragDrop: null, //拖拽敏感区域 8 | upButton: null, //提交按钮 9 | url: "", //ajax地址 10 | fileFilter: [], //过滤后的文件数组 11 | filter: function (files) { //选择文件组的过滤方法 12 | return files; 13 | }, 14 | onSelect: function () {}, //文件选择后 15 | onDelete: function () {}, //文件删除后 16 | onDragOver: function () {}, //文件拖拽到敏感区域时 17 | onDragLeave: function () {}, //文件离开到敏感区域时 18 | onProgress: function () {}, //文件上传进度 19 | onSuccess: function () {}, //文件上传成功时 20 | onFailure: function () {}, //文件上传失败时, 21 | onComplete: function () {}, //文件全部上传完毕时 22 | 23 | /* 开发参数和内置方法分界线 */ 24 | 25 | //文件拖放 26 | funDragHover: function (e) { 27 | e.stopPropagation(); 28 | e.preventDefault(); 29 | this[e.type === "dragover" ? "onDragOver" : "onDragLeave"].call(e.target); 30 | return this; 31 | }, 32 | //获取选择文件,file控件或拖放 33 | funGetFiles: function (e) { 34 | // 取消鼠标经过样式 35 | this.funDragHover(e); 36 | 37 | // 获取文件列表对象 38 | var files = e.target.files || e.dataTransfer.files; 39 | //继续添加文件 40 | this.fileFilter = this.fileFilter.concat(this.filter(files)); 41 | this.funDealFiles(); 42 | return this; 43 | }, 44 | 45 | //选中文件的处理与回调 46 | funDealFiles: function () { 47 | for (var i = 0, file; file = this.fileFilter[i]; i++) { 48 | //增加唯一索引值 49 | file.index = i; 50 | } 51 | //执行选择回调 52 | this.onSelect(this.fileFilter); 53 | return this; 54 | }, 55 | 56 | //删除对应的文件 57 | funDeleteFile: function (fileDelete) { 58 | var arrFile = []; 59 | for (var i = 0, file; file = this.fileFilter[i]; i++) { 60 | if (file != fileDelete) { 61 | arrFile.push(file); 62 | } else { 63 | this.onDelete(fileDelete); 64 | } 65 | } 66 | this.fileFilter = arrFile; 67 | return this; 68 | }, 69 | 70 | //文件上传 71 | funUploadFile: function () { 72 | var self = this; 73 | if (location.host.indexOf("sitepointstatic") >= 0) { 74 | //非站点服务器上运行 75 | return; 76 | } 77 | for (var i = 0, file; file = this.fileFilter[i]; i++) { 78 | (function (file) { 79 | var xhr = new XMLHttpRequest(); 80 | if (xhr.upload) { 81 | // 上传中 82 | xhr.upload.addEventListener("progress", function (e) { 83 | self.onProgress(file, e.loaded, e.total); 84 | }, false); 85 | 86 | // 文件上传成功或是失败 87 | xhr.onreadystatechange = function (e) { 88 | if (xhr.readyState == 4) { 89 | if (xhr.status == 200) { 90 | self.onSuccess(file, xhr.responseText); 91 | self.funDeleteFile(file); 92 | if (!self.fileFilter.length) { 93 | //全部完毕 94 | self.onComplete(); 95 | } 96 | } else { 97 | self.onFailure(file, xhr.responseText); 98 | } 99 | } 100 | }; 101 | 102 | // 开始上传 103 | xhr.open("POST", self.url, true); 104 | xhr.setRequestHeader("X_FILENAME", encodeURIComponent(file.name)); 105 | xhr.send(file); 106 | } 107 | })(file); 108 | } 109 | 110 | }, 111 | 112 | init: function () { 113 | var self = this; 114 | 115 | if (this.dragDrop) { 116 | this.dragDrop.addEventListener("dragover", function (e) { self.funDragHover(e); }, false); 117 | this.dragDrop.addEventListener("dragleave", function (e) { self.funDragHover(e); }, false); 118 | this.dragDrop.addEventListener("drop", function (e) { self.funGetFiles(e); }, false); 119 | } 120 | 121 | //文件选择控件选择 122 | if (this.fileInput) { 123 | this.fileInput.addEventListener("change", function (e) { self.funGetFiles(e); }, false); 124 | } 125 | 126 | //上传按钮提交 127 | if (this.upButton) { 128 | this.upButton.addEventListener("click", function (e) { self.funUploadFile(e); }, false); 129 | } 130 | } 131 | }; 132 | 133 | module.exports = FILE; 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /web/src/app/js/components/management/AppNavDrawer.js: -------------------------------------------------------------------------------- 1 | import React, {Component, PropTypes} from 'react'; 2 | import Drawer from '../../../../../node_modules/material-ui/Drawer'; 3 | import {List, ListItem, MakeSelectable} from '../../../../../node_modules/material-ui/List'; 4 | import {spacing, typography, zIndex} from '../../../../../node_modules/material-ui/styles'; 5 | import {cyan500} from '../../../../../node_modules/material-ui/styles/colors'; 6 | import DataService from '../../service/DataService'; 7 | 8 | const SelectableList = MakeSelectable(List); 9 | 10 | const styles = { 11 | logo: { 12 | cursor: 'pointer', 13 | fontSize: 24, 14 | color: typography.textFullWhite, 15 | lineHeight: `${spacing.desktopKeylineIncrement}px`, 16 | fontWeight: typography.fontWeightLight, 17 | backgroundColor: cyan500, 18 | paddingLeft: spacing.desktopGutter, 19 | marginBottom: 8, 20 | }, 21 | version: { 22 | paddingLeft: spacing.desktopGutterLess, 23 | fontSize: 16, 24 | }, 25 | }; 26 | 27 | class AppNavDrawer extends Component { 28 | static propTypes = { 29 | docked: PropTypes.bool.isRequired, 30 | location: PropTypes.object.isRequired, 31 | onChangeList: PropTypes.func.isRequired, 32 | onRequestChangeNavDrawer: PropTypes.func.isRequired, 33 | open: PropTypes.bool.isRequired, 34 | style: PropTypes.object, 35 | }; 36 | 37 | static contextTypes = { 38 | muiTheme: PropTypes.object.isRequired, 39 | router: PropTypes.object.isRequired, 40 | }; 41 | 42 | state = { 43 | muiVersions: [], 44 | leftOpen: true, 45 | login: '登出' 46 | }; 47 | 48 | componentDidMount() { 49 | // DataService.getUserInfo({}).then(function (data) { 50 | // console.log(data); 51 | // }); 52 | } 53 | 54 | onLogout() { 55 | DataService.logout({}).then(function (data) { 56 | window.location.href = '#/login'; 57 | }); 58 | } 59 | 60 | render() { 61 | const { 62 | location, 63 | docked, 64 | onRequestChangeNavDrawer, 65 | onChangeList, 66 | open, 67 | style, 68 | } = this.props; 69 | 70 | return ( 71 | 78 |
79 | 3fuyu 管理后台 80 | 81 | {this.state.login} 82 | 83 |
84 | 88 | , 97 | 102 | ]} 103 | /> 104 | 111 | 117 | 124 | 125 |
126 | ); 127 | } 128 | } 129 | 130 | export default AppNavDrawer; 131 | -------------------------------------------------------------------------------- /web/src/app/js/components/management/ArticleCategory.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2016/11/15. 3 | */ 4 | 5 | import {Component} from "react"; 6 | import Avatar from "../../../../../node_modules/material-ui/Avatar"; 7 | import Chip from "../../../../../node_modules/material-ui/Chip"; 8 | import TextField from "../../../../../node_modules/material-ui/TextField"; 9 | import "../../../css/articleCategory.less"; 10 | import FYT from "../../service/FYToolService"; 11 | import md5 from "md5"; 12 | import DataService from "../../service/DataService"; 13 | 14 | const styles = { 15 | chip: { 16 | margin: 4, 17 | color: '#fff' 18 | }, 19 | wrapper: { 20 | display: 'flex', 21 | flexWrap: 'wrap', 22 | }, 23 | labelColors: ['#3F53B1', '#2B98F0', '#1EBBD1', '#159487', '#663EB3', '#9A2EAD', '#E52464', '#F0443C'] 24 | }; 25 | 26 | class ArticleCategory extends Component { 27 | state = { 28 | data: [], 29 | nameErr: '', 30 | inputValue: '' 31 | }; 32 | 33 | componentWillMount() { 34 | this.getTermsList(); 35 | } 36 | 37 | getTermsList() { 38 | let t = this; 39 | 40 | DataService.adminQueryTermsList({}).then(function (data) { 41 | t.setState({ 42 | data: data 43 | }); 44 | }); 45 | } 46 | 47 | handleRequestDelete(value) { 48 | let t = this, 49 | id = $(value.target).closest('.category-label-repeat').attr('data-id'); 50 | 51 | DataService.adminDelTerm({ 52 | id: id 53 | }).then(function (data) { 54 | FYT.tips('删除成功'); 55 | t.getTermsList(); 56 | }); 57 | } 58 | 59 | handleTouchTap() { 60 | console.log('tap'); 61 | } 62 | 63 | submitCategory(_event) { 64 | let t = this; 65 | let event = _.cloneDeep(_event); 66 | 67 | if (event.charCode === 13) { 68 | let value = event.target.value; 69 | 70 | if (value) { 71 | this.setState({ 72 | nameErr: '' 73 | }); 74 | 75 | DataService.adminTermsNew({ 76 | name: value 77 | }).then(function (data) { 78 | FYT.tips('新建成功'); 79 | $(event.target).val(''); 80 | $(event.target).blur(); 81 | 82 | t.getTermsList(); 83 | }); 84 | } else { 85 | this.setState({ 86 | nameErr: '分类不能为空' 87 | }); 88 | } 89 | } 90 | } 91 | 92 | render() { 93 | let t = this; 94 | 95 | return ( 96 |
97 |
98 | this.submitCategory(event)} 101 | errorText={this.state.nameErr} 102 | /> 103 |
104 |
105 |
106 |
107 |
108 | {this.state.data.map(function (value, key) { 109 | return ( 110 | t.handleRequestDelete(value)}> 120 | {value.name.substring(0, 1).toLocaleUpperCase()} 128 | 129 | {value.name} 130 | 131 | ); 132 | })} 133 |
134 |
135 | 136 |
137 | ); 138 | } 139 | } 140 | 141 | export default ArticleCategory; -------------------------------------------------------------------------------- /web/src/app/js/components/management/ArticleList.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/10/11. 3 | */ 4 | 5 | import {Component, PropTypes} from 'react'; 6 | import { 7 | Table, 8 | TableBody, 9 | TableHeader, 10 | TableHeaderColumn, 11 | TableRow, 12 | TableRowColumn 13 | } from '../../../../../node_modules/material-ui/Table'; 14 | import FlatButton from '../../../../../node_modules/material-ui/FlatButton'; 15 | import '../../../css/main.less'; 16 | import '../../../css/articleList.less'; 17 | import DataService from '../../service/DataService'; 18 | import moment from 'moment'; 19 | import Tools from '../../service/FYToolService'; 20 | 21 | class ArticleList extends Component { 22 | constructor(props) { 23 | super(props); 24 | 25 | this.state = { 26 | fixedHeader: false, 27 | fixedFooter: false, 28 | stripedRows: false, 29 | showRowHover: true, 30 | selectable: true, 31 | multiSelectable: true, 32 | enableSelectAll: true, 33 | deselectOnClickaway: true, 34 | showCheckboxes: true, 35 | tableData: [] 36 | }; 37 | } 38 | 39 | static contextTypes = { 40 | router: PropTypes.object.isRequired, 41 | }; 42 | 43 | componentWillMount() { 44 | this.renderList(); 45 | } 46 | 47 | renderList() { 48 | let t = this; 49 | 50 | DataService.adminQueryArticleList().then(function (data) { 51 | t.setState({ 52 | tableData: data 53 | }); 54 | }); 55 | } 56 | 57 | delArticle(row) { 58 | let t = this; 59 | 60 | if (!row.id) return; 61 | 62 | Tools.confirm('删除确认', '确认删除该文章吗?', function () { 63 | DataService.adminDelArticle({ 64 | id: row.id 65 | }).then(function (data) { 66 | Tools.tips('删除成功'); 67 | t.renderList(); 68 | }); 69 | }); 70 | } 71 | 72 | editArticle(row) { 73 | let t = this; 74 | if (!row.id) return; 75 | 76 | t.context.router.push('/management/new-article/' + row.id); 77 | } 78 | 79 | render() { 80 | return ( 81 |
82 | 88 | 89 | 90 | ID 91 | 文章标题 92 | 时间 93 | 分类 94 | 操作 95 | 96 | 97 | 103 | {this.state.tableData.map((row, index) => ( 104 | 105 | {row.id} 106 | {row.postTitle} 107 | {moment(row.postDate).format('YYYY-MM-DD hh:mm')} 108 | {row.postCategoryName} 109 | 110 | this.delArticle(row)}/> 111 | this.editArticle(row)} /> 112 | 113 | 114 | ))} 115 | 116 |
117 |
118 | ); 119 | } 120 | } 121 | 122 | export default ArticleList; -------------------------------------------------------------------------------- /web/src/app/js/components/management/FullWidthSection.js: -------------------------------------------------------------------------------- 1 | import React, {Component, PropTypes} from 'react'; 2 | import ClearFix from '../../../../../node_modules/material-ui/internal/ClearFix'; 3 | import spacing from '../../../../../node_modules/material-ui/styles/spacing'; 4 | import withWidth, {SMALL, LARGE} from '../../../../../node_modules/material-ui/utils/withWidth'; 5 | 6 | const desktopGutter = spacing.desktopGutter; 7 | 8 | class FullWidthSection extends Component { 9 | 10 | static propTypes = { 11 | children: PropTypes.node, 12 | contentStyle: PropTypes.object, 13 | contentType: PropTypes.string, 14 | style: PropTypes.object, 15 | useContent: PropTypes.bool, 16 | width: PropTypes.number.isRequired, 17 | }; 18 | 19 | static defaultProps = { 20 | useContent: false, 21 | contentType: 'div', 22 | }; 23 | 24 | getStyles() { 25 | return { 26 | root: { 27 | padding: desktopGutter, 28 | boxSizing: 'border-box', 29 | }, 30 | content: { 31 | maxWidth: 1200, 32 | margin: '0 auto', 33 | }, 34 | rootWhenSmall: { 35 | paddingTop: desktopGutter * 2, 36 | paddingBottom: desktopGutter * 2, 37 | }, 38 | rootWhenLarge: { 39 | paddingTop: desktopGutter * 3, 40 | paddingBottom: desktopGutter * 3, 41 | }, 42 | }; 43 | } 44 | 45 | render() { 46 | const { 47 | style, 48 | useContent, 49 | contentType, 50 | contentStyle, 51 | width, 52 | ...other, 53 | } = this.props; 54 | 55 | const styles = this.getStyles(); 56 | 57 | let content; 58 | if (useContent) { 59 | content = 60 | React.createElement( 61 | contentType, 62 | {style: Object.assign(styles.content, contentStyle)}, 63 | this.props.children 64 | ); 65 | } else { 66 | content = this.props.children; 67 | } 68 | 69 | return ( 70 | 79 | {content} 80 | 81 | ); 82 | } 83 | } 84 | 85 | export default withWidth()(FullWidthSection); 86 | -------------------------------------------------------------------------------- /web/src/app/js/components/management/Login.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import React, {Component, PropTypes} from 'react'; 4 | import TextField from '../../../../../node_modules/material-ui/TextField'; 5 | import DataService from '../../service/DataService'; 6 | import FYT from '../../service/FYToolService'; 7 | import { Navigation } from "react-router"; 8 | import '../../../css/login.less'; 9 | 10 | class Login extends React.Component { 11 | static contextTypes = { 12 | router: PropTypes.object.isRequired 13 | }; 14 | 15 | state = { 16 | name: '', 17 | password: '', 18 | loginStyle: { 19 | color: '#bbb' 20 | }, 21 | nameErr: '', 22 | passwordErr: '' 23 | }; 24 | 25 | handleChange(event) { 26 | let t = this; 27 | 28 | if (event.target.id === 'login-name') { 29 | this.setState({ 30 | name: event.target.value 31 | }); 32 | } else if (event.target.id === 'login-password') { 33 | this.setState({ 34 | password: event.target.value 35 | }); 36 | } 37 | 38 | setTimeout(function () { 39 | if (t.state.name && t.state.password) { 40 | t.setState({ 41 | loginStyle: { 42 | color: '#ff4081' 43 | } 44 | }); 45 | } else { 46 | t.setState({ 47 | loginStyle: { 48 | color: '#bbb' 49 | } 50 | }); 51 | } 52 | }, 0); 53 | } 54 | 55 | onLogin() { 56 | let t = this; 57 | 58 | t.state.name ? t.setState({nameErr: ''}) : t.setState({nameErr: '请输入用户名'}); 59 | t.state.password ? t.setState({passwordErr: ''}) : t.setState({passwordErr: '请输入密码'}); 60 | 61 | if (t.state.name && t.state.password) { 62 | DataService.login({ 63 | name: t.state.name, 64 | password: t.state.password 65 | }).then(function (data) { 66 | FYT.tips('登录成功!'); 67 | window.location.href = '#/management/article-list'; 68 | }, function (data) { 69 | if (data.errorCode === 401) { 70 | FYT.tips(data.errorDescription); 71 | } else { 72 | throw (data.errorDescription); 73 | } 74 | }); 75 | } 76 | } 77 | listenKeyPress(e) { 78 | if (e.nativeEvent.keyCode === 13) { 79 | this.onLogin(); 80 | } 81 | } 82 | 83 | render() { 84 | return ( 85 |
this.listenKeyPress(e)}> 86 |
87 | 3fuyu's blog 88 |
89 |
90 | this.handleChange(event)} />
98 | 99 |
this.onLogin()} style={this.state.loginStyle}> 100 | 101 |
102 | 103 | this.handleChange(event)}/>
112 |
113 |
114 | ); 115 | } 116 | } 117 | // 118 | // Login.contextTypes = { 119 | // router: React.PropTypes.func.isRequired 120 | // } 121 | 122 | export default Login; -------------------------------------------------------------------------------- /web/src/app/js/components/management/MarkdownElement.js: -------------------------------------------------------------------------------- 1 | import React, {Component, PropTypes} from 'react'; 2 | import marked from 'marked'; 3 | 4 | require('./mui-github-markdown.css'); 5 | 6 | const styles = { 7 | root: { 8 | marginTop: 20, 9 | marginBottom: 20, 10 | padding: '0 10px', 11 | }, 12 | }; 13 | 14 | class MarkdownElement extends Component { 15 | 16 | static propTypes = { 17 | style: PropTypes.object, 18 | text: PropTypes.string.isRequired, 19 | }; 20 | 21 | static defaultProps = { 22 | text: '', 23 | }; 24 | 25 | componentWillMount() { 26 | marked.setOptions({ 27 | gfm: true, 28 | tables: true, 29 | breaks: false, 30 | pedantic: false, 31 | sanitize: false, 32 | smartLists: true, 33 | smartypants: false, 34 | highlight: function(code, lang) { 35 | return require('highlight.js').highlight(lang, code).value; 36 | }, 37 | }); 38 | } 39 | 40 | render() { 41 | const { 42 | style, 43 | text, 44 | } = this.props; 45 | 46 | /* eslint-disable react/no-danger */ 47 | return ( 48 |
53 | ); 54 | /* eslint-enable */ 55 | } 56 | } 57 | 58 | export default MarkdownElement; 59 | -------------------------------------------------------------------------------- /web/src/app/js/components/management/NewArticle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/10/5. 3 | */ 4 | 5 | import React, {Component, PropTypes} from "react"; 6 | import ReactDOM from "react-dom"; 7 | import TextField from "../../../../../node_modules/material-ui/TextField"; 8 | import FloatingActionButton from "../../../../../node_modules/material-ui/FloatingActionButton"; 9 | import ContentAdd from "../../../../../node_modules/material-ui/svg-icons/content/add"; 10 | import AutoComplete from "../../../../../node_modules/material-ui/AutoComplete"; 11 | import DatePicker from "../../../../../node_modules/material-ui/DatePicker"; 12 | import moment from "moment"; 13 | import "../../../css/newArticle.less"; 14 | import DataService from "../../service/DataService"; 15 | import Util from "../../service/FYToolService"; 16 | 17 | const dataSourceConfig = { 18 | text: 'name', 19 | value: 'id' 20 | }; 21 | 22 | let categoryObj = {}; 23 | 24 | class NewArticle extends Component { 25 | state = { 26 | title: '', 27 | date: new Date(), 28 | dataSource: [], 29 | content: '' 30 | }; 31 | 32 | static contextTypes = { 33 | muiTheme: PropTypes.object.isRequired, 34 | router: PropTypes.object.isRequired 35 | }; 36 | 37 | getDate() { 38 | let date = new Date(this.state.date || ''); 39 | 40 | return moment(date).format('YYYY-MM-DD'); 41 | } 42 | 43 | componentDidMount() { 44 | let target = ReactDOM.findDOMNode(document.getElementById('article-editor')), 45 | parentTitle = ReactDOM.findDOMNode(document.getElementsByClassName('article-title')[0]), 46 | parentDate = ReactDOM.findDOMNode(document.getElementsByClassName('article-date')[0]), 47 | parentCategory = ReactDOM.findDOMNode(document.getElementsByClassName('article-category')[0]); 48 | 49 | target.addEventListener('scroll', function () { 50 | let scrollTop = this.scrollTop; 51 | 52 | if (scrollTop < 20) { 53 | $(parentTitle).fadeIn(100); 54 | $(parentDate).fadeIn(100); 55 | $(parentCategory).fadeIn(100); 56 | } else { 57 | $(parentTitle).fadeOut(100); 58 | $(parentDate).fadeOut(100); 59 | $(parentCategory).fadeOut(100); 60 | } 61 | }); 62 | } 63 | 64 | componentWillMount() { 65 | let type = this.props.params.type, 66 | t = this; 67 | 68 | if (type && type !== 'new') { 69 | DataService.adminGetArticle({ 70 | id: type 71 | }).then(function (suc) { 72 | let data = suc[0]; 73 | t.setState({ 74 | content: data.postContent, 75 | date: data.postDate, 76 | title: data.postTitle 77 | }); 78 | }); 79 | } 80 | 81 | this.getCategoryList(); 82 | } 83 | 84 | getCategoryList() { 85 | var t = this; 86 | 87 | DataService.adminQueryTermsList({}).then(function (data) { 88 | t.setState({ 89 | dataSource: data 90 | }); 91 | }); 92 | } 93 | 94 | submit() { 95 | const t = this, 96 | type = this.props.params.type; 97 | 98 | if (type === 'new') { 99 | DataService.adminPostNew({ 100 | title: t.state.title, 101 | content: t.refs.articleContent.value, 102 | categoryId: categoryObj.id, 103 | categoryName: categoryObj.name, 104 | date: +new Date(t.state.date) 105 | }).then(function (data) { 106 | Util.tips('发布成功'); 107 | t.context.router.push('/management/article-list'); 108 | }); 109 | } else { 110 | DataService.adminPostUpdate({ 111 | id: this.props.params.type, 112 | title: t.state.title, 113 | content: t.refs.articleContent.value, 114 | categoryId: categoryObj.id, 115 | categoryName: categoryObj.name, 116 | date: +new Date(t.state.date) 117 | }).then(function (data) { 118 | Util.tips('发布成功'); 119 | t.context.router.push('/management/article-list'); 120 | }); 121 | } 122 | } 123 | 124 | titleChange(e) { 125 | this.setState({ 126 | title: e.target.value 127 | }); 128 | } 129 | 130 | contentChange(e) { 131 | this.setState({ 132 | content: e.target.value 133 | }) 134 | } 135 | 136 | dateChange(event, date) { 137 | this.setState({ 138 | date: date 139 | }); 140 | } 141 | 142 | handleUpdateInput(value) { 143 | // console.log(value); 144 | } 145 | 146 | selectedCategory(value) { 147 | categoryObj = value; 148 | } 149 | 150 | render() { 151 | var t = this, 152 | date = this.getDate(); 153 | 154 | return ( 155 |
156 | this.titleChange(event)} 162 | /> 163 | 164 |
Date:     {date}
165 | 166 | this.selectedCategory(value)} 174 | onUpdateInput={(value) => this.handleUpdateInput(value)} 175 | /> 176 | 177 | 178 | 179 | this.submit()}> 180 | 181 | 182 |
183 | ); 184 | } 185 | } 186 | 187 | export default NewArticle; -------------------------------------------------------------------------------- /web/src/app/js/lib/ZeroClipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/js/lib/ZeroClipboard.swf -------------------------------------------------------------------------------- /web/src/app/js/lib/changyan.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/5/26. 3 | */ 4 | define([], function () { 5 | //畅言滤重 6 | if (window.changyan !== undefined || window.cyan !== undefined) { 7 | return; 8 | } 9 | var createNs = function () { 10 | if (window.changyan !== undefined) { 11 | return; 12 | } else { 13 | window.changyan = {}; 14 | window.changyan.api = {}; 15 | window.changyan.api.config = function (conf) { 16 | window.changyan.api.tmpIsvPageConfig = conf; 17 | }; 18 | window.changyan.api.ready = function (fn) { 19 | window.changyan.api.tmpHandles = window.changyan.api.tmpHandles || []; 20 | window.changyan.api.tmpHandles.push(fn); 21 | }; 22 | window.changyan.ready = function (fn) { 23 | if (window.changyan.rendered) { 24 | fn && fn(); 25 | } else { 26 | window.changyan.tmpHandles = window.changyan.tmpHandles || []; 27 | window.changyan.tmpHandles.push(fn); 28 | } 29 | } 30 | } 31 | }; 32 | 33 | var createMobileNs = function () { 34 | if (window.cyan) { 35 | return; 36 | } 37 | 38 | window.cyan = {}; 39 | window.cyan.api = {}; 40 | window.cyan.api.ready = function (fn) { 41 | window.cyan.api.tmpHandles = window.cyan.api.tmpHandles || []; 42 | window.cyan.api.tmpHandles.push(fn); 43 | }; 44 | }; 45 | 46 | 47 | var loadVersionJs = function () { 48 | var loadJs = function (src, fun) { 49 | var head = document.getElementsByTagName('head')[0] || document.head || document.documentElement; 50 | 51 | var script = document.createElement('script'); 52 | script.setAttribute('type', 'text/javascript'); 53 | script.setAttribute('charset', 'UTF-8'); 54 | script.setAttribute('src', src); 55 | 56 | if (typeof fun === 'function') { 57 | if (window.attachEvent) { 58 | script.onreadystatechange = function () { 59 | var r = script.readyState; 60 | if (r === 'loaded' || r === 'complete') { 61 | script.onreadystatechange = null; 62 | fun(); 63 | } 64 | }; 65 | } else { 66 | script.onload = fun; 67 | } 68 | } 69 | 70 | head.appendChild(script); 71 | }; 72 | 73 | var ver = +new Date() + window.Math.random().toFixed(16); 74 | var protocol = (('https:' == window.document.location.protocol) ? "https://" : "http://"); 75 | var url = protocol + 'changyan.itc.cn/upload/version-v3.js?' + ver; 76 | loadJs(url); 77 | }; 78 | 79 | return { 80 | load: function () { 81 | createNs(); 82 | createMobileNs(); 83 | loadVersionJs(); 84 | } 85 | }; 86 | }); 87 | 88 | -------------------------------------------------------------------------------- /web/src/app/js/reducers/reducers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/9/14. 3 | */ 4 | "use strict"; 5 | 6 | import { combineReducers } from 'redux'; 7 | import todos from './todos'; 8 | 9 | const blog = combineReducers({ 10 | todos 11 | }); 12 | 13 | export default blog; -------------------------------------------------------------------------------- /web/src/app/js/reducers/todos.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/9/14. 3 | */ 4 | "use strict"; 5 | 6 | import { ADD_TODO, COMPLETE_TODO } from '../actions/actions'; 7 | 8 | 9 | function todos(state = [], action) { 10 | switch (action.type) { 11 | case ADD_TODO: 12 | return [ 13 | ...state, 14 | { 15 | text: action.text, 16 | completed: false 17 | } 18 | ]; 19 | case COMPLETE_TODO: 20 | return [ 21 | ...state.slice(0, action.index), 22 | Object.assign({}, state[action.index], { 23 | completed: true 24 | }), 25 | ...state.slice(action.index + 1) 26 | ]; 27 | default: 28 | return state; 29 | } 30 | } 31 | 32 | export default todos; -------------------------------------------------------------------------------- /web/src/app/js/service/CacheService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/03/10. 3 | */ 4 | "use strict"; 5 | 6 | var _ = require('lodash'); 7 | 8 | var CacheService = {}; 9 | 10 | var Params = { 11 | SelectAddress: null, 12 | AllAddress: null, 13 | SelectBill: null 14 | }; 15 | 16 | _.each(Params, function (value, key) { 17 | CacheService[key] = { 18 | get: function () { 19 | return Params[key]; 20 | }, 21 | set: function (_value) { 22 | Params[key] = _value; 23 | }, 24 | getReset: function () { 25 | var _cookie = Params[key]; 26 | Params[key] = null; 27 | return _cookie; 28 | } 29 | }; 30 | }); 31 | 32 | module.exports = CacheService; 33 | -------------------------------------------------------------------------------- /web/src/app/js/service/EnumService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/03/17. 3 | */ 4 | 5 | var ENUM = {}; 6 | 7 | ENUM.TaskStatus = { 8 | 0: '无', 9 | 1: '待执行', 10 | 2: '整改中', 11 | 3: '整改完成待核查', 12 | 4: '整改关闭待核查', 13 | 5: '关闭' 14 | }; 15 | 16 | ENUM.TaskResult = { 17 | 0: '无', 18 | 1: '核查完成', 19 | 2: '核查关闭', 20 | 3: '整改完成', 21 | 4: '整改关闭', 22 | 5: '核查延误', 23 | 6: '复查延误', 24 | 7: '整改延误' 25 | }; 26 | 27 | ENUM.TaskProcessResult = { 28 | 0: '无', 29 | 1: '整改中', 30 | 2: '整改关闭', 31 | 3: '整改合格', 32 | 4: '整改延误' 33 | }; 34 | 35 | module.exports = ENUM; -------------------------------------------------------------------------------- /web/src/app/js/service/RouterService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/03/11. 3 | */ 4 | 5 | var RouterService = {}; 6 | 7 | //RouterService.config = { 8 | // main: { 9 | // url: '/', 10 | // name: 11 | // } 12 | //}; -------------------------------------------------------------------------------- /web/src/app/js/service/StorageService.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 16/03/10. 3 | */ 4 | "use strict"; 5 | 6 | var Storage = require('store'); 7 | var _ = require('lodash'); 8 | 9 | var StorageService = {}; 10 | 11 | var Params = { 12 | TASK_LIST_DATA: null, 13 | GROUP_USERS: null, 14 | DRAFTS_BOX: null, 15 | SIGNATURE: null 16 | }; 17 | 18 | _.each(Params, function (value, key) { 19 | StorageService[key] = { 20 | set: function (value) { 21 | Storage.set(key, value); 22 | }, 23 | get: function () { 24 | return Storage.get(key); 25 | }, 26 | getReset: function () { 27 | var _value = Storage.get(key); 28 | Storage.remove(key); 29 | return _value; 30 | }, 31 | clear: function () { 32 | Storage.remove(key); 33 | }, 34 | clearAll: function () { 35 | Storage.clear(); 36 | }, 37 | has: function () { 38 | return Storage.has(key); 39 | } 40 | }; 41 | }); 42 | 43 | module.exports = StorageService; -------------------------------------------------------------------------------- /web/src/app/js/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 3fuyu on 2017/2/17. 3 | */ 4 | 5 | var FILE = { 6 | fileInput: null, //html file控件 7 | dragDrop: null, //拖拽敏感区域 8 | upButton: null, //提交按钮 9 | url: "", //ajax地址 10 | fileFilter: [], //过滤后的文件数组 11 | filter: function (files) { //选择文件组的过滤方法 12 | return files; 13 | }, 14 | onSelect: function () {}, //文件选择后 15 | onDelete: function () {}, //文件删除后 16 | onDragOver: function () {}, //文件拖拽到敏感区域时 17 | onDragLeave: function () {}, //文件离开到敏感区域时 18 | onProgress: function () {}, //文件上传进度 19 | onSuccess: function () {}, //文件上传成功时 20 | onFailure: function () {}, //文件上传失败时, 21 | onComplete: function () {}, //文件全部上传完毕时 22 | 23 | /* 开发参数和内置方法分界线 */ 24 | 25 | //文件拖放 26 | funDragHover: function (e) { 27 | e.stopPropagation(); 28 | e.preventDefault(); 29 | this[e.type === "dragover" ? "onDragOver" : "onDragLeave"].call(e.target); 30 | return this; 31 | }, 32 | //获取选择文件,file控件或拖放 33 | funGetFiles: function (e) { 34 | // 取消鼠标经过样式 35 | this.funDragHover(e); 36 | 37 | // 获取文件列表对象 38 | var files = e.target.files || e.dataTransfer.files; 39 | //继续添加文件 40 | this.fileFilter = this.fileFilter.concat(this.filter(files)); 41 | this.funDealFiles(); 42 | return this; 43 | }, 44 | 45 | //选中文件的处理与回调 46 | funDealFiles: function () { 47 | for (var i = 0, file; file = this.fileFilter[i]; i++) { 48 | //增加唯一索引值 49 | file.index = i; 50 | } 51 | //执行选择回调 52 | this.onSelect(this.fileFilter); 53 | return this; 54 | }, 55 | 56 | //删除对应的文件 57 | funDeleteFile: function (fileDelete) { 58 | var arrFile = []; 59 | for (var i = 0, file; file = this.fileFilter[i]; i++) { 60 | if (file != fileDelete) { 61 | arrFile.push(file); 62 | } else { 63 | this.onDelete(fileDelete); 64 | } 65 | } 66 | this.fileFilter = arrFile; 67 | return this; 68 | }, 69 | 70 | //文件上传 71 | funUploadFile: function () { 72 | var self = this; 73 | if (location.host.indexOf("sitepointstatic") >= 0) { 74 | //非站点服务器上运行 75 | return; 76 | } 77 | for (var i = 0, file; file = this.fileFilter[i]; i++) { 78 | (function (file) { 79 | var xhr = new XMLHttpRequest(); 80 | if (xhr.upload) { 81 | // 上传中 82 | xhr.upload.addEventListener("progress", function (e) { 83 | self.onProgress(file, e.loaded, e.total); 84 | }, false); 85 | 86 | // 文件上传成功或是失败 87 | xhr.onreadystatechange = function (e) { 88 | if (xhr.readyState == 4) { 89 | if (xhr.status == 200) { 90 | self.onSuccess(file, xhr.responseText); 91 | self.funDeleteFile(file); 92 | if (!self.fileFilter.length) { 93 | //全部完毕 94 | self.onComplete(); 95 | } 96 | } else { 97 | self.onFailure(file, xhr.responseText); 98 | } 99 | } 100 | }; 101 | 102 | // 开始上传 103 | xhr.open("POST", self.url, true); 104 | xhr.setRequestHeader("X_FILENAME", encodeURIComponent(file.name)); 105 | xhr.send(file); 106 | } 107 | })(file); 108 | } 109 | 110 | }, 111 | 112 | init: function () { 113 | var self = this; 114 | 115 | if (this.dragDrop) { 116 | this.dragDrop.addEventListener("dragover", function (e) { self.funDragHover(e); }, false); 117 | this.dragDrop.addEventListener("dragleave", function (e) { self.funDragHover(e); }, false); 118 | this.dragDrop.addEventListener("drop", function (e) { self.funGetFiles(e); }, false); 119 | } 120 | 121 | //文件选择控件选择 122 | if (this.fileInput) { 123 | this.fileInput.addEventListener("change", function (e) { self.funGetFiles(e); }, false); 124 | } 125 | 126 | //上传按钮提交 127 | if (this.upButton) { 128 | this.upButton.addEventListener("click", function (e) { self.funUploadFile(e); }, false); 129 | } 130 | } 131 | }; -------------------------------------------------------------------------------- /web/src/app/laboratory/gomoku/index.css: -------------------------------------------------------------------------------- 1 | .main-content { 2 | position: relative; 3 | background-image: url(./wood.jpg); 4 | background-repeat: no-repeat; 5 | background-size: 700px; 6 | margin: 0 auto; 7 | height: 100%; 8 | box-shadow: 0px 0px 10px #000; 9 | } 10 | 11 | .options { 12 | position: absolute; 13 | top: 80px; 14 | right: 50px; 15 | } 16 | 17 | .options div { 18 | width: 150px; 19 | height: 40px; 20 | font-size: 16px; 21 | border-radius: 10px; 22 | cursor: pointer; 23 | box-shadow: 0 1px 1px #333; 24 | line-height: 40px; 25 | text-align: center; 26 | } 27 | 28 | .board-content { 29 | font-size: 0; 30 | width: 600px; 31 | margin-left: 50px; 32 | padding: 55px; 33 | } 34 | 35 | .board-item { 36 | display: inline-block; 37 | width: 40px; 38 | height: 40px; 39 | position: relative; 40 | } 41 | 42 | .row { 43 | position: absolute; 44 | height: 1px; 45 | width: 100%; 46 | content: ' '; 47 | background-color: #444; 48 | top: 20px; 49 | } 50 | 51 | .column { 52 | position: absolute; 53 | width: 1px; 54 | height: 100%; 55 | content: ' '; 56 | background-color: #444; 57 | left: 19px; 58 | } 59 | 60 | .row-left-top { 61 | position: absolute; 62 | width: 2px; 63 | height: 50%; 64 | content: ' '; 65 | background-color: #444; 66 | left: 20px; 67 | top: 20px; 68 | } 69 | 70 | .column-left-top { 71 | position: absolute; 72 | height: 2px; 73 | width: 50%; 74 | content: ' '; 75 | background-color: #444; 76 | left: 20px; 77 | top: 20px; 78 | } 79 | 80 | .row-right-top { 81 | position: absolute; 82 | width: 2px; 83 | height: 50%; 84 | content: ' '; 85 | background-color: #444; 86 | right: 20px; 87 | top: 20px; 88 | } 89 | 90 | .column-right-top { 91 | position: absolute; 92 | height: 2px; 93 | width: 50%; 94 | content: ' '; 95 | background-color: #444; 96 | right: 20px; 97 | top: 20px; 98 | } 99 | 100 | .row-left-bottom { 101 | position: absolute; 102 | width: 2px; 103 | height: 50%; 104 | content: ' '; 105 | background-color: #444; 106 | left: 20px; 107 | bottom: 20px; 108 | } 109 | 110 | .column-left-bottom { 111 | position: absolute; 112 | height: 2px; 113 | width: 50%; 114 | content: ' '; 115 | background-color: #444; 116 | left: 20px; 117 | bottom: 20px; 118 | } 119 | 120 | .row-right-bottom { 121 | position: absolute; 122 | width: 2px; 123 | height: 50%; 124 | content: ' '; 125 | background-color: #444; 126 | right: 20px; 127 | bottom: 20px; 128 | } 129 | 130 | .column-right-bottom { 131 | position: absolute; 132 | height: 2px; 133 | width: 50%; 134 | content: ' '; 135 | background-color: #444; 136 | right: 20px; 137 | bottom: 20px; 138 | } 139 | 140 | .row-top { 141 | position: absolute; 142 | height: 2px; 143 | width: 100%; 144 | content: ' '; 145 | background-color: #444; 146 | top: 20px; 147 | } 148 | 149 | .column-top { 150 | position: absolute; 151 | width: 1px; 152 | height: 50%; 153 | content: ' '; 154 | background-color: #444; 155 | top: 20px; 156 | left: 19px; 157 | } 158 | 159 | .row-bottom { 160 | position: absolute; 161 | height: 2px; 162 | width: 100%; 163 | content: ' '; 164 | background-color: #444; 165 | bottom: 20px; 166 | } 167 | 168 | .column-bottom { 169 | position: absolute; 170 | width: 1px; 171 | height: 50%; 172 | content: ' '; 173 | background-color: #444; 174 | bottom: 20px; 175 | left: 19px; 176 | } 177 | 178 | .row-left { 179 | position: absolute; 180 | height: 1px; 181 | width: 50%; 182 | content: ' '; 183 | background-color: #444; 184 | left: 20px; 185 | top: 20px; 186 | } 187 | 188 | .column-left { 189 | position: absolute; 190 | width: 2px; 191 | height: 100%; 192 | content: ' '; 193 | background-color: #444; 194 | left: 20px; 195 | } 196 | 197 | .row-right { 198 | position: absolute; 199 | height: 1px; 200 | width: 50%; 201 | content: ' '; 202 | background-color: #444; 203 | right: 20px; 204 | top: 20px; 205 | } 206 | 207 | .column-right { 208 | position: absolute; 209 | width: 2px; 210 | height: 100%; 211 | content: ' '; 212 | background-color: #444; 213 | right: 20px; 214 | } 215 | 216 | .black:before { 217 | position: absolute; 218 | width: 100%; 219 | height: 100%; 220 | border-radius: 1000px; 221 | content: ' '; 222 | z-index: 1; 223 | background: -webkit-radial-gradient(30% 25%, circle closest-corner, #777, #222); 224 | background: -moz-radial-gradient(30% 25%, circle closest-corner, #777, #222); 225 | background: -o-radial-gradient(30% 25%, circle closest-corner, #777, #222); 226 | background: -ms-radial-gradient(30% 25%, circle closest-corner, #777, #222); 227 | background: radial-gradient(30% 25%, circle closest-corner, #777, #222); 228 | -webkit-box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 10, .4), 0 0 2px rgba(0, 0, 0, .5); 229 | box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 10, .4), 0 0 2px rgba(0, 0, 0, .5); 230 | -webkit-transform: scale(.9); 231 | -moz-transform: scale(.9); 232 | -o-transform: scale(.9); 233 | -ms-transform: scale(.9); 234 | transform: scale(.9); 235 | } 236 | 237 | .white:before { 238 | position: absolute; 239 | width: 100%; 240 | height: 100%; 241 | border-radius: 1000px; 242 | content: ' '; 243 | z-index: 1; 244 | background: -webkit-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 245 | background: -moz-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 246 | background: -o-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 247 | background: -ms-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 248 | background: radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 249 | -webkit-box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 100, .4), 0 0 2px rgba(0, 0, 0, .5); 250 | box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 100, .4), 0 0 2px rgba(0, 0, 0, .5); 251 | -webkit-transform: scale(.9); 252 | -moz-transform: scale(.9); 253 | -o-transform: scale(.9); 254 | -ms-transform: scale(.9); 255 | transform: scale(.9); 256 | } 257 | 258 | .options > div { 259 | border: 1px solid #c27426; 260 | background: #c27426; 261 | font-weight: 700; 262 | color: #fff; 263 | text-shadow: 0 1px 1px #444; 264 | background-image: -webkit-gradient(linear, left top, left bottom, from(#D57F29), to(#AE6822)); 265 | background-image: -webkit-linear-gradient(#D57F29, #AE6822); 266 | background-image: -moz-linear-gradient(#D57F29, #AE6822); 267 | background-image: -ms-linear-gradient(#D57F29, #AE6822); 268 | background-image: -o-linear-gradient(#D57F29, #AE6822); 269 | background-image: linear-gradient(#D57F29, #AE6822); 270 | margin-bottom: 30px; 271 | } -------------------------------------------------------------------------------- /web/src/app/laboratory/gomoku/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gomoku 5 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
人机
13 |
重新开始
14 |
悔棋
15 |
16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /web/src/app/laboratory/gomoku/wood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/app/laboratory/gomoku/wood.jpg -------------------------------------------------------------------------------- /web/src/www/css/font-icons/fonts/material-ui-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/css/font-icons/fonts/material-ui-icons.eot -------------------------------------------------------------------------------- /web/src/www/css/font-icons/fonts/material-ui-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /web/src/www/css/font-icons/fonts/material-ui-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/css/font-icons/fonts/material-ui-icons.ttf -------------------------------------------------------------------------------- /web/src/www/css/font-icons/fonts/material-ui-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/css/font-icons/fonts/material-ui-icons.woff -------------------------------------------------------------------------------- /web/src/www/css/font-icons/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'material-ui-icons'; 3 | src: url('fonts/material-ui-icons.eot'); 4 | } 5 | @font-face { 6 | font-family: 'material-ui-icons'; 7 | src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'), 8 | url(data:application/font-woff;charset=utf-8;base64,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) format('woff'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | [class^="muidocs-icon-"], [class*=" muidocs-icon-"] { 14 | font-family: 'material-ui-icons'; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | 22 | /* Better Font Rendering =========== */ 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | .muidocs-icon-communication-phone:before { 28 | content: "\e601"; 29 | } 30 | 31 | .muidocs-icon-communication-voicemail:before { 32 | content: "\e602"; 33 | } 34 | 35 | .muidocs-icon-navigation-expand-more:before { 36 | content: "\e603"; 37 | } 38 | 39 | .muidocs-icon-action-grade:before { 40 | content: "\e604"; 41 | } 42 | 43 | .muidocs-icon-action-home:before { 44 | content: "\e605"; 45 | } 46 | 47 | .muidocs-icon-action-stars:before { 48 | content: "\e606"; 49 | } 50 | 51 | .muidocs-icon-action-thumb-up:before { 52 | content: "\e607"; 53 | } 54 | 55 | .muidocs-icon-custom-sort:before { 56 | content: "\e600"; 57 | } 58 | 59 | .muidocs-icon-custom-github:before { 60 | content: "\e625"; 61 | } 62 | 63 | .muidocs-icon-custom-arrow-drop-right:before { 64 | content: "\e60b"; 65 | } 66 | 67 | .muidocs-icon-custom-pie:before { 68 | content: "\e610"; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /web/src/www/css/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .hljs-template_comment, 18 | .diff .hljs-header, 19 | .hljs-javadoc { 20 | color: #998; 21 | font-style: italic; 22 | } 23 | 24 | .hljs-keyword, 25 | .css .rule .hljs-keyword, 26 | .hljs-winutils, 27 | .nginx .hljs-title, 28 | .hljs-subst, 29 | .hljs-request, 30 | .hljs-status { 31 | color: #333; 32 | font-weight: bold; 33 | } 34 | 35 | .hljs-number, 36 | .hljs-hexcolor, 37 | .ruby .hljs-constant { 38 | color: #008080; 39 | } 40 | 41 | .hljs-string, 42 | .hljs-tag .hljs-value, 43 | .hljs-phpdoc, 44 | .hljs-dartdoc, 45 | .tex .hljs-formula { 46 | color: #d14; 47 | } 48 | 49 | .hljs-title, 50 | .hljs-id, 51 | .scss .hljs-preprocessor { 52 | color: #900; 53 | font-weight: bold; 54 | } 55 | 56 | .hljs-list .hljs-keyword, 57 | .hljs-subst { 58 | font-weight: normal; 59 | } 60 | 61 | .hljs-class .hljs-title, 62 | .hljs-type, 63 | .vhdl .hljs-literal, 64 | .tex .hljs-command { 65 | color: #458; 66 | font-weight: bold; 67 | } 68 | 69 | .hljs-tag, 70 | .hljs-tag .hljs-title, 71 | .hljs-rules .hljs-property, 72 | .django .hljs-tag .hljs-keyword { 73 | color: #000080; 74 | font-weight: normal; 75 | } 76 | 77 | .hljs-attribute, 78 | .hljs-variable, 79 | .lisp .hljs-body { 80 | color: #008080; 81 | } 82 | 83 | .hljs-regexp { 84 | color: #009926; 85 | } 86 | 87 | .hljs-symbol, 88 | .ruby .hljs-symbol .hljs-string, 89 | .lisp .hljs-keyword, 90 | .clojure .hljs-keyword, 91 | .scheme .hljs-keyword, 92 | .tex .hljs-special, 93 | .hljs-prompt { 94 | color: #990073; 95 | } 96 | 97 | .hljs-built_in { 98 | color: #0086b3; 99 | } 100 | 101 | .hljs-preprocessor, 102 | .hljs-pragma, 103 | .hljs-pi, 104 | .hljs-doctype, 105 | .hljs-shebang, 106 | .hljs-cdata { 107 | color: #999; 108 | font-weight: bold; 109 | } 110 | 111 | .hljs-deletion { 112 | background: #fdd; 113 | } 114 | 115 | .hljs-addition { 116 | background: #dfd; 117 | } 118 | 119 | .diff .hljs-change { 120 | background: #0086b3; 121 | } 122 | 123 | .hljs-chunk { 124 | color: #aaa; 125 | } 126 | -------------------------------------------------------------------------------- /web/src/www/css/main.css: -------------------------------------------------------------------------------- 1 | /* custom font icons */ 2 | @import "font-icons/style.css"; 3 | 4 | /* hightlight.js for syntax highlighting */ 5 | @import "github.css"; 6 | 7 | a { 8 | color: #ff4081; 9 | text-decoration: none; 10 | } 11 | 12 | a:hover { 13 | text-decoration: underline; 14 | } 15 | 16 | html { 17 | font-family: 'Roboto', sans-serif; 18 | -webkit-font-smoothing: antialiased; 19 | } 20 | 21 | body, h1, h2, h3, h4, h5, h6 { 22 | margin: 0; 23 | } 24 | 25 | body { 26 | font-size: 15px; 27 | line-height: 24px; 28 | } 29 | 30 | /* Used in our inline-styles.jsx as an example */ 31 | .muidocs-checkbox-example { 32 | border: 2px solid #FF9800; 33 | background-color: #4CAF50; 34 | } 35 | -------------------------------------------------------------------------------- /web/src/www/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/fonts/iconfont.eot -------------------------------------------------------------------------------- /web/src/www/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/fonts/iconfont.ttf -------------------------------------------------------------------------------- /web/src/www/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/fonts/iconfont.woff -------------------------------------------------------------------------------- /web/src/www/images/3fuyu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/3fuyu.png -------------------------------------------------------------------------------- /web/src/www/images/3fuyu_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/3fuyu_bg.jpg -------------------------------------------------------------------------------- /web/src/www/images/3fuyu_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/3fuyu_small.jpg -------------------------------------------------------------------------------- /web/src/www/images/angular.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/angular.jpg -------------------------------------------------------------------------------- /web/src/www/images/banner_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/banner_small.jpg -------------------------------------------------------------------------------- /web/src/www/images/banner_small_two.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/banner_small_two.jpg -------------------------------------------------------------------------------- /web/src/www/images/electron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/electron.png -------------------------------------------------------------------------------- /web/src/www/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/favicon.ico -------------------------------------------------------------------------------- /web/src/www/images/gomoku.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/gomoku.jpg -------------------------------------------------------------------------------- /web/src/www/images/mongodb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/mongodb.jpg -------------------------------------------------------------------------------- /web/src/www/images/nodejs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/nodejs.jpg -------------------------------------------------------------------------------- /web/src/www/images/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/react.png -------------------------------------------------------------------------------- /web/src/www/images/vue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/vue.jpg -------------------------------------------------------------------------------- /web/src/www/images/weex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/images/weex.png -------------------------------------------------------------------------------- /web/src/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 3fuyu 8 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /web/src/www/laboratory/gomoku/index.css: -------------------------------------------------------------------------------- 1 | .main-content { 2 | position: relative; 3 | background-image: url(./wood.jpg); 4 | background-repeat: no-repeat; 5 | background-size: 700px; 6 | margin: 0 auto; 7 | height: 100%; 8 | box-shadow: 0px 0px 10px #000; 9 | } 10 | 11 | .options { 12 | position: absolute; 13 | top: 80px; 14 | right: 50px; 15 | } 16 | 17 | .options div { 18 | width: 150px; 19 | height: 40px; 20 | font-size: 16px; 21 | border-radius: 10px; 22 | cursor: pointer; 23 | box-shadow: 0 1px 1px #333; 24 | line-height: 40px; 25 | text-align: center; 26 | } 27 | 28 | .board-content { 29 | font-size: 0; 30 | width: 600px; 31 | margin-left: 50px; 32 | padding: 55px; 33 | } 34 | 35 | .board-item { 36 | display: inline-block; 37 | width: 40px; 38 | height: 40px; 39 | position: relative; 40 | } 41 | 42 | .row { 43 | position: absolute; 44 | height: 1px; 45 | width: 100%; 46 | content: ' '; 47 | background-color: #444; 48 | top: 20px; 49 | } 50 | 51 | .column { 52 | position: absolute; 53 | width: 1px; 54 | height: 100%; 55 | content: ' '; 56 | background-color: #444; 57 | left: 19px; 58 | } 59 | 60 | .row-left-top { 61 | position: absolute; 62 | width: 2px; 63 | height: 50%; 64 | content: ' '; 65 | background-color: #444; 66 | left: 20px; 67 | top: 20px; 68 | } 69 | 70 | .column-left-top { 71 | position: absolute; 72 | height: 2px; 73 | width: 50%; 74 | content: ' '; 75 | background-color: #444; 76 | left: 20px; 77 | top: 20px; 78 | } 79 | 80 | .row-right-top { 81 | position: absolute; 82 | width: 2px; 83 | height: 50%; 84 | content: ' '; 85 | background-color: #444; 86 | right: 20px; 87 | top: 20px; 88 | } 89 | 90 | .column-right-top { 91 | position: absolute; 92 | height: 2px; 93 | width: 50%; 94 | content: ' '; 95 | background-color: #444; 96 | right: 20px; 97 | top: 20px; 98 | } 99 | 100 | .row-left-bottom { 101 | position: absolute; 102 | width: 2px; 103 | height: 50%; 104 | content: ' '; 105 | background-color: #444; 106 | left: 20px; 107 | bottom: 20px; 108 | } 109 | 110 | .column-left-bottom { 111 | position: absolute; 112 | height: 2px; 113 | width: 50%; 114 | content: ' '; 115 | background-color: #444; 116 | left: 20px; 117 | bottom: 20px; 118 | } 119 | 120 | .row-right-bottom { 121 | position: absolute; 122 | width: 2px; 123 | height: 50%; 124 | content: ' '; 125 | background-color: #444; 126 | right: 20px; 127 | bottom: 20px; 128 | } 129 | 130 | .column-right-bottom { 131 | position: absolute; 132 | height: 2px; 133 | width: 50%; 134 | content: ' '; 135 | background-color: #444; 136 | right: 20px; 137 | bottom: 20px; 138 | } 139 | 140 | .row-top { 141 | position: absolute; 142 | height: 2px; 143 | width: 100%; 144 | content: ' '; 145 | background-color: #444; 146 | top: 20px; 147 | } 148 | 149 | .column-top { 150 | position: absolute; 151 | width: 1px; 152 | height: 50%; 153 | content: ' '; 154 | background-color: #444; 155 | top: 20px; 156 | left: 19px; 157 | } 158 | 159 | .row-bottom { 160 | position: absolute; 161 | height: 2px; 162 | width: 100%; 163 | content: ' '; 164 | background-color: #444; 165 | bottom: 20px; 166 | } 167 | 168 | .column-bottom { 169 | position: absolute; 170 | width: 1px; 171 | height: 50%; 172 | content: ' '; 173 | background-color: #444; 174 | bottom: 20px; 175 | left: 19px; 176 | } 177 | 178 | .row-left { 179 | position: absolute; 180 | height: 1px; 181 | width: 50%; 182 | content: ' '; 183 | background-color: #444; 184 | left: 20px; 185 | top: 20px; 186 | } 187 | 188 | .column-left { 189 | position: absolute; 190 | width: 2px; 191 | height: 100%; 192 | content: ' '; 193 | background-color: #444; 194 | left: 20px; 195 | } 196 | 197 | .row-right { 198 | position: absolute; 199 | height: 1px; 200 | width: 50%; 201 | content: ' '; 202 | background-color: #444; 203 | right: 20px; 204 | top: 20px; 205 | } 206 | 207 | .column-right { 208 | position: absolute; 209 | width: 2px; 210 | height: 100%; 211 | content: ' '; 212 | background-color: #444; 213 | right: 20px; 214 | } 215 | 216 | .black:before { 217 | position: absolute; 218 | width: 100%; 219 | height: 100%; 220 | border-radius: 1000px; 221 | content: ' '; 222 | z-index: 1; 223 | background: -webkit-radial-gradient(30% 25%, circle closest-corner, #777, #222); 224 | background: -moz-radial-gradient(30% 25%, circle closest-corner, #777, #222); 225 | background: -o-radial-gradient(30% 25%, circle closest-corner, #777, #222); 226 | background: -ms-radial-gradient(30% 25%, circle closest-corner, #777, #222); 227 | background: radial-gradient(30% 25%, circle closest-corner, #777, #222); 228 | -webkit-box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 10, .4), 0 0 2px rgba(0, 0, 0, .5); 229 | box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 10, .4), 0 0 2px rgba(0, 0, 0, .5); 230 | -webkit-transform: scale(.9); 231 | -moz-transform: scale(.9); 232 | -o-transform: scale(.9); 233 | -ms-transform: scale(.9); 234 | transform: scale(.9); 235 | } 236 | 237 | .white:before { 238 | position: absolute; 239 | width: 100%; 240 | height: 100%; 241 | border-radius: 1000px; 242 | content: ' '; 243 | z-index: 1; 244 | background: -webkit-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 245 | background: -moz-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 246 | background: -o-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 247 | background: -ms-radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 248 | background: radial-gradient(30% 25%, circle closest-corner, #fff, #eee); 249 | -webkit-box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 100, .4), 0 0 2px rgba(0, 0, 0, .5); 250 | box-shadow: inset 0 -2px 15px rgba(255, 255, 255, .3), inset -2px -1px 40px rgba(10, 10, 100, .4), 0 0 2px rgba(0, 0, 0, .5); 251 | -webkit-transform: scale(.9); 252 | -moz-transform: scale(.9); 253 | -o-transform: scale(.9); 254 | -ms-transform: scale(.9); 255 | transform: scale(.9); 256 | } 257 | 258 | .options > div { 259 | border: 1px solid #c27426; 260 | background: #c27426; 261 | font-weight: 700; 262 | color: #fff; 263 | text-shadow: 0 1px 1px #444; 264 | background-image: -webkit-gradient(linear, left top, left bottom, from(#D57F29), to(#AE6822)); 265 | background-image: -webkit-linear-gradient(#D57F29, #AE6822); 266 | background-image: -moz-linear-gradient(#D57F29, #AE6822); 267 | background-image: -ms-linear-gradient(#D57F29, #AE6822); 268 | background-image: -o-linear-gradient(#D57F29, #AE6822); 269 | background-image: linear-gradient(#D57F29, #AE6822); 270 | margin-bottom: 30px; 271 | } -------------------------------------------------------------------------------- /web/src/www/laboratory/gomoku/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gomoku 5 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
人机
13 |
重新开始
14 |
悔棋
15 |
16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /web/src/www/laboratory/gomoku/wood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/3fuyu/blog/772c4a2562a46a739c80139026ab7a5a9cfa798f/web/src/www/laboratory/gomoku/wood.jpg -------------------------------------------------------------------------------- /web/src/www/management.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 3fuyu 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /web/src/www/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "HEAD", 3 | "v0.15.4", 4 | "v0.15.3", 5 | "v0.15.2", 6 | "v0.15.1", 7 | "v0.15.0", 8 | "v0.14.4", 9 | "v0.14.3", 10 | "v0.14.2", 11 | "v0.14.1", 12 | "v0.14.0", 13 | "v0.13.4", 14 | "v0.13.3", 15 | "v0.13.2", 16 | "v0.13.1", 17 | "v0.13.0", 18 | "v0.12.5", 19 | "v0.12.4", 20 | "v0.12.3", 21 | "v0.12.2", 22 | "v0.12.1", 23 | "v0.12.0", 24 | "v0.11.1", 25 | "v0.11.0", 26 | "v0.10.4", 27 | "v0.10.3", 28 | "v0.10.2", 29 | "v0.10.1", 30 | "v0.10.0", 31 | "v0.9.2", 32 | "v0.9.1", 33 | "v0.9.0", 34 | "v0.8.0", 35 | "v0.7.5", 36 | "v0.7.2", 37 | "v0.7.1", 38 | "v0.5.0", 39 | "v0.7.4", 40 | "v0.7.3", 41 | "v0.7.0", 42 | "v0.6.1", 43 | "v0.6.0", 44 | "v0.4.1", 45 | "v0.4.0", 46 | "v0.3.3", 47 | "v0.3.2", 48 | "v0.3.1", 49 | "v0.3.0" 50 | ] 51 | -------------------------------------------------------------------------------- /web/test/testHightlight.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /web/testHS.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HashAndSearch 6 | 7 | 8 | 9 | 10 | ya 11 | 20 | 21 | -------------------------------------------------------------------------------- /web/webpack-production.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const buildPath = path.resolve(__dirname, 'build'); 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | 7 | const config = { 8 | // Entry point to the project 9 | entry: [ 10 | './node_modules/babel-polyfill/lib/index.js', 11 | path.resolve(__dirname, 'src/app/app.js'), 12 | ], 13 | // Webpack config options on how to obtain modules 14 | resolve: { 15 | // When requiring, you don't need to add these extensions 16 | extensions: ['', '.js', '.md', '.txt'], 17 | alias: { 18 | // material-ui requires will be searched in src folder, not in node_modules 19 | 'material-ui': path.resolve(__dirname, '../src'), 20 | }, 21 | }, 22 | devtool: 'source-map', 23 | // Configuration for server 24 | devServer: { 25 | contentBase: 'build', 26 | // Required for webpack-dev-server 27 | outputPath: buildPath, 28 | }, 29 | // Output file config 30 | output: { 31 | path: buildPath, // Path of output file 32 | filename: 'app.js', // Name of output file 33 | }, 34 | plugins: [ 35 | new webpack.optimize.OccurenceOrderPlugin(), 36 | new webpack.optimize.DedupePlugin(), 37 | new webpack.optimize.UglifyJsPlugin({ 38 | compress: { 39 | warnings: false, 40 | }, 41 | output: { 42 | comments: false, 43 | }, 44 | }), 45 | new webpack.DefinePlugin({ 46 | 'process.env': { 47 | NODE_ENV: JSON.stringify('production'), 48 | }, 49 | }), 50 | 51 | // Allows error warnings but does not stop compiling. Will remove when eslint is added 52 | new webpack.NoErrorsPlugin(), 53 | // Transfer Files 54 | new CopyWebpackPlugin([ 55 | {from: 'src/www/css', to: 'css'}, 56 | {from: 'src/www/images', to: 'images'}, 57 | {from: 'src/www/index.html'}, 58 | {from: 'src/www/versions.json'}, 59 | {from: 'src/app/js/lib/ZeroClipboard.swf'}, 60 | ]), 61 | 62 | ], 63 | module: { 64 | // Allow loading of non-es5 js files. 65 | loaders: [ 66 | { 67 | test: /\.js$/, 68 | loader: 'babel-loader', 69 | exclude: /node_modules/, 70 | }, 71 | { 72 | test: /\.json$/, 73 | loader: 'json-loader', 74 | }, 75 | { 76 | test: /\.txt$/, 77 | loader: 'raw-loader', 78 | include: path.resolve(__dirname, 'src/app/components/raw-code'), 79 | }, 80 | { 81 | test: /\.md$/, 82 | loader: 'raw-loader', 83 | }, 84 | { 85 | test: /\.css$/, 86 | loader: 'style-loader!css-loader', 87 | }, 88 | { 89 | test: /\.(less)$/, 90 | loader: 'style-loader!css-loader!less-loader' 91 | } 92 | ], 93 | }, 94 | eslint: { 95 | configFile: '../.eslintrc', 96 | }, 97 | }; 98 | 99 | module.exports = config; 100 | -------------------------------------------------------------------------------- /web/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const buildPath = path.resolve(__dirname, 'src/www'); 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | 6 | const config = { 7 | // Entry point to the project 8 | entry: [ 9 | 'webpack/hot/dev-server', 10 | 'webpack/hot/only-dev-server', 11 | './node_modules/babel-polyfill/lib/index.js', 12 | path.resolve(__dirname, 'src/app/app.js'), 13 | ], 14 | // Webpack config options on how to obtain modules 15 | resolve: { 16 | // When requiring, you don't need to add these extensions 17 | extensions: ['', '.js', '.md', '.txt'], 18 | alias: { 19 | // material-ui requires will be searched in src folder, not in node_modules 20 | 'material-ui': path.resolve(__dirname, '../src'), 21 | }, 22 | }, 23 | // Configuration for dev server 24 | devServer: { 25 | contentBase: 'src/www', 26 | devtool: 'eval', 27 | hot: true, 28 | inline: true, 29 | port: 3000, 30 | // Required for webpack-dev-server. 31 | outputPath: buildPath, 32 | }, 33 | devtool: 'eval', 34 | // Output file config 35 | output: { 36 | path: buildPath, // Path of output file 37 | filename: 'app.js', // Name of output file 38 | }, 39 | plugins: [ 40 | // Allows for sync with browser while developing (like BrowserSync) 41 | new webpack.HotModuleReplacementPlugin(), 42 | // Allows error warninggs but does not stop compiling. Will remove when eslint is added 43 | new webpack.NoErrorsPlugin(), 44 | new CopyWebpackPlugin([ 45 | {from: 'src/www/index.html'}, 46 | ]), 47 | ], 48 | module: { 49 | // Allow loading of non-es 50 | loaders: [ 51 | { 52 | test: /\.js$/, 53 | loaders: [ 54 | 'babel-loader', 55 | ], 56 | exclude: /node_modules/, 57 | }, 58 | { 59 | test: /\.json$/, 60 | loader: 'json-loader', 61 | }, 62 | { 63 | test: /\.txt$/, 64 | loader: 'raw-loader', 65 | include: path.resolve(__dirname, 'src/app/components/raw-code'), 66 | }, 67 | { 68 | test: /\.md$/, 69 | loader: 'raw-loader', 70 | }, 71 | { 72 | test: /\.css$/, 73 | loader: 'style-loader!css-loader', 74 | }, 75 | { 76 | test: /\.(less)$/, 77 | loader: 'style-loader!css-loader!less-loader' 78 | } 79 | ], 80 | }, 81 | eslint: { 82 | configFile: '../.eslintrc', 83 | }, 84 | }; 85 | 86 | module.exports = config; 87 | --------------------------------------------------------------------------------