├── .gitignore
├── README.md
├── conf
├── styleLoaderConf.js
├── webpack.config.js
├── webpack.dev.conf.js
├── webpack.dll.conf.js
└── webpack.prod.conf.js
├── demos
├── app.component.ts
├── app.module.ts
├── app.routes.ts
├── app.ts
├── crisis-list
│ ├── component.ts
│ ├── crisis-list.component.html
│ └── module.ts
├── heroes-list
│ ├── component.ts
│ ├── heroes-list.component.html
│ └── module.ts
├── index.html
├── miniapp
│ ├── about.component.ts
│ ├── app-routing.module.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── home.component.ts
│ ├── index.html
│ ├── index.ts
│ └── main.ts
├── not-found.component.ts
├── tsconfig.json
└── webpack.config.js
├── package.json
├── pnpm-lock.yaml
├── src
├── antd
│ ├── demos.ts
│ ├── directive.ts
│ ├── module.ts
│ └── ngModule.ts
├── app.ts
├── app
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── app.routing.ts
│ ├── article
│ │ ├── addarticle
│ │ │ ├── addarticle.html
│ │ │ ├── addarticle.service.ts
│ │ │ └── addarticle.ts
│ │ ├── article.component.ts
│ │ ├── article.module.ts
│ │ ├── article.routing.ts
│ │ ├── articlelist
│ │ │ ├── articlelist.html
│ │ │ ├── articlelist.service.ts
│ │ │ └── articlelist.ts
│ │ ├── editarticle
│ │ │ ├── editarticle.html
│ │ │ ├── editarticle.service.ts
│ │ │ └── editarticle.ts
│ │ └── model
│ │ │ └── article.model.ts
│ ├── articletype
│ │ ├── addarticletype
│ │ │ ├── addarticletype.html
│ │ │ ├── addarticletype.service.ts
│ │ │ └── addarticletype.ts
│ │ ├── articletype.component.ts
│ │ ├── articletype.module.ts
│ │ ├── articletype.routing.ts
│ │ ├── articletypelist
│ │ │ ├── articletypelist.html
│ │ │ ├── articletypelist.service.ts
│ │ │ └── articletypelist.ts
│ │ ├── editarticletype
│ │ │ ├── editarticletype.html
│ │ │ ├── editarticletype.service.ts
│ │ │ └── editarticletype.ts
│ │ └── model
│ │ │ └── articletype.model.ts
│ ├── charts
│ │ ├── chart.component.ts
│ │ ├── chart.html
│ │ ├── chart.module.ts
│ │ ├── chart.routing.ts
│ │ ├── chart.service.ts
│ │ ├── model
│ │ │ └── chart.model.ts
│ │ └── out-let.component.ts
│ ├── comment
│ │ ├── comment.component.ts
│ │ ├── comment.module.ts
│ │ ├── comment.routing.ts
│ │ ├── commentdetail
│ │ │ ├── commentdetail.html
│ │ │ ├── commentdetail.service.ts
│ │ │ └── commentdetail.ts
│ │ ├── commentlist
│ │ │ ├── commentlist.html
│ │ │ ├── commentlist.service.ts
│ │ │ └── commentlist.ts
│ │ └── model
│ │ │ └── comment.model.ts
│ ├── dashboard
│ │ ├── dashboard.component.ts
│ │ ├── dashboard.html
│ │ ├── dashboard.module.ts
│ │ ├── dashboard.routing.ts
│ │ ├── dashboard.service.ts
│ │ └── index.ts
│ ├── demos
│ │ ├── demos.component.ts
│ │ ├── demos.html
│ │ ├── demos.module.ts
│ │ ├── demos.routing.ts
│ │ ├── demos.service.ts
│ │ ├── models
│ │ │ └── demo.model.ts
│ │ └── out-let.component.ts
│ ├── doubleball
│ │ ├── doubleball.component.ts
│ │ ├── doubleball.module.ts
│ │ ├── doubleball.routing.ts
│ │ ├── doubleballlist
│ │ │ ├── doubleball.directive.ts
│ │ │ ├── doubleballlist.html
│ │ │ ├── doubleballlist.service.ts
│ │ │ └── doubleballlist.ts
│ │ └── model
│ │ │ └── doubleball.model.ts
│ ├── home
│ │ ├── home.component.html
│ │ ├── home.component.ts
│ │ └── index.ts
│ ├── login
│ │ ├── bubble.ts
│ │ ├── login.component.ts
│ │ ├── login.html
│ │ └── style.less
│ ├── systemlogs
│ │ ├── model
│ │ │ └── systemlog.model.ts
│ │ ├── systemlog.component.ts
│ │ ├── systemlog.module.ts
│ │ ├── systemlog.routing.ts
│ │ ├── systemlogdetail
│ │ │ ├── systemlogdetail.html
│ │ │ ├── systemlogdetail.service.ts
│ │ │ └── systemlogdetail.ts
│ │ └── systemloglist
│ │ │ ├── systemloglist.html
│ │ │ ├── systemloglist.service.ts
│ │ │ └── systemloglist.ts
│ ├── tag
│ │ ├── addtag
│ │ │ ├── addtag.html
│ │ │ ├── addtag.service.ts
│ │ │ └── addtag.ts
│ │ ├── edittag
│ │ │ ├── edittag.html
│ │ │ ├── edittag.service.ts
│ │ │ └── edittag.ts
│ │ ├── index.ts
│ │ ├── model
│ │ │ └── tag.model.ts
│ │ ├── tag.component.ts
│ │ ├── tag.module.ts
│ │ ├── tag.routing.ts
│ │ └── taglist
│ │ │ ├── taglist.html
│ │ │ ├── taglist.service.ts
│ │ │ └── taglist.ts
│ └── user
│ │ ├── adduser
│ │ ├── adduser.html
│ │ ├── adduser.service.ts
│ │ └── adduser.ts
│ │ ├── edituser
│ │ ├── edituser.html
│ │ ├── edituser.service.ts
│ │ └── edituser.ts
│ │ ├── index.ts
│ │ ├── model
│ │ └── user.model.ts
│ │ ├── user.component.ts
│ │ ├── user.module.ts
│ │ ├── user.routing.ts
│ │ └── userlist
│ │ ├── userlist.html
│ │ ├── userlist.service.ts
│ │ └── userlist.ts
├── assets
│ ├── i18n
│ │ ├── en.json
│ │ └── zh.json
│ ├── images
│ │ ├── logo.png
│ │ └── logo.svg
│ └── less
│ │ └── index.less
├── components
│ ├── datetime-picker
│ │ ├── datetime-picker.component.ts
│ │ ├── datetime-picker.module.ts
│ │ └── datetime-range.html
│ ├── editor
│ │ ├── editor.component.ts
│ │ ├── editor.html
│ │ └── editor.module.ts
│ ├── shared
│ │ ├── breadcrumb
│ │ │ ├── breadcrumb.component.html
│ │ │ ├── breadcrumb.component.less
│ │ │ └── breadcrumb.component.ts
│ │ ├── header
│ │ │ ├── header.component.html
│ │ │ ├── header.component.less
│ │ │ └── header.component.ts
│ │ ├── index.ts
│ │ └── sidebar
│ │ │ ├── sidebar.component.html
│ │ │ ├── sidebar.component.less
│ │ │ └── sidebar.component.ts
│ └── upload-file
│ │ ├── upload-file.component.ts
│ │ ├── upload-file.directvie.ts
│ │ ├── upload-file.html
│ │ └── upload-file.module.ts
├── index.ts
├── polyfills.ts
├── registerServiceWorker.ts
├── styles
│ ├── global.less
│ ├── index.less
│ ├── tailwind.css
│ └── theme.less
├── template
│ └── index_base.html
├── types
│ ├── custome.d.ts
│ ├── demo.ts
│ ├── global.d.ts
│ └── login.ts
├── utils
│ ├── auth
│ │ ├── auth-guard.service.ts
│ │ └── auth.service.ts
│ ├── echarts
│ │ └── index.ts
│ ├── funs.ts
│ ├── httpInterceptor
│ │ ├── helper.service.ts
│ │ ├── httpInterceptor.service.ts
│ │ └── index.ts
│ ├── params.service.ts
│ └── tools.ts
└── vendor.ts
├── static
├── favicon.ico
├── logo.svg
└── manifest.json
├── tailwind.config.js
├── tsconfig.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 |
4 | .vscode
5 | .idea
6 |
7 | node_modules
8 | .npm
9 |
10 | .tmp
11 | dist
12 | tests
13 | deploy.js
14 |
15 | logs
16 | *.log
17 | npm-debug.log*
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular18 for CMS
2 |
3 | ### Project Technical Structure
4 | ***
5 | * angular18
6 | * ng-zorro-antd
7 | * angular/router
8 | * angular/http
9 | * rxjs
10 | * webpack5
11 | * less
12 |
13 | ### Install
14 |
15 | ***
16 | project address: (`git clone`)
17 |
18 | ```
19 | git clone git@github.com:xpioneer/angular-typescript.git
20 | ```
21 | install node_modules with `yarn`
22 |
23 | ```
24 | yarn #in your command terminal
25 | ```
26 | ***
27 | ### Run
28 |
29 | start server: (http://localhost:9100)
30 |
31 | ```
32 | yarn run start
33 | ```
34 |
35 | publish production
36 |
37 | ```
38 | yarn run build
39 | ```
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/conf/styleLoaderConf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin")
3 |
4 | const _PROD_ = process.env.NODE_ENV === 'production'
5 |
6 | const postcssLoader = {
7 | loader: 'postcss-loader',
8 | options: {
9 | sourceMap: _PROD_ ? false : true,
10 | postcssOptions: {
11 | plugins: [
12 | require('tailwindcss'),
13 | ['postcss-preset-env', {
14 | browsers: '> 0.5%, not dead, iOS >= 12, Android >= 4.5'
15 | }]
16 | ]
17 | },
18 | // plugins: [
19 | // require('autoprefixer')({
20 | // browsers: ["Android 4.1", "iOS 7.1", "Chrome > 31", "ff > 31", "ie >= 8"]
21 | // })
22 | // ]
23 | }
24 | }
25 |
26 | const styleRules = [
27 | // {
28 | // test: /\.less$/,
29 | // use: [
30 | // 'raw-loader',
31 | // 'less-loader'
32 | // ]
33 | // },
34 | {
35 | test: /\.less$/,
36 | use: [
37 | 'style-loader',
38 | 'css-loader',
39 | postcssLoader,
40 | {
41 | loader: 'less-loader',
42 | options: {
43 | lessOptions: {
44 | modifyVars: {
45 | '@primary-color': '#8514f5',
46 | '@link-color': '#8514f5',
47 | },
48 | javascriptEnabled: true
49 | }
50 | }
51 | }
52 | ]
53 | },
54 | {
55 | test: /\.css$/,
56 | use: [
57 | 'style-loader',
58 | 'css-loader',
59 | postcssLoader
60 | ]
61 | },
62 | ]
63 |
64 | if(_PROD_) {
65 | styleRules.forEach(rule => {
66 | rule.use.splice(0, 1, MiniCssExtractPlugin.loader)
67 | })
68 | }
69 |
70 | module.exports = styleRules
71 |
--------------------------------------------------------------------------------
/conf/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path'),
2 | webpack = require('webpack'),
3 | UglifyJSPlugin = require("uglifyjs-webpack-plugin"),
4 | HtmlWebpackPlugin = require("html-webpack-plugin"),
5 | config = require('./webpack.config.js');
6 |
7 | const _PROD_ = process.env.NODE_ENV === 'production'
8 |
9 | config.mode = _PROD_ ? 'development' : 'none'
10 | config.watchOptions = {
11 | aggregateTimeout: 300,
12 | poll: 1000,
13 | }
14 | config.devServer = {
15 | port: '9100',
16 | host: 'localhost',
17 |
18 | proxy: [{
19 | context: ['/api', '/uploads'],
20 | target: 'http://127.0.0.1:9901'
21 | }],
22 | historyApiFallback: true,
23 | static: {
24 | directory: path.join(__dirname, 'public'),
25 | },
26 | // contentBase: path.join(__dirname, '../dist'),
27 | // publicPath: '/',
28 | // inline: true,
29 | // stats: {
30 | // colors: true
31 | // },
32 | client: {
33 | // progress: true,
34 | overlay: {
35 | warnings: false,
36 | errors: true,
37 | },
38 | },
39 | // hot: true,
40 | // hotOnly: true,
41 | }
42 |
43 | config.plugins = (config.plugins || []).concat([
44 | new webpack.HotModuleReplacementPlugin(),
45 | // new webpack.NamedModulesPlugin(),
46 | new HtmlWebpackPlugin({
47 | title: 'CMS-FE DEV',
48 | filename: 'index.html',
49 | template: '../src/template/index_base.html',
50 | inject: 'body',
51 | templateParameters: false,
52 | })
53 | ]);
54 |
55 | module.exports = config;
--------------------------------------------------------------------------------
/conf/webpack.dll.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path'),
2 | webpack = require('webpack'),
3 | UglifyJSPlugin = require("uglifyjs-webpack-plugin"),
4 | HtmlWebpackPlugin = require("html-webpack-plugin");
5 |
6 | const _DEV_ = process.env.NODE_ENV === 'development';
7 |
8 | const config = {
9 | entry: {
10 | polyfills: [path.resolve(__dirname, '../src/polyfills.ts')],
11 | vendor: [path.resolve(__dirname, '../src/vendor.ts')],
12 | vendor1: ['ng-zorro-antd'],
13 | },
14 |
15 | output: {
16 | path: path.resolve(__dirname, "../dist/vendor"),
17 | filename: "[name].[chunkhash].dll.js",
18 | library: "[name]_[chunkhash]_lib"
19 | },
20 |
21 | // plugins
22 | plugins: [
23 | new UglifyJSPlugin({
24 | output: {
25 | comments: false,
26 | beautify: !_DEV_ ? false : true,
27 | },
28 | compress: !_DEV_ ? {
29 | drop_console: true,
30 | } : false,
31 | warnings: false
32 | }),
33 | new webpack.optimize.CommonsChunkPlugin({
34 | name: ['vendor1', 'vendor', 'polyfills'],
35 | }),
36 | new webpack.DllPlugin({
37 | context: path.resolve(__dirname, '../dist'),
38 | name: "[name]_[chunkhash]_lib",
39 | path: path.join(__dirname, "../dist/vendor", "[name].manifest.json")
40 | }),
41 | new HtmlWebpackPlugin({
42 | title: 'CMS-管理后台',
43 | filename: '../index.html',
44 | template: 'src/template/index_base.html',
45 | }),
46 | // new webpack.ContextReplacementPlugin(
47 | // /angular(\\|\/)core(\\|\/)@angular/,
48 | // path.resolve(__dirname, '../src')
49 | // )
50 | ]
51 | };
52 |
53 | module.exports = config;
--------------------------------------------------------------------------------
/conf/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path'),
2 | webpack = require('webpack'),
3 | config = require('./webpack.config.js'),
4 | UglifyJsPlugin = require("uglifyjs-webpack-plugin"),
5 | HtmlWebpackPlugin = require("html-webpack-plugin"),
6 | // CleanWebpackPlugin = require('clean-webpack-plugin'),
7 | OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"),
8 | SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
9 |
10 | const _PROD_ = process.env.NODE_ENV === 'production'
11 |
12 | config.mode = _PROD_ ? 'production' : 'none'
13 | config.plugins = (config.plugins || []).concat([
14 | // new CleanWebpackPlugin(['dist/*'],
15 | // {
16 | // root: path.join(__dirname, '../'),
17 | // verbose: true,
18 | // dry: false
19 | // }),
20 | new OptimizeCSSAssetsPlugin({
21 | // cssProcessor: require('cssnano')({ autoprefixer: false })
22 | }),
23 | new UglifyJsPlugin({
24 | uglifyOptions: {
25 | compress: {
26 | warnings: false,
27 | drop_console: !_PROD_ ? false : true,
28 | },
29 | output: {
30 | comments: false
31 | }
32 | },
33 | parallel: true
34 | }),
35 | // new webpack.HashedModuleIdsPlugin(),
36 | // new webpack.NamedModulesPlugin(),
37 | new HtmlWebpackPlugin({
38 | title: 'CMS-管理后台',
39 | filename: 'index.html',
40 | template: '../src/template/index_base.html',
41 | minify: {
42 | minifyJS: true,
43 | removeComments: true,
44 | collapseWhitespace: true,
45 | removeAttributeQuotes: true
46 | }
47 | }),
48 | new SWPrecacheWebpackPlugin({
49 | cacheId: 'ngadmin-sw',
50 | dontCacheBustUrlsMatching: /\.\w{8}\./,
51 | filename: 'serviceWorker.js',
52 | logger(message) {
53 | console.log(message);
54 | if (message.indexOf('Total precache size is') === 0) {
55 | return;
56 | }
57 | if (message.indexOf('Skipping static resource') === 0) {
58 | return;
59 | }
60 | },
61 | minify: true,
62 | navigateFallback: '/index.html',
63 | navigateFallbackWhitelist: [/^(?!\/__).*/],
64 | staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
65 | })
66 | ]);
67 |
68 | module.exports = config;
--------------------------------------------------------------------------------
/demos/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewEncapsulation } from '@angular/core';
2 | import { RouterOutlet } from '@angular/router'
3 |
4 | @Component({
5 | selector: 'app-root',
6 | encapsulation: ViewEncapsulation.Emulated,
7 | imports: [
8 | RouterOutlet
9 | ],
10 | template: `
11 |
Angular Router Sample
12 |
16 | Hello, Angular
17 |
18 | `,
19 | })
20 | export class AppComponent implements OnInit {
21 |
22 | constructor () {
23 | }
24 |
25 | public ngOnInit () {
26 | console.log('demo app entry')
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/demos/app.module.ts:
--------------------------------------------------------------------------------
1 | import { registerLocaleData } from '@angular/common';
2 | import zh from '@angular/common/locales/zh';
3 | import { LOCALE_ID, NgModule, OnInit } from '@angular/core';
4 | import { BrowserModule } from '@angular/platform-browser';
5 | import { provideRouter, RouterModule } from '@angular/router'
6 | import { AppComponent } from './app.component';
7 | import { AppRoutingModule, routes } from './app.routes';
8 | import { CrisisModule } from './crisis-list/module'
9 | import { HeroesModule } from './heroes-list/module'
10 |
11 |
12 | registerLocaleData(zh);
13 |
14 | @NgModule({
15 | // schemas: [],
16 | declarations: [
17 | AppComponent,
18 | ],
19 | imports: [
20 | BrowserModule,
21 | // RouterModule,
22 | AppRoutingModule,
23 | CrisisModule,
24 | HeroesModule,
25 | ],
26 | exports: [
27 | ],
28 | providers: [
29 | // provideRouter(routes), // use with RouterModule
30 | ],
31 | bootstrap: [AppComponent],
32 | })
33 | export class AppModule {
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/demos/app.routes.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { CrisisListComponent } from './crisis-list/component';
4 | import { HeroesListComponent } from './heroes-list/component';
5 | import { NotFoundComponent } from './not-found.component';
6 |
7 | export const routes: Routes = [
8 | { path: 'crisis-list', component: CrisisListComponent },
9 | { path: 'heroes-list', component: HeroesListComponent },
10 | { path: '', redirectTo: '/crisis-list', pathMatch: 'full' },
11 | { path: '**', component: NotFoundComponent },
12 | ];
13 |
14 | @NgModule({
15 | imports: [RouterModule.forRoot(routes)],
16 | exports: [RouterModule],
17 | })
18 | export class AppRoutingModule { }
19 |
--------------------------------------------------------------------------------
/demos/app.ts:
--------------------------------------------------------------------------------
1 | import 'zone.js';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 | import { AppModule } from './app.module';
4 |
5 | platformBrowserDynamic().bootstrapModule(AppModule).catch((e) => console.error(e));
--------------------------------------------------------------------------------
/demos/crisis-list/component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewEncapsulation, OnChanges, OnDestroy, AfterContentChecked, ChangeDetectionStrategy } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-crisis-list',
5 | encapsulation: ViewEncapsulation.Emulated,
6 | changeDetection: ChangeDetectionStrategy.OnPush,
7 | templateUrl: `./crisis-list.component.html`,
8 | })
9 | export class CrisisListComponent implements OnInit, OnChanges, OnDestroy, AfterContentChecked {
10 |
11 | constructor () {
12 | }
13 |
14 | crisisName = ''
15 |
16 | public ngOnInit () {
17 | console.log('CrisisListComponent')
18 | }
19 |
20 | ngOnChanges() {
21 | console.log('ngOnChanges')
22 | }
23 |
24 | // 自定义变更检查
25 | ngDoCheck() {
26 | console.log('ngDoCheck', this.crisisName)
27 | }
28 |
29 | // 内容投影初始化完成后的逻辑
30 | ngAfterContentInit() {
31 | console.log('ngAfterContentInit')
32 | }
33 |
34 | // 每次内容变更检测后的逻辑
35 | ngAfterContentChecked() {
36 | console.log('ngAfterContentChecked', this.crisisName)
37 | }
38 |
39 | // 视图初始化完成后的逻辑
40 | ngAfterViewInit() {
41 | console.log('ngAfterViewInit')
42 | }
43 |
44 | // 每次视图变更检测后的逻辑
45 | ngAfterViewChecked() {
46 | console.log('ngAfterViewChecked', this.crisisName)
47 | }
48 |
49 | // 清理工作
50 | ngOnDestroy() {
51 | console.log('ngOnDestroy')
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/demos/crisis-list/crisis-list.component.html:
--------------------------------------------------------------------------------
1 | CRISIS CENTER
2 | Get your crisis here
3 |
4 |
5 | Your crisis name is: {{ crisisName }}
6 |
--------------------------------------------------------------------------------
/demos/crisis-list/module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | // import { CommonModule } from '@angular/common';
3 | import { FormsModule } from '@angular/forms';
4 | import { CrisisListComponent } from './component'
5 |
6 | @NgModule({
7 | declarations: [CrisisListComponent],
8 | exports: [CrisisListComponent], // 导出组件
9 | imports: [
10 | FormsModule,
11 | ],
12 | })
13 | export class CrisisModule { }
--------------------------------------------------------------------------------
/demos/heroes-list/component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewEncapsulation } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-heroes-list',
5 | encapsulation: ViewEncapsulation.Emulated,
6 | templateUrl: `./heroes-list.component.html`,
7 | })
8 | export class HeroesListComponent implements OnInit {
9 |
10 | constructor () {
11 | }
12 |
13 | public ngOnInit () {
14 | console.log('HeroesListComponent')
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/demos/heroes-list/heroes-list.component.html:
--------------------------------------------------------------------------------
1 | HEROES
2 | Get your heroes here
--------------------------------------------------------------------------------
/demos/heroes-list/module.ts:
--------------------------------------------------------------------------------
1 | import { Component, NgModule, OnInit, ViewEncapsulation } from '@angular/core';
2 | import { HeroesListComponent } from './component'
3 | // import { CommonModule } from '@angular/common';
4 |
5 | @NgModule({
6 | declarations: [HeroesListComponent],
7 | exports: [HeroesListComponent], // 导出组件
8 | // imports: [CommonModule]
9 | })
10 | export class HeroesModule { }
--------------------------------------------------------------------------------
/demos/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | CMS-管理后台
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/demos/miniapp/about.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-about',
5 | template: `About Page
`
6 | })
7 | export class AboutComponent {}
8 |
--------------------------------------------------------------------------------
/demos/miniapp/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { HomeComponent } from './home.component';
4 | import { AboutComponent } from './about.component';
5 |
6 | const routes: Routes = [
7 | { path: '', component: HomeComponent }, // 根路径显示 HomeComponent
8 | { path: 'about', component: AboutComponent } // /about 显示 AboutComponent
9 | ];
10 |
11 | @NgModule({
12 | imports: [RouterModule.forRoot(routes)],
13 | exports: [RouterModule]
14 | })
15 | export class AppRoutingModule {}
16 |
--------------------------------------------------------------------------------
/demos/miniapp/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | template: `
6 | Angular Routing Example
7 |
11 |
12 | `
13 | })
14 | export class AppComponent {}
15 |
--------------------------------------------------------------------------------
/demos/miniapp/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { AppComponent } from './app.component';
4 | import { HomeComponent } from './home.component';
5 | import { AboutComponent } from './about.component';
6 | import { AppRoutingModule } from './app-routing.module'; // 导入路由模块
7 |
8 | @NgModule({
9 | declarations: [AppComponent, HomeComponent, AboutComponent],
10 | imports: [BrowserModule, AppRoutingModule], // 引入 BrowserModule 和 AppRoutingModule
11 | bootstrap: [AppComponent]
12 | })
13 | export class AppModule {}
14 |
--------------------------------------------------------------------------------
/demos/miniapp/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-home',
5 | template: `Home Page
`
6 | })
7 | export class HomeComponent {}
8 |
--------------------------------------------------------------------------------
/demos/miniapp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular Routing Example
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/demos/miniapp/index.ts:
--------------------------------------------------------------------------------
1 | import "@angular/compiler"
2 | import("./main")
--------------------------------------------------------------------------------
/demos/miniapp/main.ts:
--------------------------------------------------------------------------------
1 | import 'zone.js';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 | import { AppModule } from './app.module';
4 |
5 | platformBrowserDynamic().bootstrapModule(AppModule)
6 | .catch(err => console.error(err));
7 |
--------------------------------------------------------------------------------
/demos/not-found.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-not-found',
5 | template: `404 - Page Not Found
`,
6 | })
7 | export class NotFoundComponent {}
8 |
--------------------------------------------------------------------------------
/demos/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "outDir": "./dist",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "module": "esnext",
8 | "moduleResolution": "node",
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "target": "ESNext",
12 | "typeRoots": ["node_modules/@types"],
13 | "lib": ["es2017", "dom"],
14 | "baseUrl": "./demos",
15 | },
16 | "include": ["./**/*.ts"]
17 | }
18 |
--------------------------------------------------------------------------------
/demos/webpack.config.js:
--------------------------------------------------------------------------------
1 | const { AngularWebpackPlugin } = require('@ngtools/webpack');
2 | const path = require('path');
3 | const HtmlWebpackPlugin = require("html-webpack-plugin")
4 |
5 | const _PROD_ = process.env.NODE_ENV === 'production'
6 |
7 | console.log(`
8 | This is mini app with Angular Router.
9 | `)
10 |
11 | module.exports = {
12 | devServer: {
13 | port: '9100',
14 | historyApiFallback: true,
15 | client: {
16 | overlay: {
17 | warnings: false,
18 | errors: true,
19 | },
20 | },
21 | },
22 | mode: _PROD_ ? 'production' : 'development',
23 | entry: './demos/app.ts', // 入口文件
24 | output: {
25 | path: path.resolve(__dirname, 'dist'),
26 | filename: 'bundle.js',
27 | publicPath: '/',
28 | assetModuleFilename: 'static/assets/[hash][ext][query]',
29 | },
30 | resolve: {
31 | extensions: ['.ts', '.js'], // 解析 .ts 和 .js 文件
32 | },
33 | module: {
34 | rules: [
35 | {
36 | test: /\.ts$/,
37 | use: [
38 | {
39 | loader: '@ngtools/webpack',
40 | },
41 | ],
42 | },
43 | {
44 | test: /\.html$/,
45 | use: 'html-loader',
46 | },
47 | ],
48 | },
49 | plugins: [
50 | new AngularWebpackPlugin({
51 | tsconfig: './demos/tsconfig.json',
52 | jitMode: true,
53 | }),
54 | new HtmlWebpackPlugin({
55 | title: 'CMS-FE DEV',
56 | filename: 'index.html',
57 | template: './demos/index.html',
58 | inject: 'body',
59 | templateParameters: false,
60 | })
61 | ],
62 | };
63 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-typescript",
3 | "version": "1.2.0",
4 | "description": "Angular18 for CMS",
5 | "main": "index.js",
6 | "author": "xpioneer",
7 | "keywords": [
8 | "Angular18",
9 | "Typescript",
10 | "HttpInterceptor",
11 | "lazyload",
12 | "ng-zorro-antd",
13 | "loadChildren"
14 | ],
15 | "license": "MIT",
16 | "scripts": {
17 | "start": "NODE_ENV=development webpack-dev-server --config conf/webpack.dev.conf.js",
18 | "dev": "yarn start",
19 | "clean": "rm -rf dist",
20 | "demo": "webpack-dev-server --config ./demos/webpack.config.js",
21 | "build": "NODE_ENV=production webpack --config conf/webpack.prod.conf.js",
22 | "test": "NODE_ENV=development yarn run dll && webpack --config conf/webpack.dev.conf.js",
23 | "lint": "NODE_ENV=development node_modules/.bin/tslint -c tslint.json -p tsconfig.json",
24 | "lintfix": "NODE_ENV=development node_modules/.bin/tslint -c tslint.json -p tsconfig.json --fix --force"
25 | },
26 | "dependencies": {
27 | "@angular/animations": "^18.2.5",
28 | "@angular/common": "^18.2.5",
29 | "@angular/core": "^18.2.5",
30 | "@angular/forms": "^18.2.5",
31 | "@angular/platform-browser": "^18.2.5",
32 | "@angular/router": "^18.2.5",
33 | "@ant-design/icons-angular": "^18.0.0",
34 | "core-js": "^3.38.1",
35 | "cron-parser": "^4.9.0",
36 | "d3-selection": "^3.0.0",
37 | "d3-zoom": "^3.0.0",
38 | "dagre-compound": "^0.0.13",
39 | "date-fns": "^4.1.0",
40 | "dayjs": "^1.11.13",
41 | "echarts": "^5.5.1",
42 | "monaco-editor": "^0.52.0",
43 | "ng-zorro-antd": "^18.1.1",
44 | "quill": "^1.3.2",
45 | "rxjs": "^7.8.1",
46 | "zone.js": "^0.15.0"
47 | },
48 | "devDependencies": {
49 | "@angular/compiler": "^18.2.5",
50 | "@angular/compiler-cli": "^18.2.5",
51 | "@angular/platform-browser-dynamic": "^18.2.5",
52 | "@ngtools/webpack": "^18.2.5",
53 | "@types/d3-zoom": "^3.0.8",
54 | "@types/node": "^22.6.1",
55 | "copy-webpack-plugin": "^12.0.2",
56 | "css-loader": "^7.1.2",
57 | "html-loader": "^5.1.0",
58 | "html-webpack-plugin": "^5.6.0",
59 | "less": "^4.2.0",
60 | "less-loader": "^12.2.0",
61 | "mini-css-extract-plugin": "^2.9.1",
62 | "optimize-css-assets-webpack-plugin": "^6.0.1",
63 | "postcss-loader": "^8.1.1",
64 | "postcss-preset-env": "^10.0.5",
65 | "raw-loader": "^4.0.2",
66 | "style-loader": "^4.0.0",
67 | "sw-precache-webpack-plugin": "^0.11.5",
68 | "tailwindcss": "^3.4.14",
69 | "typescript": "5.5.4",
70 | "uglifyjs-webpack-plugin": "^2.2.0",
71 | "webpack": "^5.94.0",
72 | "webpack-cli": "^5.1.4",
73 | "webpack-dev-server": "^5.1.0"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/antd/demos.ts:
--------------------------------------------------------------------------------
1 | import { Component, NgModule } from '@angular/core'
2 | import { NzFlexDirective } from 'ng-zorro-antd/flex';
3 |
4 | // demo for NzFlexDirective use specially
5 |
6 | /**
7 | * your component
8 | */
9 | @Component({
10 | selector: 'app-your-component',
11 | templateUrl: './your-component.component.html',
12 | styleUrls: ['./your-component.component.css']
13 | })
14 | export class YourComponent {
15 | // ...
16 | }
17 |
18 | @NgModule({
19 | declarations: [
20 | YourComponent,
21 | NzFlexDirective // add NzFlexDirective to declarations
22 | ],
23 | // ... other configs
24 | })
25 | export class YourModule { }
--------------------------------------------------------------------------------
/src/antd/directive.ts:
--------------------------------------------------------------------------------
1 |
2 | export { NzDateCellDirective, NzMonthCellDirective, NzDateFullCellDirective, NzMonthFullCellDirective } from 'ng-zorro-antd/calendar';
3 | export { NzCardGridDirective } from 'ng-zorro-antd/card';
4 | export { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
5 | export { NzCollapseModule } from 'ng-zorro-antd/collapse';
6 | export { NzCommentAvatarDirective, NzCommentContentDirective, NzCommentActionHostDirective } from 'ng-zorro-antd/comment';
7 | export { NzWaveDirective } from 'ng-zorro-antd/core/wave';
8 | export { NzDropDownADirective, NzDropDownDirective, NzDropdownButtonDirective, NzDropDownModule, NzDropdownMenuComponent } from 'ng-zorro-antd/dropdown';
9 | export { NzFlexDirective } from 'ng-zorro-antd/flex';
10 | export { NzFormDirective } from 'ng-zorro-antd/form';
11 | export { NzRowDirective, NzColDirective } from 'ng-zorro-antd/grid';
12 | export { NzIconDirective } from 'ng-zorro-antd/icon';
13 | export { NzImageDirective } from 'ng-zorro-antd/image';
14 | export { NzInputDirective, NzAutosizeDirective, NzInputGroupWhitSuffixOrPrefixDirective } from 'ng-zorro-antd/input';
15 | export { NzInputNumberGroupWhitSuffixOrPrefixDirective } from 'ng-zorro-antd/input-number';
16 | export { NzListGridDirective, NzListLoadMoreDirective, NzListItemMetaDescriptionComponent } from 'ng-zorro-antd/list';
17 | export { NzMentionTriggerDirective, NzMentionSuggestionDirective } from 'ng-zorro-antd/mention';
18 | export { NzMenuDirective, NzMenuDividerDirective } from 'ng-zorro-antd/menu';
19 | export { NzModalTitleDirective, NzModalContentDirective, NzModalFooterDirective } from 'ng-zorro-antd/modal';
20 | export {
21 | NzPageHeaderTagDirective, NzPageHeaderTitleDirective, NzPageHeaderAvatarDirective,
22 | NzPageHeaderBreadcrumbDirective, NzPageHeaderFooterDirective, NzPageHeaderExtraDirective,
23 | NzPageHeaderContentDirective, NzPageHeaderSubtitleDirective
24 | } from 'ng-zorro-antd/page-header';
25 | export { NzPopconfirmDirective } from 'ng-zorro-antd/popconfirm';
26 | export { NzPopoverDirective } from 'ng-zorro-antd/popover';
27 | export {
28 | NzResultIconDirective, NzResultExtraDirective, NzResultTitleDirective,
29 | NzResultContentDirective, NzResultSubtitleDirective
30 | } from 'ng-zorro-antd/result';
31 | export { NzSkeletonElementDirective } from 'ng-zorro-antd/skeleton';
32 | export { NzSpaceDirection, NzSpaceItemDirective } from 'ng-zorro-antd/space';
33 | export {
34 | NzCellAlignDirective, NzTrDirective, NzTableDataService, NzTrExpandDirective,
35 | NzCellFixedDirective, NzRowIndentDirective, NzTableCellDirective, NzThMeasureDirective,
36 | NzCellEllipsisDirective, NzCustomColumnDirective, NzCellBreakWordDirective,
37 | NzTableInnerDefaultComponent, NzRowExpandButtonDirective, NzTableVirtualScrollDirective,
38 | } from 'ng-zorro-antd/table';
39 | export {
40 | NzTabDirective, NzTabLinkDirective, NzTabsCanDeactivateFn, NzTabLinkTemplateDirective
41 | } from 'ng-zorro-antd/tabs';
42 | export { NzTooltipDirective, NzTooltipBaseDirective } from 'ng-zorro-antd/tooltip';
43 | export {
44 | NzTreeNodeDefDirective, NzTreeNodeOutletDirective, NzTreeNodeToggleDirective,
45 | NzTreeNodePaddingDirective, NzTreeNodeIndentLineDirective, NzTreeNodeNoopToggleDirective,
46 | NzTreeNodeToggleActiveIconDirective, NzTreeNodeToggleRotateIconDirective,
47 | NzTreeVirtualScrollNodeOutletDirective
48 | } from 'ng-zorro-antd/tree-view';
49 | export { NzResizeDirection, NzResizableDirective } from 'ng-zorro-antd/resizable';
50 | export {
51 | NzGraphEdgeDirective, NzGraphNodeDirective, NzGraphZoomDirective, NzGraphGroupNodeDirective
52 | } from 'ng-zorro-antd/graph';
53 |
--------------------------------------------------------------------------------
/src/antd/module.ts:
--------------------------------------------------------------------------------
1 |
2 | export { NzAffixModule } from 'ng-zorro-antd/affix';
3 | export { NzAlertModule } from 'ng-zorro-antd/alert';
4 | export { NzAnchorModule } from 'ng-zorro-antd/anchor';
5 | export { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete';
6 | export { NzAvatarModule } from 'ng-zorro-antd/avatar';
7 | export { NzBackTopModule } from 'ng-zorro-antd/back-top';
8 | export { NzBadgeModule } from 'ng-zorro-antd/badge';
9 | export { NzBreadCrumbModule } from 'ng-zorro-antd/breadcrumb';
10 | export { NzButtonModule } from 'ng-zorro-antd/button';
11 | export { NzCalendarModule } from 'ng-zorro-antd/calendar';
12 | export { NzCardModule } from 'ng-zorro-antd/card';
13 | export { NzCarouselModule } from 'ng-zorro-antd/carousel';
14 | export { NzCascaderModule } from 'ng-zorro-antd/cascader';
15 | export { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
16 | export { NzCollapseModule } from 'ng-zorro-antd/collapse';
17 | export { NzCommentModule } from 'ng-zorro-antd/comment';
18 | export { NzNoAnimationModule } from 'ng-zorro-antd/core/no-animation';
19 | export { NzTransButtonModule } from 'ng-zorro-antd/core/trans-button';
20 | export { NzWaveModule } from 'ng-zorro-antd/core/wave';
21 | export { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
22 | export { NzDescriptionsModule } from 'ng-zorro-antd/descriptions';
23 | export { NzDividerModule } from 'ng-zorro-antd/divider';
24 | export { NzDrawerModule } from 'ng-zorro-antd/drawer';
25 | export { NzDropDownModule } from 'ng-zorro-antd/dropdown';
26 | export { NzEmptyModule } from 'ng-zorro-antd/empty';
27 | export { NzFlexModule } from 'ng-zorro-antd/flex';
28 | export { NzFormModule } from 'ng-zorro-antd/form';
29 | export { NzGridModule } from 'ng-zorro-antd/grid';
30 | export { NzI18nModule } from 'ng-zorro-antd/i18n';
31 | export { NzIconModule } from 'ng-zorro-antd/icon';
32 | export { NzImageModule } from 'ng-zorro-antd/image';
33 | export { NzInputModule } from 'ng-zorro-antd/input';
34 | export { NzInputNumberModule } from 'ng-zorro-antd/input-number';
35 | export { NzLayoutModule } from 'ng-zorro-antd/layout';
36 | export { NzListModule } from 'ng-zorro-antd/list';
37 | export { NzMentionModule } from 'ng-zorro-antd/mention';
38 | export { NzMenuModule } from 'ng-zorro-antd/menu';
39 | export { NzMessageModule } from 'ng-zorro-antd/message';
40 | export { NzModalModule } from 'ng-zorro-antd/modal';
41 | export { NzNotificationModule } from 'ng-zorro-antd/notification';
42 | export { NzPageHeaderModule } from 'ng-zorro-antd/page-header';
43 | export { NzPaginationModule } from 'ng-zorro-antd/pagination';
44 | export { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm';
45 | export { NzPopoverModule } from 'ng-zorro-antd/popover';
46 | export { NzProgressModule } from 'ng-zorro-antd/progress';
47 | export { NzRadioModule } from 'ng-zorro-antd/radio';
48 | export { NzRateModule } from 'ng-zorro-antd/rate';
49 | export { NzResultModule } from 'ng-zorro-antd/result';
50 | export { NzSegmentedModule } from 'ng-zorro-antd/segmented';
51 | export { NzSelectModule } from 'ng-zorro-antd/select';
52 | export { NzSkeletonModule } from 'ng-zorro-antd/skeleton';
53 | export { NzSliderModule } from 'ng-zorro-antd/slider';
54 | export { NzSpaceModule } from 'ng-zorro-antd/space';
55 | export { NzSpinModule } from 'ng-zorro-antd/spin';
56 | export { NzStatisticModule } from 'ng-zorro-antd/statistic';
57 | export { NzStepsModule } from 'ng-zorro-antd/steps';
58 | export { NzSwitchModule } from 'ng-zorro-antd/switch';
59 | export { NzTableModule } from 'ng-zorro-antd/table';
60 | export { NzTabsModule } from 'ng-zorro-antd/tabs';
61 | export { NzTagModule } from 'ng-zorro-antd/tag';
62 | export { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
63 | export { NzTimelineModule } from 'ng-zorro-antd/timeline';
64 | export { NzToolTipModule } from 'ng-zorro-antd/tooltip';
65 | export { NzTransferModule } from 'ng-zorro-antd/transfer';
66 | export { NzTreeModule } from 'ng-zorro-antd/tree';
67 | export { NzTreeViewModule } from 'ng-zorro-antd/tree-view';
68 | export { NzTreeSelectModule } from 'ng-zorro-antd/tree-select';
69 | export { NzTypographyModule } from 'ng-zorro-antd/typography';
70 | export { NzUploadModule } from 'ng-zorro-antd/upload';
71 | export { NzResizableModule } from 'ng-zorro-antd/resizable';
72 | export { NzPipesModule } from 'ng-zorro-antd/pipes';
73 | export { NzCodeEditorModule } from 'ng-zorro-antd/code-editor';
74 | export { NzGraphModule } from 'ng-zorro-antd/graph';
75 | export { NzCronExpressionModule } from 'ng-zorro-antd/cron-expression';
76 | export { NzQRCodeModule } from 'ng-zorro-antd/qr-code';
77 | export { NzWaterMarkModule } from 'ng-zorro-antd/water-mark';
78 |
--------------------------------------------------------------------------------
/src/app.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 | import { AppModule } from './app/app.module';
4 | // import './assets/less/index.less';
5 | import './styles/index.less';
6 | import '@/styles/tailwind.css'
7 | // require('../node_modules/ng-zorro-antd/ng-zorro-antd.min.css');
8 | // import 'quill/dist/quill.bubble.css';
9 | // import 'quill/dist/quill.core.css';
10 | import 'quill/dist/quill.snow.css';
11 | import registerServiceWorker from './registerServiceWorker'
12 |
13 | // declare var module: any;
14 | // if (module.hot) {
15 | // module.hot.accept();
16 | // }
17 |
18 | if (process.env.NODE_ENV === 'production') {
19 | enableProdMode();
20 | }
21 | platformBrowserDynamic().bootstrapModule(AppModule).catch((e) => console.error(e));
22 | registerServiceWorker()
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewEncapsulation } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-root',
5 | encapsulation: ViewEncapsulation.Emulated,
6 | template: '',
7 | })
8 | export class AppComponent implements OnInit {
9 |
10 | constructor () {
11 | }
12 |
13 | public ngOnInit () {
14 | console.log('app entry')
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { registerLocaleData } from '@angular/common';
2 | import zh from '@angular/common/locales/zh';
3 | import { HttpClientModule, HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
4 | import { LOCALE_ID, NgModule } from '@angular/core';
5 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
6 | import { BrowserModule } from '@angular/platform-browser';
7 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
8 | import { provideRouter, RouterModule } from '@angular/router';
9 | import { NZ_ICONS } from 'ng-zorro-antd/icon';
10 | import { NZ_I18N, zh_CN } from 'ng-zorro-antd/i18n';
11 | import { IconDefinition } from '@ant-design/icons-angular'
12 | import { UserOutline, LockOutline, SettingOutline, AppstoreOutline, CalculatorOutline, LineChartOutline, SmileOutline, BulbOutline, PlusOutline, GlobalOutline } from '@ant-design/icons-angular/icons'
13 |
14 | import { BreadCrumbComponent, HeaderComponent, SidebarComponent } from '../components/shared';
15 | import { AppComponent } from './app.component';
16 | import { AppRouting, appRoutes } from './app.routing';
17 | import { HomeComponent } from './home';
18 | import { LoginComponent } from './login/login.component';
19 |
20 | import { HttpClientInterceptor } from '@utils/httpInterceptor';
21 | import { AuthGuard } from '@utils/auth/auth-guard.service';
22 | import { AuthService } from '../utils/auth/auth.service';
23 | import { HelperService } from '../utils/httpInterceptor/helper.service';
24 | import { Params } from '../utils/params.service';
25 | import { ZorroAntdModule } from '@/antd/ngModule'
26 |
27 | registerLocaleData(zh);
28 | const icons: IconDefinition[] = [
29 | UserOutline, LockOutline, SettingOutline, AppstoreOutline,
30 | CalculatorOutline, LineChartOutline, SmileOutline, BulbOutline,
31 | PlusOutline, GlobalOutline,
32 | ]
33 |
34 | @NgModule({
35 | // schemas: [],
36 | declarations: [
37 | AppComponent,
38 | HomeComponent,
39 | LoginComponent,
40 | HeaderComponent,
41 | SidebarComponent,
42 | BreadCrumbComponent,
43 | // NzPageHeaderBreadcrumbDirective,
44 | // NzMenuDirective,
45 | ],
46 | imports: [
47 | BrowserModule,
48 | BrowserAnimationsModule,
49 | FormsModule,
50 | ReactiveFormsModule,
51 | // HttpClientModule,
52 | RouterModule,
53 | // AppRouting,
54 | ZorroAntdModule,
55 | ],
56 | exports: [
57 |
58 | // NzMenuModule,
59 | ],
60 | providers: [
61 | provideRouter(appRoutes),
62 | provideHttpClient(withInterceptorsFromDi()),
63 | { provide: NZ_I18N, useValue: zh_CN },
64 | { provide: NZ_ICONS, useValue: icons },
65 | {
66 | provide: HTTP_INTERCEPTORS,
67 | useClass: HttpClientInterceptor,
68 | multi: true,
69 | },
70 | Params,
71 | HelperService,
72 | AuthGuard,
73 | AuthService,
74 | ],
75 | bootstrap: [AppComponent],
76 | })
77 | export class AppModule {
78 | constructor () {}
79 | }
80 |
--------------------------------------------------------------------------------
/src/app/app.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '../utils/auth/auth-guard.service';
4 | import { HomeComponent } from './home';
5 | import { LoginComponent } from './login/login.component';
6 |
7 | export const appRoutes: Routes = [
8 | {
9 | path: 'login',
10 | component: LoginComponent,
11 | },
12 | {
13 | path: '',
14 | component: HomeComponent,
15 | children: [
16 | { path: '', redirectTo: 'dashboard', pathMatch: 'full' },
17 | { path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.module') },
18 | { path: 'article', loadChildren: () => import('./article/article.module') },
19 | { path: 'articletype', loadChildren: () => import('./articletype/articletype.module') },
20 | { path: 'tag', loadChildren: () => import('./tag/tag.module') },
21 | { path: 'user', loadChildren: () => import('./user/user.module') },
22 | { path: 'comment', loadChildren: () => import('./comment/comment.module') },
23 | { path: 'charts', loadChildren: () => import('./charts/chart.module') },
24 | { path: 'systemlog', loadChildren: () => import('./systemlogs/systemlog.module') },
25 | { path: 'doubleball', loadChildren: () => import('./doubleball/doubleball.module') },
26 | { path: 'demos', loadChildren: () => import('./demos/demos.module') },
27 | { path: '**', redirectTo: 'dashboard', pathMatch: 'full' },
28 | ],
29 | },
30 | ];
31 |
32 | @NgModule({
33 | imports: [RouterModule.forRoot(appRoutes, { useHash: false })],
34 | exports: [RouterModule],
35 | })
36 | export class AppRouting { }
37 |
--------------------------------------------------------------------------------
/src/app/article/addarticle/addarticle.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class AddArticleService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public insertArticle (data: any) {
13 | return this.http.post('/article', data);
14 | }
15 |
16 | public getTags () {
17 | return this.http.get('/tag?' + this.params.format({
18 | current_page: 1,
19 | per_page: 999,
20 | }));
21 | }
22 |
23 | public getTypes () {
24 | return this.http.get('/articletype?' + this.params.format({
25 | current_page: 1,
26 | per_page: 999,
27 | }));
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/app/article/addarticle/addarticle.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { ArticleModel, ITag } from '../model/article.model';
6 | import { AddArticleService } from './addarticle.service';
7 |
8 | @Component({
9 | selector: 'app-add-article',
10 | templateUrl: './addarticle.html',
11 | // styles: [``],
12 | })
13 | export class AddArticleComponent implements OnInit {
14 | public isConfirmLoading = false;
15 | public addArticle: ArticleModel = new ArticleModel();
16 | @ViewChild('form') private form: NgForm;
17 |
18 | public tagList: ITag[] = [];
19 | public checkedTag: AnyObject = {};
20 | public typeAjaxList: any[] = [];
21 |
22 | constructor (
23 | private router: Router,
24 | private addArticleService: AddArticleService,
25 | private notification: NzNotificationService,
26 | ) { }
27 |
28 | public ngOnInit () {
29 | this.getTypeList();
30 | this.getTagList();
31 | }
32 |
33 | public save () {
34 | for (const i in this.form.controls) {
35 | this.form.controls[ i ].markAsDirty();
36 | }
37 | this.addArticle.tag = this.getCheckedTag();
38 | if (this.form.valid) {
39 | this.isConfirmLoading = true;
40 | this.addArticleService.insertArticle(this.addArticle).subscribe((res: any) => {
41 | this.isConfirmLoading = false;
42 | this.router.navigate(['/article']);
43 | }, (err: any) => {
44 | this.isConfirmLoading = false;
45 | });
46 | }
47 | }
48 |
49 | public getTypeList () {
50 | this.addArticleService.getTypes().subscribe((res: any) => {
51 | this.typeAjaxList = res.data;
52 | }, (err: any) => {
53 | //
54 | });
55 | }
56 |
57 | public getTagList () {
58 | this.addArticleService.getTags().subscribe((res: any) => {
59 | this.tagList = res.data;
60 | }, (err: any) => {
61 | //
62 | });
63 | }
64 |
65 | public getCheckedTag () {
66 | const arr = [];
67 | for (const item of this.tagList) {
68 | if (this.checkedTag[item.id]) {
69 | arr.push(item.name);
70 | }
71 | }
72 | return arr.join(',');
73 | }
74 |
75 | public back () {
76 | this.router.navigate(['article']);
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/app/article/article.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-article',
5 | template: '',
6 | })
7 | export class ArticleComponent {
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/article/article.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { EditorModule } from '@components/editor/editor.module';
6 | import { UploadFileModule } from '@components/upload-file/upload-file.module';
7 | import { AddArticleComponent } from './addarticle/addarticle';
8 | import { AddArticleService } from './addarticle/addarticle.service';
9 | import { ArticleComponent } from './article.component';
10 | import { ArticleRouting } from './article.routing';
11 | import { ArticleListComponent } from './articlelist/articlelist';
12 | import { ArticleListService } from './articlelist/articlelist.service';
13 | import { EditArticleComponent } from './editarticle/editarticle';
14 | import { EditArticleService } from './editarticle/editarticle.service';
15 | import { ZorroAntdModule } from '@/antd/ngModule'
16 |
17 | @NgModule({
18 | imports: [
19 | FormsModule,
20 | // ReactiveFormsModule,
21 | CommonModule,
22 | ArticleRouting,
23 | // NgZorroAntdModule.forRoot(),
24 | UploadFileModule,
25 | EditorModule,
26 | ZorroAntdModule,
27 | ],
28 | declarations: [
29 | ArticleComponent,
30 | ArticleListComponent,
31 | AddArticleComponent,
32 | EditArticleComponent,
33 | ],
34 | providers: [
35 | ArticleListService,
36 | AddArticleService,
37 | EditArticleService,
38 | ],
39 | })
40 | export default class ArticleModule {}
41 |
--------------------------------------------------------------------------------
/src/app/article/article.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { AddArticleComponent } from './addarticle/addarticle';
5 | import { ArticleComponent } from './article.component';
6 | import { ArticleListComponent } from './articlelist/articlelist';
7 | import { EditArticleComponent } from './editarticle/editarticle';
8 |
9 | const routes: Routes = [
10 | {
11 | path: '',
12 | canActivateChild: [AuthGuard],
13 | component: ArticleComponent,
14 | children: [
15 | { path: '', redirectTo: 'list', pathMatch: 'full' },
16 | { path: 'list', component: ArticleListComponent },
17 | { path: 'add', component: AddArticleComponent },
18 | { path: 'edit/:id', component: EditArticleComponent },
19 | ],
20 | },
21 | ];
22 |
23 | @NgModule({
24 | imports: [RouterModule.forChild(routes)],
25 | exports: [RouterModule],
26 | })
27 | export class ArticleRouting {}
28 |
--------------------------------------------------------------------------------
/src/app/article/articlelist/articlelist.html:
--------------------------------------------------------------------------------
1 |
2 | 文章列表
3 |
21 |
22 |
23 |
24 |
34 |
35 |
36 | 文章名称 |
37 | 图片 |
38 | 摘要 |
39 | 浏览数 |
40 | 原创 |
41 | 创建时间 |
42 | 操作 |
43 |
44 |
45 |
46 |
47 | {{data.title}}
48 | |
49 | }}) |
50 | {{data.abstract}}
51 | |
52 | {{data.view_count}} |
53 | {{data.is_original?'是':'否'}} |
54 | {{data.created_at}} |
55 |
56 | 编辑
57 | 删除
58 | |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/app/article/articlelist/articlelist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 | import { Params } from '../../../utils/params.service';
5 |
6 | @Injectable()
7 | export class ArticleListService {
8 | constructor (
9 | private http: HttpClient,
10 | private params: Params,
11 | ) {}
12 |
13 | public getArticleList (data: any) {
14 | return this.http.get('/article?' + this.params.fmtpages(data));
15 | }
16 |
17 | public deleteArticle (id: string) {
18 | return this.http.delete('/article/' + id);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/article/articlelist/articlelist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { Router } from '@angular/router';
3 | import { NzModalService } from 'ng-zorro-antd/modal';
4 | import { ArticleModel } from '../model/article.model';
5 | import { ArticleListService } from './articlelist.service';
6 | import { finalize } from 'rxjs';
7 |
8 | @Component({
9 | selector: 'app-article-list',
10 | templateUrl: './articlelist.html',
11 | })
12 | export class ArticleListComponent implements OnInit {
13 |
14 | public current_page = 1;
15 | public per_page = 10;
16 | public total = 1;
17 | public dataSet: ArticleModel[] = [];
18 | public _loading = true;
19 |
20 | public value: any = {};
21 | public isVisible = false;
22 | public isConfirmLoading = false;
23 | public deleteId: string;
24 |
25 | public options: object[];
26 |
27 | constructor (
28 | private router: Router,
29 | private modalService: NzModalService,
30 | private articleListService: ArticleListService,
31 | ) {
32 | }
33 |
34 | public ngOnInit () {
35 | this.clear();
36 | this.query();
37 | }
38 |
39 | public query () {
40 | this._loading = true;
41 | this.value.current_page = this.current_page;
42 | this.value.per_page = this.per_page;
43 | this.articleListService.getArticleList(this.value)
44 | .pipe(finalize(() => { this._loading = false; }))
45 | .subscribe((res: any) => {
46 | this.dataSet = res.data;
47 | this.current_page = res.meta.current_page;
48 | this.total = res.meta.total;
49 | }, (e) => { });
50 | }
51 |
52 | public clear () {
53 | this.value = {
54 | title: {
55 | val: '',
56 | exp: 'like',
57 | },
58 | abstract: {
59 | val: '',
60 | exp: 'like',
61 | },
62 | };
63 | }
64 |
65 | public delArticle (id: string) {
66 | const that = this;
67 | this.modalService.confirm({
68 | nzTitle : '确认是否删除',
69 | nzContent: '删除后将无法找回这篇文章',
70 | nzOkLoading: true,
71 | nzOnOk () {
72 | return new Promise((resolve) => {
73 | that.articleListService.deleteArticle(id)
74 | .pipe(finalize(() => { resolve(); }))
75 | .subscribe((res: any) => { that.query(); }, (err) => { });
76 | });
77 | },
78 | nzOnCancel () { },
79 | });
80 | }
81 |
82 | public getPics (url: string) {
83 | return !!url ? url + '?Authorization-User=' + localStorage.getItem('ACCESS_TOKEN') : '';
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/app/article/editarticle/editarticle.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class EditArticleService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getArticle (id: string) {
13 | return this.http.get('/article/' + id);
14 | }
15 |
16 | public updateArticle (data: any) {
17 | return this.http.put('/article/' + data.id, data);
18 | }
19 |
20 | public getTags () {
21 | return this.http.get('/tag?' + this.params.format({
22 | current_page: 1,
23 | per_page: 999,
24 | }));
25 | }
26 |
27 | public getTypes () {
28 | return this.http.get('/articletype?' + this.params.format({
29 | current_page: 1,
30 | per_page: 999,
31 | }));
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/app/article/editarticle/editarticle.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { ActivatedRoute, Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { ArticleModel, ITag } from '../model/article.model';
6 | import { EditArticleService } from './editarticle.service';
7 | import { finalize } from 'rxjs';
8 |
9 | @Component({
10 | selector: 'app-edit-aritcle',
11 | templateUrl: './editarticle.html',
12 | // styles: [``],
13 | })
14 | export class EditArticleComponent implements OnInit {
15 | public isConfirmLoading = false;
16 | public mainModel: ArticleModel = new ArticleModel();
17 | @ViewChild('form') private form: NgForm;
18 |
19 | public tagList: ITag[] = [];
20 | public _tagList: object[] = [];
21 | public checkedTag: AnyObject = {};
22 | public typeAjaxList: any[] = [];
23 |
24 | constructor (
25 | private router: Router,
26 | private route: ActivatedRoute,
27 | private editArticleService: EditArticleService,
28 | private notification: NzNotificationService,
29 | ) { }
30 |
31 | public ngOnInit () {
32 | this.route.params.subscribe((param) => {
33 | if (param.id) {
34 | this.getData(param.id);
35 | }
36 | this.getTypeList();
37 | this.getTagList();
38 | }, (err) => {
39 | this.notification.warning('错误', '参数错误');
40 | });
41 | }
42 |
43 | public getData (id: string) {
44 | this.editArticleService.getArticle(id).subscribe((res: any) => {
45 | this.mainModel = res.data;
46 | res.data.tag.split(',').forEach((v: string) => {
47 | this.checkedTag[v] = true;
48 | });
49 | }, (err: any) => {
50 | //
51 | });
52 | }
53 |
54 | public getPics (url: string) {
55 | return !!url ? url + '?Authorization-User=' + localStorage.getItem('ACCESS_TOKEN') : '';
56 | }
57 |
58 | public save () {
59 | for (const i in this.form.controls) {
60 | this.form.controls[ i ].markAsDirty();
61 | }
62 | this.mainModel.tag = this.getCheckedTag();
63 | if (this.form.valid) {
64 | this.isConfirmLoading = true;
65 | this.editArticleService.updateArticle(this.mainModel)
66 | .pipe(finalize(() => this.isConfirmLoading = false))
67 | .subscribe((res: any) => {
68 | this.router.navigate(['/article']);
69 | }, (err: any) => {
70 | });
71 | }
72 | }
73 |
74 | public getTypeList () {
75 | this.editArticleService.getTypes().subscribe((res: any) => {
76 | this.typeAjaxList = res.data;
77 | }, (err: any) => {
78 | //
79 | });
80 | }
81 |
82 | public getTagList () {
83 | this.editArticleService.getTags().subscribe((res: any) => {
84 | this.tagList = res.data;
85 | }, (err: any) => {
86 | //
87 | });
88 | }
89 |
90 | public getCheckedTag () {
91 | return this.tagList.filter((t) => {
92 | return this.checkedTag[t.name];
93 | }).map((t) => {
94 | return t.name;
95 | }).join(',');
96 | }
97 |
98 | public back () {
99 | this.router.navigate(['article']);
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/app/article/model/article.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class ArticleModel {
3 | public id: string;
4 | public title: string;
5 | public is_top: number = 0;
6 | public type_id: string;
7 | public abstract: string;
8 | public pics: string;
9 | public content: string;
10 | public praise: number;
11 | public view_count: number;
12 | public is_original: boolean = true;
13 | public tag: string;
14 | public created_at: string;
15 | }
16 |
17 | export interface ITag {
18 | id: string;
19 | name: string;
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/articletype/addarticletype/addarticletype.html:
--------------------------------------------------------------------------------
1 | 添加文章类型
2 |
--------------------------------------------------------------------------------
/src/app/articletype/addarticletype/addarticletype.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class AddArticleTypeService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public addArticleType (data: any) {
13 | return this.http.post('/articletype', data);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/articletype/addarticletype/addarticletype.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { ArticleTypeModel } from '../model/articletype.model';
6 | import { AddArticleTypeService } from './addarticletype.service';
7 |
8 | @Component({
9 | selector: 'app-add-articletype',
10 | templateUrl: './addarticletype.html',
11 | // styles: [],
12 | })
13 | export class AddArticleTypeComponent implements OnInit {
14 | public isConfirmLoading = false;
15 | public addArticleType: ArticleTypeModel = new ArticleTypeModel();
16 | @ViewChild('form') private form: NgForm;
17 |
18 | constructor (
19 | private router: Router,
20 | private addArticleTypeService: AddArticleTypeService,
21 | private notification: NzNotificationService,
22 | ) { }
23 |
24 | public ngOnInit () {
25 | //
26 | }
27 |
28 | public save () {
29 | for (const i in this.form.controls) {
30 | this.form.controls[ i ].markAsDirty();
31 | }
32 | if (this.form.valid) {
33 | this.isConfirmLoading = true;
34 | this.addArticleTypeService.addArticleType(this.addArticleType).subscribe((res: any) => {
35 | this.isConfirmLoading = false;
36 | this.notification.success('成功', res.msg);
37 | this.router.navigate(['/articletype']);
38 | }, (err: any) => {
39 | this.isConfirmLoading = false;
40 | });
41 | }
42 | }
43 |
44 | public back () {
45 | this.router.navigate(['./articletype']);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/articletype/articletype.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { Router } from '@angular/router';
3 |
4 | @Component({
5 | selector: 'app-articletype',
6 | template: '',
7 | })
8 | export class ArticleTypeComponent {
9 |
10 | constructor () {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/articletype/articletype.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { AddArticleTypeComponent } from './addarticletype/addarticletype';
6 | import { AddArticleTypeService } from './addarticletype/addarticletype.service';
7 | import { ArticleTypeComponent } from './articletype.component';
8 | import { ArticleTypeRouting } from './articletype.routing';
9 | import { ArticleTypeListComponent } from './articletypelist/articletypelist';
10 | import { ArticleTypeListService } from './articletypelist/articletypelist.service';
11 | import { EditArticleTypeComponent } from './editarticletype/editarticletype';
12 | import { EditArticleTypeService } from './editarticletype/editarticletype.service';
13 | import { ZorroAntdModule } from '@/antd/ngModule'
14 |
15 | @NgModule({
16 | imports: [
17 | FormsModule,
18 | // ReactiveFormsModule,
19 | CommonModule,
20 | ArticleTypeRouting,
21 | // NgZorroAntdModule.forRoot(),
22 | ZorroAntdModule,
23 | ],
24 | declarations: [
25 | ArticleTypeComponent,
26 | ArticleTypeListComponent,
27 | AddArticleTypeComponent,
28 | EditArticleTypeComponent,
29 | ],
30 | providers: [
31 | ArticleTypeListService,
32 | AddArticleTypeService,
33 | EditArticleTypeService,
34 | ],
35 | })
36 | export default class ArticleTypeModule {}
37 |
--------------------------------------------------------------------------------
/src/app/articletype/articletype.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { AddArticleTypeComponent } from './addarticletype/addarticletype';
5 | import { ArticleTypeComponent } from './articletype.component';
6 | import { ArticleTypeListComponent } from './articletypelist/articletypelist';
7 | import { EditArticleTypeComponent } from './editarticletype/editarticletype';
8 |
9 | const routes: Routes = [
10 | {
11 | path: '',
12 | canActivateChild: [AuthGuard],
13 | component: ArticleTypeComponent,
14 | children: [
15 | { path: '', redirectTo: 'list', pathMatch: 'full' },
16 | { path: 'list', component: ArticleTypeListComponent },
17 | { path: 'add', component: AddArticleTypeComponent },
18 | { path: 'edit/:id', component: EditArticleTypeComponent },
19 | ],
20 | },
21 | ];
22 |
23 | @NgModule({
24 | imports: [RouterModule.forChild(routes)],
25 | exports: [RouterModule],
26 | })
27 | export class ArticleTypeRouting {}
28 |
--------------------------------------------------------------------------------
/src/app/articletype/articletypelist/articletypelist.html:
--------------------------------------------------------------------------------
1 |
2 | 文章类型列表
3 |
21 |
22 |
32 |
33 |
34 | ID |
35 | 类型名称 |
36 | 备注 |
37 | 创建时间 |
38 | 操作 |
39 |
40 |
41 |
42 |
43 | {{data.id}} |
44 | {{data.type_name}} |
45 | {{data.remark}}
46 | |
47 | {{data.created_at}} |
48 | 编辑 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/app/articletype/articletypelist/articletypelist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class ArticleTypeListService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getArticleTypeList (data: any) {
13 | return this.http.get('/articletype?' + this.params.fmtpages(data));
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/articletype/articletypelist/articletypelist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { Router } from '@angular/router';
3 | import { ArticleTypeModel } from '../model/articletype.model';
4 | import { ArticleTypeListService } from './articletypelist.service';
5 | import { finalize } from 'rxjs';
6 |
7 | @Component({
8 | selector: 'app-article-list',
9 | templateUrl: './articletypelist.html',
10 | })
11 | export class ArticleTypeListComponent implements OnInit {
12 |
13 | public current_page = 1;
14 | public per_page = 10;
15 | public total = 1;
16 | public dataSet: ArticleTypeModel[] = [];
17 | public _loading = true;
18 |
19 | public value: any = {};
20 | public _startDate = '';
21 | public __endDate = '';
22 |
23 | public options: object[];
24 |
25 | constructor (
26 | private router: Router,
27 | private articleListService: ArticleTypeListService,
28 | ) {
29 | }
30 |
31 | public ngOnInit () {
32 | this.clear();
33 | this.query();
34 | }
35 |
36 | public query () {
37 | this._loading = true;
38 | this.value.current_page = this.current_page;
39 | this.value.per_page = this.per_page;
40 | this.articleListService.getArticleTypeList(this.value)
41 | .pipe(finalize(() => { this._loading = false; }))
42 | .subscribe((res: any) => {
43 | this.dataSet = res.data;
44 | this.current_page = res.meta.current_page;
45 | this.total = res.meta.total;
46 | }, (e) => { });
47 | }
48 |
49 | public clear () {
50 | this.value = {
51 | type_name: {
52 | val: '',
53 | exp: 'like',
54 | },
55 | remark: {
56 | val: '',
57 | exp: 'like',
58 | },
59 | created_at: {
60 | val: '',
61 | exp: 'between',
62 | },
63 | };
64 | }
65 |
66 | public _startValueChange () {
67 | console.log(this._startDate, this.__endDate);
68 | this.__endDate = this._startDate;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/app/articletype/editarticletype/editarticletype.html:
--------------------------------------------------------------------------------
1 | 编辑文章类型
2 |
--------------------------------------------------------------------------------
/src/app/articletype/editarticletype/editarticletype.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class EditArticleTypeService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getArticleType (id: string) {
13 | return this.http.get('/articletype/' + id);
14 | }
15 |
16 | public updateArticleType (data: any) {
17 | return this.http.put('/articletype/' + data.id, data);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/articletype/editarticletype/editarticletype.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { ActivatedRoute, Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { ArticleTypeModel } from '../model/articletype.model';
6 | import { EditArticleTypeService } from './editarticletype.service';
7 |
8 | @Component({
9 | selector: 'app-edit-articletype',
10 | templateUrl: './editarticletype.html',
11 | // styles: [],
12 | })
13 | export class EditArticleTypeComponent implements OnInit {
14 | public isConfirmLoading = false;
15 | public editArticleType: ArticleTypeModel = new ArticleTypeModel();
16 | @ViewChild('form') private form: NgForm;
17 |
18 | constructor (
19 | private router: Router,
20 | private route: ActivatedRoute,
21 | private editArticleTypeService: EditArticleTypeService,
22 | private notification: NzNotificationService,
23 | ) { }
24 |
25 | public ngOnInit () {
26 | this.route.params.subscribe((param) => {
27 | if (param.id) {
28 | this.getData(param.id);
29 | }
30 | }, (err) => {
31 | this.notification.warning('错误', '参数错误');
32 | });
33 | }
34 |
35 | public getData (id: string) {
36 | this.editArticleTypeService.getArticleType(id).subscribe((res: any) => {
37 | this.editArticleType = res.data;
38 | }, (err) => {
39 | //
40 | });
41 | }
42 |
43 | public save () {
44 | for (const i in this.form.controls) {
45 | this.form.controls[ i ].markAsDirty();
46 | }
47 | if (this.form.valid) {
48 | this.isConfirmLoading = true;
49 | this.editArticleTypeService.updateArticleType(this.editArticleType).subscribe((res: any) => {
50 | this.isConfirmLoading = false;
51 | this.notification.success('成功', res.msg);
52 | this.router.navigate(['/articletype']);
53 | }, (err: any) => {
54 | this.isConfirmLoading = false;
55 | });
56 | }
57 | }
58 |
59 | public back () {
60 | this.router.navigate(['./articletype']);
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/app/articletype/model/articletype.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class ArticleTypeModel {
3 | public id: string;
4 | public type_name: string;
5 | public remark: string;
6 | public created_at: string;
7 | }
8 |
9 | export class ArticleTypeEditModel {
10 | public type_name: string;
11 | public remark: string;
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/charts/chart.html:
--------------------------------------------------------------------------------
1 |
2 | 图表
3 |
--------------------------------------------------------------------------------
/src/app/charts/chart.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { ChartComponent } from './chart.component';
6 | import { ChartService } from './chart.service';
7 | import { ChartRouting } from './chart.routing';
8 | import { OutletComponent } from './out-let.component';
9 | import { ZorroAntdModule } from '@/antd/ngModule'
10 |
11 | @NgModule({
12 | imports: [
13 | FormsModule,
14 | // ReactiveFormsModule,
15 | CommonModule,
16 | ChartRouting,
17 | // NgZorroAntdModule.forRoot(),
18 | ZorroAntdModule,
19 | ],
20 | declarations: [
21 | OutletComponent,
22 | ChartComponent,
23 | ],
24 | providers: [
25 | ChartService,
26 | ],
27 | })
28 | export default class ChartModule {}
29 |
--------------------------------------------------------------------------------
/src/app/charts/chart.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { ChartComponent } from './chart.component';
5 | import { OutletComponent } from './out-let.component';
6 |
7 | const routes: Routes = [
8 | {
9 | path: '',
10 | canActivateChild: [AuthGuard],
11 | component: OutletComponent,
12 | children: [
13 | { path: '', redirectTo: 'list', pathMatch: 'full' },
14 | { path: 'list', component: ChartComponent },
15 | ],
16 | },
17 | ];
18 |
19 | @NgModule({
20 | imports: [RouterModule.forChild(routes)],
21 | exports: [RouterModule],
22 | })
23 | export class ChartRouting {}
24 |
--------------------------------------------------------------------------------
/src/app/charts/chart.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 | import { Params } from '@utils/params.service';
5 |
6 | @Injectable()
7 | export class ChartService {
8 | constructor (
9 | private http: HttpClient,
10 | private params: Params,
11 | ) {}
12 |
13 | public getSystemLog () {
14 | return this.http.get('/chart/systemlog?' + this.params.fmtpages(null));
15 | }
16 |
17 | public getSystemLogDate (date: string) {
18 | return this.http.get('/chart/systemlogdate?' + this.params.fmtpages({date}));
19 | }
20 |
21 | public getArticleType () {
22 | return this.http.get('/chart/articletype?' + this.params.fmtpages(null));
23 | }
24 |
25 | public getArticleTag () {
26 | return this.http.get('/chart/articletag?' + this.params.fmtpages(null));
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/charts/model/chart.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class SystemLogModel {
3 | public date: string;
4 | public total: number;
5 | }
6 |
7 | export interface ISystemLog {
8 | date: string;
9 | total: number;
10 | }
11 |
12 | export interface IArticleType {
13 | type_name: string;
14 | total: number;
15 | }
16 |
17 | export interface IArticleTag {
18 | name: string;
19 | total: number;
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/charts/out-let.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-charts-outlet',
5 | template: '',
6 | })
7 | export class OutletComponent { }
8 |
--------------------------------------------------------------------------------
/src/app/comment/comment.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-comment',
5 | template: '',
6 | })
7 | export class CommentComponent {
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/comment/comment.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { CommentComponent } from './comment.component';
6 | import { CommentListComponent } from './commentlist/commentlist';
7 | import { CommentListService } from './commentlist/commentlist.service';
8 | import { CommentDetailComponent } from './commentdetail/commentdetail';
9 | import { CommentDetailService } from './commentdetail/commentdetail.service';
10 | import { CommentRouting } from './comment.routing';
11 | import { ZorroAntdModule } from '@/antd/ngModule'
12 |
13 | @NgModule({
14 | imports: [
15 | FormsModule,
16 | // ReactiveFormsModule,
17 | CommonModule,
18 | CommentRouting,
19 | // NgZorroAntdModule.forRoot(),
20 | ZorroAntdModule,
21 | ],
22 | declarations: [
23 | CommentComponent,
24 | CommentListComponent,
25 | CommentDetailComponent,
26 | ],
27 | providers: [
28 | CommentListService,
29 | CommentDetailService,
30 | ],
31 | })
32 | export default class CommentModule {}
33 |
--------------------------------------------------------------------------------
/src/app/comment/comment.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { CommentComponent } from './comment.component';
5 | import { CommentListComponent } from './commentlist/commentlist';
6 | import { CommentDetailComponent } from './commentdetail/commentdetail';
7 |
8 | const routes: Routes = [
9 | {
10 | path: '',
11 | canActivateChild: [AuthGuard],
12 | component: CommentComponent,
13 | children: [
14 | { path: '', redirectTo: 'list', pathMatch: 'full' },
15 | { path: 'list', component: CommentListComponent },
16 | { path: 'detail/:id', component: CommentDetailComponent },
17 | ],
18 | },
19 | ];
20 |
21 | @NgModule({
22 | imports: [RouterModule.forChild(routes)],
23 | exports: [RouterModule],
24 | })
25 | export class CommentRouting {}
26 |
--------------------------------------------------------------------------------
/src/app/comment/commentdetail/commentdetail.html:
--------------------------------------------------------------------------------
1 |
2 | 评论详情
3 |
--------------------------------------------------------------------------------
/src/app/comment/commentdetail/commentdetail.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class CommentDetailService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getComment (id: string) {
13 | return this.http.get('/comment/' + id);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/comment/commentdetail/commentdetail.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { ActivatedRoute, Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { CommentModel } from '../model/comment.model';
6 | import { CommentDetailService } from './commentdetail.service';
7 |
8 | @Component({
9 | selector: 'app-comment-detail',
10 | templateUrl: './commentdetail.html',
11 | // styles: [``],
12 | })
13 | export class CommentDetailComponent implements OnInit {
14 |
15 | public mainModel: CommentModel = new CommentModel();
16 | @ViewChild('form') private form: NgForm;
17 |
18 | public checkedTag = {};
19 | public typeAjaxList: any[] = [];
20 |
21 | constructor (
22 | private router: Router,
23 | private route: ActivatedRoute,
24 | private commentDetailService: CommentDetailService,
25 | private notification: NzNotificationService,
26 | ) { }
27 |
28 | public ngOnInit () {
29 | this.route.params.subscribe((param) => {
30 | if (param.id) {
31 | this.getData(param.id);
32 | }
33 | }, (err) => {
34 | this.notification.warning('错误', '参数错误');
35 | });
36 | }
37 |
38 | public getData (id: string) {
39 | this.commentDetailService.getComment(id).subscribe((res: any) => {
40 | this.mainModel = res.data;
41 | }, (err: any) => { });
42 | }
43 |
44 | public back () {
45 | this.router.navigate(['comment']);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/comment/commentlist/commentlist.html:
--------------------------------------------------------------------------------
1 | 评论列表
2 |
30 |
31 |
41 |
42 |
43 | ID |
44 | 请求ip |
45 | 内容 |
46 | 文章 |
47 | 客户端 |
48 | 文章id |
49 | 父级id |
50 | 创建时间 |
51 | 操作 |
52 |
53 |
54 |
55 |
56 | {{data.id}} |
57 | {{data.ip}} |
58 |
59 | {{data.content}}
60 | |
61 | {{data.article?data.article.title:''}} |
62 |
63 | {{data.client}}
64 | |
65 | {{data.article_id}} |
66 | {{data.parent_id}} |
67 | {{data.created_at}} |
68 |
69 | 详情
70 | 删除
71 | |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/app/comment/commentlist/commentlist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 | import { Params } from '../../../utils/params.service';
5 |
6 | @Injectable()
7 | export class CommentListService {
8 | constructor (
9 | private http: HttpClient,
10 | private params: Params,
11 | ) {}
12 |
13 | public getCommentList (data: any) {
14 | return this.http.get('/comment?' + this.params.fmtpages(data));
15 | }
16 |
17 | public deleteComment (id: string) {
18 | return this.http.delete('/comment/' + id);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/comment/commentlist/commentlist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | // import { NgForm } from '@angular/forms';
3 | import { Router } from '@angular/router';
4 | import { NzModalService } from 'ng-zorro-antd/modal';
5 | import { CommentModel } from '../model/comment.model';
6 | import { CommentListService } from './commentlist.service';
7 | import { finalize } from 'rxjs';
8 |
9 | @Component({
10 | selector: 'app-comment-list',
11 | templateUrl: './commentlist.html',
12 | })
13 | export class CommentListComponent implements OnInit {
14 | // @ViewChild('form') private form: NgForm;
15 | private timer: number = 0;
16 | public current_page = 1;
17 | public per_page = 10;
18 | public total = 1;
19 | public dataSet: CommentModel[] = [];
20 | public _loading = true;
21 |
22 | public value: any = {};
23 | public isVisible = false;
24 | public isConfirmLoading = false;
25 | public deleteId: string;
26 |
27 | public options: object[];
28 |
29 | constructor (
30 | private router: Router,
31 | private modalService: NzModalService,
32 | private commentListService: CommentListService,
33 | ) {
34 | }
35 |
36 | public ngOnInit () {
37 | this.clear();
38 | this.query();
39 | }
40 |
41 | public query () {
42 | // if (cur_page) {
43 | // this.current_page = 1;
44 | // }
45 | this.value.current_page = this.current_page;
46 | this.value.per_page = this.per_page;
47 | this._loading = true;
48 | // clearTimeout(this.timer);
49 | // this.timer = setTimeout(() => {
50 | this.commentListService.getCommentList(this.value)
51 | .pipe(finalize(() => { this._loading = false; }))
52 | .subscribe((res: any) => {
53 | this.dataSet = res.data;
54 | this.total = res.meta.total;
55 | }, (e) => { });
56 | // });
57 | }
58 |
59 | public clear () {
60 | this.value = {
61 | ip: {
62 | val: '',
63 | exp: 'like',
64 | },
65 | content: {
66 | val: '',
67 | exp: 'like',
68 | },
69 | client: {
70 | val: '',
71 | exp: 'like',
72 | },
73 | created_at: {
74 | val: '',
75 | exp: 'between',
76 | },
77 | article_title: '',
78 | };
79 | }
80 |
81 | public delComment (id: string) {
82 | const that = this;
83 | this.modalService.confirm({
84 | nzTitle : '确认是否删除',
85 | nzContent: '删除后将无法找回这条评论',
86 | nzOkLoading: true,
87 | nzOnOk () {
88 | return new Promise((resolve) => {
89 | that.commentListService.deleteComment(id)
90 | .pipe(finalize(() => { resolve(); }))
91 | .subscribe((res: any) => { that.query(); }, (err: any) => { });
92 | });
93 | },
94 | nzOnCancel () { },
95 | });
96 | }
97 |
98 | public ngDoDestory () {
99 | clearTimeout(this.timer);
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/app/comment/model/comment.model.ts:
--------------------------------------------------------------------------------
1 | import { UserModel } from '@app/user/model/user.model';
2 | import { ArticleModel } from '@app/article/model/article.model';
3 |
4 | export class CommentModel {
5 | public id: string;
6 | public article_id: string;
7 | public content: string;
8 | public ip: string;
9 | public client: string;
10 | public parent_id: string;
11 | public created_by: string;
12 | public created_at: string;
13 | public updated_by: string;
14 | public updated_at: string;
15 | public deleted_by: string;
16 | public deleted_at: string;
17 | public version: number;
18 | public creator: UserModel = new UserModel();
19 | public article: ArticleModel = new ArticleModel();
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/dashboard/dashboard.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
28 |
29 |
36 |
37 |
--------------------------------------------------------------------------------
/src/app/dashboard/dashboard.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
3 | import { NgModule } from '@angular/core';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { Dashboard } from './dashboard.component';
6 | import { DashboardRouting } from './dashboard.routing';
7 | import { DashBoardService } from './dashboard.service';
8 | import { NzSelectModule } from '@/antd/module'
9 | import { ZorroAntdModule } from '@/antd/ngModule'
10 |
11 | @NgModule({
12 | imports: [
13 | FormsModule,
14 | CommonModule,
15 | DashboardRouting,
16 | // NgZorroAntdModule.forRoot(),
17 | ZorroAntdModule,
18 | // NzSelectModule,
19 | ],
20 | declarations: [
21 | Dashboard,
22 | ],
23 | providers: [
24 | DashBoardService,
25 | ],
26 | })
27 | export default class DashboardModule {}
28 |
--------------------------------------------------------------------------------
/src/app/dashboard/dashboard.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '../../utils/auth/auth-guard.service';
4 | import { Dashboard } from './dashboard.component';
5 |
6 | const routes: Routes = [
7 | {
8 | path: '',
9 | component: Dashboard,
10 | canActivate: [AuthGuard],
11 | },
12 | ];
13 |
14 | @NgModule({
15 | imports: [RouterModule.forChild(routes)],
16 | exports: [RouterModule],
17 | })
18 | export class DashboardRouting {}
19 |
--------------------------------------------------------------------------------
/src/app/dashboard/dashboard.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient, HttpResponse } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | // import { Observable } from 'rxjs/Observable';
4 | import { Params } from '@utils/params.service';
5 |
6 | @Injectable()
7 | export class DashBoardService {
8 | constructor (
9 | private params: Params,
10 | private http: HttpClient,
11 | ) {}
12 |
13 | public getSystemLogChina (source: string) {
14 | return this.http.get('/chart/syslogchina?' + this.params.fmtpages({source}));
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/app/dashboard/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard.component';
2 |
3 | export * from './dashboard.module';
4 |
--------------------------------------------------------------------------------
/src/app/demos/demos.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | import { BrowserModule } from '@angular/platform-browser';
5 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
6 | import { DemosComponent } from './demos.component';
7 | import { DemosRouting } from './demos.routing';
8 | import { OutletComponent } from './out-let.component';
9 | import { UploadFileModule } from '@components/upload-file/upload-file.module';
10 | import { ZorroAntdModule } from '@/antd/ngModule'
11 | import { DemosService } from './demos.service';
12 |
13 | @NgModule({
14 | imports: [
15 | FormsModule, ReactiveFormsModule,
16 | UploadFileModule,
17 | CommonModule,
18 | DemosRouting,
19 | // NgZorroAntdModule.forRoot(),
20 | ZorroAntdModule,
21 | ],
22 | declarations: [
23 | OutletComponent,
24 | DemosComponent,
25 | ],
26 | providers: [
27 | DemosService
28 | ],
29 | })
30 | export default class DemosModule {}
31 |
--------------------------------------------------------------------------------
/src/app/demos/demos.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { DemosComponent } from './demos.component';
5 | import { OutletComponent } from './out-let.component';
6 |
7 | const routes: Routes = [
8 | {
9 | path: '',
10 | canActivateChild: [AuthGuard],
11 | component: OutletComponent,
12 | children: [
13 | { path: '', redirectTo: 'list', pathMatch: 'full' },
14 | { path: 'list', component: DemosComponent },
15 | ],
16 | },
17 | ];
18 |
19 | @NgModule({
20 | imports: [RouterModule.forChild(routes)],
21 | exports: [RouterModule],
22 | })
23 | export class DemosRouting {}
24 |
--------------------------------------------------------------------------------
/src/app/demos/demos.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient, HttpParams } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 | // import { Params } from '../../../utils/params.service';
5 |
6 | @Injectable()
7 | export class DemosService {
8 | constructor (
9 | private http: HttpClient,
10 | ) {}
11 |
12 | testStatus (params: HttpParams) {
13 | return this.http.get('/article', {params});
14 | }
15 |
16 | testApi (url: string, data: any) {
17 | return this.http.get(url, {params: data});
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/demos/models/demo.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class UrlModel {
3 | public url: string;
4 | public method: string = 'GET';
5 | public params: string;
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/demos/out-let.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-demos-outlet',
5 | template: '',
6 | })
7 | export class OutletComponent { }
8 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleball.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-doubleball',
5 | template: '',
6 | })
7 | export class DoubleBallComponent {
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleball.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { DoubleBallComponent } from './doubleball.component';
6 | import { DoubleBallListComponent } from './doubleballlist/doubleballlist';
7 | import { DoubleBallListService } from './doubleballlist/doubleballlist.service';
8 | import { DoubleBallRouting } from './doubleball.routing';
9 | import { DoubleBallDirective } from './doubleballlist/doubleball.directive';
10 | import { ZorroAntdModule } from '@/antd/ngModule'
11 |
12 | @NgModule({
13 | imports: [
14 | FormsModule,
15 | CommonModule,
16 | DoubleBallRouting,
17 | // NgZorroAntdModule.forRoot(),
18 | ZorroAntdModule,
19 | ],
20 | declarations: [
21 | DoubleBallComponent,
22 | DoubleBallListComponent,
23 |
24 | DoubleBallDirective,
25 | ],
26 | providers: [
27 | DoubleBallListService,
28 | ],
29 | })
30 | export default class DoubleBallModule {}
31 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleball.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { DoubleBallComponent } from './doubleball.component';
5 | import { DoubleBallListComponent } from './doubleballlist/doubleballlist';
6 |
7 | const routes: Routes = [
8 | {
9 | path: '',
10 | canActivateChild: [AuthGuard],
11 | component: DoubleBallComponent,
12 | children: [
13 | { path: '', redirectTo: 'list', pathMatch: 'full' },
14 | { path: 'list', component: DoubleBallListComponent },
15 | ],
16 | },
17 | ];
18 |
19 | @NgModule({
20 | imports: [RouterModule.forChild(routes)],
21 | exports: [RouterModule],
22 | })
23 | export class DoubleBallRouting {}
24 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleballlist/doubleball.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ViewContainerRef, Input, ElementRef, Renderer2 } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[doubleballResult]',
5 | })
6 | export class DoubleBallDirective {
7 | @Input('doubleballResult') public data: string;
8 |
9 | constructor (
10 | private renderer: Renderer2,
11 | private ref: ElementRef,
12 | // private viewContainerRef: ViewContainerRef,
13 | ) { }
14 |
15 | public ngOnInit () {
16 | // this.renderer.appendChild(this.ref.nativeElement, _html.body.querySelector('div'));
17 | this.ref.nativeElement.insertAdjacentHTML('afterbegin', '' + this.data.split(',').map((v, i) => {
18 | return `${v}`;
19 | }).join('') + '
');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleballlist/doubleballlist.html:
--------------------------------------------------------------------------------
1 | 双色球列表
2 |
9 |
10 |
20 |
21 |
22 | 红色球 |
23 | 蓝色球 |
24 | 生成结果 |
25 | 开奖结果 |
26 | 创建时间 |
27 | 操作 |
28 |
29 |
30 |
31 |
32 | {{data.red_balls}} |
33 | {{data.blue_ball}} |
34 | {{data.gen_result}} |
35 | |
36 | {{data.created_at}} |
37 |
38 |
39 | 删除
40 | |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleballlist/doubleballlist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 | import { Params } from '../../../utils/params.service';
5 |
6 | @Injectable()
7 | export class DoubleBallListService {
8 | constructor (
9 | private http: HttpClient,
10 | private params: Params,
11 | ) {}
12 |
13 | public getDoubleBallList (data: any) {
14 | return this.http.get('/doubleball?' + this.params.fmtpages(data));
15 | }
16 |
17 | public addDoubleBall () {
18 | return this.http.post('/doubleball', {});
19 | }
20 |
21 | public deleteDoubleBall (id: string) {
22 | return this.http.delete('/doubleball/' + id);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/doubleball/doubleballlist/doubleballlist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, Input } from '@angular/core';
2 | // import { DomSanitizer } from '@angular/platform-browser';
3 | import { Router } from '@angular/router';
4 | import { NzModalService } from 'ng-zorro-antd/modal';
5 | import { DoubleBallModel } from '../model/doubleball.model';
6 | import { DoubleBallListService } from './doubleballlist.service';
7 | import { finalize } from 'rxjs';
8 |
9 | @Component({
10 | selector: 'app-doubleball-list',
11 | templateUrl: './doubleballlist.html',
12 | })
13 | export class DoubleBallListComponent implements OnInit {
14 |
15 | public current_page = 1;
16 | public per_page = 10;
17 | public total = 1;
18 | public dataSet: DoubleBallModel[] = [];
19 | public _loading = true;
20 |
21 | public value: any = {};
22 | public isVisible = false;
23 | public isConfirmLoading = false;
24 | public deleteId: string;
25 |
26 | public options: object[];
27 |
28 | constructor (
29 | private router: Router,
30 | private modalService: NzModalService,
31 | private doubleBallListService: DoubleBallListService,
32 | ) {
33 | }
34 |
35 | public ngOnInit () {
36 | this.clear();
37 | this.query();
38 | }
39 |
40 | public add () {
41 | this._loading = true;
42 | this.doubleBallListService.addDoubleBall()
43 | .pipe(finalize(() => { this._loading = false; }))
44 | .subscribe((res: any) => {
45 | this.query();
46 | }, (e) => { });
47 | }
48 |
49 | public query () {
50 | this._loading = true;
51 | this.value.current_page = this.current_page;
52 | this.value.per_page = this.per_page;
53 | this.doubleBallListService.getDoubleBallList(this.value)
54 | .pipe(finalize(() => { this._loading = false; }))
55 | .subscribe((res: any) => {
56 | this.dataSet = res.data;
57 | this.current_page = res.meta.current_page;
58 | this.total = res.meta.total;
59 | }, (e) => { });
60 | }
61 |
62 | public clear () {
63 | this.value = {
64 | title: {
65 | val: '',
66 | exp: 'like',
67 | },
68 | abstract: {
69 | val: '',
70 | exp: 'like',
71 | },
72 | };
73 | }
74 |
75 | public delArticle (id: string) {
76 | const that = this;
77 | this.modalService.confirm({
78 | nzTitle : '确认是否删除',
79 | nzContent: '删除后将无法找回这条信息',
80 | nzOkLoading: true,
81 | nzOnOk () {
82 | return new Promise((resolve) => {
83 | that.doubleBallListService.deleteDoubleBall(id)
84 | .pipe(finalize(() => { resolve(); }))
85 | .subscribe((res: any) => { that.query(); }, (err) => { });
86 | });
87 | },
88 | nzOnCancel () { },
89 | });
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/app/doubleball/model/doubleball.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class DoubleBallModel {
3 | public id: string;
4 | public red_balls: string;
5 | public blue_ball: string;
6 | public gen_result: string;
7 | public award: string;
8 | public created_at: string;
9 | }
10 |
11 | export interface ITag {
12 | id: string;
13 | name: string;
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/app/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnDestroy } from '@angular/core';
2 | // import { Http, Response } from '@angular/http';
3 | import { NzNotificationService } from 'ng-zorro-antd/notification';
4 | import { AuthService } from '@utils/auth/auth.service';
5 |
6 | const _PROD_ = process.env.NODE_ENV === 'production';
7 |
8 | @Component({
9 | selector: 'home',
10 | templateUrl: './home.component.html',
11 | // styles: [``],
12 | })
13 | export class HomeComponent implements OnDestroy {
14 |
15 | private counter: number = 0;
16 | private timer: any = null;
17 | private wsHost: string = (/^https:?/ig.test(location.protocol) ? 'wss' : 'ws') + '://' + `${location.host}/ws`;
18 | private ws: WebSocket;
19 | private wsInfo: WSInfoModel = new WSInfoModel();
20 |
21 | private ab2str (ab: ArrayBuffer): string {
22 | const s = String.fromCharCode.apply(null, new Uint8Array(ab));
23 | return decodeURIComponent(s);
24 | }
25 |
26 | private openWS () {
27 | if (!navigator.onLine) {
28 | this.notification.error('错误', '请检查网络连接!');
29 | return;
30 | }
31 | this.ws = null;
32 | this.ws = new WebSocket(this.wsHost);
33 | this.ws.binaryType = 'arraybuffer';
34 | this.ws.onopen = () => {
35 | this.counter = 0;
36 | this.ws.send('connect...');
37 | };
38 | //
39 | this.ws.onmessage = (mEvent: MessageEvent) => {
40 | const data: any = JSON.parse(this.ab2str(mEvent.data));
41 | const opened = JSON.parse(localStorage.getItem('NOTICE_OPEN') ? localStorage.getItem('NOTICE_OPEN') : 'false');
42 |
43 | console.log('mEvent:', data, opened)
44 | if (data && data.data && opened) {
45 | this.wsInfo = data.data;
46 | this.notification.blank('访问信息',
47 | `ip: ${this.wsInfo.ip}
48 | url: ${this.wsInfo.url}
49 | 客户端: ${this.wsInfo.agent}
50 | 位置: ${this.wsInfo.country_name_zh || '-'}/${this.wsInfo.subdivisions_name_zh || '-'}/${this.wsInfo.city_name_zh || '-'}
`, {});
51 | }
52 | };
53 | //
54 | this.ws.onclose = (data: any) => {
55 | console.log(data);
56 | this.reOpen();
57 | };
58 | //
59 | this.ws.onerror = (err: any) => {
60 | console.log(err);
61 | this.reOpen();
62 | };
63 | }
64 |
65 | private reOpen () {
66 | const NOTICE_OPEN = localStorage.getItem('NOTICE_OPEN');
67 | const opened = JSON.parse(NOTICE_OPEN ? NOTICE_OPEN : 'false');
68 | if (!opened) return;
69 | clearTimeout(this.timer);
70 | this.timer = setTimeout(() => {
71 | if (this.counter < 10) {
72 | if (this.ws.CLOSED === this.ws.readyState) {
73 | this.counter++;
74 | this.openWS();
75 | }
76 | } else {
77 | this.notification.error('WebScoket连接失败', '请刷新网页重新连接通知!', {nzDuration: 0});
78 | }
79 | }, 6000);
80 |
81 | }
82 |
83 | constructor (private authService: AuthService, private notification: NzNotificationService) {
84 | // this.wsHost = (_PROD_ ? 'wss' : 'ws') + '://' + this.host;
85 | }
86 |
87 | public ngOnChanges () {
88 | // console.log('ngOnChanges');
89 | }
90 |
91 | public ngOnInit () {
92 | // console.log('ngOnInit');
93 | }
94 |
95 | public ngDoCheck () {
96 | // console.log('ngDoCheck');
97 | }
98 |
99 | public ngAfterContentInit () {
100 | // console.log('ngAfterContentInit');
101 | }
102 |
103 | public ngAfterContentChecked () {
104 | // console.log('ngAfterContentChecked');
105 | }
106 |
107 | public ngAfterViewInit () {
108 | // console.log('ngAfterViewInit');
109 | if (this.authService.isLogged) {
110 | this.openWS();
111 | }
112 | }
113 |
114 | public ngAfterViewChecked () {
115 | // console.log('ngAfterViewChecked');
116 | }
117 |
118 | public ngOnDestroy () {
119 | clearTimeout(this.timer);
120 | }
121 |
122 | }
123 |
124 | class WSInfoModel {
125 | public ip: string;
126 | public created_at: string;
127 | public url: string;
128 | public agent: string;
129 | public country_name_zh: string;
130 | public subdivisions_name_zh: string;
131 | public city_name_zh: string;
132 | }
133 |
--------------------------------------------------------------------------------
/src/app/home/index.ts:
--------------------------------------------------------------------------------
1 | export * from './home.component';
2 |
--------------------------------------------------------------------------------
/src/app/login/bubble.ts:
--------------------------------------------------------------------------------
1 |
2 | class Bubble {
3 | constructor(w = 0, h = 0) {
4 | this.canvasW = w
5 | this.canvasH = h
6 | this.setPosition(true);
7 | }
8 |
9 | canvasW = 0
10 | canvasH = 0
11 | x = 0
12 | y = 0
13 | radius = 0
14 | color = ''
15 | speedX = 0
16 | speedY = 0
17 | growth = 0
18 |
19 | setPosition(init = false) {
20 | this.radius = Math.random() * 50 + 2.5; // 初始半径
21 | this.growth = Math.random() * 0.02 + 0.01; // 增长速度
22 | this.speedY = Math.random() * 4 + 1;
23 | this.speedX = (Math.random() * 4 - 1) * 1;
24 | this.x = Math.random() * this.canvasW;
25 | this.y = init ? Math.random() * this.canvasH : this.canvasH + this.radius;
26 | this.color = this.getRandomColor(); // 随机颜色
27 | }
28 |
29 | draw(ctx: CanvasRenderingContext2D) {
30 | // console.log(this.x, this.y, this.radius)
31 | ctx.beginPath();
32 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
33 | ctx.fillStyle = this.color;
34 | ctx.closePath();
35 | ctx.fill();
36 | }
37 |
38 | update() {
39 | this.x += this.speedX; // 更新x坐标
40 | this.y -= this.speedY; // 更新y坐标
41 | this.radius += this.growth; // 气泡逐渐变大
42 |
43 | // 检查是否超出屏幕边界,如果是则重置
44 | if (this.y + this.radius < 0 || this.x + this.radius < 0 || this.x - this.radius > this.canvasW) {
45 | this.setPosition();
46 | }
47 | }
48 |
49 | getRandomColor() {
50 | const letters = '0123456789ABCDEF';
51 | // let color = '#00bfff' + Math.random().toString(16).slice(2,4);
52 | let color = '#';
53 | for (let i = 0; i < 6; i++) {
54 | color += letters[Math.floor(Math.random() * 16)];
55 | }
56 | return color;
57 | }
58 | }
59 |
60 | export const drawBubbles = (el: HTMLCanvasElement) => {
61 | const ctx = el.getContext('2d', { antialias: true }) as CanvasRenderingContext2D;
62 | const dpr = window.devicePixelRatio || 1;
63 |
64 | // set canvs width and height
65 | const canvasW = window.innerWidth * dpr;
66 | const canvasH = window.innerHeight * dpr;
67 | el.width = canvasW;
68 | el.height = canvasH;
69 |
70 | const bubbles: Bubble[] = [];
71 | const maxBubbles = 120;
72 |
73 | function createBubbles() {
74 | for (let i = 0; i < maxBubbles; i++) {
75 | bubbles.push(new Bubble(canvasW, canvasH));
76 | }
77 | }
78 | createBubbles();
79 |
80 | // animate
81 | function animate() {
82 | ctx.clearRect(0, 0, canvasW, canvasH);
83 | ctx.imageSmoothingEnabled = true;
84 | bubbles.forEach(bubble => {
85 | bubble.draw(ctx);
86 | bubble.update();
87 | });
88 | requestAnimationFrame(animate);
89 | }
90 | animate();
91 | }
--------------------------------------------------------------------------------
/src/app/login/login.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { NgForm, NonNullableFormBuilder, Validators } from '@angular/forms';
4 | import { AuthService } from '@utils/auth/auth.service';
5 | import { finalize } from 'rxjs';
6 | import { drawBubbles } from './bubble'
7 |
8 | @Component({
9 | selector: 'app-login',
10 | templateUrl: './login.html',
11 | // styleUrl: './style.less',
12 | styles: [`
13 | canvas {
14 | position: absolute;
15 | z-index: 0;
16 | top: 0;
17 | left: 0;
18 | width: 100%;
19 | height: 100%;
20 | background: #f7f7f7;
21 | // background: linear-gradient(to bottom, #87ceeb55, #87ceeb);
22 | }
23 | .login-form {
24 | position: relative;
25 | width: 300px;
26 | margin: 0 auto;
27 | }
28 |
29 | .login-form-forgot {
30 | float: right;
31 | }
32 |
33 | .login-form-button {
34 | width: 100%;
35 | }
36 | `],
37 | })
38 | export class LoginComponent implements OnInit {
39 | public loading: boolean = false;
40 | public _window: any;
41 | @ViewChild('canvas') private canvas: ElementRef;
42 | @ViewChild('form') private form: NgForm;
43 | public userInfo: UserModel = new UserModel();
44 | loginForm: ValidateForm;
45 |
46 | constructor (
47 | private http: HttpClient,
48 | private authService: AuthService,
49 | private fb: NonNullableFormBuilder
50 | ) {
51 | if (this.authService.isLogged) {
52 | location.href = '/dashboard';
53 | }
54 | this.loginForm = this.fb.group({
55 | username: ['', [Validators.required]],
56 | password: ['', [Validators.required]],
57 | remember: [false]
58 | });
59 | }
60 |
61 | public ngOnInit () {
62 | //
63 | }
64 |
65 | ngAfterViewInit() {
66 | drawBubbles(this.canvas.nativeElement)
67 | }
68 |
69 | onSubmit() {
70 | if (this.loginForm.valid) {
71 | // 表单数据提交逻辑
72 | console.log(this.loginForm.value);
73 | } else {
74 | const controls = this.loginForm.controls
75 | Object.values(controls).forEach(control => {
76 | control.markAsDirty();
77 | control.updateValueAndValidity();
78 | })
79 | }
80 | }
81 |
82 | public login () {
83 | const form = this.form.form
84 | const controls = form.controls
85 | console.log(form.valid, controls)
86 | for (const i in controls) {
87 | controls[ i ].markAsDirty();
88 | controls[ i ].updateValueAndValidity();
89 | }
90 | if (form.valid) {
91 | // this.authService.login(this.userInfo);
92 | // this.userInfo = new UserModel();
93 | this.loading = true;
94 | this.http.post('/login', this.userInfo)
95 | .pipe(finalize(() => { this.loading = false; }))
96 | .subscribe((res: any) => {
97 | this.authService.isLogged = true;
98 | localStorage.setItem('ACCESS_TOKEN', res.msg);
99 | localStorage.setItem('USER_INFO', JSON.stringify(res.data));
100 | location.href = !!this.authService.redirectUrl ? this.authService.redirectUrl : '/dashboard';
101 | }, (err: any) => { });
102 | }
103 | }
104 |
105 | }
106 |
107 | class UserModel {
108 | public username: string;
109 | public password: string;
110 | }
111 |
--------------------------------------------------------------------------------
/src/app/login/login.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/login/style.less:
--------------------------------------------------------------------------------
1 | .login-form {
2 | max-width: 300px;
3 | margin: 0 auto;
4 | }
5 |
6 | .login-form-forgot {
7 | float: right;
8 | }
9 |
10 | .login-form-button {
11 | width: 100%;
12 | }
--------------------------------------------------------------------------------
/src/app/systemlogs/model/systemlog.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class SystemLogModel {
3 | public id: string;
4 | public request_ip: string;
5 | public request_url: string;
6 | public request_method: string;
7 | public request_params: string;
8 | public request_client: string;
9 | public client_type: string;
10 | public client_version: string;
11 | public host: string;
12 | public hostname: string;
13 | public request_header: string;
14 | public path: string;
15 | public origin: string;
16 | public time: number;
17 | public msg: string;
18 | public source: string;
19 | public created_by: string;
20 | public created_at: string;
21 | public updated_by: string;
22 | public updated_at: string;
23 | public deleted_by: string;
24 | public deleted_at: string;
25 | public version: number;
26 | public creator: UserModel = new UserModel();
27 | }
28 |
29 | class UserModel {
30 | public id: string;
31 | public username: string;
32 | public nick_name: string;
33 | public sex: number;
34 | public user_type: number;
35 | }
36 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemlog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-systemlog',
5 | template: '',
6 | })
7 | export class SystemLogComponent {
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemlog.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { DateTimeRangeModule } from '@components/datetime-picker/datetime-picker.module';
6 | import { SystemLogComponent } from './systemlog.component';
7 | import { SystemLogListComponent } from './systemloglist/systemloglist';
8 | import { SystemLogListService } from './systemloglist/systemloglist.service';
9 | import { SystemLogDetailComponent } from './systemlogdetail/systemlogdetail';
10 | import { SystemLogDetailService } from './systemlogdetail/systemlogdetail.service';
11 | import { SystemLogRouting } from './systemlog.routing';
12 | import { ZorroAntdModule } from '@/antd/ngModule'
13 | import { NzFlexDirective, } from 'ng-zorro-antd/flex'
14 | import { NzGridModule, NzColDirective, NzRowDirective } from 'ng-zorro-antd/grid'
15 |
16 | @NgModule({
17 | imports: [
18 | FormsModule,
19 | CommonModule,
20 | SystemLogRouting,
21 | DateTimeRangeModule,
22 | // NgZorroAntdModule.forRoot(),
23 | ZorroAntdModule,
24 | // NzFlexDirective,
25 | NzGridModule,
26 | // NzColDirective,
27 | ],
28 | declarations: [
29 | SystemLogComponent,
30 | SystemLogListComponent,
31 | SystemLogDetailComponent,
32 | ],
33 | providers: [
34 | SystemLogListService,
35 | SystemLogDetailService,
36 | ],
37 | })
38 | export default class SystemLogModule {}
39 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemlog.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '../../utils/auth/auth-guard.service';
4 | import { SystemLogComponent } from './systemlog.component';
5 | import { SystemLogListComponent } from './systemloglist/systemloglist';
6 | import { SystemLogDetailComponent } from './systemlogdetail/systemlogdetail';
7 |
8 | const routes: Routes = [
9 | {
10 | path: '',
11 | canActivateChild: [AuthGuard],
12 | component: SystemLogComponent,
13 | children: [
14 | { path: '', redirectTo: 'list', pathMatch: 'full' },
15 | { path: 'list', component: SystemLogListComponent },
16 | { path: 'detail/:id', component: SystemLogDetailComponent },
17 | ],
18 | },
19 | ];
20 |
21 | @NgModule({
22 | imports: [RouterModule.forChild(routes)],
23 | exports: [RouterModule],
24 | })
25 | export class SystemLogRouting {}
26 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemlogdetail/systemlogdetail.html:
--------------------------------------------------------------------------------
1 |
2 | 系统日志详情
3 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemlogdetail/systemlogdetail.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class SystemLogDetailService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getSystemLog (id: string) {
13 | return this.http.get('/systemlog/' + id);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemlogdetail/systemlogdetail.ts:
--------------------------------------------------------------------------------
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { ActivatedRoute, Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { SystemLogModel } from '../model/systemlog.model';
6 | import { SystemLogDetailService } from './systemlogdetail.service';
7 |
8 | @Component({
9 | selector: 'app-systemlog-detail',
10 | templateUrl: './systemlogdetail.html',
11 | // styles: [``],
12 | })
13 | export class SystemLogDetailComponent implements OnInit {
14 |
15 | public mainModel: SystemLogModel = new SystemLogModel();
16 | @ViewChild('form') private form: NgForm;
17 |
18 | public checkedTag = {};
19 | public typeAjaxList: any[] = [];
20 |
21 | constructor (
22 | private router: Router,
23 | private route: ActivatedRoute,
24 | private systemLogDetailService: SystemLogDetailService,
25 | private notification: NzNotificationService,
26 | ) { }
27 |
28 | public ngOnInit () {
29 | this.route.params.subscribe((param) => {
30 | if (param.id) {
31 | this.getData(param.id);
32 | }
33 | }, (err) => {
34 | this.notification.warning('错误', '参数错误');
35 | });
36 | }
37 |
38 | public getData (id: string) {
39 | this.systemLogDetailService.getSystemLog(id).subscribe((res: any) => {
40 | this.mainModel = res.data;
41 | }, (err: any) => { });
42 | }
43 |
44 | public back () {
45 | this.router.navigate(['systemlog']);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemloglist/systemloglist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Observable } from 'rxjs';
4 | import { Params } from '../../../utils/params.service';
5 |
6 | @Injectable()
7 | export class SystemLogListService {
8 | constructor (
9 | private http: HttpClient,
10 | private params: Params,
11 | ) {}
12 |
13 | public getSystemLogList (data: any) {
14 | return this.http.get('/systemlog?' + this.params.fmtpages(data));
15 | }
16 |
17 | public deleteSystemLog (id: string) {
18 | return this.http.delete('/systemlog/' + id);
19 | }
20 |
21 | public syncGeoInfo () {
22 | return this.http.post('/system/geoinfo', {});
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/systemlogs/systemloglist/systemloglist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | // import { NgForm } from '@angular/forms';
3 | // import { Router } from '@angular/router';
4 | import { NzModalService } from 'ng-zorro-antd/modal';
5 | import { SystemLogModel } from '../model/systemlog.model';
6 | import { SystemLogListService } from './systemloglist.service';
7 | // import * as Moment from 'moment'
8 | import { finalize } from 'rxjs';
9 | // import { } from 'ng-zorro-antd/flex'
10 |
11 | @Component({
12 | selector: 'app-systemlog-list',
13 | templateUrl: './systemloglist.html',
14 | })
15 | export class SystemLogListComponent implements OnInit {
16 | // @ViewChild('form') private form: NgForm;
17 | private timer: number = 0;
18 | public current_page = 1;
19 | public per_page = 10;
20 | public total = 1;
21 | public dataSet: SystemLogModel[] = [];
22 | public _loading = true;
23 |
24 | public value: any = {};
25 | public isVisible = false;
26 | public deleteId: string;
27 | public startDate: string;
28 | public endDate: string;
29 |
30 | public options: object[];
31 |
32 | nzSpan = 6
33 | nzGutter = [12, 12]
34 |
35 | constructor (
36 | // private router: Router,
37 | private modalService: NzModalService,
38 | private systemLogListService: SystemLogListService,
39 | ) { }
40 |
41 | public ngOnInit () {
42 | this.clear();
43 | this.query(undefined);
44 | }
45 |
46 | public query (cur_page: number) {
47 | if (cur_page) {
48 | this.current_page = 1;
49 | }
50 | if(this.value.created_at.val.length) {
51 | this.value.created_at.val = this.value.created_at.val.map((d: Date, i: number) => {
52 | return i > 0 ? d['format']('YYYY/MM/DD 23:59:59:999') : d['format']('YYYY/MM/DD 00:00:00:000')
53 | })
54 |
55 | console.log(this.value.created_at, 'this.value')
56 | }
57 | this.value.current_page = this.current_page;
58 | this.value.per_page = this.per_page;
59 | this._loading = true;
60 | this.systemLogListService.getSystemLogList(this.value)
61 | .pipe(finalize(() => { this._loading = false; }))
62 | .subscribe((res: any) => {
63 | this.dataSet = res.data;
64 | this.total = res.meta.total;
65 | }, (e) => { });
66 | }
67 |
68 | public clear () {
69 | this.value = {
70 | request_ip: {
71 | val: '',
72 | exp: 'like',
73 | },
74 | request_method: {
75 | val: '',
76 | exp: 'like',
77 | },
78 | client_version: {
79 | val: '',
80 | exp: 'like',
81 | },
82 | status: {
83 | val: '',
84 | exp: 'in',
85 | },
86 | time: {
87 | val: '',
88 | exp: 'between',
89 | },
90 | created_at: {
91 | val: '',
92 | exp: 'between',
93 | },
94 | source: {
95 | val: '',
96 | exp: '=',
97 | },
98 | };
99 | }
100 |
101 | public delSystemLog (id: string) {
102 | const that = this;
103 | this.modalService.confirm({
104 | nzTitle : '确认是否删除',
105 | nzContent: '删除后将无法找回这条日志',
106 | nzOkLoading: true,
107 | nzOnOk () {
108 | return new Promise((resolve) => {
109 | that.systemLogListService.deleteSystemLog(id)
110 | .pipe(finalize(() => { resolve(); }))
111 | .subscribe((res: any) => { that.query(undefined); }, (err) => { });
112 | });
113 | },
114 | nzOnCancel () { },
115 | });
116 | }
117 |
118 | public getStatus (status: number) {
119 | let nzStatus = '';
120 | switch (status) {
121 | case 200:
122 | case 201:
123 | nzStatus = 'success';
124 | break;
125 | case 400:
126 | case 401:
127 | case 403:
128 | case 404:
129 | case 405:
130 | case 406:
131 | nzStatus = 'warning';
132 | break;
133 | case 500:
134 | case 501:
135 | case 502:
136 | case 503:
137 | case 504:
138 | case 505:
139 | nzStatus = 'error';
140 | break;
141 |
142 | default:
143 | nzStatus = 'default';
144 | break;
145 | }
146 | return nzStatus;
147 | }
148 |
149 | public sync () {
150 | this._loading = true;
151 | this.systemLogListService.syncGeoInfo()
152 | .pipe(finalize(() => { this._loading = false; }))
153 | .subscribe((res: any) => {
154 | this.query(this.current_page);
155 | }, (e) => { });
156 | }
157 |
158 | public ngDoDestory () {
159 | clearTimeout(this.timer);
160 | }
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/src/app/tag/addtag/addtag.html:
--------------------------------------------------------------------------------
1 | 添加文章标签
2 |
--------------------------------------------------------------------------------
/src/app/tag/addtag/addtag.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable()
5 | export class AddTagService {
6 | constructor (
7 | private http: HttpClient,
8 | ) {}
9 |
10 | public addTag (data: any) {
11 | return this.http.post('/tag', data);
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/tag/addtag/addtag.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { TagModel } from '../model/tag.model';
6 |
7 | import { AddTagService } from './addtag.service';
8 |
9 | @Component({
10 | selector: 'app-add-tag',
11 | templateUrl: './addtag.html',
12 | // styles: [],
13 | })
14 | export class AddTagComponent implements OnInit {
15 | public isConfirmLoading = false;
16 | public addTag: TagModel = new TagModel();
17 | @ViewChild('form') private form: NgForm;
18 |
19 | constructor (
20 | private router: Router,
21 | private addTagService: AddTagService,
22 | private notification: NzNotificationService,
23 | ) {
24 | }
25 |
26 | public ngOnInit () {
27 | //
28 | }
29 |
30 | public save () {
31 | for (const i in this.form.controls) {
32 | this.form.controls[ i ].markAsDirty();
33 | }
34 | if (this.form.valid) {
35 | this.isConfirmLoading = true;
36 | this.addTagService.addTag(this.addTag).subscribe((res: any) => {
37 | this.isConfirmLoading = false;
38 | this.notification.success('成功', res.msg);
39 | this.router.navigate(['/tag']);
40 | }, (err: any) => {
41 | this.isConfirmLoading = false;
42 | });
43 | }
44 | }
45 |
46 | public back () {
47 | this.router.navigate(['./tag']);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/tag/edittag/edittag.html:
--------------------------------------------------------------------------------
1 | 编辑文章标签
2 |
--------------------------------------------------------------------------------
/src/app/tag/edittag/edittag.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable()
5 | export class EditTagService {
6 | constructor (
7 | private http: HttpClient,
8 | ) {}
9 |
10 | public getTag (id: string) {
11 | return this.http.get(`/tag/${id}`);
12 | }
13 |
14 | public updateTag (data: any) {
15 | return this.http.put(`/tag/${data.id}`, data);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/tag/edittag/edittag.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { ActivatedRoute, Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { TagModel } from '../model/tag.model';
6 |
7 | import { EditTagService } from './edittag.service';
8 | import { finalize } from 'rxjs';
9 |
10 | @Component({
11 | selector: 'app-edit-tag',
12 | templateUrl: './edittag.html',
13 | // styles: [],
14 | })
15 | export class EditTagComponent implements OnInit {
16 | public isConfirmLoading = false;
17 | public editTag: TagModel = new TagModel();
18 | @ViewChild('form') private form: NgForm;
19 |
20 | constructor (
21 | private router: Router,
22 | private route: ActivatedRoute,
23 | private EditTagService: EditTagService,
24 | private notification: NzNotificationService,
25 | ) {
26 | }
27 |
28 | public ngOnInit () {
29 | this.route.params.subscribe((param) => {
30 | if (param.id) {
31 | this.getData(param.id);
32 | }
33 | }, (err) => {
34 | this.notification.warning('错误', '参数错误');
35 | });
36 | }
37 |
38 | public getData (id: any) {
39 | this.EditTagService.getTag(id).subscribe((res: any) => {
40 | this.editTag = res.data;
41 | });
42 | }
43 |
44 | public save () {
45 | for (const i in this.form.controls) {
46 | this.form.controls[ i ].markAsDirty();
47 | }
48 | if (this.form.valid) {
49 | this.isConfirmLoading = true;
50 | this.EditTagService.updateTag(this.editTag)
51 | .pipe(finalize(() => this.isConfirmLoading = false))
52 | .subscribe((res: any) => {
53 | this.router.navigate(['/tag']);
54 | }, (err: any) => { });
55 | }
56 | }
57 |
58 | public back () {
59 | this.router.navigate(['./tag']);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/app/tag/index.ts:
--------------------------------------------------------------------------------
1 | export * from './tag.component';
2 |
--------------------------------------------------------------------------------
/src/app/tag/model/tag.model.ts:
--------------------------------------------------------------------------------
1 | class BaseModel {
2 | public current_page: number;
3 | public per_page: number = 10;
4 | public total: number;
5 | }
6 |
7 | export class TagModel extends BaseModel {
8 | public id: string;
9 | public name: string;
10 | public remark: string;
11 | public created_at: string;
12 | }
13 |
--------------------------------------------------------------------------------
/src/app/tag/tag.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-tag',
5 | template: '',
6 | })
7 | export class TagComponent {
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/tag/tag.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { AddTagComponent } from './addtag/addtag';
6 | import { AddTagService } from './addtag/addtag.service';
7 | import { EditTagComponent } from './edittag/edittag';
8 | import { EditTagService } from './edittag/edittag.service';
9 | import { TagComponent } from './tag.component';
10 | import { TagRouting } from './tag.routing';
11 | import { TagListComponent } from './taglist/taglist';
12 | import { TagListService } from './taglist/taglist.service';
13 | import { ZorroAntdModule } from '@/antd/ngModule'
14 |
15 | @NgModule({
16 | imports: [
17 | FormsModule,
18 | CommonModule,
19 | TagRouting,
20 | // NgZorroAntdModule.forRoot(),
21 | ZorroAntdModule,
22 | ],
23 | declarations: [
24 | TagComponent,
25 | TagListComponent,
26 | AddTagComponent,
27 | EditTagComponent,
28 | ],
29 | providers: [
30 | TagListService,
31 | AddTagService,
32 | EditTagService,
33 | ],
34 | })
35 | export default class TagModule {}
36 |
--------------------------------------------------------------------------------
/src/app/tag/tag.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '../../utils/auth/auth-guard.service';
4 | import { AddTagComponent } from './addtag/addtag';
5 | import { EditTagComponent } from './edittag/edittag';
6 | import { TagComponent } from './tag.component';
7 | import { TagListComponent } from './taglist/taglist';
8 |
9 | const routes: Routes = [
10 | {
11 | path: '',
12 | canActivateChild: [AuthGuard],
13 | component: TagComponent,
14 | children: [
15 | { path: '', redirectTo: 'list', pathMatch: 'full' },
16 | { path: 'list', component: TagListComponent },
17 | { path: 'add', component: AddTagComponent },
18 | { path: 'edit/:id', component: EditTagComponent },
19 | ],
20 | },
21 | ];
22 |
23 | @NgModule({
24 | imports: [RouterModule.forChild(routes)],
25 | exports: [RouterModule],
26 | })
27 | export class TagRouting {}
28 |
--------------------------------------------------------------------------------
/src/app/tag/taglist/taglist.html:
--------------------------------------------------------------------------------
1 | 标签列表
2 |
20 |
21 |
31 |
32 |
33 | ID |
34 | 类型名称 |
35 | 备注 |
36 | 创建时间 |
37 | 操作 |
38 |
39 |
40 |
41 |
42 | {{data.id}} |
43 | {{data.name}} |
44 | {{data.remark}}
45 | |
46 | {{data.created_at}} |
47 | 编辑 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/app/tag/taglist/taglist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class TagListService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getTagList (data: any) {
13 | return this.http.get('/tag?' + this.params.fmtpages(data));
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/tag/taglist/taglist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { TagListService } from './taglist.service';
3 | import { finalize } from 'rxjs';
4 |
5 | @Component({
6 | selector: 'app-tag-list',
7 | templateUrl: './taglist.html',
8 | })
9 | export class TagListComponent implements OnInit {
10 |
11 | public current_page = 1;
12 | public per_page = 10;
13 | public total = 1;
14 | public dataSet: any = [];
15 | public _loading = true;
16 |
17 | public value: any = {};
18 |
19 | constructor (
20 | private tagListService: TagListService,
21 | ) { }
22 |
23 | public ngOnInit () {
24 | this.clear();
25 | this.query();
26 | }
27 |
28 | public query () {
29 | this.value.current_page = this.current_page;
30 | this.value.per_page = this.per_page;
31 | this._loading = true;
32 | this.tagListService.getTagList(this.value)
33 | .pipe(finalize(() => this._loading = false))
34 | .subscribe((res: any) => {
35 | this.dataSet = res.data;
36 | this.current_page = res.meta.current_page;
37 | this.total = res.meta.total;
38 | }, (err: any) => { });
39 | }
40 |
41 | public clear () {
42 | this.value = {
43 | name: {
44 | val: '',
45 | exp: 'like',
46 | },
47 | remark: {
48 | val: '',
49 | exp: 'like',
50 | },
51 | created_at: {
52 | val: '',
53 | exp: 'between',
54 | },
55 | };
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/app/user/adduser/adduser.html:
--------------------------------------------------------------------------------
1 | 添加用户
2 |
--------------------------------------------------------------------------------
/src/app/user/adduser/adduser.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable()
5 | export class AddUserService {
6 | constructor (
7 | private http: HttpClient,
8 | ) {}
9 |
10 | public addUser (data: any) {
11 | return this.http.post('/user', data);
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/user/adduser/adduser.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { UserModel } from '../model/user.model';
6 |
7 | import { AddUserService } from './adduser.service';
8 |
9 | @Component({
10 | selector: 'app-add-user',
11 | templateUrl: './adduser.html',
12 | // styles: [],
13 | })
14 | export class AddUserComponent implements OnInit {
15 | public isConfirmLoading = false;
16 | public addUser: UserModel = new UserModel();
17 | @ViewChild('form') private form: NgForm;
18 |
19 | constructor (
20 | private router: Router,
21 | private addUserService: AddUserService,
22 | private notification: NzNotificationService,
23 | ) {
24 | }
25 |
26 | public ngOnInit () {
27 | //
28 | }
29 |
30 | public save () {
31 | for (const i in this.form.controls) {
32 | this.form.controls[ i ].markAsDirty();
33 | }
34 | if (this.form.valid) {
35 | this.isConfirmLoading = true;
36 | this.addUserService.addUser(this.addUser).subscribe((res: any) => {
37 | this.isConfirmLoading = false;
38 | this.notification.success('成功', res.msg);
39 | this.router.navigate(['/user']);
40 | }, (err: any) => {
41 | this.isConfirmLoading = false;
42 | });
43 | }
44 | }
45 |
46 | public back () {
47 | this.router.navigate(['./user']);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/user/edituser/edituser.html:
--------------------------------------------------------------------------------
1 | 添加用户
2 |
--------------------------------------------------------------------------------
/src/app/user/edituser/edituser.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable()
5 | export class EditUserService {
6 | constructor (
7 | private http: HttpClient,
8 | ) {}
9 |
10 | public getUser (id: any) {
11 | return this.http.get(`/user/${id}`);
12 | }
13 |
14 | public updateUser (data: any) {
15 | return this.http.put(`/user/${data.id}`, data);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/user/edituser/edituser.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, ViewChild } from '@angular/core';
2 | import { NgForm } from '@angular/forms';
3 | import { ActivatedRoute, Router } from '@angular/router';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 | import { UserModel } from '../model/user.model';
6 |
7 | import { EditUserService } from './edituser.service';
8 | import { finalize } from 'rxjs';
9 |
10 | @Component({
11 | selector: 'app-edit-user',
12 | templateUrl: './edituser.html',
13 | // styles: [],
14 | })
15 | export class EditUserComponent implements OnInit {
16 | public isConfirmLoading = false;
17 | public editUser: UserModel = new UserModel();
18 | @ViewChild('form') private form: NgForm;
19 |
20 | constructor (
21 | private router: Router,
22 | private route: ActivatedRoute,
23 | private editUserService: EditUserService,
24 | private notification: NzNotificationService,
25 | ) {
26 | }
27 |
28 | public ngOnInit () {
29 | this.route.params.subscribe((param) => {
30 | if (param.id) {
31 | this.getData(param.id);
32 | }
33 | }, (err) => {
34 | this.notification.warning('错误', '参数错误');
35 | });
36 | }
37 |
38 | public getData (id: any) {
39 | this.editUserService.getUser(id).subscribe((res: any) => {
40 | this.editUser = res.data;
41 | });
42 | }
43 |
44 | public save () {
45 | for (const i in this.form.controls) {
46 | this.form.controls[ i ].markAsDirty();
47 | }
48 | if (this.form.valid) {
49 | this.isConfirmLoading = true;
50 | this.editUserService.updateUser(this.editUser)
51 | .pipe(finalize(() => this.isConfirmLoading = false))
52 | .subscribe((res: any) => {
53 | this.router.navigate(['/user']);
54 | });
55 | }
56 | }
57 |
58 | public back () {
59 | this.router.navigate(['./user']);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/app/user/index.ts:
--------------------------------------------------------------------------------
1 | export * from './user.component';
2 |
--------------------------------------------------------------------------------
/src/app/user/model/user.model.ts:
--------------------------------------------------------------------------------
1 |
2 | export class UserModel {
3 | public id: string;
4 | public username: string;
5 | public password: string;
6 | public nick_name: string;
7 | public sex: number;
8 | public user_type: number;
9 | public remark: string;
10 | public created_at: string;
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/user/user.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-user',
5 | template: '',
6 | })
7 | export class UserComponent {
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/user/user.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4 | // import { NgZorroAntdModule } from 'ng-zorro-antd';
5 | import { AddUserComponent } from './adduser/adduser';
6 | import { AddUserService } from './adduser/adduser.service';
7 | import { EditUserComponent } from './edituser/edituser';
8 | import { EditUserService } from './edituser/edituser.service';
9 | import { UserComponent } from './user.component';
10 | import { UserRouting } from './user.routing';
11 | import { UserListComponent } from './userlist/userlist';
12 | import { UserListService } from './userlist/userlist.service';
13 | import { ZorroAntdModule } from '@/antd/ngModule'
14 |
15 | @NgModule({
16 | imports: [
17 | FormsModule,
18 | CommonModule,
19 | UserRouting,
20 | // NgZorroAntModule.forRoot(),
21 | ZorroAntdModule,
22 | ],
23 | declarations: [
24 | UserComponent,
25 | UserListComponent,
26 | AddUserComponent,
27 | EditUserComponent,
28 | ],
29 | providers: [
30 | UserListService,
31 | AddUserService,
32 | EditUserService,
33 | ],
34 | })
35 | export default class UserModule {}
36 |
--------------------------------------------------------------------------------
/src/app/user/user.routing.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import { AuthGuard } from '@utils/auth/auth-guard.service';
4 | import { AddUserComponent } from './adduser/adduser';
5 | import { EditUserComponent } from './edituser/edituser';
6 | import { UserComponent } from './user.component';
7 | import { UserListComponent } from './userlist/userlist';
8 |
9 | const routes: Routes = [
10 | {
11 | path: '',
12 | // canActivateChild: [AuthGuard],
13 | component: UserComponent,
14 | children: [
15 | { path: '', redirectTo: 'list', pathMatch: 'full' },
16 | { path: 'list', component: UserListComponent },
17 | { path: 'add', component: AddUserComponent },
18 | { path: 'edit/:id', component: EditUserComponent },
19 | ],
20 | },
21 | ];
22 |
23 | @NgModule({
24 | imports: [RouterModule.forChild(routes)],
25 | exports: [RouterModule],
26 | })
27 | export class UserRouting {}
28 |
--------------------------------------------------------------------------------
/src/app/user/userlist/userlist.html:
--------------------------------------------------------------------------------
1 |
2 | 用户列表
3 |
24 |
25 |
35 |
36 |
37 | ID |
38 | 用户名称 |
39 | 用户昵称 |
40 | 性别 |
41 | 用户类型 |
42 | 备注 |
43 | 创建时间 |
44 | 操作 |
45 |
46 |
47 |
48 |
49 | {{data.id}} |
50 | {{data.username}} |
51 | {{data.nick_name}} |
52 | {{data.sex}} |
53 | {{data.user_type}} |
54 | {{data.remark}}
55 | |
56 | {{data.created_at}} |
57 |
58 | 编辑
59 | 删除
60 | |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | 确认删除该条信息?
69 |
70 |
--------------------------------------------------------------------------------
/src/app/user/userlist/userlist.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { Params } from '../../../utils/params.service';
4 |
5 | @Injectable()
6 | export class UserListService {
7 | constructor (
8 | private http: HttpClient,
9 | private params: Params,
10 | ) {}
11 |
12 | public getUserList (data: any) {
13 | return this.http.get('/user?' + this.params.fmtpages(data));
14 | }
15 |
16 | public deleteUser (id: string) {
17 | return this.http.delete('/user/' + id);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/user/userlist/userlist.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { UserListService } from './userlist.service';
3 | import { finalize } from 'rxjs';
4 |
5 | @Component({
6 | selector: 'app-user-list',
7 | templateUrl: './userlist.html',
8 | })
9 | export class UserListComponent implements OnInit {
10 |
11 | public current_page = 1;
12 | public per_page = 10;
13 | public total = 1;
14 | public dataSet: any = [];
15 | public _loading = true;
16 |
17 | public value: any = {};
18 | public isVisible = false;
19 | public isConfirmLoading = false;
20 | public deleteId: string;
21 |
22 | constructor (
23 | private userListService: UserListService,
24 | ) {
25 | }
26 |
27 | public ngOnInit () {
28 | this.clear();
29 | this.query();
30 | }
31 |
32 | public query () {
33 | this.value.current_page = this.current_page;
34 | this.value.per_page = this.per_page;
35 | this._loading = true;
36 | this.userListService.getUserList(this.value)
37 | .pipe(finalize(() => { this._loading = false; }))
38 | .subscribe((res: any) => {
39 | this.dataSet = res.data;
40 | this.current_page = res.meta.current_page;
41 | this.total = res.meta.total;
42 | }, (err: any) => { });
43 | }
44 |
45 | public clear () {
46 | this.value = {
47 | username: {
48 | val: '',
49 | exp: 'like',
50 | },
51 | nick_name: {
52 | val: '',
53 | exp: 'like',
54 | },
55 | remark: {
56 | val: '',
57 | exp: 'like',
58 | },
59 | created_at: {
60 | val: '',
61 | exp: 'between',
62 | },
63 | };
64 | }
65 |
66 | public delUser (id: string) {
67 | if (id) {
68 | this.deleteId = id;
69 | this.isVisible = true;
70 | } else {
71 | this.isConfirmLoading = true;
72 | this.userListService.deleteUser(this.deleteId).subscribe((res: any) => {
73 | this.isVisible = false;
74 | this.query();
75 | this.isConfirmLoading = false;
76 | }, (err: any) => {
77 | this.isConfirmLoading = false;
78 | });
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/assets/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "Menus": {
3 | "Blog_Management": "Blog Management",
4 | "Article_List": "Article List",
5 | "ArticleType_List": "ArticleType List",
6 | "Tag_List": "Tag List",
7 | "User_List": "User List",
8 | "Comment_List": "Comment List",
9 |
10 | "Log_Management": "Log Management",
11 | "System_Log": "System Logs",
12 |
13 | "Chart_Management": "Chart Management",
14 | "Chart_Statistics": "Chart Statistics",
15 |
16 | "Tests": "Tests",
17 | "Test_Demo": "Test Demo"
18 | }
19 | }
--------------------------------------------------------------------------------
/src/assets/i18n/zh.json:
--------------------------------------------------------------------------------
1 | {
2 | "Menus": {
3 | "Blog_Management": "博客管理",
4 | "Article_List": "文章列表",
5 | "ArticleType_List": "文章类型",
6 | "Tag_List": "标签管理",
7 | "User_List": "用户管理",
8 | "Comment_List": "评论管理",
9 |
10 | "Log_Management": "日志管理",
11 | "System_Log": "系统日志",
12 |
13 | "Chart_Management": "图表管理",
14 | "Chart_Statistics": "图表统计",
15 |
16 | "Tests": "测试",
17 | "Test_Demo": "测试用例"
18 | }
19 | }
--------------------------------------------------------------------------------
/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xpioneer/angular-typescript/d4daa8f288fc0fa9abfe9fd6531f55904687c56e/src/assets/images/logo.png
--------------------------------------------------------------------------------
/src/assets/images/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/components/datetime-picker/datetime-picker.component.ts:
--------------------------------------------------------------------------------
1 | import { forwardRef, Component, ElementRef, Input, OnInit, Output, ViewChild } from '@angular/core';
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
3 | import { format } from 'date-fns'
4 |
5 | @Component({
6 | selector: 'app-datetime-range',
7 | templateUrl: './datetime-range.html',
8 | styles: [`
9 | app-datetime-range{
10 | display: block;
11 | }
12 | `],
13 | providers : [{
14 | provide : NG_VALUE_ACCESSOR,
15 | useExisting: forwardRef(() => DateTimeRangeComponent),
16 | multi : true,
17 | }],
18 | })
19 | export class DateTimeRangeComponent implements ControlValueAccessor, OnInit {
20 | @Input() public xSize: string = 'default';
21 | @Input() public xFormat: string = 'YYYY-MM-DD';
22 | @Input('dateRange') public _value: any;
23 |
24 | public spanStyle: object = {};
25 | public dateStyle: object = {};
26 | public startDate: any = null;
27 | public endDate: any = null;
28 |
29 | public onChange: any = Function.prototype;
30 | public onTouched: any = Function.prototype;
31 |
32 | constructor () {}
33 |
34 | public ngOnInit () {
35 | console.log(this.xFormat, this.xSize);
36 | this.dateStyle = {
37 | width: '48%',
38 | float: 'left',
39 | };
40 | this.spanStyle = {
41 | 'float': 'left',
42 | 'line-height': this.getLineHeight(),
43 | 'text-align': 'center',
44 | 'width': '4%',
45 | };
46 | }
47 |
48 | private getLineHeight () {
49 | if (this.xSize === 'default') {
50 | return '28px';
51 | } else if (this.xSize === 'large') {
52 | return '32px';
53 | } else {
54 | return '24px';
55 | }
56 | }
57 |
58 | public ngOnChanges () {
59 | // this.show = !!this.baseUrl;
60 | }
61 |
62 | public startDateChange (event: any): void {
63 | console.log(event);
64 | }
65 |
66 | get dateRange () {
67 | return this._value;
68 | }
69 |
70 | set dateRange (val: any) {
71 | if ((this._value === val) || (((this._value === undefined) || (this._value === null)) && ((val === undefined) || (val === null)))) {
72 | return;
73 | }
74 | if (val !== this._value) {
75 | this._value = val;
76 | this.onChange(val);
77 | }
78 | }
79 |
80 | public changeSDate (date: any) {
81 | this.startDate = date;
82 | if (!this.endDate || this.startDate > this.endDate) {
83 | this.endDate = date;
84 | }
85 | this.setDateRange();
86 | }
87 |
88 | public changeEDate (date: any) {
89 | this.endDate = date;
90 | if (!this.startDate || this.startDate > this.endDate) {
91 | this.startDate = date;
92 | }
93 | this.setDateRange();
94 | }
95 |
96 | private setDateRange () {
97 | this.onChange([format(this.startDate, 'YYYY-MM-DD HH:mm:ss'), format(this.endDate, 'YYYY-MM-DD HH:mm:ss')]);
98 | }
99 |
100 | public writeValue (value: any): void {
101 | this.dateRange = value;
102 | }
103 |
104 | public registerOnChange (fn: (_: any) => {}): void {
105 | this.onChange = fn;
106 | }
107 |
108 | public registerOnTouched (fn: () => {}): void {
109 | this.onTouched = fn;
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/src/components/datetime-picker/datetime-picker.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3 | import { FormsModule } from '@angular/forms';
4 | import { DateTimeRangeComponent } from './datetime-picker.component';
5 | import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | FormsModule,
11 | NzDatePickerModule, // important
12 | ],
13 | declarations: [
14 | DateTimeRangeComponent,
15 | ],
16 | providers: [
17 | //
18 | ],
19 | schemas: [
20 | CUSTOM_ELEMENTS_SCHEMA,
21 | ],
22 | exports: [
23 | DateTimeRangeComponent,
24 | ],
25 | })
26 | export class DateTimeRangeModule {}
27 |
--------------------------------------------------------------------------------
/src/components/datetime-picker/datetime-range.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
--------------------------------------------------------------------------------
/src/components/editor/editor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/components/editor/editor.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule } from '@angular/forms';
4 | import { BrowserModule } from '@angular/platform-browser';
5 | import { EditorComponent } from './editor.component';
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | FormsModule,
11 | ],
12 | declarations: [
13 | EditorComponent,
14 | ],
15 | exports: [
16 | EditorComponent,
17 | ],
18 | })
19 | export class EditorModule {}
20 |
--------------------------------------------------------------------------------
/src/components/shared/breadcrumb/breadcrumb.component.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/components/shared/breadcrumb/breadcrumb.component.less:
--------------------------------------------------------------------------------
1 | nz-breadcrumb-item{
2 | span{
3 | display: inline-block;
4 | cursor: pointer;
5 | }
6 | }
--------------------------------------------------------------------------------
/src/components/shared/breadcrumb/breadcrumb.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { ActivatedRoute, Router } from '@angular/router';
3 |
4 | @Component({
5 | selector: 'app-breadcrumb',
6 | templateUrl: './breadcrumb.component.html',
7 | // styleUrls : ['./breadcrumb.component.less'],
8 | })
9 | export class BreadCrumbComponent implements OnInit {
10 | public currentTitle: string = '';
11 | public currentUrl: string = '';
12 |
13 | constructor (
14 | private router: Router,
15 | private route: ActivatedRoute,
16 | ) {
17 | this.currentUrl = router.url;
18 | const children = router.config[0].children;
19 | }
20 |
21 | public ngOnInit () {
22 | //
23 | }
24 |
25 | public dashBoard () {
26 | this.router.navigate(['./dashboard']);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/shared/header/header.component.html:
--------------------------------------------------------------------------------
1 |
6 |
11 |
12 |
21 |
22 |
Angular Zone
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | - Username
32 | - 中文
33 | - {{noticeOpened ? '关闭' : '开启'}}WS通知
34 | - 退出登录({{userInfo.username}})
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/shared/header/header.component.less:
--------------------------------------------------------------------------------
1 | .logo{
2 | display: inline-block;
3 | margin: 15px;
4 | width:34px;
5 | height:34px;
6 | background: url('../../../assets/images/logo.svg') no-repeat center center;
7 | background-size: cover;
8 | // animation: rotate 6s linear 0s infinite normal running;
9 | // transform-origin: center center;
10 | /*transition: all 0.3s;*/
11 |
12 | &:hover{
13 | animation-play-state: paused;
14 | }
15 | }
16 | .sys-name{
17 | font-size: 16px;
18 | color: #fff;
19 | margin: 28px 0 0;
20 | display: inline-block;
21 | vertical-align: top;
22 | }
23 | .user-info{
24 | float: right;
25 | margin: 20px 20px 0 0;
26 | }
27 |
28 | @keyframes rotate{
29 | from{
30 | transform: rotateZ(0deg)
31 | }
32 | to{
33 | transform: rotateZ(360deg)
34 | }
35 | }
36 |
37 | .bar-right{
38 | display: flex;
39 | height: 100%;
40 | position: absolute;
41 | top: 0;
42 | right: 0;
43 | align-items: center;
44 | padding-right: 10px;
45 | }
46 | .bar-right .lang{
47 | margin-right: 10px;
48 | }
49 | .bar-right .anticon{
50 | color: #fff;
51 | font-size: 24px;
52 | cursor: pointer;
53 | }
54 |
--------------------------------------------------------------------------------
/src/components/shared/header/header.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import { en_US, zh_CN, NzI18nService } from 'ng-zorro-antd/i18n';
3 | import { AuthService } from '@utils/auth/auth.service';
4 |
5 | @Component({
6 | selector: 'app-header',
7 | templateUrl: './header.component.html',
8 | // styleUrls : ['./header.component.less'],
9 | styles: [`
10 | header{position: relative}
11 | .logo{
12 | // display: inline-block;
13 | // margin: 10px;
14 | width:44px;
15 | height:44px;
16 | // animation: rotate 6s linear 0s infinite normal running;
17 | // transform-origin: center center;
18 | }
19 | .logo:hover{
20 | animation-play-state: paused;
21 | }
22 | .sys-name{
23 | font-size: 16px;
24 | color: #fff;
25 | // margin: 28px 0 0;
26 | // display: inline-block;
27 | // vertical-align: top;
28 | }
29 | // .user-info{
30 | // float: right;
31 | // margin: 20px 20px 0 0;
32 | // }
33 |
34 | @keyframes rotate{
35 | from{
36 | transform: rotateZ(0deg)
37 | }
38 | to{
39 | transform: rotateZ(360deg)
40 | }
41 | }
42 |
43 | .bar-right{
44 | display: flex;
45 | height: 100%;
46 | position: absolute;
47 | top: 0;
48 | right: 0;
49 | align-items: center;
50 | padding-right: 10px;
51 | }
52 | .bar-right .lang{
53 | margin-right: 10px;
54 | }
55 | .bar-right .anticon{
56 | color: #fff;
57 | font-size: 24px;
58 | cursor: pointer;
59 | }
60 | `],
61 | })
62 | export class HeaderComponent implements OnInit {
63 | public store: any;
64 | public noticeOpened: boolean;
65 | public userInfo: object = {};
66 | public isVertical = false
67 |
68 | constructor (private authService: AuthService, private nzI18nService: NzI18nService) {
69 | this.store = localStorage;
70 | this.noticeOpened = JSON.parse(this.store.getItem('NOTICE_OPEN') ? this.store.getItem('NOTICE_OPEN') : 'false');
71 | }
72 |
73 | public ngOnInit () {
74 | this.userInfo = JSON.parse(this.store.getItem('USER_INFO')) || {};
75 | }
76 |
77 | public toggleLang () {
78 | const lang: string = this.nzI18nService.getLocale().locale;
79 | console.log(lang, this.nzI18nService.getLocale());
80 | if (/zh/ig.test(lang)) {
81 | this.nzI18nService.setLocale(en_US);
82 | } else {
83 | this.nzI18nService.setLocale(zh_CN);
84 | }
85 | }
86 |
87 | public toggleNotice () {
88 | this.noticeOpened = !this.noticeOpened;
89 | this.store.setItem('NOTICE_OPEN', this.noticeOpened);
90 | }
91 |
92 | public logout () {
93 | this.authService.logout();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/components/shared/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sidebar/sidebar.component';
2 | export * from './header/header.component';
3 | export * from './breadcrumb/breadcrumb.component';
4 |
--------------------------------------------------------------------------------
/src/components/shared/sidebar/sidebar.component.html:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 | - 文章列表
5 | - 文章类型
6 | - 标签管理
7 | - 用户管理
8 | - 评论管理
9 |
10 |
11 | -
12 |
15 |
16 | -
17 |
20 |
21 | -
22 |
25 |
26 | -
27 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/components/shared/sidebar/sidebar.component.less:
--------------------------------------------------------------------------------
1 | div{
2 | display: block;
3 | }
--------------------------------------------------------------------------------
/src/components/shared/sidebar/sidebar.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-sidebar',
5 | templateUrl: './sidebar.component.html',
6 | // styleUrls : ['./sidebar.component.less'],
7 | })
8 | export class SidebarComponent implements OnInit {
9 |
10 | public isOpen: AnyObject = {
11 | one: true,
12 | two: false,
13 | three: false,
14 | four: false,
15 | five: false,
16 | };
17 |
18 | private store: object;
19 |
20 | constructor () {
21 | // this.store = localStorage;
22 | }
23 |
24 | public openChange (value: string) {
25 | Object.keys(this.isOpen).forEach((v, i) => {
26 | if (value == v) {
27 | this.isOpen[v] = true;
28 | } else {
29 | this.isOpen[v] = false;
30 | }
31 | });
32 | }
33 |
34 | public ngOnInit () {
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/components/upload-file/upload-file.directvie.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[preViewImg]',
5 | })
6 | export class PreViewDirective {
7 |
8 | constructor (private eleRef: ElementRef) { }
9 |
10 | public wrapEle: any;
11 | public divEle: any;
12 | public btnEle: any;
13 | public imgEle: any;
14 | public timer: any;
15 |
16 | @Input('preViewImg') private preViewImgSrc: string;
17 |
18 | @HostListener('click')
19 | public onClick () {
20 | if (this.preViewImgSrc)
21 | document.body.appendChild(this.createModal());
22 | }
23 |
24 | public ngOnInit () {
25 | //
26 | }
27 |
28 | public createModal () {
29 | if (!this.wrapEle) {
30 | this.wrapEle = document.createElement('div');
31 | this.wrapEle.className = 'pre-view-wrap';
32 | }
33 | if (!this.divEle) {
34 | this.divEle = document.createElement('div');
35 | this.divEle.className = 'pre-view-content';
36 | } else {
37 | this.divEle.className = 'pre-view-content';
38 | }
39 | if (!this.btnEle) {
40 | this.btnEle = document.createElement('button');
41 | this.btnEle.className = 'pre-close-btn';
42 | }
43 | if (!this.imgEle) {
44 | this.imgEle = document.createElement('img');
45 | this.imgEle.src = this.preViewImgSrc;
46 | }
47 | this.divEle.appendChild(this.btnEle);
48 | this.divEle.appendChild(this.imgEle);
49 | this.wrapEle.appendChild(this.divEle);
50 |
51 | this.divEle.addEventListener('click', (e: any) => {e.stopPropagation(); });
52 | this.wrapEle.addEventListener('click', this.closeModal.bind(this), false);
53 | this.btnEle.addEventListener('click', this.closeModal.bind(this), false);
54 | return this.wrapEle;
55 | }
56 |
57 | public closeModal (event: any) {
58 | this.divEle.className = 'pre-view-content view-fade-out';
59 | this.timer = setTimeout(() => {
60 | const wrapEle = document.getElementsByClassName('pre-view-wrap')[0];
61 | if (wrapEle) {
62 | document.body.removeChild(wrapEle);
63 | }
64 | }, 300);
65 | }
66 |
67 | //
68 | public ngOnDestroy () {
69 | clearTimeout(this.timer);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/components/upload-file/upload-file.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 | 正在上传...
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 图片大小不超过{{maxSize}}K
17 |
18 |
--------------------------------------------------------------------------------
/src/components/upload-file/upload-file.module.ts:
--------------------------------------------------------------------------------
1 | import { CommonModule } from '@angular/common';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule } from '@angular/forms';
4 | import { BrowserModule } from '@angular/platform-browser';
5 | import { UploadFileComponent } from './upload-file.component';
6 | import { PreViewDirective } from './upload-file.directvie';
7 |
8 | @NgModule({
9 | imports: [
10 | CommonModule,
11 | FormsModule,
12 | ],
13 | declarations: [
14 | UploadFileComponent,
15 | PreViewDirective,
16 | ],
17 | providers: [
18 | //
19 | ],
20 | exports: [
21 | UploadFileComponent,
22 | ],
23 | })
24 | export class UploadFileModule {}
25 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | // index.ts
2 |
3 | // import '@utils/tools'
4 | // import './polyfills.ts';
5 | // import './vendor.ts';
6 | import 'zone.js'
7 | import './app';
8 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | // Polyfills
2 | // import 'reflect-metadata';
3 | import 'core-js/es6/array';
4 | import 'core-js/es6/date';
5 | import 'core-js/es6/function';
6 | import 'core-js/es6/map';
7 | import 'core-js/es6/math';
8 | import 'core-js/es6/number';
9 | import 'core-js/es6/object';
10 | import 'core-js/es6/parse-float';
11 | import 'core-js/es6/parse-int';
12 | import 'core-js/es6/promise';
13 | import 'core-js/es6/reflect';
14 | import 'core-js/es6/regexp';
15 | import 'core-js/es6/set';
16 | import 'core-js/es6/string';
17 | import 'core-js/es6/symbol';
18 | import 'core-js/es6/typed';
19 | import 'core-js/es6/weak-map';
20 | import 'core-js/es6/weak-set';
21 | import 'core-js/es7/reflect';
22 | import 'zone.js/dist/zone';
23 |
24 | import 'rxjs/add/observable/of';
25 | import 'rxjs/add/operator/do';
26 | import 'rxjs/add/operator/finally';
27 | import 'rxjs/add/operator/map';
28 | import 'rxjs/add/operator/mergeMap';
29 |
--------------------------------------------------------------------------------
/src/styles/index.less:
--------------------------------------------------------------------------------
1 | @import './theme.less';
2 | @import './global.less';
--------------------------------------------------------------------------------
/src/styles/tailwind.css:
--------------------------------------------------------------------------------
1 | /* styles.css */
2 | @import 'tailwindcss/base';
3 | @import 'tailwindcss/components';
4 | @import 'tailwindcss/utilities';
--------------------------------------------------------------------------------
/src/styles/theme.less:
--------------------------------------------------------------------------------
1 | :global {
2 | --main-color: #8514f5;
3 | }
4 |
5 |
6 | @import "../../node_modules/ng-zorro-antd/ng-zorro-antd.less";
7 |
8 | // overwrite
9 | // @primary-color: var(--main-color);
--------------------------------------------------------------------------------
/src/template/index_base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | CMS-管理后台
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/types/custome.d.ts:
--------------------------------------------------------------------------------
1 | import { FormGroup, FormControl } from '@angular/forms'
2 |
3 | declare global {
4 |
5 | type FormFields = {
6 | [P in keyof T]: FormControl
7 | }
8 |
9 | type ValidateForm = FormGroup>
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/types/demo.ts:
--------------------------------------------------------------------------------
1 |
2 | export type APIForm = {
3 | email?: string
4 | url: string
5 | method: string
6 | params: string
7 | res: string
8 | }
--------------------------------------------------------------------------------
/src/types/global.d.ts:
--------------------------------------------------------------------------------
1 |
2 | interface Date {
3 | format: (s: string) => string
4 | }
5 |
6 | type AnyObject = Record
7 |
8 |
9 | declare const classes: Readonly>
10 |
11 | declare module '*.less' {
12 | export default classes
13 | }
14 |
15 | declare module '*.module.less' {
16 | export default classes
17 | }
18 |
--------------------------------------------------------------------------------
/src/types/login.ts:
--------------------------------------------------------------------------------
1 |
2 | interface LoginForm {
3 | username: string
4 | password: string
5 | remember: boolean
6 | }
7 |
--------------------------------------------------------------------------------
/src/utils/auth/auth-guard.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import {
3 | ActivatedRouteSnapshot,
4 | CanActivate,
5 | CanActivateChild,
6 | CanLoad,
7 | Route,
8 | Router,
9 | RouterStateSnapshot,
10 | } from '@angular/router';
11 | import { AuthService } from './auth.service';
12 |
13 | @Injectable()
14 | export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
15 | constructor (private authService: AuthService) {}
16 |
17 | public canActivate (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
18 | const url: string = state.url;
19 | return this.checkLogin(url);
20 | }
21 |
22 | public canActivateChild (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
23 | return this.canActivate(route, state);
24 | }
25 |
26 | public canLoad (route: Route): boolean {
27 | const url = `/${route.path}`;
28 | return this.checkLogin(url);
29 | }
30 |
31 | public checkLogin (url: string): boolean {
32 | return true;
33 | if (this.authService.isLogged) {
34 | return true;
35 | } else {
36 | console.log(url);
37 | this.authService.redirectUrl = url;
38 | location.href = 'login';
39 | return false;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/utils/auth/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 |
4 | @Injectable()
5 | export class AuthService {
6 | public store: Storage;
7 | public isLogged: boolean = false;
8 |
9 | constructor (private http: HttpClient) {
10 | this.store = localStorage;
11 | this.isLogged = this.store.getItem('ACCESS_TOKEN')
12 | && this.store.getItem('ACCESS_TOKEN').length == 64
13 | && this.store.getItem('USER_INFO') ? true : false;
14 | }
15 |
16 | get redirectUrl () {
17 | return sessionStorage.getItem('RedirectUrl') || '';
18 | }
19 |
20 | set redirectUrl (url: string) {
21 | sessionStorage.setItem('RedirectUrl', url);
22 | }
23 |
24 | public login (userInfo: object) {
25 | this.http.post('/login', userInfo).subscribe((res: any) => {
26 | this.isLogged = true;
27 | this.store.setItem('ACCESS_TOKEN', res.msg);
28 | this.store.setItem('USER_INFO', JSON.stringify(res.data));
29 | location.href = !!this.redirectUrl ? this.redirectUrl : '/dashboard';
30 | }, (err: any) => { });
31 | }
32 |
33 | public logout (): void {
34 | this.http.post('/logout', {}).subscribe((res: any) => {
35 | this.isLogged = false;
36 | this.store.clear();
37 | sessionStorage.clear();
38 | setTimeout(() => {
39 | location.href = 'login';
40 | }, 1000);
41 | }, (err: any) => { });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/utils/echarts/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * echarts
3 | */
4 | // const Echarts = require('echarts/lib/echarts');
5 | import * as Echarts from 'echarts/core'
6 | import { VisualMapComponentOption, TitleComponentOption } from 'echarts/components'
7 | import {
8 | TitleComponent,
9 | TooltipComponent,
10 | ToolboxComponent,
11 | LegendComponent,
12 | LegendScrollComponent,
13 | VisualMapComponent,
14 | } from 'echarts/components'
15 | import { CanvasRenderer } from 'echarts/renderers'
16 |
17 | Echarts.use([
18 | CanvasRenderer,
19 | TitleComponent,
20 | TooltipComponent,
21 | ToolboxComponent,
22 | LegendComponent,
23 | LegendScrollComponent,
24 | VisualMapComponent,
25 | ])
26 |
27 | export {
28 | Echarts,
29 | };
30 |
--------------------------------------------------------------------------------
/src/utils/funs.ts:
--------------------------------------------------------------------------------
1 |
2 | export const storage = {
3 | get: (key: string): string => {
4 | const value = localStorage.getItem(key)
5 | return value || ''
6 | },
7 |
8 | set: (key: string, value: string) => {
9 | if (value !== null && value !== undefined) {
10 | localStorage.setItem(key, value)
11 | }
12 | },
13 |
14 | remove: (key: string): void => {
15 | localStorage.removeItem(key)
16 | },
17 |
18 | clear(exclude = false) {
19 | if(exclude) {
20 | } else {
21 | localStorage.clear()
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/utils/httpInterceptor/helper.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
2 | import { Injectable } from '@angular/core';
3 | import { storage } from '@utils/funs';
4 | import { NzNotificationService } from 'ng-zorro-antd/notification';
5 |
6 | @Injectable()
7 | export class HelperService {
8 | public store: any;
9 | public seStore: any;
10 |
11 | constructor (private notification: NzNotificationService) {
12 | this.store = localStorage;
13 | this.seStore = sessionStorage;
14 | }
15 |
16 | public successHelper (res: HttpResponse): void {
17 | switch (res.status) {
18 | case 201:
19 | const arr = res.url.split('/api');
20 | if (arr[arr.length - 1] === '/login') {
21 | this.notification.success('成功', '登陆成功');
22 | } else if (arr[arr.length - 1] === '/upload-file') {
23 | this.notification.success('成功', '文件上传成功');
24 | } else {
25 | this.notification.success('成功', '操作成功');
26 | }
27 | break;
28 | default:
29 | //
30 | break;
31 | }
32 | }
33 |
34 | public errorHelper (err: HttpErrorResponse): void {
35 | switch (err.status) {
36 | case 400:
37 | const arr = err.url.split('/api');
38 | if (arr[arr.length - 1] === '/login') {
39 | this.notification.error('错误', '用户名或密码错误');
40 | } else if (arr[arr.length - 1] === '/upload-file') {
41 | this.notification.error('失败', '文件上传失败');
42 | } else {
43 | this.notification.error('请求错误', err.error.msg || err.error.data);
44 | }
45 | break;
46 | case 401:
47 | storage.clear();
48 | this.notification.error('未授权', '请重新登录');
49 | sessionStorage.setItem('RedirectUrl', location.pathname);
50 | setTimeout(() => {
51 | location.href = 'login';
52 | }, 1000);
53 | break;
54 | case 403:
55 | this.notification.error('错误', '禁止访问');
56 | break;
57 | case 404:
58 | this.notification.error('未找到', '未找到资源,请检查');
59 | break;
60 | case 405:
61 | this.notification.error('错误', '此方法不允许');
62 | break;
63 | case 406:
64 | this.notification.error('错误', '此方法不接受,请检查');
65 | break;
66 | case 406:
67 | this.notification.error('错误', '此方法不接受,请检查');
68 | break;
69 | case 500:
70 | this.notification.error('错误', err.error.msg || err.error.data);
71 | break;
72 | case 503:
73 | this.notification.error('连接被拒绝', '服务不可用');
74 | break;
75 | case 504:
76 | this.notification.error('网关超时', '请与运维小郭联系');
77 | break;
78 | default:
79 | this.notification.error('错误', '服务端未知错误');
80 | break;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/utils/httpInterceptor/httpInterceptor.service.ts:
--------------------------------------------------------------------------------
1 | import {
2 | HttpErrorResponse,
3 | HttpEvent,
4 | HttpHandler,
5 | HttpInterceptor,
6 | HttpRequest,
7 | HttpResponse,
8 | } from '@angular/common/http';
9 | import { Injectable } from '@angular/core';
10 | import { Observable, finalize } from 'rxjs';
11 | import { HelperService } from './helper.service';
12 |
13 | @Injectable()
14 | export class HttpClientInterceptor implements HttpInterceptor {
15 | public baseUrl: string = '/api';
16 | public store: any;
17 |
18 | constructor (private helper: HelperService) {
19 | this.store = localStorage;
20 | }
21 |
22 | public intercept (req: HttpRequest, next: HttpHandler): Observable> {
23 | const isHttpEntry = /^http/.test(req.url)
24 | const url = `${isHttpEntry ? '' : this.baseUrl}${req.url}`
25 | const request = req.clone({
26 | url,
27 | setHeaders: {
28 | 'X-Requested-With': 'XMLHttpRequest',
29 | 'Authorization-User': this.store.getItem('ACCESS_TOKEN') || 'no_token',
30 | },
31 | // withCredentials: true, // same origin not use
32 | });
33 | return next.handle(request).pipe((res) => {
34 | if (res instanceof HttpResponse) {
35 | this.helper.successHelper(res);
36 | }
37 | return res;
38 | }, (err) => {
39 | if (err instanceof HttpErrorResponse) {
40 | this.helper.errorHelper(err);
41 | }
42 | return err;
43 | }, finalize(() => {
44 | //
45 | }));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/utils/httpInterceptor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './httpInterceptor.service';
2 |
--------------------------------------------------------------------------------
/src/utils/params.service.ts:
--------------------------------------------------------------------------------
1 |
2 | export class Params {
3 | constructor () {}
4 |
5 | public format (data: any) {
6 | const arr = [];
7 | for (const i in data) {
8 | if (data[i] !== undefined && data[i] !== '' && data[i] !== null) {
9 | const s = encodeURIComponent(i) + '=' + encodeURIComponent(data[i]);
10 | arr.push(s);
11 | }
12 | }
13 | arr.push('_=' + Date.now());
14 | return arr.join('&');
15 | }
16 |
17 | public fmtpages (data: any) {
18 | const arr: any = [];
19 | let n: number = 0;
20 | if (data !== null && typeof data === 'object') {
21 | for (const i in data) {
22 | if (typeof data[i] !== 'object') {
23 | if (data[i] !== undefined && data[i] !== '' && data[i] !== null) {
24 | const s = encodeURIComponent(i) + '=' + encodeURIComponent(data[i]);
25 | arr.push(s);
26 | }
27 | } else {
28 | if (data[i].val !== undefined && data[i].val !== '' && data[i].val !== null) {
29 | const num = n++;
30 | arr.push(encodeURIComponent('colFilter[' + num + '][col]') + '=' + i);
31 | arr.push(encodeURIComponent('colFilter[' + num + '][exp]') + '=' + encodeURIComponent(data[i].exp ? data[i].exp : '='));
32 | arr.push(encodeURIComponent('colFilter[' + num + '][val]') + '=' + encodeURIComponent(data[i].val));
33 | }
34 | }
35 | }
36 | }
37 | arr.push('_=' + Date.now());
38 | return arr.join('&');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/utils/tools.ts:
--------------------------------------------------------------------------------
1 |
2 | const prototypeFun = () => {
3 | Date.prototype['format'] = function format(fmt: string) {
4 | if(Object.prototype.toString.call(this) !== '[object Date]') {
5 | throw new Error('this caller must be a Date type.')
6 | }
7 | if(!fmt) fmt = 'YYYY-MM-DD HH:mm:ss:SSS'
8 | let d: Date = this
9 | let o = {
10 | 'Y+': d.getFullYear(),
11 | 'M+': (d.getMonth() + 1),
12 | 'D+': d.getDate(),
13 | 'H+': d.getHours(),
14 | 'm+': d.getMinutes(),
15 | 's+': d.getSeconds(),
16 | 'S+': d.getMilliseconds()
17 | }
18 | for(let k in o) {
19 | let matched = fmt.match(k)
20 | let _k = matched ? matched[0] : null
21 | const v = o[k as keyof typeof o]
22 | fmt = fmt.replace(_k, (`${v > 9 ? v : '0'}${v}`))
23 | }
24 | return fmt
25 | }
26 | }
27 |
28 | export default prototypeFun()
--------------------------------------------------------------------------------
/src/vendor.ts:
--------------------------------------------------------------------------------
1 | // Angular
2 | import '@angular/core';
3 | import '@angular/common';
4 | import '@angular/animations';
5 | import '@angular/forms';
6 | import '@angular/http';
7 | import '@angular/platform-browser';
8 | import '@angular/platform-browser-dynamic';
9 | import '@angular/router';
10 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xpioneer/angular-typescript/d4daa8f288fc0fa9abfe9fd6531f55904687c56e/static/favicon.ico
--------------------------------------------------------------------------------
/static/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Angular",
3 | "icons": [
4 | {
5 | "src": "logo.svg",
6 | "sizes": "192x192",
7 | "type": "image/svg"
8 | }
9 | ],
10 | "theme_color": "#ffffff",
11 | "background_color": "#ffffff",
12 | "start_url": "/Angular-PWA/",
13 | "display": "standalone"
14 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | // tailwind.config.js
2 | module.exports = {
3 | mode: 'jit',
4 | // purge: ['./src/**/*.{html,js}'], // 用于清除未使用的 CSS
5 | content: [
6 | // './src/**/*.{html,js,ts,tsx}',
7 | './src/**/*.html'
8 | ],
9 | darkMode: false, // 可以设置为 'media' 或 'class' 来启用暗模式
10 | theme: {
11 | extend: {},
12 | },
13 | variants: {
14 | extend: {},
15 | },
16 | plugins: [],
17 | };
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "moduleResolution": "node",
6 | "sourceMap": false,
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "removeComments": false,
10 | "noImplicitAny": true,
11 | "lib": [ "es2015", "dom" ],
12 | "baseUrl": "./src",
13 | "paths": {
14 | "@/*": ["*"],
15 | "@app/*": ["app/*"],
16 | "@assets/*": ["assets/*"],
17 | "@components/*": ["components/*"],
18 | "@utils/*": ["utils/*"]
19 | }
20 | },
21 | "compileOnSave": true,
22 | "exclude": [
23 | "node_modules"
24 | ]
25 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rulesDirectory": ["src/"],
4 | "rules": {
5 | "forin": false,
6 | "no-empty": false,
7 | "variable-name": false,
8 | "import-spacing": false,
9 | "ordered-imports": false,
10 | "max-line-length": false,
11 | "object-literal-sort-keys": false,
12 | "quotemark": [true, "single", "avoid-escape"],
13 | "no-console": false,
14 | "member-ordering": false,
15 | "max-classes-per-file": [false, 1],
16 | "indent": [true, "spaces", 2],
17 | "curly": false,
18 | "space-before-function-paren": [true, "always"],
19 | "one-variable-per-declaration": false,
20 | "no-var-requires": false,
21 | "no-shadowed-variable": false,
22 | "no-irregular-whitespace": false,
23 | "object-literal-key-quotes": false,
24 | "whitespace": [
25 | true,
26 | "check-branch",
27 | "check-decl",
28 | "check-operator",
29 | "check-module",
30 | "check-separator",
31 | "check-rest-spread",
32 | "check-typecast",
33 | "check-type",
34 | "check-type-operator",
35 | "check-preblock"
36 | ],
37 | "triple-equals": false,
38 | "eofline": true,
39 | "interface-name": [true, "always-prefix"],
40 | "semicolon": [true, "always", "ignore-interfaces", "ignore-bound-class-methods"]
41 | }
42 | }
--------------------------------------------------------------------------------