feat: add cleanup tags support (#587)

Signed-off-by: Ryan Wang <i@ryanc.cc>

<!--  Thanks for sending a pull request!  Here are some tips for you:
1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。
1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>.
2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request.
3. 请确保你已经添加并运行了适当的测试。
3. Ensure you have added or ran the appropriate tests for your PR.
-->

#### What type of PR is this?

/kind feature
/milestone 1.6.x

<!--
添加其中一个类别:
Add one of the following kinds:

/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind optimization

适当添加其中一个或多个类别(可选):
Optionally add one or more of the following kinds if applicable:

/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

#### What this PR does / why we need it:

支持清理没有被文章使用的标签

#### Which issue(s) this PR fixes:

Fixes halo-dev/halo#2203

<!--
PR 合并时自动关闭 issue。
Automatically closes linked issue when PR is merged.

用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)`
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->

#### Screenshots:

<!--
如果此 PR 有 UI 的改动,最好截图说明这个 PR 的改动。
If there are UI changes to this PR, it is best to take a screenshot to illustrate the changes to this PR.

eg.

Before:

![screenshot-before](https://user-images.githubusercontent.com/screenshot.png)

After:

![screenshot-after](https://user-images.githubusercontent.com/screenshot.png)
-->


<img width="1330" alt="image" src="https://user-images.githubusercontent.com/21301288/179342105-11916eff-5908-4737-81dc-034244528554.png">

<img width="1331" alt="image" src="https://user-images.githubusercontent.com/21301288/179342113-1368128d-af84-4c95-af34-1da32c8ad52d.png">


#### Special notes for your reviewer:

/ping @halo-dev/sig-halo-admin 

#### Does this PR introduce a user-facing change?

<!--
如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。
否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change),
Release Note 需要以 `action required` 开头。
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->

```release-note
支持清理没有被文章使用的标签
```
pull/597/head
Ryan Wang 2022-07-18 22:48:08 +08:00 committed by GitHub
parent 02cbf3987c
commit ca8f1f138b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 424 additions and 58 deletions

View File

@ -1,4 +1,4 @@
lockfileVersion: 5.3
lockfileVersion: 5.4
specifiers:
'@ant-design/colors': 3.2.2
@ -58,7 +58,7 @@ dependencies:
'@codemirror/lang-java': 0.19.1
'@halo-dev/admin-api': 1.1.0
'@halo-dev/editor': 3.0.5
ant-design-vue: 1.7.8_9065e7474e033a8e4b95615fc8e6c36c
ant-design-vue: 1.7.8_sbs6or2oam5i4s4vmfp4rzwdnq
dayjs: 1.11.0
enquire.js: 2.1.6
filepond: 4.30.3
@ -85,17 +85,17 @@ dependencies:
devDependencies:
'@ant-design/colors': 3.2.2
'@babel/core': 7.17.9
'@babel/eslint-parser': 7.17.0_@babel+core@7.17.9+eslint@7.32.0
'@babel/eslint-parser': 7.17.0_t4il3idmfqwni5mkm6mrv4ujfe
'@tailwindcss/aspect-ratio': 0.4.0_tailwindcss@3.0.23
'@vue/cli-plugin-babel': 5.0.4_1a7ab14a3c0306b5654c447f15269443
'@vue/cli-plugin-eslint': 5.0.4_6084a5b0c7b00dd6f5be6d9e72604c89
'@vue/cli-plugin-babel': 5.0.4_dj5lcsr4amdlkzkmir7rkjuuim
'@vue/cli-plugin-eslint': 5.0.4_mccklmghwag5n5n6nwpheycmre
'@vue/cli-plugin-router': 5.0.4_@vue+cli-service@5.0.4
'@vue/cli-plugin-vuex': 5.0.4_@vue+cli-service@5.0.4
'@vue/cli-service': 5.0.4_5d13c34fbb1c7f04d8fb86bfe0fd54c5
'@vue/cli-service': 5.0.4_luj4gt53dr7qjwh3q276b7kuyu
compression-webpack-plugin: 9.2.0
eslint: 7.32.0
eslint-config-prettier: 8.5.0_eslint@7.32.0
eslint-plugin-prettier: 4.0.0_2544802fe0b6e1e28814bd742f96f471
eslint-plugin-prettier: 4.0.0_evcial7aw3q6fcauxv2c7fxuoe
eslint-plugin-vue: 8.6.0_eslint@7.32.0
husky: 6.0.0
less: 3.13.1
@ -129,7 +129,7 @@ packages:
dependencies:
tinycolor2: 1.4.2
/@ant-design/icons-vue/2.0.0_5210b89c4866a5e12cef6b8991791cc1:
/@ant-design/icons-vue/2.0.0_kiilrhcim2s6clhpnoezc6i4ye:
resolution: {integrity: sha512-2c0QQE5hL4N48k5NkPG5sdpMl9YnvyNhf0U7YkdZYDlLnspoRU7vIA0UK9eHBs6OpFLcJB6o8eJrIl2ajBskPg==}
peerDependencies:
'@ant-design/icons': ^2.0.0
@ -188,7 +188,7 @@ packages:
- supports-color
dev: true
/@babel/eslint-parser/7.17.0_@babel+core@7.17.9+eslint@7.32.0:
/@babel/eslint-parser/7.17.0_t4il3idmfqwni5mkm6mrv4ujfe:
resolution: {integrity: sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA==}
engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0}
peerDependencies:
@ -2131,16 +2131,16 @@ packages:
resolution: {integrity: sha512-ZTLAAydILjvx0XHUGSNu/cQDpmvLTMYUutDf2vf6XGkSWYqncQ6RwkeMSQhvQNlgpa/ovwIgrlGxLoojFRwdVg==}
dev: true
/@vue/cli-plugin-babel/5.0.4_1a7ab14a3c0306b5654c447f15269443:
/@vue/cli-plugin-babel/5.0.4_dj5lcsr4amdlkzkmir7rkjuuim:
resolution: {integrity: sha512-413ZwOWLtgw5vWJoMbrv36crW3qTas4Iru8sU7cRb0IqEZbS28R9X4PVtO8Pek2NYFbrs2XKRYOB7GblB6hVqg==}
peerDependencies:
'@vue/cli-service': ^3.0.0 || ^4.0.0 || ^5.0.0-0
dependencies:
'@babel/core': 7.17.9
'@vue/babel-preset-app': 5.0.4_vue@2.6.14
'@vue/cli-service': 5.0.4_5d13c34fbb1c7f04d8fb86bfe0fd54c5
'@vue/cli-service': 5.0.4_luj4gt53dr7qjwh3q276b7kuyu
'@vue/cli-shared-utils': 5.0.4
babel-loader: 8.2.3_146f664a5492b7663289772a77ab73de
babel-loader: 8.2.3_crxwmssusk3wmmujo4vhpk3t3y
thread-loader: 3.0.4_webpack@5.66.0
webpack: 5.66.0
transitivePeerDependencies:
@ -2153,16 +2153,16 @@ packages:
- webpack-cli
dev: true
/@vue/cli-plugin-eslint/5.0.4_6084a5b0c7b00dd6f5be6d9e72604c89:
/@vue/cli-plugin-eslint/5.0.4_mccklmghwag5n5n6nwpheycmre:
resolution: {integrity: sha512-NLBEKFTFJhYHMzQ3z+sb6xlkcNaN/RcbZ3hiCY72aJe4YOO8jEAp0XkPzlHd4xYkMW7jrmOwwLOPw+3BJ4b77Q==}
peerDependencies:
'@vue/cli-service': ^3.0.0 || ^4.0.0 || ^5.0.0-0
eslint: '>=7.5.0'
dependencies:
'@vue/cli-service': 5.0.4_5d13c34fbb1c7f04d8fb86bfe0fd54c5
'@vue/cli-service': 5.0.4_luj4gt53dr7qjwh3q276b7kuyu
'@vue/cli-shared-utils': 5.0.4
eslint: 7.32.0
eslint-webpack-plugin: 3.1.1_eslint@7.32.0+webpack@5.66.0
eslint-webpack-plugin: 3.1.1_r5ttmlnuwekoedpe3sb3jokknu
globby: 11.1.0
webpack: 5.66.0
yorkie: 2.0.0
@ -2179,7 +2179,7 @@ packages:
peerDependencies:
'@vue/cli-service': ^3.0.0 || ^4.0.0 || ^5.0.0-0
dependencies:
'@vue/cli-service': 5.0.4_5d13c34fbb1c7f04d8fb86bfe0fd54c5
'@vue/cli-service': 5.0.4_luj4gt53dr7qjwh3q276b7kuyu
'@vue/cli-shared-utils': 5.0.4
transitivePeerDependencies:
- encoding
@ -2190,10 +2190,10 @@ packages:
peerDependencies:
'@vue/cli-service': ^3.0.0 || ^4.0.0 || ^5.0.0-0
dependencies:
'@vue/cli-service': 5.0.4_5d13c34fbb1c7f04d8fb86bfe0fd54c5
'@vue/cli-service': 5.0.4_luj4gt53dr7qjwh3q276b7kuyu
dev: true
/@vue/cli-service/5.0.4_5d13c34fbb1c7f04d8fb86bfe0fd54c5:
/@vue/cli-service/5.0.4_luj4gt53dr7qjwh3q276b7kuyu:
resolution: {integrity: sha512-xRiLNTFYmMCT9edZpyYXHijW5xot3gbZpcWDOXUOhKPHN4qs4XqWALnZlU97JYjZOr3XIr/ZvyciyEfrlUVqSA==}
engines: {node: ^12.0.0 || >= 14.0.0}
hasBin: true
@ -2233,7 +2233,7 @@ packages:
'@vue/cli-plugin-vuex': 5.0.4_@vue+cli-service@5.0.4
'@vue/cli-shared-utils': 5.0.4
'@vue/component-compiler-utils': 3.3.0
'@vue/vue-loader-v15': /vue-loader/15.9.8_b9027617f4ed1744c121688a6a6ed625
'@vue/vue-loader-v15': /vue-loader/15.9.8_xebhmf7u5ulujqjbncfgu3wweu
'@vue/web-component-wrapper': 1.3.0
acorn: 8.7.0
acorn-walk: 8.2.0
@ -2255,7 +2255,7 @@ packages:
fs-extra: 9.1.0
globby: 11.1.0
hash-sum: 2.0.0
html-webpack-plugin: 5.5.0_acorn@8.7.0+webpack@5.66.0
html-webpack-plugin: 5.5.0_webpack@5.66.0
is-file-esm: 1.0.0
launch-editor-middleware: 2.3.0
less-loader: 5.0.0_less@3.13.1
@ -2266,10 +2266,10 @@ packages:
module-alias: 2.2.2
portfinder: 1.0.28
postcss: 8.4.6
postcss-loader: 6.2.1_postcss@8.4.6+webpack@5.66.0
postcss-loader: 6.2.1_htxkhb6jebiaoss5frze7mxjii
progress-webpack-plugin: 1.0.12_webpack@5.66.0
ssri: 8.0.1
terser-webpack-plugin: 5.3.0_acorn@8.7.0+webpack@5.66.0
terser-webpack-plugin: 5.3.0_webpack@5.66.0
thread-loader: 3.0.4_webpack@5.66.0
vue-loader: 17.0.0_webpack@5.66.0
vue-style-loader: 4.1.3
@ -2285,15 +2285,69 @@ packages:
- '@babel/core'
- '@parcel/css'
- '@swc/core'
- '@vue/compiler-sfc'
- arc-templates
- atpl
- babel-core
- bracket-template
- bufferutil
- clean-css
- coffee-script
- csso
- dot
- dust
- dustjs-helpers
- dustjs-linkedin
- eco
- ect
- ejs
- encoding
- esbuild
- haml-coffee
- hamlet
- hamljs
- handlebars
- hogan.js
- htmling
- jade
- jazz
- jqtpl
- just
- liquid-node
- liquor
- lodash
- marko
- mote
- mustache
- nunjucks
- plates
- pug
- qejs
- ractive
- razor-tmpl
- react
- react-dom
- slm
- squirrelly
- supports-color
- swig
- swig-templates
- teacup
- templayed
- then-jade
- then-pug
- tinyliquid
- toffee
- twig
- twing
- uglify-js
- underscore
- utf-8-validate
- vash
- velocityjs
- walrus
- webpack-cli
- whiskers
dev: true
/@vue/cli-shared-utils/5.0.4:
@ -2328,6 +2382,60 @@ packages:
vue-template-es2015-compiler: 1.9.1
optionalDependencies:
prettier: 2.6.2
transitivePeerDependencies:
- arc-templates
- atpl
- babel-core
- bracket-template
- coffee-script
- dot
- dust
- dustjs-helpers
- dustjs-linkedin
- eco
- ect
- ejs
- haml-coffee
- hamlet
- hamljs
- handlebars
- hogan.js
- htmling
- jade
- jazz
- jqtpl
- just
- liquid-node
- liquor
- lodash
- marko
- mote
- mustache
- nunjucks
- plates
- pug
- qejs
- ractive
- razor-tmpl
- react
- react-dom
- slm
- squirrelly
- swig
- swig-templates
- teacup
- templayed
- then-jade
- then-pug
- tinyliquid
- toffee
- twig
- twing
- underscore
- vash
- velocityjs
- walrus
- whiskers
dev: true
/@vue/web-component-wrapper/1.3.0:
@ -2629,7 +2737,7 @@ packages:
color-convert: 2.0.1
dev: true
/ant-design-vue/1.7.8_9065e7474e033a8e4b95615fc8e6c36c:
/ant-design-vue/1.7.8_sbs6or2oam5i4s4vmfp4rzwdnq:
resolution: {integrity: sha512-F1hmiS9vwbyfuFvlamdW5l9bHKqRlj9wHaGDIE41NZMWXyWy8qL0UFa/+I0Wl8gQWZCqODW5pN6Yfoyn85At3A==}
requiresBuild: true
peerDependencies:
@ -2637,7 +2745,7 @@ packages:
vue-template-compiler: ^2.6.0
dependencies:
'@ant-design/icons': 2.1.1
'@ant-design/icons-vue': 2.0.0_5210b89c4866a5e12cef6b8991791cc1
'@ant-design/icons-vue': 2.0.0_kiilrhcim2s6clhpnoezc6i4ye
'@simonwep/pickr': 1.7.4
add-dom-event-listener: 1.1.0
array-tree-filter: 2.1.0
@ -2769,7 +2877,7 @@ packages:
resolution: {integrity: sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==}
dev: false
/babel-loader/8.2.3_146f664a5492b7663289772a77ab73de:
/babel-loader/8.2.3_crxwmssusk3wmmujo4vhpk3t3y:
resolution: {integrity: sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==}
engines: {node: '>= 8.9'}
peerDependencies:
@ -2880,6 +2988,8 @@ packages:
qs: 6.9.6
raw-body: 2.4.2
type-is: 1.6.18
transitivePeerDependencies:
- supports-color
dev: true
/bonjour/3.5.0:
@ -3250,6 +3360,8 @@ packages:
on-headers: 1.0.2
safe-buffer: 5.1.2
vary: 1.1.2
transitivePeerDependencies:
- supports-color
dev: true
/concat-map/0.0.1:
@ -3264,6 +3376,167 @@ packages:
/consolidate/0.15.1:
resolution: {integrity: sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==}
engines: {node: '>= 0.10.0'}
peerDependencies:
arc-templates: ^0.5.3
atpl: '>=0.7.6'
babel-core: ^6.26.3
bracket-template: ^1.1.5
coffee-script: ^1.12.7
dot: ^1.1.3
dust: ^0.3.0
dustjs-helpers: ^1.7.4
dustjs-linkedin: ^2.7.5
eco: ^1.1.0-rc-3
ect: ^0.5.9
ejs: ^3.1.5
haml-coffee: ^1.14.1
hamlet: ^0.3.3
hamljs: ^0.6.2
handlebars: ^4.7.6
hogan.js: ^3.0.2
htmling: ^0.0.8
jade: ^1.11.0
jazz: ^0.0.18
jqtpl: ~1.1.0
just: ^0.1.8
liquid-node: ^3.0.1
liquor: ^0.0.5
lodash: ^4.17.20
marko: ^3.14.4
mote: ^0.2.0
mustache: ^3.0.0
nunjucks: ^3.2.2
plates: ~0.4.11
pug: ^3.0.0
qejs: ^3.0.5
ractive: ^1.3.12
razor-tmpl: ^1.3.1
react: ^16.13.1
react-dom: ^16.13.1
slm: ^2.0.0
squirrelly: ^5.1.0
swig: ^1.4.2
swig-templates: ^2.0.3
teacup: ^2.0.0
templayed: '>=0.2.3'
then-jade: '*'
then-pug: '*'
tinyliquid: ^0.2.34
toffee: ^0.3.6
twig: ^1.15.2
twing: ^5.0.2
underscore: ^1.11.0
vash: ^0.13.0
velocityjs: ^2.0.1
walrus: ^0.10.1
whiskers: ^0.4.0
peerDependenciesMeta:
arc-templates:
optional: true
atpl:
optional: true
babel-core:
optional: true
bracket-template:
optional: true
coffee-script:
optional: true
dot:
optional: true
dust:
optional: true
dustjs-helpers:
optional: true
dustjs-linkedin:
optional: true
eco:
optional: true
ect:
optional: true
ejs:
optional: true
haml-coffee:
optional: true
hamlet:
optional: true
hamljs:
optional: true
handlebars:
optional: true
hogan.js:
optional: true
htmling:
optional: true
jade:
optional: true
jazz:
optional: true
jqtpl:
optional: true
just:
optional: true
liquid-node:
optional: true
liquor:
optional: true
lodash:
optional: true
marko:
optional: true
mote:
optional: true
mustache:
optional: true
nunjucks:
optional: true
plates:
optional: true
pug:
optional: true
qejs:
optional: true
ractive:
optional: true
razor-tmpl:
optional: true
react:
optional: true
react-dom:
optional: true
slm:
optional: true
squirrelly:
optional: true
swig:
optional: true
swig-templates:
optional: true
teacup:
optional: true
templayed:
optional: true
then-jade:
optional: true
then-pug:
optional: true
tinyliquid:
optional: true
toffee:
optional: true
twig:
optional: true
twing:
optional: true
underscore:
optional: true
vash:
optional: true
velocityjs:
optional: true
walrus:
optional: true
whiskers:
optional: true
dependencies:
bluebird: 3.7.2
dev: true
@ -4017,16 +4290,25 @@ packages:
/de-indent/1.0.2:
resolution: {integrity: sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=}
dev: true
/debug/2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: true
/debug/3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.1.3
dev: true
@ -4384,7 +4666,7 @@ packages:
eslint: 7.32.0
dev: true
/eslint-plugin-prettier/4.0.0_2544802fe0b6e1e28814bd742f96f471:
/eslint-plugin-prettier/4.0.0_evcial7aw3q6fcauxv2c7fxuoe:
resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==}
engines: {node: '>=6.0.0'}
peerDependencies:
@ -4464,7 +4746,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/eslint-webpack-plugin/3.1.1_eslint@7.32.0+webpack@5.66.0:
/eslint-webpack-plugin/3.1.1_r5ttmlnuwekoedpe3sb3jokknu:
resolution: {integrity: sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==}
engines: {node: '>= 12.13.0'}
peerDependencies:
@ -4676,6 +4958,8 @@ packages:
type-is: 1.6.18
utils-merge: 1.0.1
vary: 1.1.2
transitivePeerDependencies:
- supports-color
dev: true
/fast-deep-equal/3.1.3:
@ -4770,6 +5054,8 @@ packages:
parseurl: 1.3.3
statuses: 1.5.0
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
dev: true
/find-cache-dir/3.3.2:
@ -5035,7 +5321,6 @@ packages:
/he/1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
dev: true
/highlight.js/10.7.3:
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
@ -5063,7 +5348,7 @@ packages:
resolution: {integrity: sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==}
dev: true
/html-minifier-terser/6.1.0_acorn@8.7.0:
/html-minifier-terser/6.1.0:
resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==}
engines: {node: '>=12'}
hasBin: true
@ -5074,9 +5359,7 @@ packages:
he: 1.2.0
param-case: 3.0.4
relateurl: 0.2.7
terser: 5.10.0_acorn@8.7.0
transitivePeerDependencies:
- acorn
terser: 5.10.0
dev: true
/html-tags/2.0.0:
@ -5089,20 +5372,18 @@ packages:
engines: {node: '>=8'}
dev: true
/html-webpack-plugin/5.5.0_acorn@8.7.0+webpack@5.66.0:
/html-webpack-plugin/5.5.0_webpack@5.66.0:
resolution: {integrity: sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==}
engines: {node: '>=10.13.0'}
peerDependencies:
webpack: ^5.20.0
dependencies:
'@types/html-minifier-terser': 6.1.0
html-minifier-terser: 6.1.0_acorn@8.7.0
html-minifier-terser: 6.1.0
lodash: 4.17.21
pretty-error: 4.0.0
tapable: 2.2.1
webpack: 5.66.0
transitivePeerDependencies:
- acorn
dev: true
/htmlparser2/6.1.0:
@ -6514,6 +6795,8 @@ packages:
async: 2.6.3
debug: 3.2.7
mkdirp: 0.5.5
transitivePeerDependencies:
- supports-color
dev: true
/postcss-calc/8.2.2_postcss@8.4.6:
@ -6608,7 +6891,7 @@ packages:
yaml: 1.10.2
dev: true
/postcss-loader/6.2.1_postcss@8.4.6+webpack@5.66.0:
/postcss-loader/6.2.1_htxkhb6jebiaoss5frze7mxjii:
resolution: {integrity: sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==}
engines: {node: '>= 12.13.0'}
peerDependencies:
@ -7348,6 +7631,8 @@ packages:
on-finished: 2.3.0
range-parser: 1.2.1
statuses: 1.5.0
transitivePeerDependencies:
- supports-color
dev: true
/serialize-javascript/6.0.0:
@ -7367,6 +7652,8 @@ packages:
http-errors: 1.6.3
mime-types: 2.1.34
parseurl: 1.3.3
transitivePeerDependencies:
- supports-color
dev: true
/serve-static/1.14.2:
@ -7377,6 +7664,8 @@ packages:
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.17.2
transitivePeerDependencies:
- supports-color
dev: true
/setprototypeof/1.1.0:
@ -7783,7 +8072,7 @@ packages:
engines: {node: '>=6'}
dev: true
/terser-webpack-plugin/5.3.0_acorn@8.7.0+webpack@5.66.0:
/terser-webpack-plugin/5.3.0_webpack@5.66.0:
resolution: {integrity: sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ==}
engines: {node: '>= 10.13.0'}
peerDependencies:
@ -7803,18 +8092,14 @@ packages:
schema-utils: 3.1.1
serialize-javascript: 6.0.0
source-map: 0.6.1
terser: 5.10.0_acorn@8.7.0
terser: 5.10.0
webpack: 5.66.0
transitivePeerDependencies:
- acorn
dev: true
/terser/5.10.0_acorn@8.7.0:
/terser/5.10.0:
resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==}
engines: {node: '>=10'}
hasBin: true
peerDependencies:
acorn: ^8.5.0
peerDependenciesMeta:
acorn:
optional: true
@ -8080,14 +8365,17 @@ packages:
resolution: {integrity: sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==}
dev: true
/vue-loader/15.9.8_b9027617f4ed1744c121688a6a6ed625:
/vue-loader/15.9.8_xebhmf7u5ulujqjbncfgu3wweu:
resolution: {integrity: sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==}
peerDependencies:
'@vue/compiler-sfc': ^3.0.8
cache-loader: '*'
css-loader: '*'
vue-template-compiler: '*'
webpack: ^3.0.0 || ^4.1.0 || ^5.0.0-0
peerDependenciesMeta:
'@vue/compiler-sfc':
optional: true
cache-loader:
optional: true
vue-template-compiler:
@ -8101,6 +8389,60 @@ packages:
vue-style-loader: 4.1.3
vue-template-compiler: 2.6.14
webpack: 5.66.0
transitivePeerDependencies:
- arc-templates
- atpl
- babel-core
- bracket-template
- coffee-script
- dot
- dust
- dustjs-helpers
- dustjs-linkedin
- eco
- ect
- ejs
- haml-coffee
- hamlet
- hamljs
- handlebars
- hogan.js
- htmling
- jade
- jazz
- jqtpl
- just
- liquid-node
- liquor
- lodash
- marko
- mote
- mustache
- nunjucks
- plates
- pug
- qejs
- ractive
- razor-tmpl
- react
- react-dom
- slm
- squirrelly
- swig
- swig-templates
- teacup
- templayed
- then-jade
- then-pug
- tinyliquid
- toffee
- twig
- twing
- underscore
- vash
- velocityjs
- walrus
- whiskers
dev: true
/vue-loader/17.0.0_webpack@5.66.0:
@ -8142,7 +8484,6 @@ packages:
dependencies:
de-indent: 1.0.2
he: 1.2.0
dev: true
/vue-template-es2015-compiler/1.9.1:
resolution: {integrity: sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==}
@ -8150,7 +8491,6 @@ packages:
/vue/2.6.14:
resolution: {integrity: sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==}
dev: false
/vuedraggable/2.24.3:
resolution: {integrity: sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==}
@ -8347,7 +8687,7 @@ packages:
neo-async: 2.6.2
schema-utils: 3.1.1
tapable: 2.2.1
terser-webpack-plugin: 5.3.0_acorn@8.7.0+webpack@5.66.0
terser-webpack-plugin: 5.3.0_webpack@5.66.0
watchpack: 2.3.1
webpack-sources: 3.2.3
transitivePeerDependencies:

View File

@ -1,7 +1,5 @@
<template>
<a-tag :color="tag.color" :style="{ color: labelColor }">
{{ tag.name }}
</a-tag>
<a-tag :color="tag.color" :style="{ color: labelColor }"> {{ tag.name }}({{ tag.postCount }})</a-tag>
</template>
<script>
import { isHex, isLight } from '@/utils/colorUtil'

View File

@ -60,14 +60,18 @@
</a-col>
<a-col :lg="14" :md="14" :sm="24" :xl="14" :xs="24" class="pb-3">
<a-card :bodyStyle="{ padding: '16px' }" title="所有标签">
<template #extra>
<a class="p-0 m-0" href="javascript:void(0)" @click="handleCleanup">使</a>
</template>
<a-spin :spinning="list.loading">
<a-empty v-if="list.data.length === 0" />
<a-tooltip v-for="tag in list.data" v-else :key="tag.id" placement="topLeft">
<template slot="title">
<span>{{ tag.postCount }} 篇文章</span>
</template>
<post-tag :tag="tag" style="margin-bottom: 8px; cursor: pointer" @click.native="handleEdit(tag)" />
</a-tooltip>
<post-tag
v-for="tag in list.data"
:key="tag.id"
:tag="tag"
style="margin-bottom: 8px; cursor: pointer"
@click.native="handleEdit(tag)"
/>
</a-spin>
</a-card>
</a-col>
@ -187,6 +191,30 @@ export default {
}
_this.handleListTags()
}
},
handleCleanup() {
const tags = this.list.data.filter(tag => {
return tag.postCount === 0
})
this.$confirm({
title: '提示',
content: '是否确认清理没有使用的标签?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
try {
const promises = tags.map(tag => {
return apiClient.tag.delete(tag.id)
})
await Promise.all(promises)
} catch (e) {
this.$log.error('Failed to cleanup tags:', e)
} finally {
this.handleListTags()
}
}
})
}
}
}