├── angular-cli.json
├── e2e
├── app.e2e-spec.ts
├── app.po.ts
└── tsconfig.json
├── karma.conf.js
├── package.json
├── protractor.conf.js
├── src
├── app
│ ├── app.component.html
│ ├── app.component.scss
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── app.routing.ts
│ ├── article
│ │ ├── article-detail
│ │ │ ├── article-detail.component.html
│ │ │ ├── article-detail.component.scss
│ │ │ ├── article-detail.component.spec.ts
│ │ │ ├── article-detail.component.ts
│ │ │ ├── article-detail.service.spec.ts
│ │ │ ├── article-detail.service.ts
│ │ │ ├── comment.ts
│ │ │ └── detail.ts
│ │ ├── article-list
│ │ │ ├── article-list.component.html
│ │ │ ├── article-list.component.scss
│ │ │ ├── article-list.component.spec.ts
│ │ │ ├── article-list.component.ts
│ │ │ ├── article-list.service.spec.ts
│ │ │ ├── article-list.service.ts
│ │ │ └── list.ts
│ │ ├── article-main
│ │ │ ├── article-main.component.html
│ │ │ ├── article-main.component.scss
│ │ │ ├── article-main.component.spec.ts
│ │ │ └── article-main.component.ts
│ │ ├── article.module.ts
│ │ ├── article.routing.ts
│ │ └── showdown
│ │ │ ├── index.ts
│ │ │ ├── showdown.component.html
│ │ │ ├── showdown.component.scss
│ │ │ ├── showdown.component.spec.ts
│ │ │ └── showdown.component.ts
│ ├── home
│ │ ├── home.component.html
│ │ ├── home.component.scss
│ │ ├── home.component.spec.ts
│ │ ├── home.component.ts
│ │ ├── home.service.spec.ts
│ │ ├── home.service.ts
│ │ └── option.ts
│ ├── index.ts
│ ├── menu
│ │ ├── menu.component.html
│ │ ├── menu.component.scss
│ │ ├── menu.component.spec.ts
│ │ ├── menu.component.ts
│ │ ├── menu.service.spec.ts
│ │ └── menu.service.ts
│ ├── search
│ │ ├── articles.ts
│ │ ├── search.component.html
│ │ ├── search.component.scss
│ │ ├── search.component.spec.ts
│ │ ├── search.component.ts
│ │ ├── search.service.spec.ts
│ │ └── search.service.ts
│ ├── shared
│ │ ├── component
│ │ │ ├── back
│ │ │ │ ├── back.component.html
│ │ │ │ ├── back.component.scss
│ │ │ │ ├── back.component.spec.ts
│ │ │ │ ├── back.component.ts
│ │ │ │ └── index.ts
│ │ │ ├── breadcrumb
│ │ │ │ ├── breadcrumb.component.html
│ │ │ │ ├── breadcrumb.component.scss
│ │ │ │ ├── breadcrumb.component.spec.ts
│ │ │ │ ├── breadcrumb.component.ts
│ │ │ │ └── index.ts
│ │ │ ├── copyright
│ │ │ │ ├── copyright.component.html
│ │ │ │ ├── copyright.component.scss
│ │ │ │ ├── copyright.component.spec.ts
│ │ │ │ ├── copyright.component.ts
│ │ │ │ └── index.ts
│ │ │ ├── mdeditor
│ │ │ │ ├── index.ts
│ │ │ │ ├── mdeditor.component.html
│ │ │ │ ├── mdeditor.component.scss
│ │ │ │ ├── mdeditor.component.spec.ts
│ │ │ │ └── mdeditor.component.ts
│ │ │ ├── pagination
│ │ │ │ ├── index.ts
│ │ │ │ ├── pagination.component.html
│ │ │ │ ├── pagination.component.scss
│ │ │ │ ├── pagination.component.spec.ts
│ │ │ │ └── pagination.component.ts
│ │ │ └── tags
│ │ │ │ ├── index.ts
│ │ │ │ ├── tags.component.html
│ │ │ │ ├── tags.component.scss
│ │ │ │ ├── tags.component.spec.ts
│ │ │ │ └── tags.component.ts
│ │ ├── directive
│ │ │ └── local
│ │ │ │ ├── index.ts
│ │ │ │ ├── local.directive.spec.ts
│ │ │ │ └── local.directive.ts
│ │ ├── index.ts
│ │ ├── pipe
│ │ │ ├── safe-style
│ │ │ │ ├── index.ts
│ │ │ │ ├── safe-style.pipe.spec.ts
│ │ │ │ └── safe-style.pipe.ts
│ │ │ └── sanitize
│ │ │ │ ├── index.ts
│ │ │ │ ├── sanitize-html.pipe.spec.ts
│ │ │ │ └── sanitize-html.pipe.ts
│ │ ├── service
│ │ │ ├── admin
│ │ │ │ ├── admin.service.spec.ts
│ │ │ │ ├── admin.service.ts
│ │ │ │ └── index.ts
│ │ │ ├── auth
│ │ │ │ ├── auth.service.spec.ts
│ │ │ │ ├── auth.service.ts
│ │ │ │ └── index.ts
│ │ │ ├── locker
│ │ │ │ ├── index.ts
│ │ │ │ ├── locker.service.spec.ts
│ │ │ │ └── locker.service.ts
│ │ │ ├── mission
│ │ │ │ ├── index.ts
│ │ │ │ ├── mission.service.spec.ts
│ │ │ │ └── mission.service.ts
│ │ │ └── static
│ │ │ │ ├── index.ts
│ │ │ │ ├── static.service.spec.ts
│ │ │ │ └── static.service.ts
│ │ └── shared.module.ts
│ └── user
│ │ ├── user-console
│ │ ├── console-admin
│ │ │ ├── admin-check
│ │ │ │ ├── admin-check.component.html
│ │ │ │ ├── admin-check.component.scss
│ │ │ │ ├── admin-check.component.spec.ts
│ │ │ │ ├── admin-check.component.ts
│ │ │ │ ├── check.service.spec.ts
│ │ │ │ ├── check.service.ts
│ │ │ │ └── list.ts
│ │ │ ├── admin-main
│ │ │ │ ├── admin-main.component.html
│ │ │ │ ├── admin-main.component.scss
│ │ │ │ ├── admin-main.component.spec.ts
│ │ │ │ └── admin-main.component.ts
│ │ │ ├── admin-member
│ │ │ │ ├── admin-member.component.html
│ │ │ │ ├── admin-member.component.scss
│ │ │ │ ├── admin-member.component.spec.ts
│ │ │ │ └── admin-member.component.ts
│ │ │ ├── admin-menu
│ │ │ │ ├── admin-menu.component.html
│ │ │ │ ├── admin-menu.component.scss
│ │ │ │ ├── admin-menu.component.spec.ts
│ │ │ │ └── admin-menu.component.ts
│ │ │ ├── admin-option
│ │ │ │ ├── admin-option.component.html
│ │ │ │ ├── admin-option.component.scss
│ │ │ │ ├── admin-option.component.spec.ts
│ │ │ │ ├── admin-option.component.ts
│ │ │ │ ├── option.service.spec.ts
│ │ │ │ ├── option.service.ts
│ │ │ │ └── option.ts
│ │ │ ├── admin-recommend
│ │ │ │ ├── admin-recommend.component.html
│ │ │ │ ├── admin-recommend.component.scss
│ │ │ │ ├── admin-recommend.component.spec.ts
│ │ │ │ ├── admin-recommend.component.ts
│ │ │ │ ├── list.ts
│ │ │ │ ├── option.ts
│ │ │ │ ├── recommend.service.spec.ts
│ │ │ │ └── recommend.service.ts
│ │ │ ├── admin.module.ts
│ │ │ └── admin.routing.ts
│ │ ├── console-editor
│ │ │ ├── console-editor.component.html
│ │ │ ├── console-editor.component.scss
│ │ │ ├── console-editor.component.spec.ts
│ │ │ ├── console-editor.component.ts
│ │ │ └── index.ts
│ │ ├── console-main
│ │ │ ├── console-main.component.html
│ │ │ ├── console-main.component.scss
│ │ │ ├── console-main.component.spec.ts
│ │ │ └── console-main.component.ts
│ │ ├── console-reply
│ │ │ ├── console-reply.component.html
│ │ │ ├── console-reply.component.scss
│ │ │ ├── console-reply.component.spec.ts
│ │ │ ├── console-reply.component.ts
│ │ │ ├── console-reply.service.spec.ts
│ │ │ ├── console-reply.service.ts
│ │ │ └── reply.ts
│ │ ├── console-setting
│ │ │ ├── console-setting.component.html
│ │ │ ├── console-setting.component.scss
│ │ │ ├── console-setting.component.spec.ts
│ │ │ ├── console-setting.component.ts
│ │ │ ├── setting.service.spec.ts
│ │ │ └── setting.service.ts
│ │ ├── console-subject
│ │ │ ├── console-subject.component.html
│ │ │ ├── console-subject.component.scss
│ │ │ ├── console-subject.component.spec.ts
│ │ │ ├── console-subject.component.ts
│ │ │ ├── console-subject.service.spec.ts
│ │ │ ├── console-subject.service.ts
│ │ │ └── subject.ts
│ │ ├── console-write
│ │ │ ├── console-write.component.html
│ │ │ ├── console-write.component.scss
│ │ │ ├── console-write.component.spec.ts
│ │ │ ├── console-write.component.ts
│ │ │ ├── console-write.service.spec.ts
│ │ │ └── console-write.service.ts
│ │ ├── console.module.ts
│ │ └── console.routing.ts
│ │ ├── user-login
│ │ ├── login.component.html
│ │ ├── login.component.scss
│ │ ├── login.component.spec.ts
│ │ ├── login.component.ts
│ │ ├── login.service.spec.ts
│ │ ├── login.service.ts
│ │ └── user.ts
│ │ ├── user-main
│ │ ├── user-main.component.html
│ │ ├── user-main.component.scss
│ │ ├── user-main.component.spec.ts
│ │ └── user-main.component.ts
│ │ ├── user-register
│ │ ├── register.component.html
│ │ ├── register.component.scss
│ │ ├── register.component.spec.ts
│ │ ├── register.component.ts
│ │ ├── register.service.spec.ts
│ │ ├── register.service.ts
│ │ └── user.ts
│ │ ├── user.module.ts
│ │ └── user.routing.ts
├── assets
│ ├── .gitkeep
│ ├── .npmignore
│ ├── css
│ │ ├── atom-one-dark.css
│ │ ├── iconfont.css
│ │ ├── markdown.scss
│ │ ├── simplemde.css
│ │ └── skeleton.css
│ ├── fonts
│ │ ├── en_US.aff
│ │ ├── en_US.dic
│ │ ├── futura.ttf
│ │ ├── iconfont.css
│ │ ├── iconfont.eot
│ │ ├── iconfont.js
│ │ ├── iconfont.svg
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ └── material.woff2
│ ├── images
│ │ ├── default_bg.jpeg
│ │ └── default_photo.png
│ └── sass
│ │ ├── _normalize.scss
│ │ ├── _theme.scss
│ │ ├── _variables.scss
│ │ ├── _vendor-prefixes.scss
│ │ └── master.scss
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
├── test.ts
├── tsconfig.json
└── typings.d.ts
├── static-deploy.js
└── tslint.json
/angular-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "project": {
3 | "version": "1.0.0-beta.22",
4 | "name": "sails-blog-frontend"
5 | },
6 | "apps": [
7 | {
8 | "root": "src",
9 | "outDir": "dist",
10 | "assets": [
11 | "assets",
12 | "favicon.ico"
13 | ],
14 | "index": "index.html",
15 | "main": "main.ts",
16 | "test": "test.ts",
17 | "tsconfig": "tsconfig.json",
18 | "prefix": "app",
19 | "mobile": false,
20 | "styles": [
21 | "styles.css",
22 | "../node_modules/ng2-toasty/style.css",
23 | "assets/sass/master.scss"
24 | ],
25 | "scripts": [],
26 | "environments": {
27 | "source": "environments/environment.ts",
28 | "dev": "environments/environment.ts",
29 | "prod": "environments/environment.prod.ts"
30 | }
31 | }
32 | ],
33 | "addons": [],
34 | "packages": [],
35 | "e2e": {
36 | "protractor": {
37 | "config": "./protractor.conf.js"
38 | }
39 | },
40 | "test": {
41 | "karma": {
42 | "config": "./karma.conf.js"
43 | }
44 | },
45 | "defaults": {
46 | "styleExt": "scss",
47 | "prefixInterfaces": false,
48 | "inline": {
49 | "style": false,
50 | "template": false
51 | },
52 | "spec": {
53 | "class": false,
54 | "component": true,
55 | "directive": true,
56 | "module": false,
57 | "pipe": true,
58 | "service": true
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { NgPage } from './app.po';
2 |
3 | describe('ng App', function() {
4 | let page: NgPage;
5 |
6 | beforeEach(() => {
7 | page = new NgPage();
8 | });
9 |
10 | it('should display message saying app works', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('app works!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, element, by } from 'protractor';
2 |
3 | export class NgPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "declaration": false,
5 | "emitDecoratorMetadata": true,
6 | "experimentalDecorators": true,
7 | "module": "commonjs",
8 | "moduleResolution": "node",
9 | "outDir": "../dist/out-tsc-e2e",
10 | "sourceMap": true,
11 | "target": "es5",
12 | "typeRoots": [
13 | "../node_modules/@types"
14 | ]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/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-remap-istanbul'),
12 | require('angular-cli/plugins/karma')
13 | ],
14 | files: [
15 | { pattern: './src/test.ts', watched: false }
16 | ],
17 | preprocessors: {
18 | './src/test.ts': ['angular-cli']
19 | },
20 | remapIstanbulReporter: {
21 | reports: {
22 | html: 'coverage',
23 | lcovonly: './coverage/coverage.lcov'
24 | }
25 | },
26 | angularCli: {
27 | config: './angular-cli.json',
28 | environment: 'dev'
29 | },
30 | reporters: ['progress', 'karma-remap-istanbul'],
31 | port: 9876,
32 | colors: true,
33 | logLevel: config.LOG_INFO,
34 | autoWatch: true,
35 | browsers: ['Chrome'],
36 | singleRun: false
37 | });
38 | };
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tcome-frontend",
3 | "version": "1.1.0",
4 | "license": "MIT",
5 | "angular-cli": {},
6 | "scripts": {
7 | "start": "ng serve -port 3001 -dev",
8 | "start_pro": "ng serve -port 3001 -prod",
9 | "lint": "tslint \"src/**/*.ts\"",
10 | "test": "ng test",
11 | "pree2e": "webdriver-manager update",
12 | "e2e": "protractor",
13 | "build": "ng build -prod -aot",
14 | "build-static": "node static-deploy.js"
15 | },
16 | "private": true,
17 | "dependencies": {
18 | "@angular/common": "~4.0.0-beta.3",
19 | "@angular/compiler": "~4.0.0-beta.3",
20 | "@angular/core": "~4.0.0-beta.3",
21 | "@angular/forms": "~4.0.0-beta.3",
22 | "@angular/http": "~4.0.0-beta.3",
23 | "@angular/material": "^2.0.0-beta.1",
24 | "@angular/platform-browser": "~4.0.0-beta.3",
25 | "@angular/platform-browser-dynamic": "~4.0.0-beta.3",
26 | "@angular/router": "~4.0.0-beta.3",
27 | "angular2-moment": "^1.0.0",
28 | "core-js": "^2.4.1",
29 | "highlight": "^0.2.4",
30 | "highlight.js": "^9.9.0",
31 | "markdown": "^0.5.0",
32 | "moment": "^2.17.1",
33 | "ng2-responsive": "^0.8.3",
34 | "ng2-toasty": "^2.2.2",
35 | "remarkable": "^1.7.1",
36 | "rxjs": "^5.0.3",
37 | "showdown": "^1.5.4",
38 | "simplemde": "^1.11.2",
39 | "ts-helpers": "^1.1.1",
40 | "zone.js": "^0.7.2"
41 | },
42 | "devDependencies": {
43 | "@angular/compiler-cli": "^2.3.1",
44 | "@types/jasmine": "^2.2.30",
45 | "@types/node": "^6.0.42",
46 | "angular-cli": "1.0.0-beta.25.5",
47 | "codelyzer": "~2.0.0-beta.4",
48 | "jasmine-core": "2.5.2",
49 | "jasmine-spec-reporter": "3.2.0",
50 | "karma": "1.4.0",
51 | "karma-chrome-launcher": "^2.0.0",
52 | "karma-cli": "^1.0.1",
53 | "karma-jasmine": "^1.0.2",
54 | "karma-remap-istanbul": "^0.4.0",
55 | "node-sass": "^3.10.1",
56 | "protractor": "5.0.0",
57 | "qiniu": "^6.1.13",
58 | "ts-node": "2.0.0",
59 | "tslint": "4.3.1",
60 | "typescript": "2.1.5",
61 | "webdriver-manager": "10.2.5"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/docs/referenceConf.js
3 |
4 | /*global jasmine */
5 | var SpecReporter = require('jasmine-spec-reporter');
6 |
7 | exports.config = {
8 | allScriptsTimeout: 11000,
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: 30000,
21 | print: function() {}
22 | },
23 | useAllAngular2AppRoots: true,
24 | beforeLaunch: function() {
25 | require('ts-node').register({
26 | project: 'e2e'
27 | });
28 | },
29 | onPrepare: function() {
30 | jasmine.getEnv().addReporter(new SpecReporter());
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 | @import "../assets/sass/variables";
2 | // 主页相关样式
3 | //
4 |
5 | .app-body {
6 | height: 100%;
7 | flex: 1;
8 | display: flex;
9 | flex-flow: row;
10 | >.app-list {
11 | position: fixed;
12 | top: 0;
13 | left: 0;
14 | bottom: 0;
15 | width: 350px;
16 | height: 100%;
17 | z-index: 10;
18 | }
19 | >.app-content {
20 | flex: 1;
21 | overflow-x: hidden;
22 | height: 100%;
23 | margin-left: 350px;
24 | background: #FCFCFC;
25 | }
26 | }
27 |
28 |
29 |
30 |
31 | // mobile
32 |
33 |
34 | .mobile-body {
35 | width: 100%;
36 | height: 100%;
37 | flex: 1;
38 | display: flex;
39 | flex-flow: row;
40 | >.mobile-list {
41 |
42 | }
43 | >.mobile-content {
44 | flex: 1;
45 | overflow-x: hidden;
46 | height: 100%;
47 | background: #FCFCFC;
48 | padding-top: 50px;
49 | }
50 | }
--------------------------------------------------------------------------------
/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: Ng', () => {
7 | beforeEach(() => {
8 | TestBed.configureTestingModule({
9 | declarations: [
10 | AppComponent
11 | ],
12 | });
13 | });
14 |
15 | it('should create the app', async(() => {
16 | let fixture = TestBed.createComponent(AppComponent);
17 | let app = fixture.debugElement.componentInstance;
18 | expect(app).toBeTruthy();
19 | }));
20 |
21 | it(`should have as title 'app works!'`, async(() => {
22 | let fixture = TestBed.createComponent(AppComponent);
23 | let app = fixture.debugElement.componentInstance;
24 | expect(app.title).toEqual('app works!');
25 | }));
26 |
27 | it('should render title in a h1 tag', async(() => {
28 | let fixture = TestBed.createComponent(AppComponent);
29 | fixture.detectChanges();
30 | let compiled = fixture.debugElement.nativeElement;
31 | expect(compiled.querySelector('h1').textContent).toContain('app works!');
32 | }));
33 | });
34 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, AfterViewInit, ViewChild} from '@angular/core'
2 | import {Title} from '@angular/platform-browser'
3 |
4 | import {MissionService} from './shared/service/mission'
5 | import {StaticService} from './shared/service/static'
6 |
7 | @Component({
8 | selector: 'app-root',
9 | templateUrl: './app.component.html',
10 | styleUrls: ['./app.component.scss'],
11 | providers: []
12 | })
13 | export class AppComponent{
14 | constructor (
15 | private missionService: MissionService,
16 | private titleService: Title,
17 | private staticService: StaticService
18 | ){
19 | // 订阅子组件通知 通知至所有子组件
20 | missionService.missionConfirmed$.subscribe(
21 | astronaut =>{
22 | missionService.announceMission(astronaut)
23 | }
24 | )
25 | }
26 |
27 | ngAfterViewInit (){
28 | this.titleService.setTitle('欢迎-维特博客')
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import {BrowserModule} from '@angular/platform-browser'
2 | import {CommonModule} from '@angular/common'
3 | import {FormsModule} from '@angular/forms'
4 | import {NgModule} from '@angular/core'
5 | import {HttpModule} from '@angular/http'
6 | import {RouterModule} from '@angular/router'
7 | import {MomentModule} from 'angular2-moment'
8 | import {ToastyModule} from 'ng2-toasty';
9 | import {SharedModule} from './shared/shared.module'
10 | import {ResponsiveModule, ResponsiveConfig} from 'ng2-responsive'
11 |
12 | import {AppComponent} from './app.component'
13 | import {AppRoutingModule} from './app.routing'
14 | import {MenuComponent} from './menu/menu.component'
15 | import {HomeComponent} from './home/home.component'
16 | import {SearchComponent} from './search/search.component'
17 | import {AuthService} from './shared/service/auth'
18 | import {AdminService} from './shared/service/admin'
19 | import {LockerService} from './shared/service/locker'
20 | import {MissionService} from './shared/service/mission'
21 | import {StaticService} from './shared/service/static'
22 |
23 | const config = {
24 | breakPoints: {
25 | xs: {max: 600},
26 | sm: {min: 601, max: 959},
27 | md: {min: 960, max: 1279},
28 | lg: {min: 1280, max: 1919},
29 | xl: {min: 1920}
30 | },
31 | debounceTime: 100
32 | };
33 |
34 | export function ResponsiveDefinition (){
35 | return new ResponsiveConfig(config);
36 | }
37 |
38 | @NgModule({
39 | imports: [
40 | ToastyModule.forRoot(),
41 | ResponsiveModule,
42 | BrowserModule,
43 | CommonModule,
44 | FormsModule,
45 | RouterModule,
46 | HttpModule,
47 | SharedModule.forRoot(),
48 | MomentModule,
49 | AppRoutingModule,
50 | ],
51 | declarations: [
52 | AppComponent,
53 | MenuComponent,
54 | HomeComponent,
55 | SearchComponent,
56 | ],
57 | providers: [
58 | MissionService,
59 | LockerService,
60 | AuthService,
61 | AdminService,
62 | {
63 | provide: ResponsiveConfig,
64 | useFactory: ResponsiveDefinition
65 | }
66 | ],
67 | bootstrap: [AppComponent],
68 | })
69 | export class AppModule {
70 | constructor (){
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/app/app.routing.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 16/8/17.
3 | */
4 |
5 | import {NgModule} from '@angular/core'
6 | import {Routes, RouterModule} from '@angular/router'
7 |
8 | import {HomeComponent} from './home/home.component'
9 | import {SearchComponent} from './search/search.component'
10 |
11 | export const appRoutes: Routes = [
12 | {path: '', component: HomeComponent},
13 | {path: 'welcome', component: HomeComponent},
14 | {path: 'search', component: SearchComponent},
15 | {path: 'articles', loadChildren: './article/article.module#ArticleModule', data: {preload: true}},
16 | {path: 'user', loadChildren: './user/user.module#UserModule', data: {preload: false}},
17 | ]
18 |
19 | @NgModule({
20 | imports: [RouterModule.forRoot(appRoutes, { useHash: false })],
21 | exports: [RouterModule]
22 | })
23 | export class AppRoutingModule {
24 | }
--------------------------------------------------------------------------------
/src/app/article/article-detail/article-detail.component.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
{{detail.title}}
12 |
13 | {{detail.authorName}} -
14 | {{detail.createdAt | amDateFormat:'LL'}} -
15 | {{detail.readTotal}} viewed
16 |
17 |
18 |
19 |
20 |
21 |
22 | {{tag}}
23 |
24 |
25 |
26 |
27 |
版权声明
28 |
本文版权属于 维特博客,作者为 {{detail.authorName}},本文仅用于学习、研究和交流目的,欢迎非商业转载。转载
29 | 请务必注明出处、作者及完整链接。
30 |
31 |
32 |
33 |
56 |
57 |
58 |
59 |
5">提交回复
60 |
63 |
64 |
65 |
已提交评论。
66 |
我们希望每一次评论都是深思熟虑的,所以对连续评论作出了一些限制。
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/app/article/article-detail/article-detail.component.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 |
3 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
4 | import { By } from '@angular/platform-browser';
5 | import { DebugElement } from '@angular/core';
6 |
7 | import { ArticleDetailComponent } from './article-detail.component';
8 |
9 | describe('ArticleDetailComponent', () => {
10 | let component: ArticleDetailComponent;
11 | let fixture: ComponentFixture;
12 |
13 | beforeEach(async(() => {
14 | TestBed.configureTestingModule({
15 | declarations: [ ArticleDetailComponent ]
16 | })
17 | .compileComponents();
18 | }));
19 |
20 | beforeEach(() => {
21 | fixture = TestBed.createComponent(ArticleDetailComponent);
22 | component = fixture.componentInstance;
23 | fixture.detectChanges();
24 | });
25 |
26 | it('should create', () => {
27 | expect(component).toBeTruthy();
28 | });
29 | });
30 |
31 |
--------------------------------------------------------------------------------
/src/app/article/article-detail/article-detail.service.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 |
3 | import {TestBed, async, inject} from '@angular/core/testing';
4 | import {ArticleDetailService} from './article-detail.service';
5 |
6 | describe('Service: Detail', () =>{
7 | beforeEach(() =>{
8 | TestBed.configureTestingModule({
9 | providers: [ArticleDetailService]
10 | });
11 | });
12 |
13 | it('should ...', inject([ArticleDetailService], (service: ArticleDetailService) =>{
14 | expect(service).toBeTruthy();
15 | }));
16 | });
17 |
--------------------------------------------------------------------------------
/src/app/article/article-detail/article-detail.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {Http, Response} from '@angular/http'
3 | import {Observable} from 'rxjs/Observable'
4 | import 'rxjs/Rx'
5 |
6 | import {StaticService} from '../../shared/service/static'
7 | import {Detail} from './detail'
8 | import {Comment} from './comment'
9 |
10 | @Injectable()
11 | export class ArticleDetailService {
12 |
13 | constructor(private http: Http,
14 | private staticService: StaticService) {
15 | }
16 |
17 | private detailUrl = this.staticService.makeApi('articles')
18 |
19 | getDetail (id: string): Observable {
20 | return this.http.get(`${this.detailUrl}/${id}`, this.staticService.options())
21 | .map(this.staticService.extractData)
22 | .catch(this.handleError)
23 | }
24 | getComment (id: string): Observable {
25 | return this.http.get(`${this.detailUrl}/${id}/comment`, this.staticService.options())
26 | .map(this.staticService.extractData)
27 | .catch(this.handleError)
28 | }
29 | postComment (id: string, content: any): Observable {
30 |
31 | return this.http.post(`${this.detailUrl}/${id}/comment`, content, this.staticService.options())
32 | .map(this.staticService.extractData)
33 | .catch(this.handleError)
34 | }
35 |
36 | private handleError (error: any){
37 | if(error instanceof Response) {
38 | return Observable.throw(error.status || '服务器错误');
39 | }
40 | return Observable.throw(error || '服务器错误')
41 | }
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/app/article/article-detail/comment.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 2016/12/11.
3 | */
4 |
5 | export class Comment {
6 | authorId: string
7 | authorName: string
8 | content: string
9 | createdAt: string
10 | id: string
11 | avatar?: string
12 | }
--------------------------------------------------------------------------------
/src/app/article/article-detail/detail.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 2016/10/21.
3 | * Detail Model
4 | */
5 |
6 | export class Detail {
7 | id: string // id
8 | title: string // 标题
9 | content: string // 详情
10 | authorId: string // 作者id
11 | authorName: string // 作者名
12 | avatar?: string
13 | thumbnail?: string
14 |
15 | createdAt: string // 创建日期
16 | updatedAt: string // 更新日期
17 | tags: string[] // 标签
18 | readTotal: number // 阅读数
19 | commentTotal: number // 评论数
20 | }
--------------------------------------------------------------------------------
/src/app/article/article-list/article-list.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
{{item.title}}
7 |
{{item.abstract | slice: 0:130}}
8 |
9 |
{{item.authorName}} - {{item.createdAt | amDateFormat:'MM-DD-YYYY'}} - {{item.readTotal}} views
10 |
11 |
12 |
13 |
14 |
![]()
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/app/article/article-list/article-list.component.scss:
--------------------------------------------------------------------------------
1 | .article-list-box {
2 | width: 90%;
3 | max-width: 950px;
4 | min-width: 500px;
5 | height: auto;
6 | margin: 0 auto;
7 | padding: 20px 0;
8 | }
9 | ul.article-list{
10 | width: 100%;
11 | height: auto;
12 | >li {
13 | width: 100%;
14 | height: 195px;
15 | border-bottom: 1px solid #E6E6E6;
16 | padding: 22px 0;
17 | font-family: -apple-system, "Hiragino Sans GB", "Hiragino Sans GB W3", Helvetica, "Microsoft YaHei", sans-serif;
18 | &:last-child {
19 | border-bottom: none;
20 | }
21 | .profiles {
22 | width: 65%;
23 | height: 100%;
24 | float: left;
25 | position: relative;
26 | padding-right: 12px;
27 | &.no-thumbnail {
28 | width: 100%;
29 | }
30 | h3 {
31 | font-size: 24px;
32 | font-weight: normal;
33 | line-height: 30px;
34 | color: #333;
35 | margin-bottom: 8px;
36 | cursor: pointer;
37 | -webkit-transition: all 0.15s;
38 | -moz-transition: all 0.15s;
39 | -o-transition: all 0.15s;
40 | transition: all 0.15s;
41 | &:hover {
42 | color: #458fd2;
43 | }
44 | }
45 | p {
46 | font-size: 15px;
47 | color: #828181;
48 | }
49 | .additional {
50 | position: absolute;
51 | padding-right: 12px;
52 | bottom: 0;
53 | left: 0;
54 | right: 0;
55 | width: 100%;
56 | overflow: hidden;
57 | p.author {
58 | float: left;
59 | font-size: 14px;
60 | color: #c7c7c7;
61 | }
62 | p.views {
63 | float: right;
64 | }
65 | }
66 | }
67 | .thumbnail {
68 | width: 35%;
69 | height: 100%;
70 | float: right;
71 | img {
72 | width: 100%;
73 | height: 100%;
74 | }
75 | }
76 | }
77 | }
78 |
79 |
80 |
81 | // mobile
82 | .mobile-article-list {
83 | width:100%;
84 | height: auto;
85 | margin: 0 auto;
86 | padding: 0 8px;
87 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif;
88 | >ul{
89 | width: 100%;
90 | >li {
91 | width: 100%;
92 | height: auto;
93 | border-bottom: 1px solid #E6E6E6;
94 | padding: 15px 0;
95 |
96 | h3 {
97 | font-size: 18px;
98 | font-weight: normal;
99 | line-height: 20px;
100 | color: #4094C7;
101 | margin-bottom: 5px;
102 | cursor: pointer;
103 | }
104 | p {
105 | font-size: 13px;
106 | }
107 | .mobile-article-list-additional {
108 | padding-top: 10px;
109 | width: 100%;
110 | overflow: hidden;
111 | color: #9ba9b5;
112 | p.author {
113 | float: left;
114 | font-size: 12px;
115 | }
116 | p.views {
117 | float: right;
118 | font-size: 12px;
119 | }
120 | }
121 | }
122 | }
123 | }
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/src/app/article/article-list/article-list.component.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 |
3 | import {TestBed, async} from '@angular/core/testing';
4 | import {ArticleListComponent} from './article-list.component';
5 |
6 | describe('Component: list', () =>{
7 | it('should create an instance', () =>{
8 | let component = new ArticleListComponent();
9 | expect(component).toBeTruthy();
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/src/app/article/article-list/article-list.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core'
2 | import {Title} from '@angular/platform-browser'
3 | import {Router, ActivatedRoute, Params} from '@angular/router'
4 | import {StaticService} from '../../shared/service/static'
5 |
6 | import {List} from './list'
7 | import {ArticleListService} from './article-list.service'
8 |
9 | @Component({
10 | selector: 'app-article-list',
11 | templateUrl: './article-list.component.html',
12 | styleUrls: ['./article-list.component.scss'],
13 | providers: [ArticleListService]
14 | })
15 | export class ArticleListComponent implements OnInit {
16 |
17 | constructor(
18 | private listService: ArticleListService,
19 | private titleService: Title,
20 | private router: Router,
21 | private route: ActivatedRoute,
22 | private staticService: StaticService
23 | ) {}
24 |
25 | list: List[]
26 | errorMessage: string
27 | public activePage: number = 1
28 | public listOver: boolean = false
29 |
30 | getList(pageSize:number = 1) {
31 | this.activePage = ~~pageSize? pageSize: 1
32 | this.listService.getList(this.activePage)
33 | .subscribe(
34 | res => {
35 | if (res&& res.list){
36 | this.list = res.list
37 | this.checkOver(res.total)
38 | }
39 | },
40 | error => {
41 | this.errorMessage = error.json().message
42 | }
43 | )
44 | }
45 | checkOver (total: number){
46 | if (total&& total / 15 <= this.activePage){
47 | return this.listOver = true
48 | }
49 | this.listOver = false
50 | }
51 |
52 | goNext (path){
53 | this.router.navigate(['/articles/list', path])
54 | }
55 | pageNext (page: number){
56 | this.router.navigate(['/articles/list/page', page])
57 | }
58 |
59 | ngOnInit() {
60 | this.titleService.setTitle('文章列表-维特博客')
61 | this.route.params
62 | .forEach((params: Params) => this.getList(+params['p']))
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/app/article/article-list/article-list.service.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 |
3 | import {TestBed, async, inject} from '@angular/core/testing';
4 | import {ArticleListService} from './article-list.service';
5 |
6 | describe('Service: articleListService', () => {
7 | beforeEach(() => {
8 | TestBed.configureTestingModule({
9 | providers: [ArticleListService]
10 | });
11 | });
12 |
13 | it('should ...', inject([ArticleListService], (service: ArticleListService) => {
14 | expect(service).toBeTruthy();
15 | }));
16 | });
17 |
--------------------------------------------------------------------------------
/src/app/article/article-list/article-list.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core'
2 | import {Http, Response} from '@angular/http'
3 | import {Observable} from 'rxjs/Observable'
4 | import {Headers, RequestOptions} from '@angular/http'
5 | import 'rxjs/Rx'
6 |
7 | import {List} from './list'
8 | import {StaticService} from '../../shared/service/static'
9 |
10 | @Injectable()
11 | export class ArticleListService {
12 |
13 | constructor (
14 | private http: Http,
15 | private staticService: StaticService
16 | ){
17 | }
18 |
19 | private listUrl = this.staticService.makeApi('articles')
20 |
21 | getList (pageSize): Observable{
22 | return this.http.get(`${this.listUrl}?page=${pageSize}`)
23 | .map(this.extractData)
24 | .catch(this.handleError)
25 | }
26 |
27 | public extractData(res: Response) {
28 | // 存在总数限制,通知其他组件
29 | const total = res.headers.get('total')
30 |
31 | if (res.status != 204) return {list: res.json(), total: ~~total} || {}
32 | return {}
33 | }
34 |
35 | private handleError (error: any){
36 | return Observable.throw(error || '服务器错误')
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/app/article/article-list/list.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 2016/10/19.
3 | * List Model
4 | */
5 |
6 | export class List {
7 | id: string // id
8 | title: string // 标题
9 | createdAt: string // 创建日期
10 | readTotal: number // 阅读数
11 | commentTotal: number // 评论数
12 | authorName: string // 用户姓名
13 | thumbnail?: string
14 | }
--------------------------------------------------------------------------------
/src/app/article/article-main/article-main.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/article/article-main/article-main.component.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unix/tcome-frontend/78c14565ed740a46e92c7e1a9754c552ce317438/src/app/article/article-main/article-main.component.scss
--------------------------------------------------------------------------------
/src/app/article/article-main/article-main.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 { ArticleMainComponent } from './article-main.component';
7 |
8 | describe('ArticleMainComponent', () => {
9 | let component: ArticleMainComponent;
10 | let fixture: ComponentFixture;
11 |
12 | beforeEach(async(() => {
13 | TestBed.configureTestingModule({
14 | declarations: [ ArticleMainComponent ]
15 | })
16 | .compileComponents();
17 | }));
18 |
19 | beforeEach(() => {
20 | fixture = TestBed.createComponent(ArticleMainComponent);
21 | component = fixture.componentInstance;
22 | fixture.detectChanges();
23 | });
24 |
25 | it('should create', () => {
26 | expect(component).toBeTruthy();
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/app/article/article-main/article-main.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-article-main',
5 | templateUrl: './article-main.component.html',
6 | styleUrls: ['./article-main.component.scss']
7 | })
8 | export class ArticleMainComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/article/article.module.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 2017/1/25.
3 | * @description :: article module
4 | */
5 | import {NgModule} from '@angular/core'
6 | import {CommonModule} from '@angular/common'
7 | import {FormsModule} from '@angular/forms'
8 | import {HttpModule} from '@angular/http'
9 | import {MomentModule} from 'angular2-moment'
10 | import {SharedModule} from '../shared/shared.module'
11 | import {ResponsiveModule} from 'ng2-responsive'
12 |
13 | import {ArticleRoutingModule} from './article.routing'
14 | import {ShowdownComponent} from './showdown/showdown.component'
15 | import {ArticleMainComponent} from './article-main/article-main.component'
16 | import {ArticleListComponent} from './article-list/article-list.component'
17 | import {ArticleDetailComponent} from './article-detail/article-detail.component'
18 |
19 | @NgModule({
20 | declarations: [
21 | ArticleMainComponent,
22 | ShowdownComponent,
23 | ArticleListComponent,
24 | ArticleDetailComponent
25 | ],
26 | imports: [
27 | SharedModule,
28 | CommonModule,
29 | FormsModule,
30 | HttpModule,
31 | MomentModule,
32 | ArticleRoutingModule,
33 | ResponsiveModule
34 | ],
35 | exports: [ArticleMainComponent],
36 | providers: []
37 | })
38 | export class ArticleModule {
39 | }
--------------------------------------------------------------------------------
/src/app/article/article.routing.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 2017/1/25.
3 | * @description :: article route
4 | */
5 | import {NgModule} from '@angular/core'
6 | import {Routes, RouterModule} from '@angular/router'
7 |
8 | import {ArticleMainComponent} from './article-main/article-main.component'
9 | import {ArticleListComponent} from './article-list/article-list.component'
10 | import {ArticleDetailComponent} from './article-detail/article-detail.component'
11 |
12 | const userRoutes: Routes = [{
13 | path: '', component: ArticleMainComponent,
14 | children: [{
15 | path: '', redirectTo:'list',pathMatch:'full'
16 | },{
17 | path: 'list', component: ArticleListComponent
18 | },{
19 | path: 'list/page/:p', component: ArticleListComponent
20 | },{
21 | path: 'list/:id', component: ArticleDetailComponent
22 | }]
23 | }]
24 |
25 | @NgModule({
26 | imports: [RouterModule.forChild(userRoutes)],
27 | exports: [RouterModule]
28 | })
29 | export class ArticleRoutingModule {
30 | }
--------------------------------------------------------------------------------
/src/app/article/showdown/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by WittBulter on 2016/12/24.
3 | */
4 |
5 | import {ShowdownComponent} from './showdown.component'
6 |
7 | export {ShowdownComponent}
--------------------------------------------------------------------------------
/src/app/article/showdown/showdown.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/app/article/showdown/showdown.component.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/app/article/showdown/showdown.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 { ShowdownComponent } from './showdown.component';
7 |
8 | describe('ShowdownComponent', () => {
9 | let component: ShowdownComponent;
10 | let fixture: ComponentFixture;
11 |
12 | beforeEach(async(() => {
13 | TestBed.configureTestingModule({
14 | declarations: [ ShowdownComponent ]
15 | })
16 | .compileComponents();
17 | }));
18 |
19 | beforeEach(() => {
20 | fixture = TestBed.createComponent(ShowdownComponent);
21 | component = fixture.componentInstance;
22 | fixture.detectChanges();
23 | });
24 |
25 | it('should create', () => {
26 | expect(component).toBeTruthy();
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/app/article/showdown/showdown.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, Input, AfterViewInit, OnInit} from '@angular/core'
2 |
3 | const Remarkable = require('remarkable')
4 | const hljs = require('highlight.js')
5 |
6 | @Component({
7 | selector: 'app-showdown',
8 | templateUrl: './showdown.component.html',
9 | styleUrls: ['./showdown.component.scss']
10 | })
11 | export class ShowdownComponent implements OnInit {
12 |
13 | constructor (){
14 | }
15 |
16 | @Input() html: string = ''
17 | public innerHTML: any
18 |
19 | ngOnInit (){
20 | const md = new Remarkable({
21 | highlight: (str, lang) =>{
22 | if (lang && hljs.getLanguage(lang)) {
23 | try {
24 | return hljs.highlight(lang, str).value;
25 | } catch (err) {}
26 | }
27 | try {
28 | return hljs.highlightAuto(str).value;
29 | } catch (err) {
30 |
31 | }
32 | return ''
33 | }
34 | })
35 | this.innerHTML = md.render(this.html)
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Today's Special
4 |
11 |
12 |
13 |
{{option.blogName?option.blogName: 'NEW BLOG'}}
14 |
{{option.blogSubhead}}
15 |
16 |
17 |
18 |
19 |
20 |
{{option.blogName?option.blogName: 'NEW BLOG'}} Today's Special
21 |
{{option.blogSubhead}}
22 |
23 |
30 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/app/home/home.component.scss:
--------------------------------------------------------------------------------
1 |
2 | .content {
3 | width: 1100px;
4 | margin: 0 auto;
5 | padding-left: 200px;
6 | padding-top: 150px;
7 | overflow: hidden;
8 | .recommended {
9 | width: 50%;
10 | float: left;
11 | padding-right: 20px;
12 | border-right: 2px solid #eee;
13 | min-height: 300px;
14 | padding-bottom: 50px;
15 | h2 {
16 | font-family: "futura-pt", sans-serif;
17 | font-weight: normal;
18 | font-size: 26px;
19 | text-align: right;
20 | line-height: 2.2;
21 | color: #404040;
22 | }
23 | > ul {
24 | width: 100%;
25 | li {
26 | width: 100%;
27 | text-align: right;
28 | margin-bottom: 10px;
29 | h3 {
30 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif;
31 | font-weight: 300;
32 | font-size: 20px;
33 | a {
34 | color: #4094C7;
35 | text-decoration: none;
36 | }
37 | }
38 | p {
39 | font-size: 13px;
40 | color: #ccc;
41 | line-height: 1;
42 | }
43 | }
44 | }
45 | }
46 | .welcome {
47 | width: 50%;
48 | float: right;
49 | padding-left: 10px;
50 | padding-top: 30px;
51 | overflow: hidden;
52 | font-family: "futura-pt", sans-serif;
53 | h1 {
54 | font-weight: normal;
55 | font-size: 30px;
56 | color: #404040;
57 | line-height: 2.2;
58 | }
59 | p {
60 | font-size: 18px;
61 | font-weight: normal;
62 | color: #404040;
63 | border-bottom: 1px solid #eee;
64 | display: inline-block;
65 | word-wrap: break-word;
66 | }
67 | }
68 |
69 | }
70 |
71 | //mobile
72 |
73 | .mobile-home {
74 | width: 100%;
75 | height: auto;
76 | padding-left: 6%;
77 | .mobile-home-title {
78 | font-family: "futura-pt", sans-serif;
79 | margin-top: 20px;
80 | h1 {
81 | font-weight: normal;
82 | font-size: 22px;
83 | color: #404040;
84 | line-height: 2.2;
85 | border-bottom: 2px solid #eee;
86 | >span {
87 | font-size: 14px;
88 | }
89 | }
90 | p {
91 | font-size: 14px;
92 | font-weight: normal;
93 | color: #404040;
94 | display: inline-block;
95 | word-wrap: break-word;
96 | }
97 | }
98 | .mobile-home-list {
99 | width: 100%;
100 | margin-top: 30px;
101 | >li {
102 | width: 100%;
103 | text-align: left;
104 | margin-bottom: 10px;
105 | h3 {
106 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif;
107 | font-weight: 300;
108 | font-size: 16px;
109 | a {
110 | color: #4094C7;
111 | text-decoration: none;
112 | }
113 | }
114 | p {
115 | font-size: 13px;
116 | color: #ccc;
117 | line-height: 1;
118 | }
119 | }
120 | }
121 |
122 | }
123 |
124 | .mobile-home-tips{
125 | width: 100%;
126 | position: fixed;
127 | left: 0;
128 | right: 0;
129 | bottom: 5px;
130 | text-align: center;
131 | font-size: 14px;
132 | font-weight: 300;
133 | color: #ccc;
134 | }
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/src/app/home/home.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 { HomeComponent } from './home.component';
7 |
8 | describe('HomeComponent', () => {
9 | let component: HomeComponent;
10 | let fixture: ComponentFixture;
11 |
12 | beforeEach(async(() => {
13 | TestBed.configureTestingModule({
14 | declarations: [ HomeComponent ]
15 | })
16 | .compileComponents();
17 | }));
18 |
19 | beforeEach(() => {
20 | fixture = TestBed.createComponent(HomeComponent);
21 | component = fixture.componentInstance;
22 | fixture.detectChanges();
23 | });
24 |
25 | it('should create', () => {
26 | expect(component).toBeTruthy();
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/app/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core'
2 | import {Title} from '@angular/platform-browser'
3 |
4 | import {HomeService} from './home.service'
5 | import {Option} from './option'
6 |
7 | @Component({
8 | selector: 'app-home',
9 | templateUrl: './home.component.html',
10 | styleUrls: ['./home.component.scss'],
11 | providers: [HomeService]
12 | })
13 | export class HomeComponent implements OnInit {
14 |
15 | constructor (
16 | private titleService: Title,
17 | private homeService: HomeService
18 | ){
19 | }
20 | public option: Option
21 |
22 | getOption (){
23 | this.homeService.getOption()
24 | .subscribe(
25 | option => {
26 | this.option = option
27 | },
28 | error =>{
29 | console.log(error);
30 | }
31 | )
32 | }
33 |
34 | ngOnInit (){
35 | this.titleService.setTitle('欢迎-维特博客')
36 | this.getOption()
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/app/home/home.service.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 |
3 | import { TestBed, async, inject } from '@angular/core/testing';
4 | import { HomeService } from './home.service';
5 |
6 | describe('HomeService', () => {
7 | beforeEach(() => {
8 | TestBed.configureTestingModule({
9 | providers: [HomeService]
10 | });
11 | });
12 |
13 | it('should ...', inject([HomeService], (service: HomeService) => {
14 | expect(service).toBeTruthy();
15 | }));
16 | });
17 |
--------------------------------------------------------------------------------
/src/app/home/home.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core'
2 | import {Http, Response} from '@angular/http'
3 | import {Observable} from 'rxjs/Observable'
4 | import 'rxjs/Rx'
5 |
6 | import {StaticService} from '../shared/service/static'
7 | import {Option} from './option'
8 |
9 | @Injectable()
10 | export class HomeService {
11 |
12 | constructor (private http: Http,
13 | private staticService: StaticService){
14 | }
15 |
16 | private optionLink = this.staticService.makeApi('option')
17 |
18 | getOption ():Observable
{{c.authorName}}
43 | {{c.createdAt | amDateFormat:'LL'}} 44 |