Compare commits

..

211 Commits

Author SHA1 Message Date
dependabot[bot]
467394e255 chore(deps): bump @angular/compiler from 14.2.12 to 15.2.0
Bumps [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) from 14.2.12 to 15.2.0.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/15.2.0/packages/compiler)

---
updated-dependencies:
- dependency-name: "@angular/compiler"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-01 07:03:03 +00:00
dependabot[bot]
ba80d7bffa chore(deps-dev): bump typescript from 4.1.6 to 4.9.3
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.1.6 to 4.9.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.1.6...v4.9.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:15:55 +08:00
dependabot[bot]
5fe04e2490 chore(deps-dev): bump karma-jasmine from 4.0.2 to 5.1.0
Bumps [karma-jasmine](https://github.com/karma-runner/karma-jasmine) from 4.0.2 to 5.1.0.
- [Release notes](https://github.com/karma-runner/karma-jasmine/releases)
- [Changelog](https://github.com/karma-runner/karma-jasmine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma-jasmine/compare/v4.0.2...v5.1.0)

---
updated-dependencies:
- dependency-name: karma-jasmine
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:11:48 +08:00
dependabot[bot]
77c0a5981f chore(deps-dev): bump eslint-plugin-import from 2.25.2 to 2.26.0
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.25.2 to 2.26.0.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.25.2...v2.26.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:10:12 +08:00
dependabot[bot]
4abd43fef0 chore(deps): bump zone.js from 0.11.8 to 0.12.0
Bumps [zone.js](https://github.com/angular/angular/tree/HEAD/packages/zone.js) from 0.11.8 to 0.12.0.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/packages/zone.js/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/zone.js-0.12.0/packages/zone.js)

---
updated-dependencies:
- dependency-name: zone.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:09:57 +08:00
dependabot[bot]
45acb1e697 chore(deps-dev): bump @types/jasmine from 3.10.6 to 4.3.0
Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.10.6 to 4.3.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine)

---
updated-dependencies:
- dependency-name: "@types/jasmine"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:09:44 +08:00
dependabot[bot]
7bca7a0ade chore(deps-dev): bump @types/node from 16.18.4 to 18.11.10
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 16.18.4 to 18.11.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:09:24 +08:00
dependabot[bot]
9515e6cc27 chore(deps): bump rxjs from 6.6.7 to 7.5.7
Bumps [rxjs](https://github.com/reactivex/rxjs) from 6.6.7 to 7.5.7.
- [Release notes](https://github.com/reactivex/rxjs/releases)
- [Changelog](https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reactivex/rxjs/compare/6.6.7...7.5.7)

---
updated-dependencies:
- dependency-name: rxjs
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:08:16 +08:00
e3778e3dd3 ci: update config 2022-12-02 01:01:48 +08:00
95c4178a86 chore: remove build:prod 2022-12-02 00:57:07 +08:00
72d16a1996 chore: disable @angular-eslint/template/eqeqeq lint 2022-12-02 00:48:28 +08:00
3dc44b8a34 ci: update yml config 2022-12-02 00:38:32 +08:00
28f798df9d fix error 2022-12-02 00:33:54 +08:00
e770b2a7cf update 2022-12-02 00:01:47 +08:00
516874e9d5 update 2022-12-01 23:55:59 +08:00
7cba060b9f update to 14 2022-12-01 23:50:05 +08:00
548a2014d9 update to 13 2022-12-01 23:42:04 +08:00
716b7ced8b ng update @angular/core@12 @angular/cli@12 2022-12-01 22:54:02 +08:00
c4676fe232 ng update 2022-12-01 22:34:40 +08:00
dependabot[bot]
af1d07f25b chore(deps-dev): bump jasmine-core from 3.99.1 to 4.5.0
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 3.99.1 to 4.5.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v3.99.1...v4.5.0)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-01 22:22:14 +08:00
dependabot[bot]
d689b9a6ef chore(deps-dev): bump eslint-plugin-import from 2.23.4 to 2.26.0
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.23.4 to 2.26.0.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.23.4...v2.26.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-01 22:22:02 +08:00
dependabot[bot]
186ed62d18 chore(deps-dev): bump @angular-eslint/template-parser
Bumps [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) from 13.0.1 to 15.1.0.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/main/packages/template-parser/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v15.1.0/packages/template-parser)

---
updated-dependencies:
- dependency-name: "@angular-eslint/template-parser"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-01 22:21:39 +08:00
da5900b45a fix: 工信部链接 2022-04-27 21:41:52 +08:00
dependabot[bot]
323bc86df1 chore(deps-dev): bump @angular-eslint/eslint-plugin
Bumps [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) from 12.6.1 to 13.1.0.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v13.1.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-20 15:38:16 +08:00
dependabot[bot]
0136ee4603 chore(deps-dev): bump @angular-eslint/schematics from 12.2.0 to 13.1.0
Bumps [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) from 12.2.0 to 13.1.0.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/schematics/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v13.1.0/packages/schematics)

---
updated-dependencies:
- dependency-name: "@angular-eslint/schematics"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-20 15:38:04 +08:00
dependabot[bot]
35bde50c55 chore(deps-dev): bump ts-node from 9.1.1 to 10.5.0
Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 9.1.1 to 10.5.0.
- [Release notes](https://github.com/TypeStrong/ts-node/releases)
- [Commits](https://github.com/TypeStrong/ts-node/compare/v9.1.1...v10.5.0)

---
updated-dependencies:
- dependency-name: ts-node
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-19 23:31:42 +08:00
dependabot[bot]
d9fa76e9e2 chore(deps-dev): bump @angular-eslint/builder from 12.2.0 to 13.0.1
Bumps [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) from 12.2.0 to 13.0.1.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/builder/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v13.0.1/packages/builder)

---
updated-dependencies:
- dependency-name: "@angular-eslint/builder"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-19 23:25:15 +08:00
dependabot[bot]
28c03b962e chore(deps-dev): bump @angular-eslint/template-parser
Bumps [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser) from 1.2.0 to 13.0.1.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/template-parser/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v13.0.1/packages/template-parser)

---
updated-dependencies:
- dependency-name: "@angular-eslint/template-parser"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-19 23:25:01 +08:00
dependabot[bot]
ae94a50a3e chore(deps-dev): bump @angular/language-service from 11.2.14 to 13.2.0
Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.2.14 to 13.2.0.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/docs/RELEASE_SCHEDULE.md)
- [Commits](https://github.com/angular/angular/commits/13.2.0/packages/language-service)

---
updated-dependencies:
- dependency-name: "@angular/language-service"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-19 23:24:47 +08:00
dependabot[bot]
840d827c80 chore(deps-dev): bump @types/node from 14.17.32 to 16.11.6 (#167) 2021-11-01 17:20:54 +00:00
dependabot[bot]
a909fd650c chore(deps-dev): bump @angular-eslint/eslint-plugin from 1.2.0 to 12.6.1
Bumps [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin) from 1.2.0 to 12.6.1.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v12.6.1/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@angular-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-01 12:09:40 -05:00
禾几海
3a0008650e Delete codeql-analysis.yml 2021-11-02 01:08:00 +08:00
dependabot[bot]
6468d0d8d4 chore(deps-dev): bump eslint-plugin-jsdoc from 35.1.2 to 35.4.1
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 35.1.2 to 35.4.1.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v35.1.2...v35.4.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-19 11:25:32 +08:00
dependabot[bot]
969fda50f7 chore(deps-dev): bump @angular-eslint/schematics from 1.2.0 to 12.2.0
Bumps [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics) from 1.2.0 to 12.2.0.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/schematics/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v12.2.0/packages/schematics)

---
updated-dependencies:
- dependency-name: "@angular-eslint/schematics"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-26 21:30:52 +08:00
dependabot[bot]
89d7c98c21 chore(deps-dev): bump @angular-eslint/builder from 2.0.2 to 12.2.0
Bumps [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) from 2.0.2 to 12.2.0.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/builder/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v12.2.0/packages/builder)

---
updated-dependencies:
- dependency-name: "@angular-eslint/builder"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-26 21:10:16 +08:00
dependabot[bot]
1ddb7c093f chore(deps-dev): bump eslint-plugin-import from 2.22.1 to 2.23.4
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.22.1 to 2.23.4.
- [Release notes](https://github.com/benmosher/eslint-plugin-import/releases)
- [Changelog](https://github.com/benmosher/eslint-plugin-import/blob/master/CHANGELOG.md)
- [Commits](https://github.com/benmosher/eslint-plugin-import/compare/v2.22.1...v2.23.4)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-26 21:09:52 +08:00
dependabot[bot]
307e0aefa4 chore(deps-dev): bump jasmine-spec-reporter from 6.0.0 to 7.0.0
Bumps [jasmine-spec-reporter](https://github.com/bcaudan/jasmine-spec-reporter) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/bcaudan/jasmine-spec-reporter/releases)
- [Changelog](https://github.com/bcaudan/jasmine-spec-reporter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcaudan/jasmine-spec-reporter/compare/v6.0.0...v7.0.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-26 09:19:08 +08:00
dependabot[bot]
be312f4d80 chore(deps-dev): bump eslint-plugin-jsdoc from 32.2.0 to 35.1.2
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 32.2.0 to 35.1.2.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v32.2.0...v35.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-26 09:17:30 +08:00
dependabot[bot]
4bcc35b0b9 chore(deps-dev): bump @typescript-eslint/parser from 4.17.0 to 4.26.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.17.0 to 4.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.26.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-26 09:16:41 +08:00
禾几海
2e7e835861 Merge pull request #94 from xiaohai2271/dependabot/npm_and_yarn/angular-eslint/eslint-plugin-template-2.0.2
chore(deps-dev): bump @angular-eslint/eslint-plugin-template from 1.2.0 to 2.0.2
2021-04-01 14:03:16 +08:00
禾几海
60a1ed9163 Merge pull request #93 from xiaohai2271/dependabot/npm_and_yarn/angular-eslint/builder-2.0.2
chore(deps-dev): bump @angular-eslint/builder from 1.2.0 to 2.0.2
2021-04-01 14:02:55 +08:00
dependabot[bot]
6b62c76064 chore(deps-dev): bump @angular-eslint/eslint-plugin-template
Bumps [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template) from 1.2.0 to 2.0.2.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/eslint-plugin-template/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v2.0.2/packages/eslint-plugin-template)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-01 05:31:11 +00:00
dependabot[bot]
3915663838 chore(deps-dev): bump @angular-eslint/builder from 1.2.0 to 2.0.2
Bumps [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder) from 1.2.0 to 2.0.2.
- [Release notes](https://github.com/angular-eslint/angular-eslint/releases)
- [Changelog](https://github.com/angular-eslint/angular-eslint/blob/master/packages/builder/CHANGELOG.md)
- [Commits](https://github.com/angular-eslint/angular-eslint/commits/v2.0.2/packages/builder)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-01 05:29:29 +00:00
禾几海
2532f8894e fix: 使用base64解密的异常 2021-03-16 21:39:56 +08:00
禾几海
defb5042ef feat: 使用base64加密localStorage信息 2021-03-16 21:15:45 +08:00
禾几海
2ba3d4ca1b refactor: 用LocalStorageService代理localStorage 2021-03-16 21:15:45 +08:00
禾几海
a2e80e6fdd refactor: 规范请求头的token 2021-03-16 21:15:45 +08:00
禾几海
5e29f42115 ci: Sync repository to gitee 2021-03-15 22:21:24 +08:00
禾几海
7c08892bac Merge pull request #88 from xiaohai2271/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-4.17.0
chore(deps-dev): bump @typescript-eslint/eslint-plugin from 4.3.0 to 4.17.0
2021-03-13 11:43:18 +08:00
禾几海
080338a824 Merge pull request #90 from xiaohai2271/dependabot/npm_and_yarn/eslint-plugin-prefer-arrow-1.2.3
chore(deps-dev): bump eslint-plugin-prefer-arrow from 1.2.2 to 1.2.3
2021-03-13 11:42:38 +08:00
dependabot[bot]
b88132fe60 chore(deps-dev): bump @typescript-eslint/eslint-plugin
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.3.0 to 4.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.17.0/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-13 03:17:13 +00:00
dependabot[bot]
5484e058d7 chore(deps-dev): bump eslint-plugin-prefer-arrow from 1.2.2 to 1.2.3
Bumps [eslint-plugin-prefer-arrow](https://github.com/TristonJ/eslint-plugin-prefer-arrow) from 1.2.2 to 1.2.3.
- [Release notes](https://github.com/TristonJ/eslint-plugin-prefer-arrow/releases)
- [Commits](https://github.com/TristonJ/eslint-plugin-prefer-arrow/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-13 03:16:55 +00:00
禾几海
5d7852c54f Merge pull request #91 from xiaohai2271/dependabot/npm_and_yarn/typescript-eslint/parser-4.17.0
chore(deps-dev): bump @typescript-eslint/parser from 4.3.0 to 4.17.0
2021-03-13 11:16:04 +08:00
禾几海
00e10091f3 Merge pull request #92 from xiaohai2271/dependabot/npm_and_yarn/eslint-plugin-jsdoc-32.2.0
chore(deps-dev): bump eslint-plugin-jsdoc from 30.7.6 to 32.2.0
2021-03-13 11:15:41 +08:00
dependabot[bot]
78cd04a88d chore(deps-dev): bump eslint-plugin-jsdoc from 30.7.6 to 32.2.0
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 30.7.6 to 32.2.0.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v30.7.6...v32.2.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-12 16:38:02 +00:00
dependabot[bot]
b61b56795e chore(deps-dev): bump @typescript-eslint/parser from 4.3.0 to 4.17.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.3.0 to 4.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.17.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-12 16:34:14 +00:00
禾几海
6d3abed910 Merge pull request #85 from xiaohai2271/dependabot/npm_and_yarn/karma-6.2.0
chore(deps-dev): bump karma from 5.2.3 to 6.2.0
2021-03-12 19:53:58 +08:00
dependabot[bot]
b55c03cbd5 chore(deps-dev): bump karma from 5.2.3 to 6.2.0
Bumps [karma](https://github.com/karma-runner/karma) from 5.2.3 to 6.2.0.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v5.2.3...v6.2.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-12 11:37:15 +00:00
禾几海
06d203b65f Merge pull request #86 from xiaohai2271/feature-tslint2eslint
Convert tslint to eslint
2021-03-12 18:00:05 +08:00
禾几海
754193d6ab chore: fix bug 2021-03-12 17:55:00 +08:00
禾几海
03cf88868e chore: Clean up eslint configuration files 2021-03-12 17:40:09 +08:00
禾几海
7f4e4568e5 style: update eslint of ban-types 2021-03-12 17:38:19 +08:00
禾几海
6bfb42e43d style: eslint of naming-convention 2021-03-12 17:30:05 +08:00
禾几海
7ea7f83227 style: eslint of member-ordering 2021-03-12 16:48:27 +08:00
禾几海
2037c95ffd chore(deps-dev): remove tslint dependences 2021-03-12 16:16:23 +08:00
禾几海
33d7bbaf43 style: eslint fix 2021-03-12 16:11:09 +08:00
禾几海
b65b25c1fa chore: ignore some code rules 2021-03-12 16:10:07 +08:00
禾几海
c13a7844a6 chore: convert tslint to eslint 2021-03-12 16:00:56 +08:00
禾几海
da30c3c51b chore(CodeQL): remove the unnecessary step 2021-03-12 15:25:55 +08:00
dependabot[bot]
33cc2ae8ec Merge pull request #82 from xiaohai2271/dependabot/npm_and_yarn/ng-zorro-antd-11.2.0 2021-03-11 16:19:23 +00:00
dependabot[bot]
51159a49b7 chore(deps): bump ng-zorro-antd from 10.1.2 to 11.2.0
Bumps [ng-zorro-antd](https://github.com/NG-ZORRO/ng-zorro-antd) from 10.1.2 to 11.2.0.
- [Release notes](https://github.com/NG-ZORRO/ng-zorro-antd/releases)
- [Changelog](https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NG-ZORRO/ng-zorro-antd/compare/10.1.2...11.2.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-11 16:12:16 +00:00
禾几海
dc6bf57587 chore(deps): 依赖超前的问题 2021-03-12 00:10:17 +08:00
禾几海
ea83364c12 fix(common-table): common-table 在移动设备上部分内容不显示 2021-03-11 21:00:10 +08:00
禾几海
1c5423ebb2 chore(deps): delete package-lock.json file
[skip ci]
2021-03-11 20:42:29 +08:00
禾几海
02718d23db fix(common-table): 修复table组件无法切换页面 2021-03-11 20:33:06 +08:00
禾几海
288eb358a3 chore(deps): ignore file package-lock.json
[skip ci]
2021-03-11 20:33:06 +08:00
禾几海
6e5282daef Merge pull request #74 from xiaohai2271/dependabot/npm_and_yarn/angular/cli-11.1.2
chore(deps-dev): bump @angular/cli from 11.0.5 to 11.1.2
2021-02-28 22:26:26 +08:00
dependabot[bot]
8e93e84634 chore(deps-dev): bump @angular/cli from 11.0.5 to 11.1.2
Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.0.5 to 11.1.2.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.0.5...v11.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-01 05:43:48 +00:00
禾几海
4596bbe1d2 Merge pull request #64 from xiaohai2271/dependabot/npm_and_yarn/angular/cli-11.0.5
chore(deps-dev): bump @angular/cli from 11.0.2 to 11.0.5
2021-01-20 22:13:16 +08:00
dependabot[bot]
08e98c5a69 chore(deps-dev): bump @angular/cli from 11.0.2 to 11.0.5
Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.0.2 to 11.0.5.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v11.0.2...v11.0.5)

Signed-off-by: dependabot[bot] <support@github.com>
2021-01-01 05:46:40 +00:00
禾几海
5cf648da67 Merge pull request #54 from xiaohai2271/dependabot/npm_and_yarn/zone.js-0.11.3
chore(deps): bump zone.js from 0.11.2 to 0.11.3
2020-12-02 10:59:49 +08:00
禾几海
7eac8dbdde Merge pull request #56 from xiaohai2271/dependabot/npm_and_yarn/types/node-14.14.10
chore(deps-dev): bump @types/node from 14.14.6 to 14.14.10
2020-12-02 10:56:40 +08:00
禾几海
cbf688fb6c Merge pull request #57 from xiaohai2271/dependabot/npm_and_yarn/types/jasmine-3.6.2
chore(deps-dev): bump @types/jasmine from 3.6.0 to 3.6.2
2020-12-02 10:56:06 +08:00
dependabot[bot]
4d9acbe51b chore(deps-dev): bump @types/jasmine from 3.6.0 to 3.6.2
Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-01 05:45:32 +00:00
dependabot[bot]
19a49f2c69 chore(deps-dev): bump @types/node from 14.14.6 to 14.14.10
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.6 to 14.14.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-01 05:44:08 +00:00
dependabot[bot]
5941fb41e9 chore(deps): bump zone.js from 0.11.2 to 0.11.3
Bumps [zone.js](https://github.com/angular/angular/tree/HEAD/packages/zone.js) from 0.11.2 to 0.11.3.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/zone.js-0.11.3/packages/zone.js)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-01 05:40:19 +00:00
禾几海
6a5f1fdefd fix: 无法发布文章的bug 2020-11-29 00:52:36 +08:00
禾几海
68b380906a style: format project
[skip ci]
2020-11-22 22:00:09 +08:00
dependabot[bot]
ad3759afb3 Merge pull request #53 from xiaohai2271/dependabot/npm_and_yarn/ng-zorro-antd-10.1.2 2020-11-22 11:58:10 +00:00
禾几海
a45e558662 fix: 更新依赖导致的错误异常 2020-11-22 19:53:11 +08:00
dependabot[bot]
6d9aa66536 chore(deps): bump ng-zorro-antd from 9.3.0 to 10.1.2
Bumps [ng-zorro-antd](https://github.com/NG-ZORRO/ng-zorro-antd) from 9.3.0 to 10.1.2.
- [Release notes](https://github.com/NG-ZORRO/ng-zorro-antd/releases)
- [Changelog](https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NG-ZORRO/ng-zorro-antd/compare/9.3.0...10.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-22 08:47:52 +00:00
禾几海
27fc65b759 chore(deps): update dependency
[skip ci]
2020-11-22 16:43:49 +08:00
禾几海
75b56c604a Merge branch 'master' of https://github.com/xiaohai2271/blog-frontEnd 2020-11-22 16:27:48 +08:00
禾几海
4b1b44a125 Merge pull request #51 from xiaohai2271/dependabot/npm_and_yarn/types/node-14.14.6
chore(deps-dev): bump @types/node from 14.14.3 to 14.14.6
2020-11-22 16:25:33 +08:00
禾几海
53fb39678a Merge pull request #51 from xiaohai2271/dependabot/npm_and_yarn/types/node-14.14.6
chore(deps-dev): bump @types/node from 14.14.3 to 14.14.6
2020-11-22 15:55:26 +08:00
禾几海
a5ae7b8465 ci: skip ci action situation
[skip ci]
2020-11-14 21:39:42 +08:00
禾几海
39a8c33be4 ci: skip ci action situation
[skip ci]
2020-11-14 21:35:14 +08:00
dependabot[bot]
274fdf0fad chore(deps-dev): bump @types/node from 14.14.3 to 14.14.6
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.3 to 14.14.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-02 07:51:01 +00:00
dependabot[bot]
19fd3e55f7 Merge pull request #50 from xiaohai2271/dependabot/npm_and_yarn/angular/language-service-10.2.1 2020-11-02 07:17:02 +00:00
dependabot[bot]
5c274705b0 chore(deps-dev): bump @angular/language-service from 10.2.0 to 10.2.1
Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 10.2.0 to 10.2.1.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/10.2.1/packages/language-service)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-02 07:09:38 +00:00
dependabot[bot]
e0d6943c96 Merge pull request #49 from xiaohai2271/dependabot/npm_and_yarn/typescript-4.0.5 2020-11-02 07:08:17 +00:00
dependabot[bot]
a96313867e Merge pull request #48 from xiaohai2271/dependabot/npm_and_yarn/vditor-3.6.0 2020-11-02 07:04:00 +00:00
禾几海
ae86991fe8 Update dependabot.yml 2020-11-02 15:03:54 +08:00
dependabot[bot]
3d0c806fd2 chore(deps-dev): bump typescript from 4.0.3 to 4.0.5
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.3 to 4.0.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.3...v4.0.5)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-02 07:00:08 +00:00
dependabot[bot]
2997fed054 chore(deps): bump vditor from 3.5.5 to 3.6.0
Bumps [vditor](https://github.com/Vanessa219/vditor) from 3.5.5 to 3.6.0.
- [Release notes](https://github.com/Vanessa219/vditor/releases)
- [Changelog](https://github.com/Vanessa219/vditor/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Vanessa219/vditor/compare/v3.5.5...v3.6.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-11-02 06:56:23 +00:00
禾几海
beb0d27532 Merge pull request #43 from xiaohai2271/dependabot/npm_and_yarn/angular-devkit/build-angular-0.1002.0
chore(deps-dev): bump @angular-devkit/build-angular from 0.1001.7 to 0.1002.0
2020-10-27 22:56:16 +08:00
dependabot[bot]
f05a0cf2b3 chore(deps-dev): bump @angular-devkit/build-angular
Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1001.7 to 0.1002.0.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-26 14:45:58 +00:00
禾几海
8917e2fe5a Merge pull request #44 from xiaohai2271/dependabot/npm_and_yarn/types/node-14.14.3
chore(deps-dev): bump @types/node from 14.14.0 to 14.14.3
2020-10-26 22:43:39 +08:00
禾几海
8c8cd95c96 Merge pull request #45 from xiaohai2271/dependabot/npm_and_yarn/angular/language-service-10.2.0
chore(deps-dev): bump @angular/language-service from 10.1.6 to 10.2.0
2020-10-26 22:42:26 +08:00
dependabot[bot]
4472c4bcdc chore(deps-dev): bump @types/node from 14.14.0 to 14.14.3
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.0 to 14.14.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-26 11:20:49 +00:00
dependabot[bot]
6d0fc77ec1 chore(deps-dev): bump @angular/language-service from 10.1.6 to 10.2.0
Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 10.1.6 to 10.2.0.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/10.2.0/packages/language-service)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-26 11:20:12 +00:00
禾几海
845972df71 Merge pull request #46 from xiaohai2271/dependabot/npm_and_yarn/types/jasmine-3.6.0
chore(deps-dev): bump @types/jasmine from 3.5.14 to 3.6.0
2020-10-26 19:18:55 +08:00
禾几海
ca9fcddd31 Merge pull request #47 from xiaohai2271/dependabot/npm_and_yarn/angular/cli-10.2.0
chore(deps-dev): bump @angular/cli from 10.1.7 to 10.2.0
2020-10-26 19:18:27 +08:00
dependabot[bot]
425e75cccf chore(deps-dev): bump @angular/cli from 10.1.7 to 10.2.0
Bumps [@angular/cli](https://github.com/angular/angular-cli) from 10.1.7 to 10.2.0.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v10.1.7...v10.2.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-26 06:45:18 +00:00
dependabot[bot]
2fefcb1ce7 chore(deps-dev): bump @types/jasmine from 3.5.14 to 3.6.0
Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.5.14 to 3.6.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-26 06:43:17 +00:00
dependabot[bot]
12a7db276d Merge pull request #42 from xiaohai2271/dependabot/npm_and_yarn/types/node-14.14.0 2020-10-20 15:04:06 +00:00
dependabot[bot]
93b9e7e6eb chore(deps-dev): bump @types/node from 14.11.10 to 14.14.0
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.11.10 to 14.14.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-20 14:56:40 +00:00
dependabot[bot]
4e18c7108b Merge pull request #41 from xiaohai2271/dependabot/npm_and_yarn/tslib-2.0.3 2020-10-20 14:55:19 +00:00
dependabot[bot]
a7711a5833 chore(deps): bump tslib from 2.0.1 to 2.0.3
Bumps [tslib](https://github.com/Microsoft/tslib) from 2.0.1 to 2.0.3.
- [Release notes](https://github.com/Microsoft/tslib/releases)
- [Commits](https://github.com/Microsoft/tslib/compare/2.0.1...2.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-20 04:59:24 +00:00
禾几海
f7867cb9d9 Merge pull request #39 from xiaohai2271/dependabot/npm_and_yarn/zone.js-0.11.2
chore(deps): bump zone.js from 0.11.1 to 0.11.2
2020-10-20 12:55:17 +08:00
禾几海
83d117856c Merge pull request #35 from xiaohai2271/dependabot/npm_and_yarn/jasmine-spec-reporter-6.0.0
chore(deps-dev): bump jasmine-spec-reporter from 5.0.2 to 6.0.0
2020-10-20 12:54:23 +08:00
禾几海
f829b269e9 Merge pull request #32 from xiaohai2271/dependabot/npm_and_yarn/codelyzer-6.0.1
chore(deps-dev): bump codelyzer from 6.0.0 to 6.0.1
2020-10-20 12:53:34 +08:00
dependabot[bot]
ea5e6cd8d7 chore(deps): bump zone.js from 0.11.1 to 0.11.2
Bumps [zone.js](https://github.com/angular/angular/tree/HEAD/packages/zone.js) from 0.11.1 to 0.11.2.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/zone.js-0.11.2/packages/zone.js)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-19 07:26:07 +00:00
dependabot[bot]
a6a34113c9 chore(deps-dev): bump codelyzer from 6.0.0 to 6.0.1
Bumps [codelyzer](https://github.com/mgechev/codelyzer) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/mgechev/codelyzer/releases)
- [Changelog](https://github.com/mgechev/codelyzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mgechev/codelyzer/commits/6.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-19 07:24:54 +00:00
dependabot[bot]
cf323dfa20 chore(deps-dev): bump jasmine-spec-reporter from 5.0.2 to 6.0.0
Bumps [jasmine-spec-reporter](https://github.com/bcaudan/jasmine-spec-reporter) from 5.0.2 to 6.0.0.
- [Release notes](https://github.com/bcaudan/jasmine-spec-reporter/releases)
- [Changelog](https://github.com/bcaudan/jasmine-spec-reporter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bcaudan/jasmine-spec-reporter/compare/v5.0.2...v6.0.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-19 07:24:21 +00:00
禾几海
0dd3e756b6 Merge pull request #33 from xiaohai2271/dependabot/npm_and_yarn/angular-devkit/build-angular-0.1001.7
chore(deps-dev): bump @angular-devkit/build-angular from 0.1001.1 to 0.1001.7
2020-10-19 15:06:49 +08:00
禾几海
f389bebf44 Merge pull request #31 from xiaohai2271/dependabot/npm_and_yarn/karma-5.2.3
chore(deps-dev): bump karma from 5.2.2 to 5.2.3
2020-10-19 15:03:35 +08:00
禾几海
88f7e8111d Merge pull request #28 from xiaohai2271/dependabot/npm_and_yarn/typescript-4.0.3
chore(deps-dev): bump typescript from 4.0.2 to 4.0.3
2020-10-19 15:02:12 +08:00
禾几海
19d556f2f3 Revert "Update test.yml"
This reverts commit f9a4c8d6
2020-10-19 14:52:51 +08:00
禾几海
152f10b449 Merge branch 'master' into dependabot/npm_and_yarn/angular-devkit/build-angular-0.1001.7 2020-10-19 14:49:01 +08:00
禾几海
f2b95c3510 Merge pull request #34 from xiaohai2271/dependabot/npm_and_yarn/angular/language-service-10.1.6
chore(deps-dev): bump @angular/language-service from 10.1.1 to 10.1.6
2020-10-19 14:47:03 +08:00
禾几海
a41a7e9eed Merge pull request #36 from xiaohai2271/dependabot/npm_and_yarn/angular/cli-10.1.7
chore(deps-dev): bump @angular/cli from 10.1.1 to 10.1.7
2020-10-19 14:46:05 +08:00
禾几海
9b656716dc Merge pull request #37 from xiaohai2271/dependabot/npm_and_yarn/vditor-3.5.5
chore(deps): bump vditor from 3.5.4 to 3.5.5
2020-10-19 14:41:20 +08:00
禾几海
9d6af4dc92 Merge pull request #38 from xiaohai2271/dependabot/npm_and_yarn/types/node-14.11.10
chore(deps-dev): bump @types/node from 14.10.2 to 14.11.10
2020-10-19 14:40:22 +08:00
dependabot[bot]
77d54fa7e0 chore(deps-dev): bump @types/node from 14.10.2 to 14.11.10
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.10.2 to 14.11.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-19 06:31:37 +00:00
禾几海
f9a4c8d629 Update test.yml 2020-10-16 19:33:36 +08:00
dependabot[bot]
23f67e23b2 chore(deps): bump vditor from 3.5.4 to 3.5.5
Bumps [vditor](https://github.com/Vanessa219/vditor) from 3.5.4 to 3.5.5.
- [Release notes](https://github.com/Vanessa219/vditor/releases)
- [Changelog](https://github.com/Vanessa219/vditor/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Vanessa219/vditor/compare/v3.5.4...v3.5.5)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-16 11:22:36 +00:00
dependabot[bot]
0b81661b76 chore(deps-dev): bump @angular/cli from 10.1.1 to 10.1.7
Bumps [@angular/cli](https://github.com/angular/angular-cli) from 10.1.1 to 10.1.7.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/compare/v10.1.1...v10.1.7)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-16 11:21:04 +00:00
dependabot[bot]
29930ccec0 chore(deps-dev): bump @angular/language-service from 10.1.1 to 10.1.6
Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 10.1.1 to 10.1.6.
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/10.1.6/packages/language-service)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-16 11:20:03 +00:00
dependabot[bot]
b59b30b32c chore(deps-dev): bump @angular-devkit/build-angular
Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1001.1 to 0.1001.7.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-16 11:19:38 +00:00
禾几海
6f1dd5cba5 Update dependabot.yml 2020-10-16 19:19:23 +08:00
dependabot[bot]
20ec1552a6 chore(deps-dev): bump karma from 5.2.2 to 5.2.3
Bumps [karma](https://github.com/karma-runner/karma) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v5.2.2...v5.2.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-16 11:15:42 +00:00
dependabot[bot]
c388297f12 chore(deps-dev): bump typescript from 4.0.2 to 4.0.3
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.2 to 4.0.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.2...v4.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-16 11:14:21 +00:00
禾几海
dcbd47332e Create dependabot.yml 2020-10-16 19:12:32 +08:00
禾几海
c8323a965c fix: 订阅未取消引发的异常 2020-10-10 00:33:44 +08:00
禾几海
086e476da8 fix: token校验失败时移除token 2020-10-10 00:26:00 +08:00
禾几海
a4fa38deee fix: 空值异常 2020-10-10 00:25:22 +08:00
禾几海
b63697f717 refactor: 删除残留代码 2020-10-10 00:24:46 +08:00
禾几海
1f2c925b45 Merge pull request #27 from xiaohai2271/refactor-mdEditor
切换markdown编辑器为vditor
2020-10-09 19:33:06 +08:00
禾几海
c67d7b7593 feat: 配置文件上传 2020-10-09 18:59:42 +08:00
禾几海
7f418c7f95 feat: 锚点 2020-10-09 17:53:14 +08:00
禾几海
2ce76455a4 feat: 锚点 2020-10-09 17:52:42 +08:00
禾几海
7d181b71a9 fix: 代码lint 2020-10-09 17:29:54 +08:00
禾几海
91921bda96 feat: 配置markdown预览 2020-10-09 17:29:24 +08:00
禾几海
5b96b66af5 feat: 配置markdown编辑器 2020-10-09 16:37:58 +08:00
禾几海
4cf1d4130b refactor: 切换markdown编辑器到vditor 2020-10-09 00:26:07 +08:00
禾几海
dfd609ded3 ci: 调整ci 2020-10-08 11:32:46 +08:00
禾几海
1d994d16b1 ci: 调整测试ci 2020-10-08 11:22:47 +08:00
禾几海
23aec69b4f chore: 移除无效引用 2020-10-08 10:56:10 +08:00
禾几海
322c52ce86 refactor: lint检查 2020-10-07 23:45:53 +08:00
禾几海
410013779e Create codeql-analysis.yml 2020-10-03 18:12:10 +08:00
禾几海
b00c6e5a2b chore: 更新依赖版本 2020-09-16 16:22:06 +08:00
禾几海
13c0529def feat: Upload a Build Artifact 2020-09-13 15:40:37 +08:00
禾几海
d59eb47f03 Merge branch 'dev' 2020-09-13 15:33:42 +08:00
禾几海
25cf2290b9 refactor: 修改copyright 2020-09-13 15:33:16 +08:00
禾几海
130e135e03 Merge branch 'dev' 2020-09-13 12:24:17 +08:00
禾几海
f8e30d8823 refactor: 修改copyright 2020-09-13 12:22:03 +08:00
禾几海
b42d3b7d33 Update issue templates 2020-09-07 12:20:57 +08:00
禾几海
138b93da09 fix(commonTable): 请求参数的传递 2020-09-05 17:19:07 +08:00
禾几海
072eaa12e8 fix: 参数异常 2020-09-05 17:09:10 +08:00
禾几海
d263cc132d feat(访客管理): 添加对位置信息的展示 2020-09-05 16:54:06 +08:00
禾几海
f044e9d01b fix(commonTable): 未设置action列导致的空值异常 2020-09-04 08:24:17 +08:00
禾几海
c14f495f8e chore: 本地存储favicon.ico和logo图片 2020-08-31 22:17:36 +08:00
禾几海
ab8a9154ec remove console.log() 2020-08-28 22:32:01 +08:00
禾几海
6da84e259e feature(commonTable): dynamic detection of data changes 2020-08-28 14:53:11 +08:00
禾几海
e95cd8fe23 fix(commonTable): error cause by shallow copy 2020-08-28 14:46:55 +08:00
禾几海
d8e6e9c5d9 refactor(commonTable): remove unused field 2020-08-28 11:36:42 +08:00
禾几海
990548b8d5 feat(commonTable): adjust column's width 2020-08-28 11:35:29 +08:00
禾几海
449adc4cee feat(commonTable): editable field 2020-08-28 11:25:45 +08:00
禾几海
22480569a2 Merge branch 'dev' 2020-08-28 09:38:15 +08:00
禾几海
58655bed94 fix(token): token signature error 2020-08-28 09:36:21 +08:00
禾几海
32e5c4daf0 Update build.yml 2020-08-27 21:58:48 +08:00
禾几海
6ea2f792db Update build.yml 2020-08-27 21:24:37 +08:00
禾几海
ab6d056d3a Update build.yml 2020-08-27 21:09:30 +08:00
禾几海
670b028384 手机端布局异常,移除i标签 2020-08-08 11:26:53 +08:00
禾几海
2e1fa1eb6a Update README.md 2020-08-07 22:20:35 +08:00
禾几海
c6aebd8d68 Create LICENSE 2020-08-07 22:16:04 +08:00
禾几海
1e8acd91c2 调整友链页面,友链管理页面 2020-08-07 22:05:03 +08:00
禾几海
398716e3ff 补全表单缺失项 2020-08-07 21:45:39 +08:00
禾几海
58d11c4fa8 icon 图标的颜色 2020-08-07 21:31:24 +08:00
禾几海
5454a747a7 加入网站图标预览和友链页链接自动补写 2020-08-07 21:29:30 +08:00
禾几海
953fba5b17 调整友链页面样式 2020-08-07 21:10:20 +08:00
禾几海
fee6f45ea9 新增获取随机颜色的方法 2020-08-07 21:10:10 +08:00
禾几海
7803629cd3 添加维护页面,修复bug 2020-08-05 23:20:38 +08:00
禾几海
a81f41e15c 友链添加按钮 2020-08-05 22:36:09 +08:00
禾几海
86378a46f2 typo 2020-08-05 22:33:53 +08:00
禾几海
53ddfe6e4c 全局异常提示 2020-08-05 22:30:07 +08:00
禾几海
44f251135c 路由跳转 2020-08-05 22:16:30 +08:00
禾几海
6fb62adb91 清理代码 2020-08-05 21:38:21 +08:00
禾几海
01c21f5732 删除ErrDispatch.ts 2020-08-05 21:35:10 +08:00
禾几海
66d523e69c 使用service过度error处理 2020-08-05 21:34:26 +08:00
禾几海
3ff80e5b54 解除继承关系 2020-08-05 21:31:24 +08:00
禾几海
8fb268f4cf 显示小header 2020-08-05 12:55:58 +08:00
禾几海
34ff380731 维护页面入口 2020-08-05 12:55:12 +08:00
禾几海
392c7f3996 添加维护页面 2020-08-05 12:54:58 +08:00
禾几海
0c8eed9243 ... 2020-08-01 21:43:36 +08:00
禾几海
7e0b2b0e78 Merge pull request #24 from xiaohai2271/feature-#23
调整友链申请
2020-08-01 21:27:19 +08:00
禾几海
6b63e7b02b 修复接口异常 2020-08-01 19:21:56 +08:00
禾几海
5d3b55b8b7 调整弹窗 2020-08-01 19:21:37 +08:00
禾几海
a6c3f16ddf 调整 2020-08-01 13:31:10 +08:00
禾几海
c75b17fa05 调整 2020-08-01 13:30:57 +08:00
534 changed files with 2528 additions and 94884 deletions

87
.eslintrc.json Normal file
View File

@@ -0,0 +1,87 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"tsconfig.json",
"e2e/tsconfig.json"
],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/ng-cli-compat",
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"prefer-arrow/prefer-arrow-functions": [
"off"
],
"@typescript-eslint/ban-types": [
"error",
{
"types": {
"Object": {
"message": "Use {} instead",
"fixWith": "{}"
},
"{}": false
}
}
],
"@angular-eslint/component-selector": [
"off",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"off",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/no-inferrable-types": [
"off",
{
"ignoreParameters": true
}
],
"arrow-parens": [
"off",
"always"
],
"import/order": "off"
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@angular-eslint/template/recommended"
],
"rules": {
"@angular-eslint/template/eqeqeq": "off"
}
}
]
}

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

12
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "monthly"
open-pull-requests-limit: 15

View File

@@ -1,6 +1,3 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Build
on:
@@ -9,33 +6,51 @@ on:
jobs:
build:
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '.md')" # 如果 commit 信息包含以下关键字则跳过该任务
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 12.x
- name: Sync to Gitee
uses: x-dr/sync-repo-to-gitee@master
env:
# 在 Settings->Secrets 配置 GITEE_KEY
SSH_KEY: ${{ secrets.GITEE_KEY }}
with:
# 注意替换为你的 GitHub 源仓库地址
github-repo: "git@github.com:xiaohai2271/blog-frontEnd.git"
# 注意替换为你的 Gitee 目标仓库地址
gitee-repo: "git@gitee.com:xiaohai2271/blog-frontEnd.git"
- name: Use Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: npm install -g @angular/cli
- run: bash build.sh
node-version: '16.x'
- run: npm install
- run: npm run lint && npm run build
- run: cd dist/index/ && tar -cf index.tar ./* && mv index.tar ../../
- name: SCP
uses: appleboy/scp-action@master
- name: Upload a Build Artifact
uses: actions/upload-artifact@v2.1.4
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
source: "index.tar"
target: "/www/wwwroot/celess.cn"
name: dist
path: ./dist/index/*
- name: Run SSH command
uses: garygrossgarten/github-action-ssh@v0.5.0
with:
command: cd /www/wwwroot/celess.cn && bash deploy.sh
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
# - name: SCP
# uses: appleboy/scp-action@master
# with:
# host: ${{ secrets.SSH_HOST }}
# username: ${{ secrets.SSH_USERNAME }}
# password: ${{ secrets.SSH_PASSWORD }}
# port: ${{ secrets.SSH_PORT }}
# source: "index.tar"
# target: "/www/wwwroot/www.celess.cn"
# - name: Run SSH command
# uses: garygrossgarten/github-action-ssh@v0.5.0
# with:
# command: cd /www/wwwroot/www.celess.cn && bash deploy.sh
# host: ${{ secrets.SSH_HOST }}
# username: ${{ secrets.SSH_USERNAME }}
# password: ${{ secrets.SSH_PASSWORD }}
# port: ${{ secrets.SSH_PORT }}

View File

@@ -1,20 +0,0 @@
name: test
on:
push:
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: npm install -g @angular/cli
- run: bash build.sh

19
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Test
on:
push:
pull_request:
branches: [ master ]
jobs:
build:
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '.md')" # 如果 commit 信息包含以下关键字则跳过该任务
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: '16.x'
- run: npm install
- run: npm run lint && npm run build

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
/.angular/cache
dist
node_modules
.idea
.editorconfig
package-lock.json

View File

@@ -1,4 +1,6 @@
Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
MIT License
Copyright (c) 2020 禾几海
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -7,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -51,15 +51,13 @@
##### 构建
>
>
> > 1. 进入index目录
> > 2. npm install
> > 3. 修改环境数据中的host
> >
> > 1. npm install
> > 2. 修改环境数据中的host
> >
> > - ` /src/environments/environment.ts` (本地开发环境)
> > - `/src/environments/environment-prod.ts`(线上发布环境)
> > 4. ng build --prod
> > 3. ng build --prod
>
>
>可使用项目根目录的`build.sh` 脚本进行构建,但是 两个项目中的环境里面的变量仍需自己修改
@@ -68,7 +66,7 @@
##### 发布
-`index/dist/index`下的全部文件上传到网站根目录
-`dist/index`下的全部文件上传到网站根目录
- 目录结构如下:

View File

@@ -22,7 +22,7 @@
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets",
@@ -34,18 +34,11 @@
"src/manifest.webmanifest"
],
"styles": [
"src/assets/editor/css/editormd.css",
"./node_modules/ng-zorro-antd/ng-zorro-antd.min.css",
"src/styles.less"
],
"scripts": [
"./node_modules/jquery/dist/jquery.min.js",
"src/assets/editor/lib/marked.min.js",
"src/assets/editor/lib/prettify.min.js",
"src/assets/editor/lib/underscore.min.js",
"src/assets/editor/lib/flowchart.min.js",
"src/assets/editor/lib/jquery.flowchart.min.js",
"src/assets/editor/editormd.min.js"
"./node_modules/jquery/dist/jquery.min.js"
]
},
"configurations": {
@@ -59,7 +52,6 @@
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
@@ -119,15 +111,11 @@
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"builder": "@angular-eslint/builder:lint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
},
@@ -146,7 +134,6 @@
}
}
},
"defaultProject": "index",
"cli": {
"analytics": false
}

View File

@@ -1,40 +0,0 @@
#!/bin/sh
basePath=$(pwd)
$(hash node 2>/dev/null)
if ! [ $? ]; then
echo -e "\t\t请先安装nodejs -------> https://nodejs.org/"
exit 1
else
echo -e "\t\t nodejs\t\t $(node --version)"
fi
$(hash npm 2>/dev/null)
if ! [ $? ]; then
echo -e "\t\t Can't find command npm"
exit 1
else
echo -e "\t\t npm\t\t $(npm --version)"
fi
$(hash ng 2>/dev/null)
if ! [ $? ]; then
echo -e "\t\tinstall angular cli to build the project"
npm install -g @angular/cli
else
echo -e "\t\t angular-cli\t\t $(ng --version)"
fi
# index
echo -e "\t\tBuild for index page "
npm install && ng build --prod
cd ./dist/index/ && tar -cf index.tar ./* && cp index.tar $basePath
#cd "$basePath"
## admin
#echo -e "\t\tBuild for admin page "
#cd $basePath/admin && npm install && ng build --prod
#cd ./dist/admin/ && sed '6s/\"\/\"/\"\/admin\/\"/g' index.html > index.txt && cp index.txt index.html
# cd .. && tar -cf admin.tar ./admin/ && cp admin.tar $basePath

17483
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,41 +11,52 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^10.0.3",
"@angular/common": "^10.0.3",
"@angular/compiler": "^10.0.3",
"@angular/core": "^10.0.3",
"@angular/forms": "^10.0.3",
"@angular/platform-browser": "^10.0.3",
"@angular/platform-browser-dynamic": "^10.0.3",
"@angular/router": "^10.0.3",
"@angular/service-worker": "^10.0.3",
"@angular/animations": "^14.2.12",
"@angular/common": "^14.2.12",
"@angular/compiler": "^15.2.0",
"@angular/core": "^14.2.12",
"@angular/forms": "^14.2.12",
"@angular/platform-browser": "^14.2.12",
"@angular/platform-browser-dynamic": "^14.2.12",
"@angular/router": "^14.2.12",
"@angular/service-worker": "^14.2.12",
"jquery": "^3.5.1",
"ng-zorro-antd": "^9.3.0",
"nrm": "^1.2.1",
"rxjs": "^6.6.0",
"tslib": "^2.0.0",
"zone.js": "^0.10.3"
"js-base64": "^3.6.0",
"ng-zorro-antd": "^14.2.1",
"rxjs": "^7.5.7",
"tslib": "^2.0.3",
"vditor": "~3.6.3",
"zone.js": "^0.12.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1000.2",
"@angular/cli": "^10.0.2",
"@angular/compiler-cli": "^10.0.3",
"@angular/language-service": "^10.0.3",
"@types/jasmine": "^3.5.11",
"@angular-devkit/build-angular": "^14.2.10",
"@angular-eslint/builder": "14.4.0",
"@angular-eslint/eslint-plugin": "14.4.0",
"@angular-eslint/eslint-plugin-template": "14.4.0",
"@angular-eslint/schematics": "14.4.0",
"@angular-eslint/template-parser": "15.1.0",
"@angular/cli": "^14.2.10",
"@angular/compiler-cli": "^14.2.12",
"@angular/language-service": "^14.2.12",
"@types/jasmine": "^4.3.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^14.0.22",
"codelyzer": "^6.0.0",
"jasmine-core": "^3.5.0",
"jasmine-spec-reporter": "^5.0.2",
"karma": "^5.1.0",
"@types/node": "^18.11.10",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"codelyzer": "^6.0.1",
"eslint": "^8.23.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsdoc": "^39.6.4",
"eslint-plugin-prefer-arrow": "1.2.3",
"jasmine-core": "^4.5.0",
"jasmine-spec-reporter": "^7.0.0",
"karma": "^6.2.0",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^3.3.1",
"karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^1.5.4",
"protractor": "^7.0.0",
"ts-node": "^8.10.2",
"tslint": "^6.1.2",
"typescript": "^3.9.6"
"ts-node": "^10.5.0",
"typescript": "~4.8.4"
}
}

View File

@@ -1,39 +1,26 @@
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Article} from '../class/Article';
import {Article, ArticleReq} from '../class/Article';
import {HttpService} from './http/http.service';
import {PageList} from '../class/HttpReqAndResp';
import {ErrDispatch} from '../class/ErrDispatch';
import {ArticleReq} from '../class/Article';
import {Category, Tag} from '../class/Tag';
import {Comment} from '../class/Comment';
import {CommentReq} from '../class/Comment';
import {Link} from '../class/Link';
import {User} from '../class/User';
import {LoginReq} from '../class/User';
import {LocalStorageService} from '../services/local-storage.service';
import {Comment, CommentReq} from '../class/Comment';
import {ApplyLinkReq, Link} from '../class/Link';
import {LoginReq, User} from '../class/User';
import {Visitor} from '../class/Visitor';
import {UpdateInfo} from '../class/UpdateInfo';
@Injectable({
providedIn: 'root'
})
export class ApiService extends HttpService {
export class ApiService {
constructor(httpClient: HttpClient,
localStorageService: LocalStorageService) {
super(httpClient, localStorageService);
}
setErrDispatch(errDispatch: ErrDispatch) {
super.setErrDispatch(errDispatch);
constructor(private httpService: HttpService) {
}
createArticle(article: ArticleReq) {
article.id = null;
return super.Service<Article>({
return this.httpService.service<Article>({
path: '/admin/article/create',
contentType: 'application/json',
method: 'POST',
@@ -42,15 +29,15 @@ export class ApiService extends HttpService {
}
deleteArticle(id: number) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: '/admin/article/del',
method: 'DELETE',
queryParam: {articleID: id}
})
});
}
articles(pageNumber: number = 1, pageSize: number = 5) {
return super.Service<PageList<Article>>({
return this.httpService.service<PageList<Article>>({
path: '/articles',
method: 'GET',
queryParam: {
@@ -61,7 +48,7 @@ export class ApiService extends HttpService {
}
adminArticles(pageNumber: number = 1, pageSize: number = 10) {
return super.Service<PageList<Article>>({
return this.httpService.service<PageList<Article>>({
path: '/admin/articles',
method: 'GET',
queryParam: {
@@ -72,7 +59,7 @@ export class ApiService extends HttpService {
}
updateArticle(article: ArticleReq) {
return super.Service<Article>({
return this.httpService.service<Article>({
path: '/admin/article/update',
method: 'PUT',
contentType: 'application/json',
@@ -81,7 +68,7 @@ export class ApiService extends HttpService {
}
getArticle(articleId: number, is4Update: boolean = false) {
return super.Service<Article>({
return this.httpService.service<Article>({
path: `/article/articleID/${articleId}`,
method: 'GET',
queryParam: {update: is4Update},
@@ -89,7 +76,7 @@ export class ApiService extends HttpService {
}
articlesByCategory(category: string, pageNumber: number = 1, pageSize: number = 10) {
return super.Service<PageList<Article>>({
return this.httpService.service<PageList<Article>>({
path: `/articles/category/${category}`,
method: 'GET',
queryParam: {
@@ -100,7 +87,7 @@ export class ApiService extends HttpService {
}
articlesByTag(tag: string, pageNumber: number = 1, pageSize: number = 10) {
return super.Service<PageList<Article>>({
return this.httpService.service<PageList<Article>>({
path: `/articles/tag/${tag}`,
method: 'GET',
queryParam: {
@@ -111,14 +98,14 @@ export class ApiService extends HttpService {
}
categories() {
return super.Service<PageList<Category>>({
return this.httpService.service<PageList<Category>>({
path: '/categories',
method: 'GET'
});
}
createCategory(nameStr: string) {
return super.Service<Category>({
return this.httpService.service<Category>({
path: '/admin/category/create',
method: 'POST',
queryParam: {name: nameStr}
@@ -126,7 +113,7 @@ export class ApiService extends HttpService {
}
deleteCategory(categoryId: number) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: '/admin/category/del',
method: 'DELETE',
queryParam: {id: categoryId}
@@ -134,7 +121,7 @@ export class ApiService extends HttpService {
}
updateCategory(categoryId: number, nameStr: string) {
return super.Service<Category>({
return this.httpService.service<Category>({
path: '/admin/category/update',
method: 'PUT',
queryParam: {id: categoryId, name: nameStr}
@@ -142,7 +129,7 @@ export class ApiService extends HttpService {
}
tags(pageNumber: number = 1, pageSize: number = 10) {
return super.Service<PageList<Tag>>({
return this.httpService.service<PageList<Tag>>({
path: '/tags',
method: 'GET',
queryParam: {
@@ -153,38 +140,38 @@ export class ApiService extends HttpService {
}
tagsNac() {
return super.Service<{ name: string, size: number }[]>({
return this.httpService.service<{ name: string; size: number }[]>({
path: '/tags/nac',
method: 'GET'
});
}
createTag(nameStr: string) {
return super.Service<Tag>({
return this.httpService.service<Tag>({
path: '/admin/tag/create',
method: 'POST',
queryParam: {name: nameStr}
});
}
deleteTag(TagId: number) {
return super.Service<boolean>({
deleteTag(tagId: number) {
return this.httpService.service<boolean>({
path: '/admin/tag/del',
method: 'DELETE',
queryParam: {id: TagId}
queryParam: {id: tagId}
});
}
updateTag(TagId: number, nameStr: string) {
return super.Service<Tag>({
updateTag(tagId: number, nameStr: string) {
return this.httpService.service<Tag>({
path: '/admin/tag/update',
method: 'PUT',
queryParam: {id: TagId, name: nameStr}
queryParam: {id: tagId, name: nameStr}
});
}
getCommentByTypeForAdmin(pagePath: string, pageNumber: number = 1, pageSize: number = 10) {
return super.Service<PageList<Comment>>({
return this.httpService.service<PageList<Comment>>({
path: `/admin/comment/pagePath/${pagePath}`,
method: 'GET',
queryParam: {
@@ -195,7 +182,7 @@ export class ApiService extends HttpService {
}
getCommentByTypeForUser(pagePath: string, pageNumber: number = 1, pageSize: number = 10) {
return super.Service<PageList<Comment>>({
return this.httpService.service<PageList<Comment>>({
path: `/user/comment/pagePath/${pagePath}`,
method: 'GET',
queryParam: {
@@ -206,7 +193,7 @@ export class ApiService extends HttpService {
}
deleteComment(idNumer: number) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: `/user/comment/del`,
method: 'DELETE',
queryParam: {id: idNumer}
@@ -214,7 +201,7 @@ export class ApiService extends HttpService {
}
updateComment(commentReq: CommentReq) {
return super.Service<Comment>({
return this.httpService.service<Comment>({
path: `/user/comment/update`,
method: 'PUT',
data: commentReq,
@@ -223,7 +210,7 @@ export class ApiService extends HttpService {
}
comments(pagePath: string, pageSize: number = 10, pageNumber: number = 1) {
return super.Service<PageList<Comment>>({
return this.httpService.service<PageList<Comment>>({
path: `/comment/pagePath/${pagePath}`,
method: 'GET',
queryParam: {
@@ -234,7 +221,7 @@ export class ApiService extends HttpService {
}
createComment(commentReq: CommentReq) {
return super.Service<Comment>({
return this.httpService.service<Comment>({
path: '/user/comment/create',
method: 'POST',
contentType: 'application/json',
@@ -244,12 +231,12 @@ export class ApiService extends HttpService {
counts() {
return super.Service<{
articleCount: number,
visitorCount: number,
categoryCount: number,
tagCount: number,
commentCount: number
return this.httpService.service<{
articleCount: number;
visitorCount: number;
categoryCount: number;
tagCount: number;
commentCount: number;
}>({
path: '/counts',
method: 'GET'
@@ -257,7 +244,7 @@ export class ApiService extends HttpService {
}
adminLinks(pageSize: number = 10, pageNumber: number = 1) {
return super.Service<PageList<Link>>({
return this.httpService.service<PageList<Link>>({
path: '/admin/links',
method: 'GET',
queryParam: {
@@ -268,7 +255,7 @@ export class ApiService extends HttpService {
}
createLink(linkReq: Link) {
return super.Service<Link>({
return this.httpService.service<Link>({
path: '/admin/links/create',
method: 'POST',
data: linkReq,
@@ -277,14 +264,14 @@ export class ApiService extends HttpService {
}
deleteLink(idNumber: number) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: `/admin/links/del/${idNumber}`,
method: 'DELETE',
});
}
updateLink(linkReq: Link) {
return super.Service<Link>({
return this.httpService.service<Link>({
path: '/admin/links/update',
method: 'PUT',
data: linkReq,
@@ -292,26 +279,34 @@ export class ApiService extends HttpService {
});
}
applyLink(link: Link) {
return super.Service<string>({
applyLink(link: ApplyLinkReq) {
return this.httpService.service<string>({
path: '/apply',
method: 'POST',
data: link,
contentType: 'application/json'
});
}
reapplyLink(keyStr: string) {
return this.httpService.service<string>({
path: '/reapply',
method: 'POST',
queryParam: {
name: link.name,
url: link.url
key: keyStr
}
});
}
links() {
return super.Service<Link[]>({
return this.httpService.service<Link[]>({
path: '/links',
method: 'GET',
});
}
verifyImgCode(codeStr: string) {
return super.Service<string>({
return this.httpService.service<string>({
path: '/verCode',
method: 'POST',
queryParam: {code: codeStr}
@@ -320,7 +315,7 @@ export class ApiService extends HttpService {
login(loginReq: LoginReq) {
return super.Service<User>({
return this.httpService.service<User>({
path: '/login',
method: 'POST',
contentType: 'application/json',
@@ -329,14 +324,14 @@ export class ApiService extends HttpService {
}
logout() {
return super.Service<string>({
return this.httpService.service<string>({
path: '/logout',
method: 'GET',
});
}
registration(emailStr: string, pwd: string) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: '/registration',
method: 'POST',
queryParam: {
@@ -347,7 +342,7 @@ export class ApiService extends HttpService {
}
resetPwd(idStr: string, emailStr: string, pwdStr: string) {
return super.Service<string>({
return this.httpService.service<string>({
path: '/resetPwd',
method: 'POST',
queryParam: {
@@ -359,7 +354,7 @@ export class ApiService extends HttpService {
}
emailVerify(idStr: string, emailStr: string) {
return super.Service<void>({
return this.httpService.service<void>({
path: '/emailVerify',
method: 'POST',
queryParam: {
@@ -371,7 +366,7 @@ export class ApiService extends HttpService {
sendResetPwdEmail(emailStr: string) {
return super.Service<string>({
return this.httpService.service<string>({
path: '/sendResetPwdEmail',
method: 'POST',
queryParam: {email: emailStr}
@@ -379,7 +374,7 @@ export class ApiService extends HttpService {
}
sendVerifyEmail(emailStr: string) {
return super.Service<string>({
return this.httpService.service<string>({
path: '/sendVerifyEmail',
method: 'POST',
queryParam: {email: emailStr}
@@ -387,30 +382,30 @@ export class ApiService extends HttpService {
}
userInfo() {
return super.Service<User>({
return this.httpService.service<User>({
path: '/user/userInfo',
method: 'GET',
});
}
adminUpdateUser(user: User) {
return super.Service<User>({
return this.httpService.service<User>({
path: '/admin/user',
method: 'PUT',
data: user,
contentType: 'application/json'
})
});
}
deleteUser(id: number) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: `/admin/user/delete/${id}`,
method: 'DELETE',
});
}
multipleDeleteUser(idArray: number[]) {
return super.Service<{ id: number; msg: string; status: boolean }[]>({
return this.httpService.service<{ id: number; msg: string; status: boolean }[]>({
path: `/admin/user/delete`,
method: 'DELETE',
data: idArray,
@@ -420,14 +415,14 @@ export class ApiService extends HttpService {
// 获取邮件是否已注册
emailStatus(email: string) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: `/emailStatus/${email}`,
method: 'GET'
})
});
}
updateUserInfo(descStr: string, disPlayNameStr: string) {
return super.Service<User>({
return this.httpService.service<User>({
path: '/user/userInfo/update',
method: 'PUT',
queryParam: {
@@ -438,7 +433,7 @@ export class ApiService extends HttpService {
}
adminUsers(pageSize: number = 10, pageNumber: number = 1) {
return super.Service<PageList<User>>({
return this.httpService.service<PageList<User>>({
path: '/admin/users',
method: 'GET',
queryParam: {
@@ -449,14 +444,14 @@ export class ApiService extends HttpService {
}
visit() {
return super.Service<Visitor>({
return this.httpService.service<Visitor>({
path: '/visit',
method: 'POST'
});
}
adminVisitors(location: boolean = false, pageSize: number = 10, pageNumber: number = 1) {
return super.Service<PageList<Visitor>>({
return this.httpService.service<PageList<Visitor>>({
path: '/admin/visitor/page',
method: 'GET',
queryParam: {
@@ -468,42 +463,42 @@ export class ApiService extends HttpService {
}
dayVisitCount() {
return super.Service<number>({
return this.httpService.service<number>({
path: '/dayVisitCount',
method: 'GET',
});
}
getLocalIp() {
return super.Service<string>({
return this.httpService.service<string>({
path: '/ip',
method: 'GET',
});
}
getIpLocation(ip: string) {
return super.Service<string>({
return this.httpService.service<string>({
path: `/ip/${ip}`,
method: 'GET',
});
}
visitorCount() {
return super.Service<number>({
return this.httpService.service<number>({
path: `/visitor/count`,
method: 'GET',
});
}
webUpdate() {
return super.Service<{ id: number, info: string, time: string }[]>({
return this.httpService.service<{ id: number; info: string; time: string }[]>({
path: '/webUpdate',
method: 'GET'
});
}
webUpdatePage(pageSize: number = 10, pageNumber: number = 1) {
return super.Service<PageList<{ id: number, info: string, time: string }>>({
return this.httpService.service<PageList<{ id: number; info: string; time: string }>>({
path: '/webUpdate/pages',
method: 'GET',
queryParam: {
@@ -514,13 +509,13 @@ export class ApiService extends HttpService {
}
lastestUpdate() {
return super.Service<{
return this.httpService.service<{
lastUpdateTime: string;
lastUpdateInfo: string;
lastCommit: string;
committerAuthor: string;
committerDate: string;
commitUrl: string
commitUrl: string;
}>({
path: '/lastestUpdate',
method: 'GET'
@@ -528,7 +523,7 @@ export class ApiService extends HttpService {
}
createWebUpdateInfo(infoStr: string) {
return super.Service<UpdateInfo>({
return this.httpService.service<UpdateInfo>({
path: '/admin/webUpdate/create',
method: 'POST',
queryParam: {info: infoStr}
@@ -536,14 +531,14 @@ export class ApiService extends HttpService {
}
deleteWebUpdateInfo(idNumber: number) {
return super.Service<boolean>({
return this.httpService.service<boolean>({
path: `/admin/webUpdate/del/${idNumber}`,
method: 'DELETE',
});
}
updateWebUpdateInfo(idNumber: number, infoStr: string) {
return super.Service<UpdateInfo>({
return this.httpService.service<UpdateInfo>({
path: '/admin/webUpdate/update',
method: 'PUT',
queryParam: {id: idNumber, info: infoStr}
@@ -551,14 +546,14 @@ export class ApiService extends HttpService {
}
bingPic() {
return super.Service<string>({
return this.httpService.service<string>({
path: '/bingPic',
method: 'GET'
});
}
setPwd(pwdStr: string, newPwdStr: string, confirmPwdStr: string,) {
return super.Service<string>({
return this.httpService.service<string>({
path: '/user/setPwd',
method: 'POST',
queryParam: {

View File

@@ -1,32 +1,32 @@
import {Injectable} from '@angular/core';
import {RequestObj} from '../../class/HttpReqAndResp';
import {Injectable, Injector} from '@angular/core';
import {RequestObj, Response} from '../../class/HttpReqAndResp';
import {HttpClient, HttpResponse} from '@angular/common/http';
import {environment} from '../../../environments/environment';
import {LocalStorageService} from '../../services/local-storage.service';
import {Response} from '../../class/HttpReqAndResp';
import {Observable, Observer, Subject} from 'rxjs';
import {ErrDispatch} from '../../class/ErrDispatch';
import {Observable, Observer, Subscription} from 'rxjs';
import {ErrorService} from '../../services/error.service';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class HttpService {
private subscriptionQueue: Subscription[] = [];
constructor(private httpClient: HttpClient,
protected localStorageService: LocalStorageService) {
private localStorageService: LocalStorageService,
private injector: Injector) {
}
private errorDispatch: ErrDispatch;
public getSubscriptionQueue = () => this.subscriptionQueue;
setErrDispatch(errDispatch: ErrDispatch) {
this.errorDispatch = errDispatch;
}
Service<T>(request: RequestObj) {
service<T>(request: RequestObj) {
const errorService = this.injector.get(ErrorService);
request.url = null;
// 设置默认值
request.contentType = request.contentType == null ? 'application/x-www-form-urlencoded' : request.contentType;
request.header = {
// eslint-disable-next-line @typescript-eslint/naming-convention
'Content-Type': request.contentType
};
const token = this.localStorageService.getToken();
@@ -55,25 +55,32 @@ export class HttpService {
const oob = new Observable<Response<T>>(o => observer = o);
observable.subscribe(o => {
const tokenFromReps = o.headers.get('Authorization');
if (tokenFromReps) {
this.localStorageService.setToken(tokenFromReps);
}
if (o.body.code !== 0) {
observer.error(o.body);
if (this.errorDispatch) {
this.errorDispatch.errHandler(o.body.code, o.body.msg, request);
const subscription = observable.subscribe({
next: o => {
const tokenFromReps = o.headers.get('Authorization');
if (tokenFromReps) {
this.localStorageService.setToken(tokenFromReps);
}
} else {
observer.next(o.body);
}
observer.complete();
if (o.body.code !== 0) {
observer.error(o.body);
errorService.httpException(o.body, request);
} else {
observer.next(o.body);
}
observer.complete();
},
error: err => {
errorService.httpError(err, request);
errorService.checkConnection();
this.subscriptionQueue.splice(this.subscriptionQueue.indexOf(subscription), 1);
},
complete: () => this.subscriptionQueue.splice(this.subscriptionQueue.indexOf(subscription), 1)
});
this.subscriptionQueue.push(subscription);
return oob;
}
private get<T>(request: RequestObj) {
get<T>(request: RequestObj) {
return this.httpClient.get<T>(request.url,
{
headers: request.header,
@@ -82,7 +89,7 @@ export class HttpService {
});
}
private post<T>(request: RequestObj) {
post<T>(request: RequestObj) {
return this.httpClient.post<T>(request.url, request.data,
{
headers: request.header,
@@ -91,7 +98,7 @@ export class HttpService {
});
}
private put<T>(request: RequestObj) {
put<T>(request: RequestObj) {
return this.httpClient.put<T>(request.url, request.data,
{
headers: request.header,
@@ -100,7 +107,7 @@ export class HttpService {
});
}
private delete<T>(request: RequestObj) {
delete<T>(request: RequestObj) {
return this.httpClient.delete<T>(request.url,
{
headers: request.header,
@@ -111,6 +118,7 @@ export class HttpService {
/**
* 验证并且处理拼接 URl
*
* @param req Request
*/
private checkUrl(req: RequestObj): string {

View File

@@ -11,17 +11,15 @@ const routes: Routes = [
{path: 'resetPwd', loadChildren: () => import('./view/reset-pwd/reset-pwd.module').then(mod => mod.ResetPwdModule)},
{path: 'write', loadChildren: () => import('./view/write/write.module').then(mod => mod.WriteModule)},
{path: 'links', loadChildren: () => import('./view/link/link.module').then(mod => mod.LinkModule)},
{path: 'admin', loadChildren: () => import('./view/admin/admin.module').then(mod => mod.AdminModule)},
{path: 'maintain', loadChildren: () => import('./view/maintain/maintain.module').then(mod => mod.MaintainModule)},
{
path: 'emailVerify',
loadChildren: () => import('./view/email-verify/email-verify.module').then(mod => mod.EmailVerifyModule)
},
{
path: 'user', loadChildren: () => import('./view/login-registration/login-registration.module')
.then(mod => mod.LoginRegistrationModule)
},
{
path: 'admin',
loadChildren: () => import('./view/admin/admin.module').then(mod => mod.AdminModule),
path: 'user',
loadChildren: () => import('./view/login-registration/login-registration.module').then(mod => mod.LoginRegistrationModule)
},
{
path: '**',

View File

@@ -9,9 +9,9 @@ import {ComponentStateService} from './services/component-state.service';
styleUrls: ['./app.component.less']
})
export class AppComponent {
@ViewChild('headerComponent') header: HeaderComponent;
loginModal: boolean = false;
regModal: boolean = false;
@ViewChild('headerComponent') header: HeaderComponent;
constructor(public componentStateService: ComponentStateService) {
}

View File

@@ -1,7 +1,7 @@
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {AppComponent} from './app.component';
import {NgZorroAntdModule, NZ_I18N, zh_CN} from 'ng-zorro-antd';
import {NZ_I18N, zh_CN} from 'ng-zorro-antd/i18n';
import {FormsModule} from '@angular/forms';
import {HttpClientModule} from '@angular/common/http';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
@@ -12,8 +12,24 @@ import {FooterComponent} from './components/footer/footer.component';
import {AppRoutingModule} from './app-routing.module';
import {LoginRegistrationModule} from './view/login-registration/login-registration.module';
import {AdminModule} from './view/admin/admin.module';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import {ServiceWorkerModule} from '@angular/service-worker';
import {environment} from '../environments/environment';
import {HttpService} from './api/http/http.service';
import {ErrorService} from './services/error.service';
import {ComponentStateService} from './services/component-state.service';
import {GlobalUserService} from './services/global-user.service';
import {LocalStorageService} from './services/local-storage.service';
import {ApiService} from './api/api.service';
import {NzMessageService} from 'ng-zorro-antd/message';
import {NzBackTopModule} from 'ng-zorro-antd/back-top';
import {NzModalModule} from 'ng-zorro-antd/modal';
import {NzNotificationService} from 'ng-zorro-antd/notification';
import {NzDropDownModule} from 'ng-zorro-antd/dropdown';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzAvatarModule} from 'ng-zorro-antd/avatar';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzGridModule} from 'ng-zorro-antd/grid';
import {NzDividerModule} from 'ng-zorro-antd/divider';
registerLocaleData(zh);
@@ -27,15 +43,32 @@ registerLocaleData(zh);
imports: [
BrowserModule,
AppRoutingModule,
NgZorroAntdModule,
FormsModule,
HttpClientModule,
BrowserAnimationsModule,
LoginRegistrationModule,
AdminModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production}),
NzBackTopModule,
NzModalModule,
NzDropDownModule,
NzIconModule,
NzAvatarModule,
NzButtonModule,
NzGridModule,
NzDividerModule
],
providers: [
ComponentStateService,
GlobalUserService,
LocalStorageService,
HttpService,
ApiService,
NzMessageService,
NzNotificationService,
ErrorService,
{provide: NZ_I18N, useValue: zh_CN},
],
providers: [{provide: NZ_I18N, useValue: zh_CN}],
exports: [],
bootstrap: [AppComponent]
})

View File

@@ -1,27 +0,0 @@
import {environment} from '../../environments/environment';
export class EditorConfig {
public width = '100%';
public height = '400';
public path = 'assets/editor/lib/';
public codeFold: true;
public searchReplace = true;
public toolbar = true;
public placeholder = '欢迎来到小海的创作中心';
public emoji = true;
public taskList = true;
public tex = true;
public readOnly = false;
public tocm = true;
public watch = true;
public previewCodeHighlight = true;
public saveHTMLToTextarea = true;
public markdown = '';
public flowChart = true;
public syncScrolling = true;
public sequenceDiagram = false; // 时序图/序列图
public imageUpload = true;
public imageFormats = ['jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp'];
public imageUploadURL = environment.host + '/imgUpload';
public useAjaxToUploadImg = true
}

View File

@@ -1,5 +0,0 @@
import {RequestObj} from './HttpReqAndResp';
export interface ErrDispatch {
errHandler(code: number, msg: string, request?: RequestObj): void;
}

View File

@@ -6,7 +6,7 @@ export class RequestObj {
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
data?: {};
contentType?: 'application/json' | 'application/x-www-form-urlencoded';
queryParam?: {};
queryParam?: { [key: string]: any };
header?: HttpHeaders | {
[header: string]: string | string[];
};

View File

@@ -6,3 +6,13 @@ export class Link {
iconPath: string;
desc: string;
}
export class ApplyLinkReq {
desc: string;
email: string;
iconPath: string;
linkUrl: string;
name: string;
url: string;
}

View File

@@ -8,7 +8,7 @@ export class User {
role?: string;
token?: string;
pwd?: string;
recentlyLandedDate?: string
recentlyLandedDate?: string;
}
export class LoginReq {

View File

@@ -20,16 +20,16 @@
<div id="landr" *ngIf="!user">
<nz-space>
<nz-space-item>
<template *nzSpaceItem>
<a routerLink="/user/login">
<button nz-button nzType="primary">登录</button>
</a>
</nz-space-item>
<nz-space-item>
</template>
<template *nzSpaceItem>
<a routerLink="/user/registration">
<button nz-button nzType="primary">注册</button>
</a>
</nz-space-item>
</template>
</nz-space>
</div>

View File

@@ -8,13 +8,14 @@ import {User} from '../../class/User';
styleUrls: ['./admin-header.component.less']
})
export class AdminHeaderComponent implements OnInit {
@Output() infoClicked = new EventEmitter<void>();
user: User;
noAvatarUrl = 'https://cdn.celess.cn/';
constructor(private userService: GlobalUserService) {
}
user: User
@Output() infoClicked = new EventEmitter<void>()
noAvatarUrl = 'https://cdn.celess.cn/'
logout = () => this.userService.logout();
infoClickedEvent = () => this.infoClicked.emit();
@@ -23,7 +24,7 @@ export class AdminHeaderComponent implements OnInit {
next: data => this.user = data.result,
error: err => this.user = null,
complete: null
})
});
}
}

View File

@@ -1,12 +1,10 @@
<div class="footer">
<nz-divider></nz-divider>
<div>
<a href="http://www.miitbeian.gov.cn" target="_blank">
鄂ICP备18023929号
</a>
<a href="https://beian.miit.gov.cn" target="_blank">鄂ICP备18023929号-2</a>
<div>
© 2019 <a href="https://www.celess.cn">小海博客</a> -
<span>郑海 </span> <span *ngIf="gName">& {{gName}} </span>版权所有
© 2020 <a href="https://www.celess.cn">小海博客</a> -
<span>{{bName}} </span> <span *ngIf="gName">& {{gName}} </span>版权所有
</div>
</div>
</div>

View File

@@ -9,7 +9,7 @@
left: 0;
bottom: 0;
/* 设置z-index 是为了write页面将footer隐藏*/
z-index: -1;
z-index: 0;
}
hr {

View File

@@ -8,11 +8,12 @@ import {ComponentStateService} from '../../services/component-state.service';
})
export class FooterComponent implements OnInit {
readonly gName: string = '何梦幻';
readonly bName: string = '郑海';
constructor(public componentStateService: ComponentStateService) {
}
readonly gName: string;
ngOnInit() {
}

View File

@@ -1,7 +1,6 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Router} from '@angular/router';
import {windowWidthChange} from '../../utils/util';
import {ApiService} from '../../api/api.service';
import {User} from '../../class/User';
import {ComponentStateService} from '../../services/component-state.service';
import {GlobalUserService} from '../../services/global-user.service';
@@ -12,6 +11,25 @@ import {GlobalUserService} from '../../services/global-user.service';
styleUrls: ['./header.component.less']
})
export class HeaderComponent implements OnInit {
@Output() loginEvent = new EventEmitter();
@Output() registrationEvent = new EventEmitter();
@Input() userInfo: User;
size: 'large' | 'default';
currentPath: string;
noAvatarUrl = 'https://cdn.celess.cn/';
public pageList: {
path: string;
name: string;
icon: string;
iconType: 'outline' | 'fill' | 'twotone';
show: boolean;
}[];
public showList = true;
// css 样式中设置移动端最大宽度为910px 见src/app/global-variables.less
private readonly mobileMaxWidth = 940;
constructor(private router: Router,
public componentStateService: ComponentStateService,
@@ -37,7 +55,8 @@ export class HeaderComponent implements OnInit {
});
// 订阅一级路由的变化
componentStateService.watchRouterChange().subscribe(prefix => {
if (prefix === '/user' || prefix === '/write' || prefix === '/update') {
// TODO:: 使用service来获取 size
if (prefix === '/user' || prefix === '/write' || prefix === '/update' || prefix === '/maintain') {
this.size = 'default';
} else {
this.size = 'large';
@@ -45,26 +64,6 @@ export class HeaderComponent implements OnInit {
});
}
@Output() loginEvent = new EventEmitter();
@Output() registrationEvent = new EventEmitter();
size: 'large' | 'default';
currentPath: string;
noAvatarUrl = 'https://cdn.celess.cn/'
public pageList: {
path: string;
name: string;
icon: string;
iconType: 'outline' | 'fill' | 'twotone';
show: boolean;
}[];
public showList = true;
// css 样式中设置移动端最大宽度为910px 见src/app/global-variables.less
private readonly mobileMaxWidth = 940;
@Input() userInfo: User;
ngOnInit() {
}
@@ -74,17 +73,6 @@ export class HeaderComponent implements OnInit {
this.changeLoginButtonV();
}
private changeLoginButtonV() {
this.pageList.forEach(e => {
if (e.name === '登录' || e.name === '注册') {
if (this.userInfo) {
e.show = false;
} else {
e.show = (this.showList && window.innerWidth < this.mobileMaxWidth);
}
}
});
}
dealLink(path: string) {
this.showList = window.innerWidth > this.mobileMaxWidth;
@@ -136,7 +124,20 @@ export class HeaderComponent implements OnInit {
}
toAdminPage() {
this.router.navigateByUrl('/admin')
this.router.navigateByUrl('/admin');
}
private changeLoginButtonV() {
this.pageList.forEach(e => {
if (e.name === '登录' || e.name === '注册') {
if (this.userInfo) {
e.show = false;
} else {
e.show = (this.showList && window.innerWidth < this.mobileMaxWidth);
}
}
});
}
}

View File

@@ -1,24 +1,25 @@
import {Injectable} from '@angular/core';
import {filter} from 'rxjs/operators';
import {NavigationEnd, Router, RouterEvent} from '@angular/router';
import {Observable, of, Subscriber} from 'rxjs';
import {Observable, Subscriber} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ComponentStateService {
constructor(private router: Router) {
this.watchRouterChange()
}
visible = {
header: true,
footer: true,
globalBackToTop: true
};
currentPath: string;
constructor(private router: Router) {
this.watchRouterChange();
}
currentPath: string
getCurrentRouterPath = () => this.currentPath;
watchRouterChange() {
@@ -31,28 +32,30 @@ export class ComponentStateService {
// lastIndexOf ==> 0/index
const indexOf = path.lastIndexOf('/');
const prefix = path.substr(0, indexOf === 0 ? path.length : indexOf);
this.dealWithPathChange(prefix)
this.dealWithPathChange(prefix);
this.currentPath = prefix;
if (subscriber) subscriber.next(prefix)
if (subscriber) {
subscriber.next(prefix);
}
});
return ob;
}
private dealWithPathChange(path) {
// tslint:disable-next-line:forin
// eslint-disable-next-line guard-for-in
for (const visibleKey in this.visible) {
this.visible[visibleKey] = true
this.visible[visibleKey] = true;
}
switch (path) {
case '/admin':
this.visible.header = false
this.visible.footer = false
this.visible.globalBackToTop = false
break
this.visible.header = false;
this.visible.footer = false;
this.visible.globalBackToTop = false;
break;
case '/user':
case '/write':
this.visible.footer = false
this.visible.globalBackToTop = false
this.visible.footer = false;
this.visible.globalBackToTop = false;
break;
default:

View File

@@ -0,0 +1,79 @@
import {Injectable, Injector} from '@angular/core';
import {RequestObj, Response} from '../class/HttpReqAndResp';
import {environment} from '../../environments/environment';
import {Router} from '@angular/router';
import {ComponentStateService} from './component-state.service';
import {NzNotificationService} from 'ng-zorro-antd/notification';
import {HttpService} from '../api/http/http.service';
import {LocalStorageService} from './local-storage.service';
@Injectable({
providedIn: 'root'
})
export class ErrorService {
private static httpErrorCount: number = 0;
private readonly maintainPagePrefix = '/maintain';
private readonly adminPagePrefix = '/admin';
constructor(/*private httpService: HttpService,*/
private router: Router,
private injector: Injector,
private componentStateService: ComponentStateService,
private notification: NzNotificationService,
private localStorageService: LocalStorageService) {
}
public httpError(err: any, request: RequestObj) {
if (!environment.production) {
console.log('error=>', err, request);
}
ErrorService.httpErrorCount++;
// this.httpService.getSubscriptionQueue().map(a => a.unsubscribe())
}
public httpException(response: Response<any>, request: RequestObj) {
if (!environment.production) {
console.log('exception=>', response, request);
}
if (response.code === -1 && response.msg === '重复请求') {
return;
}
if (this.componentStateService.currentPath === this.adminPagePrefix) {
this.notification.create('error', `请求失败<${response.code}>`, `${response.msg}`);
}
/***
* 3700, "登陆过期"
* 3710, "账户已注销"
* 3711, "账户不可用"
* 3800, "密码不正确"
* 3810, "Token过期"
* 3820, "Token格式不对"
* 3820, "Token格式不对"
* 3830, "Token签名错误"
* 3840, "不支持的Token"
*/
if (response.code > 3700 && response.code < 3900) {
this.localStorageService.removeToken();
}
}
public checkConnection() {
// The HTTP_ERROR_COUNT is start with 1 in this function
if (ErrorService.httpErrorCount === 1) {
const req: RequestObj = {
path: '/headerInfo',
method: 'GET',
url: environment.host + '/headerInfo'
};
this.injector.get(HttpService).get(req).subscribe({
next: () => null,
error: () => {
if (this.componentStateService.currentPath !== this.maintainPagePrefix) {
this.router.navigateByUrl(this.maintainPagePrefix);
}
ErrorService.httpErrorCount = 0;
}
});
}
}
}

View File

@@ -10,10 +10,6 @@ import {LocalStorageService} from './local-storage.service';
})
export class GlobalUserService {
constructor(private apiService: ApiService,
private localStorageService: LocalStorageService) {
}
private lastRequestTime: number;
private userInfo: User = null;
@@ -21,26 +17,29 @@ export class GlobalUserService {
private userObserverArray: Observer<Response<User>>[] = [];
private multicastArray: Observer<Response<User>>[] = [];
constructor(private apiService: ApiService,
private localStorageService: LocalStorageService) {
}
watchUserInfo(observer: Observer<Response<User>>) {
if (this.userObserverArray.indexOf(observer) < 0) this.userObserverArray.push(observer);
if (this.userObserverArray.indexOf(observer) < 0) {this.userObserverArray.push(observer);}
this.multicastArray = [...this.userObserverArray];
let subscription: Subscription = null;
const unsubscribe = () => {
this.userObserverArray.splice(this.userObserverArray.indexOf(observer), 1);
observer.complete();
if (subscription) subscription.unsubscribe();
if (subscription) {subscription.unsubscribe();}
};
if (this.lastRequestTime && Date.now() - this.lastRequestTime < 3000) {
if (this.userInfo && this.multicastArray.length) {
this.broadcast()
this.broadcast();
this.lastRequestTime = Date.now();
}
return {unsubscribe}
return {unsubscribe};
}
// 获取数据
subscription = this.getUserInfoFromServer();
return {unsubscribe}
return {unsubscribe};
}
// 刷新用户信息
@@ -59,7 +58,7 @@ export class GlobalUserService {
// this.localStorageService.setUser(o.result);
// this.userObserver.next(o);
this.userInfo = o.result;
this.broadcast()
this.broadcast();
observer.next(o);
observer.complete();
},
@@ -82,7 +81,7 @@ export class GlobalUserService {
// 如果不需要返回消息也ok
this.apiService.logout().subscribe(data => {
this.localStorageService.clear();
this.broadcast()
this.broadcast();
if (observer) {
observer.next(data);
observer.complete();
@@ -93,7 +92,7 @@ export class GlobalUserService {
observer.error(error);
observer.complete();
}
})
});
}
getUserInfoFromServer(observer?: Observer<Response<User>>) {
@@ -102,7 +101,7 @@ export class GlobalUserService {
this.lastRequestTime = Date.now();
this.userInfo = o.result;
// this.localStorageService.setUser(o.result);
this.broadcast()
this.broadcast();
if (observer) {
observer.next(o);
observer.complete();
@@ -118,12 +117,12 @@ export class GlobalUserService {
if (err.code === -1) {
// 请求重复
return
return;
}
// this.requested = false;
// this.localStorageService.removeToken();
this.multicastArray.forEach(ob => ob.next(new Response<User>(this.userInfo)))
this.multicastArray.forEach(ob => ob.error(err))
this.multicastArray.forEach(ob => ob.next(new Response<User>(this.userInfo)));
this.multicastArray.forEach(ob => ob.error(err));
this.multicastArray.splice(0, this.multicastArray.length);
}
@@ -131,7 +130,7 @@ export class GlobalUserService {
}
private broadcast() {
this.multicastArray.forEach(ob => ob.next(new Response<User>(this.userInfo)))
this.multicastArray.forEach(ob => ob.next(new Response<User>(this.userInfo)));
this.multicastArray.splice(0, this.multicastArray.length);
}
}

View File

@@ -1,34 +1,65 @@
import {Injectable} from '@angular/core';
import {User} from '../class/User';
import {Base64} from 'js-base64';
@Injectable({
providedIn: 'root'
})
export class LocalStorageService {
readonly place = 30 * 1000;
constructor() {
}
// 30s
readonly place = 30 * 1000;
getToken(): string {
return localStorage.getItem('token');
const item = this.getItem('token');
if (!item) {
return null;
}
return 'Bearer ' + item;
}
setToken(token: string) {
localStorage.setItem('t', new Date().valueOf().toString());
localStorage.setItem('token', token);
const t = new Date().valueOf().toString();
this.setItem('t', t);
if (token.startsWith('Bearer')) {
token = token.replace('Bearer', '');
}
if (token.startsWith('bearer')) {
token = token.replace('bearer', '');
}
this.setItem('token', token);
}
removeToken() {
localStorage.removeItem('token');
this.removeItem('token');
}
isLogin() {
return this.getToken() != null;
}
setItem(key: string, value: any) {
localStorage.setItem(key, Base64.encode(value));
}
getItem(key: string) {
const item = localStorage.getItem(key);
let decode;
try {
decode = Base64.decode(item);
return item ? decode : null;
} catch (e) {
localStorage.removeItem(key);
return item;
}
}
removeItem(key: string) {
localStorage.removeItem(key);
}
// setUser(user: User) {
// // TODO: 简单加个密
// localStorage.setItem('t', new Date().valueOf().toString());

View File

@@ -1,4 +1,9 @@
export const ColorList: { bgColor: string, fontColor: string }[] = [
export class Color {
bgColor: string;
fontColor: string;
}
export const COLOR_LIST: Color[] = [
{bgColor: '#7bcfa6', fontColor: '#000000'}, // 石青
{bgColor: '#bce672', fontColor: '#000000'}, // 松花色
{bgColor: '#ff8936', fontColor: '#000000'}, // 橘黄
@@ -7,3 +12,28 @@ export const ColorList: { bgColor: string, fontColor: string }[] = [
{bgColor: '#3eede7', fontColor: '#000000'}, // 碧蓝
{bgColor: '#177cb0', fontColor: '#ffffff'}, // 靛青
];
export const COLOR_LIST_LENGTH = COLOR_LIST.length;
/**
* 获取一组随机颜色
*
* @param count 数量
*/
export function randomColor(count: number = 1): Color[] {
const map = new Map<number, number>();
COLOR_LIST.forEach((color, index) => map.set(index, 0));
const colorArray: Color[] = [];
const oneRandomColor = () => {
const minValue = Math.min.apply(null, Array.from(map.values()));
const keys = Array.from(map.keys()).filter(key => map.get(key) === minValue);
const keyIndex = Math.floor(Math.random() * keys.length);
const index = keys[keyIndex];
map.set(index, minValue + 1);
return COLOR_LIST[index];
};
for (let i = 0; i < count; i++) {
colorArray.push(oneRandomColor());
}
return colorArray;
}

View File

@@ -3,6 +3,7 @@ import {PageList} from '../class/HttpReqAndResp';
/**
* 判断 一个Page<any>[] 中是否存在一条已查询的数据
*
* @param pageNum 页码
* @param pageSize 单页数量
* @param pageList 源数据
@@ -12,14 +13,14 @@ export function exist<T>(pageNum: number, pageSize: number, pageList: PageList<a
if (pageList === undefined || pageList == null || pageList.length === 0) {
return null;
}
// tslint:disable-next-line:prefer-for-of
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < pageList.length; i++) {
// tslint:disable-next-line:triple-equals
// eslint-disable-next-line eqeqeq
if (pageList[i].pageNum == pageNum && pageList[i].pageSize == pageSize) {
const ob: Observable<PageList<T>> = new Observable(o => {
o.next(pageList[i]);
o.complete();
})
});
}
}
return null;

View File

@@ -1,11 +1,12 @@
export class SvgIconUtil {
// eslint-disable-next-line max-len
static readonly nameIcon = '<svg t="1581933298087" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3223" width="200" height="200"><path d="M983.04 163.84H40.96c-24.576 0-40.96 16.384-40.96 40.96v614.4c0 20.48 16.384 40.96 40.96 40.96h942.08c20.48 0 40.96-20.48 40.96-40.96V204.8c0-24.576-20.48-40.96-40.96-40.96zM253.952 749.568c0-102.4 61.44-192.512 147.456-233.472-28.672-24.576-45.056-61.44-45.056-102.4 0-77.824 65.536-143.36 143.36-143.36s143.36 65.536 143.36 143.36c0 40.96-12.288 73.728-36.864 98.304 94.208 36.864 163.84 131.072 163.84 237.568H253.952z" p-id="3224" fill="#1296db"></path></svg>';
// eslint-disable-next-line max-len
static readonly locationIcon = '<svg t="1581933583276" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3981" width="200" height="200"><path d="M511.932268 0c-213.943865 0-387.880498 170.933833-387.880499 381.06211 0 164.815346 238.869364 485.098975 341.66447 620.247558a58.249807 58.249807 0 0 0 46.216029 22.690332c18.129688 0 35.491743-8.443964 46.328916-22.690332 102.704796-135.126006 341.709624-455.432213 341.709624-620.247558C899.970808 170.933833 725.89871 0 511.932268 0z m0 519.574733c-91.393496 0-165.786176-72.902569-165.786176-162.670489 0-89.722765 74.39268-162.738221 165.786176-162.73822 91.438651 0 165.718443 73.015456 165.718443 162.73822 0 89.76792-74.279793 162.670488-165.718443 162.670489z" fill="#1296db" p-id="3982"></path></svg>';
constructor() {
}
// tslint:disable-next-line:max-line-length
static readonly nameIcon = '<svg t="1581933298087" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3223" width="200" height="200"><path d="M983.04 163.84H40.96c-24.576 0-40.96 16.384-40.96 40.96v614.4c0 20.48 16.384 40.96 40.96 40.96h942.08c20.48 0 40.96-20.48 40.96-40.96V204.8c0-24.576-20.48-40.96-40.96-40.96zM253.952 749.568c0-102.4 61.44-192.512 147.456-233.472-28.672-24.576-45.056-61.44-45.056-102.4 0-77.824 65.536-143.36 143.36-143.36s143.36 65.536 143.36 143.36c0 40.96-12.288 73.728-36.864 98.304 94.208 36.864 163.84 131.072 163.84 237.568H253.952z" p-id="3224" fill="#1296db"></path></svg>';
// tslint:disable-next-line:max-line-length
static readonly locationIcon = '<svg t="1581933583276" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3981" width="200" height="200"><path d="M511.932268 0c-213.943865 0-387.880498 170.933833-387.880499 381.06211 0 164.815346 238.869364 485.098975 341.66447 620.247558a58.249807 58.249807 0 0 0 46.216029 22.690332c18.129688 0 35.491743-8.443964 46.328916-22.690332 102.704796-135.126006 341.709624-455.432213 341.709624-620.247558C899.970808 170.933833 725.89871 0 511.932268 0z m0 519.574733c-91.393496 0-165.786176-72.902569-165.786176-162.670489 0-89.722765 74.39268-162.738221 165.786176-162.73822 91.438651 0 165.718443 73.015456 165.718443 162.73822 0 89.76792-74.279793 162.670488-165.718443 162.670489z" fill="#1296db" p-id="3982"></path></svg>';
}

View File

@@ -1,32 +1,32 @@
<common-table cardTitle="文章管理"
#commonTableComponent
[headData]="headData"
[request]="request"
[template]="{
<common-table #commonTableComponent
[headData]="headData"
[request]="request"
[template]="{
original:{temp:original,param:{true:'原创',false:'转载'}},
readingNumber:{temp:readingNumber},
likeCount:{temp:likeCount},
dislikeCount:{temp:dislikeCount},
open:{temp:open}
}">
}"
cardTitle="文章管理">
</common-table>
<ng-template let-value="value" let-originValue="originValue" #original>
<ng-template #original let-originValue="originValue" let-value="value">
<nz-tag [nzColor]="originValue?'green':'#ff5500'">{{value}}</nz-tag>
</ng-template>
<ng-template let-value="value" #readingNumber>
<ng-template #readingNumber let-value="value">
<nz-tag nzColor="purple">{{value}}</nz-tag>
</ng-template>
<ng-template let-value="value" #likeCount>
<ng-template #likeCount let-value="value">
<nz-tag nzColor="blue">{{value}}</nz-tag>
</ng-template>
<ng-template let-value="value" #dislikeCount>
<ng-template #dislikeCount let-value="value">
<nz-tag nzColor="magenta">{{value}}</nz-tag>
</ng-template>
<ng-template #open let-value="value">
<label nz-checkbox nzDisabled [ngModel]="value"></label>
<label [ngModel]="value" nz-checkbox nzDisabled></label>
</ng-template>

View File

@@ -1,5 +1,5 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {NzMessageService} from 'ng-zorro-antd/message';
import {ApiService} from '../../../api/api.service';
import {RequestObj} from '../../../class/HttpReqAndResp';
import {Article} from '../../../class/Article';
@@ -14,6 +14,10 @@ import {Router} from '@angular/router';
})
export class AdminArticleComponent implements OnInit {
@ViewChild('commonTableComponent') private commonTableComponent: CommonTableComponent<Article>;
request: RequestObj;
headData: Data<Article>[];
constructor(private apiService: ApiService, private nzMessage: NzMessageService, private title: Title,
private router: Router) {
this.request = {
@@ -23,15 +27,11 @@ export class AdminArticleComponent implements OnInit {
page: 1,
count: 10
}
}
};
}
request: RequestObj;
headData: Data<Article>[]
@ViewChild('commonTableComponent') private commonTableComponent: CommonTableComponent<Article>
ngOnInit(): void {
this.title.setTitle('小海博客 | 文章管理')
this.title.setTitle('小海博客 | 文章管理');
this.headData = [
{title: '主键', fieldValue: 'id', show: false, primaryKey: true},
{title: '标题', fieldValue: 'title', show: true},
@@ -54,18 +54,18 @@ export class AdminArticleComponent implements OnInit {
{name: '编辑', color: '#2db7f5', click: (d) => this.router.navigateByUrl(`/write?id=${d.id}`)},
]
}
]
];
}
deleteArticle(article: Article) {
this.apiService.deleteArticle(article.id).subscribe({
next: data => {
this.nzMessage.success('删除成功')
this.nzMessage.success('删除成功');
this.commonTableComponent.getData();
},
error: err => {
this.nzMessage.error(err.msg)
this.nzMessage.error(err.msg);
}
})
});
}
}

View File

@@ -4,7 +4,8 @@ import {RouterModule} from '@angular/router';
import {AdminArticleComponent} from './admin-article.component';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {FormsModule} from '@angular/forms';
import {NzCheckboxModule, NzTagModule} from 'ng-zorro-antd';
import {NzCheckboxModule} from 'ng-zorro-antd/checkbox';
import {NzTagModule} from 'ng-zorro-antd/tag';
@NgModule({
declarations: [

View File

@@ -1,44 +1,44 @@
<common-table #commonTableComponent
[request]="request"
[headData]="headData"
cardTitle="评论管理"
[template]="{status:{temp:status,param:{'0':' 正常 ','3':'已删除'}},content:{temp:content}}">
[request]="request"
[template]="{status:{temp:status,param:{'0':' 正常 ','3':'已删除'}},content:{temp:content}}"
cardTitle="评论管理">
</common-table>
<ng-template let-originValue="originValue" let-value="value" #status>
<nz-tag nzColor="geekblue" *ngIf="originValue==0">{{value}}</nz-tag>
<nz-tag nzColor="#f50" *ngIf="originValue==3">{{value}}</nz-tag>
<ng-template #status let-originValue="originValue" let-value="value">
<nz-tag *ngIf="originValue==0" nzColor="geekblue">{{value}}</nz-tag>
<nz-tag *ngIf="originValue==3" nzColor="#f50">{{value}}</nz-tag>
</ng-template>
<ng-template #content let-value="value" let-data="data">
<ng-template #content let-data="data" let-value="value">
<editable-tag #editableTagComponent
(modalOK)="textChange($event,data)"
[key]="data.id"
[showBorder]="false"
[text]="value"
[showConfirmModal]="true"
(modalOK)="textChange($event,data)">
[text]="value">
</editable-tag>
</ng-template>
<nz-modal nzTitle="查看" [nzClosable]="true" [(nzVisible)]="modalData.visible" (nzOnOk)="modalData.visible=false"
[nzCancelText]="null">
<nz-modal (nzOnOk)="modalData.visible=false" [(nzVisible)]="modalData.visible" [nzCancelText]="null" [nzClosable]="true"
nzTitle="查看">
<ng-template #commentTemplateRef let-comment="comment">
<nz-comment [nzAuthor]="comment && comment.fromUser.displayName" [nzDatetime]="comment&&comment.date">
<nz-avatar nz-comment-avatar nzIcon="user"
[nzSrc]="comment && comment.fromUser && comment.fromUser.avatarImgUrl"></nz-avatar>
<nz-avatar [nzSrc]="comment && comment.fromUser && comment.fromUser.avatarImgUrl" nz-comment-avatar
nzIcon="user"></nz-avatar>
<nz-comment-content>
<p>{{ comment && comment.content }}</p>
</nz-comment-content>
<!-- <nz-comment-action>Reply to</nz-comment-action>-->
<!-- <nz-comment-action>Reply to</nz-comment-action>-->
<ng-container *ngIf="comment&&comment.children && comment.children.length">
<ng-template ngFor let-child [ngForOf]="comment&&comment.children">
<ng-template [ngTemplateOutlet]="commentTemplateRef" [ngTemplateOutletContext]="{ comment: child }">
<ng-template [ngForOf]="comment&&comment.children" let-child ngFor>
<ng-template [ngTemplateOutletContext]="{ comment: child }" [ngTemplateOutlet]="commentTemplateRef">
</ng-template>
</ng-template>
</ng-container>
</nz-comment>
</ng-template>
<ng-template [ngTemplateOutlet]="commentTemplateRef" [ngTemplateOutletContext]="{ comment: modalData.comment }">
<ng-template [ngTemplateOutletContext]="{ comment: modalData.comment }" [ngTemplateOutlet]="commentTemplateRef">
</ng-template>
</nz-modal>

View File

@@ -1,5 +1,5 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {NzMessageService} from 'ng-zorro-antd/message';
import {ApiService} from '../../../api/api.service';
import {RequestObj} from '../../../class/HttpReqAndResp';
import {Comment, CommentReq} from '../../../class/Comment';
@@ -15,17 +15,30 @@ import {CommonTableComponent} from '../components/common-table/common-table.comp
})
export class AdminCommentComponent implements OnInit {
@ViewChild('editableTagComponent') editableTagComponent: EditableTagComponent;
@ViewChild('commonTableComponent') commonTableComponent: CommonTableComponent<Comment>;
request: RequestObj;
editInfo = {
id: null,
content: new CommentReq(null),
};
headData: Data<Comment>[];
modalData = {
visible: false,
comment: null
};
constructor(private apiService: ApiService, private messageService: NzMessageService, private userService: GlobalUserService,
private title: Title) {
this.title.setTitle('小海博客 | 评论管理')
this.title.setTitle('小海博客 | 评论管理');
this.userService.watchUserInfo({
next: data => {
let pathStr;
if (data.result) {
if (data.result.role === 'admin') {
pathStr = '/admin/comment/pagePath/*'
pathStr = '/admin/comment/pagePath/*';
} else {
pathStr = '/user/comment/pagePath/*'
pathStr = '/user/comment/pagePath/*';
}
this.request = {
path: pathStr,
@@ -34,27 +47,14 @@ export class AdminCommentComponent implements OnInit {
page: 1,
count: 10
}
}
};
}
},
error: () => null,
complete: () => null
})
});
}
request: RequestObj;
editInfo = {
id: null,
content: new CommentReq(null),
}
headData: Data<Comment>[];
modalData = {
visible: false,
comment: null
}
@ViewChild('editableTagComponent') editableTagComponent: EditableTagComponent;
@ViewChild('commonTableComponent') commonTableComponent: CommonTableComponent<Comment>;
ngOnInit(): void {
this.headData = [
{title: '主键', fieldValue: 'id', show: false, primaryKey: true},
@@ -74,7 +74,7 @@ export class AdminCommentComponent implements OnInit {
{
name: '查看',
click: data => {
this.modalData.visible = true
this.modalData.visible = true;
this.modalData.comment = data;
}
},
@@ -88,13 +88,13 @@ export class AdminCommentComponent implements OnInit {
deleteComment(data: Comment) {
if (data.status === 3) {
this.messageService.error('该数据已被删除');
return
return;
}
this.apiService.deleteComment(data.id).subscribe({
next: () => this.messageService.success('删除评论成功'),
error: err => this.messageService.error(err.msg),
complete: () => this.commonTableComponent.getData()
})
});
}
edit() {
@@ -106,7 +106,7 @@ export class AdminCommentComponent implements OnInit {
this.messageService.success(err.msg);
},
complete: () => null
})
});
}
textChange(value: { value: string; originalValue: string; changed: boolean }, data: Comment) {
@@ -115,7 +115,7 @@ export class AdminCommentComponent implements OnInit {
this.editInfo.content.pid = data.pid;
this.editInfo.content.id = data.id;
this.editInfo.content.content = value.value;
this.edit()
this.edit();
}
}
}

View File

@@ -3,7 +3,10 @@ import {CommonModule} from '@angular/common';
import {RouterModule} from '@angular/router';
import {AdminCommentComponent} from './admin-comment.component';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {NzAvatarModule, NzCommentModule, NzModalModule, NzTagModule} from 'ng-zorro-antd';
import {NzAvatarModule} from 'ng-zorro-antd/avatar';
import {NzCommentModule} from 'ng-zorro-antd/comment';
import {NzModalModule} from 'ng-zorro-antd/modal';
import {NzTagModule} from 'ng-zorro-antd/tag';
import {EditableTagModule} from '../components/editable-tag/editable-tag.module';

View File

@@ -1,6 +1,6 @@
<div *ngIf="userInfo&&userInfo.role==='admin'">
<div nz-row>
<nz-card nzTitle="统计" nz-col nzXs="24" nzSm="12" nzSize="small">
<nz-card nz-col nzSize="small" nzSm="12" nzTitle="统计" nzXs="24">
<nz-row [nzGutter]="24">
<nz-col [nzSpan]="6">
<nz-statistic [nzValue]="(counts.articleCount | number)!" nzTitle="文章数量"></nz-statistic>
@@ -16,7 +16,7 @@
</nz-col>
</nz-row>
</nz-card>
<nz-card nzTitle="信息" nz-col nzXs="24" [nzSm]="{span:11,offset:1}" nzSize="small">
<nz-card [nzSm]="{span:11,offset:1}" nz-col nzSize="small" nzTitle="信息" nzXs="24">
<nz-row [nzGutter]="24">
<nz-col [nzSpan]="8">
<nz-statistic [nzValue]="(counts.visitorCount | number)!" nzTitle="总访问量"></nz-statistic>
@@ -32,9 +32,9 @@
</nz-card>
</div>
<div nz-row>
<nz-card style="width: 100%" nzSize="small" nzTitle="日志" [nzExtra]="reload">
<nz-card [nzExtra]="reload" nzSize="small" nzTitle="日志" style="width: 100%">
<ng-template #reload>
<a (click)="getLog()" title="刷新"><i nz-icon nzType="reload" nzTheme="outline"></i></a>
<a (click)="getLog()" title="刷新"><i nz-icon nzTheme="outline" nzType="reload"></i></a>
</ng-template>
<nz-spin [nzSpinning]="logLoading" style="width: 100%;">
<pre style="width: 100%;max-height: 500px;overflow: auto;">{{logText}}</pre>
@@ -44,11 +44,11 @@
</div>
<div *ngIf="userInfo&&userInfo.role==='user'">
<div nz-row>
<nz-card nzTitle="信息" nz-col nzXs="24" [nzMd]="{span:11}" [nzXl]="{span:6,offset:1}" nzSize="small">
<nz-card [nzMd]="{span:11}" [nzXl]="{span:6,offset:1}" nz-col nzSize="small" nzTitle="信息" nzXs="24">
<nz-statistic [nzValue]="userInfo.recentlyLandedDate?userInfo.recentlyLandedDate:''"
nzTitle="上次登录"></nz-statistic>
</nz-card>
<nz-card nzTitle="关于此博客" nzSize="small" nz-col nzXs="24" [nzMd]="{span:11,offset:2}" [nzXl]="{span:6,offset:2}">
<nz-card [nzMd]="{span:11,offset:2}" [nzXl]="{span:6,offset:2}" nz-col nzSize="small" nzTitle="关于此博客" nzXs="24">
<p>此博客由 <a href="https://github.com/xiaohai2271" target="_blank">禾几海(郑海)</a> 设计并实现的</p>
<p>博客自2019年3月开始开发编写 5月开始正式运行至今</p>
<p>博客所有代码都是开源的,你可以随意修改,运行和发布</p>
@@ -59,7 +59,7 @@
</p>
<p>如果觉得博客还不错请前往Github支持我给我点一个star吧</p>
</nz-card>
<nz-card nz-col nzXs="24" [nzMd]="{span:12,offset:6}" [nzXl]="{span:6,offset:2}">
<nz-card [nzMd]="{span:12,offset:6}" [nzXl]="{span:6,offset:2}" nz-col nzXs="24">
<p style="font-style: italic">坚强的信心,能使平凡的人做出惊人的事业。</p>
<p style="text-align: right"> ——马尔顿</p>
</nz-card>

View File

@@ -11,47 +11,46 @@ import {Title} from '@angular/platform-browser';
styleUrls: ['./admin-dashboard.component.less']
})
export class AdminDashboardComponent implements OnInit {
logLoading: boolean = true;
logText: string = null;
counts: {
articleCount: number;
visitorCount: number;
categoryCount: number;
tagCount: number;
commentCount: number;
} = {articleCount: 0, visitorCount: 0, categoryCount: 0, tagCount: 0, commentCount: 0};
dayVisitCount: number = 0;
userInfo: User = new User();
private isRequested: boolean = false;
constructor(private apiService: ApiService, private userService: GlobalUserService, private http: HttpClient,
private title: Title) {
this.title.setTitle('小海博客 | 后台管理');
this.getUserInfo();
}
logLoading: boolean = true;
logText: string = null;
counts: {
articleCount: number,
visitorCount: number,
categoryCount: number,
tagCount: number,
commentCount: number
} = {articleCount: 0, visitorCount: 0, categoryCount: 0, tagCount: 0, commentCount: 0}
dayVisitCount: number = 0;
userInfo: User = new User();
private isRequested: boolean = false;
ngOnInit(): void {
}
getLog() {
this.http.get('https://api.celess.cn/blog.log', {responseType: 'text'}).subscribe(data => {
this.logText = data;
this.logLoading = false
this.logLoading = false;
});
}
getCounts = () => this.apiService.counts().subscribe({
next: data => this.counts = data.result
})
});
getDayVisitCount = () => this.apiService.dayVisitCount().subscribe({
next: data => this.dayVisitCount = data.result
})
});
getUserInfo = () => this.userService.watchUserInfo({
next: data => {
this.userInfo = data.result
this.userInfo = data.result;
if (data.result && data.result.role === 'admin' && !this.isRequested) {
this.getLog();
this.getCounts();
@@ -61,5 +60,5 @@ export class AdminDashboardComponent implements OnInit {
},
error: () => null,
complete: () => null
})
});
}

View File

@@ -2,15 +2,13 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AdminDashboardComponent} from './admin-dashboard.component';
import {RouterModule} from '@angular/router';
import {
NzButtonModule,
NzCardModule,
NzDividerModule,
NzGridModule,
NzIconModule,
NzSpinModule,
NzStatisticModule
} from 'ng-zorro-antd';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzCardModule} from 'ng-zorro-antd/card';
import {NzDividerModule} from 'ng-zorro-antd/divider';
import {NzGridModule} from 'ng-zorro-antd/grid';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzSpinModule} from 'ng-zorro-antd/spin';
import {NzStatisticModule} from 'ng-zorro-antd/statistic';
@NgModule({

View File

@@ -1,33 +1,34 @@
<common-table #commonTableComponent
cardTitle="友链管理"
[request]="request"
[headData]="headData"
[request]="request"
[template]="{open:{temp:open,param:{true:'可见',false:'不可见'}},delete:{temp:deleteTemp,param:{true:'已删除',false:'未删除'}}}"
cardTitle="友链管理"
>
<button (click)="addLink()" nz-button>添加</button>
</common-table>
<ng-template #open let-value="value">
<label nz-checkbox nzDisabled [ngModel]="value"></label>
<label [ngModel]="value" nz-checkbox nzDisabled></label>
</ng-template>
<ng-template let-value="value" let-originValue="originValue" #deleteTemp>
<nz-tag [nzColor]="'blue'" *ngIf="originValue=='false'">{{value}}</nz-tag>
<nz-tag [nzColor]="'#ff5500'" *ngIf="originValue!='false'">{{value}}</nz-tag>
<ng-template #deleteTemp let-originValue="originValue" let-value="value">
<nz-tag *ngIf="originValue=='false'" [nzColor]="'blue'">{{value}}</nz-tag>
<nz-tag *ngIf="originValue!='false'" [nzColor]="'#ff5500'">{{value}}</nz-tag>
</ng-template>
<nz-modal [(nzVisible)]="modalVisible" [nzTitle]="modalTitle" (nzOnOk)="modalConfirm()"
(nzOnCancel)="modalVisible = false" [nzClosable]="true" [nzOkDisabled]="!formGroup.valid">
<form nz-form [formGroup]="formGroup">
<nz-modal (nzOnCancel)="modalVisible = false" (nzOnOk)="modalConfirm()" [(nzVisible)]="modalVisible"
[nzClosable]="true" [nzOkDisabled]="!formGroup.valid" [nzTitle]="modalTitle">
<form [formGroup]="formGroup" nz-form>
<nz-form-item>
<nz-form-label nzRequired>网站名称</nz-form-label>
<nz-form-control nzErrorTip="网站名称不可为空">
<input nz-input formControlName="name">
<nz-form-label nzFlex="80px" nzRequired>网站名称</nz-form-label>
<nz-form-control nzErrorTip="网站名称不可为空" nzFlex="auto">
<input formControlName="name" nz-input>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>网站链接</nz-form-label>
<nz-form-control [nzErrorTip]="nameErrTip">
<input nz-input formControlName="url">
<nz-form-label nzFlex="80px" nzRequired>网站链接</nz-form-label>
<nz-form-control [nzErrorTip]="nameErrTip" nzFlex="auto">
<input formControlName="url" nz-input>
<ng-template #nameErrTip>
<div *ngIf="formGroup.controls.url.hasError('required')">网站链接不可为空</div>
<div *ngIf="formGroup.controls.url.hasError('pattern')">网站链接格式不正确</div>
@@ -36,13 +37,32 @@
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>是否公开</nz-form-label>
<nz-form-control nzErrorTip="不可为空">
<nz-select nzPlaceHolder="请选择" formControlName="open" [nzAllowClear]="true">
<nz-form-label nzFlex="80px" nzRequired>是否公开</nz-form-label>
<nz-form-control nzErrorTip="不可为空" nzFlex="auto">
<nz-select [nzAllowClear]="true" formControlName="open" nzPlaceHolder="请选择">
<nz-option [nzValue]="true" nzLabel="公开"></nz-option>
<nz-option [nzValue]="false" nzLabel="不公开"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzFlex="80px">网站图标</nz-form-label>
<nz-form-control nzErrorTip="链接格式不正确" nzFlex="auto">
<nz-input-group [nzSuffix]="icon" nzSize="large">
<input formControlName="iconPath" nz-input>
</nz-input-group>
<ng-template #icon>
<img *ngIf="formGroup.value.iconPath" [src]="formGroup.value.iconPath"
alt="icon" style="width: 25px;height: 25px">
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzFlex="80px">网站描述</nz-form-label>
<nz-form-control nzErrorTip="可输入最大文字长度为255" nzFlex="auto">
<textarea [nzAutosize]="{ minRows: 2, maxRows: 6 }" formControlName="desc" nz-input></textarea>
</nz-form-control>
</nz-form-item>
</form>
</nz-modal>

View File

@@ -2,8 +2,8 @@ import {Component, OnInit, ViewChild} from '@angular/core';
import {RequestObj, Response} from '../../../class/HttpReqAndResp';
import {Link} from '../../../class/Link';
import {ApiService} from '../../../api/api.service';
import {NzMessageService} from 'ng-zorro-antd';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {NzMessageService} from 'ng-zorro-antd/message';
import {UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms';
import {Observable} from 'rxjs';
import {Title} from '@angular/platform-browser';
import {CommonTableComponent} from '../components/common-table/common-table.component';
@@ -15,25 +15,33 @@ import {Data} from '../components/common-table/data';
})
export class AdminLinkComponent implements OnInit {
constructor(private apiService: ApiService, private messageService: NzMessageService, private title: Title) {
this.title.setTitle('小海博客 | 友链管理');
this.formGroup = new FormGroup({
id: new FormControl(null),
name: new FormControl(null, [Validators.required]),
url: new FormControl(null, [Validators.required, Validators.pattern(/^(https:\/\/|http:\/\/|)([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?$/)]),
open: new FormControl(null, [Validators.required]),
oper: new FormControl(null)
})
}
@ViewChild('commonTableComponent') commonTableComponent: CommonTableComponent<Link>;
modalVisible: boolean = false;
modalTitle: string = '';
formGroup: FormGroup;
formGroup: UntypedFormGroup;
request: RequestObj;
@ViewChild('commonTableComponent') commonTableComponent: CommonTableComponent<Link>
headData: Data<Link>[];
constructor(private apiService: ApiService, private messageService: NzMessageService, private title: Title) {
this.title.setTitle('小海博客 | 友链管理');
this.formGroup = new UntypedFormGroup({
id: new UntypedFormControl(null),
name: new UntypedFormControl(null, [Validators.required]),
url: new UntypedFormControl(null, [
Validators.required,
Validators.pattern(/^(https:\/\/|http:\/\/|)([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?$/)
]
),
open: new UntypedFormControl(null, [Validators.required]),
desc: new UntypedFormControl(null, [Validators.maxLength(255)]),
iconPath: new UntypedFormControl(null, [
Validators.pattern(/^(https:\/\/|http:\/\/|)([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?$/)
]
),
oper: new UntypedFormControl(null)
});
}
ngOnInit(): void {
this.request = {
path: '/admin/links',
@@ -42,7 +50,7 @@ export class AdminLinkComponent implements OnInit {
count: 10,
page: 1
}
}
};
this.headData = [
{title: '主键', fieldValue: 'id', show: false, primaryKey: true},
{title: '友链名称', fieldValue: 'name', show: true},
@@ -71,25 +79,19 @@ export class AdminLinkComponent implements OnInit {
this.messageService.error('删除失败');
},
complete: () => null,
})
});
}
showEdit(data: Link) {
this.modalVisible = true;
this.modalTitle = '编辑友链信息';
this.formGroup.patchValue(data);
this.formGroup.controls.oper.setValue('edit')
this.formGroup.controls.oper.setValue('edit');
}
modalConfirm() {
this.modalVisible = false;
const linkReq: Link = new Link();
linkReq.name = this.formGroup.value.name;
linkReq.url = this.formGroup.value.url;
linkReq.open = this.formGroup.value.open;
// 暂时设置未空
linkReq.desc = '';
linkReq.iconPath = '';
const linkReq: Link = this.formGroup.value;
const oper = this.formGroup.value.oper;
let observable: Observable<Response<Link>>;
if (oper === 'edit') {
@@ -102,13 +104,13 @@ export class AdminLinkComponent implements OnInit {
next: data => this.messageService.success('操作成功'),
error: err => this.messageService.error('操作失败,' + err.msg),
complete: () => this.commonTableComponent.getData()
})
});
}
addLink() {
this.modalVisible = true;
this.modalTitle = '新增友链信息';
this.formGroup.reset();
this.formGroup.controls.oper.setValue('add')
this.formGroup.controls.oper.setValue('add');
}
}

View File

@@ -3,7 +3,13 @@ import {CommonModule} from '@angular/common';
import {RouterModule} from '@angular/router';
import {AdminLinkComponent} from './admin-link.component';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {NzCheckboxModule, NzFormModule, NzInputModule, NzModalModule, NzSelectModule, NzTagModule} from 'ng-zorro-antd';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzCheckboxModule} from 'ng-zorro-antd/checkbox';
import {NzFormModule} from 'ng-zorro-antd/form';
import {NzInputModule} from 'ng-zorro-antd/input';
import {NzModalModule} from 'ng-zorro-antd/modal';
import {NzSelectModule} from 'ng-zorro-antd/select';
import {NzTagModule} from 'ng-zorro-antd/tag';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
@@ -23,6 +29,7 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms';
NzInputModule,
NzSelectModule,
NzTagModule,
NzButtonModule,
]
})

View File

@@ -1,14 +1,14 @@
<div class="inner-content">
<nz-card nzTitle="" nzSize="small">
<nz-card nzSize="small" nzTitle="">
<nz-tabset [nzTabBarExtraContent]="reload">
<nz-tab nzTitle="分类管理" (nzClick)="tabChanged('tag')">
<nz-tab (nzClick)="tabChanged('tag')" nzTitle="分类管理">
<div style="margin-bottom: 15px;width: 150px">
<editable-tag [showBorder]="false"
[showEditIcon]="false"
[doubleClick]="false"
size="default"
<editable-tag (valueChange)="addCategory($event)"
[autoClear]="true"
(valueChange)="addCategory($event)"
[doubleClick]="false"
[showBorder]="false"
[showEditIcon]="false"
size="default"
>
<button nz-button>新增</button>
</editable-tag>
@@ -19,7 +19,7 @@
[template]="{name:{temp:nameTemplate}}">
</common-table>
</nz-tab>
<nz-tab nzTitle="标签管理" (nzClick)="tabChanged('category')">
<nz-tab (nzClick)="tabChanged('category')" nzTitle="标签管理">
<common-table #tagCTComponent
[headData]="tagCTData.headData"
[request]="tagCTData.request"
@@ -30,15 +30,15 @@
</nz-card>
</div>
<ng-template #reload>
<a (click)="getData()" title="刷新"><i nz-icon nzType="reload" nzTheme="outline"></i></a>
<a (click)="getData()" title="刷新"><i nz-icon nzTheme="outline" nzType="reload"></i></a>
</ng-template>
<ng-template #nameTemplate let-value="value" let-data="data">
<ng-template #nameTemplate let-data="data" let-value="value">
<editable-tag #editableTagComponent
(modalOK)="textChange($event,data)"
[key]="data.id"
[showBorder]="false"
[text]="value"
[showConfirmModal]="true"
(modalOK)="textChange($event,data)">
[text]="value">
</editable-tag>
</ng-template>

View File

@@ -1,8 +1,8 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {NzMessageService} from 'ng-zorro-antd/message';
import {Category, Tag} from '../../../class/Tag';
import {ApiService} from '../../../api/api.service';
import {PageList, RequestObj} from '../../../class/HttpReqAndResp';
import {RequestObj} from '../../../class/HttpReqAndResp';
import {Title} from '@angular/platform-browser';
import {Data} from '../components/common-table/data';
import {CommonTableComponent} from '../components/common-table/common-table.component';
@@ -15,27 +15,28 @@ import {EditableTagComponent} from '../components/editable-tag/editable-tag.comp
})
export class AdminTagComponent implements OnInit {
@ViewChild('categoryCTComponent', {static: true}) categoryCTComponent: CommonTableComponent<Category>;
@ViewChild('tagCTComponent', {static: true}) tagCTComponent: CommonTableComponent<Tag>;
@ViewChild('editableTagComponent') editableTagComponent: EditableTagComponent;
categoryCTData: { headData: Data<Category>[]; commonTable: CommonTableComponent<Category>; request: RequestObj } = {
headData: null,
commonTable: null,
request: null
};
tagCTData: { headData: Data<Category>[]; commonTable: CommonTableComponent<Tag>; request: RequestObj } = {
headData: null,
commonTable: null,
request: null
};
getData: any;
private updateData: any;
constructor(private apiService: ApiService, private nzMessageService: NzMessageService, private title: Title, private router: Router) {
}
categoryCTData: { headData: Data<Category>[], commonTable: CommonTableComponent<Category>, request: RequestObj } = {
headData: null,
commonTable: null,
request: null
}
tagCTData: { headData: Data<Category>[], commonTable: CommonTableComponent<Tag>, request: RequestObj } = {
headData: null,
commonTable: null,
request: null
}
@ViewChild('categoryCTComponent', {static: true}) categoryCTComponent: CommonTableComponent<Category>
@ViewChild('tagCTComponent', {static: true}) tagCTComponent: CommonTableComponent<Tag>
@ViewChild('editableTagComponent') editableTagComponent: EditableTagComponent
private updateData: any;
getData: any;
ngOnInit(): void {
this.title.setTitle('小海博客 | 标签分类管理')
this.title.setTitle('小海博客 | 标签分类管理');
this.categoryCTData = {
commonTable: this.categoryCTComponent,
headData: [
@@ -64,7 +65,7 @@ export class AdminTagComponent implements OnInit {
count: 1000
}
}
}
};
this.tagCTData = {
commonTable: this.tagCTComponent,
headData: [
@@ -87,7 +88,7 @@ export class AdminTagComponent implements OnInit {
count: 10
}
}
}
};
this.getData = this.categoryCTComponent.getData;
}
@@ -96,29 +97,29 @@ export class AdminTagComponent implements OnInit {
if (mode === 'tag') {
this.apiService.deleteTag(id).subscribe({
next: data => {
this.nzMessageService.success('删除成功')
this.nzMessageService.success('删除成功');
this.tagCTComponent.getData();
},
complete: () => null,
error: err => this.nzMessageService.error(err.msg)
})
});
} else if (mode === 'category') {
this.apiService.deleteCategory(id).subscribe({
next: data => {
this.nzMessageService.success('删除成功')
this.nzMessageService.success('删除成功');
this.categoryCTComponent.getData();
},
complete: () => null,
error: err => this.nzMessageService.error(err.msg)
})
});
}
}
addCategory($event: { value: string; originalValue: string; changed: boolean }) {
if (!$event.value || !$event.changed) return
if (!$event.value || !$event.changed) {return;}
this.apiService.createCategory($event.value).subscribe({
next: data => {
this.nzMessageService.success('新增成功')
this.nzMessageService.success('新增成功');
this.getData = this.categoryCTComponent.getData();
},
complete: () => null,
@@ -133,14 +134,14 @@ export class AdminTagComponent implements OnInit {
this.updateData = this.apiService.updateTag;
} else {
this.getData = this.tagCTComponent.getData;
this.updateData = this.apiService.updateCategory
this.updateData = this.apiService.updateCategory;
}
}
textChange(value: { value: string; originalValue: string; changed: boolean }, textData: Category | Tag) {
this.updateData(textData.id, value.value).subscribe({
next: data => {
this.nzMessageService.success('更新成功')
this.nzMessageService.success('更新成功');
this.tagCTComponent.getData();
this.categoryCTComponent.getData();
},

View File

@@ -5,7 +5,10 @@ import {AdminTagComponent} from './admin-tag.component';
import {FormsModule} from '@angular/forms';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {EditableTagModule} from '../components/editable-tag/editable-tag.module';
import {NzButtonModule, NzCardModule, NzIconModule, NzTabsModule} from "ng-zorro-antd";
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzCardModule} from 'ng-zorro-antd/card';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzTabsModule} from 'ng-zorro-antd/tabs';
@NgModule({

View File

@@ -1,8 +1,8 @@
<common-table [request]="request" [headData]="headData" cardTitle="更新管理">
<button nz-button (click)="showModal()">新增</button>
<common-table [headData]="headData" [request]="request" cardTitle="更新管理">
<button (click)="showModal()" nz-button>新增</button>
</common-table>
<nz-modal [(nzVisible)]="modalData.visible" [nzClosable]="true" (nzOnCancel)="modalData.visible = false"
(nzOnOk)="confirm()" [nzTitle]="modalData.title">
<textarea nz-input [(ngModel)]="modalData.content" [nzAutosize]="{ minRows: 2, maxRows: 8 }"></textarea>
<nz-modal (nzOnCancel)="modalData.visible = false" (nzOnOk)="confirm()" [(nzVisible)]="modalData.visible"
[nzClosable]="true" [nzTitle]="modalData.title">
<textarea [(ngModel)]="modalData.content" [nzAutosize]="{ minRows: 2, maxRows: 8 }" nz-input></textarea>
</nz-modal>

View File

@@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {NzMessageService} from 'ng-zorro-antd/message';
import {Title} from '@angular/platform-browser';
import {Observable} from 'rxjs';
import {ApiService} from '../../../api/api.service';
import {PageList, RequestObj, Response} from '../../../class/HttpReqAndResp';
import {RequestObj, Response} from '../../../class/HttpReqAndResp';
import {UpdateInfo} from '../../../class/UpdateInfo';
import {Data} from '../components/common-table/data';
@@ -14,9 +14,6 @@ import {Data} from '../components/common-table/data';
export class AdminUpdateComponent implements OnInit {
constructor(private apiService: ApiService, private nzMessage: NzMessageService, private title: Title) {
}
modalData = {
visible: false,
content: null,
@@ -26,8 +23,11 @@ export class AdminUpdateComponent implements OnInit {
headData: Data<UpdateInfo>[];
request: RequestObj;
constructor(private apiService: ApiService, private nzMessage: NzMessageService, private title: Title) {
}
ngOnInit(): void {
this.title.setTitle('小海博客 | 更新信息管理')
this.title.setTitle('小海博客 | 更新信息管理');
this.headData = [
{fieldValue: 'id', show: false, title: '主键', primaryKey: true},
{fieldValue: 'info', show: true, title: '更新内容'},
@@ -46,7 +46,7 @@ export class AdminUpdateComponent implements OnInit {
count: 1,
page: 10,
}
}
};
}
@@ -54,21 +54,21 @@ export class AdminUpdateComponent implements OnInit {
this.apiService.deleteWebUpdateInfo(id).subscribe({
next: data => this.nzMessage.success('删除成功'),
error: err => this.nzMessage.error(err.msg)
})
});
}
confirm() {
this.modalData.visible = false;
let observable: Observable<Response<UpdateInfo>>
let observable: Observable<Response<UpdateInfo>>;
if (this.modalData.id) {
observable = this.apiService.updateWebUpdateInfo(this.modalData.id, this.modalData.content)
observable = this.apiService.updateWebUpdateInfo(this.modalData.id, this.modalData.content);
} else {
observable = this.apiService.createWebUpdateInfo(this.modalData.content)
observable = this.apiService.createWebUpdateInfo(this.modalData.content);
}
observable.subscribe({
next: data => this.nzMessage.success('操作成功'),
error: err => this.nzMessage.error(err.msg)
})
});
}
showModal(data?: UpdateInfo) {

View File

@@ -5,7 +5,9 @@ import {AdminUpdateComponent} from './admin-update.component';
import {FormsModule} from '@angular/forms';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {NzButtonModule, NzInputModule, NzModalModule} from 'ng-zorro-antd';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzInputModule} from 'ng-zorro-antd/input';
import {NzModalModule} from 'ng-zorro-antd/modal';
@NgModule({

View File

@@ -1,56 +1,56 @@
<common-table [headData]="headData"
[request]="request"
cardTitle="用户信息管理"
[template]="{role:{temp:role},emailStatus:{temp:emailStatus,param:{true:'已验证',false:'未验证'}}}"
cardTitle="用户信息管理"
>
</common-table>
<ng-template let-value="value" #role>
<nz-tag [nzColor]="'blue'" *ngIf="value == 'admin'">{{value}}</nz-tag>
<nz-tag [nzColor]="'purple'" *ngIf="value == 'user'">{{value}}</nz-tag>
<ng-template #role let-value="value">
<nz-tag *ngIf="value == 'admin'" [nzColor]="'blue'">{{value}}</nz-tag>
<nz-tag *ngIf="value == 'user'" [nzColor]="'purple'">{{value}}</nz-tag>
</ng-template>
<ng-template let-value="value" let-originValue="originValue" #emailStatus>
<nz-tag [nzColor]="'green'" *ngIf="originValue !='false'">{{value}}</nz-tag>
<nz-tag [nzColor]="'red'" *ngIf="originValue !='true'">{{value}}</nz-tag>
<ng-template #emailStatus let-originValue="originValue" let-value="value">
<nz-tag *ngIf="originValue !='false'" [nzColor]="'green'">{{value}}</nz-tag>
<nz-tag *ngIf="originValue !='true'" [nzColor]="'red'">{{value}}</nz-tag>
</ng-template>
<nz-modal [(nzVisible)]="modalData.visible" [nzClosable]="true" [nzTitle]="modalData.title"
(nzOnCancel)="modalData.visible = false" (nzOnOk)="modalConfirm()"
<nz-modal (nzOnCancel)="modalData.visible = false" (nzOnOk)="modalConfirm()" [(nzVisible)]="modalData.visible"
[nzClosable]="true" [nzContent]="showContent"
[nzFooter]="modalData.isEdit?editContentFooter:showContentFooter"
[nzContent]="showContent">
[nzTitle]="modalData.title">
<ng-template #showContent>
<form nz-form [formGroup]="formGroup" (ngSubmit)="modalConfirm()">
<form (ngSubmit)="modalConfirm()" [formGroup]="formGroup" nz-form>
<nz-form-item>
<nz-form-label nzSpan="4" nzRequired>邮箱</nz-form-label>
<nz-form-label nzRequired nzSpan="4">邮箱</nz-form-label>
<nz-form-control nzSpan="18">
<input type="email" nz-input formControlName="email"
[disabled]="!modalData.isEdit">
<input [disabled]="!modalData.isEdit" formControlName="email" nz-input
type="email">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nzRequired>昵称</nz-form-label>
<nz-form-label nzRequired nzSpan="4">昵称</nz-form-label>
<nz-form-control nzSpan="18">
<input type="text" nz-input formControlName="displayName" [disabled]="!modalData.isEdit">
<input [disabled]="!modalData.isEdit" formControlName="displayName" nz-input type="text">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nzRequired>角色</nz-form-label>
<nz-form-label nzRequired nzSpan="4">角色</nz-form-label>
<nz-form-control nzSpan="18">
<nz-select formControlName="role" [nzDisabled]="!modalData.isEdit||formGroup.value.id==user.id">
<nz-option nzValue="admin" nzLabel="admin"></nz-option>
<nz-option nzValue="user" nzLabel="user"></nz-option>
<nz-select [nzDisabled]="!modalData.isEdit||formGroup.value.id==user.id" formControlName="role">
<nz-option nzLabel="admin" nzValue="admin"></nz-option>
<nz-option nzLabel="user" nzValue="user"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="4" nzRequired>状态</nz-form-label>
<nz-form-label nzRequired nzSpan="4">状态</nz-form-label>
<nz-form-control nzSpan="18">
<nz-radio-group formControlName="emailStatus" [nzDisabled]="!modalData.isEdit">
<label nz-radio [nzValue]="true">邮箱已验证</label>
<label nz-radio [nzValue]="false">邮箱未验证</label>
<nz-radio-group [nzDisabled]="!modalData.isEdit" formControlName="emailStatus">
<label [nzValue]="true" nz-radio>邮箱已验证</label>
<label [nzValue]="false" nz-radio>邮箱未验证</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
@@ -58,14 +58,14 @@
<nz-form-item *ngIf="modalData.isEdit">
<nz-form-label nzSpan="4">密码</nz-form-label>
<nz-form-control nzSpan="18">
<a *ngIf="!modalData.resetPwd" (click)="modalData.resetPwd = true">
重设密码<i nz-icon nzType="edit" nzTheme="twotone" style="margin-left: 10px;"></i>
<a (click)="modalData.resetPwd = true" *ngIf="!modalData.resetPwd">
重设密码<i nz-icon nzTheme="twotone" nzType="edit" style="margin-left: 10px;"></i>
</a>
<nz-input-group *ngIf="modalData.resetPwd" [nzSuffix]="cancelBtn" nzSize="small">
<input type="password" nz-input formControlName="pwd" autocomplete="new-password"
[disabled]="!modalData.isEdit">
<input [disabled]="!modalData.isEdit" autocomplete="new-password" formControlName="pwd" nz-input
type="password">
<ng-template #cancelBtn>
<button nz-button (click)="modalData.resetPwd = false" nzSize="small" nzType="link">取消
<button (click)="modalData.resetPwd = false" nz-button nzSize="small" nzType="link">取消
</button>
</ng-template>
</nz-input-group>
@@ -75,20 +75,20 @@
<nz-form-item>
<nz-form-label nzSpan="4">描述</nz-form-label>
<nz-form-control nzSpan="18">
<textarea nz-input [nzAutosize]="{ minRows: 2, maxRows: 4 }" formControlName="desc"
[disabled]="!modalData.isEdit"></textarea>
<textarea [disabled]="!modalData.isEdit" [nzAutosize]="{ minRows: 2, maxRows: 4 }" formControlName="desc"
nz-input></textarea>
</nz-form-control>
</nz-form-item>
</form>
</ng-template>
<ng-template #showContentFooter>
<button nz-button (click)="modalData.visible = false">关闭</button>
<button (click)="modalData.visible = false" nz-button>关闭</button>
</ng-template>
<ng-template #editContentFooter>
<button nz-button (click)="modalData.visible = false">取消</button>
<button nz-button (click)="modalConfirm()" nzType="primary">提交</button>
<button (click)="modalData.visible = false" nz-button>取消</button>
<button (click)="modalConfirm()" nz-button nzType="primary">提交</button>
</ng-template>
</nz-modal>

View File

@@ -1,7 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {NzMessageService} from 'ng-zorro-antd';
import {NzMessageService} from 'ng-zorro-antd/message';
import {Title} from '@angular/platform-browser';
import {FormControl, FormGroup} from '@angular/forms';
import {UntypedFormControl, UntypedFormGroup} from '@angular/forms';
import {RequestObj} from '../../../class/HttpReqAndResp';
import {ApiService} from '../../../api/api.service';
import {User} from '../../../class/User';
@@ -14,38 +14,37 @@ import {Data} from '../components/common-table/data';
})
export class AdminUserComponent implements OnInit {
constructor(private apiService: ApiService, private title: Title, private messageService: NzMessageService,
private userService: GlobalUserService) {
this.formGroup = new FormGroup({
id: new FormControl(null),
email: new FormControl(''),
displayName: new FormControl(''),
emailStatus: new FormControl(null),
desc: new FormControl(null),
role: new FormControl(null),
pwd: new FormControl(''),
});
this.userService.watchUserInfo({
next: data => this.user = data.result,
error: null,
complete: null
})
}
user: User;
modalData = {
visible: false,
title: null,
isEdit: false,
resetPwd: false
}
formGroup: FormGroup;
};
formGroup: UntypedFormGroup;
headData: Data<User>[];
request: RequestObj;
constructor(private apiService: ApiService, private title: Title, private messageService: NzMessageService,
private userService: GlobalUserService) {
this.formGroup = new UntypedFormGroup({
id: new UntypedFormControl(null),
email: new UntypedFormControl(''),
displayName: new UntypedFormControl(''),
emailStatus: new UntypedFormControl(null),
desc: new UntypedFormControl(null),
role: new UntypedFormControl(null),
pwd: new UntypedFormControl(''),
});
this.userService.watchUserInfo({
next: data => this.user = data.result,
error: null,
complete: null
});
}
ngOnInit(): void {
this.title.setTitle('小海博客 | 用户管理')
this.title.setTitle('小海博客 | 用户管理');
this.request = {
path: '/admin/users',
method: 'GET',
@@ -79,24 +78,24 @@ export class AdminUserComponent implements OnInit {
this.apiService.deleteUser(id).subscribe({
next: data => this.messageService.success('删除成功'),
error: err => this.messageService.error(err.msg)
})
});
}
showModal(isEdit: boolean, data: User) {
this.modalData.visible = true;
this.modalData.isEdit = isEdit;
this.modalData.title = isEdit ? '编辑用户' : '查看用户'
this.modalData.title = isEdit ? '编辑用户' : '查看用户';
this.formGroup.reset();
this.formGroup.patchValue(data);
}
modalConfirm() {
this.modalData.visible = false
this.modalData.visible = false;
this.apiService.adminUpdateUser(this.formGroup.value).subscribe({
next: data => {
this.messageService.success('修改用户信息成功');
this.userService.refreshUserInfo();
}
})
});
}
}

View File

@@ -4,15 +4,15 @@ import {RouterModule} from '@angular/router';
import {AdminUserComponent} from './admin-user.component';
import {ReactiveFormsModule} from '@angular/forms';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {
NzButtonModule,
NzFormModule,
NzGridModule,
NzIconModule,
NzInputModule, NzModalModule,
NzRadioModule,
NzSelectModule, NzTagModule
} from 'ng-zorro-antd';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzFormModule} from 'ng-zorro-antd/form';
import {NzGridModule} from 'ng-zorro-antd/grid';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzInputModule} from 'ng-zorro-antd/input';
import {NzModalModule} from 'ng-zorro-antd/modal';
import {NzRadioModule} from 'ng-zorro-antd/radio';
import {NzSelectModule} from 'ng-zorro-antd/select';
import {NzTagModule} from 'ng-zorro-antd/tag';
@NgModule({

View File

@@ -1,4 +1,4 @@
<common-table [request]="request" [headData]="headData" cardTitle="访客信息管理">
<common-table [headData]="headData" [request]="request" cardTitle="访客信息管理">
</common-table>

View File

@@ -11,38 +11,31 @@ import {Data} from '../components/common-table/data';
})
export class AdminVisitorComponent implements OnInit {
headData: Data<Visitor>[];
request: RequestObj;
constructor(private apiService: ApiService, private title: Title) {
}
headData: Data<Visitor>[];
request: RequestObj
/***
* browserName: "Chrome 8"
browserVersion: "83.0.4103.116"
date: "2020-07-11 09:30:13"
id: 3131
ip: "127.0.0.1"
osname: "Windows 10"
*/
ngOnInit(): void {
this.title.setTitle('小海博客 | 访客信息管理')
this.title.setTitle('小海博客 | 访客信息管理');
this.request = {
path: '/admin/visitor/page',
method: 'GET',
queryParam: {
count: 1,
page: 10,
showLocation: location
showLocation: true
}
}
};
this.headData = [
{fieldValue: 'id', title: '主键', show: false, primaryKey: true},
{fieldValue: 'date', title: '访问日期', show: true},
{fieldValue: 'browserName', title: '浏览器', show: true},
{fieldValue: 'ip', title: 'ip地址', show: true},
{fieldValue: 'location', title: '位置', show: true},
{fieldValue: 'browserName', title: '浏览器', show: true},
{fieldValue: 'browserVersion', title: '浏览器版本', show: true},
{fieldValue: 'osname', title: '系统', show: true}
]
];
}
}

View File

@@ -1,40 +1,40 @@
<c-admin-header (infoClicked)="showInfoDrawer()"></c-admin-header>
<nz-layout class="layout">
<nz-sider nzCollapsible
<nz-sider *ngIf="user"
[(nzCollapsed)]="isCollapsed"
[nzBreakpoint]="'lg'"
[nzCollapsedWidth]="0"
[nzZeroTrigger]="zeroTrigger"
nzTheme="light"
*ngIf="user">
<ul nz-menu nzTheme="light" nzMode="inline" [nzInlineCollapsed]="isCollapsed">
nzCollapsible
nzTheme="light">
<ul [nzInlineCollapsed]="isCollapsed" nz-menu nzMode="inline" nzTheme="light">
<li nz-menu-item routerLink="/admin">
<i nz-icon nzType="dashboard" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="dashboard"></i>
<span>后台首页</span>
</li>
<li nz-submenu nzTitle="文章管理" nzIcon="file" *ngIf="user.role=='admin'">
<li *ngIf="user.role=='admin'" nz-submenu nzIcon="file" nzTitle="文章管理">
<ul>
<li nz-menu-item>
<a routerLink="/write">
<i nz-icon nzType="form" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="form"></i>
<span>新增文章</span>
</a>
</li>
<li nz-menu-item routerLink="/admin/article">
<i nz-icon nzType="ordered-list" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="ordered-list"></i>
<span>文章列表</span>
</li>
</ul>
</li>
<li nz-menu-item routerLink="/admin/comment">
<i nz-icon nzType="message" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="message"></i>
<span>评论管理</span>
</li>
<li nz-menu-item routerLink="/admin/tag" *ngIf="user.role=='admin'">
<i nz-icon nzType="tags" nzTheme="outline"></i>
<li *ngIf="user.role=='admin'" nz-menu-item routerLink="/admin/tag">
<i nz-icon nzTheme="outline" nzType="tags"></i>
<span>标签管理</span>
</li>
@@ -43,37 +43,37 @@
<!-- <span>分类管理</span>-->
<!-- </li>-->
<li nz-menu-item routerLink="/admin/user" *ngIf="user.role=='admin'">
<i nz-icon nzType="user" nzTheme="outline"></i>
<li *ngIf="user.role=='admin'" nz-menu-item routerLink="/admin/user">
<i nz-icon nzTheme="outline" nzType="user"></i>
<span>用户管理</span>
</li>
<li nz-menu-item routerLink="/admin/link" *ngIf="user.role=='admin'">
<i nz-icon nzType="link" nzTheme="outline"></i>
<li *ngIf="user.role=='admin'" nz-menu-item routerLink="/admin/link">
<i nz-icon nzTheme="outline" nzType="link"></i>
<span>友链管理</span>
</li>
<li nz-menu-item routerLink="/admin/visitor" *ngIf="user.role=='admin'">
<i nz-icon nzType="chrome" nzTheme="outline"></i>
<li *ngIf="user.role=='admin'" nz-menu-item routerLink="/admin/visitor">
<i nz-icon nzTheme="outline" nzType="chrome"></i>
<span>访问管理</span>
</li>
<li nz-menu-item routerLink="/admin/update" *ngIf="user.role=='admin'">
<i nz-icon nzType="arrow-up" nzTheme="outline"></i>
<li *ngIf="user.role=='admin'" nz-menu-item routerLink="/admin/update">
<i nz-icon nzTheme="outline" nzType="arrow-up"></i>
<span>更新管理</span>
</li>
<li nz-menu-item (click)="infoDrawerVisible = true">
<i nz-icon nzType="idcard" nzTheme="outline"></i>
<li (click)="infoDrawerVisible = true" nz-menu-item>
<i nz-icon nzTheme="outline" nzType="idcard"></i>
<span>查看信息</span>
</li>
<!--TODO : do something here ..... -->
<nz-card class="myCard" *ngIf="!isCollapsed&&user.role=='admin'">
<nz-card *ngIf="!isCollapsed&&user.role=='admin'" class="myCard">
<p>别管别人言语</p>
<p>做最好的自己</p>
</nz-card>
<nz-card class="myCard" *ngIf="!isCollapsed&&user.role=='user'">
<nz-card *ngIf="!isCollapsed&&user.role=='user'" class="myCard">
<p>欢迎来访小海博客</p>
</nz-card>
@@ -88,95 +88,95 @@
<nz-footer>© <a href="https://www.celess.cn">小海博客</a> - Design by 小海</nz-footer>
</nz-layout>
</nz-layout>
<nz-drawer [nzClosable]="false" [nzVisible]="infoDrawerVisible" nzPlacement="right"
[nzTitle]="sayHelloTemp" (nzOnClose)="infoDrawerVisible = false" nzWidth="300px">
<nz-drawer (nzOnClose)="infoDrawerVisible = false" [nzClosable]="false" [nzTitle]="sayHelloTemp"
[nzVisible]="infoDrawerVisible" nzPlacement="right" nzWidth="300px">
<p>您最近一次登录是在:</p>
<p>{{user && user.recentlyLandedDate}}</p>
<nz-divider></nz-divider>
<div style="text-align: center;margin-bottom: 10px;">
<nz-avatar [nzSize]="64" [nzSrc]="user.avatarImgUrl"
*ngIf="user.avatarImgUrl!==noAvatarUrl"></nz-avatar>
<nz-avatar [nzSize]="64" [nzText]="user.displayName" style="background: #f56a00"
*ngIf="user.avatarImgUrl===noAvatarUrl"></nz-avatar>
<nz-avatar *ngIf="user.avatarImgUrl!==noAvatarUrl" [nzSize]="64"
[nzSrc]="user.avatarImgUrl"></nz-avatar>
<nz-avatar *ngIf="user.avatarImgUrl===noAvatarUrl" [nzSize]="64" [nzText]="user.displayName"
style="background: #f56a00"></nz-avatar>
<nz-upload style="display: block" [nzAction]="host+'/user/imgUpload'" nzWithCredentials="true" nzLimit="1"
(nzChange)="avatarUpload($event)" [nzHeaders]="uploadHeader">
<nz-upload (nzChange)="avatarUpload($event)" [nzAction]="host+'/user/imgUpload'" [nzHeaders]="uploadHeader" nzLimit="1"
nzWithCredentials="true" style="display: block">
<button nz-button nzBlock nzType="link"><i nz-icon nzType="upload"></i>修改头像</button>
</nz-upload>
</div>
<nz-descriptions [nzColumn]="1">
<nz-descriptions-item nzTitle="邮箱">
<div>
<i nz-icon nzType="mail" class="icon" nzTheme="twotone"></i>
<i class="icon" nz-icon nzTheme="twotone" nzType="mail"></i>
<span>{{user && user.email}}</span>
<i nz-icon nzType="edit" class="edit-icon" nzTheme="twotone" (click)="showEditInfoModal()"></i>
<i (click)="showEditInfoModal()" class="edit-icon" nz-icon nzTheme="twotone" nzType="edit"></i>
</div>
</nz-descriptions-item>
<nz-descriptions-item nzTitle="昵称">
<div>
<i nz-icon nzType="crown" class="icon" nzTheme="twotone"></i>
<i class="icon" nz-icon nzTheme="twotone" nzType="crown"></i>
<span>{{user && user.displayName}}</span>
<i nz-icon nzType="edit" class="edit-icon" nzTheme="twotone" (click)="showEditInfoModal()"></i>
<i (click)="showEditInfoModal()" class="edit-icon" nz-icon nzTheme="twotone" nzType="edit"></i>
</div>
</nz-descriptions-item>
<nz-descriptions-item nzTitle="描述" *ngIf="user&&user.desc">
<i nz-icon nzType="info-circle" class="icon" nzTheme="twotone"></i>
<span nz-tooltip [nzTooltipTitle]="user.desc" nzTooltipPlacement="left" nz-typography [nzEllipsis]="true"
[nzContent]="user.desc" style="max-width: 100px">{{user.desc}}</span>
<i nz-icon nzType="edit" class="edit-icon" nzTheme="twotone" (click)="showEditInfoModal()"></i>
<nz-descriptions-item *ngIf="user&&user.desc" nzTitle="描述">
<i class="icon" nz-icon nzTheme="twotone" nzType="info-circle"></i>
<span [nzContent]="user.desc" [nzEllipsis]="true" [nzTooltipTitle]="user.desc" nz-tooltip nz-typography
nzTooltipPlacement="left" style="max-width: 100px">{{user.desc}}</span>
<i (click)="showEditInfoModal()" class="edit-icon" nz-icon nzTheme="twotone" nzType="edit"></i>
</nz-descriptions-item>
<nz-descriptions-item nzTitle="密码">
<i nz-icon nzType="fire" nzTheme="twotone"> </i>
<i nz-icon nzTheme="twotone" nzType="fire"> </i>
<span> *********</span>
<i nz-icon nzType="edit" class="edit-icon" nzTheme="twotone" (click)="showResetPwdModal()"></i>
<i (click)="showResetPwdModal()" class="edit-icon" nz-icon nzTheme="twotone" nzType="edit"></i>
</nz-descriptions-item>
</nz-descriptions>
<nz-divider></nz-divider>
<!-- <div >-->
<button nz-button nzDanger nzBlock nzType="primary" (click)="logout()">注销</button>
<button (click)="logout()" nz-button nzBlock nzDanger nzType="primary">注销</button>
<!-- </div>-->
<!-- TODO: 展示更多信息 -->
</nz-drawer>
<nz-modal [(nzVisible)]="editInfoModalVisible" (nzOnOk)="modalConfirm()" (nzOnCancel)="editInfoModalVisible=false"
<nz-modal (nzOnCancel)="editInfoModalVisible=false" (nzOnOk)="modalConfirm()" [(nzVisible)]="editInfoModalVisible"
nzTitle="编辑信息">
<form nz-form [formGroup]="editInfoFormGroup" (ngSubmit)="modalConfirm()">
<form (ngSubmit)="modalConfirm()" [formGroup]="editInfoFormGroup" nz-form>
<nz-form-item>
<nz-form-label>邮箱</nz-form-label>
<nz-form-control>
<input nz-input disabled formControlName="email">
<input disabled formControlName="email" nz-input>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label>昵称</nz-form-label>
<nz-form-control>
<input nz-input formControlName="displayName" placeholder="默认为你的邮箱地址">
<input formControlName="displayName" nz-input placeholder="默认为你的邮箱地址">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label>描述</nz-form-label>
<nz-form-control>
<input nz-input formControlName="desc" placeholder="请输入自我介绍">
<input formControlName="desc" nz-input placeholder="请输入自我介绍">
</nz-form-control>
</nz-form-item>
</form>
</nz-modal>
<nz-modal [(nzVisible)]="resetPwdModalVisible" nzClosable="true" (nzOnCancel)="resetPwdModalVisible = false"
(nzOnOk)="resetPwdConfirm()" nzTitle="修改密码" [nzOkDisabled]="!resetPwdFormGroup.valid">
<form nz-form (submit)="resetPwdConfirm()" [formGroup]="resetPwdFormGroup">
<nz-modal (nzOnCancel)="resetPwdModalVisible = false" (nzOnOk)="resetPwdConfirm()" [(nzVisible)]="resetPwdModalVisible"
[nzOkDisabled]="!resetPwdFormGroup.valid" nzClosable="true" nzTitle="修改密码">
<form (submit)="resetPwdConfirm()" [formGroup]="resetPwdFormGroup" nz-form>
<nz-form-item>
<nz-form-label nzRequired>原密码</nz-form-label>
<nz-form-control nzErrorTip="原密码不可为空">
<input type="password" name="xxx" nz-input formControlName="originPwd">
<input formControlName="originPwd" name="xxx" nz-input type="password">
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>新密码</nz-form-label>
<nz-form-control [nzErrorTip]="newPwdErrTip">
<input type="password" name="xxx" nz-input formControlName="newPwd">
<input formControlName="newPwd" name="xxx" nz-input type="password">
</nz-form-control>
<ng-template #newPwdErrTip>
<div *ngIf="resetPwdFormGroup.controls.newPwd.hasError('required')">新密码不可为空</div>
@@ -188,7 +188,7 @@
<nz-form-item>
<nz-form-label nzRequired>确认密码</nz-form-label>
<nz-form-control [nzErrorTip]="newPwdConfirmErrTip">
<input type="password" nz-input name="xxx" formControlName="newPwdConfirm">
<input formControlName="newPwdConfirm" name="xxx" nz-input type="password">
</nz-form-control>
<ng-template #newPwdConfirmErrTip>
<div *ngIf="resetPwdFormGroup.controls.newPwdConfirm.hasError('required')">确认密码不可为空</div>
@@ -202,10 +202,10 @@
</nz-modal>
<ng-template #zeroTrigger>
<i nz-icon nzType="menu-fold" nzTheme=outline></i>
<i nz-icon nzTheme=outline nzType="menu-fold"></i>
</ng-template>
<ng-template #sayHelloTemp>
<span>{{sayHelloContent}}</span>
<i nz-icon [nzType]="'smile'" [nzTheme]="'twotone'" nzTwotoneColor="#52c41a" style="margin-left: 5px"></i>
<i [nzTheme]="'twotone'" [nzType]="'smile'" nz-icon nzTwotoneColor="#52c41a" style="margin-left: 5px"></i>
</ng-template>

View File

@@ -31,7 +31,8 @@ nz-content {
.icon {
margin-right: 5px;
}
.edit-icon{
.edit-icon {
margin-left: 10px;
cursor: pointer;
}

View File

@@ -1,6 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {AbstractControl, FormControl, FormGroup, Validators} from '@angular/forms';
import {NzMessageService, UploadFile} from 'ng-zorro-antd';
import {AbstractControl, UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms';
import {NzMessageService} from 'ng-zorro-antd/message';
import {NzUploadFile} from 'ng-zorro-antd/upload';
import {Router} from '@angular/router';
import {GlobalUserService} from '../../services/global-user.service';
import {User} from '../../class/User';
@@ -16,83 +17,62 @@ import {LocalStorageService} from '../../services/local-storage.service';
})
export class AdminComponent implements OnInit {
constructor(public gUserService: GlobalUserService, private apiService: ApiService, private messageService: NzMessageService,
private router: Router, private localStorageService: LocalStorageService) {
this.gUserService.watchUserInfo({
complete: () => null,
error: (err) => null,
next: data => {
console.log('更新user')
this.user = data.result
if (data.result) this.initHelloWords()
}
}
);
this.editInfoFormGroup = new FormGroup({
desc: new FormControl(),
displayName: new FormControl(),
email: new FormControl({value: null, disabled: true})
});
this.resetPwdFormGroup = new FormGroup({
originPwd: new FormControl(null, [Validators.required]),
newPwd: new FormControl(null, [
Validators.required, Validators.minLength(6), Validators.maxLength(16), Validators.pattern(/^[\w_-]{6,16}$/)
]),
newPwdConfirm: new FormControl(null, [
Validators.required, Validators.minLength(6), Validators.maxLength(16), Validators.pattern(/^[\w_-]{6,16}$/),
this.checkSamePwd()
]),
})
}
user: User;
isCollapsed: boolean = false;
infoDrawerVisible: boolean = false;
sayHelloContent: string;
editInfoModalVisible: boolean = false;
resetPwdModalVisible: boolean = false;
editInfoFormGroup: FormGroup;
resetPwdFormGroup: FormGroup;
noAvatarUrl = 'https://cdn.celess.cn/'
host: string
editInfoFormGroup: UntypedFormGroup;
resetPwdFormGroup: UntypedFormGroup;
noAvatarUrl = 'https://cdn.celess.cn/';
host: string;
constructor(public gUserService: GlobalUserService, private apiService: ApiService, private messageService: NzMessageService,
private router: Router, private localStorageService: LocalStorageService) {
this.gUserService.watchUserInfo({
complete: () => null,
error: (err) => null,
next: data => {
this.user = data.result;
if (data.result) {this.initHelloWords();}
}
}
);
this.editInfoFormGroup = new UntypedFormGroup({
desc: new UntypedFormControl(),
displayName: new UntypedFormControl(),
email: new UntypedFormControl({value: null, disabled: true})
});
this.resetPwdFormGroup = new UntypedFormGroup({
originPwd: new UntypedFormControl(null, [Validators.required]),
newPwd: new UntypedFormControl(null, [
Validators.required, Validators.minLength(6), Validators.maxLength(16), Validators.pattern(/^[\w_-]{6,16}$/)
]),
newPwdConfirm: new UntypedFormControl(null, [
Validators.required, Validators.minLength(6), Validators.maxLength(16), Validators.pattern(/^[\w_-]{6,16}$/),
this.checkSamePwd()
]),
});
}
showInfoDrawer = () => this.infoDrawerVisible = !this.infoDrawerVisible;
logout() {
this.gUserService.logout();
this.router.navigateByUrl('/')
this.router.navigateByUrl('/');
}
ngOnInit(): void {
this.host = environment.host;
}
checkSamePwd = () => {
return (control: AbstractControl): { [key: string]: any } | null => {
console.log('a')
checkSamePwd = () => (control: AbstractControl): { [key: string]: any } | null => {
const newPwd = this.resetPwdFormGroup && this.resetPwdFormGroup.value.newPwd;
return control.value !== newPwd ? {pwdNotSame: true} : null;
};
}
uploadHeader = (file: UploadFile): object | Observable<{}> => {
return {Authorization: this.localStorageService.getToken()}
};
private initHelloWords() {
const hours = new Date().getHours();
if (hours < 6) {
this.sayHelloContent = `夜深了,注意早点休息哦!${this.user.displayName}`
} else if (hours < 10) {
this.sayHelloContent = `早上好呀!${this.user.displayName}`
} else if (hours < 14) {
this.sayHelloContent = `中午好呀!${this.user.displayName}`
} else if (hours < 19) {
this.sayHelloContent = `下午好呀!${this.user.displayName}`
} else if (hours < 22) {
this.sayHelloContent = `晚上好呀!${this.user.displayName}`
} else {
this.sayHelloContent = `时间不早了,注意休息哦!${this.user.displayName}`
}
}
// eslint-disable-next-line @typescript-eslint/naming-convention
uploadHeader = (file: NzUploadFile): any | Observable<{}> => ({Authorization: this.localStorageService.getToken()});
showEditInfoModal() {
this.editInfoModalVisible = true;
@@ -105,7 +85,7 @@ export class AdminComponent implements OnInit {
const displayName = this.editInfoFormGroup.value.displayName;
this.apiService.updateUserInfo(desc, displayName).subscribe({
next: data => {
this.messageService.success('修改信息成功')
this.messageService.success('修改信息成功');
this.gUserService.refreshUserInfo();
},
error: err => {
@@ -128,13 +108,13 @@ export class AdminComponent implements OnInit {
error: err => {
this.messageService.error('修改密码失败,' + err.msg);
}
})
});
this.resetPwdModalVisible = false;
}
showResetPwdModal() {
this.resetPwdModalVisible = true;
this.infoDrawerVisible = false
this.infoDrawerVisible = false;
}
avatarUpload(info: any) {
@@ -143,4 +123,21 @@ export class AdminComponent implements OnInit {
this.gUserService.refreshUserInfo();
}
}
private initHelloWords() {
const hours = new Date().getHours();
if (hours < 6) {
this.sayHelloContent = `夜深了,注意早点休息哦!${this.user.displayName}`;
} else if (hours < 10) {
this.sayHelloContent = `早上好呀!${this.user.displayName}`;
} else if (hours < 14) {
this.sayHelloContent = `中午好呀!${this.user.displayName}`;
} else if (hours < 19) {
this.sayHelloContent = `下午好呀!${this.user.displayName}`;
} else if (hours < 22) {
this.sayHelloContent = `晚上好呀!${this.user.displayName}`;
} else {
this.sayHelloContent = `时间不早了,注意休息哦!${this.user.displayName}`;
}
}
}

View File

@@ -2,12 +2,25 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AdminRoutingModule} from './admin-routing.module';
import {AdminComponent} from './admin.component';
import {NgZorroAntdModule} from 'ng-zorro-antd';
import {NzSpaceModule} from 'ng-zorro-antd/space';
import {AdminHeaderComponent} from '../../components/admin-header/admin-header.component';
import {ReactiveFormsModule} from '@angular/forms';
import {AuthGuard} from './auth.guard';
import {NzAvatarModule} from 'ng-zorro-antd/avatar';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzLayoutModule} from 'ng-zorro-antd/layout';
import {NzMenuModule} from 'ng-zorro-antd/menu';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzCardModule} from 'ng-zorro-antd/card';
import {NzDividerModule} from 'ng-zorro-antd/divider';
import {NzUploadModule} from 'ng-zorro-antd/upload';
import {NzToolTipModule} from 'ng-zorro-antd/tooltip';
import {NzTypographyModule} from 'ng-zorro-antd/typography';
import {NzModalModule} from 'ng-zorro-antd/modal';
import {NzFormModule} from 'ng-zorro-antd/form';
import {NzInputModule} from 'ng-zorro-antd/input';
import {NzDescriptionsModule} from 'ng-zorro-antd/descriptions';
import {NzDrawerModule} from 'ng-zorro-antd/drawer';
@NgModule({
declarations: [
@@ -17,9 +30,23 @@ import {AuthGuard} from './auth.guard';
imports: [
CommonModule,
AdminRoutingModule,
NgZorroAntdModule,
NzSpaceModule,
ReactiveFormsModule,
NzAvatarModule,
NzButtonModule,
NzLayoutModule,
NzMenuModule,
NzIconModule,
NzCardModule,
NzDividerModule,
NzUploadModule,
NzToolTipModule,
NzTypographyModule,
NzModalModule,
NzFormModule,
NzInputModule,
NzDescriptionsModule,
NzDrawerModule
],
providers: [AuthGuard]
})

View File

@@ -1,12 +1,5 @@
import {Injectable} from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
UrlTree,
Router,
CanActivateChild
} from '@angular/router';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {Observable, Observer} from 'rxjs';
import {User} from '../../class/User';
import {GlobalUserService} from '../../services/global-user.service';
@@ -16,15 +9,15 @@ import {GlobalUserService} from '../../services/global-user.service';
})
export class AuthGuard implements CanActivate {
constructor(private userService: GlobalUserService, private router: Router) {
}
userInfo: User;
visitCount: number = 0; // 记录一共走过几次canActivate
private path: string;
private readonly loginPath: string = '/user/login';
private observable: Observable<boolean>;
constructor(private userService: GlobalUserService, private router: Router) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
this.path = state.url.indexOf('?') > 0 ? state.url.substr(0, state.url.indexOf('?')) : state.url;
this.visitCount++;
@@ -53,7 +46,7 @@ export class AuthGuard implements CanActivate {
this.userInfo = data.result;
this.checkPath(observer);
}
})
});
}
@@ -67,7 +60,7 @@ export class AuthGuard implements CanActivate {
case '/admin/visitor':
if (this.userInfo && this.userInfo.role !== 'admin') {
observer.next(false);
if (this.visitCount === 1) this.router.navigateByUrl('/admin')
if (this.visitCount === 1) {this.router.navigateByUrl('/admin');}
observer.complete();
return;
}

View File

@@ -1,28 +1,30 @@
<nz-card *ngIf="cardTitle" nzSize="small" [nzExtra]="refresh" [nzTitle]="cardTitle" [nzLoading]="loading">
<nz-card *ngIf="cardTitle" [nzExtra]="extra" [nzLoading]="loading" [nzTitle]="cardTitle" nzSize="small">
<ng-container *ngTemplateOutlet="table"></ng-container>
</nz-card>
<ng-container [ngTemplateOutlet]="table" *ngIf="!cardTitle"></ng-container>
<ng-container *ngIf="!cardTitle" [ngTemplateOutlet]="table"></ng-container>
<ng-template #refresh>
<i nz-icon nzType="reload" nzTheme="outline" (click)="getData()" title="刷新" style="cursor: pointer"></i>
<ng-template #extra>
<i (click)="showFieldSetting()" nz-icon nzTheme="outline" nzType="setting" style="cursor: pointer;margin-right: 10px"
title="设置"></i>
<i (click)="getData()" nz-icon nzTheme="outline" nzType="reload" style="cursor: pointer" title="刷新"></i>
</ng-template>
<ng-template #table>
<ng-content></ng-content>
<nz-table nzTableLayout="fixed"
[nzData]="dataList.list"
[nzTotal]="dataList.total"
<nz-table (nzPageIndexChange)="getData($event)"
[(nzPageIndex)]="dataList.pageNum"
[nzData]="dataList.list"
[nzLoading]="loading"
[nzPageSize]="dataList.pageSize"
(nzPageIndexChange)="getData()"
[nzScroll]="{x:visibleFieldLength*100+'px'}"
[nzTotal]="dataList.total"
nzFrontPagination="false"
[nzScroll]="{x:'1300px'}"
[nzLoading]="loading">
nzTableLayout="fixed">
<thead>
<tr>
<ng-container *ngFor="let data of headData">
<th *ngIf="data.show">
<ng-container *ngFor="let data of filedData">
<th *ngIf="data.show" [nzWidth]="data.isActionColumns?data.action.length*80+'px':null">
{{data.title}}
</th>
</ng-container>
@@ -30,14 +32,14 @@
</thead>
<tbody>
<tr *ngFor="let t of dataList.list;let index = index">
<ng-container *ngFor="let data of headData">
<ng-container *ngFor="let data of filedData">
<td *ngIf="data.show"
nz-typography
nzEllipsis
[nzEllipsisRows]="data.isActionColumns?3:1"
[nzTooltipTitle]="data.isActionColumns ? null : data.title+' : '+getValue(index,data.fieldValue)"
nzTooltipPlacement="top"
nz-tooltip>
nz-tooltip
nz-typography
nzEllipsis
nzTooltipPlacement="top">
<ng-template [ngIf]="!data.isActionColumns">
<ng-template [ngIf]="template[data.fieldValue]">
<ng-container
@@ -49,15 +51,15 @@
</ng-template>
</ng-template>
<ng-container *ngIf="data.isActionColumns">
<a *ngFor="let action of data.action; let i = index"
(mouseenter)="action.hover(t)"
<a (mouseenter)="action.hover(t)"
(mouseout)="null"
[ngStyle]="{'color':action.color,'font-size':action.fontSize}"
nz-popconfirm
[nzPopconfirmTitle]="'是否确认'+action.name+'该数据?'"
[nzCondition]="!action.needConfirm"
(nzOnConfirm)="action.click(t)"
[title]="action.name">
*ngFor="let action of data.action; let i = index"
[ngStyle]="{'color':action.color,'font-size':action.fontSize}"
[nzCondition]="!action.needConfirm"
[nzPopconfirmTitle]="'是否确认'+action.name+'该数据?'"
[title]="action.name"
nz-popconfirm>
{{action.name}}
<ng-template [ngIf]="i!=data.action.length-1">
<nz-divider nzType="vertical"></nz-divider>
@@ -70,3 +72,27 @@
</tbody>
</nz-table>
</ng-template>
<nz-modal (nzOnCancel)="cancel()"
(nzOnOk)="ok()"
[(nzVisible)]="settingModalVisible"
[nzClosable]="true"
nzTitle="表格字段设置(可拖动排序)"
>
<button (click)="reset()" [disabled]="!changed" nz-button nzType="primary">重置</button>
<nz-table [nzData]="filedData" nzPageSize="10000" nzShowPagination="false" nzSize="small">
<tbody (cdkDropListDropped)="drop($event)" cdkDropList>
<ng-template [ngForOf]="filedData" let-index="index" let-item ngFor>
<tr (click)="click()" *ngIf="!item.isActionColumns" cdkDrag>
<td>{{index + 1}}</td>
<td style="text-align: center">{{item.title}}</td>
<td style="text-align: center">{{item.fieldValue}}</td>
<td style="text-align: right">
<nz-switch [(ngModel)]="item.show" nzSize="small"></nz-switch>
</td>
</tr>
</ng-template>
</tbody>
</nz-table>
</nz-modal>

View File

@@ -0,0 +1,14 @@
ul {
list-style: none;
margin: 0;
padding: 0;
li {
margin: 8px 0;
padding: 0;
}
}
td {
border-bottom: none !important;
}

View File

@@ -2,6 +2,8 @@ import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges
import {Data} from './data';
import {PageList, RequestObj} from '../../../../class/HttpReqAndResp';
import {HttpService} from '../../../../api/http/http.service';
import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop';
import {LocalStorageService} from '../../../../services/local-storage.service';
@Component({
selector: 'common-table',
@@ -10,62 +12,79 @@ import {HttpService} from '../../../../api/http/http.service';
})
export class CommonTableComponent<T> implements OnInit, OnChanges {
constructor(private httpService: HttpService) {
}
/**
* 设置readonly data 因为后面有使用eval 为了安全
*/
@Input() headData: Data<T>[];
@Input() request: RequestObj;
@Output() pageInfo = new EventEmitter<{ page: number; pageSize: number }>();
@Input() cardTitle: string | null;
@Input() template: {
[fieldValue: string]: {
temp: TemplateRef<any>,
param?: { [key: string]: string }
}
temp: TemplateRef<any>;
param?: { [key: string]: string };
};
};
@Output() pageInfo = new EventEmitter<{ page: number, pageSize: number }>();
@Input() request: RequestObj;
@Input() private headData: Data<T>[];
loading: boolean = true;
dataList: PageList<T> = new PageList<T>();
settingModalVisible: boolean = false;
filedData: Data<T>[];
changed: boolean = false;
visibleFieldLength: number = 0;
constructor(private httpService: HttpService,
private localStorageService: LocalStorageService) {
}
ngOnInit(): void {
if (!this.template) this.template = {}
if (this.localStorageService.getItem(this.request.path)) {
this.filedData = this.cloneData(this.localStorageService.getItem(this.request.path));
this.changed = true;
} else {
this.filedData = this.cloneData(this.headData);
}
this.calculateVisibleFieldLength();
if (!this.template) {
this.template = {};
}
this.headData.forEach(dat => {
if (!dat.action) return;
if (!dat.action) {
return;
}
dat.action.forEach(act => {
if (!act.hover) {
act.hover = () => null;
}
})
});
});
if (!this.request || !this.request.path) return
if (!this.request || !this.request.path) {
return;
}
this.getData();
}
getData = () => {
getData = (pageNumber?: number) => {
this.loading = true;
const pageValue = this.dataList.pageNum ? this.dataList.pageNum : 1;
const countValue = this.dataList.pageSize ? this.dataList.pageSize : 10
this.request.queryParam = {
page: pageValue,
count: countValue
}
this.pageInfo.emit({page: pageValue, pageSize: countValue})
return this.httpService.Service<PageList<T>>(this.request).subscribe({
const pageValue = pageNumber ? pageNumber : 1;
const countValue = this.dataList.pageSize ? this.dataList.pageSize : 10;
this.request.queryParam.page = pageValue;
this.request.queryParam.count = countValue;
// this.request.queryParam = {
// page: pageValue,
// count: countValue
// }
this.pageInfo.emit({page: pageValue, pageSize: countValue});
return this.httpService.service<PageList<T>>(this.request).subscribe({
next: resp => {
this.dataList = resp.result;
setTimeout(() => this.loading = false, 10)
setTimeout(() => this.loading = false, 10);
},
error: err => this.loading = false
});
}
};
ngOnChanges(changes: SimpleChanges): void {
if (changes.request && !changes.request.isFirstChange()) {
console.log(changes.request)
this.request = changes.request.currentValue;
this.getData().unsubscribe();
this.getData();
@@ -76,7 +95,9 @@ export class CommonTableComponent<T> implements OnInit, OnChanges {
getValue(index: number, fieldValue: string): string {
let value = this.dataList.list[index];
try {
for (const key of fieldValue.split('.')) value = value[key]
for (const key of fieldValue.split('.')) {
value = value[key];
}
} catch (e) {
// ignore
}
@@ -85,19 +106,78 @@ export class CommonTableComponent<T> implements OnInit, OnChanges {
getContext = (fieldValue: string, index: number) => {
const valueData = this.getValue(index, fieldValue);
let context: { value: string, originValue?: string, data: T };
let context: { value: string; originValue?: string; data: T };
if (this.template[fieldValue].param) {
context = {
value: this.template[fieldValue].param[valueData],
originValue: valueData,
data: this.dataList.list[index]
}
};
} else {
context = {
value: valueData,
data: this.dataList.list[index]
}
};
}
return context;
};
showFieldSetting = () => this.settingModalVisible = true;
cancel = () => this.settingModalVisible = false;
calculateVisibleFieldLength = () => this.visibleFieldLength = this.filedData.filter(value => value.show).length;
ok() {
this.calculateVisibleFieldLength();
this.settingModalVisible = !this.settingModalVisible;
if (!this.changed) {
return;
}
this.dataList = JSON.parse(JSON.stringify(this.dataList));
this.localStorageService.setItem(this.request.path, JSON.stringify(this.filedData));
this.changed = true;
}
drop(event: CdkDragDrop<T, any>) {
this.changed = true;
moveItemInArray(this.filedData, event.previousIndex, event.currentIndex);
}
reset = () => {
this.localStorageService.removeItem(this.request.path);
this.filedData = this.cloneData(this.headData);
this.changed = false;
this.calculateVisibleFieldLength();
};
cloneData = (source: Data<T>[] | string): Data<T>[] => {
let dist: Data<T>[];
if (typeof source === 'string') {
dist = JSON.parse(source);
} else {
dist = JSON.parse(JSON.stringify(source));
}
const action = this.headData.filter(value => value.isActionColumns).pop();
if (!action) {
return dist;
}
const del = dist.filter(value => value.isActionColumns).pop();
dist.splice(dist.indexOf(del), 1);
dist.push(action);
return dist;
};
/**
* 字段编辑项被点击
*/
click = () => {
this.changed = false;
for (let i = 0; i < this.filedData.length; i++) {
const d1 = this.filedData[i];
const d2 = this.headData[i];
if (d1.fieldValue !== d2.fieldValue || d1.show !== d2.show) {
this.changed = true;
}
}
};
}

View File

@@ -1,15 +1,20 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {CommonTableComponent} from './common-table.component';
import {
NzCardModule,
NzDividerModule,
NzIconModule, NzOutletModule, NzPopconfirmModule,
NzTableModule,
NzToolTipModule,
NzTypographyModule
} from 'ng-zorro-antd';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzCardModule} from 'ng-zorro-antd/card';
import {NzDividerModule} from 'ng-zorro-antd/divider';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzModalModule} from 'ng-zorro-antd/modal';
import {NzOutletModule} from 'ng-zorro-antd/core/outlet';
import {NzPopconfirmModule} from 'ng-zorro-antd/popconfirm';
import {NzSwitchModule} from 'ng-zorro-antd/switch';
import {NzTableModule} from 'ng-zorro-antd/table';
import {NzTagModule} from 'ng-zorro-antd/tag';
import {NzToolTipModule} from 'ng-zorro-antd/tooltip';
import {NzTypographyModule} from 'ng-zorro-antd/typography';
import {FormsModule} from '@angular/forms';
import {DragDropModule} from '@angular/cdk/drag-drop';
@NgModule({
declarations: [
@@ -27,7 +32,13 @@ import {
NzCardModule,
NzIconModule,
NzOutletModule,
NzPopconfirmModule
NzPopconfirmModule,
NzModalModule,
NzTagModule,
NzSwitchModule,
FormsModule,
DragDropModule,
NzButtonModule
]
})
export class CommonTableModule {

View File

@@ -7,18 +7,19 @@ export class Data<T> {
primaryKey?: boolean = false;
isActionColumns?: boolean = false;
template?: {
template: TemplateRef<any>,
template: TemplateRef<any>;
keymap?: {
[value: string]: string
}
[value: string]: string;
};
};
action ?: {
name: string,
color?: string,
order?: number,
fontSize?: string,
needConfirm?: boolean,
click: (data: T) => void,
// order?: number;
action?: {
name: string;
color?: string;
order?: number;
fontSize?: string;
needConfirm?: boolean;
click: (data: T) => void;
hover?: (data: T) => void | null;
}[] = []
}[] = [];
}

View File

@@ -1,15 +1,5 @@
import {
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
import {NzModalRef, NzModalService} from 'ng-zorro-antd';
import {Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core';
import {NzModalRef, NzModalService} from 'ng-zorro-antd/modal';
@Component({
selector: 'editable-tag',
@@ -39,17 +29,9 @@ import {NzModalRef, NzModalService} from 'ng-zorro-antd';
})
export class EditableTagComponent implements OnInit, OnChanges {
private static instanceArray: EditableTagComponent[] = []
constructor(private modal: NzModalService) {
EditableTagComponent.instanceArray.push(this);
}
inputVisible = false;
inputValue = '';
private static instanceArray: EditableTagComponent[] = [];
@ViewChild('inputElement', {static: false}) inputElement?: ElementRef;
@Output() valueChange = new EventEmitter<{ value: string, originalValue: string, changed: boolean }>();
@Output() valueChange = new EventEmitter<{ value: string; originalValue: string; changed: boolean }>();
@Input() color: string;
@Input() showEditIcon: boolean;
@Input() showBorder: boolean;
@@ -60,14 +42,19 @@ export class EditableTagComponent implements OnInit, OnChanges {
@Input() autoClear: boolean;
@Input() size: 'small' | 'default' | 'large';
@Output() inEditStatus = new EventEmitter<void>();
@Output() modalOK = new EventEmitter<{ value: string, originalValue: string, changed: boolean }>();
@Output() modalCancel = new EventEmitter<{ value: string, originalValue: string, changed: boolean }>();
@Output() modalOK = new EventEmitter<{ value: string; originalValue: string; changed: boolean }>();
@Output() modalCancel = new EventEmitter<{ value: string; originalValue: string; changed: boolean }>();
inputVisible = false;
inputValue = '';
confirmModal?: NzModalRef;
private tmpKey: any;
private doubleClickInfo = {
date: null,
};
confirmModal?: NzModalRef;
constructor(private modal: NzModalService) {
EditableTagComponent.instanceArray.push(this);
}
ngOnInit(): void {
if (this.showEditIcon == null) {
@@ -97,17 +84,17 @@ export class EditableTagComponent implements OnInit, OnChanges {
if (this.doubleClick && doubleClick) {
if (!this.doubleClickInfo.date) {
this.doubleClickInfo.date = new Date().getTime();
return
return;
}
if (new Date().getTime() - this.doubleClickInfo.date < 200) {
this.inEditStatus.emit()
this.inEditStatus.emit();
this.inputVisible = true;
setTimeout(() => this.inputElement?.nativeElement.focus(), 10);
}
this.doubleClickInfo.date = new Date().getTime();
} else {
this.inputVisible = true;
this.inEditStatus.emit()
this.inEditStatus.emit();
setTimeout(() => this.inputElement?.nativeElement.focus(), 10);
}
}
@@ -118,7 +105,7 @@ export class EditableTagComponent implements OnInit, OnChanges {
if (tag.key === this.tmpKey) {
tag.showInput(false);
}
})
});
}
@@ -127,8 +114,8 @@ export class EditableTagComponent implements OnInit, OnChanges {
value: this.inputValue,
originalValue: this.text,
changed: this.inputValue !== this.text
}
this.valueChange.emit(value)
};
this.valueChange.emit(value);
this.text = this.inputValue;
this.inputValue = '';
this.inputVisible = false;
@@ -141,7 +128,7 @@ export class EditableTagComponent implements OnInit, OnChanges {
});
}
if (this.autoClear) {
this.text = null
this.text = null;
}
}

View File

@@ -1,7 +1,9 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {EditableTagComponent} from './editable-tag.component';
import {NzIconModule, NzInputModule, NzTagModule} from 'ng-zorro-antd';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzInputModule} from 'ng-zorro-antd/input';
import {NzTagModule} from 'ng-zorro-antd/tag';
import {FormsModule} from '@angular/forms';

View File

@@ -14,15 +14,15 @@
<nz-tag [nzColor]="'#f50'">{{value}}</nz-tag>
</ng-template>
<ng-template #original let-value="value" let-originValue="originValue">
<ng-template #original let-originValue="originValue" let-value="value">
<nz-tag [nzColor]="originValue?'#87d068':'#f50'">{{value}}</nz-tag>
</ng-template>
<ng-template #open let-value="value">
<label nz-checkbox nzDisabled [ngModel]="value"></label>
<label [ngModel]="value" nz-checkbox nzDisabled></label>
</ng-template>
<editable-tag color="green">hhh</editable-tag>
<editable-tag color="green" [showEditIcon]="false">hhh</editable-tag>
<editable-tag color="green" [showBorder]="false">hhh</editable-tag>
<editable-tag [showEditIcon]="false" color="green">hhh</editable-tag>
<editable-tag [showBorder]="false" color="green">hhh</editable-tag>

View File

@@ -1,4 +1,4 @@
import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {Data} from '../components/common-table/data';
import {Article} from '../../../class/Article';
import {RequestObj} from '../../../class/HttpReqAndResp';
@@ -24,8 +24,12 @@ summary: a
tags: [{id: 26, name: "脚本"}, {id: 27, name: "网课"}]
title: "教你动手写一个刷课脚本"
updateDateFormat: "2020-05-27 00:55:05"*/
// @ViewChild('tag') tagTemp: TemplateRef<any>;
data: Data<Article>[];
req: RequestObj;
constructor() {
this.data = [
{title: '主键', fieldValue: 'id', show: false, primaryKey: true},
@@ -58,12 +62,9 @@ updateDateFormat: "2020-05-27 00:55:05"*/
},
]
}
]
];
}
data: Data<Article>[];
req: RequestObj;
ngOnInit(): void {
this.req = {
path: '/admin/articles',
@@ -72,7 +73,7 @@ updateDateFormat: "2020-05-27 00:55:05"*/
page: 1,
count: 10
}
}
};
}
}

View File

@@ -1,9 +1,10 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {TestCommonTableComponent} from './test-common-table.component';
import {Router, RouterModule} from '@angular/router';
import {RouterModule} from '@angular/router';
import {CommonTableModule} from '../components/common-table/common-table.module';
import {NzCheckboxModule, NzTagModule} from 'ng-zorro-antd';
import {NzCheckboxModule} from 'ng-zorro-antd/checkbox';
import {NzTagModule} from 'ng-zorro-antd/tag';
import {FormsModule} from '@angular/forms';
import {EditableTagModule} from '../components/editable-tag/editable-tag.module';

View File

@@ -1,6 +1,6 @@
<div id="main">
<div id="article-content"></div>
<div #divElement id="article-content"></div>
<ng-template [ngIf]="article">
<span id="over">over</span>
@@ -15,20 +15,20 @@
<div class="article-tag" id="tag">
<!-- TODO -->
<span *ngFor="let item of (article.tags||'')" class="tag">
<i nz-icon nzType="tag" nzTheme="fill"></i>
<a class="tag" [routerLink]="['/tags/'+item.name]">{{item.name}}</a>
<i nz-icon nzTheme="fill" nzType="tag"></i>
<a [routerLink]="['/tags/'+item.name]" class="tag">{{item.name}}</a>
</span>
</div>
<div class="article-bAnda">
<a (click)="toArticle(article.nextArticle.id)" [class.disabled]="!article.nextArticle">
<i nz-icon nzType="left" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="left"></i>
{{(article.nextArticle && article.nextArticle.title) || '无'}}
</a>
<a (click)="toArticle(article.preArticle.id)" [class.disabled]="!article.preArticle"
style="float: right" id="pre">
id="pre" style="float: right">
{{(article.preArticle && article.preArticle.title) || '无'}}
<i nz-icon nzType="right" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="right"></i>
</a>
</div>
@@ -36,18 +36,18 @@
</ng-template>
<nz-comment id="f-comment">
<nz-avatar nz-comment-avatar nzIcon="user" [nzSrc]="avatarImgUrl"></nz-avatar>
<nz-avatar [nzSrc]="avatarImgUrl" nz-comment-avatar nzIcon="user"></nz-avatar>
<nz-comment-content>
<nz-form-item>
<textarea [(ngModel)]="comment.content" nz-input rows="4" [disabled]="!user"
[nzAutosize]="{ minRows: 2, maxRows: user?6:2 }"></textarea>
<span *ngIf="!user">请先 <a routerLink="/user/login"
[queryParams]="{url:'/article/'+articleId}">登录</a></span>
<textarea [(ngModel)]="comment.content" [disabled]="!user" [nzAutosize]="{ minRows: 2, maxRows: user?6:2 }" nz-input
rows="4"></textarea>
<span *ngIf="!user">请先 <a [queryParams]="{url:'/article/'+articleId}"
routerLink="/user/login">登录</a></span>
</nz-form-item>
<nz-form-item>
<button nz-button nzType="primary" [nzLoading]="!user&&submitting"
[disabled]="!comment.content"
(click)="submitComment(true)">评论
<button (click)="submitComment(true)" [disabled]="!comment.content" [nzLoading]="!user&&submitting"
nz-button
nzType="primary">评论
</button>
</nz-form-item>
</nz-comment-content>
@@ -61,28 +61,28 @@
<nz-list [nzLoading]="!commentPage">
<nz-list-item *ngFor="let comment of commentPage.list">
<nz-comment [nzAuthor]="comment.fromUser.displayName" [nzDatetime]="comment.date" style="width: 100%">
<nz-avatar nz-comment-avatar nzIcon="user" [nzSrc]="comment.fromUser.avatarImgUrl"
*ngIf="comment.fromUser.avatarImgUrl">
<nz-avatar *ngIf="comment.fromUser.avatarImgUrl" [nzSrc]="comment.fromUser.avatarImgUrl" nz-comment-avatar
nzIcon="user">
</nz-avatar>
<nz-avatar nz-comment-avatar nzIcon="user" [nzText]="comment.fromUser.displayName"
*ngIf="!comment.fromUser.avatarImgUrl">
<nz-avatar *ngIf="!comment.fromUser.avatarImgUrl" [nzText]="comment.fromUser.displayName" nz-comment-avatar
nzIcon="user">
</nz-avatar>
<nz-comment-content>
<p style="font-size: larger">{{ comment.content }}</p>
</nz-comment-content>
<nz-comment-action>
<i nz-icon nzType="message" nzTheme="outline"></i>
<button nz-button nzType="link" (click)="resp(comment.id,comment.fromUser.displayName)">回复
<i nz-icon nzTheme="outline" nzType="message"></i>
<button (click)="resp(comment.id,comment.fromUser.displayName)" nz-button nzType="link">回复
</button>
</nz-comment-action>
<nz-list-item *ngFor="let com of comment.respComment">
<nz-comment [nzAuthor]="com.fromUser.displayName" [nzDatetime]="com.date">
<nz-avatar nz-comment-avatar nzIcon="user" [nzSrc]="com.fromUser.avatarImgUrl"
*ngIf="com.fromUser.avatarImgUrl">
<nz-avatar *ngIf="com.fromUser.avatarImgUrl" [nzSrc]="com.fromUser.avatarImgUrl" nz-comment-avatar
nzIcon="user">
</nz-avatar>
<nz-avatar nz-comment-avatar nzIcon="user" [nzText]="com.fromUser.displayName"
*ngIf="!com.fromUser.avatarImgUrl">
<nz-avatar *ngIf="!com.fromUser.avatarImgUrl" [nzText]="com.fromUser.displayName" nz-comment-avatar
nzIcon="user">
</nz-avatar>
<nz-comment-content>
<p style="font-size: larger">{{ com.content }}</p>
@@ -96,18 +96,18 @@
<nz-form-item *ngIf="pid==comment.id">
<nz-input-group [nzAddOnBefore]="respName">
<textarea nz-input [(ngModel)]="content" placeholder="写出你的想法"
[nzAutosize]="{ minRows: 2, maxRows: 6 }" [disabled]="!user">
<textarea [(ngModel)]="content" [disabled]="!user" [nzAutosize]="{ minRows: 2, maxRows: 6 }"
nz-input placeholder="写出你的想法">
</textarea>
<ng-template #respName>
<span>@{{name}}</span>
</ng-template>
</nz-input-group>
<div *ngIf="!user">请先 <a routerLink="/user/login"
[queryParams]="{url:'/article/'+articleId}">登录</a></div>
<button nz-button (click)="pid=null" style="margin-top: 10px;">取消</button>
<button nz-button nzType="primary" (click)="submitComment(false)"
style="margin-left: 30px;margin-top: 10px;" [nzLoading]="!user&&submitting">回复
<div *ngIf="!user">请先 <a [queryParams]="{url:'/article/'+articleId}"
routerLink="/user/login">登录</a></div>
<button (click)="pid=null" nz-button style="margin-top: 10px;">取消</button>
<button (click)="submitComment(false)" [nzLoading]="!user&&submitting" nz-button
nzType="primary" style="margin-left: 30px;margin-top: 10px;">回复
</button>
</nz-form-item>

View File

@@ -102,6 +102,7 @@ nz-content {
.article-bAnda {
height: 70px;
max-height: 110px;
a {
display: block;
}
@@ -110,4 +111,4 @@ nz-content {
#f-comment {
margin: 30px 3%
}
}
}

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { ArticleComponent } from './article.component';
import {ArticleComponent} from './article.component';
describe('ArticleComponent', () => {
let component: ArticleComponent;
let fixture: ComponentFixture<ArticleComponent>;
let component: ArticleComponent;
let fixture: ComponentFixture<ArticleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ArticleComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ArticleComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ArticleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(ArticleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,16 +1,15 @@
import {Component, OnInit} from '@angular/core';
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {ApiService} from '../../api/api.service';
import {Article} from '../../class/Article';
import {Title} from '@angular/platform-browser';
import {User} from '../../class/User';
import {CommentReq} from '../../class/Comment';
import {Comment, CommentReq} from '../../class/Comment';
import {PageList} from '../../class/HttpReqAndResp';
import {Comment} from '../../class/Comment';
import {GlobalUserService} from '../../services/global-user.service';
import VditorPreview from 'vditor/dist/method.min';
declare var editormd;
declare var $;
declare let $;
@Component({
selector: 'view-article',
@@ -19,6 +18,20 @@ declare var $;
})
export class ArticleComponent implements OnInit {
@ViewChild('divElement') divElement: ElementRef;
articleId: number;
article: Article;
copyRightUrl: string;
user: User;
submitting: boolean = false;
comment: CommentReq;
// 作为输入框@ 的提示
name: string;
commentPage: PageList<Comment>;
avatarImgUrl: string;
pid: number;
content: string;
constructor(private activatedRoute: ActivatedRoute,
private apiService: ApiService,
private userService: GlobalUserService,
@@ -27,19 +40,7 @@ export class ArticleComponent implements OnInit {
this.articleId = +activatedRoute.snapshot.paramMap.get('id');
}
articleId: number;
article: Article;
copyRightUrl: string;
user: User;
submitting: boolean = false;
comment: CommentReq;
// 作为输入框@ 的提示
name: string;
commentPage: PageList<Comment>;
avatarImgUrl: string;
pid: number;
content: string;
// private vditor: Vditor;
ngOnInit() {
this.toArticle(this.articleId);
@@ -48,24 +49,37 @@ export class ArticleComponent implements OnInit {
error: (err) => null,
next: data => {
this.user = data.result;
if (data.result) this.avatarImgUrl = data.result.avatarImgUrl;
if (data.result) {this.avatarImgUrl = data.result.avatarImgUrl;}
}
});
this.comment = new CommentReq(`article/${this.articleId}`);
}
parseMd(md: string) {
editormd.markdownToHTML('article-content', {
markdown: this.article.mdContent,
htmlDecode: 'style,script,iframe', // you can filter tags decode
toc: false,
tocm: false, // Using [TOCM]
// tocContainer: '#article-slider', // 自定义 ToC 容器层
// tocDropdown: true,
emoji: true,
taskList: true,
flowChart: true, // 默认不解析
});
const option: IPreviewOptions = {
anchor: 1,
hljs: {
lineNumber: true
},
markdown: {
autoSpace: true,
fixTermTypo: true,
chinesePunct: true,
linkBase: location.href,
toc: true,
mark: true
},
after: () => {
// 处理锚点
const tocList: HTMLCollection = this.divElement.nativeElement
.getElementsByClassName('vditor-toc')[0]?.getElementsByTagName(`a`);
for (let i = 0; i < tocList?.length; i++) {
const linkValue = tocList.item(i).getAttribute('href');
tocList.item(i).setAttribute('href', window.location.pathname + linkValue);
}
}
};
VditorPreview.preview(this.divElement.nativeElement, md, option);
}
toArticle(id: number) {

View File

@@ -2,16 +2,19 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ArticleRoutingModule} from './article-routing.module';
import {ArticleComponent} from './article.component';
import {
NzAffixModule,
NzAnchorModule, NzAvatarModule,
NzButtonModule,
NzCommentModule,
NzDividerModule, NzFormModule,
NzGridModule,
NzIconModule, NzInputModule,
NzLayoutModule, NzListModule, NzTabsModule
} from 'ng-zorro-antd';
import {NzAffixModule} from 'ng-zorro-antd/affix';
import {NzAnchorModule} from 'ng-zorro-antd/anchor';
import {NzAvatarModule} from 'ng-zorro-antd/avatar';
import {NzButtonModule} from 'ng-zorro-antd/button';
import {NzCommentModule} from 'ng-zorro-antd/comment';
import {NzDividerModule} from 'ng-zorro-antd/divider';
import {NzFormModule} from 'ng-zorro-antd/form';
import {NzGridModule} from 'ng-zorro-antd/grid';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzInputModule} from 'ng-zorro-antd/input';
import {NzLayoutModule} from 'ng-zorro-antd/layout';
import {NzListModule} from 'ng-zorro-antd/list';
import {NzTabsModule} from 'ng-zorro-antd/tabs';
import {FormsModule} from '@angular/forms';

View File

@@ -3,9 +3,9 @@
<div id="category">
<ul *ngIf="categoryList.length">
<c-tag-tag *ngFor="let category of categoryList"
[tag]="{name:category.name,size:category.articles.length}"
(tagClick)="changeCategory(category)">
<c-tag-tag (tagClick)="changeCategory(category)"
*ngFor="let category of categoryList"
[tag]="{name:category.name,size:category.articles.length}">
</c-tag-tag>
</ul>
@@ -16,7 +16,7 @@
<span style="font-weight: bolder;">{{name}}</span>
</span>
<ul id="detail" *ngIf="articleList&&articleList.list.length">
<ul *ngIf="articleList&&articleList.list.length" id="detail">
<c-article-detail-card *ngFor="let article of articleList.list"
[data]="article" [showMediaArea]="false" [showTagArea]="false">
</c-article-detail-card>
@@ -25,4 +25,4 @@
<div *ngIf="!articleList||!articleList.list.length">
<h2 style="text-align: center">该分类暂无文章</h2>
</div>
</div>
</div>

View File

@@ -23,7 +23,8 @@
#main {
width: 100%;
}
#detail{
#detail {
margin: 10px 40px 10px 0;
}
}
}

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { CategoryComponent } from './category.component';
import {CategoryComponent} from './category.component';
describe('CategoryComponent', () => {
let component: CategoryComponent;
let fixture: ComponentFixture<CategoryComponent>;
let component: CategoryComponent;
let fixture: ComponentFixture<CategoryComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CategoryComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CategoryComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CategoryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(CategoryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,7 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {ApiService} from '../../api/api.service';
import {Tag} from '../../class/Tag';
import {NzMessageService} from 'ng-zorro-antd';
import {NzMessageService} from 'ng-zorro-antd/message';
import {PageList} from '../../class/HttpReqAndResp';
import {Article} from '../../class/Article';
import {ActivatedRoute} from '@angular/router';
@@ -15,6 +15,11 @@ import {Title} from '@angular/platform-browser';
})
export class CategoryComponent implements OnInit {
categoryList: Tag[] = [];
articleList: PageList<Article>;
name: string;
private category: Tag;
constructor(private apiService: ApiService,
private nzMessageService: NzMessageService,
private activatedRoute: ActivatedRoute,
@@ -22,12 +27,6 @@ export class CategoryComponent implements OnInit {
private title: Title) {
}
categoryList: Tag[] = [];
private category: Tag;
articleList: PageList<Article>;
name: string;
ngOnInit() {
this.name = this.activatedRoute.snapshot.paramMap.get('category');
this.getCategories(this.name == null);

View File

@@ -2,7 +2,8 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {CategoryComponent} from './category.component';
import {CategoryRoutingModule} from './category-routing.module';
import {NzIconModule, NzToolTipModule} from 'ng-zorro-antd';
import {NzIconModule} from 'ng-zorro-antd/icon';
import {NzToolTipModule} from 'ng-zorro-antd/tooltip';
import {IndexModule} from '../index/index.module';

View File

@@ -1,7 +1,5 @@
<div>
<div id="main">
<nz-alert [nzType]="type" [nzMessage]="message"
[nzDescription]="desc" nzShowIcon>
</nz-alert>
<nz-alert [nzDescription]="desc" [nzMessage]="message" [nzType]="type" nzShowIcon></nz-alert>
</div>
</div>
</div>

View File

@@ -1,6 +1,6 @@
#main{
#main {
width: 60%;
height: 50px;
margin: 0 auto;
padding: 15% 0;
}
}

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { EmailVerifyComponent } from './email-verify.component';
import {EmailVerifyComponent} from './email-verify.component';
describe('EmailVerifyComponent', () => {
let component: EmailVerifyComponent;
let fixture: ComponentFixture<EmailVerifyComponent>;
let component: EmailVerifyComponent;
let fixture: ComponentFixture<EmailVerifyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EmailVerifyComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EmailVerifyComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EmailVerifyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(EmailVerifyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -10,6 +10,12 @@ import {Title} from '@angular/platform-browser';
})
export class EmailVerifyComponent implements OnInit {
type: string = 'info';
message: string = '正在验证,请稍等';
desc: string = '';
private email: string;
private verifyId: string;
constructor(private titleService: Title,
private router: Router,
public routerinfo: ActivatedRoute,
@@ -17,14 +23,6 @@ export class EmailVerifyComponent implements OnInit {
titleService.setTitle('小海博客 | 邮箱验证');
}
type: string = 'info';
message: string = '正在验证,请稍等';
desc: string = '';
private email: string;
private verifyId: string;
ngOnInit(): void {
this.email = this.routerinfo.snapshot.queryParams.email;
this.verifyId = this.routerinfo.snapshot.queryParams.verifyId;

View File

@@ -2,7 +2,7 @@ import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {Route, RouterModule} from '@angular/router';
import {EmailVerifyComponent} from './email-verify.component';
import {NzAlertModule} from 'ng-zorro-antd';
import {NzAlertModule} from 'ng-zorro-antd/alert';
const routes: Route[] = [
{path: '**', component: EmailVerifyComponent}

View File

@@ -1,19 +1,19 @@
<nz-card id="article-card" [nzLoading]="data==null">
<nz-card [nzLoading]="data==null" id="article-card">
<h1><a [routerLink]="'/article/'+data.id">{{data.title}}</a></h1>
<div>
<span *ngIf="showMediaArea" id="article-original" [ngClass]="data.original?'original':'reproduced'">
<span *ngIf="showMediaArea" [ngClass]="data.original?'original':'reproduced'" id="article-original">
{{data.original ? '原创' : '转载'}}
</span>
<span *ngIf="showMediaArea" class="badge">
<i nz-icon nzType="calendar" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="calendar"></i>
<span>{{data.publishDateFormat}}</span>
</span>
<span *ngIf="showMediaArea" class="badge">
<i nz-icon nzType="user" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="user"></i>
<span>{{data.author.displayName}}</span>
</span>
<span *ngIf="showMediaArea" class="badge">
<i nz-icon nzType="file" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="file"></i>
<span>
<a [routerLink]="'/categories/'+data.category">{{data.category}}</a>
</span>
@@ -21,13 +21,13 @@
</div>
<p>{{data.summary}}</p>
<span style="float: right;margin-bottom: 10px">
<a [routerLink]="'/article/'+data.id">阅读更多<i nz-icon nzType="right" nzTheme="outline"></i></a>
<a [routerLink]="'/article/'+data.id">阅读更多<i nz-icon nzTheme="outline" nzType="right"></i></a>
</span>
<ng-template [ngIf]="showTagArea&&data.tags.length>0">
<nz-divider></nz-divider>
<div>
<span *ngFor="let tag of data.tags">
<i nz-icon nzType="tag" nzTheme="outline"></i>
<i nz-icon nzTheme="outline" nzType="tag"></i>
<a [routerLink]="'/tags/'+tag.name">{{tag.name}}</a>
</span>
</div>

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { ArticleDetailCardComponent } from './article-detail-card.component';
import {ArticleDetailCardComponent} from './article-detail-card.component';
describe('ArticleDetailCardComponent', () => {
let component: ArticleDetailCardComponent;
let fixture: ComponentFixture<ArticleDetailCardComponent>;
let component: ArticleDetailCardComponent;
let fixture: ComponentFixture<ArticleDetailCardComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ArticleDetailCardComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ArticleDetailCardComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ArticleDetailCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(ArticleDetailCardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,6 +1,5 @@
import {Component, Input, OnInit} from '@angular/core';
import {Article} from '../../../../class/Article';
import {ColorList} from '../../../../utils/color';
@Component({
selector: 'c-article-detail-card',
@@ -9,13 +8,13 @@ import {ColorList} from '../../../../utils/color';
})
export class ArticleDetailCardComponent implements OnInit {
constructor() {
}
@Input() data: Article;
@Input() showMediaArea: boolean;
@Input() showTagArea: boolean;
constructor() {
}
ngOnInit() {
if (this.data == null || this.data.id == null) {
throw Error('data 不可为空');

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { CardDetailComponent } from './card-detail.component';
import {CardDetailComponent} from './card-detail.component';
describe('CardDetailComponent', () => {
let component: CardDetailComponent;
let fixture: ComponentFixture<CardDetailComponent>;
let component: CardDetailComponent;
let fixture: ComponentFixture<CardDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CardDetailComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [CardDetailComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CardDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(CardDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -7,11 +7,11 @@ import {Component, Input, OnInit} from '@angular/core';
})
export class CardDetailComponent implements OnInit {
@Input() title: string;
constructor() {
}
@Input() title: string;
// @ContentChildren() c:T;
ngOnInit() {

View File

@@ -1,19 +1,19 @@
<div class="tag-tag" nz-tooltip
style="cursor: pointer"
[nzTooltipTitle]="tag.name"
(click)="click()">
<span class="tag-name"
[style.background-color]="randColor.bgColor"
<div (click)="click()" [nzTooltipTitle]="tag.name"
class="tag-tag"
nz-tooltip
style="cursor: pointer">
<span [style.background-color]="randColor.bgColor"
[style.color]="randColor.fontColor"
[style.font-size]="size=='large'?'large':''"
[style.padding]="size=='large'?'12px 15px':'5px 7px'"
class="tag-name"
>{{tag.name}}
</span>
<ng-template [ngIf]="enableCount">
<span class="tag-count"
[style.border-color]="randColor.bgColor"
<span [style.border-color]="randColor.bgColor"
[style.font-size]="size=='large'?'large':''"
[style.padding]="size=='large'?'11px 14px':'4px 6px'"
class="tag-count"
>{{tag.size}}
</span>
</ng-template>

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { TagTagComponent } from './tag-tag.component';
import {TagTagComponent} from './tag-tag.component';
describe('TagTagComponent', () => {
let component: TagTagComponent;
let fixture: ComponentFixture<TagTagComponent>;
let component: TagTagComponent;
let fixture: ComponentFixture<TagTagComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TagTagComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TagTagComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TagTagComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(TagTagComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,5 +1,5 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ColorList} from '../../../../utils/color';
import {COLOR_LIST} from '../../../../utils/color';
import {Router} from '@angular/router';
@Component({
@@ -9,20 +9,19 @@ import {Router} from '@angular/router';
})
export class TagTagComponent implements OnInit {
constructor(private router: Router) {
}
@Input() tag: { name: string, size: number };
@Input() tag: { name: string; size: number };
@Input() size: 'default' | 'large' = 'default';
@Input() clickable: boolean; // default true
@Input() enableCount: boolean; // default true
@Output() tagClick = new EventEmitter();
randColor: { bgColor: string; fontColor: string };
randColor: { bgColor: string, fontColor: string };
constructor(private router: Router) {
}
ngOnInit() {
const randomNumber = Math.floor(ColorList.length * Math.random());
this.randColor = ColorList[randomNumber];
const randomNumber = Math.floor(COLOR_LIST.length * Math.random());
this.randColor = COLOR_LIST[randomNumber];
if (this.clickable == null) {
this.clickable = true;
}

View File

@@ -1,83 +1,83 @@
<div nz-row id="index-container">
<div nz-col nzSpan="14" nzOffset="2" id="index-left">
<div id="index-container" nz-row>
<div id="index-left" nz-col nzOffset="2" nzSpan="14">
<ng-template [ngIf]="articles&&articles.total">
<c-article-detail-card *ngFor="let item of articles.list" [data]="item">
</c-article-detail-card>
</ng-template>
<nz-pagination style="text-align: center"
<nz-pagination (nzPageIndexChange)="getArticles($event)"
*ngIf="articles" [nzPageIndex]="articles.pageNum"
[nzTotal]="articles.total"
[nzPageSize]="articles.pageSize"
(nzPageIndexChange)="getArticles($event)">
[nzTotal]="articles.total"
style="text-align: center">
</nz-pagination>
</div>
<div nz-col nzSpan="5" nzOffset="1" id="index-right">
<div id="index-right" nz-col nzOffset="1" nzSpan="5">
<!-- 关于博主 -->
<c-card-detail title="关于博主">
<div id="index-bloger-container" title="">
<img id="index-bloger-pic"
[src]="imgUrl" alt="pic">
<img [src]="imgUrl"
alt="pic" id="index-bloger-pic">
<div id="index-bloger-desc">
<p><span style="font-weight: bold;font-size: x-large;"
[title]="desc"> 郑 海</span></p>
<p><span [title]="desc"
style="font-weight: bold;font-size: x-large;"> 郑 海</span></p>
<p><i nz-icon nzType="blog:location"></i> Location : 武汉</p>
<p><i nz-icon nzType="github" nzTheme="outline"></i>
Github : <a target="_blank" href="https://github.com/xiaohai2271"> link>></a>
<p><i nz-icon nzTheme="outline" nzType="github"></i>
Github : <a href="https://github.com/xiaohai2271" target="_blank"> link>></a>
</p>
</div>
</div>
<div id="index-bloger-button-area" title="">
<div id="index-bloger-qq-btn">
<i nz-icon nzType="qq" title="QQ二维码" nzTheme="outline"
style="color: #ff8936;border-color: #ff8936;cursor: pointer"
(mouseenter)="changeImg(qqQrImgUrl)" (mouseleave)="changeImg()"></i>
<i (mouseenter)="changeImg(qqQrImgUrl)" (mouseleave)="changeImg()" nz-icon nzTheme="outline"
nzType="qq"
style="color: #ff8936;border-color: #ff8936;cursor: pointer" title="QQ二维码"></i>
</div>
<div id="index-bloger-wx-btn">
<i nz-icon nzType="wechat" title="微信二维码" nzTheme="outline"
style="color: #7bcfa6;border-color: #7bcfa6;cursor: pointer"
(mouseenter)="changeImg(wxQrImgUrl)" (mouseleave)="changeImg()"></i>
<i (mouseenter)="changeImg(wxQrImgUrl)" (mouseleave)="changeImg()" nz-icon nzTheme="outline"
nzType="wechat"
style="color: #7bcfa6;border-color: #7bcfa6;cursor: pointer" title="微信二维码"></i>
</div>
</div>
</c-card-detail>
<!-- 分类云 -->
<c-card-detail title="分类云">
<div title="" style="text-align: center;user-select: none">
<c-tag-tag *ngFor="let category of categoryList"
[tag]="{name:category.name,size:category.articles.length}"
(tagClick)="toCategory(category.name)">
<div style="text-align: center;user-select: none" title="">
<c-tag-tag (tagClick)="toCategory(category.name)"
*ngFor="let category of categoryList"
[tag]="{name:category.name,size:category.articles.length}">
</c-tag-tag>
</div>
</c-card-detail>
<!-- 标签云 -->
<c-card-detail title="标签云">
<div title="" style="text-align: center;user-select: none">
<c-tag-tag *ngFor="let tag of tagNameAndNumber" [tag]="tag" (tagClick)="toTag(tag.name)">
<div style="text-align: center;user-select: none" title="">
<c-tag-tag (tagClick)="toTag(tag.name)" *ngFor="let tag of tagNameAndNumber" [tag]="tag">
</c-tag-tag>
</div>
</c-card-detail>
<!-- 网站信息 -->
<c-card-detail title="网站信息" id="index-site-info">
<c-card-detail id="index-site-info" title="网站信息">
<p *ngIf="counts && counts.articleCount">
<i nz-icon nzType="info-circle" nzTheme="outline"></i>文章总数: {{counts.articleCount}}篇
<i nz-icon nzTheme="outline" nzType="info-circle"></i>文章总数: {{counts.articleCount}}篇
</p>
<p *ngIf="counts && counts.categoryCount">
<i nz-icon nzType="info-circle" nzTheme="outline"></i>分类总数: {{counts.categoryCount}}个
<i nz-icon nzTheme="outline" nzType="info-circle"></i>分类总数: {{counts.categoryCount}}个
</p>
<p *ngIf="counts && counts.tagCount">
<i nz-icon nzType="info-circle" nzTheme="outline"></i>标签总数: {{counts.tagCount}}个
<i nz-icon nzTheme="outline" nzType="info-circle"></i>标签总数: {{counts.tagCount}}个
</p>
<p *ngIf="counts && counts.visitorCount">
<i nz-icon nzType="info-circle" nzTheme="outline"></i>访客总数: {{counts.visitorCount}}次
<i nz-icon nzTheme="outline" nzType="info-circle"></i>访客总数: {{counts.visitorCount}}次
</p>
<p *ngIf="lastestUpdate">
<i nz-icon nzType="info-circle" nzTheme="outline"></i>上次更新时间: {{lastestUpdate.lastUpdateTime}}
<i nz-icon nzTheme="outline" nzType="info-circle"></i>上次更新时间: {{lastestUpdate.lastUpdateTime}}
</p>
<p *ngIf="lastestUpdate&&lastestUpdate.committerDate">
<i nz-icon nzType="info-circle" nzTheme="outline"></i>上次提交代码时间: {{lastestUpdate.committerDate}}
<i nz-icon nzTheme="outline" nzType="info-circle"></i>上次提交代码时间: {{lastestUpdate.committerDate}}
</p>
</c-card-detail>

View File

@@ -1,25 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { IndexComponent } from './index.component';
import {IndexComponent} from './index.component';
describe('IndexComponent', () => {
let component: IndexComponent;
let fixture: ComponentFixture<IndexComponent>;
let component: IndexComponent;
let fixture: ComponentFixture<IndexComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ IndexComponent ]
})
.compileComponents();
}));
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [IndexComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(IndexComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
fixture = TestBed.createComponent(IndexComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,13 +1,12 @@
import {Component, OnInit} from '@angular/core';
import {ApiService} from '../../api/api.service';
import {Article} from '../../class/Article';
import {NzIconService, NzMessageService} from 'ng-zorro-antd';
import {NzIconService} from 'ng-zorro-antd/icon';
import {NzMessageService} from 'ng-zorro-antd/message';
import {SvgIconUtil} from '../../utils/svgIconUtil';
import {PageList} from '../../class/HttpReqAndResp';
import {ErrDispatch} from '../../class/ErrDispatch';
import {RequestObj} from '../../class/HttpReqAndResp';
import {PageList, RequestObj} from '../../class/HttpReqAndResp';
import {Router} from '@angular/router';
import {Category, Tag} from '../../class/Tag';
import {Category} from '../../class/Tag';
import {Title} from '@angular/platform-browser';
@Component({
@@ -16,33 +15,22 @@ import {Title} from '@angular/platform-browser';
styleUrls: ['./index.component.less'],
providers: [ApiService]
})
export class IndexComponent implements OnInit, ErrDispatch {
constructor(private apiService: ApiService,
private iconService: NzIconService,
private nzMessageService: NzMessageService,
private router: Router,
private title: Title) {
this.iconService.addIconLiteral('blog:location', SvgIconUtil.locationIcon);
apiService.setErrDispatch(this);
title.setTitle('小海博客');
}
export class IndexComponent implements OnInit {
readonly logoImgUrl: string = 'https://56462271.oss-cn-beijing.aliyuncs.com/web/logo.png';
readonly qqQrImgUrl: string = 'https://56462271.oss-cn-beijing.aliyuncs.com/web/qq.jpg';
readonly wxQrImgUrl: string = 'https://56462271.oss-cn-beijing.aliyuncs.com/web/wx.jpg';
imgUrl: string;
desc: string;
articles: PageList<Article>;
tagNameAndNumber: { name: string, size: number }[];
tagNameAndNumber: { name: string; size: number }[];
categoryList: Category[];
counts: {
articleCount: number,
visitorCount: number,
categoryCount: number,
tagCount: number,
commentCount: number
articleCount: number;
visitorCount: number;
categoryCount: number;
tagCount: number;
commentCount: number;
};
lastestUpdate: {
lastUpdateTime: string;
@@ -50,9 +38,18 @@ export class IndexComponent implements OnInit, ErrDispatch {
lastCommit: string;
committerAuthor: string;
committerDate: string;
commitUrl: string
commitUrl: string;
};
constructor(private apiService: ApiService,
private iconService: NzIconService,
private nzMessageService: NzMessageService,
private router: Router,
private title: Title) {
this.iconService.addIconLiteral('blog:location', SvgIconUtil.locationIcon);
title.setTitle('小海博客');
}
ngOnInit() {
this.imgUrl = this.logoImgUrl;
this.desc = '一个爱好瞎捣鼓的技术宅 :)\n欢迎一起来探讨学习。';

Some files were not shown because too many files have changed in this diff Show More