From c5ef88062eeaae068d1b5db1ca40cb422ba32f36 Mon Sep 17 00:00:00 2001 From: Guan Guan Date: Sat, 2 Jul 2016 02:01:19 +0800 Subject: [PATCH] Init commit --- .gitignore | 7 + Gruntfile.js | 239 ++++++++++ README.md | 2 +- app/404.html | 157 +++++++ app/images/favicon.ico | Bin 0 -> 5876 bytes app/index.html | 75 +++ app/less/draft.less | 223 +++++++++ app/less/main.less | 495 ++++++++++++++++++++ app/robots.txt | 3 + app/scripts/actions/article.js | 5 + app/scripts/actions/articleactions.js | 8 + app/scripts/actions/banuseractions.js | 9 + app/scripts/actions/explorebanneractions.js | 9 + app/scripts/actions/explorethemeactions.js | 9 + app/scripts/actions/feedbackactions.js | 8 + app/scripts/actions/judgepostactions.js | 8 + app/scripts/actions/postactions.js | 20 + app/scripts/actions/recommendhomeactions.js | 8 + app/scripts/actions/reportactions.js | 10 + app/scripts/actions/skuactions.js | 12 + app/scripts/actions/statsactions.js | 7 + app/scripts/actions/stickeractions.js | 13 + app/scripts/actions/tagactions.js | 11 + app/scripts/actions/tagclassactions.js | 7 + app/scripts/actions/useractions.js | 16 + app/scripts/actions/userdetailactions.js | 13 + app/scripts/app.js | 51 ++ app/scripts/components/articlelist.jsx | 56 +++ app/scripts/components/bannedusers.jsx | 56 +++ app/scripts/components/brandlist.jsx | 62 +++ app/scripts/components/editarticle.jsx | 439 +++++++++++++++++ app/scripts/components/editrecommend.jsx | 149 ++++++ app/scripts/components/editshortvideo.jsx | 210 +++++++++ app/scripts/components/editsku.jsx | 248 ++++++++++ app/scripts/components/editsticker.jsx | 102 ++++ app/scripts/components/editstickerset.jsx | 125 +++++ app/scripts/components/edittag.jsx | 173 +++++++ app/scripts/components/explorepage.jsx | 147 ++++++ app/scripts/components/feedback.jsx | 54 +++ app/scripts/components/home.jsx | 64 +++ app/scripts/components/judgeposts.jsx | 45 ++ app/scripts/components/layout.jsx | 124 +++++ app/scripts/components/postlist.jsx | 142 ++++++ app/scripts/components/postpanel.jsx | 146 ++++++ app/scripts/components/recommendhome.jsx | 64 +++ app/scripts/components/report.jsx | 118 +++++ app/scripts/components/skulist.jsx | 152 ++++++ app/scripts/components/stickerlist.jsx | 94 ++++ app/scripts/components/taglist.jsx | 160 +++++++ app/scripts/components/test.jsx | 18 + app/scripts/components/userdetail.jsx | 184 ++++++++ app/scripts/components/userlist.jsx | 93 ++++ app/scripts/reducers/article.js | 14 + app/scripts/stores/activeusersstore.js | 32 ++ app/scripts/stores/articlestore.js | 75 +++ app/scripts/stores/banuserstore.js | 56 +++ app/scripts/stores/explorebannerstore.js | 62 +++ app/scripts/stores/explorethemestore.js | 67 +++ app/scripts/stores/feedbackstore.js | 53 +++ app/scripts/stores/judgepoststore.js | 56 +++ app/scripts/stores/poststore.js | 212 +++++++++ app/scripts/stores/recommendhomestore.js | 48 ++ app/scripts/stores/reportstore.js | 85 ++++ app/scripts/stores/skustore.js | 146 ++++++ app/scripts/stores/statsstore.js | 31 ++ app/scripts/stores/stickerstore.js | 97 ++++ app/scripts/stores/tagclassstore.js | 33 ++ app/scripts/stores/tagstore.js | 117 +++++ app/scripts/stores/userdetailstore.js | 235 ++++++++++ app/scripts/stores/userliststore.js | 56 +++ app/scripts/utils/stateToHTML.js | 337 +++++++++++++ app/scripts/widgets/cdn.jsx | 26 + app/scripts/widgets/if.jsx | 13 + app/scripts/widgets/numbercard.jsx | 36 ++ app/scripts/widgets/test.jsx | 21 + bower.json | 25 + package.json | 72 +++ 77 files changed, 6654 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 Gruntfile.js create mode 100644 app/404.html create mode 100644 app/images/favicon.ico create mode 100644 app/index.html create mode 100644 app/less/draft.less create mode 100644 app/less/main.less create mode 100644 app/robots.txt create mode 100644 app/scripts/actions/article.js create mode 100644 app/scripts/actions/articleactions.js create mode 100644 app/scripts/actions/banuseractions.js create mode 100644 app/scripts/actions/explorebanneractions.js create mode 100644 app/scripts/actions/explorethemeactions.js create mode 100644 app/scripts/actions/feedbackactions.js create mode 100644 app/scripts/actions/judgepostactions.js create mode 100644 app/scripts/actions/postactions.js create mode 100644 app/scripts/actions/recommendhomeactions.js create mode 100644 app/scripts/actions/reportactions.js create mode 100644 app/scripts/actions/skuactions.js create mode 100644 app/scripts/actions/statsactions.js create mode 100644 app/scripts/actions/stickeractions.js create mode 100644 app/scripts/actions/tagactions.js create mode 100644 app/scripts/actions/tagclassactions.js create mode 100644 app/scripts/actions/useractions.js create mode 100644 app/scripts/actions/userdetailactions.js create mode 100644 app/scripts/app.js create mode 100644 app/scripts/components/articlelist.jsx create mode 100644 app/scripts/components/bannedusers.jsx create mode 100644 app/scripts/components/brandlist.jsx create mode 100644 app/scripts/components/editarticle.jsx create mode 100644 app/scripts/components/editrecommend.jsx create mode 100644 app/scripts/components/editshortvideo.jsx create mode 100644 app/scripts/components/editsku.jsx create mode 100644 app/scripts/components/editsticker.jsx create mode 100644 app/scripts/components/editstickerset.jsx create mode 100644 app/scripts/components/edittag.jsx create mode 100644 app/scripts/components/explorepage.jsx create mode 100644 app/scripts/components/feedback.jsx create mode 100644 app/scripts/components/home.jsx create mode 100644 app/scripts/components/judgeposts.jsx create mode 100644 app/scripts/components/layout.jsx create mode 100644 app/scripts/components/postlist.jsx create mode 100644 app/scripts/components/postpanel.jsx create mode 100644 app/scripts/components/recommendhome.jsx create mode 100644 app/scripts/components/report.jsx create mode 100644 app/scripts/components/skulist.jsx create mode 100644 app/scripts/components/stickerlist.jsx create mode 100644 app/scripts/components/taglist.jsx create mode 100644 app/scripts/components/test.jsx create mode 100644 app/scripts/components/userdetail.jsx create mode 100644 app/scripts/components/userlist.jsx create mode 100644 app/scripts/reducers/article.js create mode 100644 app/scripts/stores/activeusersstore.js create mode 100644 app/scripts/stores/articlestore.js create mode 100644 app/scripts/stores/banuserstore.js create mode 100644 app/scripts/stores/explorebannerstore.js create mode 100644 app/scripts/stores/explorethemestore.js create mode 100644 app/scripts/stores/feedbackstore.js create mode 100644 app/scripts/stores/judgepoststore.js create mode 100644 app/scripts/stores/poststore.js create mode 100644 app/scripts/stores/recommendhomestore.js create mode 100644 app/scripts/stores/reportstore.js create mode 100644 app/scripts/stores/skustore.js create mode 100644 app/scripts/stores/statsstore.js create mode 100644 app/scripts/stores/stickerstore.js create mode 100644 app/scripts/stores/tagclassstore.js create mode 100644 app/scripts/stores/tagstore.js create mode 100644 app/scripts/stores/userdetailstore.js create mode 100644 app/scripts/stores/userliststore.js create mode 100644 app/scripts/utils/stateToHTML.js create mode 100644 app/scripts/widgets/cdn.jsx create mode 100644 app/scripts/widgets/if.jsx create mode 100644 app/scripts/widgets/numbercard.jsx create mode 100644 app/scripts/widgets/test.jsx create mode 100644 bower.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fd3dec --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +dist/* +node_modules/* +target/* +.tmp/* +.sass-cache/* +app/styles/* +app/vendor/* diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..14e0ee4 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,239 @@ +'use strict'; + +var livereload = require('connect-livereload'), + path = require('path'); + +module.exports = function (grunt) { + + // show elapsed time at the end + require('time-grunt')(grunt); + + // load all grunt tasks + require('load-grunt-tasks')(grunt); + + // Project settings + var yeomanConfig = { + app: require('./bower.json').appPath || 'app', + dist: 'dist' + }; + + grunt.initConfig({ + yeoman: yeomanConfig, + connect: { + options: { + port: 3000, + hostname: '0.0.0.0' //change to 'localhost' to disable outside connections + }, + livereload: { + options: { + middleware: function (connect) { + return [ + livereload({port: 35729}), + connect.static(path.resolve('.tmp')), + connect.static(path.resolve(yeomanConfig.app)) + ]; + } + } + } + }, + watch: { + options: { + livereload: 35729 + }, + less: { + files: ['app/less/*.less'], + tasks: ['less:dev'] + }, + gruntfile: { + files: ['Gruntfile.js'] + }, + livereload: { + options: { + livereload: '<%= connect.options.livereload %>' + }, + files: [ + '<%= yeoman.app %>/{,*/}*.html', + '.tmp/styles/{,*/}*.css', + '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' + ] + }, + react: { + files: ['<%= yeoman.app %>/scripts/**/*.{jsx,js}'], + tasks: ['browserify:dist'], + options: { + livereload: true + } + }, + images: { + files: [ + '<%= yeoman.app %>/*.html', + '<%= yeoman.app %>/images/{,*/}*.{ico,icon,png,jpg,jpeg,gif,webp,svg}' + ] + } + }, + clean: { + dist: ['.tmp', '<%= yeoman.dist %>/*'], + serve: '.tmp' + }, + less: { + dev: { + options: { + compress: true, + paths: ['app/vendor/bootstrap/less', 'app/styles'] + }, + files: { + 'app/styles/main.css': 'app/less/main.less' + } + } + }, + browserify: { + options: { + transform: [ + [ 'reactify', {'es6': true} ] + ] + }, + dist: { + files: { + '.tmp/scripts/bundle/app.js': '<%= yeoman.app %>/scripts/app.js' + }, + options: { + browserifyOptions: { + extensions: '.jsx' + }, + transform: [ + ['babelify', { + }] + ] + } + } + }, + useminPrepare: { + src: '<%= yeoman.app %>/index.html', + options: { + dest: '<%= yeoman.dist %>' + } + }, + imagemin: { + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.app %>/images', + src: '{,*/}*.{png,jpg,jpeg}', + dest: '<%= yeoman.dist %>/images' + }] + } + }, + htmlmin: { + dist: { + options: { + //removeCommentsFromCDATA: true, + // https://github.com/yeoman/grunt-usemin/issues/44 + collapseWhitespace: true, + collapseBooleanAttributes: true, + //removeAttributeQuotes: true, + removeRedundantAttributes: true, + //useShortDoctype: true, + removeEmptyAttributes: true, + //removeOptionalTags: true + }, + files: [{ + expand: true, + cwd: '<%= yeoman.dist %>', + src: '*.html', + dest: '<%= yeoman.dist %>' + }] + } + }, + filerev: { + dist: { + files: [{ + src: [ + '<%= yeoman.dist %>/scripts/**/*.js', + '<%= yeoman.dist %>/styles/**/*.css', + '<%= yeoman.dist %>/vendor/**/*.js' + ] + }] + } + }, + autoprefixer: { + options: { + browsers: [ + 'last 5 versions' + ] + }, + dist: { + expand: true, + src: '.tmp/concat/styles/*.css' + } + }, + copy: { + dist: { + files: [{ + expand: true, + dot: true, + cwd: '<%= yeoman.app %>', + dest: '<%= yeoman.dist %>', + src: [ + '*.html', + '*.wav', + '*.{ico,txt}', + 'images/{,*/}*.{ico,webp,gif}' + ] + }, { + expand: true, + flatten: true, + cwd: '<%= yeoman.app %>', + src: [ + 'vendor/bootstrap/dist/fonts/*.*', + 'vendor/font-awesome/fonts/*.*' + ], + dest: '<%= yeoman.dist %>/fonts' + }] + } + }, + usemin: { + html: ['<%= yeoman.dist %>/{,*/}*.html'], + css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], + options: { + dirs: ['<%= yeoman.dist %>'] + } + }, + env : { + options : { + }, + dev : { + NODE_ENV : 'production' + }, + build : { + NODE_ENV : 'production' + } + } + }); + + grunt.registerTask('server', [ + 'clean:serve', + 'less:dev', + 'browserify', + // 'connect:livereload', + 'watch' + ]); + + grunt.registerTask('build', [ + 'clean:dist', + 'browserify', + 'useminPrepare', + 'autoprefixer', + 'concat', + 'imagemin', + 'cssmin', + 'uglify', + 'copy', + 'filerev', + 'usemin', + 'htmlmin' + ]); + + grunt.registerTask('default', 'build'); + + grunt.loadNpmTasks('grunt-env'); +}; diff --git a/README.md b/README.md index 669dd5f..db589e8 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# play-dashboard-frontend \ No newline at end of file +## like-dashboard diff --git a/app/404.html b/app/404.html new file mode 100644 index 0000000..fdace4a --- /dev/null +++ b/app/404.html @@ -0,0 +1,157 @@ + + + + + Page Not Found :( + + + +
+

Not found :(

+

Sorry, but the page you were trying to view does not exist.

+

It looks like this was the result of either:

+ + + +
+ + diff --git a/app/images/favicon.ico b/app/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..05a67e8b1fe2a5551f28a223099ebbbe7ed359dd GIT binary patch literal 5876 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 + + + + + + + + + Play玩具控 - Dashboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + diff --git a/app/less/draft.less b/app/less/draft.less new file mode 100644 index 0000000..593824c --- /dev/null +++ b/app/less/draft.less @@ -0,0 +1,223 @@ +.edit-section { + padding-top: 10px; + padding-bottom: 10px; +} + +.edit-section .insert-window { + position: relative;; + left: 20%; + bottom: 200px; + background-color: #fff; + border: 1px solid #ddd; + width: 60%; + min-height: 200px; + z-index: 1000; + + -webkit-box-shadow: 0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); + -moz-box-shadow: 0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); + box-shadow: 0 10px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); + + .close { + cursor:pointer; + } + + .video-code { + width: 100%; + height: auto; + } + + .modal-body { + max-height: 400px; + overflow: auto; + float: left; + } +} + +.edit-section { + .gallery-image { + float: left; + margin-right: 10px; + margin-bottom: 10px; + img { + width: 100px; + height: 100px; + object-fit: cover; + border: 2px solid #fff; + } + img:hover { + border: 2px solid #40E837; + } + } + .dropzone { + border-width: 2px; + border-color: black; + border-style: dashed; + border-radius: 4px; + font-size: 12px; + font-weight: bold; + padding: 15px; + width: 100px; + height: 100px; + font-size: + transition: all 0.5s; + } + .cover-img { + width: auto; + height: 100px; + object-fit: cover; + border: 2px solid #fff; + } +} + + +.RichEditor-root { + background: #fff; + border: 1px solid #ddd; + font-family: 'Georgia', serif; + font-size: 14px; + padding: 15px; +} + +.RichEditor-editor { + cursor: text; + font-size: 16px; +} + +.DraftEditor-root { + border-bottom: 1px solid #ddd; + padding-bottom: 15px; + margin-bottom: 10px; +} + +.RichEditor-editor .public-DraftEditorPlaceholder-root, +.RichEditor-editor .public-DraftEditor-content { + margin: 0 -15px -15px; + padding: 15px; +} + +.RichEditor-editor .public-DraftEditor-content { + min-height: 100px; +} + +.RichEditor-hidePlaceholder .public-DraftEditorPlaceholder-root { + display: none; +} + +.RichEditor-editor .RichEditor-blockquote { + border-left: 5px solid #eee; + color: #666; + font-family: 'Hoefler Text', 'Georgia', serif; + font-style: italic; + margin: 16px 0; + padding: 10px 20px; +} + +.RichEditor-editor .public-DraftStyleDefault-pre { + background-color: rgba(0, 0, 0, 0.05); + font-family: 'Inconsolata', 'Menlo', 'Consolas', monospace; + font-size: 16px; + padding: 20px; +} + +.RichEditor-controls { + font-family: 'Helvetica', sans-serif; + font-size: 14px; + margin-bottom: 5px; + user-select: none; + display: inline-block; +} + +.RichEditor-controls-btn { + font-size: 14px; + margin-bottom: 5px; + user-select: none; + display: inline-block; + margin-left: 5px; + margin-right: 5px; + cursor: pointer; +} + +.RichEditor-styleButton { + color: #999; + cursor: pointer; + margin-right: 4px; + display: inline-block; + border: 1px solid #fff; + border-radius: 3px; + width: 30px; + height: 30px; + text-align: center; + line-height: 30px; +} + +.RichEditor-styleButton::before { + line-height: 30px; +} + +.RichEditor-activeButton { + color: #5890ff; + border: 1px solid #5890ff; +} + +// +.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:rgba(255,255,255,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;z-index:0}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4} + + +// +.title-input { + background-color: #fff; + border: 1px solid #ccc; + overflow: hidden; + padding-left: 5px; + padding-top: 5px; + width: 100%; + line-height: 30px; + font-size: 20px; + font-weight: 300; +} + +// tags-input +.react-tagsinput { + background-color: #fff; + border: 1px solid #ccc; + overflow: hidden; + padding-left: 5px; + padding-top: 5px; +} + +.react-tagsinput-tag { + background-color: #cde69c; + border-radius: 2px; + border: 1px solid #a5d24a; + color: #638421; + display: inline-block; + font-family: sans-serif; + font-size: 13px; + font-weight: 400; + margin-bottom: 5px; + margin-right: 5px; + padding: 5px; +} + +.react-tagsinput-remove { + cursor: pointer; + font-weight: bold; +} + +.react-tagsinput-tag a::before { + content: " x"; +} + +.react-tagsinput-input { + background: transparent; + border: 0; + color: #777; + font-family: sans-serif; + font-size: 13px; + font-weight: 400; + margin-bottom: 6px; + margin-top: 1px; + outline: none; + padding: 5px; + width: 80px; +} diff --git a/app/less/main.less b/app/less/main.less new file mode 100644 index 0000000..143bf00 --- /dev/null +++ b/app/less/main.less @@ -0,0 +1,495 @@ +body { + background: #fafafa; + font-family: system, -apple-system, ".SFNSDisplay-Regular", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #333; +} + +html, body { + height: 100%; +} + +.content-wrapper { + background-color: #fafafa; +} + +.fluid-container { + .row { + margin-left: 0; + margin-right: 0; + } +} + +.main { + padding-top: 80px; +} + +.footer { + bottom: 0; + margin-top: 20px; + width: 100%; + height: 60px; + background-color: #f5f5f5; +} + +.wrap { + min-height: 100%; + height: auto; + margin: 0 auto -60px; +} + +.wrap > .container { + padding: 70px 15px 20px; +} + +.col { + padding-right:5px; + padding-left:5px; +} + +.footer { + height: 60px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + padding-top: 20px; +} + +.jumbotron { + text-align: center; + background-color: transparent; +} + +.jumbotron .btn { + font-size: 21px; + padding: 14px 24px; +} + +.not-set { + color: #c55; + font-style: italic; +} + +// New version +////////////// + +// panel ... +.no-padding { + padding: 0; +} + +.no-top-padding { + padding-top: 0; + padding-bottom: 0; +} + +.panel-video { + position:absolute; + height:100%; + width:100%; + overflow: hidden; +} + +video { + width: 100% !important; + height: auto !important; +} + +.panel-photos-wrapper { + width: 100%; + height: 0; + padding-bottom: 100%; + overflow: hidden; +} +.panel-photos-big { + object-fit: cover; + max-height: 300px; + width: 100%; +} +.panel-photos-small { + object-fit: cover; + max-height: 100px; + padding: 2px 2px 2px 0; +} +.panel-photos div { + width: 12.5%; + height: 0; + padding-bottom: 12.5%; + overflow: hidden; + display: inline; +} +.panel-photos img { + object-fit: cover; + width: 100% !important; + height: auto !important; + display: inline; +} +// panel end... + +.toy-item .products-list .product-img img { + width: 100px; + height: 100px; + object-fit: cover; + object-position: 0px 0px; +} + +.toy-item .products-list .product-info { + margin-left: 110px; +} + +.products-list .product-title { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.toy-item .products-list .product-title { + white-space: nowrap; + text-overflow: ellipsis; + word-break: break-all; + overflow: hidden; + line-height: 1.1em; + height: 2.2em; +} + +.label { + font-size: 100% !important; + a { + color: #fff; + cursor: pointer; + } + a:visited { + color: #fff; + } + i { + cursor: pointer; + } +} + +.tag-info { + color: #999; + font-size: 12px; +} + +.box-footer a { + color: #333; +} + +.label-margin { + margin: 3px; + display: inline-block; +} + +.pl-form { + margin: 10px 50px; +} + +.ql-toolbar-container { + border-bottom: 1px solid #ccc; + padding: 5px 12px; +} + +.alloyeditor-container { + padding: 10px; + margin: 10px; +} + +////////////// + + +/* add sorting icons to gridview sort links */ +a.asc:after, a.desc:after { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + padding-left: 5px; +} + +a.asc:after { + content: /*"\e113"*/ "\e151"; +} + +a.desc:after { + content: /*"\e114"*/ "\e152"; +} + +.sort-numerical a.asc:after { + content: "\e153"; +} + +.sort-numerical a.desc:after { + content: "\e154"; +} + +.sort-ordinal a.asc:after { + content: "\e155"; +} + +.sort-ordinal a.desc:after { + content: "\e156"; +} + +.grid-view th { + white-space: nowrap; +} + +.hint-block { + display: block; + margin-top: 5px; + color: #999; +} + +.error-summary { + color: #a94442; + background: #fdf7f7; + border-left: 3px solid #eed3d7; + padding: 10px 20px; + margin: 0 0 15px 0; +} + +.table > tbody > tr > td { + vertical-align: middle; +} + +.post-panel { + + .post-heading { + padding:0; + background-color: #fdfdfd; + } + + .post-heading>a { + display: block; + padding: 0 10px; + clear: both; + font-weight: 400; + line-height: 1.42857143; + color: #333; + white-space: nowrap + } + + .post-heading>a:focus,.post-heading>a:hover { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; + } + +} + +.post-caption { + padding: 5px; + .post-caption-btn { + // margin-right: 2px; + } +} + +.post-image { + position: relative; + /*padding: 2px;*/ + img { + width: 100% !important; + display: block !important; + } +} + +.image-modal { + max-width: 100%; +} + +.media, .media-body { + overflow: hidden; + zoom: 1; +} + +.media .media-object { + margin: 5px 0 5px 0; +} + +.media .post-user-info { + padding: 10px 5px 10px 0; + width: 60%; + .block { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin: 0; + } + .text-muted { + } +} + +.thumb { + display: inline-block; +} + +.post-summary { + padding: 0 0 15px 15px; +} + +.user-profile { + display: inline-block; + color: #979898; + vertical-align: middle; + padding: 0 0 0 10px; +} + +.user-profile h2 { + margin-top: 5px; + margin-bottom: 0px; +} + +img.img-corona { + -webkit-box-shadow: 0 0 0 4px rgba(221,221,221,.3); + -moz-box-shadow: 0 0 0 4px rgba(221,221,221,.3); + box-shadow: 0 0 0 4px rgba(221,221,221,.3); +} + +.user-info { + +} + +.publish-btn { + padding-top: 28px; +} + +.empty { + padding:15px; +} + +.post-pagination { + padding-right:15px; +} + +.post-image .thumb-pane { + position: absolute; + bottom: 40px; + width: 100%; + opacity: 0.6; + background-color: #000; + + .post-mark-li { + cursor: pointer; + } + .liked { + background-color: #ff442c; + border-radius: 2px; + } +} + +.post-panel:hover .thumb-pane { + opacity: 0.8; +} + +.thumb-pane ul { + list-style: none; + padding: 0; +} + +.thumb-pane ul li { + float: left; + padding: 3px; + margin: 5px; + color: #fff; + font-size: 14px; + font-weight: normal; +} + +.thumbnail-text p { + margin: 0; +} + +.post-info { + display: inline-block; + color: #979898; + vertical-align: middle; + padding: 0 0 0 10px; +} + +.post-info .glyphicon { + font-size: 18px; +} + +.load-more-btn { + text-align: center; + margin: auto; + width: 350px; + border: 1px solid #dddddd; + padding: 20px 40px; + cursor: pointer; +} + +.tag-panel { + .panel-heading { + padding: 5px; + } + .panel-body { + padding: 0; + } +} + +.tag-add-btn { + padding: 5px; + margin-left: 5px; +} + +.tag-btn { + margin: 5px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 5px; +} + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +.nav-tabs-custom .nav-tabs { + margin: 0; + border-bottom-color: #f4f4f4; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.nav-tabs-custom .nav-tabs>li:first-of-type { + margin-left: 0; +} +.nav-tabs-custom .nav-tabs>li.active { + border-top-color: #3c8dbc; +} +.nav-tabs-custom .nav-tabs>li { + border-top: 3px solid transparent; + margin-bottom: -2px; + margin-right: 5px; +} +.nav-tabs-custom .nav-tabs>li:first-of-type.active>a { + border-left-color: transparent; +} +.nav-tabs-custom .nav-tabs>li.active>a { + border-top-color: transparent; + border-left-color: #f4f4f4; + border-right-color: #f4f4f4; +} +.nav-tabs-custom .nav-tabs>li.active>a, .nav-tabs-custom .nav-tabs>li.active:hover>a { + background-color: #fff; + color: #444; +} +.nav-tabs-custom .nav-tabs>li>a, .nav-tabs-custom .nav-tabs>li>a:hover { + background: transparent; + margin: 0; +} +.nav-tabs-custom .nav-tabs>li>a { + color: #444; + border-radius: 0; +} +.nav-tabs-custom .nav-tabs>li:not(.active)>a { + border: none; +} + + +@import "draft.less"; diff --git a/app/robots.txt b/app/robots.txt new file mode 100644 index 0000000..9417495 --- /dev/null +++ b/app/robots.txt @@ -0,0 +1,3 @@ +# robotstxt.org + +User-agent: * diff --git a/app/scripts/actions/article.js b/app/scripts/actions/article.js new file mode 100644 index 0000000..5aebede --- /dev/null +++ b/app/scripts/actions/article.js @@ -0,0 +1,5 @@ +export const TOGGLE_PUBLISH = 'TOGGLE_PUBLISH' + +export function toggleArticlePublish(id) { + return { type: TOGGLE_PUBLISH, id } +} diff --git a/app/scripts/actions/articleactions.js b/app/scripts/actions/articleactions.js new file mode 100644 index 0000000..0006720 --- /dev/null +++ b/app/scripts/actions/articleactions.js @@ -0,0 +1,8 @@ +var Reflux = require('reflux'); + +var ArticleActions = Reflux.createActions([ + 'fetchArticleList', + 'toggleArticlePublish' +]); + +module.exports = ArticleActions; diff --git a/app/scripts/actions/banuseractions.js b/app/scripts/actions/banuseractions.js new file mode 100644 index 0000000..8cba5c0 --- /dev/null +++ b/app/scripts/actions/banuseractions.js @@ -0,0 +1,9 @@ +var Reflux = require('reflux'); + +var BanUserActions = Reflux.createActions([ + 'fetchBannedUsers', + 'banUser', + 'removeBanUser' +]); + +module.exports = BanUserActions; diff --git a/app/scripts/actions/explorebanneractions.js b/app/scripts/actions/explorebanneractions.js new file mode 100644 index 0000000..f536b3c --- /dev/null +++ b/app/scripts/actions/explorebanneractions.js @@ -0,0 +1,9 @@ +var Reflux = require('reflux'); + +var BannerActions = Reflux.createActions([ + 'fetchBannerList', + 'addBanner', + 'deleteBanner' +]); + +module.exports = BannerActions; diff --git a/app/scripts/actions/explorethemeactions.js b/app/scripts/actions/explorethemeactions.js new file mode 100644 index 0000000..6ee0f88 --- /dev/null +++ b/app/scripts/actions/explorethemeactions.js @@ -0,0 +1,9 @@ +var Reflux = require('reflux'); + +var ThemeActions = Reflux.createActions([ + 'fetchThemeList', + 'addTheme', + 'deleteTheme' +]); + +module.exports = ThemeActions; diff --git a/app/scripts/actions/feedbackactions.js b/app/scripts/actions/feedbackactions.js new file mode 100644 index 0000000..71f50f6 --- /dev/null +++ b/app/scripts/actions/feedbackactions.js @@ -0,0 +1,8 @@ +var Reflux = require('reflux'); + +var FeedbackActions = Reflux.createActions([ + 'fetchFeedbackList', + 'deleteFeedback' +]); + +module.exports = FeedbackActions; diff --git a/app/scripts/actions/judgepostactions.js b/app/scripts/actions/judgepostactions.js new file mode 100644 index 0000000..6cea81a --- /dev/null +++ b/app/scripts/actions/judgepostactions.js @@ -0,0 +1,8 @@ +var Reflux = require('reflux'); + +var JudgePostActions = Reflux.createActions([ + 'fetchPostList', + 'judge' +]); + +module.exports = JudgePostActions; diff --git a/app/scripts/actions/postactions.js b/app/scripts/actions/postactions.js new file mode 100644 index 0000000..54eadd7 --- /dev/null +++ b/app/scripts/actions/postactions.js @@ -0,0 +1,20 @@ +var Reflux = require('reflux'); + +var PostActions = Reflux.createActions([ + 'fetchPostList', + 'deletePost', + 'toggleRecommendPost', + 'toggleBlockPost', + 'toggleR18Post', + 'setPostClassification', + 'removePostClassification', + 'addSku', + 'addTag', + 'removeTag', + 'deleteMark', + 'addMark', + 'like', + 'unlike' +]); + +module.exports = PostActions; diff --git a/app/scripts/actions/recommendhomeactions.js b/app/scripts/actions/recommendhomeactions.js new file mode 100644 index 0000000..ba07a59 --- /dev/null +++ b/app/scripts/actions/recommendhomeactions.js @@ -0,0 +1,8 @@ +var Reflux = require('reflux'); + +var HomeAdActions = Reflux.createActions([ + 'fetchHomeAdList', + 'deleteHomeAd' +]); + +module.exports = HomeAdActions; diff --git a/app/scripts/actions/reportactions.js b/app/scripts/actions/reportactions.js new file mode 100644 index 0000000..fe1663d --- /dev/null +++ b/app/scripts/actions/reportactions.js @@ -0,0 +1,10 @@ +var Reflux = require('reflux'); + +var ReportActions = Reflux.createActions([ + 'fetchReportList', + 'deleteReport', + 'hidePost', + 'deletePost' +]); + +module.exports = ReportActions; diff --git a/app/scripts/actions/skuactions.js b/app/scripts/actions/skuactions.js new file mode 100644 index 0000000..2bdc0a5 --- /dev/null +++ b/app/scripts/actions/skuactions.js @@ -0,0 +1,12 @@ +var Reflux = require('reflux'); + +var SkuActions = Reflux.createActions([ + 'fetchSkus', + 'deleteSku', + 'toggleR18', + 'toggleRecommend', + 'addSku', + 'recommendToy' +]); + +module.exports = SkuActions; diff --git a/app/scripts/actions/statsactions.js b/app/scripts/actions/statsactions.js new file mode 100644 index 0000000..ee5c2e0 --- /dev/null +++ b/app/scripts/actions/statsactions.js @@ -0,0 +1,7 @@ +var Reflux = require('reflux'); + +var StatsActions = Reflux.createActions([ + 'updateStats' +]); + +module.exports = StatsActions; diff --git a/app/scripts/actions/stickeractions.js b/app/scripts/actions/stickeractions.js new file mode 100644 index 0000000..812fc1f --- /dev/null +++ b/app/scripts/actions/stickeractions.js @@ -0,0 +1,13 @@ +var Reflux = require('reflux'); + +var StickerActions = Reflux.createActions([ + 'fetchStickers', + 'addStickerSet', + 'removeStickerSet', + 'updateCollection', + 'deleteSticker', + 'riseSticker', + 'riseStickerSet' +]); + +module.exports = StickerActions; diff --git a/app/scripts/actions/tagactions.js b/app/scripts/actions/tagactions.js new file mode 100644 index 0000000..6b6883b --- /dev/null +++ b/app/scripts/actions/tagactions.js @@ -0,0 +1,11 @@ +var Reflux = require('reflux'); + +var TagActions = Reflux.createActions([ + 'fetchTags', + 'setTagClassification', + 'removeTagClassification', + 'recommendTag', + 'deleteTag' +]); + +module.exports = TagActions; diff --git a/app/scripts/actions/tagclassactions.js b/app/scripts/actions/tagclassactions.js new file mode 100644 index 0000000..75f0012 --- /dev/null +++ b/app/scripts/actions/tagclassactions.js @@ -0,0 +1,7 @@ +var Reflux = require('reflux'); + +var TagClassActions = Reflux.createActions([ + 'fetchClassifications' +]); + +module.exports = TagClassActions; diff --git a/app/scripts/actions/useractions.js b/app/scripts/actions/useractions.js new file mode 100644 index 0000000..2d5769a --- /dev/null +++ b/app/scripts/actions/useractions.js @@ -0,0 +1,16 @@ +var Reflux = require('reflux'); + +var UserActions = Reflux.createActions([ + 'updateParams', + 'fetchUserList', + 'recommendUser', + 'toggleVerifyUser', + 'deletePost', + 'toggleRecommendPost', + 'toggleBlockPost', + 'deleteMark', + 'like', + 'unlike' +]); + +module.exports = UserActions; diff --git a/app/scripts/actions/userdetailactions.js b/app/scripts/actions/userdetailactions.js new file mode 100644 index 0000000..22fd493 --- /dev/null +++ b/app/scripts/actions/userdetailactions.js @@ -0,0 +1,13 @@ +var Reflux = require('reflux'); + +var UserDetailActions = Reflux.createActions([ + 'fetchUserDetailInfo', + 'fetchUserPosts', + 'updateUserId', + 'setActive', + 'updateUserInfo', + 'refreshUserCount', + 'changeForm' +]); + +module.exports = UserDetailActions; diff --git a/app/scripts/app.js b/app/scripts/app.js new file mode 100644 index 0000000..7d8c0df --- /dev/null +++ b/app/scripts/app.js @@ -0,0 +1,51 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Router, Route, IndexRoute, hashHistory } from 'react-router'; + +import Layout from './components/layout'; +import Home from './components/home'; +import RecommendHome from './components/recommendhome'; +import ExplorePage from './components/explorepage'; +import PostList from './components/postlist'; +import UserList from './components/userlist'; +import SkuList from './components/skulist'; +import UserDetail from './components/userdetail'; +import TagList from './components/taglist'; +import StickerList from './components/stickerlist'; +import ArticleList from './components/articlelist'; + +import EditTag from './components/edittag'; +import EditShortVideo from './components/editshortvideo'; +import EditSticker from './components/editsticker'; +import EditStickerSet from './components/editstickerset'; +import EditRecommend from './components/editrecommend'; +import EditSku from './components/editsku'; +import EditArticle from './components/editarticle'; + +import Test from './components/test'; + +ReactDOM.render(( + + + + + + + + + + + + + + + + + + + + + + + +), document.getElementById('app')); diff --git a/app/scripts/components/articlelist.jsx b/app/scripts/components/articlelist.jsx new file mode 100644 index 0000000..b153140 --- /dev/null +++ b/app/scripts/components/articlelist.jsx @@ -0,0 +1,56 @@ +import React from 'react' +import Reflux from 'reflux' +import {Link} from 'react-router' +import {Row, Button} from 'react-bootstrap' +import Moment from 'moment' +import ArticleStore from '../stores/articlestore' +import ArticleActions from '../actions/articleactions' + +var ArticleList = React.createClass({ + mixins: [Reflux.connect(ArticleStore, 'articles')], + getInitialState: function() { + return { query: '' }; + }, + fetchMoreArticles: function() { + ArticleActions.fetchArticleList(this.state.query); + }, + render: function() { + if (this.state.articles) { + return ( +
+
+ +
+
+ + + {this.state.articles.map(function(article) { + return ( + + + + + + + + + + + ); + },this)} + + +
{article.title}{article.author}{article.category}{article.tags.join()}{article.counts.views} views{Moment.unix(article.created / 1000).fromNow()}预览
+
+ +
Load More
+
+
+ ) + } else { + return (); + } + } +}); + +module.exports = ArticleList; diff --git a/app/scripts/components/bannedusers.jsx b/app/scripts/components/bannedusers.jsx new file mode 100644 index 0000000..d332e33 --- /dev/null +++ b/app/scripts/components/bannedusers.jsx @@ -0,0 +1,56 @@ +var React = require('react/addons'); +var Reflux = require('reflux'); +var Row = require('react-bootstrap').Row; +var Input = require('react-bootstrap').Input; +var BanUserStore = require('../stores/banuserstore'); +var BanUserActions = require('../actions/banuseractions'); +var Moment = require('moment'); + +var BanUserList = React.createClass({ + mixins: [Reflux.connect(BanUserStore, 'banusers'), React.addons.LinkedStateMixin], + getInitialState: function() { + return { banid: '' }; + }, + banUser: function() { + BanUserActions.banUser(this.state.banid); + }, + removeBanUser: function(id) { + BanUserActions.removeBanUser(id); + }, + render: function() { + if (this.state.banusers) { + return ( +
+ +
Total {this.state.banusers.length} users are banned
+
+
+ + + + +
+
+
+
+ + + + {this.state.banusers.map(function (user) { + return ( + + ); + }, this)} + + +
#IDAvatarNicknameLikesAction
{user.id}{user.nickname}{user.likes}Remove
+
+
+ ); + } else { + return (); + } + } +}); + +module.exports = BanUserList; diff --git a/app/scripts/components/brandlist.jsx b/app/scripts/components/brandlist.jsx new file mode 100644 index 0000000..50e73a1 --- /dev/null +++ b/app/scripts/components/brandlist.jsx @@ -0,0 +1,62 @@ +var React = require('react'); +var Reflux = require('reflux'); +var Row = require('react-bootstrap').Row; +var Col = require('react-bootstrap').Col; +var Link = require('react-router').Link; +var Button = require('react-bootstrap').Button; +var ButtonToolbar = require('react-bootstrap').ButtonToolbar; +var BrandStore = require('../stores/brandstore'); +var BrandActions = require('../actions/brandactions'); + +var Brands = React.createClass({ + mixins: [Reflux.connect(BrandStore, 'brandlist')], + fetchMoreBrands: function() { + BrandActions.fetchBrandList(); + }, + togglePromoteBrand: function(id) { + BrandActions.togglePromoteBrand(id); + }, + deleteBrand: function(id) { + if (confirm('Delete this brand?')) { + BrandActions.deleteBrand(id); + } + }, + render: function() { + if (this.state.brandlist) { + return ( +
+

+ +

+ {this.state.brandlist.map(function (brand) { + var promoteBtn = Promote; + if (brand.isPromoted) { + promoteBtn = Promoted; + } + return ( + + + {brand.name} + {brand.description} + + + Edit + {promoteBtn} + Delete + + + + ); + }.bind(this))} + +
Load More
+
+
+ ); + } else { + return (
); + } + } +}); + +module.exports = Brands; diff --git a/app/scripts/components/editarticle.jsx b/app/scripts/components/editarticle.jsx new file mode 100644 index 0000000..dc4b331 --- /dev/null +++ b/app/scripts/components/editarticle.jsx @@ -0,0 +1,439 @@ +import React from 'react'; +import {AtomicBlockUtils, Editor, EditorState, Entity, RichUtils, convertToRaw} from 'draft-js'; +import stateToHTML from '../utils/stateToHTML'; +import Dropzone from 'react-dropzone'; +import TagsInput from 'react-tagsinput'; +import Request from 'superagent'; +import $ from 'jquery'; +import CDN from '../widgets/cdn'; + + +function isFunction(fn) { + let getType = {}; + return fn && getType.toString.call(fn) === '[object Function]'; +} + +function makeid() { + let text = ''; + const possible = 'abcdefghijklmnopqrstuvwxyz0123456789'; + for( let i=0; i < 10; i++ ) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} + +function getBlockStyle(block) { + switch (block.getType()) { + case 'blockquote': return 'RichEditor-blockquote'; + case 'unstyled': return 'paragraph'; + default: return null; + } +} + +class StyleButton extends React.Component { + constructor() { + super(); + this.onToggle = (e) => { + e.preventDefault(); + this.props.onToggle(this.props.style); + }; + } + + render() { + let className = 'RichEditor-styleButton'; + if (this.props.active) { + className += ' RichEditor-activeButton'; + } + if (this.props.icon) { + className += (' ' + this.props.icon); + } + + return ( + + {this.props.icon ? null : this.props.label} + + ); + } +} + +const BLOCK_TYPES = [ + {label: 'H1', style: 'header-one', icon: ''}, + {label: 'H2', style: 'header-two', icon: ''}, + {label: 'Blockquote', style: 'blockquote', icon: 'fa fa-quote-left'}, + {label: 'UL', style: 'unordered-list-item', icon: 'fa fa-list-ul'}, + {label: 'OL', style: 'ordered-list-item', icon: 'fa fa-list-ol'}, +]; + +const BlockStyleControls = (props) => { + const {editorState} = props; + const selection = editorState.getSelection(); + const blockType = editorState + .getCurrentContent() + .getBlockForKey(selection.getStartKey()) + .getType(); + + return ( +
+ {BLOCK_TYPES.map((type) => + + )} +
+ ); +}; + + +const INLINE_STYLES = [ + {label: 'Bold', style: 'BOLD', icon: 'fa fa-bold'}, + {label: 'Italic', style: 'ITALIC', icon: 'fa fa-italic'}, + {label: 'Underline', style: 'UNDERLINE', icon: 'fa fa-underline'}, +]; + +const InlineStyleControls = (props) => { + var currentStyle = props.editorState.getCurrentInlineStyle(); + return ( +
+ {INLINE_STYLES.map(type => + + )} +
+ ); +}; + +const Media = (props) => { + const entity = Entity.get(props.block.getEntityAt(0)); + const {src, html} = entity.getData(); + const type = entity.getType(); + let media; + if (type === 'image') { + media = (
+ +
); + } else if (type === 'video') { + media =
; + } + return media; +}; + +export default class ArticleEditor extends React.Component { + constructor(props) { + super(props); + this.state = { + editorState: EditorState.createEmpty(), + showImageWindow: false, + showVideoWindow: false, + videoCode: '', + title: '', + cover: '', + tags: [], + category: '评测', + authorId: '', + gallery:[], + uploadUrl: 'http://upload.qiniu.com/', + }; + + this.focus = () => this.refs.editor.focus(); + this.onChange = (editorState) => this.setState({editorState}); + + this.handleKeyCommand = (command) => this._handleKeyCommand(command); + this.toggleBlockType = (type) => this._toggleBlockType(type); + this.toggleInlineStyle = (style) => this._toggleInlineStyle(style); + this.toggleImageWindow = () => this.setState({showImageWindow: !this.state.showImageWindow}); + this.toggleVideoWindow = () => this.setState({showVideoWindow: !this.state.showVideoWindow}); + this.handleTagsChange = (tags) => this.setState({tags}); + this.handleTitleChange = (e) => this.setState({title: e.target.value}); + this.handleCategoryChange = (e) => this.setState({category: e.target.value}); + this.handleAuthorChange = (e) => this.setState({authorId: e.target.value}); + + this.onDrop = (files) => this._onDrop(files); + this.onDropCover = (files) => this._onDropCover(files); + this.onChangeVideoCode = (e) => this.setState({videoCode: e.target.value}); + this.addImage = (imageKey) => this._addImage(imageKey); + this.addVideo = () => this._addVideo(); + this.publish = () => this._publish(); + this.blockRenderer = (block) => { + if (block.getType() === 'atomic') { + return { + component: Media, + editable: false, + }; + } + return null; + }; + } + _handleKeyCommand(command) { + const {editorState} = this.state; + const newState = RichUtils.handleKeyCommand(editorState, command); + if (newState) { + this.onChange(newState); + return true; + } + return false; + } + _toggleBlockType(blockType) { + this.onChange( + RichUtils.toggleBlockType( + this.state.editorState, + blockType + ) + ); + } + _toggleInlineStyle(inlineStyle) { + this.onChange( + RichUtils.toggleInlineStyle( + this.state.editorState, + inlineStyle + ) + ); + } + _addImage(imageKey) { + const src = CDN.show(imageKey) + '?articlestyle'; + const entityKey = Entity.create('image', 'IMMUTABLE', {src}); + this.onChange(AtomicBlockUtils.insertAtomicBlock( + this.state.editorState, + entityKey, + ' ' + )); + this.setState({showImageWindow: false}); + } + _addVideo() { + if (this.state.videoCode.trim().length === 0) { + return false; + } + const html = this.state.videoCode.trim().replace("width=510", "width=640"); + const entityKey = Entity.create('video', 'IMMUTABLE', {html}); + this.onChange(AtomicBlockUtils.insertAtomicBlock( + this.state.editorState, + entityKey, + ' ' + )); + this.setState({videoCode:'', showVideoWindow: false}); + } + _onDrop(files) { + let _this = this; + $.ajax({ + url : '/api/uptoken', + type : 'GET', + success : function(data) { + let uploadToken = data.uptoken; + let progresses = {}; + files.forEach((file)=> { + // genereate upload key + let d = new Date(); + let id = makeid(); + let uploadKey = 'article/photo/' + Math.round(d.getTime()/1000) + '_' + id + '.' + file.name.split('.').pop(); + // file.preview = URL.createObjectURL(file); + file.onprogress = function(e) { + progresses[file.preview] = e.percent; + _this.setState({progresses: progresses}); + }; + file.request = _this.uploadToQiniu(file, uploadKey, uploadToken); + }); + } + }); + } + uploadToQiniu(file, uploadKey, uploadToken) { + if (!file || file.size === 0) { + return null; + } + let _this = this; + const req = Request + .post(this.state.uploadUrl) + .field('key', uploadKey) + .field('token', uploadToken) + .field('x:filename', file.name) + .field('x:size', file.size) + .attach('file', file, file.name) + .set('Accept', 'application/json'); + + if (isFunction(file.onprogress)) { + req.on('progress', file.onprogress); + } + req.end(function(err, res){ + let value = _this.state.gallery.slice(); + value.push(uploadKey); + _this.setState({gallery: value}); + }); + return req; + } + _onDropCover(files) { + let _this = this; + Request.get('/api/uptoken').end(function(err, res){ + let uploadToken = res.body.uptoken; + const file = files[0]; + const img = new Image(); + img.onload = () => { + console.log(img.width + ' ' + img.height); + const id = makeid(); + const date = new Date(); + const uploadKey = 'article/cover/' + Math.round(date.getTime()/1000) + '_w_' + img.width + '_h_' + img.height + '_' + id + '.' + file.name.split('.').pop(); + Request + .post(_this.state.uploadUrl) + .field('key', uploadKey) + .field('token', uploadToken) + .field('x:filename', file.name) + .field('x:size', file.size) + .attach('file', file, file.name) + .set('Accept', 'application/json') + .end(function(err, res){ + _this.setState({cover: uploadKey}); + }); + }; + img.src = file.preview; + }); + } + _publish() { + let _this = this; + + let title = this.state.title; + let cover = this.state.cover; + let tags = this.state.tags; + let category = this.state.category; + let authorId = this.state.authorId; + let gallery = this.state.gallery; + let html = stateToHTML(this.state.editorState.getCurrentContent()).replace('

', ''); + let raw = convertToRaw(this.state.editorState.getCurrentContent()); + + let data = {title, cover, tags, category, authorId, gallery, html, raw}; + console.log(data); + Request + .post('/api/article') + .send(data) + .end(function(err, res){ + console.log(err); + console.log(res); + console.log((err || !res.ok)); + if (err || !res.ok) { + alert('保存失败!'); + } else { + alert('保存成功.'); + location.href = `/article/${res.text}/preview`; + } + }); + } + render() { + const {editorState} = this.state; + + // If the user changes block type before entering any text, we can + // either style the placeholder or hide it. Let's just hide it now. + let className = 'RichEditor-editor'; + let contentState = editorState.getCurrentContent(); + if (!contentState.hasText()) { + if (contentState.getBlockMap().first().getType() !== 'unstyled') { + className += ' RichEditor-hidePlaceholder'; + } + } + return ( +
+ +
+
文章标题
+ +
+
+
+
+ +
+ + + 添加图片 + 添加视频 +
+ {this.state.showImageWindow ? +
+
+ +

选择图片

+
+
+ + 点击此处选取图片或将文件拖入该区域 + + {this.state.gallery.map(function (imageKey) { + return ( +
+ this.addImage(imageKey)}/> +
+ ); + }, this)} +
+
+ : null + } + {this.state.showVideoWindow ? +
+
+ +

粘贴视频通用代码

+
+
+