├── src ├── assets │ ├── .gitkeep │ ├── .npmignore │ ├── imgs │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ ├── 9.png │ │ ├── 10.png │ │ ├── angular2.png │ │ ├── angular-weibo.png │ │ ├── angular2-small.png │ │ ├── angular-wechat-channel.jpg │ │ └── angular.svg │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── icomoon │ │ │ ├── icomoon.eot │ │ │ ├── icomoon.ttf │ │ │ ├── icomoon.woff │ │ │ └── icomoon │ │ │ │ ├── fonts │ │ │ │ ├── icomoon.eot │ │ │ │ ├── icomoon.ttf │ │ │ │ └── icomoon.woff │ │ │ │ ├── Read Me.txt │ │ │ │ └── demo-files │ │ │ │ └── demo.css │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── fontawesome-webfont.woff2 │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ ├── glyphicons-halflings-regular.woff2 │ │ ├── simple-line-icons │ │ │ ├── Simple-Line-Icons.eot │ │ │ ├── Simple-Line-Icons.ttf │ │ │ ├── Simple-Line-Icons.woff │ │ │ └── Simple-Line-Icons.woff2 │ │ └── bootstrap │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ ├── skins │ │ └── lightgray │ │ │ ├── img │ │ │ ├── anchor.gif │ │ │ ├── loader.gif │ │ │ ├── object.gif │ │ │ └── trans.gif │ │ │ ├── fonts │ │ │ ├── tinymce.eot │ │ │ ├── tinymce.ttf │ │ │ ├── tinymce.woff │ │ │ ├── tinymce-small.eot │ │ │ ├── tinymce-small.ttf │ │ │ └── tinymce-small.woff │ │ │ ├── content.inline.min.css │ │ │ └── content.min.css │ ├── i18n │ │ ├── zh.json │ │ └── en.json │ └── css │ │ └── prism.css ├── app │ ├── app.component.css │ ├── home │ │ ├── home.component.scss │ │ ├── online-contact │ │ │ ├── online-contact.component.scss │ │ │ ├── online-contact.component.spec.ts │ │ │ ├── online-contact.component.ts │ │ │ └── online-contact.component.html │ │ ├── social-channel │ │ │ ├── social-channel.component.scss │ │ │ ├── social-channel.component.spec.ts │ │ │ ├── social-channel.component.ts │ │ │ └── social-channel.component.html │ │ ├── home.routes.ts │ │ ├── home.component.ts │ │ ├── home.component.html │ │ ├── home.module.ts │ │ └── home.component.spec.ts │ ├── map │ │ └── gaode-map │ │ │ ├── gaode-map.component.scss │ │ │ ├── amap │ │ │ ├── amap.component.scss │ │ │ ├── amap.component.html │ │ │ └── amap.component.ts │ │ │ ├── gaode-map.component.html │ │ │ ├── gaode-map.component.ts │ │ │ └── gaode-map.component.spec.ts │ ├── use-jquery │ │ ├── use-jquery.component.scss │ │ ├── use-jquery.component.ts │ │ ├── use-jquery.component.spec.ts │ │ └── use-jquery.component.html │ ├── user │ │ ├── user-info │ │ │ ├── user-info.component.scss │ │ │ ├── user-info.component.spec.ts │ │ │ ├── user-info.component.html │ │ │ └── user-info.component.ts │ │ ├── user-main │ │ │ ├── user-main.component.scss │ │ │ ├── user-main.component.spec.ts │ │ │ ├── user-main.component.ts │ │ │ └── user-main.component.html │ │ ├── forget-pwd │ │ │ ├── forget-pwd.component.scss │ │ │ ├── forget-pwd.component.spec.ts │ │ │ ├── forget-pwd.service.ts │ │ │ ├── forget-pwd.component.ts │ │ │ └── forget-pwd.component.html │ │ ├── user-profile │ │ │ ├── user-profile.component.scss │ │ │ ├── dynamic-form │ │ │ │ ├── form-field │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── image.ts │ │ │ │ │ ├── textarea.ts │ │ │ │ │ ├── textbox.ts │ │ │ │ │ └── field-base.ts │ │ │ │ ├── form-control.component.ts │ │ │ │ └── form-control.component.html │ │ │ ├── user-profile.component.spec.ts │ │ │ ├── user-profile.component.html │ │ │ └── user-profile.component.ts │ │ ├── user-login │ │ │ ├── user-login.component.scss │ │ │ ├── user-login.component.spec.ts │ │ │ ├── user-login.service.ts │ │ │ ├── user-login.component.ts │ │ │ └── user-login.component.html │ │ ├── user-register │ │ │ ├── user-register.component.scss │ │ │ ├── user-register.component.spec.ts │ │ │ ├── directives │ │ │ │ └── equal-validator.directive.ts │ │ │ ├── user-register.service.ts │ │ │ ├── user-register.component.ts │ │ │ └── user-register.component.html │ │ ├── model │ │ │ └── user-model.ts │ │ ├── user.routes.ts │ │ └── user.module.ts │ ├── manage │ │ ├── sys-param │ │ │ ├── sys-param.component.scss │ │ │ ├── sys-param.component.spec.ts │ │ │ ├── sys-param.component.ts │ │ │ └── sys-param.component.html │ │ ├── manage-main │ │ │ ├── manage-main.component.scss │ │ │ ├── manage-main.component.spec.ts │ │ │ ├── manage-main.component.ts │ │ │ └── manage-main.component.html │ │ ├── post-table │ │ │ ├── post-table.component.scss │ │ │ ├── post-table.component.spec.ts │ │ │ ├── services │ │ │ │ └── post-table.service.ts │ │ │ ├── post-table.component.ts │ │ │ └── post-table.component.html │ │ ├── user-table │ │ │ ├── user-table.component.scss │ │ │ ├── user-table.component.spec.ts │ │ │ ├── user-table.component.ts │ │ │ └── user-table.component.html │ │ ├── comment-table │ │ │ ├── comment-table.component.scss │ │ │ ├── comment-table.component.spec.ts │ │ │ ├── comment-worker.js │ │ │ ├── comment-table.component.ts │ │ │ └── comment-table.component.html │ │ ├── auth-guard.ts │ │ ├── manage.module.ts │ │ └── manage.routes.ts │ ├── sitestat │ │ ├── sitestat.component.scss │ │ ├── sitestat.component.spec.ts │ │ ├── sitestat.component.ts │ │ └── sitestat.component.html │ ├── index.ts │ ├── post │ │ ├── post-detail-main │ │ │ ├── post-detail-main.component.scss │ │ │ ├── post-detail-main.component.spec.ts │ │ │ ├── post-detail-main.component.html │ │ │ └── post-detail-main.component.ts │ │ ├── write-post │ │ │ ├── write-post.component.scss │ │ │ ├── write-post.component.spec.ts │ │ │ ├── write-post.component.html │ │ │ └── write-post.component.ts │ │ ├── post-detail │ │ │ ├── post-detail.component.scss │ │ │ ├── post-detail.component.spec.ts │ │ │ ├── post-detail.component.html │ │ │ ├── services │ │ │ │ └── post-detail.service.ts │ │ │ └── post-detail.component.ts │ │ ├── model │ │ │ └── post-model.ts │ │ ├── postlist │ │ │ ├── postlist.component.spec.ts │ │ │ ├── postlist.component.scss │ │ │ ├── services │ │ │ │ └── postlist.service.ts │ │ │ ├── postlist.component.html │ │ │ └── postlist.component.ts │ │ ├── post.routes.ts │ │ └── post.module.ts │ ├── chart │ │ ├── chart.component.scss │ │ ├── chart.component.html │ │ ├── echart-option.directive.ts │ │ ├── chart.component.spec.ts │ │ └── chart.component.ts │ ├── comment │ │ ├── model │ │ │ └── comment-model.ts │ │ ├── add-comment │ │ │ ├── add-comment.component.scss │ │ │ ├── add-comment.component.spec.ts │ │ │ ├── add-comment.component.html │ │ │ └── add-comment.component.ts │ │ └── services │ │ │ └── comment.service.ts │ ├── app.component.spec.ts │ ├── utils │ │ └── boolean-pipe.ts │ ├── animations │ │ ├── fade-in.ts │ │ └── fly-in.ts │ ├── jsplumb-demo │ │ ├── jsplumb-demo.component.html │ │ ├── jsplumb-demo.component.spec.ts │ │ ├── jsplumb-demo.component.css │ │ └── jsplumb-demo.component.ts │ ├── shared │ │ ├── post.module.ts │ │ └── shared.module.ts │ ├── app.component.scss │ ├── app.routes.ts │ ├── app.module.ts │ ├── app.component.ts │ └── app.component.html ├── mock-data │ ├── forget-pwd-mock.json │ ├── user-login-mock.json │ ├── user-register-mock.json │ ├── comment-mock.json │ ├── postlist-search-mock.json │ ├── post-mock.json │ └── postlist-mock.json ├── favicon.ico ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── electron │ ├── package.json │ └── main.js ├── main.ts ├── typings.d.ts ├── tsconfig.json ├── styles.scss ├── index.html ├── test.ts └── polyfills.ts ├── .idea └── vcs.xml ├── .editorconfig ├── e2e ├── tsconfig.json └── app.e2e-spec.ts ├── .gitignore ├── protractor.conf.js ├── LICENSE ├── karma.conf.js ├── README.md ├── dir-desc.txt ├── package.json ├── tslint.json └── .angular-cli.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/.npmignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/home/home.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/map/gaode-map/gaode-map.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/use-jquery/use-jquery.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/user/user-info/user-info.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/user/user-main/user-main.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/manage/sys-param/sys-param.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/user/forget-pwd/forget-pwd.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/user/user-profile/user-profile.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/sitestat/sitestat.component.scss: -------------------------------------------------------------------------------- 1 | .site-stat-container{ 2 | 3 | } -------------------------------------------------------------------------------- /src/app/user/user-login/user-login.component.scss: -------------------------------------------------------------------------------- 1 | .user-login-container{ 2 | } -------------------------------------------------------------------------------- /src/mock-data/forget-pwd-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "message":"邮件发送成功,请登录邮箱查看。" 3 | } -------------------------------------------------------------------------------- /src/app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app.component'; 2 | export * from './app.module'; 3 | -------------------------------------------------------------------------------- /src/app/manage/manage-main/manage-main.component.scss: -------------------------------------------------------------------------------- 1 | .manage-main-container{ 2 | 3 | } -------------------------------------------------------------------------------- /src/app/user/user-register/user-register.component.scss: -------------------------------------------------------------------------------- 1 | .user-register-container{ 2 | } -------------------------------------------------------------------------------- /src/app/home/online-contact/online-contact.component.scss: -------------------------------------------------------------------------------- 1 | .online-contact-container{ 2 | 3 | } -------------------------------------------------------------------------------- /src/app/home/social-channel/social-channel.component.scss: -------------------------------------------------------------------------------- 1 | .social-channel-container{ 2 | 3 | } -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/app/post/post-detail-main/post-detail-main.component.scss: -------------------------------------------------------------------------------- 1 | .post-detail-main-container{ 2 | 3 | } -------------------------------------------------------------------------------- /src/app/post/write-post/write-post.component.scss: -------------------------------------------------------------------------------- 1 | .write-post-container{ 2 | padding-right:2px; 3 | } -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/app/post/post-detail/post-detail.component.scss: -------------------------------------------------------------------------------- 1 | .post-detail-container{ 2 | margin-bottom:30px; 3 | } -------------------------------------------------------------------------------- /src/assets/imgs/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/1.png -------------------------------------------------------------------------------- /src/assets/imgs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/2.png -------------------------------------------------------------------------------- /src/assets/imgs/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/3.png -------------------------------------------------------------------------------- /src/assets/imgs/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/4.png -------------------------------------------------------------------------------- /src/assets/imgs/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/5.png -------------------------------------------------------------------------------- /src/assets/imgs/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/6.png -------------------------------------------------------------------------------- /src/assets/imgs/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/7.png -------------------------------------------------------------------------------- /src/assets/imgs/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/8.png -------------------------------------------------------------------------------- /src/assets/imgs/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/9.png -------------------------------------------------------------------------------- /src/app/chart/chart.component.scss: -------------------------------------------------------------------------------- 1 | .nf-chart{ 2 | width:100%; 3 | height:400px; 4 | float:left; 5 | } -------------------------------------------------------------------------------- /src/assets/imgs/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/10.png -------------------------------------------------------------------------------- /src/app/map/gaode-map/amap/amap.component.scss: -------------------------------------------------------------------------------- 1 | .gaodemap-container{ 2 | width:100%; 3 | height:600px; 4 | } -------------------------------------------------------------------------------- /src/app/map/gaode-map/amap/amap.component.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /src/assets/imgs/angular2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/angular2.png -------------------------------------------------------------------------------- /src/mock-data/user-login-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "userName": "admin", 4 | "token": "fake-jwt-token" 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/assets/imgs/angular-weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/angular-weibo.png -------------------------------------------------------------------------------- /src/assets/imgs/angular2-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/angular2-small.png -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/icomoon/icomoon.eot -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/icomoon/icomoon.ttf -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/icomoon/icomoon.woff -------------------------------------------------------------------------------- /src/electron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-electron", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "main": "main.js" 6 | } -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/assets/skins/lightgray/img/anchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/img/anchor.gif -------------------------------------------------------------------------------- /src/assets/skins/lightgray/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/img/loader.gif -------------------------------------------------------------------------------- /src/assets/skins/lightgray/img/object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/img/object.gif -------------------------------------------------------------------------------- /src/assets/skins/lightgray/img/trans.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/img/trans.gif -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/assets/imgs/angular-wechat-channel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/imgs/angular-wechat-channel.jpg -------------------------------------------------------------------------------- /src/assets/skins/lightgray/fonts/tinymce.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/fonts/tinymce.eot -------------------------------------------------------------------------------- /src/assets/skins/lightgray/fonts/tinymce.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/fonts/tinymce.ttf -------------------------------------------------------------------------------- /src/app/manage/post-table/post-table.component.scss: -------------------------------------------------------------------------------- 1 | .post-table-container { 2 | .post-item-container { 3 | padding: 15px 0px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/app/manage/user-table/user-table.component.scss: -------------------------------------------------------------------------------- 1 | .user-table-container { 2 | .user-item-container { 3 | padding: 15px 0px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/skins/lightgray/fonts/tinymce.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/fonts/tinymce.woff -------------------------------------------------------------------------------- /src/mock-data/user-register-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "username": "admin", 4 | "email": "XXXXX@qq.com", 5 | "token":"fake-jwt-token" 6 | } -------------------------------------------------------------------------------- /src/assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/assets/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/icomoon/icomoon/fonts/icomoon.eot -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/icomoon/icomoon/fonts/icomoon.ttf -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/icomoon/icomoon/fonts/icomoon.woff -------------------------------------------------------------------------------- /src/assets/skins/lightgray/fonts/tinymce-small.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/fonts/tinymce-small.eot -------------------------------------------------------------------------------- /src/assets/skins/lightgray/fonts/tinymce-small.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/fonts/tinymce-small.ttf -------------------------------------------------------------------------------- /src/assets/skins/lightgray/fonts/tinymce-small.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/skins/lightgray/fonts/tinymce-small.woff -------------------------------------------------------------------------------- /src/app/manage/comment-table/comment-table.component.scss: -------------------------------------------------------------------------------- 1 | .comment-table-container { 2 | .comment-item-container { 3 | padding: 15px 0px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/fonts/simple-line-icons/Simple-Line-Icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/simple-line-icons/Simple-Line-Icons.eot -------------------------------------------------------------------------------- /src/assets/fonts/simple-line-icons/Simple-Line-Icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/simple-line-icons/Simple-Line-Icons.ttf -------------------------------------------------------------------------------- /src/app/comment/model/comment-model.ts: -------------------------------------------------------------------------------- 1 | export class Comment{ 2 | id: number; 3 | postId: number; 4 | content: string; 5 | date: Date; 6 | username: string; 7 | } -------------------------------------------------------------------------------- /src/assets/fonts/bootstrap/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/bootstrap/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/assets/fonts/simple-line-icons/Simple-Line-Icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/simple-line-icons/Simple-Line-Icons.woff -------------------------------------------------------------------------------- /src/assets/fonts/simple-line-icons/Simple-Line-Icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/simple-line-icons/Simple-Line-Icons.woff2 -------------------------------------------------------------------------------- /src/app/comment/add-comment/add-comment.component.scss: -------------------------------------------------------------------------------- 1 | .add-component-container{ 2 | .comment-item-container{ 3 | padding:15px 0px; 4 | border-bottom: 1px dashed #d9d9d9; 5 | } 6 | } -------------------------------------------------------------------------------- /src/assets/fonts/bootstrap/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/bootstrap/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damoqiongqiu/NiceBlogElectron/HEAD/src/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/app/post/model/post-model.ts: -------------------------------------------------------------------------------- 1 | export class Post { 2 | id: number 3 | title: string 4 | text: string 5 | author: string 6 | postTime: Date 7 | readTimes: number 8 | commentTimes: number 9 | } -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-field/index.ts: -------------------------------------------------------------------------------- 1 | export { FieldBase } from './field-base'; 2 | export { Textbox } from './textbox'; 3 | export { TextArea } from './textarea'; 4 | export { Image } from './image'; -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { AppComponent } from './app.component'; 5 | 6 | describe('App: Angular2BootstrapSass', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/user/model/user-model.ts: -------------------------------------------------------------------------------- 1 | export class User { 2 | id: number; 3 | userName: string; 4 | nickName: string; 5 | password: string; 6 | remeberMe:boolean; 7 | email: string; 8 | confirmPassword: string; 9 | vcode:string; 10 | } -------------------------------------------------------------------------------- /src/app/sitestat/sitestat.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { SitestatComponent } from './sitestat.component'; 5 | 6 | describe('Component: Sitestat', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/post/postlist/postlist.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { PostlistComponent } from './postlist.component'; 5 | 6 | describe('Component: Postlist', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/manage/sys-param/sys-param.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { SysParamComponent } from './sys-param.component'; 5 | 6 | describe('Component: SysParam', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/user/user-info/user-info.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { UserInfoComponent } from './user-info.component'; 5 | 6 | describe('Component: UserInfo', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/user/user-main/user-main.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { UserMainComponent } from './user-main.component'; 5 | 6 | describe('Component: UserMain', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/manage/post-table/post-table.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { PostTableComponent } from './post-table.component'; 5 | 6 | describe('Component: PostTable', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/manage/user-table/user-table.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { UserTableComponent } from './user-table.component'; 5 | 6 | describe('Component: UserTable', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/post/write-post/write-post.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { WritePostComponent } from './write-post.component'; 5 | 6 | describe('Component: WritePost', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/user/forget-pwd/forget-pwd.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { ForgetPwdComponent } from './forget-pwd.component'; 5 | 6 | describe('Component: ForgetPwd', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/user/user-login/user-login.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { UserLoginComponent } from './user-login.component'; 5 | 6 | describe('Component: UserLogin', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/comment/add-comment/add-comment.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { AddCommentComponent } from './add-comment.component'; 5 | 6 | describe('Component: AddComment', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/manage/manage-main/manage-main.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { ManageMainComponent } from './manage-main.component'; 5 | 6 | describe('Component: ManageMain', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/post/post-detail/post-detail.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { PostDetailComponent } from './post-detail.component'; 5 | 6 | describe('Component: PostDetail', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/post/postlist/postlist.component.scss: -------------------------------------------------------------------------------- 1 | .post-list-container { 2 | >form { 3 | margin-bottom: 15px; 4 | } 5 | .post-item-container { 6 | padding-bottom: 20px; 7 | margin-bottom: 30px; 8 | border-bottom: 1px solid #d9d9d9; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/app/user/user-profile/user-profile.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { UserProfileComponent } from './user-profile.component'; 5 | 6 | describe('Component: UserProfile', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/manage/comment-table/comment-table.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { CommentTableComponent } from './comment-table.component'; 5 | 6 | describe('Component: CommentTable', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/user/user-register/user-register.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { UserRegisterComponent } from './user-register.component'; 5 | 6 | describe('Component: UserRegister', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/home/online-contact/online-contact.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { OnlineContactComponent } from './online-contact.component'; 5 | 6 | describe('Component: OnlineContact', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/home/social-channel/social-channel.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { SocialChannelComponent } from './social-channel.component'; 5 | 6 | describe('Component: SocialChannel', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/post/post-detail-main/post-detail-main.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { TestBed, async } from '@angular/core/testing'; 4 | import { PostDetailMainComponent } from './post-detail-main.component'; 5 | 6 | describe('Component: PostDetailMain', () => { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/utils/boolean-pipe.ts: -------------------------------------------------------------------------------- 1 | import {Pipe, PipeTransform} from '@angular/core'; 2 | 3 | @Pipe({ 4 | name: 'boolean' 5 | }) 6 | 7 | export class BooleanPipe implements PipeTransform { 8 | constructor() {} 9 | 10 | transform(flag: string): string { 11 | return flag==="true" ? "text-danger":""; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-field/image.ts: -------------------------------------------------------------------------------- 1 | import { FieldBase } from './field-base'; 2 | 3 | export class Image extends FieldBase { 4 | controlType = 'image'; 5 | src: string; 6 | constructor(options: {} = {}) { 7 | super(options); 8 | this.src = options['src'] || ''; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-field/textarea.ts: -------------------------------------------------------------------------------- 1 | import { FieldBase } from './field-base'; 2 | 3 | export class TextArea extends FieldBase { 4 | controlType = 'textarea'; 5 | rows: number; 6 | constructor(options: {} = {}) { 7 | super(options); 8 | this.rows = options['rows'] || 1; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-field/textbox.ts: -------------------------------------------------------------------------------- 1 | import { FieldBase } from './field-base'; 2 | 3 | export class Textbox extends FieldBase { 4 | controlType = 'textbox'; 5 | type: string; 6 | constructor(options: {} = {}) { 7 | super(options); 8 | this.type = options['type'] || ''; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/app/map/gaode-map/gaode-map.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

请注意,高德地图需要你自己去申请开发者key才能运行,我把架子都搭好了,你自己去高德的主页上申请一个免费的开发者key,修改index.html里面对应的注释,然后打开amap.component.ts里面的代码注释就可以看到地图了!

5 | 6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /src/app/animations/fade-in.ts: -------------------------------------------------------------------------------- 1 | import { trigger, style, transition, animate } from '@angular/animations'; 2 | 3 | export const fadeIn = trigger('fadeIn', [ 4 | transition("void => *", [ 5 | style({ opacity: 0 }), 6 | animate(600, style({ opacity: 1 })) 7 | ]), 8 | transition("* => void", [ 9 | animate(600, style({ opacity: 0 })) 10 | ]) 11 | ]); 12 | -------------------------------------------------------------------------------- /src/app/home/home.routes.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { HomeComponent } from './home.component'; 3 | 4 | export const homeRoutes=[ 5 | { 6 | path:'', 7 | component:HomeComponent, 8 | children:[{ 9 | path:'', 10 | loadChildren:'../post/post.module#PostModule' 11 | }] 12 | } 13 | ]; -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { environment } from './environments/environment'; 4 | import { AppModule } from './app/'; 5 | 6 | if (environment.production) { 7 | enableProdMode(); 8 | } 9 | 10 | platformBrowserDynamic().bootstrapModule(AppModule); 11 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | // Typings reference file, see links for more information 2 | // https://github.com/typings/typings 3 | // https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html 4 | 5 | declare var System: any; 6 | declare var require: NodeRequire; 7 | declare var tinymce: any; 8 | declare var JQuery: any; 9 | declare var jQuery: any; 10 | declare var $: any; -------------------------------------------------------------------------------- /src/app/post/post-detail/post-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

{{ post.title }}

5 |

{{ post.author }} {{ post.postTime }} 点击:{{ post.readTimes }} 评论:{{ post.commentTimes }}

6 |
7 |
8 |
9 |
10 |
11 |
12 |
-------------------------------------------------------------------------------- /src/app/home/online-contact/online-contact.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-online-contact', 5 | templateUrl: './online-contact.component.html', 6 | styleUrls: ['./online-contact.component.scss'] 7 | }) 8 | export class OnlineContactComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/home/social-channel/social-channel.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-social-channel', 5 | templateUrl: './social-channel.component.html', 6 | styleUrls: ['./social-channel.component.scss'] 7 | }) 8 | export class SocialChannelComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { flyIn } from '../animations/fly-in'; 3 | 4 | @Component({ 5 | selector: 'app-home', 6 | templateUrl: './home.component.html', 7 | styleUrls: ['./home.component.scss'], 8 | animations: [ 9 | flyIn 10 | ] 11 | }) 12 | export class HomeComponent implements OnInit { 13 | constructor() { 14 | } 15 | ngOnInit() { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/manage/comment-table/comment-worker.js: -------------------------------------------------------------------------------- 1 | onmessage = event => { 2 | if (event.data && "load" === event.data.action){ 3 | //构造返回结果 4 | let rows = []; 5 | for(let i=1;i<100000;i++){ 6 | rows.push({ 7 | No:i, 8 | content:'内容'+i, 9 | user:'admin', 10 | date:new Date() 11 | }); 12 | } 13 | postMessage({rows}); 14 | } 15 | } -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "lib": [ 8 | "es2016" 9 | ], 10 | "module": "commonjs", 11 | "moduleResolution": "node", 12 | "outDir": "../dist/out-tsc-e2e", 13 | "sourceMap": true, 14 | "target": "es6", 15 | "typeRoots": [ 16 | "../node_modules/@types" 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /src/app/manage/sys-param/sys-param.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { flyIn } from '../../animations/fly-in'; 3 | 4 | @Component({ 5 | selector: 'app-sys-param', 6 | templateUrl: './sys-param.component.html', 7 | styleUrls: ['./sys-param.component.scss'], 8 | animations: [ 9 | flyIn 10 | ] 11 | }) 12 | export class SysParamComponent implements OnInit { 13 | 14 | constructor() { } 15 | 16 | ngOnInit() { 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/app/chart/chart.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /src/app/manage/manage-main/manage-main.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { flyIn } from '../../animations/fly-in'; 3 | 4 | @Component({ 5 | selector: 'app-manage-main', 6 | templateUrl: './manage-main.component.html', 7 | styleUrls: ['./manage-main.component.scss'], 8 | animations: [ 9 | flyIn 10 | ] 11 | }) 12 | export class ManageMainComponent implements OnInit { 13 | 14 | constructor() { } 15 | 16 | ngOnInit() { 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/app/map/gaode-map/gaode-map.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { flyIn } from '../../animations/fly-in'; 3 | import { AmapComponent } from './amap/amap.component'; 4 | 5 | @Component({ 6 | selector: 'app-gaode-map', 7 | templateUrl: './gaode-map.component.html', 8 | styleUrls: ['./gaode-map.component.scss'], 9 | animations:[flyIn] 10 | }) 11 | export class GaodeMapComponent implements OnInit { 12 | constructor() { } 13 | ngOnInit() { 14 | } 15 | } -------------------------------------------------------------------------------- /src/app/chart/echart-option.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef, HostListener, Input, OnInit } from '@angular/core'; 2 | import * as echarts from 'echarts'; 3 | 4 | @Directive({ 5 | selector: 'echart' 6 | }) 7 | export class EChartOptionDirective1 implements OnInit { 8 | @Input('chartType') chartType: any; 9 | 10 | constructor(private el: ElementRef) {} 11 | 12 | public ngOnInit(): void { 13 | echarts.init(this.el.nativeElement).setOption(this.chartType); 14 | } 15 | } -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "lib": ["es6", "dom"], 7 | "mapRoot": "./", 8 | "module": "es6", 9 | "moduleResolution": "node", 10 | "outDir": "../dist/out-tsc", 11 | "sourceMap": true, 12 | "target": "es5", 13 | "typeRoots": [ 14 | "../node_modules/@types" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/sitestat/sitestat.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-sitestat', 5 | templateUrl: './sitestat.component.html', 6 | styleUrls: ['./sitestat.component.scss'] 7 | }) 8 | export class SitestatComponent implements OnInit { 9 | public currentTime: Date = new Date(); 10 | 11 | constructor() { 12 | window.setInterval( 13 | ()=>this.currentTime=new Date() 14 | ,1000); 15 | } 16 | 17 | ngOnInit() { 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/app/post/post-detail-main/post-detail-main.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 | 7 |
8 |
9 | 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /src/app/post/post.routes.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | 3 | import { PostDetailMainComponent } from './post-detail-main/post-detail-main.component'; 4 | import { PostlistComponent } from './postlist/postlist.component'; 5 | 6 | export const postRoutes=[ 7 | { 8 | path:'', 9 | redirectTo:'page/1', 10 | pathMatch:'full' 11 | }, 12 | { 13 | path:'page/:page', 14 | component:PostlistComponent 15 | }, 16 | { 17 | path: 'postdetail/:postId', 18 | component: PostDetailMainComponent 19 | } 20 | ]; -------------------------------------------------------------------------------- /src/app/jsplumb-demo/jsplumb-demo.component.html: -------------------------------------------------------------------------------- 1 |

点击线上的标签文字可修改

2 |
3 |
开始

4 |
提交申请

5 |
审批

6 |
结束

7 |
-------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-control.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit ,Input} from '@angular/core'; 2 | import { FormGroup } from '@angular/forms'; 3 | 4 | import { FieldBase } from './form-field'; 5 | 6 | @Component({ 7 | selector: 'form-control', 8 | templateUrl: 'form-control.component.html' 9 | }) 10 | export class FormControlComponent implements OnInit { 11 | @Input() field: FieldBase; 12 | @Input() form: FormGroup; 13 | 14 | constructor() { } 15 | 16 | ngOnInit() { } 17 | 18 | } -------------------------------------------------------------------------------- /src/mock-data/comment-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "items":[{ 3 | "id":1, 4 | "postId":1, 5 | "content":"这是评论的内容。。。", 6 | "date":"2016-09-09 12:00:09", 7 | "username":"大漠" 8 | },{ 9 | "id":2, 10 | "postId":1, 11 | "content":"这是评论的内容。。。", 12 | "date":"2016-09-09 12:00:09", 13 | "username":"大漠2" 14 | },{ 15 | "id":3, 16 | "postId":1, 17 | "content":"这是评论的内容。。。", 18 | "date":"2016-09-09 12:00:09", 19 | "username":"大漠3" 20 | }] 21 | } -------------------------------------------------------------------------------- /src/app/use-jquery/use-jquery.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, OnInit } from '@angular/core'; 2 | import { fadeIn } from '../animations/fade-in'; 3 | 4 | @Component({ 5 | selector: 'app-use-jquery', 6 | templateUrl: './use-jquery.component.html', 7 | styleUrls: ['./use-jquery.component.scss'], 8 | animations:[ fadeIn ] 9 | }) 10 | export class UseJqueryComponent implements OnInit { 11 | constructor() { 12 | } 13 | 14 | ngOnInit() { 15 | $("#datepicker").datepicker(); 16 | $("#tabs").tabs(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/user/user-profile/user-profile.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/mock-data/postlist-search-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "total":3, 3 | "items":[ 4 | {"postId":"8","title":"这是搜索出来的啊。。。。","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","isfamous":"true"}, 5 | {"postId":"9","title":"这是搜索出来的啊。。。。","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","isfamous":"false"}, 6 | {"postId":"10","title":"这是搜索出来的啊。。。。","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","isfamous":"false"} 7 | ]} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | *.launch 16 | .settings/ 17 | 18 | # misc 19 | /.sass-cache 20 | /connect.lock 21 | /coverage/* 22 | /libpeerconnection.log 23 | npm-debug.log 24 | testem.log 25 | /typings 26 | 27 | # e2e 28 | /e2e/*.js 29 | /e2e/*.map 30 | 31 | #System Files 32 | .DS_Store 33 | Thumbs.db 34 | /*.zip 35 | /.vscode 36 | *.orig 37 | -------------------------------------------------------------------------------- /src/app/sitestat/sitestat.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

{{currentTime | date:'yyyy-MM-dd HH:mm:ss'}}

5 |
6 |
7 |

访问总数:16742169

8 |

文章总数:2458

9 |

评论总数:7880

10 |

会员总数:12772

11 |

在线访客:187

12 |

在线会员:2

13 |

在线记录:268

14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /src/app/user/forget-pwd/forget-pwd.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Headers, Response } from '@angular/http'; 3 | import { Observable } from 'rxjs/Observable'; 4 | import 'rxjs/add/operator/map'; 5 | 6 | @Injectable() 7 | export class ForgetPwdService { 8 | public validateEmailURL = "mock-data/forget-pwd-mock.json"; 9 | 10 | constructor(public http: Http) { } 11 | 12 | public sendValidationEmail(email: string):Observable{ 13 | return this.http.get(this.validateEmailURL) 14 | .map((res: Response) => res.json()); 15 | } 16 | } -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | * { 3 | font-family: '微软雅黑', Microsoft YaHei, '宋体', Tahoma, Helvetica, Arial, sans-serif; 4 | -ms-text-size-adjust: 100%; 5 | -webkit-text-size-adjust: 100%; 6 | } 7 | 8 | body { 9 | font-family: '微软雅黑', Microsoft YaHei, '宋体', Tahoma, Helvetica, Arial, sans-serif; 10 | font-size: 14px; 11 | line-height: 1.5; 12 | } 13 | 14 | html { 15 | min-height: 100%; 16 | position: relative; 17 | padding-bottom: 162px; 18 | } 19 | 20 | @import "~jquery-ui-dist/jquery-ui.css"; 21 | @import "~ng2-toastr/bundles/ng2-toastr.min.css"; -------------------------------------------------------------------------------- /src/app/user/user-info/user-info.component.html: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-field/field-base.ts: -------------------------------------------------------------------------------- 1 | export class FieldBase{ 2 | value: T; 3 | key: string; 4 | label: string; 5 | controlType: string; 6 | placeholder: string; 7 | 8 | constructor(options: { 9 | value?: T, 10 | key?: string, 11 | label?: string, 12 | required?: boolean, 13 | order?: number, 14 | controlType?: string, 15 | placeholder?: string 16 | } = {}) { 17 | this.value = options.value; 18 | this.key = options.key || ''; 19 | this.label = options.label || ''; 20 | this.controlType = options.controlType || ''; 21 | this.placeholder = options.placeholder || ''; 22 | } 23 | } -------------------------------------------------------------------------------- /src/mock-data/post-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "id":1, 3 | "author":"大漠穷秋", 4 | "postTime":"2016-12-12 12:12:12", 5 | "readTimes":999999, 6 | "commentTimes":99999, 7 | "title":"Angular2 自定义组件。。。。。。滴滴答答滴滴答答滴滴答答的", 8 | "text":"

这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。

这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。这文章这么长。。。。

" 9 | } -------------------------------------------------------------------------------- /src/app/user/user-main/user-main.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { flyIn } from '../../animations/fly-in'; 3 | 4 | @Component({ 5 | selector: 'app-user-main', 6 | templateUrl: './user-main.component.html', 7 | styleUrls: ['./user-main.component.scss'], 8 | animations: [ 9 | flyIn 10 | ] 11 | }) 12 | export class UserMainComponent implements OnInit { 13 | 14 | constructor() { } 15 | 16 | ngOnInit() { 17 | } 18 | 19 | onActivate(component) { 20 | console.log("组件加载完成>"+component); 21 | } 22 | 23 | onDeactivate(component) { 24 | console.log("组件已经移除>"+component); 25 | } 26 | 27 | doFollow(){ 28 | alert("自己不能关注自己!"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/comment/services/comment.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers, RequestOptions,URLSearchParams } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs/Rx'; 5 | import 'rxjs/add/operator/map'; 6 | import 'rxjs/add/operator/catch'; 7 | 8 | import { Comment } from '../model/comment-model'; 9 | 10 | @Injectable() 11 | export class CommentService { 12 | public commentListURL = "mock-data/comment-mock.json"; 13 | 14 | constructor(public http: Http) { } 15 | 16 | public getCommentList(postId: number):Observable{ 17 | return this.http.get(this.commentListURL) 18 | .map((res: Response) => res.json()) 19 | } 20 | } -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon/Read Me.txt: -------------------------------------------------------------------------------- 1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. 2 | 3 | To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. 4 | 5 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. 6 | 7 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu > Manage Projects) to retrieve your icon selection. 8 | -------------------------------------------------------------------------------- /src/app/post/post-detail/services/post-detail.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers, RequestOptions,URLSearchParams } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs/Rx'; 5 | import 'rxjs/add/operator/map'; 6 | import 'rxjs/add/operator/catch'; 7 | 8 | import { Post } from '../../model/post-model'; 9 | 10 | @Injectable() 11 | export class PostDetailService { 12 | public postDetailURL = "mock-data/post-mock.json"; 13 | 14 | constructor(public http: Http) { 15 | } 16 | 17 | public getPost(id:number):Observable{ 18 | return this.http 19 | .get(this.postDetailURL) 20 | .map((res: Response) => res.json()); 21 | } 22 | } -------------------------------------------------------------------------------- /src/app/user/user-profile/dynamic-form/form-control.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 7 | 9 | 10 |
11 |
12 |
-------------------------------------------------------------------------------- /src/app/manage/auth-guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router'; 3 | import { UserLoginService } from '../user/user-login/user-login.service'; 4 | 5 | @Injectable() 6 | export class AuthGuard implements CanActivate { 7 | constructor( 8 | private router: Router, 9 | public userLoginService: UserLoginService) { 10 | 11 | } 12 | 13 | canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean { 14 | //这里可以调用真实的服务进行验证 15 | // this.userLoginService.currentUser 16 | // .subscribe( 17 | // data => { 18 | 19 | // }, 20 | // error => console.error(error) 21 | // ); 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/app/map/gaode-map/gaode-map.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { GaodeMapComponent } from './gaode-map.component'; 4 | 5 | describe('GaodeMapComponent', () => { 6 | let component: GaodeMapComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ GaodeMapComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(GaodeMapComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | //【看这里】protractor提供的语法请仔细看这里的文档 2 | // http://www.protractortest.org 3 | 4 | import { browser, element, by } from 'protractor'; 5 | 6 | describe('NiceFish App', function() { 7 | it('这是一个空的测试,什么都没干',()=>{ 8 | console.log("可以开始写测试用例了!"); 9 | }); 10 | 11 | //测试:当访问index.html的时候应该跳转到index.html#/phones这个路由 12 | it('should redirect index.html to index.html#/phones', function() { 13 | //这里的browser对象是由Protractor提供的,大家可以把下面一行注释放开,看看这个对象的内容 14 | //console.log(browser); 15 | //首先利用browser.get()这个接口让浏览器打开app.index.html这个页面 16 | browser.get('app/index.html'); 17 | //然后用browser.getLocationAbsUrl()获取到地址栏的URL,看看是不是转向了/phones这个路径 18 | browser.getLocationAbsUrl().then(function(url) { 19 | expect(url.split('#')[1]).toBe('/phones'); 20 | }); 21 | }); 22 | }); -------------------------------------------------------------------------------- /src/app/use-jquery/use-jquery.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { UseJqueryComponent } from './use-jquery.component'; 4 | 5 | describe('UseJqueryComponent', () => { 6 | let component: UseJqueryComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ UseJqueryComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(UseJqueryComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/jsplumb-demo/jsplumb-demo.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { JsplumbDemoComponent } from './jsplumb-demo.component'; 4 | 5 | describe('JsplumbDemoComponent', () => { 6 | let component: JsplumbDemoComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ JsplumbDemoComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(JsplumbDemoComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/manage/manage-main/manage-main.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /src/app/shared/post.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ModalModule } from 'ng2-bootstrap'; 3 | import { PaginationModule } from 'ng2-bootstrap'; 4 | import { SharedModule } from './shared.module'; 5 | 6 | import { CommentTableComponent } from '../manage/comment-table/comment-table.component'; 7 | import { PostTableComponent } from '../manage/post-table/post-table.component'; 8 | 9 | @NgModule({ 10 | imports:[ 11 | SharedModule, 12 | ModalModule.forRoot(), 13 | PaginationModule.forRoot() 14 | ], 15 | declarations:[ 16 | CommentTableComponent, 17 | PostTableComponent 18 | ], 19 | exports:[ 20 | ModalModule, 21 | PaginationModule, 22 | CommentTableComponent, 23 | PostTableComponent 24 | ] 25 | }) 26 | 27 | export class PostSharedModule { 28 | 29 | } -------------------------------------------------------------------------------- /src/app/home/social-channel/social-channel.component.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /src/app/animations/fly-in.ts: -------------------------------------------------------------------------------- 1 | import { trigger, state, style, transition, animate, keyframes } from '@angular/animations'; 2 | 3 | export const flyIn = trigger('flyIn', [ 4 | state('in', style({transform: 'translateX(0)'})), 5 | transition('void => *', [ 6 | animate(300, keyframes([ 7 | style({opacity: 0, transform: 'translateX(-100%)', offset: 0}), 8 | style({opacity: 1, transform: 'translateX(25px)', offset: 0.3}), 9 | style({opacity: 1, transform: 'translateX(0)', offset: 1.0}) 10 | ])) 11 | ]), 12 | transition('* => void', [ 13 | animate(300, keyframes([ 14 | style({opacity: 1, transform: 'translateX(0)', offset: 0}), 15 | style({opacity: 1, transform: 'translateX(-25px)', offset: 0.7}), 16 | style({opacity: 0, transform: 'translateX(100%)', offset: 1.0}) 17 | ])) 18 | ]) 19 | ]); -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | /*global jasmine */ 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | exports.config = { 8 | allScriptsTimeout: 15000, 9 | specs: [ 10 | './e2e/**/*.e2e-spec.ts' 11 | ], 12 | capabilities: { 13 | 'browserName': 'chrome' 14 | }, 15 | directConnect: true, 16 | baseUrl: 'http://localhost:4200/', 17 | framework: 'jasmine', 18 | jasmineNodeOpts: { 19 | showColors: true, 20 | defaultTimeoutInterval: 15000, 21 | print: function() {} 22 | }, 23 | beforeLaunch: function() { 24 | require('ts-node').register({ 25 | project: 'e2e' 26 | }); 27 | }, 28 | onPrepare() { 29 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { RouterModule } from '@angular/router'; 4 | import { HomeComponent } from './home.component'; 5 | import { SocialChannelComponent } from './social-channel/social-channel.component'; 6 | import { SitestatComponent } from '../sitestat/sitestat.component'; 7 | import { OnlineContactComponent } from './online-contact/online-contact.component'; 8 | 9 | import {homeRoutes} from './home.routes'; 10 | 11 | @NgModule({ 12 | imports: [ 13 | SharedModule, 14 | RouterModule.forChild(homeRoutes) 15 | ], 16 | exports: [], 17 | declarations: [ 18 | HomeComponent, 19 | SocialChannelComponent, 20 | SitestatComponent, 21 | OnlineContactComponent 22 | ], 23 | providers: [], 24 | }) 25 | export class HomeModule { } 26 | -------------------------------------------------------------------------------- /src/app/user/user-main/user-main.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 | 8 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /src/app/chart/chart.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 3 | import { By } from '@angular/platform-browser'; 4 | import { DebugElement } from '@angular/core'; 5 | 6 | import { ChartComponent } from './chart.component'; 7 | 8 | describe('ChartComponent', () => { 9 | // let component: ChartComponent; 10 | // let fixture: ComponentFixture; 11 | 12 | // beforeEach(async(() => { 13 | // TestBed.configureTestingModule({ 14 | // declarations: [ ChartComponent ] 15 | // }) 16 | // .compileComponents(); 17 | // })); 18 | 19 | // beforeEach(() => { 20 | // fixture = TestBed.createComponent(ChartComponent); 21 | // component = fixture.componentInstance; 22 | // fixture.detectChanges(); 23 | // }); 24 | 25 | // it('should create', () => { 26 | // expect(component).toBeTruthy(); 27 | // }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/app/user/user-info/user-info.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; 2 | import { User } from '../model/user-model'; 3 | 4 | @Component({ 5 | selector: 'app-user-info', 6 | templateUrl: './user-info.component.html', 7 | styleUrls: ['./user-info.component.scss'] 8 | }) 9 | export class UserInfoComponent implements OnInit { 10 | @Input() 11 | public panelTitle:string; 12 | 13 | @Output() 14 | public follow = new EventEmitter(); 15 | 16 | public currentUser: User; 17 | 18 | constructor() { 19 | this.currentUser = JSON.parse(localStorage.getItem("currentUser")); 20 | //构造组件的时候,@Input的属性还没有值 21 | console.log(this.panelTitle); 22 | } 23 | 24 | ngOnInit() { 25 | //组件初始化完成之后,panelTitle才会有值 26 | console.log(this.panelTitle); 27 | } 28 | 29 | public followBtnClick(){ 30 | this.follow.emit("follow"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/assets/imgs/angular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .main-nav { 2 | background: #6f5499; 3 | height: 50px; 4 | min-height: 50px; 5 | padding: 0; 6 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.24); 7 | } 8 | 9 | .navbar-toggle { 10 | .icon-bar { 11 | background-color: #fff; 12 | } 13 | } 14 | 15 | .nav > li > a { 16 | color: #fff; 17 | } 18 | 19 | .nav > li.active, 20 | .nav > li > a:hover, 21 | .nav > li > a:focus, 22 | .nav .open > a, 23 | .nav .open > a:hover, 24 | .nav .open > a:focus { 25 | color: #fff; 26 | background-color: #777; 27 | } 28 | 29 | .navbar-brand-my { 30 | color: #fff; 31 | } 32 | 33 | .logo-img { 34 | width: 100%; 35 | height: 100%; 36 | } 37 | 38 | .main-container { 39 | padding-top: 80px; 40 | min-height: 800px; 41 | } 42 | 43 | .footer { 44 | text-align: left; 45 | padding: 40px 48px; 46 | background: #263238; 47 | color: #fff; 48 | position: absolute; 49 | left: 0; 50 | right: 0; 51 | bottom: 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/app/user/user.routes.ts: -------------------------------------------------------------------------------- 1 | import {RouterModule} from "@angular/router"; 2 | import { UserMainComponent } from './user-main/user-main.component'; 3 | import { UserProfileComponent } from './user-profile/user-profile.component'; 4 | import { WritePostComponent } from '../post/write-post/write-post.component'; 5 | import { PostTableComponent } from '../manage/post-table/post-table.component'; 6 | import { CommentTableComponent } from '../manage/comment-table/comment-table.component'; 7 | 8 | export const userRoutes = [ 9 | { 10 | path:'', 11 | component:UserMainComponent, 12 | children: [ 13 | { path: '', redirectTo:'posttable/page/1',pathMatch:'full'}, 14 | { path: 'write', component: WritePostComponent }, 15 | { path: 'posttable/page/:page', component: PostTableComponent }, 16 | { path: 'commenttable/page/:page', component: CommentTableComponent }, 17 | { path: 'profile', component: UserProfileComponent }, 18 | { path:'**', redirectTo:'write' } 19 | ] 20 | } 21 | ]; -------------------------------------------------------------------------------- /src/app/manage/post-table/services/post-table.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers, RequestOptions,URLSearchParams } from '@angular/http'; 3 | import { Observable } from 'rxjs/Rx'; 4 | import 'rxjs/add/operator/map'; 5 | 6 | @Injectable() 7 | export class PostTableService { 8 | public delURL: string = ""; 9 | public toEditURL: string = ""; 10 | 11 | constructor(public http: Http) { } 12 | 13 | public getPostTable(dataURL:string){ 14 | return this.http.get(dataURL) 15 | .map((res:Response) => res.json()) 16 | .catch((error:any) => Observable.throw(error || 'Server error')); 17 | } 18 | 19 | public del(postId: number):Observable{ 20 | return this.http.delete(this.delURL) 21 | .map((res: Response) => res.json()); 22 | } 23 | 24 | public toEdit(postId: number):Observable{ 25 | return this.http.get(this.toEditURL) 26 | .map((res: Response) => res.json()); 27 | } 28 | } -------------------------------------------------------------------------------- /src/app/comment/add-comment/add-comment.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
{{comment.content}}
18 |

{{comment.username}} {{comment.date}}

19 |
20 |
21 |
22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /src/assets/i18n/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "articles": "动态", 4 | "welcome": "欢迎你", 5 | "logout": "退出", 6 | "login": "登录", 7 | "register": "注册", 8 | "doc": "官方文档", 9 | "console": "管理后台" 10 | }, 11 | "post": { 12 | "publish": "发布文章" 13 | }, 14 | "userRegister":{ 15 | "userSignUp":"用户注册", 16 | "userName":"用户名:", 17 | "userName-placeholder":"用户名4到32个字符", 18 | "nickName":"昵称:", 19 | "nickName-placeholder":"昵称2到32个字符", 20 | "email":"常用邮箱:", 21 | "email-placeholder":"常用邮箱,验证后才能登录", 22 | "notice":"【如果您未在收件箱收到验证邮件,请到垃圾箱查收。】", 23 | "password":"密码:", 24 | "password-placeholder":"密码,至少8位", 25 | "repeat-pwd":"重复密码:", 26 | "repeat-pwd-placeholder":"重复密码,两次输入必须一致", 27 | "signUp":"注册" 28 | }, 29 | "userLogin":{ 30 | "userLogin":"用户登录" 31 | }, 32 | "search": "搜索", 33 | "submit": "提交", 34 | "firstPage": "首页", 35 | "lastPage": "末页", 36 | "previousPage": "上一页", 37 | "nextPage": "下一页" 38 | } 39 | -------------------------------------------------------------------------------- /src/app/user/forget-pwd/forget-pwd.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { ForgetPwdService } from './forget-pwd.service'; 4 | import { User } from '../model/user-model'; 5 | import { fadeIn } from '../../animations/fade-in'; 6 | 7 | @Component({ 8 | selector: 'app-forget-pwd', 9 | templateUrl: './forget-pwd.component.html', 10 | styleUrls: ['./forget-pwd.component.scss'], 11 | animations: [ fadeIn ] 12 | }) 13 | export class ForgetPwdComponent implements OnInit { 14 | public user: User = new User(); 15 | public message: string; 16 | public messgeType: string; 17 | constructor( 18 | public forgetPwdService: ForgetPwdService 19 | ) { } 20 | 21 | ngOnInit() { 22 | 23 | } 24 | 25 | public sendValidationEmail():void{ 26 | this.forgetPwdService.sendValidationEmail(this.user.email) 27 | .subscribe( 28 | data => { 29 | this.message = data.message; 30 | this.messgeType = "success"; 31 | }, 32 | error => { 33 | this.message = error.messge; 34 | this.messgeType = "danger"; 35 | } 36 | ); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/app/post/post-detail/post-detail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router, Params } from '@angular/router'; 3 | 4 | import { Post } from '../model/post-model'; 5 | import { PostDetailService } from './services/post-detail.service'; 6 | 7 | @Component({ 8 | selector: 'app-post-detail', 9 | templateUrl: './post-detail.component.html', 10 | styleUrls: ['./post-detail.component.scss'] 11 | }) 12 | export class PostDetailComponent implements OnInit { 13 | public post: Post = new Post(); 14 | 15 | constructor(public postDetailService: PostDetailService, 16 | public activeRoute: ActivatedRoute 17 | ) { 18 | console.log(this.postDetailService); 19 | } 20 | 21 | ngOnInit() { 22 | this.activeRoute.params.subscribe( 23 | params =>this.getPost(params["postId"]) 24 | ); 25 | } 26 | 27 | public getPost(id:number){ 28 | this.postDetailService 29 | .getPost(id) 30 | .subscribe( 31 | data => this.post = data, 32 | error => console.error(error) 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/comment/add-comment/add-comment.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { ActivatedRoute, Router, Params } from '@angular/router'; 3 | 4 | import { CommentService } from '../services/comment.service'; 5 | import { Comment } from '../model/comment-model'; 6 | 7 | @Component({ 8 | selector: 'app-add-comment', 9 | templateUrl: './add-comment.component.html', 10 | styleUrls: ['./add-comment.component.scss'] 11 | }) 12 | export class AddCommentComponent implements OnInit { 13 | public comments: Array; 14 | 15 | constructor( 16 | public commentService: CommentService, 17 | public activeRoute: ActivatedRoute) 18 | { 19 | 20 | } 21 | 22 | ngOnInit() { 23 | this.activeRoute.params.subscribe( 24 | params => this.getCommentList(params["postId"]) 25 | ); 26 | } 27 | 28 | public getCommentList(postId: number){ 29 | this.commentService.getCommentList(postId) 30 | .subscribe( 31 | data => { 32 | this.comments = data["items"] 33 | }, 34 | error => console.error(error) 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 大漠穷秋 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ModuleWithProviders } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule ,ReactiveFormsModule} from '@angular/forms'; 4 | import { TranslateModule } from 'ng2-translate'; 5 | 6 | import { UserLoginComponent } from '../user/user-login/user-login.component'; 7 | import { UserInfoComponent } from '../user/user-info/user-info.component'; 8 | import { UserProfileComponent } from '../user/user-profile/user-profile.component'; 9 | import { FormControlComponent } from '../user/user-profile/dynamic-form/form-control.component'; 10 | 11 | @NgModule({ 12 | imports:[ 13 | CommonModule, 14 | FormsModule, 15 | ReactiveFormsModule, 16 | TranslateModule 17 | ], 18 | declarations:[ 19 | UserLoginComponent, 20 | UserInfoComponent, 21 | UserProfileComponent, 22 | FormControlComponent 23 | ], 24 | exports:[ 25 | CommonModule, 26 | FormsModule, 27 | TranslateModule, 28 | UserLoginComponent, 29 | UserInfoComponent, 30 | UserProfileComponent 31 | ] 32 | }) 33 | 34 | export class SharedModule { 35 | 36 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | NiceFish 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 |

Loading...

24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/app/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from '@angular/router'; 4 | import { ReactiveFormsModule } from '@angular/forms'; 5 | 6 | import { SharedModule } from '../shared/shared.module'; 7 | import { PostSharedModule } from '../shared/post.module'; 8 | 9 | import { AlertModule, AccordionModule } from 'ng2-bootstrap'; 10 | 11 | import { WritePostComponent } from '../post/write-post/write-post.component'; 12 | import { UserMainComponent } from './user-main/user-main.component'; 13 | 14 | import { PostTableService } from '../manage/post-table/services/post-table.service'; 15 | 16 | import { userRoutes } from './user.routes'; 17 | 18 | @NgModule({ 19 | declarations: [ 20 | UserMainComponent, 21 | WritePostComponent 22 | ], 23 | imports: [ 24 | CommonModule, 25 | ReactiveFormsModule, 26 | AlertModule, 27 | AccordionModule, 28 | SharedModule, 29 | PostSharedModule, 30 | RouterModule.forChild(userRoutes) 31 | ], 32 | exports: [ 33 | UserMainComponent 34 | ], 35 | providers: [ 36 | PostTableService 37 | ] 38 | }) 39 | export class UserModule { } -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare var __karma__: any; 17 | declare var require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/app/manage/manage.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { RouterModule } from "@angular/router"; 4 | import { AccordionModule } from 'ng2-bootstrap'; 5 | 6 | import { SharedModule} from '../shared/shared.module'; 7 | import { PostSharedModule } from '../shared/post.module'; 8 | import { ManageMainComponent } from './manage-main/manage-main.component'; 9 | import { UserTableComponent } from './user-table/user-table.component'; 10 | import { SysParamComponent } from './sys-param/sys-param.component'; 11 | 12 | import { PostTableService } from './post-table/services/post-table.service'; 13 | import { AuthGuard } from './auth-guard'; 14 | 15 | import { manageRoutes } from './manage.routes'; 16 | 17 | @NgModule({ 18 | declarations: [ 19 | ManageMainComponent, 20 | UserTableComponent, 21 | SysParamComponent 22 | ], 23 | imports: [ 24 | CommonModule, 25 | AccordionModule, 26 | SharedModule, 27 | PostSharedModule, 28 | RouterModule.forChild(manageRoutes) 29 | ], 30 | exports:[ 31 | ManageMainComponent 32 | ], 33 | providers: [ 34 | PostTableService, 35 | AuthGuard 36 | ] 37 | }) 38 | export class ManageModule { } -------------------------------------------------------------------------------- /src/app/home/online-contact/online-contact.component.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /src/app/manage/manage.routes.ts: -------------------------------------------------------------------------------- 1 | import { ManageMainComponent } from './manage-main/manage-main.component'; 2 | import { PostTableComponent } from './post-table/post-table.component'; 3 | import { CommentTableComponent } from './comment-table/comment-table.component'; 4 | import { UserTableComponent } from './user-table/user-table.component'; 5 | import { UserProfileComponent } from '../user/user-profile/user-profile.component'; 6 | import { SysParamComponent } from './sys-param/sys-param.component'; 7 | import { AuthGuard } from './auth-guard'; 8 | 9 | export const manageRoutes = [ 10 | { 11 | path:'', 12 | component:ManageMainComponent, 13 | canActivate: [AuthGuard], 14 | children: [ 15 | { path: '',redirectTo:'posttable/page/1',pathMatch:'full'}, 16 | { path: 'posttable/page/:page', component: PostTableComponent }, 17 | { path: 'commenttable/page/:page', component: CommentTableComponent }, 18 | { path: 'usertable/page/:page', component: UserTableComponent }, 19 | { path: 'usertable/edituser/:userId', component: UserProfileComponent }, 20 | { path: 'usertable/newuser', component: UserProfileComponent }, 21 | { path: 'sysparam', component: SysParamComponent }, 22 | { path: '**', redirectTo:'posttable/page/1' } 23 | ] 24 | } 25 | ]; -------------------------------------------------------------------------------- /src/app/user/user-register/directives/equal-validator.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive,Input } from '@angular/core'; 2 | import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; 3 | 4 | 5 | @Directive({ 6 | selector: '[validateEqual]', 7 | providers: [ 8 | { provide: NG_VALIDATORS, useExisting: EqualValidator, multi: true } 9 | ] 10 | }) 11 | export class EqualValidator implements Validator { 12 | @Input()validateEqual: string; 13 | @Input()reverse: boolean; 14 | constructor() { } 15 | 16 | validate(control: AbstractControl): { [key: string]: any } { 17 | //当前控件的值 18 | let selfValue = control.value; 19 | 20 | // 需要比较的控件,根据属性名称获取 21 | let targetControl = control.root.get(this.validateEqual); 22 | // 值不相等 23 | if (targetControl && selfValue !== targetControl.value ) { 24 | if(!this.reverse){ 25 | return { 26 | validateEqual: false 27 | } 28 | }else{ 29 | targetControl.setErrors({ 30 | validateEqual: false 31 | }) 32 | } 33 | }else{//值相等,清空错误信息 34 | targetControl.setErrors(null); 35 | } 36 | return null; 37 | } 38 | } -------------------------------------------------------------------------------- /src/app/post/write-post/write-post.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | 7 |
8 |
9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /src/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app":{ 3 | "welcome":"Welcome", 4 | "logout":"Logout", 5 | "login":"Login", 6 | "register":"Register", 7 | "articles":"Articles", 8 | "doc":"Document", 9 | "console":"Console" 10 | }, 11 | "post":{ 12 | "publish":"publish" 13 | }, 14 | "userRegister":{ 15 | "userSignUp":"User Sign Up", 16 | "userName":"UserName:", 17 | "userName-placeholder":"4-32 characters", 18 | "nickName":"NickName:", 19 | "nickName-placeholder":"2-32 characters", 20 | "email":"Email:", 21 | "email-placeholder":"Frequently used mailboxes, sign in after verification.", 22 | "notice":"If you do not receive a verification email in your inbox, check your trash.", 23 | "password":"Password:", 24 | "password-placeholder":"Password, at least 8 characters.", 25 | "repeat-pwd":"Repeat PWD:", 26 | "repeat-pwd-placeholder":"Repeat password, two inputs must be consistent.", 27 | "signUp":"SignUp" 28 | }, 29 | "userLogin":{ 30 | "userLogin":"User Login" 31 | }, 32 | "search":"search", 33 | "submit":"Submit", 34 | "firstPage":"First", 35 | "lastPage":"Last", 36 | "previousPage":"Previous", 37 | "nextPage":"Next" 38 | } -------------------------------------------------------------------------------- /src/app/map/gaode-map/amap/amap.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: 'amap', 6 | templateUrl: 'amap.component.html', 7 | styleUrls: ['amap.component.scss'] 8 | }) 9 | export class AmapComponent implements OnInit { 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | // let map = new AMap.Map('gaodemap-container'); 14 | // map.plugin('AMap.Geolocation', () => { 15 | // let geolocation = new AMap.Geolocation({ 16 | // enableHighAccuracy: true,//是否使用高精度定位,默认:true 17 | // timeout: 10000, //超过10秒后停止定位,默认:无穷大 18 | // maximumAge: 0, //定位结果缓存0毫秒,默认:0 19 | // convert: true, //自动偏移坐标,偏移后的坐标为高德坐标,默认:true 20 | // showButton: true, //显示定位按钮,默认:true 21 | // buttonPosition: 'LB', //定位按钮停靠位置,默认:'LB',左下角 22 | // buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20) 23 | // showMarker: true, //定位成功后在定位到的位置显示点标记,默认:true 24 | // showCircle: true, //定位成功后用圆圈表示定位精度范围,默认:true 25 | // panToLocation: true, //定位成功后将定位到的位置作为地图中心点,默认:true 26 | // zoomToAccuracy: true //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false 27 | // }); 28 | // map.addControl(geolocation); 29 | // }); 30 | } 31 | } -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular/cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | files: [ 19 | { pattern: './src/test.ts', watched: false } 20 | ], 21 | preprocessors: { 22 | './src/test.ts': ['@angular/cli'] 23 | }, 24 | mime: { 25 | 'text/x-typescript': ['ts','tsx'] 26 | }, 27 | coverageIstanbulReporter: { 28 | reports: [ 'html', 'lcovonly' ], 29 | fixWebpackSourcePaths: true 30 | }, 31 | angularCli: { 32 | config: './.angular-cli.json', 33 | environment: 'dev' 34 | }, 35 | reporters: config.angularCli && config.angularCli.codeCoverage 36 | ? ['progress', 'coverage-istanbul'] 37 | : ['progress', 'kjhtml'], 38 | port: 9876, 39 | colors: true, 40 | logLevel: config.LOG_INFO, 41 | autoWatch: true, 42 | browsers: ['Chrome'], 43 | singleRun: false 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /src/app/user/forget-pwd/forget-pwd.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

找回密码

5 |
6 |
7 |
8 |
9 | 10 |
11 | 12 |
请输入注册时使用的邮箱。
13 |
14 |
15 |
16 |
17 | 18 |
19 |
20 |
21 |
{{message}}
22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /src/app/post/post.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule} from '../shared/shared.module'; 3 | import { RouterModule } from '@angular/router'; 4 | import { PaginationModule } from 'ng2-bootstrap'; 5 | 6 | import { PostDetailComponent } from './post-detail/post-detail.component'; 7 | import { PostlistComponent } from './postlist/postlist.component'; 8 | import { PostlistService } from './postlist/services/postlist.service'; 9 | import { PostDetailService } from './post-detail/services/post-detail.service'; 10 | import { PostDetailMainComponent } from './post-detail-main/post-detail-main.component'; 11 | import { AddCommentComponent } from '../comment/add-comment/add-comment.component'; 12 | import { CommentService } from '../comment/services/comment.service'; 13 | import { BooleanPipe } from '../utils/boolean-pipe'; 14 | 15 | import {postRoutes} from './post.routes'; 16 | 17 | @NgModule({ 18 | imports: [ 19 | SharedModule, 20 | RouterModule, 21 | PaginationModule.forRoot(), 22 | RouterModule.forChild(postRoutes) 23 | ], 24 | exports: [BooleanPipe], 25 | declarations: [ 26 | PostlistComponent, 27 | PostDetailMainComponent, 28 | PostDetailComponent, 29 | AddCommentComponent, 30 | BooleanPipe 31 | ], 32 | providers: [ 33 | PostlistService, 34 | PostDetailService, 35 | CommentService 36 | ] 37 | }) 38 | export class PostModule { } 39 | -------------------------------------------------------------------------------- /src/app/post/postlist/services/postlist.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers, RequestOptions,URLSearchParams } from '@angular/http'; 3 | import { Observable } from 'rxjs/Rx'; 4 | 5 | import 'rxjs/add/operator/map'; 6 | import 'rxjs/add/operator/catch'; 7 | 8 | import { Post } from '../../model/post-model'; 9 | 10 | @Injectable() 11 | export class PostlistService { 12 | public postListURL = 'mock-data/postlist-mock.json'; 13 | public postListSearchURL = 'mock-data/postlist-search-mock.json'; 14 | 15 | constructor(public http:Http) { } 16 | 17 | public getPostList(searchText: string,page:number=1):Observable{ 18 | let url = this.postListURL; 19 | let params = new URLSearchParams(); 20 | if (searchText) { 21 | params.set('searchText',searchText); 22 | url = this.postListSearchURL; 23 | console.log(`searchText=${searchText}`); 24 | } 25 | params.set('page',String(page)); 26 | 27 | return this.http 28 | .get(url,{search:params}) 29 | .map((res:Response) => { 30 | let result=res.json(); 31 | console.log(result); 32 | return result; 33 | }) 34 | .catch((error:any) => Observable.throw(error || 'Server error')); 35 | } 36 | 37 | public getPostNumber():number{ 38 | return 0; 39 | } 40 | 41 | public addPost(user:any){ 42 | 43 | } 44 | 45 | public search() { 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/app/manage/user-table/user-table.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { flyIn } from '../../animations/fly-in'; 4 | 5 | @Component({ 6 | selector: 'app-user-table', 7 | templateUrl: './user-table.component.html', 8 | styleUrls: ['./user-table.component.scss'], 9 | animations: [ 10 | flyIn 11 | ] 12 | }) 13 | export class UserTableComponent implements OnInit { 14 | public maxSize:number = 5; 15 | public itemsPerPage:number=5; 16 | public totalItems:number = 15; 17 | public currentPage:number = 1; 18 | public numPages 19 | 20 | constructor(public router: Router, 21 | public activeRoute: ActivatedRoute) { 22 | } 23 | 24 | ngOnInit() { 25 | this.activeRoute.params.subscribe( 26 | params =>this.getUsersByPage(params["page"]) 27 | ); 28 | } 29 | 30 | public getUsersByPage(page:Number):void{ 31 | console.log("页码>"+page); 32 | } 33 | 34 | public pageChanged(event):void{ 35 | this.router.navigateByUrl("manage/usertable/page/"+event.page); 36 | } 37 | 38 | public newUser():void{ 39 | this.router.navigateByUrl("manage/usertable/newuser"); 40 | } 41 | 42 | public blockUser(userId:Number):void{ 43 | console.log(userId); 44 | } 45 | 46 | public unBlockUser(userId:Number):void{ 47 | console.log(userId); 48 | } 49 | 50 | public resetPwd(userId:Number):void{ 51 | console.log(userId); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/app/user/user-login/user-login.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Observable } from 'rxjs/Observable'; 3 | import { Subject } from 'rxjs/Subject'; 4 | import { Http, Headers, Response } from '@angular/http'; 5 | import { User } from '../model/user-model'; 6 | 7 | @Injectable() 8 | export class UserLoginService { 9 | public userLoginURL = 'mock-data/user-login-mock.json'; 10 | public subject: Subject = new Subject(); 11 | 12 | constructor(public http:Http){} 13 | 14 | public get currentUser():Observable{ 15 | return this.subject.asObservable(); 16 | } 17 | 18 | public login(user:User){ 19 | return this.http 20 | .get(this.userLoginURL) 21 | .map((response: Response) => { 22 | let user = response.json(); 23 | console.log("user object>"+user); 24 | if(user && user.token){ 25 | localStorage.setItem("currentUser",JSON.stringify(user)); 26 | this.subject.next(Object.assign({},user)); 27 | } 28 | return response; 29 | }) 30 | .subscribe( 31 | data => { 32 | console.log("login success>"+data); 33 | }, 34 | error => { 35 | console.error(error); 36 | } 37 | ); 38 | } 39 | 40 | public logout():void{ 41 | localStorage.removeItem("currentUser"); 42 | this.subject.next(Object.assign({})); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NiceBlogElectron(耐思博客桌面应用) 2 | 3 | NiceBlog is a series projects about a personal technology blog, Which was based on the project of @AngularClass's "angular-starter" and the project of @Funoqiongqiu's "NiceFish". 4 | 5 | - [NiceBlog]:The main App of the series projects,Front-end is based on Angular4 + bootstrap + Webpack。http://github.com/CN-Tower/NiceBlog 6 | 7 | - [NiceBlogAdmin]:This is the system admin interface of NiceBlog,based on AngularCLI + MaterialUI。http://github.com/CN-Tower/NiceBlogAdmin 8 | 9 | - [NiceBlogIonic]:The mobile App of NiceBlog, based on Ionic。http://github.com/CN-Tower/NiceBlogIonic 10 | 11 | - [NiceBlogElectron]:The Desk Top App of NiceBlog, based on Electron。http://github.com/CN-Tower/NiceBlogElectron 12 | 13 | - [NiceBlogBackEnd]:The back-end server of NiceBlog,based on NodeJS + Express + MongoDB。http://github.com/CN-Tower/NiceBlogBackEnd 14 | 15 | Love To Research and Happy To Share! Join me, and enjoy it :-) 16 | 17 | ### download the windows installer 18 | Link: https://github.com/CN-Tower/NiceBlogElectron/wiki/Win-Installer 19 | 20 | ### Quick start 21 | **Make sure you have Node version >= 6.0 and NPM >= 3** 22 | 23 | ```bash 24 | # clone our repo 25 | git clone https://github.com/CN-Tower/NiceBlogElectron.git 26 | 27 | # change directory to our repo 28 | cd NiceBlogElectron 29 | 30 | # install the repo with npm 31 | npm install 32 | 33 | # start the server 34 | npm start 35 | 36 | # package you app 37 | npm run package 38 | 39 | # if you're in China use cnpm 40 | # https://github.com/cnpm/cnpm 41 | ``` 42 | -------------------------------------------------------------------------------- /dir-desc.txt: -------------------------------------------------------------------------------- 1 | ├─app 2 | │ ├─animations //这里定义了动画效果 3 | │ ├─comment //这里是添加评论组件 4 | │ │ ├─add-comment 5 | │ │ ├─model 6 | │ │ └─services 7 | │ ├─home //这是首页组件 8 | │ │ ├─online-contact 9 | │ │ └─social-channel 10 | │ ├─manage //这是管理员后台组件 11 | │ │ ├─comment-table 12 | │ │ ├─manage-main 13 | │ │ ├─post-table 14 | │ │ │ └─services 15 | │ │ ├─sys-param 16 | │ │ └─user-table 17 | │ ├─post //这是跟文章有关的组件 18 | │ │ ├─model 19 | │ │ ├─post-detail 20 | │ │ │ └─services 21 | │ │ ├─post-detail-main 22 | │ │ ├─postlist 23 | │ │ │ └─services 24 | │ │ └─write-post //这是写文章组件,需要参考TinyMCE编辑器和ng2集成的请看这里 25 | │ ├─shared 26 | │ ├─sitestat 27 | │ ├─user //这里是与用户相关的组件 28 | │ │ ├─forget-pwd 29 | │ │ ├─model 30 | │ │ ├─user-info //@Input和@Output的用法请参考这个目录 31 | │ │ ├─user-login //模板驱动型表单请参考这个目录 32 | │ │ ├─user-main 33 | │ │ ├─user-profile //动态表单请参考这个目录 34 | │ │ │ └─dyn-form 35 | │ │ │ └─field 36 | │ │ └─user-register //响应式表单请参考这个目录 37 | │ │ └─directives 38 | │ └─utils 39 | ├─assets //这个目录里面是一些CSS、字体图标、图片等 40 | │ ├─bootstrap-v3.3.7 41 | │ ├─css 42 | │ ├─fonts 43 | │ │ ├─bootstrap 44 | │ │ ├─icomoon 45 | │ │ │ └─icomoon 46 | │ │ │ ├─demo-files 47 | │ │ │ └─fonts 48 | │ │ └─simple-line-icons 49 | │ ├─i18n 50 | │ ├─imgs 51 | │ └─skins 52 | │ └─lightgray 53 | │ ├─fonts 54 | │ └─img 55 | ├─documentation 56 | ├─environments 57 | └─mock-data //测试数据全部放在这个目录里面,【注意】这个目录需要你手动拷贝到Tomcat去 -------------------------------------------------------------------------------- /src/app/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { By } from '@angular/platform-browser'; 3 | import { DebugElement } from '@angular/core'; 4 | import { NO_ERRORS_SCHEMA } from '@angular/core'; 5 | import { HomeComponent } from './home.component'; 6 | import { SocialChannelComponent } from './social-channel/social-channel.component'; 7 | import { SitestatComponent } from '../sitestat/sitestat.component'; 8 | import { OnlineContactComponent } from './online-contact/online-contact.component'; 9 | import { SharedModule } from '../shared/shared.module'; 10 | 11 | import {homeRoutes} from './home.routes'; 12 | 13 | describe('Component: Home', () => { 14 | let component: HomeComponent; 15 | let fixture: ComponentFixture; 16 | 17 | beforeEach(async(() => { 18 | TestBed.configureTestingModule({ 19 | imports: [ 20 | SharedModule 21 | ], 22 | declarations: [ 23 | HomeComponent 24 | // , 25 | // SocialChannelComponent, 26 | // SitestatComponent, 27 | // OnlineContactComponent 28 | ], 29 | schemas: [ NO_ERRORS_SCHEMA ] 30 | }) 31 | .compileComponents(); 32 | })); 33 | 34 | beforeEach(() => { 35 | fixture = TestBed.createComponent(HomeComponent); 36 | component = fixture.componentInstance; 37 | fixture.detectChanges(); 38 | }); 39 | 40 | it('should create', () => { 41 | expect(component).toBeTruthy(); 42 | }); 43 | 44 | it('true is true', () => { 45 | expect(true).toBe(false); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/app/user/user-register/user-register.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Headers, Request, RequestOptions, Response, RequestMethod, URLSearchParams } from '@angular/http'; 3 | import { Observable } from 'rxjs/Observable'; 4 | import { Subject } from 'rxjs/Subject'; 5 | 6 | import { User } from '../model/user-model'; 7 | 8 | @Injectable() 9 | export class UserRegisterService { 10 | public userRegisterURL = "mock-data/user-register-mock.json"; 11 | public testEmailURL = ""; 12 | public subject: Subject = new Subject(); 13 | 14 | constructor(public http:Http) { 15 | } 16 | 17 | public get currentUser():Observable{ 18 | return this.subject.asObservable(); 19 | } 20 | 21 | public register(user: User){ 22 | console.log(user); 23 | 24 | //向后台post数据的写法如下 25 | // let data = new URLSearchParams(); 26 | // data.append('email', user.email); 27 | // data.append('password', user.password); 28 | // return this.http.post(this.userRegisterURL,data); 29 | 30 | return this.http 31 | .get(this.userRegisterURL) 32 | .map((response: Response) => { 33 | let user = response.json(); 34 | localStorage.setItem("currentUser",JSON.stringify(user)); 35 | this.subject.next(user); 36 | }); 37 | } 38 | 39 | public testEmail(email:string){ 40 | return this.http.get(this.testEmailURL) 41 | .map((response: Response) => response.json()); 42 | } 43 | } -------------------------------------------------------------------------------- /src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | 3 | import { AppComponent } from './app.component'; 4 | import { UserLoginComponent } from './user/user-login/user-login.component'; 5 | import { ForgetPwdComponent } from './user/forget-pwd/forget-pwd.component'; 6 | import { UserRegisterComponent } from './user/user-register/user-register.component'; 7 | import { ChartComponent } from './chart/chart.component'; 8 | import { GaodeMapComponent } from './map/gaode-map/gaode-map.component'; 9 | import { UseJqueryComponent } from './use-jquery/use-jquery.component'; 10 | import { JsplumbDemoComponent } from './jsplumb-demo/jsplumb-demo.component'; 11 | 12 | export const appRoutes=[ 13 | { 14 | path:'', 15 | redirectTo:'posts', 16 | pathMatch:'full' 17 | }, 18 | { 19 | path:"echart", 20 | component:ChartComponent 21 | }, 22 | { 23 | path:"map", 24 | component:GaodeMapComponent 25 | }, 26 | { 27 | path:'home', 28 | loadChildren:'./home/home.module#HomeModule' 29 | }, 30 | { 31 | path:'posts', 32 | loadChildren:'./home/home.module#HomeModule' 33 | }, 34 | { 35 | path:'post', 36 | loadChildren:'./post/post.module#PostModule' 37 | }, 38 | { 39 | path:'login', 40 | component:UserLoginComponent 41 | }, 42 | { 43 | path:'forgetpwd', 44 | component:ForgetPwdComponent 45 | }, 46 | { 47 | path:'register', 48 | component:UserRegisterComponent 49 | }, 50 | { 51 | path:'user', 52 | loadChildren:'./user/user.module#UserModule' 53 | }, 54 | { 55 | path: 'manage', 56 | loadChildren:'./manage/manage.module#ManageModule' 57 | }, 58 | { 59 | path: 'jquery', 60 | component:UseJqueryComponent 61 | },{ 62 | path:'jsplumb', 63 | component:JsplumbDemoComponent 64 | }, 65 | { 66 | path:'**',//fallback router must in the last 67 | loadChildren:'./home/home.module#HomeModule' 68 | } 69 | ]; 70 | -------------------------------------------------------------------------------- /src/app/user/user-login/user-login.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit,Input } from '@angular/core'; 2 | import { ActivatedRoute, Router, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot } from '@angular/router'; 3 | import { UserLoginService } from './user-login.service'; 4 | import { Observable } from 'rxjs/Observable'; 5 | 6 | import { User } from '../model/user-model'; 7 | import { fadeIn } from '../../animations/fade-in'; 8 | 9 | @Component({ 10 | selector: 'app-user-login', 11 | templateUrl: './user-login.component.html', 12 | styleUrls: ['./user-login.component.scss'], 13 | animations: [ fadeIn ] 14 | }) 15 | export class UserLoginComponent implements OnInit { 16 | public user:User = new User(); 17 | public error : Error; 18 | 19 | constructor( 20 | public router: Router, 21 | public activatedRoute: ActivatedRoute, 22 | public userLoginService: UserLoginService 23 | ) { 24 | console.log(this.userLoginService); 25 | } 26 | 27 | ngOnInit() { 28 | console.log("--- user-login-component ---"); 29 | console.log(this.router); 30 | console.log(this.activatedRoute); 31 | 32 | let activatedRouteSnapshot:ActivatedRouteSnapshot=this.activatedRoute.snapshot; 33 | let routerState: RouterState = this.router.routerState; 34 | let routerStateSnapshot: RouterStateSnapshot = routerState.snapshot; 35 | 36 | console.log(activatedRouteSnapshot); 37 | console.log(routerState); 38 | console.log(routerStateSnapshot); 39 | } 40 | 41 | public doLogin():void{ 42 | console.log(this.user); 43 | this.userLoginService.login(this.user); 44 | } 45 | 46 | public doLogout():void{ 47 | this.userLoginService.logout(); 48 | this.router.navigateByUrl("home"); 49 | } 50 | 51 | public forgetPwd():void{ 52 | this.router.navigateByUrl("forgetpwd"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/user/user-profile/user-profile.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { FormControl, FormGroup, Validators } from '@angular/forms'; 3 | import { ActivatedRoute, Router } from '@angular/router'; 4 | 5 | import { FieldBase, Textbox, TextArea, Image } from './dynamic-form/form-field'; 6 | 7 | @Component({ 8 | selector: 'app-user-profile', 9 | templateUrl: './user-profile.component.html', 10 | styleUrls: ['./user-profile.component.scss'] 11 | }) 12 | export class UserProfileComponent implements OnInit { 13 | 14 | @Input() fields: FieldBase[] = [ 15 | new Image({ 16 | src: "assets/imgs/angular2-small.png" 17 | }), 18 | new Textbox({ 19 | label: "头像:", 20 | placeholder: "上传头像", 21 | type: "file" 22 | }), 23 | new Textbox({ 24 | label: "用户名:", 25 | placeholder: "用户名" 26 | }), 27 | new Textbox({ 28 | label: "常用邮箱:", 29 | placeholder: "常用邮箱" 30 | }), 31 | new Textbox({ 32 | label: "密码:", 33 | type: "password", 34 | placeholder: "密码,至少8位" 35 | }), 36 | new Textbox({ 37 | label: "重复密码:", 38 | type: "password", 39 | placeholder: "重复密码" 40 | }), 41 | new TextArea({ 42 | label: "个人简介:", 43 | placeholder: "个人简介,最多140字,不能放链接。", 44 | rows: 3, 45 | }) 46 | ]; 47 | 48 | public form: FormGroup; 49 | 50 | constructor(public router: Router, 51 | public activeRoute: ActivatedRoute) { 52 | 53 | } 54 | 55 | ngOnInit() { 56 | this.form = this.toFormGroup(this.fields); 57 | 58 | this.activeRoute.params.subscribe( 59 | params => { console.log(params) } 60 | ); 61 | } 62 | 63 | toFormGroup(fields: FieldBase[]) { 64 | let group: any = {}; 65 | 66 | fields.forEach(field => { 67 | group[field.key] = new FormControl(field.value || ''); 68 | }); 69 | return new FormGroup(group); 70 | } 71 | } -------------------------------------------------------------------------------- /src/app/manage/comment-table/comment-table.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router, UrlTree, PRIMARY_OUTLET, UrlSegmentGroup, UrlSegment } from '@angular/router'; 3 | import { flyIn } from '../../animations/fly-in'; 4 | 5 | @Component({ 6 | selector: 'app-comment-table', 7 | templateUrl: './comment-table.component.html', 8 | styleUrls: ['./comment-table.component.scss'], 9 | animations: [ 10 | flyIn 11 | ] 12 | }) 13 | export class CommentTableComponent implements OnInit { 14 | public maxSize: number = 5; 15 | public itemsPerPage: number = 5; 16 | public totalItems: number = 15; 17 | public currentPage: number = 1; 18 | public numPages 19 | public worker: Worker; 20 | 21 | constructor(public router: Router, 22 | public activeRoute: ActivatedRoute) { 23 | 24 | } 25 | 26 | ngOnInit() { 27 | this.activeRoute.params.subscribe( 28 | params => this.getCommentsByPage(params["page"]) 29 | ); 30 | 31 | //启动web worker 加载数据 32 | this.worker = new Worker('src/app/manage/comment-table/comment-worker.js'); 33 | this.worker.postMessage({ action: "load" }); 34 | //注册事件 35 | this.worker.addEventListener('message', (event: MessageEvent) => { 36 | console.log(event); 37 | }); 38 | this.worker.addEventListener('error', (event: MessageEvent) => { 39 | console.error(event); 40 | }); 41 | } 42 | 43 | public getCommentsByPage(page: Number): void { 44 | console.log("页码>" + page); 45 | } 46 | 47 | public pageChanged(event: any): void { 48 | let urlTree: UrlTree = this.router.parseUrl(this.router.url); 49 | const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET]; 50 | const s: UrlSegment[] = g.segments; 51 | this.router.navigateByUrl(s[0] + "/commenttable/page/" + event.page); 52 | } 53 | 54 | public delComment(commentId: Number): void { 55 | console.log(commentId); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/mock-data/postlist-mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "total":20, 3 | "items":[ 4 | {"postId":"1","title":"这玩意必须用严格的JSON格式,我也是醉了","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"true"}, 5 | {"postId":"2","title":"Key和Value都必须用双引号!","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 6 | {"postId":"3","title":"这玩意必须用严格的JSON格式,我也是醉了","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 7 | {"postId":"4","title":"Key和Value都必须用双引号!","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 8 | {"postId":"5","title":"这玩意必须用严格的JSON格式,我也是醉了","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 9 | {"postId":"6","title":"Key和Value都必须用双引号!","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 10 | {"postId":"7","title":"这玩意必须用严格的JSON格式,我也是醉了","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 11 | {"postId":"8","title":"Key和Value都必须用双引号!","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 12 | {"postId":"9","title":"t666","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"}, 13 | {"postId":"10","title":"和上面的不一样啊。。。。","postTime":"2016-11-21 10:44","userName":"大漠穷秋","userId":"1","readTimes":"10000","commentTimes":"10000","likedTimes":"5555","isfamous":"false"} 14 | ]} -------------------------------------------------------------------------------- /src/app/post/post-detail-main/post-detail-main.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit} from '@angular/core'; 2 | import { ActivatedRoute, Router, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot } from '@angular/router'; 3 | import { flyIn } from '../../animations/fly-in'; 4 | import { UserLoginService } from '../../user/user-login/user-login.service'; 5 | import { UserInfoComponent } from '../../user/user-info/user-info.component'; 6 | import { Subscription } from 'rxjs/Subscription'; 7 | 8 | @Component({ 9 | selector: 'app-post-detail-main', 10 | templateUrl: './post-detail-main.component.html', 11 | styleUrls: ['./post-detail-main.component.scss'], 12 | animations: [ 13 | flyIn 14 | ] 15 | }) 16 | export class PostDetailMainComponent implements OnInit { 17 | private subscription:Subscription; 18 | 19 | constructor( 20 | public router: Router, 21 | public activatedRoute: ActivatedRoute, 22 | public userLoginService: UserLoginService) { 23 | 24 | } 25 | 26 | ngOnInit() { 27 | this.subscription=this.userLoginService.currentUser 28 | .subscribe( 29 | data => { 30 | let activatedRouteSnapshot:ActivatedRouteSnapshot=this.activatedRoute.snapshot; 31 | let routerState: RouterState = this.router.routerState; 32 | let routerStateSnapshot: RouterStateSnapshot = routerState.snapshot; 33 | 34 | console.log(activatedRouteSnapshot); 35 | console.log(routerState); 36 | console.log(routerStateSnapshot); 37 | 38 | //如果是从/login这个URL进行的登录,什么都不做 39 | if(routerStateSnapshot.url.indexOf("/login")==-1){ 40 | alert("用户登录成功,可以隐藏登录面板了!"); 41 | } 42 | }, 43 | error =>{ 44 | console.error(error); 45 | } 46 | ); 47 | } 48 | 49 | ngOnDestroy(){ 50 | this.subscription.unsubscribe(); 51 | } 52 | 53 | doFollow(){ 54 | alert("父组件监听子组件的事件..."); 55 | } 56 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NiceFish", 3 | "version": "0.0.8", 4 | "license": "MIT", 5 | "scripts": { 6 | "build-electron": "ng build --base-href . && node build/electron.conf.js", 7 | "start": "npm run build-electron && electron dist", 8 | "package": "npm run start && electron-packager ./dist NiceFish --platform=win32 --out ./build/package --verson=0.0.1 --overwrite --icon=./assets/imgs/nicefish.ico", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "^4.0.2", 16 | "@angular/common": "^4.0.2", 17 | "@angular/compiler": "^4.0.2", 18 | "@angular/core": "^4.0.2", 19 | "@angular/forms": "^4.0.2", 20 | "@angular/http": "^4.0.2", 21 | "@angular/platform-browser": "^4.0.2", 22 | "@angular/platform-browser-dynamic": "^4.0.2", 23 | "@angular/router": "^4.0.2", 24 | "core-js": "2.4.1", 25 | "datatables.net": "^1.10.13", 26 | "echarts": "^3.4.0", 27 | "jquery": "^3.1.1", 28 | "jquery-ui-dist": "^1.12.1", 29 | "jsplumb": "^2.3.2", 30 | "ng2-bootstrap": "1.6.3", 31 | "ng2-toastr": "^4.0.1", 32 | "ng2-translate": "5.0.0", 33 | "portfinder": "1.0.13", 34 | "rxjs": "^5.4.2", 35 | "tinymce": "4.5.6", 36 | "ts-helpers": "1.1.2", 37 | "zone.js": "0.8.8" 38 | }, 39 | "devDependencies": { 40 | "@angular/cli": "1.0.1", 41 | "@angular/compiler-cli": "^4.0.2", 42 | "@types/jasmine": "2.5.47", 43 | "@types/node": "7.0.13", 44 | "codelyzer": "3.0.0", 45 | "electron": "^1.6.11", 46 | "electron-packager": "^8.7.2", 47 | "ember-cli": "2.12.2", 48 | "jasmine-core": "2.6.0", 49 | "jasmine-spec-reporter": "^4.0.0", 50 | "karma": "1.6.0", 51 | "karma-chrome-launcher": "2.0.0", 52 | "karma-cli": "1.0.1", 53 | "karma-coverage-istanbul-reporter": "^1.0.0", 54 | "karma-jasmine": "1.1.0", 55 | "karma-jasmine-html-reporter": "^0.2.2", 56 | "karma-remap-istanbul": "0.6.0", 57 | "protractor": "5.1.1", 58 | "ts-node": "3.0.2", 59 | "tslint": "5.1.0", 60 | "typescript": "^2.4.1" 61 | }, 62 | "build": { 63 | "appId": "com.leon.NiceFish" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/app/manage/comment-table/comment-table.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
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 |
序号内容用户时间操作
1这是一条不合法的评论内容,需要删除掉。大漠穷秋2016-11-27删除
37 |
38 | 43 |
44 |
45 |
46 | -------------------------------------------------------------------------------- /src/app/post/postlist/postlist.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |

23 | {{post.title}} 24 |

25 |

26 |  {{post.likedTimes}}      27 |  {{post.commentTimes}}      28 |  {{post.readTimes}}     {{post.userName }}     {{post.postTime}} 29 |

30 |
31 | 32 |
33 |
34 |
35 | -------------------------------------------------------------------------------- /src/electron/main.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron') 2 | // Module to control application life. 3 | const app = electron.app 4 | // Module to create native browser window. 5 | const BrowserWindow = electron.BrowserWindow 6 | 7 | const path = require('path') 8 | const url = require('url') 9 | 10 | // //hide 11 | // var remote = require('electron').remote; 12 | // var Menu = remote.Menu; 13 | // var template = []; 14 | // var menu = Menu.buildFromTemplate(template); 15 | 16 | // Menu.setApplicationMenu(menu); 17 | 18 | // Keep a global reference of the window object, if you don't, the window will 19 | // be closed automatically when the JavaScript object is garbage collected. 20 | var mainWindow 21 | 22 | function createWindow () { 23 | // Create the browser window. 24 | mainWindow = new BrowserWindow({width: 1200, height: 900}) 25 | 26 | // and load the index.html of the app. 27 | mainWindow.loadURL(url.format({ 28 | pathname: path.join(__dirname, 'index.html'), 29 | protocol: 'file:', 30 | slashes: true 31 | })) 32 | 33 | // Open the DevTools. 34 | // mainWindow.webContents.openDevTools() 35 | 36 | // Emitted when the window is closed. 37 | mainWindow.on('closed', function () { 38 | // Dereference the window object, usually you would store windows 39 | // in an array if your app supports multi windows, this is the time 40 | // when you should delete the corresponding element. 41 | mainWindow = null 42 | }) 43 | } 44 | 45 | // This method will be called when Electron has finished 46 | // initialization and is ready to create browser windows. 47 | // Some APIs can only be used after this event occurs. 48 | app.on('ready', createWindow) 49 | 50 | // Quit when all windows are closed. 51 | app.on('window-all-closed', function () { 52 | // On OS X it is common for applications and their menu bar 53 | // to stay active until the user quits explicitly with Cmd + Q 54 | if (process.platform !== 'darwin') { 55 | app.quit() 56 | } 57 | }) 58 | 59 | app.on('activate', function () { 60 | // On OS X it's common to re-create a window in the app when the 61 | // dock icon is clicked and there are no other windows open. 62 | if (mainWindow === null) { 63 | createWindow() 64 | } 65 | }) 66 | 67 | // In this file you can include the rest of your app's specific main process 68 | // code. You can also put them in separate files and require them here. 69 | -------------------------------------------------------------------------------- /src/app/post/postlist/postlist.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormControl } from '@angular/forms'; 3 | import { ActivatedRoute, Router, Params } from '@angular/router'; 4 | import { Observable } from 'rxjs/Observable'; 5 | import { Subject } from 'rxjs/Subject'; 6 | import { PostlistService } from './services/postlist.service'; 7 | import { Post } from '../model/post-model'; 8 | 9 | @Component({ 10 | selector: 'app-postlist', 11 | templateUrl: './postlist.component.html', 12 | styleUrls: ['./postlist.component.scss'] 13 | }) 14 | export class PostlistComponent implements OnInit { 15 | public maxSize:number = 5; 16 | public itemsPerPage:number=5; 17 | public totalItems:number; 18 | //不要手动对这个属性进行赋值,它是和分页工具条自动绑定的 19 | public currentPage:number = 1; 20 | public numPages 21 | 22 | public searchText:string; 23 | public searchTextStream:Subject = new Subject(); 24 | 25 | public postList:Array; 26 | 27 | 28 | constructor( 29 | public router: Router, 30 | public activeRoute: ActivatedRoute, 31 | public postService:PostlistService) { 32 | 33 | } 34 | 35 | ngOnInit() { 36 | this.activeRoute.params.subscribe(params => { 37 | // 这里可以从路由里面获取URL参数 38 | console.log(params); 39 | this.loadData(this.searchText,this.currentPage); 40 | }); 41 | 42 | this.searchTextStream 43 | .debounceTime(500) 44 | .distinctUntilChanged() 45 | .subscribe(searchText => { 46 | console.log(this.searchText); 47 | this.loadData(this.searchText,this.currentPage) 48 | }); 49 | } 50 | 51 | public loadData(searchText:string,page:number){ 52 | let offset = (this.currentPage-1)*this.itemsPerPage; 53 | let end = (this.currentPage)*this.itemsPerPage; 54 | 55 | return this.postService.getPostList(searchText,page).subscribe( 56 | res=>{ 57 | this.totalItems = res["total"]; 58 | //TODO.正式环境中,需要去掉slice 59 | this.postList = res["items"].slice(offset,end>this.totalItems?this.totalItems:end); 60 | }, 61 | error => {console.log(error)}, 62 | () => {} 63 | ); 64 | } 65 | 66 | public pageChanged(event:any):void { 67 | this.router.navigateByUrl("posts/page/"+event.page); 68 | } 69 | 70 | public searchChanged($event):void{ 71 | this.searchTextStream.next(this.searchText); 72 | } 73 | 74 | public gotoWrite():void{ 75 | //TODO:如果没有登录,跳转到登录页,如果已登录,跳往写作页 76 | this.router.navigateByUrl("user/write"); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/app/user/user-login/user-login.component.html: -------------------------------------------------------------------------------- 1 | 42 | -------------------------------------------------------------------------------- /src/app/jsplumb-demo/jsplumb-demo.component.css: -------------------------------------------------------------------------------- 1 | .flowchart-demo{ 2 | min-height: 800px; 3 | } 4 | .flowchart-demo .window { 5 | border: 1px solid #346789; 6 | box-shadow: 2px 2px 19px #aaa; 7 | -o-box-shadow: 2px 2px 19px #aaa; 8 | -webkit-box-shadow: 2px 2px 19px #aaa; 9 | -moz-box-shadow: 2px 2px 19px #aaa; 10 | -moz-border-radius: 0.5em; 11 | border-radius: 0.5em; 12 | opacity: 0.8; 13 | width: 80px; 14 | height: 80px; 15 | line-height: 80px; 16 | cursor: pointer; 17 | text-align: center; 18 | z-index: 20; 19 | position: absolute; 20 | background-color: #eeeeef; 21 | color: black; 22 | font-family: helvetica, sans-serif; 23 | padding: 0.5em; 24 | font-size: 0.9em; 25 | -webkit-transition: -webkit-box-shadow 0.15s ease-in; 26 | -moz-transition: -moz-box-shadow 0.15s ease-in; 27 | -o-transition: -o-box-shadow 0.15s ease-in; 28 | transition: box-shadow 0.15s ease-in; 29 | } 30 | 31 | .flowchart-demo .window:hover { 32 | box-shadow: 2px 2px 19px #444; 33 | -o-box-shadow: 2px 2px 19px #444; 34 | -webkit-box-shadow: 2px 2px 19px #444; 35 | -moz-box-shadow: 2px 2px 19px #444; 36 | opacity: 0.6; 37 | } 38 | 39 | .flowchart-demo .active { 40 | border: 1px dotted green; 41 | } 42 | 43 | .flowchart-demo .hover { 44 | border: 1px dotted red; 45 | } 46 | 47 | #flowchartWindow1 { 48 | top: 34em; 49 | left: 5em; 50 | } 51 | 52 | #flowchartWindow2 { 53 | top: 7em; 54 | left: 36em; 55 | } 56 | 57 | #flowchartWindow3 { 58 | top: 27em; 59 | left: 48em; 60 | } 61 | 62 | #flowchartWindow4 { 63 | top: 23em; 64 | left: 22em; 65 | } 66 | 67 | .flowchart-demo .jtk-connector { 68 | z-index: 4; 69 | } 70 | 71 | .flowchart-demo .jtk-endpoint, .endpointTargetLabel, .endpointSourceLabel { 72 | z-index: 21; 73 | cursor: pointer; 74 | } 75 | 76 | .flowchart-demo .aLabel { 77 | background-color: white; 78 | padding: 0.4em; 79 | font: 12px sans-serif; 80 | color: #444; 81 | z-index: 21; 82 | border: 1px dotted gray; 83 | opacity: 0.8; 84 | cursor: pointer; 85 | } 86 | 87 | .flowchart-demo .aLabel.jtk-hover { 88 | background-color: #5C96BC; 89 | color: white; 90 | border: 1px solid white; 91 | } 92 | 93 | .window.jtk-connected { 94 | border: 1px solid green; 95 | } 96 | 97 | .jtk-drag { 98 | outline: 4px solid pink !important; 99 | } 100 | 101 | path, .jtk-endpoint { 102 | cursor: pointer; 103 | } 104 | 105 | .jtk-overlay { 106 | background-color:transparent; 107 | } -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/set'; 35 | 36 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 37 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 38 | 39 | /** IE10 and IE11 requires the following to support `@angular/animation`. */ 40 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 41 | 42 | 43 | /** Evergreen browsers require these. **/ 44 | import 'core-js/es6/reflect'; 45 | import 'core-js/es7/reflect'; 46 | 47 | 48 | /** ALL Firefox browsers require the following to support `@angular/animation`. **/ 49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 50 | 51 | 52 | 53 | /*************************************************************************************************** 54 | * Zone JS is required by Angular itself. 55 | */ 56 | import 'zone.js/dist/zone'; // Included with Angular CLI. 57 | 58 | 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | 64 | /** 65 | * Date, currency, decimal and percent pipes. 66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 67 | */ 68 | // import 'intl'; // Run `npm install --save intl`. 69 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 4 | import { RouterModule } from '@angular/router'; 5 | import { HttpModule,JsonpModule ,Http} from '@angular/http'; 6 | import { ReactiveFormsModule } from '@angular/forms'; 7 | import { TranslateModule, TranslateLoader, TranslateStaticLoader } from 'ng2-translate'; 8 | import { ToastModule } from 'ng2-toastr/ng2-toastr'; 9 | 10 | import { SharedModule } from './shared/shared.module'; 11 | import { AppComponent } from './app.component'; 12 | import { UserLoginService } from './user/user-login/user-login.service'; 13 | import { ForgetPwdComponent } from './user/forget-pwd/forget-pwd.component'; 14 | import { UserRegisterComponent } from './user/user-register/user-register.component'; 15 | import { UserRegisterService } from './user/user-register/user-register.service'; 16 | import { ForgetPwdService } from './user/forget-pwd/forget-pwd.service'; 17 | 18 | import { EqualValidator } from './user/user-register/directives/equal-validator.directive'; 19 | 20 | import { ChartComponent } from './chart/chart.component'; 21 | import { EChartOptionDirective1 } from './chart/echart-option.directive'; 22 | import { UseJqueryComponent } from './use-jquery/use-jquery.component'; 23 | import { GaodeMapComponent } from './map/gaode-map/gaode-map.component'; 24 | import { AmapComponent } from './map/gaode-map/amap/amap.component'; 25 | import { JsplumbDemoComponent } from './jsplumb-demo/jsplumb-demo.component'; 26 | import {appRoutes} from './app.routes'; 27 | 28 | export function createTranslateLoader(http: Http) { 29 | return new TranslateStaticLoader(http, './assets/i18n', '.json'); 30 | } 31 | 32 | 33 | @NgModule({ 34 | declarations: [ 35 | AppComponent, 36 | ForgetPwdComponent, 37 | UserRegisterComponent, 38 | EqualValidator, 39 | EChartOptionDirective1, 40 | ChartComponent, 41 | UseJqueryComponent, 42 | AmapComponent, 43 | GaodeMapComponent, 44 | JsplumbDemoComponent 45 | ], 46 | imports: [ 47 | BrowserModule, 48 | BrowserAnimationsModule, 49 | RouterModule, 50 | ReactiveFormsModule, 51 | HttpModule, 52 | JsonpModule, 53 | TranslateModule.forRoot({ 54 | provide: TranslateLoader, 55 | useFactory: (createTranslateLoader), 56 | deps: [Http] 57 | }), 58 | SharedModule, 59 | ToastModule.forRoot(), 60 | RouterModule.forRoot(appRoutes) 61 | ], 62 | providers: [ 63 | UserLoginService, 64 | UserRegisterService, 65 | ForgetPwdService 66 | ], 67 | bootstrap: [AppComponent] 68 | }) 69 | export class AppModule { 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/assets/skins/lightgray/content.inline.min.css: -------------------------------------------------------------------------------- 1 | .mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1} -------------------------------------------------------------------------------- /src/assets/fonts/icomoon/icomoon/demo-files/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-family: sans-serif; 5 | font-size: 1em; 6 | line-height: 1.5; 7 | color: #555; 8 | background: #fff; 9 | } 10 | h1 { 11 | font-size: 1.5em; 12 | font-weight: normal; 13 | } 14 | small { 15 | font-size: .66666667em; 16 | } 17 | a { 18 | color: #e74c3c; 19 | text-decoration: none; 20 | } 21 | a:hover, a:focus { 22 | box-shadow: 0 1px #e74c3c; 23 | } 24 | .bshadow0, input { 25 | box-shadow: inset 0 -2px #e7e7e7; 26 | } 27 | input:hover { 28 | box-shadow: inset 0 -2px #ccc; 29 | } 30 | input, fieldset { 31 | font-size: 1em; 32 | margin: 0; 33 | padding: 0; 34 | border: 0; 35 | } 36 | input { 37 | color: inherit; 38 | line-height: 1.5; 39 | height: 1.5em; 40 | padding: .25em 0; 41 | } 42 | input:focus { 43 | outline: none; 44 | box-shadow: inset 0 -2px #449fdb; 45 | } 46 | .glyph { 47 | font-size: 16px; 48 | width: 15em; 49 | padding-bottom: 1em; 50 | margin-right: 4em; 51 | margin-bottom: 1em; 52 | float: left; 53 | overflow: hidden; 54 | } 55 | .liga { 56 | width: 80%; 57 | width: calc(100% - 2.5em); 58 | } 59 | .talign-right { 60 | text-align: right; 61 | } 62 | .talign-center { 63 | text-align: center; 64 | } 65 | .bgc1 { 66 | background: #f1f1f1; 67 | } 68 | .fgc1 { 69 | color: #999; 70 | } 71 | .fgc0 { 72 | color: #000; 73 | } 74 | p { 75 | margin-top: 1em; 76 | margin-bottom: 1em; 77 | } 78 | .mvm { 79 | margin-top: .75em; 80 | margin-bottom: .75em; 81 | } 82 | .mtn { 83 | margin-top: 0; 84 | } 85 | .mtl, .mal { 86 | margin-top: 1.5em; 87 | } 88 | .mbl, .mal { 89 | margin-bottom: 1.5em; 90 | } 91 | .mal, .mhl { 92 | margin-left: 1.5em; 93 | margin-right: 1.5em; 94 | } 95 | .mhmm { 96 | margin-left: 1em; 97 | margin-right: 1em; 98 | } 99 | .mls { 100 | margin-left: .25em; 101 | } 102 | .ptl { 103 | padding-top: 1.5em; 104 | } 105 | .pbs, .pvs { 106 | padding-bottom: .25em; 107 | } 108 | .pvs, .pts { 109 | padding-top: .25em; 110 | } 111 | .unit { 112 | float: left; 113 | } 114 | .unitRight { 115 | float: right; 116 | } 117 | .size1of2 { 118 | width: 50%; 119 | } 120 | .size1of1 { 121 | width: 100%; 122 | } 123 | .clearfix:before, .clearfix:after { 124 | content: " "; 125 | display: table; 126 | } 127 | .clearfix:after { 128 | clear: both; 129 | } 130 | .hidden-true { 131 | display: none; 132 | } 133 | .textbox0 { 134 | width: 3em; 135 | background: #f1f1f1; 136 | padding: .25em .5em; 137 | line-height: 1.5; 138 | height: 1.5em; 139 | } 140 | #testDrive { 141 | display: block; 142 | padding-top: 24px; 143 | line-height: 1.5; 144 | } 145 | .fs0 { 146 | font-size: 16px; 147 | } 148 | .fs1 { 149 | font-size: 14px; 150 | } 151 | .fs2 { 152 | font-size: 24px; 153 | } 154 | -------------------------------------------------------------------------------- /src/app/manage/post-table/post-table.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input} from '@angular/core'; 2 | import { flyIn } from '../../animations/fly-in'; 3 | import { ActivatedRoute, Router, UrlTree, PRIMARY_OUTLET, UrlSegmentGroup, UrlSegment } from '@angular/router'; 4 | import { PostTableService } from './services/post-table.service'; 5 | 6 | @Component({ 7 | selector: 'app-post-table', 8 | templateUrl: './post-table.component.html', 9 | styleUrls: ['./post-table.component.scss'], 10 | animations: [ 11 | flyIn 12 | ] 13 | }) 14 | export class PostTableComponent implements OnInit { 15 | @Input() dataURL:string="mock-data/postlist-mock.json"; 16 | 17 | public postList:Array; 18 | public maxSize:number = 5; 19 | public itemsPerPage:number=5; 20 | public totalItems:number = 15; 21 | public currentPage:number = 1; 22 | public numPages 23 | 24 | constructor(public router: Router, 25 | public activeRoute: ActivatedRoute, 26 | public postTableService: PostTableService) { 27 | } 28 | 29 | ngOnInit() { 30 | this.activeRoute.params.subscribe( 31 | params =>this.getPostsByPage(params["page"]) 32 | ); 33 | } 34 | 35 | public getPostsByPage(page:Number){ 36 | console.log("页码>"+page); 37 | return this.postTableService.getPostTable(this.dataURL).subscribe( 38 | res=>{ 39 | console.log(res); 40 | this.postList=res.items; 41 | }, 42 | error => {console.log(error)}, 43 | () => {} 44 | ); 45 | } 46 | 47 | public pageChanged(event:any):void { 48 | let urlTree:UrlTree=this.router.parseUrl(this.router.url); 49 | const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET]; 50 | const s: UrlSegment[] = g.segments; 51 | this.router.navigateByUrl(s[0]+"/posttable/page/"+event.page); 52 | } 53 | 54 | public goToWrite():void{ 55 | this.router.navigateByUrl("user/write"); 56 | } 57 | 58 | public editPost(event):void{ 59 | var target = event.currentTarget; 60 | var nameAttr = target.attributes.name; 61 | var value = nameAttr.nodeValue; 62 | console.log("postId>"+value); 63 | } 64 | 65 | public top(event):void{ 66 | var target = event.currentTarget; 67 | var nameAttr = target.attributes.name; 68 | var value = nameAttr.nodeValue; 69 | console.log("postId>"+value); 70 | } 71 | 72 | public unTop(event):void{ 73 | var target = event.currentTarget; 74 | var nameAttr = target.attributes.name; 75 | var value = nameAttr.nodeValue; 76 | console.log("postId>"+value); 77 | } 78 | 79 | public delPost(event):void{ 80 | var target = event.currentTarget; 81 | var nameAttr = target.attributes.name; 82 | var value = nameAttr.nodeValue; 83 | console.log("postId>"+value); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/app/manage/user-table/user-table.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
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 | 44 | 45 | 46 |
序号用户名注册时间最后登录操作
1damoqiongqiu@126.com2010-11-11 11:112016-11-27 09:34 39 | 40 | 41 | 42 | 43 |
47 |
48 | 49 |
50 |
51 |
52 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, HostListener, ElementRef, Renderer, ViewContainerRef } from '@angular/core'; 2 | import { ActivatedRoute, Router, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot } from '@angular/router'; 3 | import { TranslateService } from 'ng2-translate'; 4 | import { UserLoginService } from './user/user-login/user-login.service'; 5 | import { UserRegisterService } from './user/user-register/user-register.service'; 6 | import { User } from './user/model/user-model'; 7 | import 'rxjs/add/operator/merge'; 8 | 9 | import { ToastsManager } from 'ng2-toastr/ng2-toastr'; 10 | 11 | @Component({ 12 | selector: 'app-root', 13 | templateUrl: './app.component.html', 14 | styleUrls: ['./app.component.scss'] 15 | }) 16 | export class AppComponent { 17 | public currentUser: User; 18 | private globalClickCallbackFn: Function; 19 | private loginSuccessCallbackFn: Function; 20 | 21 | constructor( 22 | public elementRef: ElementRef, 23 | public renderer: Renderer, 24 | public router: Router, 25 | public activatedRoute: ActivatedRoute, 26 | public translate: TranslateService, 27 | public userLoginService: UserLoginService, 28 | public userRegisterService: UserRegisterService, 29 | public toastr: ToastsManager, 30 | public vcr: ViewContainerRef 31 | ) { 32 | this.toastr.setRootViewContainerRef(vcr); 33 | } 34 | 35 | ngOnInit() { 36 | this.globalClickCallbackFn = this.renderer.listen(this.elementRef.nativeElement, 'click', (event: any) => { 37 | console.log("全局监听点击事件>" + event); 38 | }); 39 | 40 | this.currentUser = JSON.parse(localStorage.getItem("currentUser")); 41 | 42 | this.userLoginService.currentUser 43 | .merge(this.userRegisterService.currentUser) 44 | .subscribe( 45 | data => { 46 | this.currentUser = data; 47 | let activatedRouteSnapshot: ActivatedRouteSnapshot = this.activatedRoute.snapshot; 48 | let routerState: RouterState = this.router.routerState; 49 | let routerStateSnapshot: RouterStateSnapshot = routerState.snapshot; 50 | 51 | console.log(activatedRouteSnapshot); 52 | console.log(routerState); 53 | console.log(routerStateSnapshot); 54 | 55 | //如果是从/login这个URL进行的登录,跳转到首页,否则什么都不做 56 | if (routerStateSnapshot.url.indexOf("/login") != -1) { 57 | this.router.navigateByUrl("/home"); 58 | } 59 | }, 60 | error => console.error(error) 61 | ); 62 | 63 | this.translate.addLangs(["zh", "en"]); 64 | this.translate.setDefaultLang('zh'); 65 | 66 | const browserLang = this.translate.getBrowserLang(); 67 | console.log("检测到的浏览器语言>" + browserLang); 68 | this.translate.use(browserLang.match(/zh|en/) ? browserLang : 'zh'); 69 | } 70 | 71 | ngOnDestroy() { 72 | if (this.globalClickCallbackFn) { 73 | this.globalClickCallbackFn(); 74 | } 75 | } 76 | 77 | toggle(button: any) { 78 | console.log(button); 79 | } 80 | 81 | public doLogout(): void { 82 | this.userLoginService.logout(); 83 | this.toastr.success('退出成功!','系统提示'); 84 | this.router.navigateByUrl(""); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/assets/css/prism.css: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ 2 | /** 3 | * prism.js default theme for JavaScript, CSS and HTML 4 | * Based on dabblet (http://dabblet.com) 5 | * @author Lea Verou 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: black; 11 | text-shadow: 0 1px white; 12 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 13 | direction: ltr; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 32 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 33 | text-shadow: none; 34 | background: #b3d4fc; 35 | } 36 | 37 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 38 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 39 | text-shadow: none; 40 | background: #b3d4fc; 41 | } 42 | 43 | @media print { 44 | code[class*="language-"], 45 | pre[class*="language-"] { 46 | text-shadow: none; 47 | } 48 | } 49 | 50 | /* Code blocks */ 51 | pre[class*="language-"] { 52 | padding: 1em; 53 | margin: .5em 0; 54 | overflow: auto; 55 | } 56 | 57 | :not(pre) > code[class*="language-"], 58 | pre[class*="language-"] { 59 | background: #f5f2f0; 60 | } 61 | 62 | /* Inline code */ 63 | :not(pre) > code[class*="language-"] { 64 | padding: .1em; 65 | border-radius: .3em; 66 | } 67 | 68 | .token.comment, 69 | .token.prolog, 70 | .token.doctype, 71 | .token.cdata { 72 | color: slategray; 73 | } 74 | 75 | .token.punctuation { 76 | color: #999; 77 | } 78 | 79 | .namespace { 80 | opacity: .7; 81 | } 82 | 83 | .token.property, 84 | .token.tag, 85 | .token.boolean, 86 | .token.number, 87 | .token.constant, 88 | .token.symbol, 89 | .token.deleted { 90 | color: #905; 91 | } 92 | 93 | .token.selector, 94 | .token.attr-name, 95 | .token.string, 96 | .token.char, 97 | .token.builtin, 98 | .token.inserted { 99 | color: #690; 100 | } 101 | 102 | .token.operator, 103 | .token.entity, 104 | .token.url, 105 | .language-css .token.string, 106 | .style .token.string { 107 | color: #a67f59; 108 | background: hsla(0, 0%, 100%, .5); 109 | } 110 | 111 | .token.atrule, 112 | .token.attr-value, 113 | .token.keyword { 114 | color: #07a; 115 | } 116 | 117 | .token.function { 118 | color: #DD4A68; 119 | } 120 | 121 | .token.regex, 122 | .token.important, 123 | .token.variable { 124 | color: #e90; 125 | } 126 | 127 | .token.important, 128 | .token.bold { 129 | font-weight: bold; 130 | } 131 | .token.italic { 132 | font-style: italic; 133 | } 134 | 135 | .token.entity { 136 | cursor: help; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/app/manage/sys-param/sys-param.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
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 |
44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |
52 | 53 |
54 | 55 |
56 |
57 |
58 | 59 |
60 | 61 |
62 |
63 |
64 |
65 | 66 |
67 |
68 |
69 |
70 | -------------------------------------------------------------------------------- /src/assets/skins/lightgray/content.min.css: -------------------------------------------------------------------------------- 1 | body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}hr{cursor:default}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid #F00;cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#3399ff !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2d8ac7}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #7ACAFF}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2d8ac7}.mce-resize-bar-dragging{background-color:blue;opacity:.25;filter:alpha(opacity=25);zoom:1} -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "class-name": true, 7 | "comment-format": [ 8 | true, 9 | "check-space" 10 | ], 11 | "curly": true, 12 | "eofline": true, 13 | "forin": true, 14 | "indent": [ 15 | true, 16 | "spaces" 17 | ], 18 | "label-position": true, 19 | "label-undefined": true, 20 | "max-line-length": [ 21 | true, 22 | 140 23 | ], 24 | "member-access": false, 25 | "member-ordering": [ 26 | true, 27 | "static-before-instance", 28 | "variables-before-functions" 29 | ], 30 | "no-arg": true, 31 | "no-bitwise": true, 32 | "no-console": [ 33 | true, 34 | "debug", 35 | "info", 36 | "time", 37 | "timeEnd", 38 | "trace" 39 | ], 40 | "no-construct": true, 41 | "no-debugger": true, 42 | "no-duplicate-key": true, 43 | "no-duplicate-variable": true, 44 | "no-empty": false, 45 | "no-eval": true, 46 | "no-inferrable-types": true, 47 | "no-shadowed-variable": true, 48 | "no-string-literal": false, 49 | "no-switch-case-fall-through": true, 50 | "no-trailing-whitespace": true, 51 | "no-unused-expression": true, 52 | "no-unused-variable": true, 53 | "no-unreachable": true, 54 | "no-use-before-declare": true, 55 | "no-var-keyword": true, 56 | "object-literal-sort-keys": false, 57 | "one-line": [ 58 | true, 59 | "check-open-brace", 60 | "check-catch", 61 | "check-else", 62 | "check-whitespace" 63 | ], 64 | "quotemark": [ 65 | true, 66 | "single" 67 | ], 68 | "radix": true, 69 | "semicolon": [ 70 | "always" 71 | ], 72 | "triple-equals": [ 73 | true, 74 | "allow-null-check" 75 | ], 76 | "typedef-whitespace": [ 77 | true, 78 | { 79 | "call-signature": "nospace", 80 | "index-signature": "nospace", 81 | "parameter": "nospace", 82 | "property-declaration": "nospace", 83 | "variable-declaration": "nospace" 84 | } 85 | ], 86 | "variable-name": false, 87 | "whitespace": [ 88 | true, 89 | "check-branch", 90 | "check-decl", 91 | "check-operator", 92 | "check-separator", 93 | "check-type" 94 | ], 95 | 96 | "directive-selector-prefix": [true, "app"], 97 | "component-selector-prefix": [true, "app"], 98 | "directive-selector-name": [true, "camelCase"], 99 | "component-selector-name": [true, "kebab-case"], 100 | "directive-selector-type": [true, "attribute"], 101 | "component-selector-type": [true, "element"], 102 | "use-input-property-decorator": true, 103 | "use-output-property-decorator": true, 104 | "use-host-property-decorator": true, 105 | "no-input-rename": true, 106 | "no-output-rename": true, 107 | "use-life-cycle-interface": true, 108 | "use-pipe-transform-interface": true, 109 | "component-class-suffix": true, 110 | "directive-class-suffix": true 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 61 | 62 |
63 | 64 |
65 | 66 | 75 | -------------------------------------------------------------------------------- /src/app/use-jquery/use-jquery.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

本页用来演示如何集成jQuery和jQueryUI控件

5 |
6 |
7 |
8 |
9 |

10 | 【请仔细看】相关的文件有:angular-cli.json/typings.d.ts/styles.scss 11 |

12 |
13 |
14 |
15 |
16 | 日期选择器: 17 | 18 |
19 |
20 |
21 |
22 |
23 | 28 |
29 |

Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.

30 |
31 |
32 |

Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.

33 |
34 |
35 |

Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.

36 |

Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.

37 |
38 |
39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /src/app/chart/chart.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { fadeIn } from '../animations/fade-in'; 3 | 4 | @Component({ 5 | selector: 'app-chart', 6 | templateUrl: './chart.component.html', 7 | styleUrls: ['./chart.component.scss'], 8 | animations:[ fadeIn ] 9 | }) 10 | export class ChartComponent implements OnInit { 11 | pieChart = { 12 | theme: '', 13 | event: [ 14 | { 15 | type: "click", 16 | cb: function (res) { 17 | console.log(res); 18 | } 19 | } 20 | ], 21 | title: { 22 | text: 'NiceFish访问用户地区分布', 23 | subtext: '纯属虚构', 24 | x: 'center' 25 | }, 26 | tooltip: { 27 | trigger: 'item', 28 | formatter: "{a}
{b} : {c} ({d}%)" 29 | }, 30 | legend: { 31 | orient: 'vertical', 32 | left: 'left', 33 | data: ['深圳', '北京', '广州', '上海', '长沙'] 34 | }, 35 | series: [{ 36 | name: '访问来源', 37 | type: 'pie', 38 | startAngle: -180, 39 | radius: '55%', 40 | center: ['50%', '60%'], 41 | data: [{ 42 | value: 3350, 43 | name: '深圳' 44 | }, { 45 | value: 310, 46 | name: '北京' 47 | }, { 48 | value: 234, 49 | name: '广州' 50 | }, { 51 | value: 135, 52 | name: '上海' 53 | }, { 54 | value: 1548, 55 | name: '长沙' 56 | }], 57 | itemStyle: { 58 | emphasis: { 59 | shadowBlur: 10, 60 | shadowOffsetX: 0, 61 | shadowColor: 'rgba(0, 0, 0, 0.5)' 62 | } 63 | } 64 | }] 65 | }; 66 | 67 | barChart = { 68 | title: { 69 | text: 'NiceFish月访问量统计', 70 | subtext: '纯属虚构', 71 | x: 'center' 72 | }, 73 | color: ['#3398DB'], 74 | tooltip: { 75 | trigger: 'axis', 76 | axisPointer: { // 坐标轴指示器,坐标轴触发有效 77 | type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' 78 | }, 79 | formatter: "{b}月{a}:{c}" 80 | }, 81 | grid: { 82 | left: '3%', 83 | right: '4%', 84 | bottom: '3%', 85 | containLabel: true 86 | }, 87 | xAxis: [ 88 | { 89 | type: 'category', 90 | data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], 91 | axisTick: { 92 | alignWithLabel: true 93 | } 94 | } 95 | ], 96 | yAxis: [ 97 | { 98 | type: 'value' 99 | } 100 | ], 101 | series: [ 102 | { 103 | name: '访问量', 104 | type: 'bar', 105 | barWidth: '60%', 106 | data: [10, 52, 200, 334, 390, 330, 220, 1000, 500, 444, 999, 11] 107 | } 108 | ] 109 | }; 110 | 111 | lineChart = { 112 | title: { 113 | text: 'NiceFish月访问趋势图', 114 | subtext: '纯属虚构', 115 | x:"center" 116 | }, 117 | tooltip: { 118 | trigger: 'axis' 119 | }, 120 | xAxis: { 121 | type: 'category', 122 | boundaryGap: false, 123 | data: ['1', '2', '3', '4', '5', '6', '7','8','9','10','11','12'] 124 | }, 125 | yAxis: { 126 | type: 'value', 127 | axisLabel: { 128 | formatter: '{value} 次' 129 | } 130 | }, 131 | series: [ 132 | { 133 | name: '访问量', 134 | type: 'line', 135 | data: [11, 11, 15, 13, 12, 13, 10,123,100,99,66,199] 136 | } 137 | 138 | ] 139 | }; 140 | 141 | constructor() { } 142 | 143 | ngOnInit() { 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/app/manage/post-table/post-table.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
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 | 44 | 45 | 46 |
序号标题作者日期操作
{{post.postId}}{{post.title}}{{post.userName}}{{post.postTime}} 39 | 40 | 41 | 42 | 43 |
47 |
48 | 53 |
54 |
55 |
56 | 71 | -------------------------------------------------------------------------------- /src/app/post/write-post/write-post.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit,AfterViewInit,OnDestroy } from '@angular/core'; 2 | import { flyIn } from '../../animations/fly-in'; 3 | 4 | @Component({ 5 | selector: 'app-write-post', 6 | templateUrl: './write-post.component.html', 7 | styleUrls: ['./write-post.component.scss'], 8 | animations: [ 9 | flyIn 10 | ] 11 | }) 12 | 13 | export class WritePostComponent implements OnInit,AfterViewInit,OnDestroy { 14 | public editor; 15 | 16 | constructor() { } 17 | 18 | ngOnInit() { 19 | 20 | } 21 | 22 | public fileInputChangeHandler():void{ 23 | let fileInput = document.getElementById('img_input'); 24 | let inputValue=fileInput.value; 25 | if(!inputValue){ 26 | return; 27 | } 28 | //提交隐藏的表单,上传文件 29 | let fileForm=document.getElementById('file_upload_form'); 30 | fileForm.action="fileuploadurl"; 31 | fileForm.onsubmit=function(event){ 32 | console.log(event); 33 | event.preventDefault(); 34 | let file=fileInput.files[0]; 35 | let formData = new FormData(); 36 | formData.append('file', file,file.name); 37 | 38 | let xhr=new XMLHttpRequest(); 39 | xhr.withCredentials = false; 40 | xhr.open('POST', 'file_upload_URL.php'); 41 | xhr.onload = function() { 42 | let json; 43 | if (xhr.status != 200) { 44 | console.log('HTTP Error: ' + xhr.status); 45 | return; 46 | } 47 | json = JSON.parse(xhr.responseText); 48 | if (!json || typeof json.location != 'string') { 49 | console.log('Invalid JSON: ' + xhr.responseText); 50 | return; 51 | } 52 | console.log(json.location); 53 | fileInput.value=''; 54 | }; 55 | xhr.send(formData); 56 | } 57 | fileForm.submit(); 58 | fileInput.value=''; 59 | } 60 | 61 | ngAfterViewInit() { 62 | /** 63 | * 【非常重要】 64 | * 关于TinyMCE的完整文档,请查看这里https://www.tinymce.com/docs/ 65 | */ 66 | tinymce.init({ 67 | selector: '#post_editor', 68 | skin_url: '/assets/skins/lightgray', 69 | //menubar:false, 70 | plugins: [ 71 | 'advlist autolink lists link image charmap print preview hr anchor pagebreak', 72 | 'searchreplace wordcount visualblocks visualchars code fullscreen', 73 | 'insertdatetime media nonbreaking save table contextmenu directionality', 74 | 'emoticons template paste textcolor colorpicker textpattern imagetools codesample' 75 | ], 76 | toolbar1: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image', 77 | toolbar2: 'print preview media | forecolor backcolor emoticons | codesample', 78 | image_advtab: true, 79 | codesample_content_css:'/assets/css/prism.css', 80 | //文件和图片上传相关的选项 81 | file_browser_callback_types: 'image', 82 | file_browser_callback: function(field_name, url, type, win) { 83 | console.log(type); 84 | console.log(type=='image'); 85 | if(type=='image'){ 86 | let event = new MouseEvent('click', { 87 | 'view': window, 88 | 'bubbles': true, 89 | 'cancelable': true 90 | }); 91 | let fileInput = document.getElementById('img_input'); 92 | fileInput.dispatchEvent(event); 93 | } 94 | }, 95 | setup: editor => { 96 | this.editor = editor; 97 | editor.on('keyup', () => { 98 | const content = editor.getContent(); 99 | console.log(content); 100 | }); 101 | } 102 | }); 103 | } 104 | 105 | ngOnDestroy() { 106 | tinymce.remove(this.editor); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "version": "1.0.0", 5 | "name": "NiceFish" 6 | }, 7 | "apps": [{ 8 | "root": "src", 9 | "outDir": "dist", 10 | "assets": [ 11 | "assets", 12 | "mock-data", 13 | "favicon.ico" 14 | ], 15 | "index": "index.html", 16 | "main": "main.ts", 17 | "polyfills": "polyfills.ts", 18 | "test": "test.ts", 19 | "tsconfig": "tsconfig.json", 20 | "prefix": "app", 21 | "styles": [ 22 | "styles.scss" 23 | ], 24 | "scripts": [ 25 | "../node_modules/tinymce/tinymce.js", 26 | "../node_modules/tinymce/themes/modern/theme.js", 27 | "../node_modules/tinymce/plugins/advlist/plugin.js", 28 | "../node_modules/tinymce/plugins/autolink/plugin.js", 29 | "../node_modules/tinymce/plugins/lists/plugin.js", 30 | "../node_modules/tinymce/plugins/link/plugin.js", 31 | "../node_modules/tinymce/plugins/image/plugin.js", 32 | "../node_modules/tinymce/plugins/charmap/plugin.js", 33 | "../node_modules/tinymce/plugins/print/plugin.js", 34 | "../node_modules/tinymce/plugins/preview/plugin.js", 35 | "../node_modules/tinymce/plugins/hr/plugin.js", 36 | "../node_modules/tinymce/plugins/anchor/plugin.js", 37 | "../node_modules/tinymce/plugins/pagebreak/plugin.js", 38 | "../node_modules/tinymce/plugins/searchreplace/plugin.js", 39 | "../node_modules/tinymce/plugins/wordcount/plugin.js", 40 | "../node_modules/tinymce/plugins/visualblocks/plugin.js", 41 | "../node_modules/tinymce/plugins/visualchars/plugin.js", 42 | "../node_modules/tinymce/plugins/code/plugin.js", 43 | "../node_modules/tinymce/plugins/codesample/plugin.js", 44 | "../node_modules/tinymce/plugins/fullscreen/plugin.js", 45 | "../node_modules/tinymce/plugins/insertdatetime/plugin.js", 46 | "../node_modules/tinymce/plugins/media/plugin.js", 47 | "../node_modules/tinymce/plugins/nonbreaking/plugin.js", 48 | "../node_modules/tinymce/plugins/save/plugin.js", 49 | "../node_modules/tinymce/plugins/table/plugin.js", 50 | "../node_modules/tinymce/plugins/contextmenu/plugin.js", 51 | "../node_modules/tinymce/plugins/directionality/plugin.js", 52 | "../node_modules/tinymce/plugins/emoticons/plugin.js", 53 | "../node_modules/tinymce/plugins/template/plugin.js", 54 | "../node_modules/tinymce/plugins/paste/plugin.js", 55 | "../node_modules/tinymce/plugins/textcolor/plugin.js", 56 | "../node_modules/tinymce/plugins/colorpicker/plugin.js", 57 | "../node_modules/tinymce/plugins/textpattern/plugin.js", 58 | "../node_modules/tinymce/plugins/imagetools/plugin.js", 59 | 60 | "../node_modules/jquery/dist/jquery.min.js", 61 | "../node_modules/jquery-ui-dist/jquery-ui.min.js" 62 | ], 63 | "environmentSource": "environments/environment.ts", 64 | "environments": { 65 | "dev": "environments/environment.ts", 66 | "prod": "environments/environment.prod.ts" 67 | } 68 | }], 69 | "addons": [], 70 | "packages": [], 71 | "e2e": { 72 | "protractor": { 73 | "config": "./protractor.conf.js" 74 | } 75 | }, 76 | "lint": [{ 77 | "files": "src/**/*.ts", 78 | "project": "src/tsconfig.json" 79 | }, { 80 | "files": "e2e/**/*.ts", 81 | "project": "e2e/tsconfig.json" 82 | }], 83 | "test": { 84 | "karma": { 85 | "config": "./karma.conf.js" 86 | } 87 | }, 88 | "defaults": { 89 | "styleExt": "scss", 90 | "prefixInterfaces": false, 91 | "inline": { 92 | "style": false, 93 | "template": false 94 | }, 95 | "spec": { 96 | "class": false, 97 | "component": true, 98 | "directive": true, 99 | "module": false, 100 | "pipe": true, 101 | "service": true 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/app/user/user-register/user-register.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {ActivatedRoute, Router} from '@angular/router'; 3 | import {FormGroup, FormBuilder, Validators} from '@angular/forms'; 4 | 5 | import {User} from '../model/user-model'; 6 | import {UserRegisterService} from './user-register.service'; 7 | import {fadeIn} from '../../animations/fade-in'; 8 | 9 | @Component({ 10 | selector: 'app-user-register', 11 | templateUrl: './user-register.component.html', 12 | styleUrls: ['./user-register.component.scss'], 13 | animations:[ fadeIn ] 14 | }) 15 | export class UserRegisterComponent implements OnInit { 16 | 17 | public userForm: FormGroup; 18 | public userInfo: User = new User(); 19 | 20 | public formErrors = { 21 | 'userName': '', 22 | 'nickName': '', 23 | 'email': '', 24 | 'password': '', 25 | 'confirmPassword': '', 26 | 'formError': '', 27 | 'vcode': '' 28 | }; 29 | validationMessages = { 30 | 'userName': { 31 | 'required': '用户名必须输入。', 32 | 'minlength': '用户名4到32个字符。' 33 | }, 34 | 'nickName': { 35 | 'required': '昵称必须输入。', 36 | 'minlength': '昵称2到32个字符。' 37 | }, 38 | 'email': { 39 | 'required': '邮箱必须输入。', 40 | 'pattern': '请输入正确的邮箱地址。' 41 | }, 42 | 'password': { 43 | 'required': '密码必须输入。', 44 | 'minlength': '密码至少要8位。' 45 | }, 46 | 'confirmPassword': { 47 | 'required': '重复密码必须输入。', 48 | 'minlength': '密码至少要8位。', 49 | 'validateEqual': "两次输入的密码不一致。" 50 | }, 51 | 'vcode': { 52 | 'required': '验证码必须输入。', 53 | 'minlength': '4位验证码', 54 | 'maxlength': '4位验证码' 55 | }, 56 | }; 57 | 58 | constructor(public fb: FormBuilder, 59 | public userRegisterService: UserRegisterService, 60 | public router: Router, 61 | public route: ActivatedRoute,) { 62 | } 63 | 64 | ngOnInit() { 65 | this.buildForm(); 66 | } 67 | 68 | buildForm(): void { 69 | this.userForm = this.fb.group({ 70 | "userName": [ 71 | this.userInfo.userName, 72 | [ 73 | Validators.required, 74 | Validators.minLength(4), 75 | Validators.maxLength(32) 76 | ] 77 | ], 78 | "nickName": [ 79 | this.userInfo.nickName, 80 | [ 81 | Validators.required, 82 | Validators.minLength(2), 83 | Validators.maxLength(32) 84 | ] 85 | ], 86 | "email": [ 87 | this.userInfo.email, 88 | [ 89 | Validators.required, 90 | Validators.pattern("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$") 91 | ] 92 | ], 93 | "password": [ 94 | this.userInfo.password, 95 | [ 96 | Validators.required, 97 | Validators.minLength(8), 98 | ] 99 | ], 100 | "confirmPassword": [ 101 | this.userInfo.confirmPassword, 102 | [ 103 | Validators.required, 104 | Validators.minLength(8) 105 | ] 106 | ], 107 | "vcode": [ 108 | this.userInfo.vcode, 109 | [ 110 | Validators.required, 111 | Validators.minLength(4), 112 | Validators.maxLength(4) 113 | ] 114 | ] 115 | }); 116 | this.userForm.valueChanges 117 | .subscribe(data => this.onValueChanged(data)); 118 | this.onValueChanged(); 119 | } 120 | 121 | onValueChanged(data?: any) { 122 | if (!this.userForm) { 123 | return; 124 | } 125 | const form = this.userForm; 126 | for (const field in this.formErrors) { 127 | this.formErrors[field] = ''; 128 | const control = form.get(field); 129 | if (control && control.dirty && !control.valid) { 130 | const messages = this.validationMessages[field]; 131 | for (const key in control.errors) { 132 | this.formErrors[field] += messages[key] + ' '; 133 | } 134 | } 135 | } 136 | } 137 | 138 | doRegister() { 139 | if (this.userForm.valid) { 140 | this.userInfo = this.userForm.value; 141 | this.userRegisterService.register(this.userInfo) 142 | .subscribe( 143 | data => { 144 | this.router.navigateByUrl("home"); 145 | }, 146 | error => { 147 | this.formErrors.formError = error.message; 148 | console.error(error); 149 | } 150 | ); 151 | } else { 152 | this.formErrors.formError = "存在不合法的输入项,请检查。"; 153 | } 154 | console.log(this.userInfo); 155 | } 156 | 157 | testEmail() { 158 | let email = this.userForm.get("email").value; 159 | this.userRegisterService.testEmail(email) 160 | .subscribe( 161 | data => { 162 | console.log(data); 163 | }, 164 | error => { 165 | console.error(error); 166 | } 167 | ) 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/app/user/user-register/user-register.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

{{'userRegister.userSignUp' | translate}}

5 |
6 |
7 |
8 |
9 | 10 |
11 | 12 |
13 | {{ formErrors.userName }} 14 |
15 |
16 |
17 |
18 | 19 |
20 | 21 |
22 | {{ formErrors.nickName }} 23 |
24 |
25 |
26 |
27 | 28 |
29 | 30 |
31 | {{ formErrors.email }} 32 |
33 |
34 |
35 |
36 |
37 |

{{'userRegister.notice' | translate}}

38 |
39 |
40 |
41 | 42 |
43 | 44 |
45 | {{ formErrors.password }} 46 |
47 |
48 |
49 |
50 | 51 |
52 | 53 |
54 | {{ formErrors.confirmPassword }} 55 |
56 |
57 |
58 |
59 | 60 |
61 | 62 |
63 | {{ formErrors.vcode }} 64 |
65 |
66 |
67 | 验证码 68 | 69 |
70 |
71 |
{{ formErrors.formError }}
72 |
73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 |
81 | -------------------------------------------------------------------------------- /src/app/jsplumb-demo/jsplumb-demo.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import * as jsp from 'jsplumb'; 3 | 4 | @Component({ 5 | selector: 'app-jsplumb-demo', 6 | templateUrl: './jsplumb-demo.component.html', 7 | styleUrls: ['./jsplumb-demo.component.css'] 8 | }) 9 | export class JsplumbDemoComponent implements OnInit { 10 | 11 | constructor() { } 12 | 13 | ngOnInit() { 14 | var jsPlumb = jsp.jsPlumb; 15 | var instance = jsPlumb.getInstance({ 16 | // default drag options 17 | DragOptions: { cursor: 'pointer', zIndex: 2000 }, 18 | // the overlays to decorate each connection with. note that the label overlay uses a function to generate the label text; in this 19 | // case it returns the 'labelText' member that we set on each connection in the 'init' method below. 20 | ConnectionOverlays: [ 21 | ["Arrow", { 22 | location: 1, 23 | visible: true, 24 | width: 11, 25 | length: 11, 26 | id: "ARROW", 27 | events: { 28 | click: function () { alert("you clicked on the arrow overlay") } 29 | } 30 | }], 31 | ["Label", { 32 | location: 0.1, 33 | id: "label", 34 | cssClass: "aLabel", 35 | events: { 36 | // connection.getOverlay("label") 37 | tap: function () { 38 | let label = prompt("请输入标签文字:"); 39 | this.setLabel(label); 40 | } 41 | } 42 | }] 43 | ], 44 | Container: "canvas" 45 | }); 46 | 47 | var basicType = { 48 | connector: "StateMachine", 49 | paintStyle: { stroke: "red", strokeWidth: 4 }, 50 | hoverPaintStyle: { stroke: "blue" }, 51 | overlays: [ 52 | "Arrow" 53 | ] 54 | }; 55 | instance.registerConnectionType("basic", basicType); 56 | 57 | // this is the paint style for the connecting lines.. 58 | var connectorPaintStyle = { 59 | strokeWidth: 2, 60 | stroke: "#61B7CF", 61 | joinstyle: "round", 62 | outlineStroke: "white", 63 | outlineWidth: 2 64 | }, 65 | // .. and this is the hover style. 66 | connectorHoverStyle = { 67 | strokeWidth: 3, 68 | stroke: "#216477", 69 | outlineWidth: 5, 70 | outlineStroke: "white" 71 | }, 72 | endpointHoverStyle = { 73 | fill: "#216477", 74 | stroke: "#216477" 75 | }, 76 | // the definition of source endpoints (the small blue ones) 77 | sourceEndpoint = { 78 | endpoint: "Dot", 79 | paintStyle: { 80 | stroke: "#7AB02C", 81 | fill: "transparent", 82 | radius: 7, 83 | strokeWidth: 1 84 | }, 85 | isSource: true, 86 | connector: ["Flowchart", { stub: [40, 60], gap: 10, cornerRadius: 5, alwaysRespectStubs: true }], 87 | connectorStyle: connectorPaintStyle, 88 | hoverPaintStyle: endpointHoverStyle, 89 | connectorHoverStyle: connectorHoverStyle, 90 | dragOptions: {}, 91 | overlays: [ 92 | ["Label", { 93 | location: [0.5, 1.5], 94 | label: "Drag", 95 | cssClass: "endpointSourceLabel", 96 | visible: false 97 | }] 98 | ] 99 | }, 100 | // the definition of target endpoints (will appear when the user drags a connection) 101 | targetEndpoint = { 102 | endpoint: "Dot", 103 | paintStyle: { fill: "#7AB02C", radius: 7 }, 104 | hoverPaintStyle: endpointHoverStyle, 105 | maxConnections: -1, 106 | dropOptions: { hoverClass: "hover", activeClass: "active" }, 107 | isTarget: true, 108 | overlays: [ 109 | ["Label", { location: [0.5, -0.5], label: "Drop", cssClass: "endpointTargetLabel", visible: false }] 110 | ] 111 | }, 112 | init = function (connection) { 113 | connection.getOverlay("label").setLabel(connection.sourceId.substring(15) + "-" + connection.targetId.substring(15)); 114 | }; 115 | 116 | var _addEndpoints = function (toId, sourceAnchors, targetAnchors) { 117 | for (var i = 0; i < sourceAnchors.length; i++) { 118 | var sourceUUID = toId + sourceAnchors[i]; 119 | instance.addEndpoint("flowchart" + toId, sourceEndpoint, { 120 | anchor: sourceAnchors[i], uuid: sourceUUID 121 | }); 122 | } 123 | for (var j = 0; j < targetAnchors.length; j++) { 124 | var targetUUID = toId + targetAnchors[j]; 125 | instance.addEndpoint("flowchart" + toId, targetEndpoint, { anchor: targetAnchors[j], uuid: targetUUID }); 126 | } 127 | }; 128 | 129 | // suspend drawing and initialise. 130 | instance.batch(function () { 131 | 132 | _addEndpoints("Window4", ["TopCenter", "BottomCenter"], ["LeftMiddle", "RightMiddle"]); 133 | _addEndpoints("Window2", ["LeftMiddle", "BottomCenter"], ["TopCenter", "RightMiddle"]); 134 | _addEndpoints("Window3", ["RightMiddle", "BottomCenter"], ["LeftMiddle", "TopCenter"]); 135 | _addEndpoints("Window1", ["LeftMiddle", "RightMiddle"], ["TopCenter", "BottomCenter"]); 136 | 137 | // listen for new connections; initialise them the same way we initialise the connections at startup. 138 | instance.bind("connection", function (connInfo, originalEvent) { 139 | init(connInfo.connection); 140 | }); 141 | 142 | // make all the window divs draggable 143 | instance.draggable(jsPlumb.getSelector(".flowchart-demo .window"), { grid: [20, 20] }); 144 | // THIS DEMO ONLY USES getSelector FOR CONVENIENCE. Use your library's appropriate selector 145 | // method, or document.querySelectorAll: 146 | //jsPlumb.draggable(document.querySelectorAll(".window"), { grid: [20, 20] }); 147 | 148 | // connect a few up 149 | instance.connect({ uuids: ["Window1TopCenter", "Window2LeftMiddle"], editable: true }); 150 | instance.connect({ uuids: ["Window2BottomCenter", "Window3TopCenter"], editable: true }); 151 | instance.connect({ uuids: ["Window3LeftMiddle", "Window4RightMiddle"], editable: true }); 152 | // listen for clicks on connections, and offer to delete connections on click. 153 | // 154 | instance.bind("click", function (conn, originalEvent) { 155 | // if (confirm("Delete connection from " + conn.sourceId + " to " + conn.targetId + "?")) 156 | // instance.detach(conn); 157 | conn.toggleType("basic"); 158 | }); 159 | 160 | instance.bind("connectionDrag", function (connection) { 161 | console.log("connection " + connection.id + " is being dragged. suspendedElement is ", connection.suspendedElement, " of type ", connection.suspendedElementType); 162 | }); 163 | 164 | instance.bind("connectionDragStop", function (connection) { 165 | console.log("connection " + connection.id + " was dragged"); 166 | }); 167 | 168 | instance.bind("connectionMoved", function (params) { 169 | console.log("connection " + params.connection.id + " was moved"); 170 | }); 171 | }); 172 | 173 | jsPlumb.fire("jsPlumbDemoLoaded", instance); 174 | 175 | } 176 | 177 | } 178 | --------------------------------------------------------------------------------