├── console ├── controllers │ └── .gitkeep ├── models │ └── .gitkeep ├── config │ ├── bootstrap.php │ ├── .gitignore │ ├── params.php │ └── main.php ├── runtime │ └── .gitignore └── migrations │ ├── m170720_162821_change_2_comment_columns.php │ ├── m170716_100457_add_count_column_to_tag_table.php │ ├── m170716_100548_add_type_column_to_relationship_table.php │ ├── m170718_163915_add_comment_count_column_to_article_table.php │ ├── m170501_154420_add_token_key_column_to_user_table.php │ ├── m171030_154143_create_setting_table.php │ ├── m170703_160943_create_relationship_table.php │ ├── m170630_150033_create_tag_table.php │ ├── m130524_201442_init.php │ ├── m170720_142117_add_type_column_in_relationship_table_primary_key.php │ ├── m170503_160551_create_article_table.php │ └── m170718_162607_create_comment_table.php ├── backend ├── models │ └── .gitkeep ├── tests │ ├── _data │ │ ├── .gitignore │ │ └── login_data.php │ ├── _support │ │ ├── .gitignore │ │ ├── UnitTester.php │ │ └── FunctionalTester.php │ ├── _output │ │ └── .gitignore │ ├── unit.suite.yml │ ├── functional.suite.yml │ ├── functional │ │ ├── _bootstrap.php │ │ └── LoginCest.php │ ├── unit │ │ └── _bootstrap.php │ └── _bootstrap.php ├── config │ ├── bootstrap.php │ ├── .gitignore │ ├── params.php │ ├── test.php │ └── main.php ├── runtime │ └── .gitignore ├── web │ ├── assets │ │ └── .gitignore │ ├── .gitignore │ ├── robots.txt │ ├── favicon.ico │ ├── dist │ │ ├── static │ │ │ ├── fonts │ │ │ │ ├── fontello.eot │ │ │ │ ├── fontello.ttf │ │ │ │ ├── KaTeX_Main-Bold.eot │ │ │ │ ├── KaTeX_Main-Bold.ttf │ │ │ │ ├── KaTeX_AMS-Regular.eot │ │ │ │ ├── KaTeX_AMS-Regular.ttf │ │ │ │ ├── KaTeX_AMS-Regular.woff │ │ │ │ ├── KaTeX_Fraktur-Bold.eot │ │ │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ │ │ ├── KaTeX_Main-Bold.woff │ │ │ │ ├── KaTeX_Main-Bold.woff2 │ │ │ │ ├── KaTeX_Main-Italic.eot │ │ │ │ ├── KaTeX_Main-Italic.ttf │ │ │ │ ├── KaTeX_Main-Italic.woff │ │ │ │ ├── KaTeX_Main-Regular.eot │ │ │ │ ├── KaTeX_Main-Regular.ttf │ │ │ │ ├── KaTeX_Math-Italic.eot │ │ │ │ ├── KaTeX_Math-Italic.ttf │ │ │ │ ├── KaTeX_Math-Italic.woff │ │ │ │ ├── KaTeX_AMS-Regular.woff2 │ │ │ │ ├── KaTeX_Fraktur-Bold.woff │ │ │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ │ │ ├── KaTeX_Main-Italic.woff2 │ │ │ │ ├── KaTeX_Main-Regular.woff │ │ │ │ ├── KaTeX_Main-Regular.woff2 │ │ │ │ ├── KaTeX_Math-Italic.woff2 │ │ │ │ ├── KaTeX_Script-Regular.eot │ │ │ │ ├── KaTeX_Script-Regular.ttf │ │ │ │ ├── KaTeX_Size1-Regular.eot │ │ │ │ ├── KaTeX_Size1-Regular.ttf │ │ │ │ ├── KaTeX_Size2-Regular.eot │ │ │ │ ├── KaTeX_Size2-Regular.ttf │ │ │ │ ├── KaTeX_Size4-Regular.eot │ │ │ │ ├── KaTeX_Size4-Regular.ttf │ │ │ │ ├── KaTeX_Caligraphic-Bold.eot │ │ │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ │ │ ├── KaTeX_Fraktur-Regular.eot │ │ │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ │ │ ├── KaTeX_Fraktur-Regular.woff │ │ │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ │ │ ├── KaTeX_SansSerif-Regular.eot │ │ │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ │ │ ├── KaTeX_Script-Regular.woff │ │ │ │ ├── KaTeX_Script-Regular.woff2 │ │ │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ │ │ ├── KaTeX_Caligraphic-Regular.eot │ │ │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ │ │ ├── KaTeX_SansSerif-Regular.woff │ │ │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ │ │ ├── KaTeX_Typewriter-Regular.eot │ │ │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ │ │ ├── KaTeX_Typewriter-Regular.woff │ │ │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ │ │ └── KaTeX_Typewriter-Regular.woff2 │ │ │ └── js │ │ │ │ └── vendor.js │ │ └── views │ │ │ └── admin.html │ └── .htaccess ├── codeception.yml ├── controllers │ ├── UserController.php │ ├── BackendController.php │ ├── TagController.php │ ├── SettingController.php │ ├── InstallController.php │ └── ArticleController.php ├── assets │ └── AppAsset.php └── views │ ├── site │ ├── error.php │ └── login.php │ ├── layouts │ └── main.php │ └── install │ └── index.php ├── frontend ├── config │ ├── bootstrap.php │ ├── .gitignore │ ├── params.php │ ├── test.php │ └── main.php ├── runtime │ └── .gitignore ├── tests │ ├── _support │ │ ├── .gitignore │ │ ├── UnitTester.php │ │ └── FunctionalTester.php │ ├── _output │ │ └── .gitignore │ ├── functional.suite.yml │ ├── unit.suite.yml │ ├── acceptance.suite.yml.example │ ├── functional │ │ ├── AboutCest.php │ │ ├── _bootstrap.php │ │ ├── HomeCest.php │ │ ├── LoginCest.php │ │ ├── SignupCest.php │ │ └── ContactCest.php │ ├── acceptance │ │ ├── _bootstrap.php │ │ └── HomeCest.php │ ├── unit │ │ ├── _bootstrap.php │ │ └── models │ │ │ ├── ContactFormTest.php │ │ │ ├── ResetPasswordFormTest.php │ │ │ ├── SignupFormTest.php │ │ │ └── PasswordResetRequestFormTest.php │ ├── _bootstrap.php │ └── _data │ │ ├── login_data.php │ │ └── user.php ├── web │ ├── assets │ │ └── .gitignore │ ├── robots.txt │ ├── .gitignore │ ├── favicon.ico │ ├── images │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ ├── iconfont │ │ ├── MaterialIcons-Regular.eot │ │ ├── MaterialIcons-Regular.ttf │ │ ├── MaterialIcons-Regular.woff │ │ ├── MaterialIcons-Regular.woff2 │ │ ├── README.md │ │ └── material-icons.css │ ├── .htaccess │ ├── js │ │ ├── main.js │ │ └── article.js │ └── css │ │ ├── catalog.css │ │ ├── site.css │ │ └── article.css ├── codeception.yml ├── assets │ ├── HighlightAsset.php │ ├── JquerySerializeJson.php │ ├── MaterializeAsset.php │ └── AppAsset.php ├── controllers │ ├── CatalogController.php │ ├── SiteController.php │ ├── TagController.php │ ├── FrontController.php │ ├── ArchiveController.php │ ├── ArticleController.php │ └── CommentController.php ├── views │ ├── tag │ │ ├── all-tags.php │ │ └── index.php │ ├── site │ │ ├── about.php │ │ ├── index.php │ │ ├── error.php │ │ ├── resetPassword.php │ │ ├── requestPasswordResetToken.php │ │ ├── signup.php │ │ ├── login.php │ │ └── contact.php │ ├── catalog │ │ └── index.php │ ├── layouts │ │ └── main.php │ ├── archive │ │ └── list.php │ └── article │ │ └── list.php └── models │ ├── ContactForm.php │ ├── SignupForm.php │ ├── ResetPasswordForm.php │ └── PasswordResetRequestForm.php ├── common ├── tests │ ├── _support │ │ ├── .gitignore │ │ └── UnitTester.php │ ├── _output │ │ └── .gitignore │ ├── unit.suite.yml │ ├── _bootstrap.php │ ├── _data │ │ └── user.php │ └── unit │ │ └── models │ │ └── LoginFormTest.php ├── config │ ├── .gitignore │ ├── params.php │ ├── main.php │ ├── bootstrap.php │ └── test.php ├── fixtures │ └── User.php ├── mail │ ├── passwordResetToken-text.php │ ├── layouts │ │ ├── text.php │ │ └── html.php │ └── passwordResetToken-html.php ├── codeception.yml └── models │ ├── SignupForm.php │ ├── Relationship.php │ └── LoginForm.php ├── .bowerrc ├── vagrant ├── config │ ├── .gitignore │ └── vagrant-local.example.yml ├── nginx │ ├── log │ │ └── .gitignore │ └── app.conf └── provision │ ├── always-as-root.sh │ ├── once-as-vagrant.sh │ └── once-as-root.sh ├── rabc.xlsx ├── environments ├── dev │ ├── backend │ │ ├── config │ │ │ ├── params-local.php │ │ │ ├── test-local.php │ │ │ └── main-local.php │ │ └── web │ │ │ ├── index.php │ │ │ └── index-test.php │ ├── common │ │ └── config │ │ │ ├── params-local.php │ │ │ ├── test-local.php │ │ │ └── main-local.php │ ├── console │ │ └── config │ │ │ ├── params-local.php │ │ │ └── main-local.php │ ├── frontend │ │ ├── config │ │ │ ├── params-local.php │ │ │ ├── test-local.php │ │ │ └── main-local.php │ │ └── web │ │ │ ├── index.php │ │ │ └── index-test.php │ ├── yii_test.bat │ ├── yii_test │ └── yii ├── prod │ ├── common │ │ └── config │ │ │ ├── params-local.php │ │ │ └── main-local.php │ ├── console │ │ └── config │ │ │ ├── main-local.php │ │ │ └── params-local.php │ ├── backend │ │ ├── config │ │ │ ├── params-local.php │ │ │ └── main-local.php │ │ └── web │ │ │ └── index.php │ ├── frontend │ │ ├── config │ │ │ ├── params-local.php │ │ │ └── main-local.php │ │ └── web │ │ │ └── index.php │ └── yii └── index.php ├── schedule.png ├── schedule.xmind ├── vue2 ├── config │ ├── prod.env.js │ ├── test.env.js │ ├── dev.env.js │ └── modules.js ├── src │ ├── assets │ │ ├── css │ │ │ └── common.css │ │ ├── font │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.ttf │ │ │ └── iconfont.woff │ │ └── js │ │ │ ├── Lib.js │ │ │ ├── vueFilter.js │ │ │ └── conf.js │ ├── views │ │ ├── home │ │ │ ├── home.html │ │ │ ├── App.vue │ │ │ └── home.js │ │ └── admin │ │ │ ├── admin.html │ │ │ └── App.vue │ ├── pages │ │ ├── AdminHome.vue │ │ ├── Test.vue │ │ └── Post.vue │ ├── components │ │ ├── ~tpl.vue │ │ ├── adminFooter.vue │ │ ├── HbHead.vue │ │ ├── uploadFile.vue │ │ └── adminHead.vue │ ├── store │ │ └── store.js │ └── router │ │ └── admin.js ├── .gitignore ├── test │ ├── unit │ │ ├── .eslintrc │ │ ├── specs │ │ │ └── Hello.spec.js │ │ ├── index.js │ │ └── karma.conf.js │ └── e2e │ │ ├── specs │ │ └── test.js │ │ ├── custom-assertions │ │ └── elementCount.js │ │ ├── runner.js │ │ └── nightwatch.conf.js ├── .postcssrc.js ├── .babelrc ├── build │ ├── dev-client.js │ ├── vue-loader.conf.js │ ├── webpack.test.conf.js │ ├── modules.target.conf.js │ ├── build.js │ ├── build-module.js │ ├── check-versions.js │ ├── webpack.dev.conf.js │ └── webpack.base.conf.js ├── index.html └── .vscode │ └── launch.json ├── codeception.yml ├── bower.json ├── init.bat ├── yii.bat ├── .gitignore ├── composer.json └── LICENSE.md /console/controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/models/.gitkeep: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /backend/tests/_data/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /console/models/.gitkeep: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /backend/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 'admin@example.com', 4 | ]; 5 | -------------------------------------------------------------------------------- /backend/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/favicon.ico -------------------------------------------------------------------------------- /console/config/params.php: -------------------------------------------------------------------------------- 1 | 'admin@example.com', 4 | ]; 5 | -------------------------------------------------------------------------------- /frontend/config/params.php: -------------------------------------------------------------------------------- 1 | 'admin@example.com', 4 | ]; 5 | -------------------------------------------------------------------------------- /frontend/web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/favicon.ico -------------------------------------------------------------------------------- /frontend/web/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/images/1.jpg -------------------------------------------------------------------------------- /frontend/web/images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/images/2.jpg -------------------------------------------------------------------------------- /frontend/web/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/images/3.jpg -------------------------------------------------------------------------------- /frontend/web/images/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/images/4.jpg -------------------------------------------------------------------------------- /backend/tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | class_name: FunctionalTester 2 | modules: 3 | enabled: 4 | - Yii2 5 | -------------------------------------------------------------------------------- /vue2/src/assets/css/common.css: -------------------------------------------------------------------------------- 1 | .mu-text-field .mu-text-field-hint{ 2 | width: 50%; /* 修复 text 组件 placeholder 超宽的问题 */ 3 | } -------------------------------------------------------------------------------- /vue2/src/assets/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/vue2/src/assets/font/iconfont.eot -------------------------------------------------------------------------------- /vue2/src/assets/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/vue2/src/assets/font/iconfont.ttf -------------------------------------------------------------------------------- /vue2/src/assets/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/vue2/src/assets/font/iconfont.woff -------------------------------------------------------------------------------- /vagrant/nginx/log/.gitignore: -------------------------------------------------------------------------------- 1 | # nginx logs 2 | backend-access.log 3 | backend-error.log 4 | frontend-access.log 5 | frontend-error.log -------------------------------------------------------------------------------- /vue2/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | yarn-error.log 4 | test/unit/coverage 5 | test/e2e/reports 6 | selenium-debug.log -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/fontello.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/fontello.ttf -------------------------------------------------------------------------------- /frontend/tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | class_name: FunctionalTester 2 | modules: 3 | enabled: 4 | - Filesystem 5 | - Yii2 6 | -------------------------------------------------------------------------------- /frontend/web/iconfont/MaterialIcons-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/iconfont/MaterialIcons-Regular.eot -------------------------------------------------------------------------------- /frontend/web/iconfont/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/iconfont/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Bold.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Bold.ttf -------------------------------------------------------------------------------- /frontend/web/iconfont/MaterialIcons-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/iconfont/MaterialIcons-Regular.woff -------------------------------------------------------------------------------- /frontend/web/iconfont/MaterialIcons-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/frontend/web/iconfont/MaterialIcons-Regular.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_AMS-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_AMS-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_AMS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_AMS-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_AMS-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_AMS-Regular.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Bold.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Bold.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Italic.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Italic.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Italic.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Math-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Math-Italic.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Math-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Math-Italic.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Math-Italic.woff -------------------------------------------------------------------------------- /common/tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | class_name: UnitTester 2 | bootstrap: false 3 | modules: 4 | enabled: 5 | - Yii2: 6 | part: fixtures 7 | -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_AMS-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_AMS-Regular.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Bold.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Italic.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Regular.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Main-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Main-Regular.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Math-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Math-Italic.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Script-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Script-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Script-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Script-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Size1-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Size1-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Size1-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Size1-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Size2-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Size2-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Size2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Size2-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Size4-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Size4-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Size4-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Size4-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Fraktur-Regular.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Script-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Script-Regular.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Script-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Script-Regular.woff2 -------------------------------------------------------------------------------- /vue2/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Bold.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_SansSerif-Regular.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.eot -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.ttf -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.woff -------------------------------------------------------------------------------- /frontend/tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | class_name: UnitTester 2 | modules: 3 | enabled: 4 | - Yii2: 5 | part: [orm, email, fixtures] 6 | - Asserts 7 | -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.woff -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Caligraphic-Regular.woff2 -------------------------------------------------------------------------------- /backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzdxy/vue2-in-yii2/HEAD/backend/web/dist/static/fonts/KaTeX_Typewriter-Regular.woff2 -------------------------------------------------------------------------------- /environments/dev/console/config/main-local.php: -------------------------------------------------------------------------------- 1 | ['gii'], 4 | 'modules' => [ 5 | 'gii' => 'yii\gii\Module', 6 | ], 7 | ]; 8 | -------------------------------------------------------------------------------- /vue2/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /vue2/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /common/config/params.php: -------------------------------------------------------------------------------- 1 | 'admin@example.com', 4 | 'supportEmail' => 'support@example.com', 5 | 'user.passwordResetTokenExpire' => 3600, 6 | ]; 7 | -------------------------------------------------------------------------------- /common/fixtures/User.php: -------------------------------------------------------------------------------- 1 | 'app-backend-tests', 4 | 'components' => [ 5 | 'assetManager' => [ 6 | 'basePath' => __DIR__ . '/../web/assets', 7 | ], 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /frontend/config/test.php: -------------------------------------------------------------------------------- 1 | 'app-frontend-tests', 4 | 'components' => [ 5 | 'assetManager' => [ 6 | 'basePath' => __DIR__ . '/../web/assets', 7 | ], 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /vue2/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /common/config/main.php: -------------------------------------------------------------------------------- 1 | dirname(dirname(__DIR__)) . '/vendor', 4 | 'components' => [ 5 | 'cache' => [ 6 | 'class' => 'yii\caching\FileCache', 7 | ], 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /frontend/tests/acceptance.suite.yml.example: -------------------------------------------------------------------------------- 1 | class_name: AcceptanceTester 2 | modules: 3 | enabled: 4 | - WebDriver: 5 | url: http://localhost:8080 6 | browser: firefox 7 | - Yii2: 8 | part: init 9 | -------------------------------------------------------------------------------- /backend/web/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | 3 | # if a directory or a file exists, use it directly 4 | RewriteCond %{REQUEST_FILENAME} !-f 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | 7 | # otherwise forward it to index.php 8 | RewriteRule . index.php -------------------------------------------------------------------------------- /frontend/web/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | 3 | # if a directory or a file exists, use it directly 4 | RewriteCond %{REQUEST_FILENAME} !-f 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | 7 | # otherwise forward it to index.php 8 | RewriteRule . index.php -------------------------------------------------------------------------------- /common/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | 'app-common-tests', 4 | 'basePath' => dirname(__DIR__), 5 | 'components' => [ 6 | 'user' => [ 7 | 'class' => 'yii\web\User', 8 | 'identityClass' => 'common\models\User', 9 | ], 10 | ], 11 | ]; 12 | -------------------------------------------------------------------------------- /vue2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vue2/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /frontend/web/js/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by zchi on 2017/7/18. 3 | */ 4 | $(function () { 5 | initNavBar(); 6 | parallax(); 7 | 8 | }); 9 | 10 | function initNavBar() { 11 | $(".button-collapse").sideNav(); 12 | } 13 | 14 | 15 | function parallax() { 16 | $('.parallax').parallax(); 17 | } -------------------------------------------------------------------------------- /environments/dev/backend/config/test-local.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'request' => [ 5 | // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 6 | 'cookieValidationKey' => '', 7 | ], 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /environments/dev/frontend/config/test-local.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'request' => [ 5 | // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 6 | 'cookieValidationKey' => '', 7 | ], 8 | ], 9 | ]; 10 | -------------------------------------------------------------------------------- /frontend/tests/functional/AboutCest.php: -------------------------------------------------------------------------------- 1 | amOnRoute('site/about'); 11 | $I->see('About', 'h1'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /vue2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vux2 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /vagrant/provision/always-as-root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #== Bash helpers == 4 | 5 | function info { 6 | echo " " 7 | echo "--> $1" 8 | echo " " 9 | } 10 | 11 | #== Provision script == 12 | 13 | info "Provision-script user: `whoami`" 14 | 15 | info "Restart web-stack" 16 | service php5-fpm restart 17 | service nginx restart 18 | service mysql restart -------------------------------------------------------------------------------- /vue2/src/views/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Home 7 | 8 | 9 |
10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /common/mail/passwordResetToken-text.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); 7 | ?> 8 | Hello username ?>, 9 | 10 | Follow the link below to reset your password: 11 | 12 | 13 | -------------------------------------------------------------------------------- /frontend/web/iconfont/README.md: -------------------------------------------------------------------------------- 1 | The recommended way to use the Material Icons font is by linking to the web font hosted on Google Fonts: 2 | 3 | ```html 4 | 6 | ``` 7 | 8 | Read more in our full usage guide: 9 | http://google.github.io/material-design-icons/#icon-font-for-the-web 10 | -------------------------------------------------------------------------------- /common/codeception.yml: -------------------------------------------------------------------------------- 1 | namespace: common\tests 2 | actor: Tester 3 | paths: 4 | tests: tests 5 | log: tests/_output 6 | data: tests/_data 7 | helpers: tests/_support 8 | settings: 9 | bootstrap: _bootstrap.php 10 | colors: true 11 | memory_limit: 1024M 12 | modules: 13 | config: 14 | Yii2: 15 | configFile: 'config/test-local.php' 16 | -------------------------------------------------------------------------------- /backend/codeception.yml: -------------------------------------------------------------------------------- 1 | namespace: backend\tests 2 | actor: Tester 3 | paths: 4 | tests: tests 5 | log: tests/_output 6 | data: tests/_data 7 | helpers: tests/_support 8 | settings: 9 | bootstrap: _bootstrap.php 10 | colors: true 11 | memory_limit: 1024M 12 | modules: 13 | config: 14 | Yii2: 15 | configFile: 'config/test-local.php' 16 | -------------------------------------------------------------------------------- /frontend/codeception.yml: -------------------------------------------------------------------------------- 1 | namespace: frontend\tests 2 | actor: Tester 3 | paths: 4 | tests: tests 5 | log: tests/_output 6 | data: tests/_data 7 | helpers: tests/_support 8 | settings: 9 | bootstrap: _bootstrap.php 10 | colors: true 11 | memory_limit: 1024M 12 | modules: 13 | config: 14 | Yii2: 15 | configFile: 'config/test-local.php' 16 | -------------------------------------------------------------------------------- /vue2/src/pages/AdminHome.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /backend/controllers/UserController.php: -------------------------------------------------------------------------------- 1 | getAllList(); 14 | return json_encode(['result'=>0,'list'=>$List]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /common/tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /environments/dev/common/config/test-local.php: -------------------------------------------------------------------------------- 1 | [ 8 | 'db' => [ 9 | 'dsn' => 'mysql:host=localhost;dbname=yii2advanced_test', 10 | ] 11 | ], 12 | ] 13 | ); 14 | -------------------------------------------------------------------------------- /common/mail/layouts/text.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | beginPage() ?> 11 | beginBody() ?> 12 | 13 | endBody() ?> 14 | endPage() ?> 15 | -------------------------------------------------------------------------------- /vue2/src/assets/js/Lib.js: -------------------------------------------------------------------------------- 1 | require('assets/css/common.css'); 2 | 3 | //注册时,vux必须放在 import Vue from 'vue'; 之前,否侧打包的体积非常大,估计是vux OR vue 抽风了 4 | 5 | import Vue from 'vue'; 6 | 7 | import C from './conf'; 8 | import M from './common'; 9 | 10 | import vueFilter from './vueFilter'; 11 | 12 | //解决click点击300毫秒延时问题 13 | import FastClick from 'fastclick'; 14 | FastClick.attach(document.body); 15 | 16 | export default{ 17 | M,C 18 | } -------------------------------------------------------------------------------- /backend/tests/functional/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'davert']); 9 | * ``` 10 | * 11 | * In Cests 12 | * 13 | * ```php 14 | * \Codeception\Util\Fixtures::get('user1'); 15 | * ``` 16 | */ -------------------------------------------------------------------------------- /backend/tests/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'davert']); 9 | * ``` 10 | * 11 | * In Tests 12 | * 13 | * ```php 14 | * \Codeception\Util\Fixtures::get('user1'); 15 | * ``` 16 | */ 17 | -------------------------------------------------------------------------------- /frontend/tests/acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'davert']); 9 | * ``` 10 | * 11 | * In Cept 12 | * 13 | * ```php 14 | * \Codeception\Util\Fixtures::get('user1'); 15 | * ``` 16 | */ -------------------------------------------------------------------------------- /frontend/tests/functional/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'davert']); 9 | * ``` 10 | * 11 | * In Cests 12 | * 13 | * ```php 14 | * \Codeception\Util\Fixtures::get('user1'); 15 | * ``` 16 | */ -------------------------------------------------------------------------------- /frontend/tests/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'davert']); 9 | * ``` 10 | * 11 | * In Tests 12 | * 13 | * ```php 14 | * \Codeception\Util\Fixtures::get('user1'); 15 | * ``` 16 | */ 17 | -------------------------------------------------------------------------------- /frontend/tests/functional/HomeCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(\Yii::$app->homeUrl); 12 | $I->see('My Company'); 13 | $I->seeLink('About'); 14 | $I->click('About'); 15 | $I->see('This is the About page.'); 16 | } 17 | } -------------------------------------------------------------------------------- /frontend/assets/HighlightAsset.php: -------------------------------------------------------------------------------- 1 | render('index',[ 14 | 'list'=>Article::getHead(null) 15 | ]); 16 | } 17 | 18 | public function actionArticle(){ 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vue2/src/views/admin/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Admin 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/assets/JquerySerializeJson.php: -------------------------------------------------------------------------------- 1 | = 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /backend/assets/AppAsset.php: -------------------------------------------------------------------------------- 1 | 'erau', 5 | 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', 6 | // password_0 7 | 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', 8 | 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', 9 | 'created_at' => '1392559490', 10 | 'updated_at' => '1392559490', 11 | 'email' => 'sfriesen@jenkins.info', 12 | ], 13 | ]; 14 | -------------------------------------------------------------------------------- /environments/prod/common/config/main-local.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'db' => [ 5 | 'class' => 'yii\db\Connection', 6 | 'dsn' => 'mysql:host=localhost;dbname=yii2advanced', 7 | 'username' => 'root', 8 | 'password' => '', 9 | 'charset' => 'utf8', 10 | ], 11 | 'mailer' => [ 12 | 'class' => 'yii\swiftmailer\Mailer', 13 | 'viewPath' => '@common/mail', 14 | ], 15 | ], 16 | ]; 17 | -------------------------------------------------------------------------------- /vue2/src/assets/js/conf.js: -------------------------------------------------------------------------------- 1 | 2 | import store from 'store'; 3 | 4 | var Rxports = { 5 | appname:"云收银", 6 | url_host:window.location.host, 7 | background:'#FBF9FE', 8 | } 9 | 10 | export default Rxports; 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /frontend/tests/_data/login_data.php: -------------------------------------------------------------------------------- 1 | 'erau', 5 | 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', 6 | // password_0 7 | 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', 8 | 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', 9 | 'created_at' => '1392559490', 10 | 'updated_at' => '1392559490', 11 | 'email' => 'sfriesen@jenkins.info', 12 | ], 13 | ]; 14 | -------------------------------------------------------------------------------- /frontend/assets/MaterializeAsset.php: -------------------------------------------------------------------------------- 1 | urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); 8 | ?> 9 |
10 |

Hello username) ?>,

11 | 12 |

Follow the link below to reset your password:

13 | 14 |

15 |
16 | -------------------------------------------------------------------------------- /common/tests/_data/user.php: -------------------------------------------------------------------------------- 1 | 'bayer.hudson', 6 | 'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR', 7 | //password_0 8 | 'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO', 9 | 'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317', 10 | 'created_at' => '1402312317', 11 | 'updated_at' => '1402312317', 12 | 'email' => 'nicole.paucek@schultz.info', 13 | ], 14 | ]; 15 | -------------------------------------------------------------------------------- /frontend/views/tag/all-tags.php: -------------------------------------------------------------------------------- 1 | title = 'Tags'; 6 | ?> 7 |
8 |
9 |

All Tags

10 |
11 | $tag){?> 12 | count?>name?> 13 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue2-in-yii2", 3 | "homepage": "https://github.com/wzdxy/vue2-in-yii2", 4 | "authors": [ 5 | "zc " 6 | ], 7 | "description": "", 8 | "main": "", 9 | "license": "MIT", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "vendor/bower", 16 | "test", 17 | "tests" 18 | ], 19 | "dependencies": { 20 | "materialize": "^0.98.2", 21 | "highlightjs": "^9.12.0", 22 | "jquery.serializeJSON": "^2.8.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /frontend/tests/acceptance/HomeCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(Url::toRoute('/site/index')); 13 | $I->see('My Company'); 14 | 15 | $I->seeLink('About'); 16 | $I->click('About'); 17 | $I->wait(2); // wait for page to be opened 18 | 19 | $I->see('This is the About page.'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /console/migrations/m170720_162821_change_2_comment_columns.php: -------------------------------------------------------------------------------- 1 | renameColumn('comment','create_at','created_at'); 10 | $this->renameColumn('comment','update_at','updated_at'); 11 | } 12 | 13 | public function down() 14 | { 15 | $this->renameColumn('comment','created_at','create_at'); 16 | $this->renameColumn('comment','updated_at','update_at'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /console/migrations/m170716_100457_add_count_column_to_tag_table.php: -------------------------------------------------------------------------------- 1 | addColumn('tag', 'count', $this->integer()->defaultValue(0)); 16 | } 17 | 18 | /** 19 | * @inheritdoc 20 | */ 21 | public function down() 22 | { 23 | $this->dropColumn('tag', 'count'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /frontend/views/site/about.php: -------------------------------------------------------------------------------- 1 | title = 'About'; 8 | $this->params['breadcrumbs'][] = $this->title; 9 | ?> 10 | 11 |
12 |

title) ?>

13 |

source code wzdxy/vue2-in-yii2

14 |

e-mail zh.ch.0915@gmail.com

15 |
16 | -------------------------------------------------------------------------------- /vue2/src/views/home/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | 19 | 29 | -------------------------------------------------------------------------------- /init.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line init script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%init" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /frontend/views/site/index.php: -------------------------------------------------------------------------------- 1 | title = $settings['index-title']; 6 | ?> 7 |
8 |
9 |
10 |
11 |
12 |

13 | All Article 14 |

15 | All Tag 16 |
17 |
18 | 21 | -------------------------------------------------------------------------------- /vagrant/config/vagrant-local.example.yml: -------------------------------------------------------------------------------- 1 | # Your personal GitHub token 2 | github_token: 3 | # Read more: https://github.com/blog/1509-personal-api-tokens 4 | # You can generate it here: https://github.com/settings/tokens 5 | 6 | # Guest OS timezone 7 | timezone: Europe/London 8 | 9 | # Are we need check box updates for every 'vagrant up'? 10 | box_check_update: false 11 | 12 | # Virtual machine name 13 | machine_name: y2aa 14 | 15 | # Virtual machine IP 16 | ip: 192.168.83.137 17 | 18 | # Virtual machine CPU cores number 19 | cpus: 1 20 | 21 | # Virtual machine RAM 22 | memory: 512 23 | -------------------------------------------------------------------------------- /console/migrations/m170716_100548_add_type_column_to_relationship_table.php: -------------------------------------------------------------------------------- 1 | addColumn('relationship', 'type', $this->text()->notNull()); 16 | } 17 | 18 | /** 19 | * @inheritdoc 20 | */ 21 | public function down() 22 | { 23 | $this->dropColumn('relationship', 'type'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /environments/dev/yii_test.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii_test" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /frontend/assets/AppAsset.php: -------------------------------------------------------------------------------- 1 | a{ 5 | color:#7ce; 6 | } 7 | .article-content>a:hover{ 8 | color:#8df; 9 | } 10 | 11 | .article-archive .article-count{ 12 | color: #929292; 13 | } 14 | 15 | .article-archive{ 16 | width: 96%; 17 | margin: 0 2%; 18 | } 19 | 20 | .article-time{ 21 | color: #999; 22 | } 23 | @media screen and (min-device-width: 992px) { 24 | .article-archive{ 25 | margin: 0; 26 | position: absolute; 27 | top:100px; 28 | right:20px; 29 | width:20%; 30 | min-width: 220px; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /console/migrations/m170718_163915_add_comment_count_column_to_article_table.php: -------------------------------------------------------------------------------- 1 | addColumn('article', 'comment_count', $this->integer()->defaultValue(0)); 16 | } 17 | 18 | /** 19 | * @inheritdoc 20 | */ 21 | public function down() 22 | { 23 | $this->dropColumn('article', 'comment_count'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vue2/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /backend/views/site/error.php: -------------------------------------------------------------------------------- 1 | title = $name; 11 | ?> 12 |
13 | 14 |

title) ?>

15 | 16 |
17 | 18 |
19 | 20 |

21 | The above error occurred while the Web server was processing your request. 22 |

23 |

24 | Please contact us if you think this is a server error. Thank you. 25 |

26 | 27 |
28 | -------------------------------------------------------------------------------- /frontend/views/site/error.php: -------------------------------------------------------------------------------- 1 | title = $name; 11 | ?> 12 |
13 | 14 |

title) ?>

15 | 16 |
17 | 18 |
19 | 20 |

21 | The above error occurred while the Web server was processing your request. 22 |

23 |

24 | Please contact us if you think this is a server error. Thank you. 25 |

26 | 27 |
28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # yii console commands 2 | /yii 3 | /yii_test 4 | /yii_test.bat 5 | 6 | # phpstorm project files 7 | .idea 8 | 9 | # netbeans project files 10 | nbproject 11 | 12 | # zend studio for eclipse project files 13 | .buildpath 14 | .project 15 | .settings 16 | 17 | # windows thumbnail cache 18 | Thumbs.db 19 | 20 | # composer vendor dir 21 | /vendor 22 | 23 | # composer itself is not needed 24 | composer.phar 25 | 26 | # Mac DS_Store Files 27 | .DS_Store 28 | 29 | # phpunit itself is not needed 30 | phpunit.phar 31 | # local phpunit config 32 | /phpunit.xml 33 | 34 | # vagrant runtime 35 | /.vagrant 36 | 37 | # vue dist files 38 | frontend/web/dist/ 39 | #backend/web/dist/ -------------------------------------------------------------------------------- /vue2/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /vue2/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /environments/dev/backend/config/main-local.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'request' => [ 6 | // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 7 | 'cookieValidationKey' => '', 8 | ], 9 | ], 10 | ]; 11 | 12 | if (!YII_ENV_TEST) { 13 | // configuration adjustments for 'dev' environment 14 | $config['bootstrap'][] = 'debug'; 15 | $config['modules']['debug'] = [ 16 | 'class' => 'yii\debug\Module', 17 | ]; 18 | 19 | $config['bootstrap'][] = 'gii'; 20 | $config['modules']['gii'] = [ 21 | 'class' => 'yii\gii\Module', 22 | ]; 23 | } 24 | 25 | return $config; 26 | -------------------------------------------------------------------------------- /environments/dev/frontend/config/main-local.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'request' => [ 6 | // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 7 | 'cookieValidationKey' => '', 8 | ], 9 | ], 10 | ]; 11 | 12 | if (!YII_ENV_TEST) { 13 | // configuration adjustments for 'dev' environment 14 | $config['bootstrap'][] = 'debug'; 15 | $config['modules']['debug'] = [ 16 | 'class' => 'yii\debug\Module', 17 | ]; 18 | 19 | $config['bootstrap'][] = 'gii'; 20 | $config['modules']['gii'] = [ 21 | 'class' => 'yii\gii\Module', 22 | ]; 23 | } 24 | 25 | return $config; 26 | -------------------------------------------------------------------------------- /environments/dev/backend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 18 | -------------------------------------------------------------------------------- /environments/dev/frontend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 18 | -------------------------------------------------------------------------------- /environments/prod/backend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 18 | -------------------------------------------------------------------------------- /environments/dev/backend/web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 19 | -------------------------------------------------------------------------------- /environments/dev/frontend/web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 19 | -------------------------------------------------------------------------------- /environments/prod/frontend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 18 | -------------------------------------------------------------------------------- /common/tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | [ 4 | 'db' => [ 5 | 'class' => 'yii\db\Connection', 6 | 'dsn' => 'mysql:host=localhost;dbname=yii2advanced', 7 | 'username' => 'root', 8 | 'password' => '', 9 | 'charset' => 'utf8', 10 | ], 11 | 'mailer' => [ 12 | 'class' => 'yii\swiftmailer\Mailer', 13 | 'viewPath' => '@common/mail', 14 | // send all mails to a file by default. You have to set 15 | // 'useFileTransport' to false and configure a transport 16 | // for the mailer to send real emails. 17 | 'useFileTransport' => true, 18 | ], 19 | ], 20 | ]; 21 | -------------------------------------------------------------------------------- /frontend/views/tag/index.php: -------------------------------------------------------------------------------- 1 | title = '目录'; 6 | ?> 7 |
8 |
9 |

name:''?>

10 |
11 | 0) {?> 12 | $article){ 13 | echo ''.$article->author_name.''.$article->title.''; 14 | }?> 15 | 16 | 沒有內容 17 | 18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /vue2/src/components/~tpl.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 53 | 54 | 58 | -------------------------------------------------------------------------------- /backend/tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Admin 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /frontend/tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | request->headers->get('authorization'); 14 | if(isset($token_key)){ 15 | $modal=new User(); 16 | if($modal->validateToken($token_key)){ 17 | return true; 18 | }else{ 19 | return json_encode(['result'=>-1,'message'=>'用户验证失败']); 20 | } 21 | }else{ 22 | return json_encode(['result'=>-1,'message'=>'用户验证失败']); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /frontend/controllers/SiteController.php: -------------------------------------------------------------------------------- 1 | where(['name' => ['index-head', 'index-title']])->asArray()->all(); 18 | $settings=[]; 19 | foreach ($settingsQuery as $idx=>$item){ 20 | $settings[$item['name']]=$item['value']; 21 | } 22 | return $this->render('index',[ 23 | 'settings'=>$settings 24 | ]); 25 | } 26 | 27 | public function actionAbout() 28 | { 29 | return $this->render('about'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/mail/layouts/html.php: -------------------------------------------------------------------------------- 1 | 8 | beginPage() ?> 9 | 10 | 11 | 12 | 13 | <?= Html::encode($this->title) ?> 14 | head() ?> 15 | 16 | 17 | beginBody() ?> 18 | 19 | endBody() ?> 20 | 21 | 22 | endPage() ?> 23 | -------------------------------------------------------------------------------- /vue2/src/views/home/home.js: -------------------------------------------------------------------------------- 1 | 2 | // import Vue from 'vue' 3 | // import App from './listApp' 4 | 5 | // new Vue({ 6 | // render: h => h(App) 7 | // }).$mount('#app') 8 | 9 | // The Vue build version to load with the `import` command 10 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 11 | import Vue from 'vue' 12 | import App from './App' 13 | 14 | 15 | Vue.config.productionTip = false 16 | 17 | Vue.component('component-example',{ 18 | template:'
This is A custom component!
{{msg}}
', 19 | data:function(){ 20 | return{msg:'我是一个组件,我来自main.js中的定义',style:{border:"1px solid",margin:"2px"}} 21 | } 22 | }) 23 | 24 | 25 | 26 | /* eslint-disable no-new */ 27 | window.vm=new Vue({ 28 | el: '#app', 29 | template: '', 30 | components: { App } 31 | }) 32 | -------------------------------------------------------------------------------- /frontend/controllers/TagController.php: -------------------------------------------------------------------------------- 1 | request->get('url'); 16 | if(!isset($url)){ 17 | $tagQuery=Tag::getAllList(); 18 | return $this->render('all-tags',[ 19 | 'tags'=>$tagQuery 20 | ]); 21 | }else { 22 | $tag=Tag::findOne(['url'=>$url]); 23 | $articleQuery=Article::getByTagUrl($url); 24 | return $this->render('index',[ 25 | 'articles'=>$articleQuery, 26 | 'tag'=>$tag 27 | ]); 28 | } 29 | 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /vue2/src/components/adminFooter.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /vue2/src/pages/Test.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /console/migrations/m170501_154420_add_token_key_column_to_user_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 17 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 18 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 19 | } 20 | $this->addColumn('user', 'token_key', $this->text()); 21 | } 22 | 23 | /** 24 | * @inheritdoc 25 | */ 26 | public function down() 27 | { 28 | $this->dropColumn('user', 'token_key'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vue2/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /environments/dev/yii_test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 27 | exit($exitCode); 28 | -------------------------------------------------------------------------------- /frontend/controllers/FrontController.php: -------------------------------------------------------------------------------- 1 | [ 25 | 'class' => 'yii\web\ErrorAction', 26 | ], 27 | 'captcha' => [ 28 | 'class' => 'yii\captcha\CaptchaAction', 29 | 'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, 30 | ], 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /frontend/tests/_data/user.php: -------------------------------------------------------------------------------- 1 | 'okirlin', 6 | 'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv', 7 | 'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi', 8 | 'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(), 9 | 'created_at' => '1391885313', 10 | 'updated_at' => '1391885313', 11 | 'email' => 'brady.renner@rutherford.com', 12 | ], 13 | [ 14 | 'username' => 'troy.becker', 15 | 'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp', 16 | 'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2', 17 | 'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_' . time(), 18 | 'created_at' => '1391885313', 19 | 'updated_at' => '1391885313', 20 | 'email' => 'nicolas.dianna@hotmail.com', 21 | 'status' => '0', 22 | ], 23 | ]; 24 | -------------------------------------------------------------------------------- /vue2/build/modules.target.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | 3 | var modules = { 4 | "home": { 5 | index: '../../frontend/web/dist/index.html', 6 | assetsRoot: '../../frontend/web/dist', 7 | assetsSubDirectory: 'static', 8 | assetsPublicPath: '../../', 9 | }, 10 | "admin":{ 11 | index: '../../backend/web/dist/index.html', 12 | assetsRoot: '../../backend/web/dist', 13 | assetsSubDirectory: 'static', 14 | assetsPublicPath: '../../', 15 | } 16 | }; 17 | module.exports = { 18 | 19 | getModuleTarget: function (moduleName) { 20 | return { 21 | index: path.resolve(__dirname, modules[moduleName].index), 22 | assetsRoot: path.resolve(__dirname, modules[moduleName].assetsRoot), 23 | assetsSubDirectory: modules[moduleName].assetsSubDirectory, 24 | assetsPublicPath: modules[moduleName].assetsPublicPath, 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /backend/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 15 | beginPage() ?> 16 | 17 | 18 | 19 | 20 | 21 | 22 | <?= Html::encode($this->title) ?> 23 | head() ?> 24 | 25 | 26 | beginBody() ?> 27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 | endBody() ?> 35 | 36 | 37 | endPage() ?> 38 | -------------------------------------------------------------------------------- /frontend/web/css/site.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: Arial,sans-serif,Consolas,GillSans, Calibri, Trebuchet; 3 | } 4 | 5 | body { 6 | /*display: flex;*/ 7 | /*min-height: 100vh;*/ 8 | /*flex-direction: column;*/ 9 | /*overflow-x: hidden;*/ 10 | } 11 | 12 | main { 13 | /*flex: 1 0 auto;*/ 14 | } 15 | 16 | code{ 17 | font-family:Consolas, sans-serif; 18 | } 19 | 20 | .wrap{ 21 | position: relative; 22 | } 23 | 24 | /* PC 横屏 */ 25 | @media screen and (min-device-width: 992px) { 26 | body { 27 | max-height: 100vh; 28 | overflow: hidden; 29 | } 30 | .wrap{ 31 | height: calc(100vh - 65px); 32 | overflow-y: auto; 33 | } 34 | .wrap>.content-center{ 35 | width: 70%; 36 | margin: 0 auto; 37 | } 38 | nav .brand-logo{ 39 | padding:0 1rem; 40 | } 41 | } 42 | 43 | @media screen and (max-aspect-ratio: 1/1) { 44 | html{ 45 | /*height: 100vh;*/ 46 | } 47 | } -------------------------------------------------------------------------------- /console/config/main.php: -------------------------------------------------------------------------------- 1 | 'app-console', 11 | 'basePath' => dirname(__DIR__), 12 | 'bootstrap' => ['log'], 13 | 'controllerNamespace' => 'console\controllers', 14 | 'controllerMap' => [ 15 | 'fixture' => [ 16 | 'class' => 'yii\console\controllers\FixtureController', 17 | 'namespace' => 'common\fixtures', 18 | ], 19 | ], 20 | 'components' => [ 21 | 'log' => [ 22 | 'targets' => [ 23 | [ 24 | 'class' => 'yii\log\FileTarget', 25 | 'levels' => ['error', 'warning'], 26 | ], 27 | ], 28 | ], 29 | ], 30 | 'params' => $params, 31 | ]; 32 | -------------------------------------------------------------------------------- /frontend/tests/_support/FunctionalTester.php: -------------------------------------------------------------------------------- 1 | see($message, '.help-block'); 27 | } 28 | 29 | public function dontSeeValidationError($message) 30 | { 31 | $this->dontSee($message, '.help-block'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /environments/dev/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 28 | exit($exitCode); 29 | -------------------------------------------------------------------------------- /vue2/src/store/store.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Z on 2017/4/29. 3 | */ 4 | import Vue from 'vue' 5 | import Vuex from 'vuex' 6 | Vue.use(Vuex) 7 | export default new Vuex.Store({ 8 | state: { 9 | count: 0, 10 | user: { 11 | id: '', 12 | log:false 13 | }, 14 | mobileMenu:{ 15 | isOpen:false, 16 | isSlim:false 17 | } 18 | }, 19 | mutations: { 20 | login(state, user){ 21 | state.user = { 22 | id:user.id, 23 | log:true 24 | }; 25 | }, 26 | logout(state){ 27 | state.user = { 28 | id:'', 29 | log:false 30 | }; 31 | }, 32 | toggleNavSlim(state){ 33 | state.mobileMenu.isSlim=!state.mobileMenu.isSlim; 34 | }, 35 | toggleNavOpen(state){ 36 | state.mobileMenu.isOpen=!state.mobileMenu.isOpen; 37 | } 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /environments/prod/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 28 | exit($exitCode); 29 | -------------------------------------------------------------------------------- /frontend/controllers/ArchiveController.php: -------------------------------------------------------------------------------- 1 | request->get('month'); 14 | if(isset($month)){ 15 | $startTime=$month.'-01 00:00:00'; 16 | $endTime=$month.'-31 00:00:00'; 17 | return $this->render('list',[ 18 | 'list'=>Article::getHead(['and',['between','created_at',$startTime,$endTime],['status'=>0]]), 19 | 'archive'=>Article::getArchive(), 20 | 'month'=>$month 21 | ]); 22 | }else{ 23 | return $this->render('list',[ 24 | 'list'=>Article::getHead(['status'=>0]), 25 | 'archive'=>Article::getArchive(), 26 | 'month'=>'All' 27 | ]); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /frontend/views/site/resetPassword.php: -------------------------------------------------------------------------------- 1 | title = 'Reset password'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 |

title) ?>

15 | 16 |

Please choose your new password:

17 | 18 |
19 |
20 | 'reset-password-form']); ?> 21 | 22 | field($model, 'password')->passwordInput(['autofocus' => true]) ?> 23 | 24 |
25 | 'btn btn-primary']) ?> 26 |
27 | 28 | 29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /backend/tests/functional/LoginCest.php: -------------------------------------------------------------------------------- 1 | haveFixtures([ 16 | 'user' => [ 17 | 'class' => UserFixture::className(), 18 | 'dataFile' => codecept_data_dir() . 'login_data.php' 19 | ] 20 | ]); 21 | } 22 | /** 23 | * @param FunctionalTester $I 24 | */ 25 | public function loginUser(FunctionalTester $I) 26 | { 27 | $I->amOnPage('/site/login'); 28 | $I->fillField('Username', 'erau'); 29 | $I->fillField('Password', 'password_0'); 30 | $I->click('login-button'); 31 | 32 | $I->see('Logout (erau)', 'form button[type=submit]'); 33 | $I->dontSeeLink('Login'); 34 | $I->dontSeeLink('Signup'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /console/migrations/m171030_154143_create_setting_table.php: -------------------------------------------------------------------------------- 1 | createTable('setting', [ 16 | 'id' => $this->primaryKey(), 17 | 'user' => $this->integer(), 18 | 'name' => $this->string(), 19 | 'value' => $this->string(), 20 | ]); 21 | $this->batchInsert('setting', ['user', 'name', 'value'], [ 22 | [0, 'admin-domain', 'admin.zchi.me'], 23 | [0, 'front-domain', 'front.zchi.me'], 24 | [0, 'index-head', 'Welcome To ZCHI \'s Blog'], 25 | [0, 'index-title', 'ZCHI \'s Blog'] 26 | ]); 27 | } 28 | 29 | /** 30 | * @inheritdoc 31 | */ 32 | public function down() 33 | { 34 | $this->dropTable('setting'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vue2/src/pages/Post.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 40 | 41 | 44 | -------------------------------------------------------------------------------- /backend/controllers/TagController.php: -------------------------------------------------------------------------------- 1 | request->post(); 15 | $tagModel=new Tag(['type'=>1,'status'=>0]); 16 | $tagModel->load($post,''); 17 | $tagModel->url=$tagModel->name; 18 | $validate=$tagModel->uniqueValidate(); 19 | if(false===$validate['result']) 20 | return json_encode(['result'=>-1,'message'=>$validate['prop']]); 21 | else { 22 | if($tagModel->insert()){ 23 | return json_encode(['result'=>0,'message'=>'success']); 24 | }else return json_encode(['result'=>-2,'message'=>'insert db error']); 25 | } 26 | } 27 | 28 | public function actionList(){ 29 | return json_encode(['result'=>0,'list'=>ArrayHelper::toArray(Tag::getAllList())]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vue2/src/components/HbHead.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 54 | 55 | 71 | -------------------------------------------------------------------------------- /frontend/views/site/requestPasswordResetToken.php: -------------------------------------------------------------------------------- 1 | title = 'Request password reset'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 |
14 |

title) ?>

15 | 16 |

Please fill out your email. A link to reset password will be sent there.

17 | 18 |
19 |
20 | 'request-password-reset-form']); ?> 21 | 22 | field($model, 'email')->textInput(['autofocus' => true]) ?> 23 | 24 |
25 | 'btn btn-primary']) ?> 26 |
27 | 28 | 29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /console/migrations/m170703_160943_create_relationship_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 17 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 18 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 19 | } 20 | $this->createTable('relationship', [ 21 | 'cid' => $this->integer()->notNull(), 22 | 'pid'=>$this->integer()->notNull() 23 | ],$tableOptions); 24 | $this->addPrimaryKey('relationship_pk','relationship',['pid','cid']); 25 | } 26 | 27 | /** 28 | * @inheritdoc 29 | */ 30 | public function down() 31 | { 32 | $this->dropTable('relationship'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /frontend/controllers/ArticleController.php: -------------------------------------------------------------------------------- 1 | request->get('id'); 18 | if(!isset($id)){ 19 | return $this->render('list',[ 20 | 'list'=>Article::getHead(null), 21 | 'archive'=>Article::getArchive() 22 | ]); 23 | } 24 | $articleQuery=Article::findOne(['id'=>$id,'status'=>0]); 25 | if($articleQuery===null){ 26 | return '404'; 27 | } 28 | $tagQuery=Tag::getTagsByArticleId($id); 29 | $commentQuery=Comment::getByArticleId($id); 30 | return $this->render('item',[ 31 | 'article'=>$articleQuery, 32 | 'tags'=>$tagQuery, 33 | 'comments'=>$commentQuery 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/models/SignupForm.php: -------------------------------------------------------------------------------- 1 | validate()) { 39 | return null; 40 | } 41 | $user = new User(); 42 | $user->username = $this->username; 43 | $user->email = $this->email; 44 | $user->setPassword($this->password); 45 | $user->generateAuthKey(); 46 | return $user->save() ? $user : null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /vue2/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /vue2/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /vue2/build/build-module.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.module.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | // console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /console/migrations/m170630_150033_create_tag_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 17 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 18 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 19 | } 20 | $this->createTable('tag', [ 21 | 'id' => $this->primaryKey(), 22 | 'name'=> $this->text(), 23 | 'url'=>$this->text(), 24 | 'status'=>$this->integer()->defaultValue(0), 25 | 'description'=>$this->text(), 26 | 'type'=>$this->integer()->defaultValue(0), 27 | ],$tableOptions); 28 | } 29 | 30 | /** 31 | * @inheritdoc 32 | */ 33 | public function down() 34 | { 35 | $this->dropTable('tag'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vue2/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /frontend/views/site/signup.php: -------------------------------------------------------------------------------- 1 | title = 'Signup'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 | 36 | -------------------------------------------------------------------------------- /frontend/web/iconfont/material-icons.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Material Icons'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: url(MaterialIcons-Regular.eot); /* For IE6-8 */ 6 | src: local('Material Icons'), 7 | local('MaterialIcons-Regular'), 8 | url(MaterialIcons-Regular.woff2) format('woff2'), 9 | url(MaterialIcons-Regular.woff) format('woff'), 10 | url(MaterialIcons-Regular.ttf) format('truetype'); 11 | } 12 | 13 | .material-icons { 14 | font-family: 'Material Icons'; 15 | font-weight: normal; 16 | font-style: normal; 17 | font-size: 24px; /* Preferred icon size */ 18 | display: inline-block; 19 | line-height: 1; 20 | text-transform: none; 21 | letter-spacing: normal; 22 | word-wrap: normal; 23 | white-space: nowrap; 24 | direction: ltr; 25 | 26 | /* Support for all WebKit browsers. */ 27 | -webkit-font-smoothing: antialiased; 28 | /* Support for Safari and Chrome. */ 29 | text-rendering: optimizeLegibility; 30 | 31 | /* Support for Firefox. */ 32 | -moz-osx-font-smoothing: grayscale; 33 | 34 | /* Support for IE. */ 35 | font-feature-settings: 'liga'; 36 | } 37 | -------------------------------------------------------------------------------- /backend/views/site/login.php: -------------------------------------------------------------------------------- 1 | title = 'Login'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 | 36 | -------------------------------------------------------------------------------- /common/models/Relationship.php: -------------------------------------------------------------------------------- 1 | 'Cid', 41 | 'pid' => 'Pid', 42 | ]; 43 | } 44 | 45 | public static function exportAllData(){ 46 | return self::find()->asArray()->all(); 47 | } 48 | 49 | public static function batchAdd($relation){ 50 | $cols=['cid','pid','type']; 51 | return $result=Yii::$app->db->createCommand()->batchInsert(static::tableName(), $cols, $relation)->execute(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /frontend/tests/unit/models/ContactFormTest.php: -------------------------------------------------------------------------------- 1 | attributes = [ 14 | 'name' => 'Tester', 15 | 'email' => 'tester@example.com', 16 | 'subject' => 'very important letter subject', 17 | 'body' => 'body of current message', 18 | ]; 19 | 20 | expect_that($model->sendEmail('admin@example.com')); 21 | 22 | // using Yii2 module actions to check email was sent 23 | $this->tester->seeEmailIsSent(); 24 | 25 | $emailMessage = $this->tester->grabLastSentEmail(); 26 | expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface'); 27 | expect($emailMessage->getTo())->hasKey('admin@example.com'); 28 | expect($emailMessage->getFrom())->hasKey('tester@example.com'); 29 | expect($emailMessage->getSubject())->equals('very important letter subject'); 30 | expect($emailMessage->toString())->contains('body of current message'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /vue2/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /console/migrations/m130524_201442_init.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 11 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 12 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 13 | } 14 | 15 | $this->createTable('{{%user}}', [ 16 | 'id' => $this->primaryKey(), 17 | 'username' => $this->string()->notNull()->unique(), 18 | 'auth_key' => $this->string(32)->notNull(), 19 | 'password_hash' => $this->string()->notNull(), 20 | 'password_reset_token' => $this->string()->unique(), 21 | 'email' => $this->string()->notNull()->unique(), 22 | 23 | 'status' => $this->smallInteger()->notNull()->defaultValue(10), 24 | 'created_at' => $this->integer()->notNull(), 25 | 'updated_at' => $this->integer()->notNull(), 26 | ], $tableOptions); 27 | } 28 | 29 | public function down() 30 | { 31 | $this->dropTable('{{%user}}'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /frontend/tests/unit/models/ResetPasswordFormTest.php: -------------------------------------------------------------------------------- 1 | tester->haveFixtures([ 19 | 'user' => [ 20 | 'class' => UserFixture::className(), 21 | 'dataFile' => codecept_data_dir() . 'user.php' 22 | ], 23 | ]); 24 | } 25 | 26 | public function testResetWrongToken() 27 | { 28 | $this->tester->expectException('yii\base\InvalidParamException', function() { 29 | new ResetPasswordForm(''); 30 | }); 31 | 32 | $this->tester->expectException('yii\base\InvalidParamException', function() { 33 | new ResetPasswordForm('notexistingtoken_1391882543'); 34 | }); 35 | } 36 | 37 | public function testResetCorrectToken() 38 | { 39 | $user = $this->tester->grabFixture('user', 0); 40 | $form = new ResetPasswordForm($user['password_reset_token']); 41 | expect_that($form->resetPassword()); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /vagrant/provision/once-as-vagrant.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #== Import script args == 4 | 5 | github_token=$(echo "$1") 6 | 7 | #== Bash helpers == 8 | 9 | function info { 10 | echo " " 11 | echo "--> $1" 12 | echo " " 13 | } 14 | 15 | #== Provision script == 16 | 17 | info "Provision-script user: `whoami`" 18 | 19 | info "Configure composer" 20 | composer config --global github-oauth.github.com ${github_token} 21 | echo "Done!" 22 | 23 | info "Install plugins for composer" 24 | composer global require "fxp/composer-asset-plugin:^1.2.0" --no-progress 25 | 26 | info "Install codeception" 27 | composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*" --no-progress 28 | echo 'export PATH=/home/vagrant/.config/composer/vendor/bin:$PATH' | tee -a /home/vagrant/.profile 29 | 30 | info "Install project dependencies" 31 | cd /app 32 | composer --no-progress --prefer-dist install 33 | 34 | info "Init project" 35 | ./init --env=Development --overwrite=y 36 | 37 | info "Apply migrations" 38 | ./yii migrate <<< "yes" 39 | 40 | info "Create bash-alias 'app' for vagrant user" 41 | echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases 42 | 43 | info "Enabling colorized prompt for guest console" 44 | sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc 45 | -------------------------------------------------------------------------------- /console/migrations/m170720_142117_add_type_column_in_relationship_table_primary_key.php: -------------------------------------------------------------------------------- 1 | asArray()->all();//backup old data 11 | Relationship::deleteAll();//clear all 12 | $this->dropTable('relationship'); 13 | $tableOptions = null; 14 | if ($this->db->driverName === 'mysql') { 15 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 16 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 17 | } 18 | $this->createTable('relationship', [ 19 | 'cid' => $this->integer()->notNull(), 20 | 'pid'=>$this->integer()->notNull(), 21 | 'type'=>$this->string()->notNull(), 22 | ],$tableOptions); 23 | $this->addPrimaryKey('relationship_pk','relationship',['pid','cid','type']); 24 | $this->batchInsert('relationship',['cid','pid','type'],$oldData);//insert old data 25 | } 26 | 27 | public function down() 28 | { 29 | //this is an Migration can not down 30 | return false; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /backend/controllers/SettingController.php: -------------------------------------------------------------------------------- 1 | request->post(); 16 | if ($post['src'] == 'ghost') { 17 | $r = Setting::importFromGhost($post); 18 | return json_encode($r); 19 | } else if ($post['src']==='backup'){ 20 | $r = Setting::importFromBackup($post); 21 | return json_encode($r); 22 | } 23 | } 24 | 25 | public function actionBackup() 26 | { 27 | $get = yii::$app->request->get(); 28 | $data = Setting::exportAllData(); 29 | if ($get['target'] === 'file') { 30 | $path = Yii::getAlias('@runtime/backup'); 31 | if (!is_dir($path)) mkdir($path); 32 | $filename = $path . date("Ymd-hms") . '.json'; 33 | file_put_contents($filename, json_encode($data)); 34 | // return json_encode($data); 35 | 36 | header("Content-Type: application/force-download"); 37 | header("Content-Disposition: attachment; filename=" . date("Ymd-hms") . '.json'); 38 | readfile($filename); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /backend/web/dist/static/js/vendor.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,i){for(var u,a,s,f=0,l=[];ftitle = 'Login'; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 | 40 | -------------------------------------------------------------------------------- /backend/controllers/InstallController.php: -------------------------------------------------------------------------------- 1 | render('index'); 21 | } 22 | function actionInit(){ 23 | if(InstallSite::hasInstalled()){ 24 | throw new \yii\web\NotFoundHttpException('Page not found.'); 25 | } 26 | $install=new InstallSite(); 27 | $install->setAttributes($_POST); 28 | if($install->testDbConnect()===true){ 29 | if($install->install()===true) return $this->redirect('/#/signup'); 30 | else return 'install() failed'; 31 | }else{ 32 | return 'cannot connect db'; 33 | } 34 | } 35 | 36 | function actionUninstall(){ 37 | throw new \yii\web\NotFoundHttpException('Page not found.'); 38 | // InstallSite::uninstall(); 39 | } 40 | } -------------------------------------------------------------------------------- /vue2/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /frontend/views/catalog/index.php: -------------------------------------------------------------------------------- 1 | title = '目录'; 6 | ?> 7 |
8 |
9 |

Catalog

10 | 11 |
12 |
13 |
14 |
15 | class="card-title"> 16 |

140?"...":"")?>

17 |
18 |
19 | MORE 20 | AND? 21 | 22 |
23 |
24 |
25 |
26 | 27 | 28 |

Before you publish a article you can not see anything

29 | 30 |
31 |
32 | 33 | registerCssFile('@web/css/catalog.css'); 35 | ?> -------------------------------------------------------------------------------- /frontend/controllers/CommentController.php: -------------------------------------------------------------------------------- 1 | render('index',[]); 18 | } 19 | 20 | public function actionAdd(){ 21 | $model=new Comment(); 22 | $post=Yii::$app->request->post(); 23 | $model->author_ip=Yii::$app->request->userIP; 24 | if(Comment::getIpCountRecent($model->author_ip,5)>=5){ 25 | return json_encode(['result'=>-2,'message'=>'you had reviewed too many , have a rest']); 26 | }; 27 | $articleId=$post['article_id']; 28 | $articleModel=Article::findOne($post['article_id']);// new Article(['id'=>intval($post['article_id'])]); 29 | if($articleModel===null)return json_encode(['result'=>-1,'message'=>'article is not exist']); 30 | if($model->load($post,'') && $model->save()){ 31 | (new Relationship(['cid'=>$model->id,'pid'=>$articleId,'type'=>'comment-article']))->save(); 32 | $articleModel->countComments(); 33 | return json_encode(['result'=>0]); 34 | }else{ 35 | return var_dump($model->errors); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /frontend/web/js/article.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by zchi on 2017/7/19. 3 | */ 4 | $(function () { 5 | // commentValidateInit(); 6 | $('pre code').each(function(i, block) { 7 | hljs.highlightBlock(block); 8 | }); 9 | }); 10 | 11 | function commentSubmit(btn) { 12 | const timeout=3000; 13 | let $submitBtn=$('#comment-sumbit-btn').attr('disabled','disabled'); 14 | let $form=$('#review-form'); 15 | let commentFormData=$form.serializeJSON(); 16 | if(validate(commentFormData)){ 17 | $.ajax({'url':'/comment/add',method:'post',dataType:'json',data:commentFormData,success:function (res) { 18 | $submitBtn.removeAttr('disabled'); 19 | if(res.result===0){ 20 | $form[0].reset(); 21 | Materialize.toast('reviewed success', timeout) 22 | }else { 23 | Materialize.toast(res.message, timeout) 24 | } 25 | },error:function (err) { 26 | $submitBtn.removeAttr('disabled'); 27 | Materialize.toast(err.toString(), timeout) 28 | }}) 29 | }else { 30 | $submitBtn.removeAttr('disabled'); 31 | Materialize.toast('input invalid', timeout) 32 | } 33 | } 34 | 35 | function validate(commentFormData) { 36 | return !!(commentFormData.author_name && commentFormData.author_email && commentFormData.text); 37 | } 38 | 39 | function commentValidateInit() { 40 | $('#review-form').validate(); 41 | } -------------------------------------------------------------------------------- /console/migrations/m170503_160551_create_article_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 17 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 18 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 19 | } 20 | $this->createTable('article', [ 21 | 'id' => $this->primaryKey(), 22 | 'title' => $this->string(), 23 | 'text' => $this->text(), 24 | 'html' => $this->text(), 25 | 'author_id'=>$this->integer(), 26 | 'author_name'=>$this->string(), 27 | 'type'=>$this->string(), 28 | 'tag'=>$this->string(), 29 | 'status'=>$this->integer(), 30 | 'created_at'=>$this->timestamp()->defaultExpression('CURRENT_TIMESTAMP'), 31 | 'updated_at'=>$this->timestamp()->defaultExpression('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), 32 | 'url'=>$this->string() 33 | ],$tableOptions); 34 | } 35 | 36 | /** 37 | * @inheritdoc 38 | */ 39 | public function down() 40 | { 41 | $this->dropTable('article'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /console/migrations/m170718_162607_create_comment_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql') { 17 | // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci 18 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 19 | } 20 | $this->createTable('comment', [ 21 | 'id' => $this->primaryKey(), 22 | 'text'=> $this->text()->notNull(), 23 | 'author_id'=>$this->integer(), 24 | 'author_name'=>$this->text()->notNull(), 25 | 'author_email'=>$this->text()->notNull(), 26 | 'author_blog'=>$this->text(), 27 | 'author_ip'=>$this->text(), 28 | 'parent'=>$this->integer(), 29 | 'status'=>$this->integer(), 30 | 'type'=>$this->integer(), 31 | 'create_at'=>$this->timestamp()->defaultExpression('CURRENT_TIMESTAMP'), 32 | 'update_at'=>$this->timestamp()->defaultExpression('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), 33 | ],$tableOptions); 34 | } 35 | 36 | /** 37 | * @inheritdoc 38 | */ 39 | public function down() 40 | { 41 | $this->dropTable('comment'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yiisoft/yii2-app-advanced", 3 | "description": "Yii 2 Advanced Project Template", 4 | "keywords": ["yii2", "framework", "advanced", "project template"], 5 | "homepage": "http://www.yiiframework.com/", 6 | "type": "project", 7 | "license": "BSD-3-Clause", 8 | "support": { 9 | "issues": "https://github.com/yiisoft/yii2/issues?state=open", 10 | "forum": "http://www.yiiframework.com/forum/", 11 | "wiki": "http://www.yiiframework.com/wiki/", 12 | "irc": "irc://irc.freenode.net/yii", 13 | "source": "https://github.com/yiisoft/yii2" 14 | }, 15 | "minimum-stability": "stable", 16 | "require": { 17 | "php": ">=5.4.0", 18 | "yiisoft/yii2": "~2.0.6", 19 | "yiisoft/yii2-bootstrap": "~2.0.0", 20 | "yiisoft/yii2-swiftmailer": "~2.0.0", 21 | "firebase/php-jwt": "^4.0", 22 | "fxp/composer-asset-plugin": "~1.3" 23 | }, 24 | "require-dev": { 25 | "yiisoft/yii2-debug": "~2.0.0", 26 | "yiisoft/yii2-gii": "~2.0.0", 27 | "yiisoft/yii2-faker": "~2.0.0", 28 | 29 | "codeception/base": "^2.2.3", 30 | "codeception/verify": "~0.3.1" 31 | }, 32 | "config": { 33 | "process-timeout": 1800 34 | }, 35 | "extra": { 36 | "asset-installer-paths": { 37 | "npm-asset-library": "vendor/npm", 38 | "bower-asset-library": "vendor/bower" 39 | } 40 | }, 41 | "scripts": { 42 | "post-install-cmd": "php init --env=Development --overwrite=n" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /frontend/views/site/contact.php: -------------------------------------------------------------------------------- 1 | title = 'Contact'; 12 | $this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |
15 |

title) ?>

16 | 17 |

18 | If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. 19 |

20 | 21 |
22 |
23 | 'contact-form']); ?> 24 | 25 | field($model, 'name')->textInput(['autofocus' => true]) ?> 26 | 27 | field($model, 'email') ?> 28 | 29 | field($model, 'subject') ?> 30 | 31 | field($model, 'body')->textarea(['rows' => 6]) ?> 32 | 33 | field($model, 'verifyCode')->widget(Captcha::className(), [ 34 | 'template' => '
{image}
{input}
', 35 | ]) ?> 36 | 37 |
38 | 'btn btn-primary', 'name' => 'contact-button']) ?> 39 |
40 | 41 | 42 |
43 |
44 | 45 |
46 | -------------------------------------------------------------------------------- /frontend/tests/functional/LoginCest.php: -------------------------------------------------------------------------------- 1 | haveFixtures([ 13 | 'user' => [ 14 | 'class' => UserFixture::className(), 15 | 'dataFile' => codecept_data_dir() . 'login_data.php' 16 | ] 17 | ]); 18 | $I->amOnRoute('site/login'); 19 | } 20 | 21 | protected function formParams($login, $password) 22 | { 23 | return [ 24 | 'LoginForm[username]' => $login, 25 | 'LoginForm[password]' => $password, 26 | ]; 27 | } 28 | 29 | public function checkEmpty(FunctionalTester $I) 30 | { 31 | $I->submitForm('#login-form', $this->formParams('', '')); 32 | $I->seeValidationError('Username cannot be blank.'); 33 | $I->seeValidationError('Password cannot be blank.'); 34 | } 35 | 36 | public function checkWrongPassword(FunctionalTester $I) 37 | { 38 | $I->submitForm('#login-form', $this->formParams('admin', 'wrong')); 39 | $I->seeValidationError('Incorrect username or password.'); 40 | } 41 | 42 | public function checkValidLogin(FunctionalTester $I) 43 | { 44 | $I->submitForm('#login-form', $this->formParams('erau', 'password_0')); 45 | $I->see('Logout (erau)', 'form button[type=submit]'); 46 | $I->dontSeeLink('Login'); 47 | $I->dontSeeLink('Signup'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /frontend/models/ContactForm.php: -------------------------------------------------------------------------------- 1 | 'Verification Code', 42 | ]; 43 | } 44 | 45 | /** 46 | * Sends an email to the specified email address using the information collected by this model. 47 | * 48 | * @param string $email the target email address 49 | * @return bool whether the email was sent 50 | */ 51 | public function sendEmail($email) 52 | { 53 | return Yii::$app->mailer->compose() 54 | ->setTo($email) 55 | ->setFrom([$this->email => $this->name]) 56 | ->setSubject($this->subject) 57 | ->setTextBody($this->body) 58 | ->send(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /frontend/models/SignupForm.php: -------------------------------------------------------------------------------- 1 | '\common\models\User', 'message' => 'This username has already been taken.'], 26 | ['username', 'string', 'min' => 2, 'max' => 255], 27 | 28 | ['email', 'trim'], 29 | ['email', 'required'], 30 | ['email', 'email'], 31 | ['email', 'string', 'max' => 255], 32 | ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'], 33 | 34 | ['password', 'required'], 35 | ['password', 'string', 'min' => 6], 36 | ]; 37 | } 38 | 39 | /** 40 | * Signs user up. 41 | * 42 | * @return User|null the saved model or null if saving fails 43 | */ 44 | public function signup() 45 | { 46 | if (!$this->validate()) { 47 | return null; 48 | } 49 | 50 | $user = new User(); 51 | $user->username = $this->username; 52 | $user->email = $this->email; 53 | $user->setPassword($this->password); 54 | $user->generateAuthKey(); 55 | 56 | return $user->save() ? $user : null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /backend/views/install/index.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Install

4 |
5 |
6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 |
14 | 15 |
16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 |
24 | 25 |
26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 |
38 | 39 |
40 |
41 | 42 |
43 | -------------------------------------------------------------------------------- /frontend/views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 12 | beginPage() ?> 13 | 14 | 15 | 16 | 17 | 18 | <?= Html::encode($this->title) ?> 19 | head() ?> 20 | 21 | 22 | beginBody() ?> 23 | 43 |
44 | 45 |
46 | 47 | endBody() ?> 48 | 49 | 50 | endPage() ?> 51 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The Yii framework is free software. It is released under the terms of 2 | the following BSD License. 3 | 4 | Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | * Neither the name of Yii Software LLC nor the names of its 18 | contributors may be used to endorse or promote products derived 19 | from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /frontend/models/ResetPasswordForm.php: -------------------------------------------------------------------------------- 1 | _user = User::findByPasswordResetToken($token); 34 | if (!$this->_user) { 35 | throw new InvalidParamException('Wrong password reset token.'); 36 | } 37 | parent::__construct($config); 38 | } 39 | 40 | /** 41 | * @inheritdoc 42 | */ 43 | public function rules() 44 | { 45 | return [ 46 | ['password', 'required'], 47 | ['password', 'string', 'min' => 6], 48 | ]; 49 | } 50 | 51 | /** 52 | * Resets password. 53 | * 54 | * @return bool if password was reset. 55 | */ 56 | public function resetPassword() 57 | { 58 | $user = $this->_user; 59 | $user->setPassword($this->password); 60 | $user->removePasswordResetToken(); 61 | 62 | return $user->save(false); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /frontend/views/archive/list.php: -------------------------------------------------------------------------------- 1 | title = 'Archive'; 6 | ?> 7 |
8 |
9 |

10 | 11 |
12 |
13 |
14 |
15 | class="card-title"> 16 |

140?"...":"")?>

17 |
18 |
19 | MORE 20 | AND? 21 | 22 |
23 |
24 |
25 |
26 | 27 | 28 |

Nothing

29 | 30 |
31 |
32 | 33 |
34 | 40 |
41 | 42 | registerCssFile('@web/css/catalog.css'); 44 | ?> -------------------------------------------------------------------------------- /vue2/src/components/uploadFile.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 49 | 50 | 51 | 56 | -------------------------------------------------------------------------------- /frontend/views/article/list.php: -------------------------------------------------------------------------------- 1 | title = 'Articles'; 6 | ?> 7 |
8 |
9 |

All Articles

10 | 11 |
12 |
13 |
14 |
15 | class="card-title"> 16 |

140?"...":"")?>

17 |
18 |
19 | MORE 20 | AND? 21 | 22 |
23 |
24 |
25 |
26 | 27 | 28 |

Before you publish a article you can not see anything

29 | 30 |
31 |
32 | 33 |
34 | 40 |
41 | 42 | registerCssFile('@web/css/catalog.css'); 44 | ?> -------------------------------------------------------------------------------- /frontend/tests/unit/models/SignupFormTest.php: -------------------------------------------------------------------------------- 1 | tester->haveFixtures([ 18 | 'user' => [ 19 | 'class' => UserFixture::className(), 20 | 'dataFile' => codecept_data_dir() . 'user.php' 21 | ] 22 | ]); 23 | } 24 | 25 | public function testCorrectSignup() 26 | { 27 | $model = new SignupForm([ 28 | 'username' => 'some_username', 29 | 'email' => 'some_email@example.com', 30 | 'password' => 'some_password', 31 | ]); 32 | 33 | $user = $model->signup(); 34 | 35 | expect($user)->isInstanceOf('common\models\User'); 36 | 37 | expect($user->username)->equals('some_username'); 38 | expect($user->email)->equals('some_email@example.com'); 39 | expect($user->validatePassword('some_password'))->true(); 40 | } 41 | 42 | public function testNotCorrectSignup() 43 | { 44 | $model = new SignupForm([ 45 | 'username' => 'troy.becker', 46 | 'email' => 'nicolas.dianna@hotmail.com', 47 | 'password' => 'some_password', 48 | ]); 49 | 50 | expect_not($model->signup()); 51 | expect_that($model->getErrors('username')); 52 | expect_that($model->getErrors('email')); 53 | 54 | expect($model->getFirstError('username')) 55 | ->equals('This username has already been taken.'); 56 | expect($model->getFirstError('email')) 57 | ->equals('This email address has already been taken.'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /frontend/tests/functional/SignupCest.php: -------------------------------------------------------------------------------- 1 | amOnRoute('site/signup'); 15 | } 16 | 17 | public function signupWithEmptyFields(FunctionalTester $I) 18 | { 19 | $I->see('Signup', 'h1'); 20 | $I->see('Please fill out the following fields to signup:'); 21 | $I->submitForm($this->formId, []); 22 | $I->seeValidationError('Username cannot be blank.'); 23 | $I->seeValidationError('Email cannot be blank.'); 24 | $I->seeValidationError('Password cannot be blank.'); 25 | 26 | } 27 | 28 | public function signupWithWrongEmail(FunctionalTester $I) 29 | { 30 | $I->submitForm( 31 | $this->formId, [ 32 | 'SignupForm[username]' => 'tester', 33 | 'SignupForm[email]' => 'ttttt', 34 | 'SignupForm[password]' => 'tester_password', 35 | ] 36 | ); 37 | $I->dontSee('Username cannot be blank.', '.help-block'); 38 | $I->dontSee('Password cannot be blank.', '.help-block'); 39 | $I->see('Email is not a valid email address.', '.help-block'); 40 | } 41 | 42 | public function signupSuccessfully(FunctionalTester $I) 43 | { 44 | $I->submitForm($this->formId, [ 45 | 'SignupForm[username]' => 'tester', 46 | 'SignupForm[email]' => 'tester.email@example.com', 47 | 'SignupForm[password]' => 'tester_password', 48 | ]); 49 | 50 | $I->seeRecord('common\models\User', [ 51 | 'username' => 'tester', 52 | 'email' => 'tester.email@example.com', 53 | ]); 54 | 55 | $I->see('Logout (tester)', 'form button[type=submit]'); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /vue2/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | var entries = utils.getMultiEntry('./src/'+config.moduleName+'/**/**/*.js'); // 获得入口js文件 9 | 10 | // add hot-reload related code to entry chunks 11 | Object.keys(entries).forEach(function (name) { 12 | entries[name] = ['./build/dev-client'].concat(entries[name]) 13 | }) 14 | 15 | module.exports = merge(baseWebpackConfig, { 16 | entry:entries, 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: '#cheap-module-eval-source-map', 22 | plugins: [ 23 | new webpack.DefinePlugin({ 24 | 'process.env': config.dev.env 25 | }), 26 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 27 | new webpack.HotModuleReplacementPlugin(), 28 | new webpack.NoEmitOnErrorsPlugin(), 29 | // https://github.com/ampedandwired/html-webpack-plugin 30 | /* new HtmlWebpackPlugin({ 31 | filename: 'index.html', 32 | template: 'index.html', 33 | inject: true 34 | }), */ 35 | new FriendlyErrorsPlugin() 36 | ] 37 | }) 38 | 39 | 40 | var pages = utils.getMultiEntry('./src/'+config.moduleName+'/**/**/*.html'); 41 | for (var pathname in pages) { 42 | // 配置生成的html文件,定义路径等 43 | var conf = { 44 | filename: pathname + '.html', 45 | template: pages[pathname], // 模板路径 46 | chunks: [pathname, 'vendors', 'manifest'], // 每个html引用的js模块 47 | inject: true // js插入位置 48 | }; 49 | // 需要生成几个html文件,就配置几个HtmlWebpackPlugin对象 50 | module.exports.plugins.push(new HtmlWebpackPlugin(conf)); 51 | } 52 | -------------------------------------------------------------------------------- /frontend/config/main.php: -------------------------------------------------------------------------------- 1 | 'app-frontend', 11 | 'basePath' => dirname(__DIR__), 12 | 'bootstrap' => ['log'], 13 | 'controllerNamespace' => 'frontend\controllers', 14 | 'components' => [ 15 | 'request' => [ 16 | 'csrfParam' => '_csrf-frontend', 17 | 'parsers' => [ 18 | 'application/json' => 'yii\web\JsonParser', 19 | ] 20 | ], 21 | 'user' => [ 22 | 'identityClass' => 'common\models\User', 23 | 'enableAutoLogin' => true, 24 | 'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true], 25 | ], 26 | 'session' => [ 27 | // this is the name of the session cookie used for login on the frontend 28 | 'name' => 'advanced-frontend', 29 | ], 30 | 'log' => [ 31 | 'traceLevel' => YII_DEBUG ? 3 : 0, 32 | 'targets' => [ 33 | [ 34 | 'class' => 'yii\log\FileTarget', 35 | 'levels' => ['error', 'warning'], 36 | ], 37 | ], 38 | ], 39 | 'errorHandler' => [ 40 | 'errorAction' => 'site/error', 41 | ], 42 | 43 | 'urlManager' => [ 44 | 'enablePrettyUrl' => true, 45 | 'showScriptName' => false, 46 | 'rules' => [ 47 | '/' => '/index', 48 | '/' => '/index', 49 | '/' => '/index', 50 | ], 51 | ], 52 | 53 | ], 54 | 'params' => $params, 55 | ]; 56 | -------------------------------------------------------------------------------- /vue2/config/modules.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | var modules=require('../build/modules.target.conf.js') 4 | if(!process.argv[2])return console.log('Need A Argument As Module Name !!') 5 | var targetModule=modules.getModuleTarget(process.argv[2]) 6 | module.exports = { 7 | 8 | //网站模块名,例如 http://192.168.0.216:8089/module/app/initlayer.html 中的 9 | //【views】,默认为views,修改这里的配置的同时,也要同时重命名/src/views的这个文件夹名称 10 | moduleName:'views', 11 | 12 | build: { 13 | env: require('./prod.env'), 14 | index: targetModule.index, 15 | assetsRoot: targetModule.assetsRoot, 16 | assetsSubDirectory: targetModule.assetsPublicPath, 17 | assetsPublicPath: targetModule.assetsPublicPath, 18 | productionSourceMap: true, 19 | // Gzip off by default as many popular static hosts such as 20 | // Surge or Netlify already gzip all static assets for you. 21 | // Before setting to `true`, make sure to: 22 | // npm install --save-dev compression-webpack-plugin 23 | productionGzip: false, 24 | productionGzipExtensions: ['js', 'css'], 25 | // Run the build command with an extra argument to 26 | // View the bundle analyzer report after build finishes: 27 | // `npm run build --report` 28 | // Set to `true` or `false` to always turn it on or off 29 | bundleAnalyzerReport: process.env.npm_config_report 30 | }, 31 | dev: { 32 | env: require('./dev.env'), 33 | port: 8091, 34 | autoOpenBrowser: false, 35 | assetsSubDirectory: 'static', 36 | assetsPublicPath: '/', 37 | proxyTable: {}, 38 | // CSS Sourcemaps off by default because relative paths are "buggy" 39 | // with this option, according to the CSS-Loader README 40 | // (https://github.com/webpack/css-loader#sourcemaps) 41 | // In our experience, they generally work as expected, 42 | // just be aware of this issue when enabling this option. 43 | cssSourceMap: false 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /frontend/models/PasswordResetRequestForm.php: -------------------------------------------------------------------------------- 1 | '\common\models\User', 27 | 'filter' => ['status' => User::STATUS_ACTIVE], 28 | 'message' => 'There is no user with this email address.' 29 | ], 30 | ]; 31 | } 32 | 33 | /** 34 | * Sends an email with a link, for resetting the password. 35 | * 36 | * @return bool whether the email was send 37 | */ 38 | public function sendEmail() 39 | { 40 | /* @var $user User */ 41 | $user = User::findOne([ 42 | 'status' => User::STATUS_ACTIVE, 43 | 'email' => $this->email, 44 | ]); 45 | 46 | if (!$user) { 47 | return false; 48 | } 49 | 50 | if (!User::isPasswordResetTokenValid($user->password_reset_token)) { 51 | $user->generatePasswordResetToken(); 52 | if (!$user->save()) { 53 | return false; 54 | } 55 | } 56 | 57 | return Yii::$app 58 | ->mailer 59 | ->compose( 60 | ['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text'], 61 | ['user' => $user] 62 | ) 63 | ->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name . ' robot']) 64 | ->setTo($this->email) 65 | ->setSubject('Password reset for ' . Yii::$app->name) 66 | ->send(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vue2/src/router/admin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Z on 2017/4/29. 3 | */ 4 | import Vue from 'vue' 5 | import Router from 'vue-router' 6 | import Test from '@/pages/Test' 7 | import AdminHome from '@/pages/AdminHome' 8 | import AdminUser from '@/pages/AdminUser' 9 | import AdminArticle from '@/pages/AdminArticle' 10 | import Post from '@/pages/Post' 11 | import Login from '@/pages/Login' 12 | import Signup from '@/pages/Signup' 13 | import Setting from '@/pages/Setting' 14 | 15 | Vue.use(Router); 16 | 17 | export default new Router({ 18 | routes: [ 19 | { 20 | path: '/', 21 | name: 'AdminHome', 22 | component: AdminHome, 23 | meta:{ 24 | requireAuth:true 25 | } 26 | }, 27 | { 28 | path: '/test', 29 | name: 'Test', 30 | component: Test 31 | }, 32 | { 33 | path: '/user', 34 | name: 'AdminUser', 35 | component: AdminUser, 36 | meta:{ 37 | requireAuth:true 38 | } 39 | }, 40 | { 41 | path: '/article', 42 | name: 'AdminArticle', 43 | component: AdminArticle, 44 | meta:{ 45 | requireAuth:true 46 | }, 47 | }, 48 | { 49 | path: '/post', 50 | name: 'post', 51 | component: Post, 52 | meta:{ 53 | requireAuth:true 54 | } 55 | }, 56 | { 57 | path: '/login', 58 | name: 'Login', 59 | component: Login 60 | }, 61 | { 62 | path: '/Signup', 63 | name: 'Signup', 64 | component: Signup 65 | }, 66 | { 67 | path: '/setting', 68 | name: 'Setting', 69 | component: Setting, 70 | meta:{ 71 | requireAuth:true 72 | } 73 | } 74 | ] 75 | 76 | }) 77 | -------------------------------------------------------------------------------- /common/tests/unit/models/LoginFormTest.php: -------------------------------------------------------------------------------- 1 | tester->haveFixtures([ 23 | 'user' => [ 24 | 'class' => UserFixture::className(), 25 | 'dataFile' => codecept_data_dir() . 'user.php' 26 | ] 27 | ]); 28 | } 29 | 30 | public function testLoginNoUser() 31 | { 32 | $model = new LoginForm([ 33 | 'username' => 'not_existing_username', 34 | 'password' => 'not_existing_password', 35 | ]); 36 | 37 | expect('model should not login user', $model->login())->false(); 38 | expect('user should not be logged in', Yii::$app->user->isGuest)->true(); 39 | } 40 | 41 | public function testLoginWrongPassword() 42 | { 43 | $model = new LoginForm([ 44 | 'username' => 'bayer.hudson', 45 | 'password' => 'wrong_password', 46 | ]); 47 | 48 | expect('model should not login user', $model->login())->false(); 49 | expect('error message should be set', $model->errors)->hasKey('password'); 50 | expect('user should not be logged in', Yii::$app->user->isGuest)->true(); 51 | } 52 | 53 | public function testLoginCorrect() 54 | { 55 | $model = new LoginForm([ 56 | 'username' => 'bayer.hudson', 57 | 'password' => 'password_0', 58 | ]); 59 | 60 | expect('model should login user', $model->login())->true(); 61 | expect('error message should not be set', $model->errors)->hasntKey('password'); 62 | expect('user should be logged in', Yii::$app->user->isGuest)->false(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /backend/config/main.php: -------------------------------------------------------------------------------- 1 | 'app-backend', 11 | 'basePath' => dirname(__DIR__), 12 | 'controllerNamespace' => 'backend\controllers', 13 | 'bootstrap' => ['log'], 14 | 'modules' => [], 15 | 'components' => [ 16 | 'request' => [ 17 | 'csrfParam' => '_csrf-backend', 18 | ], 19 | 'user' => [ 20 | 'identityClass' => 'common\models\User', 21 | 'enableAutoLogin' => true, 22 | 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true], 23 | ], 24 | 'session' => [ 25 | // this is the name of the session cookie used for login on the backend 26 | 'name' => 'advanced-backend', 27 | ], 28 | 'log' => [ 29 | 'traceLevel' => YII_DEBUG ? 3 : 0, 30 | 'targets' => [ 31 | [ 32 | 'class' => 'yii\log\FileTarget', 33 | 'levels' => ['error', 'warning'], 34 | ], 35 | ], 36 | ], 37 | 'errorHandler' => [ 38 | 'errorAction' => 'site/error', 39 | ], 40 | 'urlManager' => [ 41 | 'enablePrettyUrl' => true, 42 | 'showScriptName' => false, 43 | 'enableStrictParsing' => true, 44 | 'rules' => [ 45 | '<_c:[\w\-]+>' => '<_c>/index', 46 | '<_c:[\w\-]+>/<_a:[\w\-]+>' => '<_c>/<_a>', 47 | '<_c:[\w\-]+>/<_a:[\w\-]+>/' => '<_c>/<_a>', 48 | ], 49 | ], 50 | 51 | 'urlManager' => [ 52 | 'enablePrettyUrl' => true, 53 | 'showScriptName' => false, 54 | 'rules' => [ 55 | ], 56 | ], 57 | 58 | ], 59 | 'params' => $params, 60 | ]; 61 | -------------------------------------------------------------------------------- /frontend/tests/unit/models/PasswordResetRequestFormTest.php: -------------------------------------------------------------------------------- 1 | tester->haveFixtures([ 21 | 'user' => [ 22 | 'class' => UserFixture::className(), 23 | 'dataFile' => codecept_data_dir() . 'user.php' 24 | ] 25 | ]); 26 | } 27 | 28 | public function testSendMessageWithWrongEmailAddress() 29 | { 30 | $model = new PasswordResetRequestForm(); 31 | $model->email = 'not-existing-email@example.com'; 32 | expect_not($model->sendEmail()); 33 | } 34 | 35 | public function testNotSendEmailsToInactiveUser() 36 | { 37 | $user = $this->tester->grabFixture('user', 1); 38 | $model = new PasswordResetRequestForm(); 39 | $model->email = $user['email']; 40 | expect_not($model->sendEmail()); 41 | } 42 | 43 | public function testSendEmailSuccessfully() 44 | { 45 | $userFixture = $this->tester->grabFixture('user', 0); 46 | 47 | $model = new PasswordResetRequestForm(); 48 | $model->email = $userFixture['email']; 49 | $user = User::findOne(['password_reset_token' => $userFixture['password_reset_token']]); 50 | 51 | expect_that($model->sendEmail()); 52 | expect_that($user->password_reset_token); 53 | 54 | $emailMessage = $this->tester->grabLastSentEmail(); 55 | expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface'); 56 | expect($emailMessage->getTo())->hasKey($model->email); 57 | expect($emailMessage->getFrom())->hasKey(Yii::$app->params['supportEmail']); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /vue2/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | 6 | var glob = require('glob'); 7 | var projectRoot = path.resolve(__dirname, '../') 8 | 9 | var vueLoaderConfig = require('./vue-loader.conf') 10 | 11 | function resolve (dir) { 12 | return path.join(__dirname, '..', dir) 13 | } 14 | 15 | module.exports = { 16 | output: { 17 | path: config.build.assetsRoot, 18 | filename: '[name].js', 19 | publicPath: process.env.NODE_ENV === 'production' 20 | ? config.build.assetsPublicPath 21 | : config.dev.assetsPublicPath 22 | }, 23 | resolve: { 24 | extensions: ['.js', '.vue', '.json'], 25 | alias: { 26 | 'vue$': 'vue/dist/vue.esm.js', 27 | '@': resolve('src'), 28 | 'src': path.resolve(__dirname, '../src'), 29 | 'assets': path.resolve(__dirname, '../src/assets'), 30 | 'components': path.resolve(__dirname, '../src/components') 31 | } 32 | }, 33 | module: { 34 | rules: [ 35 | { 36 | test: /\.vue$/, 37 | loader: 'vue-loader', 38 | options: vueLoaderConfig 39 | }, 40 | { 41 | test: /\.js$/, 42 | loader: 'babel-loader', 43 | include: [resolve('src'), resolve('test')] 44 | }, 45 | { 46 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 47 | loader: 'url-loader', 48 | query: { 49 | limit: 10000, 50 | name: utils.assetsPath('img/[name].[ext]') 51 | } 52 | }, 53 | { 54 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('fonts/[name].[ext]') 59 | } 60 | }, 61 | 62 | ] 63 | }, 64 | plugins: [ 65 | /* 66 | // 提取公共模块 67 | new webpack.optimize.CommonsChunkPlugin({ 68 | name: 'vendors', // 公共模块的名称 69 | chunks: chunks, // chunks是需要提取的模块 70 | minChunks: 4 || chunks.length //公共模块被使用的最小次数。比如配置为3,也就是同一个模块只有被3个以外的页面同时引用时才会被提取出来作为common chunks。 71 | 72 | }),*/ 73 | 74 | ] 75 | } -------------------------------------------------------------------------------- /vagrant/provision/once-as-root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #== Import script args == 4 | 5 | timezone=$(echo "$1") 6 | 7 | #== Bash helpers == 8 | 9 | function info { 10 | echo " " 11 | echo "--> $1" 12 | echo " " 13 | } 14 | 15 | #== Provision script == 16 | 17 | info "Provision-script user: `whoami`" 18 | 19 | info "Allocate swap for MySQL 5.6" 20 | fallocate -l 2048M /swapfile 21 | chmod 600 /swapfile 22 | mkswap /swapfile 23 | swapon /swapfile 24 | echo '/swapfile none swap defaults 0 0' >> /etc/fstab 25 | 26 | info "Configure locales" 27 | update-locale LC_ALL="C" 28 | dpkg-reconfigure locales 29 | 30 | info "Configure timezone" 31 | echo ${timezone} | tee /etc/timezone 32 | dpkg-reconfigure --frontend noninteractive tzdata 33 | 34 | info "Prepare root password for MySQL" 35 | debconf-set-selections <<< "mysql-server-5.6 mysql-server/root_password password \"''\"" 36 | debconf-set-selections <<< "mysql-server-5.6 mysql-server/root_password_again password \"''\"" 37 | echo "Done!" 38 | 39 | info "Update OS software" 40 | apt-get update 41 | apt-get upgrade -y 42 | 43 | info "Install additional software" 44 | apt-get install -y git php5-curl php5-cli php5-intl php5-mysqlnd php5-gd php5-fpm nginx mysql-server-5.6 45 | 46 | info "Configure MySQL" 47 | sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/my.cnf 48 | echo "Done!" 49 | 50 | info "Configure PHP-FPM" 51 | sed -i 's/user = www-data/user = vagrant/g' /etc/php5/fpm/pool.d/www.conf 52 | sed -i 's/group = www-data/group = vagrant/g' /etc/php5/fpm/pool.d/www.conf 53 | sed -i 's/owner = www-data/owner = vagrant/g' /etc/php5/fpm/pool.d/www.conf 54 | echo "Done!" 55 | 56 | info "Configure NGINX" 57 | sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf 58 | echo "Done!" 59 | 60 | info "Enabling site configuration" 61 | ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf 62 | echo "Done!" 63 | 64 | info "Initailize databases for MySQL" 65 | mysql -uroot <<< "CREATE DATABASE yii2advanced" 66 | mysql -uroot <<< "CREATE DATABASE yii2advanced_test" 67 | echo "Done!" 68 | 69 | info "Install composer" 70 | curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -------------------------------------------------------------------------------- /environments/index.php: -------------------------------------------------------------------------------- 1 | [ 11 | * 'path' => 'directory storing the local files', 12 | * 'skipFiles' => [ 13 | * // list of files that should only copied once and skipped if they already exist 14 | * ], 15 | * 'setWritable' => [ 16 | * // list of directories that should be set writable 17 | * ], 18 | * 'setExecutable' => [ 19 | * // list of files that should be set executable 20 | * ], 21 | * 'setCookieValidationKey' => [ 22 | * // list of config files that need to be inserted with automatically generated cookie validation keys 23 | * ], 24 | * 'createSymlink' => [ 25 | * // list of symlinks to be created. Keys are symlinks, and values are the targets. 26 | * ], 27 | * ], 28 | * ]; 29 | * ``` 30 | */ 31 | return [ 32 | 'Development' => [ 33 | 'path' => 'dev', 34 | 'setWritable' => [ 35 | 'backend/runtime', 36 | 'backend/web/assets', 37 | 'frontend/runtime', 38 | 'frontend/web/assets', 39 | ], 40 | 'setExecutable' => [ 41 | 'yii', 42 | 'yii_test', 43 | ], 44 | 'setCookieValidationKey' => [ 45 | 'backend/config/main-local.php', 46 | 'frontend/config/main-local.php', 47 | ], 48 | ], 49 | 'Production' => [ 50 | 'path' => 'prod', 51 | 'setWritable' => [ 52 | 'backend/runtime', 53 | 'backend/web/assets', 54 | 'frontend/runtime', 55 | 'frontend/web/assets', 56 | ], 57 | 'setExecutable' => [ 58 | 'yii', 59 | ], 60 | 'setCookieValidationKey' => [ 61 | 'backend/config/main-local.php', 62 | 'frontend/config/main-local.php', 63 | ], 64 | ], 65 | ]; 66 | -------------------------------------------------------------------------------- /common/models/LoginForm.php: -------------------------------------------------------------------------------- 1 | hasErrors()) { 44 | $user = $this->getUser(); 45 | if (!$user || !$user->validatePassword($this->password)) { 46 | $this->addError($attribute, 'Incorrect username or password.'); 47 | } 48 | } 49 | } 50 | 51 | /** 52 | * Logs in a user using the provided username and password. 53 | * 54 | * @return bool whether the user is logged in successfully 55 | */ 56 | public function login() 57 | { 58 | if ($this->validate()) { 59 | return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0); 60 | } else { 61 | return false; 62 | } 63 | } 64 | 65 | /** 66 | * Finds user by [[username]] 67 | * 68 | * @return User|null 69 | */ 70 | protected function getUser() 71 | { 72 | if ($this->_user === null) { 73 | $this->_user = User::findByUsername($this->username); 74 | } 75 | 76 | return $this->_user; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /vue2/src/views/admin/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 37 | 38 | 58 | 59 | 83 | -------------------------------------------------------------------------------- /frontend/tests/functional/ContactCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(['site/contact']); 13 | } 14 | 15 | public function checkContact(FunctionalTester $I) 16 | { 17 | $I->see('Contact', 'h1'); 18 | } 19 | 20 | public function checkContactSubmitNoData(FunctionalTester $I) 21 | { 22 | $I->submitForm('#contact-form', []); 23 | $I->see('Contact', 'h1'); 24 | $I->seeValidationError('Name cannot be blank'); 25 | $I->seeValidationError('Email cannot be blank'); 26 | $I->seeValidationError('Subject cannot be blank'); 27 | $I->seeValidationError('Body cannot be blank'); 28 | $I->seeValidationError('The verification code is incorrect'); 29 | } 30 | 31 | public function checkContactSubmitNotCorrectEmail(FunctionalTester $I) 32 | { 33 | $I->submitForm('#contact-form', [ 34 | 'ContactForm[name]' => 'tester', 35 | 'ContactForm[email]' => 'tester.email', 36 | 'ContactForm[subject]' => 'test subject', 37 | 'ContactForm[body]' => 'test content', 38 | 'ContactForm[verifyCode]' => 'testme', 39 | ]); 40 | $I->seeValidationError('Email is not a valid email address.'); 41 | $I->dontSeeValidationError('Name cannot be blank'); 42 | $I->dontSeeValidationError('Subject cannot be blank'); 43 | $I->dontSeeValidationError('Body cannot be blank'); 44 | $I->dontSeeValidationError('The verification code is incorrect'); 45 | } 46 | 47 | public function checkContactSubmitCorrectData(FunctionalTester $I) 48 | { 49 | $I->submitForm('#contact-form', [ 50 | 'ContactForm[name]' => 'tester', 51 | 'ContactForm[email]' => 'tester@example.com', 52 | 'ContactForm[subject]' => 'test subject', 53 | 'ContactForm[body]' => 'test content', 54 | 'ContactForm[verifyCode]' => 'testme', 55 | ]); 56 | $I->seeEmailIsSent(); 57 | $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /frontend/web/css/article.css: -------------------------------------------------------------------------------- 1 | .tag-box{ 2 | /*display: inline-block;*/ 3 | /*margin-right: 30px;*/ 4 | } 5 | .tag-item{ 6 | padding: 0 1rem; 7 | height: 32px; 8 | line-height: 2rem; 9 | float: right; 10 | margin-left: 0.5rem; 11 | } 12 | 13 | .article-info{ 14 | line-height:2rem; 15 | font-size: 1rem; 16 | } 17 | 18 | .card-title>h3{ 19 | margin: 0; 20 | } 21 | 22 | .article-content h1 { 23 | font-size:2.4rem; 24 | font-weight: bold; 25 | border-bottom:1px solid #ddd; 26 | padding-bottom:6px; 27 | } 28 | 29 | .article-content h2 { 30 | font-size:2.0rem; 31 | border-bottom:1px solid #ddd; 32 | padding-bottom:6px; 33 | font-weight: bold; 34 | } 35 | .article-content h3 { 36 | font-size: 1.8rem; 37 | font-weight: bold; 38 | } 39 | 40 | .article-content h4 { 41 | font-size: 1.6rem; 42 | font-weight: bold; 43 | } 44 | 45 | .article-content h5 { 46 | font-size: 1.4rem; 47 | font-weight: bold; 48 | } 49 | 50 | .article-content h6 { 51 | font-size: 1.2rem; 52 | font-weight: bold; 53 | } 54 | 55 | .article-content pre { 56 | background-color: #f3f3f3; 57 | padding: 8px; 58 | border-radius: 4px; 59 | } 60 | 61 | .article-content pre>code { 62 | background-color: #f3f3f3; 63 | } 64 | .article-content p>code { 65 | background-color: #f3f3f3; 66 | padding: 2px 3px; 67 | margin: 2px; 68 | border-radius: 4px; 69 | border: 1px solid #f0f0f0; 70 | } 71 | 72 | .article-content strong{ 73 | font-weight: bold; 74 | } 75 | .article-content sub,.article-content sup{ 76 | color: #000089; 77 | } 78 | .article-content em{ 79 | margin-right: 3px; 80 | } 81 | .article-content blockquote{ 82 | border-color: #0091EA; 83 | margin-left:10px; 84 | color: #999999; 85 | } 86 | 87 | .article-content ul,.article-content ol{ 88 | padding-left: 1rem; 89 | } 90 | .article-content ul>li{ 91 | list-style-type:circle; 92 | } 93 | .article-content>ul>li{ 94 | list-style-type: disc; 95 | } 96 | 97 | .article-content td, .article-content th{ 98 | border: 1px solid #ddd; 99 | text-align: center; 100 | } 101 | 102 | .article-content p { 103 | margin: 4px; 104 | line-height: 1.8; 105 | } 106 | .article-content img{ 107 | max-width: 100%; 108 | } -------------------------------------------------------------------------------- /backend/controllers/ArticleController.php: -------------------------------------------------------------------------------- 1 | request->post(); 13 | $text=$post['md']; 14 | $title=$post['title']; 15 | $html=$post['html']; 16 | $tag=json_decode($post['tag']); 17 | $url=isset($post['url'])?$post['url']:''; 18 | $post_time=$post['time']; 19 | $modal=new Article(); 20 | $result=$modal->publish($title,$text,$html,$tag,$url,$post_time); 21 | if($result===0){ 22 | return json_encode(['result'=>0,'message'=>'发布成功']); 23 | }else{ 24 | return json_encode(['result'=>-1,'message'=>$result]); 25 | } 26 | } 27 | 28 | public function actionUpdate(){ 29 | $post=Yii::$app->request->post(); 30 | $articleId=$post['id']; 31 | $text=$post['md']; 32 | $title=$post['title']; 33 | $html=$post['html']; 34 | $tag=json_decode($post['tag']); 35 | $modal=Article::findOne($articleId); 36 | if($modal===null)return json_encode(['result'=>-2,'message'=>'This article is not exist']); 37 | $result=$modal->edit($title,$text,$html,$tag); 38 | if($result===0){ 39 | return json_encode(['result'=>0,'message'=>'Update Success']); 40 | }else{ 41 | return json_encode(['result'=>-1,'message'=>$result]); 42 | } 43 | } 44 | 45 | public function actionDelete(){ 46 | $post=Yii::$app->request->post(); 47 | $articles=$post['articles']; 48 | $result=Article::moveRecycle($articles); 49 | if($result===count($articles)) 50 | return json_encode(['result'=>0,'message'=>'Delete Success']); 51 | else 52 | return json_encode(['result'=>-1,'message'=>$result]); 53 | } 54 | 55 | public function actionList(){ 56 | $modal=new Article(); 57 | $List=$modal->getAllList(); 58 | return json_encode(['result'=>0,'list'=>$List]); 59 | } 60 | 61 | public function actionText(){ 62 | $id=Yii::$app->request->get('id'); 63 | $text=Article::getText($id); 64 | return json_encode(['result'=>0,'content'=>$text]); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /vue2/src/components/adminHead.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 47 | 48 | 70 | -------------------------------------------------------------------------------- /vagrant/nginx/app.conf: -------------------------------------------------------------------------------- 1 | server { 2 | charset utf-8; 3 | client_max_body_size 128M; 4 | sendfile off; 5 | 6 | listen 80; ## listen for ipv4 7 | #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 8 | 9 | server_name y2aa-frontend.dev; 10 | root /app/frontend/web/; 11 | index index.php; 12 | 13 | access_log /app/vagrant/nginx/log/frontend-access.log; 14 | error_log /app/vagrant/nginx/log/frontend-error.log; 15 | 16 | location / { 17 | # Redirect everything that isn't a real file to index.php 18 | try_files $uri $uri/ /index.php$is_args$args; 19 | } 20 | 21 | # uncomment to avoid processing of calls to non-existing static files by Yii 22 | #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { 23 | # try_files $uri =404; 24 | #} 25 | #error_page 404 /404.html; 26 | 27 | location ~ \.php$ { 28 | include fastcgi_params; 29 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 30 | #fastcgi_pass 127.0.0.1:9000; 31 | fastcgi_pass unix:/var/run/php5-fpm.sock; 32 | try_files $uri =404; 33 | } 34 | 35 | location ~ /\.(ht|svn|git) { 36 | deny all; 37 | } 38 | } 39 | 40 | server { 41 | charset utf-8; 42 | client_max_body_size 128M; 43 | sendfile off; 44 | 45 | listen 80; ## listen for ipv4 46 | #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 47 | 48 | server_name y2aa-backend.dev; 49 | root /app/backend/web/; 50 | index index.php; 51 | 52 | access_log /app/vagrant/nginx/log/backend-access.log; 53 | error_log /app/vagrant/nginx/log/backend-error.log; 54 | 55 | location / { 56 | # Redirect everything that isn't a real file to index.php 57 | try_files $uri $uri/ /index.php$is_args$args; 58 | } 59 | 60 | # uncomment to avoid processing of calls to non-existing static files by Yii 61 | #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { 62 | # try_files $uri =404; 63 | #} 64 | #error_page 404 /404.html; 65 | 66 | location ~ \.php$ { 67 | include fastcgi_params; 68 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 69 | #fastcgi_pass 127.0.0.1:9000; 70 | fastcgi_pass unix:/var/run/php5-fpm.sock; 71 | try_files $uri =404; 72 | } 73 | 74 | location ~ /\.(ht|svn|git) { 75 | deny all; 76 | } 77 | } 78 | --------------------------------------------------------------------------------