From e0df9ade6edfa1509cfc0b6fa363c6a018f9ef59 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Mon, 16 Jan 2023 10:58:13 +0800 Subject: [PATCH] feat: add full-functional post tag select component for formkit (halo-dev/console#817) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind feature #### What this PR does / why we need it: 添加功能更为全面的文章标签选择器,解决在标签过多场景下的适用性问题,支持以下特性: 1. 支持搜索标签。 2. 支持没有搜索结果的时候创建新标签。 3. 支持单选和多选。 > 当前并未考虑实现一个通用的标签创建组件,仅为文章考虑。 todo list: - [x] 样式整理 - [x] 重命名组件名 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2670 #### Screenshots: image image #### Special notes for your reviewer: 1. 创建若干文章,并进行标签设置的操作。 2. 测试标签选择,搜索,创建,删除,取消选择等操作。 #### Does this PR introduce a user-facing change? ```release-note 重构 Console 端的文章标签选择器。 ``` --- docs/custom-formkit-input/README.md | 2 + src/formkit/formkit.config.ts | 2 +- src/formkit/inputs/tag-select.ts | 24 -- src/formkit/inputs/tag-select/TagSelect.vue | 308 ++++++++++++++++++ src/formkit/inputs/tag-select/index.ts | 37 +++ .../inputs/tag-select/sections/index.ts | 8 + src/formkit/theme.ts | 13 + .../posts/components/PostSettingModal.vue | 3 +- .../posts/tags/components/PostTag.vue | 7 + 9 files changed, 378 insertions(+), 26 deletions(-) delete mode 100644 src/formkit/inputs/tag-select.ts create mode 100644 src/formkit/inputs/tag-select/TagSelect.vue create mode 100644 src/formkit/inputs/tag-select/index.ts create mode 100644 src/formkit/inputs/tag-select/sections/index.ts diff --git a/docs/custom-formkit-input/README.md b/docs/custom-formkit-input/README.md index 6a46d7b3f..caa60e384 100644 --- a/docs/custom-formkit-input/README.md +++ b/docs/custom-formkit-input/README.md @@ -22,6 +22,8 @@ - `categorySelect`:选择分类 - `categoryCheckbox`:选择多个分类 - `tagSelect`:选择标签 + - 参数 + 1. multiple: 是否多选,默认为 `false` - `tagCheckbox`:选择多个标签 在 Vue 单组件中使用: diff --git a/src/formkit/formkit.config.ts b/src/formkit/formkit.config.ts index 6ddc6e8a6..c5431313b 100644 --- a/src/formkit/formkit.config.ts +++ b/src/formkit/formkit.config.ts @@ -12,9 +12,9 @@ import { menuItemSelect } from "./inputs/menu-item-select"; import { postSelect } from "./inputs/post-select"; import { singlePageSelect } from "./inputs/singlePage-select"; import { categorySelect } from "./inputs/category-select"; -import { tagSelect } from "./inputs/tag-select"; import { categoryCheckbox } from "./inputs/category-checkbox"; import { tagCheckbox } from "./inputs/tag-checkbox"; +import { tagSelect } from "./inputs/tag-select/index"; import radioAlt from "./plugins/radio-alt"; import stopImplicitSubmission from "./plugins/stop-implicit-submission"; diff --git a/src/formkit/inputs/tag-select.ts b/src/formkit/inputs/tag-select.ts deleted file mode 100644 index c09ea09c2..000000000 --- a/src/formkit/inputs/tag-select.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { apiClient } from "@/utils/api-client"; -import type { FormKitNode, FormKitTypeDefinition } from "@formkit/core"; -import { select, selects, defaultIcon } from "@formkit/inputs"; - -function optionsHandler(node: FormKitNode) { - node.on("created", async () => { - const { data } = - await apiClient.extension.tag.listcontentHaloRunV1alpha1Tag(); - - node.props.options = data.items.map((tag) => { - return { - value: tag.metadata.name, - label: tag.spec.displayName, - }; - }); - }); -} - -export const tagSelect: FormKitTypeDefinition = { - ...select, - props: ["placeholder"], - forceTypeProp: "select", - features: [optionsHandler, selects, defaultIcon("select", "select")], -}; diff --git a/src/formkit/inputs/tag-select/TagSelect.vue b/src/formkit/inputs/tag-select/TagSelect.vue new file mode 100644 index 000000000..d6a5ee883 --- /dev/null +++ b/src/formkit/inputs/tag-select/TagSelect.vue @@ -0,0 +1,308 @@ + + + diff --git a/src/formkit/inputs/tag-select/index.ts b/src/formkit/inputs/tag-select/index.ts new file mode 100644 index 000000000..5efc26d59 --- /dev/null +++ b/src/formkit/inputs/tag-select/index.ts @@ -0,0 +1,37 @@ +import type { FormKitTypeDefinition } from "@formkit/core"; +import { + help, + icon, + inner, + label, + message, + messages, + outer, + prefix, + suffix, + wrapper, +} from "@formkit/inputs"; +import TagSelect from "./TagSelect.vue"; +import { TagSelectSection } from "./sections"; + +export const tagSelect: FormKitTypeDefinition = { + schema: outer( + wrapper( + label("$label"), + inner( + icon("prefix"), + prefix(), + TagSelectSection(), + suffix(), + icon("suffix") + ) + ), + help("$help"), + messages(message("$message.value")) + ), + type: "input", + props: ["multiple"], + library: { + TagSelect: TagSelect, + }, +}; diff --git a/src/formkit/inputs/tag-select/sections/index.ts b/src/formkit/inputs/tag-select/sections/index.ts new file mode 100644 index 000000000..5c1bb85a0 --- /dev/null +++ b/src/formkit/inputs/tag-select/sections/index.ts @@ -0,0 +1,8 @@ +import { createSection } from "@formkit/inputs"; + +export const TagSelectSection = createSection("TagSelectSection", () => ({ + $cmp: "TagSelect", + props: { + context: "$node.context", + }, +})); diff --git a/src/formkit/theme.ts b/src/formkit/theme.ts index d53887c03..d95a4a3bc 100644 --- a/src/formkit/theme.ts +++ b/src/formkit/theme.ts @@ -91,6 +91,19 @@ const theme: Record> = { content: "flex-1 p-2 col-span-11", controls: "bg-gray-200 col-span-1 flex items-center justify-center", }, + tagSelect: { + ...textClassification, + inner: `${textClassification.inner} !overflow-visible !h-auto min-h-[2.25rem]`, + input: `w-0 flex-grow outline-0 bg-transparent py-1 px-3 block transition-all appearance-none text-sm antialiased`, + "post-tags-wrapper": "flex w-full items-center", + "post-tags": "flex w-full flex-wrap items-center", + "post-tag-wrapper": "inline-flex items-center p-1", + "post-tag-close": + "h-4 w-4 cursor-pointer text-gray-600 hover:text-gray-900", + "post-tags-button": "inline-flex h-full cursor-pointer items-center px-1", + "dropdown-wrapper": + "absolute ring-1 ring-white top-full bottom-auto right-0 z-10 mt-1 max-h-96 w-full overflow-auto rounded bg-white shadow-lg", + }, }; export default theme; diff --git a/src/modules/contents/posts/components/PostSettingModal.vue b/src/modules/contents/posts/components/PostSettingModal.vue index 47c4ace11..7a4259f09 100644 --- a/src/modules/contents/posts/components/PostSettingModal.vue +++ b/src/modules/contents/posts/components/PostSettingModal.vue @@ -276,7 +276,8 @@ const annotationsFormRef = ref>(); v-model="formState.spec.tags" label="标签" name="tags" - type="tagCheckbox" + type="tagSelect" + :multiple="true" /> (), { + rounded: false, route: false, } ); @@ -43,8 +45,13 @@ const handleRouteToDetail = () => { background: tag.spec.color, color: labelColor, }" + :rounded="rounded" @click="handleRouteToDetail" > {{ tag.spec.displayName }} + +