diff --git a/docs/custom-formkit-input/README.md b/docs/custom-formkit-input/README.md index caa60e38..39d1084c 100644 --- a/docs/custom-formkit-input/README.md +++ b/docs/custom-formkit-input/README.md @@ -20,6 +20,8 @@ - `postSelect`:选择文章 - `singlePageSelect`:选择自定义页面 - `categorySelect`:选择分类 + - 参数 + 1. multiple: 是否多选,默认为 `false` - `categoryCheckbox`:选择多个分类 - `tagSelect`:选择标签 - 参数 diff --git a/src/formkit/formkit.config.ts b/src/formkit/formkit.config.ts index c5431313..5b302894 100644 --- a/src/formkit/formkit.config.ts +++ b/src/formkit/formkit.config.ts @@ -11,10 +11,10 @@ import { menuRadio } from "./inputs/menu-radio"; import { menuItemSelect } from "./inputs/menu-item-select"; import { postSelect } from "./inputs/post-select"; import { singlePageSelect } from "./inputs/singlePage-select"; +import { tagSelect } from "./inputs/tag-select"; import { categorySelect } from "./inputs/category-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/category-select.ts b/src/formkit/inputs/category-select.ts deleted file mode 100644 index 35a42869..00000000 --- a/src/formkit/inputs/category-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.category.listcontentHaloRunV1alpha1Category(); - - node.props.options = data.items.map((category) => { - return { - value: category.metadata.name, - label: category.spec.displayName, - }; - }); - }); -} - -export const categorySelect: FormKitTypeDefinition = { - ...select, - props: ["placeholder"], - forceTypeProp: "select", - features: [optionsHandler, selects, defaultIcon("select", "select")], -}; diff --git a/src/formkit/inputs/category-select/CategorySelect.vue b/src/formkit/inputs/category-select/CategorySelect.vue new file mode 100644 index 00000000..cd62d4cb --- /dev/null +++ b/src/formkit/inputs/category-select/CategorySelect.vue @@ -0,0 +1,315 @@ + + + diff --git a/src/formkit/inputs/category-select/components/CategoryListItem.vue b/src/formkit/inputs/category-select/components/CategoryListItem.vue new file mode 100644 index 00000000..eb5f9a40 --- /dev/null +++ b/src/formkit/inputs/category-select/components/CategoryListItem.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/formkit/inputs/category-select/components/CategoryTag.vue b/src/formkit/inputs/category-select/components/CategoryTag.vue new file mode 100644 index 00000000..37a19b40 --- /dev/null +++ b/src/formkit/inputs/category-select/components/CategoryTag.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/formkit/inputs/category-select/components/SearchResultListItem.vue b/src/formkit/inputs/category-select/components/SearchResultListItem.vue new file mode 100644 index 00000000..5e7c80c7 --- /dev/null +++ b/src/formkit/inputs/category-select/components/SearchResultListItem.vue @@ -0,0 +1,67 @@ + + + diff --git a/src/formkit/inputs/category-select/index.ts b/src/formkit/inputs/category-select/index.ts new file mode 100644 index 00000000..6507627f --- /dev/null +++ b/src/formkit/inputs/category-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 CategorySelect from "./CategorySelect.vue"; +import { CategorySelectSection } from "./sections"; + +export const categorySelect: FormKitTypeDefinition = { + schema: outer( + wrapper( + label("$label"), + inner( + icon("prefix"), + prefix(), + CategorySelectSection(), + suffix(), + icon("suffix") + ) + ), + help("$help"), + messages(message("$message.value")) + ), + type: "input", + props: ["multiple"], + library: { + CategorySelect: CategorySelect, + }, +}; diff --git a/src/formkit/inputs/category-select/sections/index.ts b/src/formkit/inputs/category-select/sections/index.ts new file mode 100644 index 00000000..d0ef0cb5 --- /dev/null +++ b/src/formkit/inputs/category-select/sections/index.ts @@ -0,0 +1,11 @@ +import { createSection } from "@formkit/inputs"; + +export const CategorySelectSection = createSection( + "CategorySelectSection", + () => ({ + $cmp: "CategorySelect", + props: { + context: "$node.context", + }, + }) +); diff --git a/src/formkit/theme.ts b/src/formkit/theme.ts index d95a4a3b..3e7b386a 100644 --- a/src/formkit/theme.ts +++ b/src/formkit/theme.ts @@ -104,6 +104,17 @@ const theme: Record> = { "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", }, + categorySelect: { + ...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-categories-wrapper": "flex w-full items-center", + "post-categories": "flex w-full flex-wrap items-center", + "post-categories-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/categories/utils/index.ts b/src/modules/contents/posts/categories/utils/index.ts index 0a552d6d..13a9768c 100644 --- a/src/modules/contents/posts/categories/utils/index.ts +++ b/src/modules/contents/posts/categories/utils/index.ts @@ -121,3 +121,26 @@ export function convertCategoryTreeToCategory( }, }; } + +export const getCategoryPath = ( + categories: CategoryTree[], + name: string, + path: CategoryTree[] = [] +) => { + for (const category of categories) { + if (category.metadata && category.metadata.name === name) { + return path.concat([category]); + } + + if (category.spec && category.spec.children) { + const found = getCategoryPath( + category.spec.children, + name, + path.concat([category]) + ); + if (found) { + return found; + } + } + } +}; diff --git a/src/modules/contents/posts/components/PostSettingModal.vue b/src/modules/contents/posts/components/PostSettingModal.vue index 7a4259f0..d7eb79bf 100644 --- a/src/modules/contents/posts/components/PostSettingModal.vue +++ b/src/modules/contents/posts/components/PostSettingModal.vue @@ -270,7 +270,8 @@ const annotationsFormRef = ref>(); v-model="formState.spec.categories" label="分类目录" name="categories" - type="categoryCheckbox" + type="categorySelect" + :multiple="true" />