refactor: simplify MenuItem with targetRef instead of multi refs (halo-dev/console#730)

#### What type of PR is this?

/kind improvement
/milestone 2.0

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

重构菜单项关联关系的引用方式。适配:https://github.com/halo-dev/halo/pull/2799

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

Fixes https://github.com/halo-dev/halo/issues/2739

#### Special notes for your reviewer:

测试方式:

1. Halo 需要切换到 https://github.com/halo-dev/halo/pull/2799 分支。
2. Console 需要 `pnpm install`
3. 创建若干带有关联关系的菜单项,检查创建和更新是否正常。

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

```release-note
None
```
pull/3445/head
Ryan Wang 2022-11-30 11:51:47 +08:00 committed by GitHub
parent 9f23b78fd9
commit ebeba0fb52
4 changed files with 90 additions and 108 deletions

View File

@ -32,7 +32,7 @@
"@formkit/themes": "^1.0.0-beta.12", "@formkit/themes": "^1.0.0-beta.12",
"@formkit/utils": "^1.0.0-beta.12", "@formkit/utils": "^1.0.0-beta.12",
"@formkit/vue": "^1.0.0-beta.12", "@formkit/vue": "^1.0.0-beta.12",
"@halo-dev/api-client": "^0.0.56", "@halo-dev/api-client": "^0.0.58",
"@halo-dev/components": "workspace:*", "@halo-dev/components": "workspace:*",
"@halo-dev/console-shared": "workspace:*", "@halo-dev/console-shared": "workspace:*",
"@halo-dev/richtext-editor": "^0.0.0-alpha.16", "@halo-dev/richtext-editor": "^0.0.0-alpha.16",

View File

@ -12,7 +12,7 @@ importers:
'@formkit/themes': ^1.0.0-beta.12 '@formkit/themes': ^1.0.0-beta.12
'@formkit/utils': ^1.0.0-beta.12 '@formkit/utils': ^1.0.0-beta.12
'@formkit/vue': ^1.0.0-beta.12 '@formkit/vue': ^1.0.0-beta.12
'@halo-dev/api-client': ^0.0.56 '@halo-dev/api-client': ^0.0.58
'@halo-dev/components': workspace:* '@halo-dev/components': workspace:*
'@halo-dev/console-shared': workspace:* '@halo-dev/console-shared': workspace:*
'@halo-dev/richtext-editor': ^0.0.0-alpha.16 '@halo-dev/richtext-editor': ^0.0.0-alpha.16
@ -104,7 +104,7 @@ importers:
'@formkit/themes': 1.0.0-beta.12-e579559_tailwindcss@3.2.4 '@formkit/themes': 1.0.0-beta.12-e579559_tailwindcss@3.2.4
'@formkit/utils': 1.0.0-beta.12-e579559 '@formkit/utils': 1.0.0-beta.12-e579559
'@formkit/vue': 1.0.0-beta.12-e579559_ior6jr3fpijijuwpr34w2i25va '@formkit/vue': 1.0.0-beta.12-e579559_ior6jr3fpijijuwpr34w2i25va
'@halo-dev/api-client': 0.0.56 '@halo-dev/api-client': 0.0.58
'@halo-dev/components': link:packages/components '@halo-dev/components': link:packages/components
'@halo-dev/console-shared': link:packages/shared '@halo-dev/console-shared': link:packages/shared
'@halo-dev/richtext-editor': 0.0.0-alpha.16_vue@3.2.45 '@halo-dev/richtext-editor': 0.0.0-alpha.16_vue@3.2.45
@ -1962,8 +1962,8 @@ packages:
- windicss - windicss
dev: false dev: false
/@halo-dev/api-client/0.0.56: /@halo-dev/api-client/0.0.58:
resolution: {integrity: sha512-Htwyk+pFNVGRrOLcabyNTPc5RQS/RwdUizrGWxRErBCXj4NIQyMYv3owcNS1lOMtsKXyfG1NX/cJKIw3g9y1WQ==} resolution: {integrity: sha512-CGDsHYrtVXD47Lt3S+KYJkyFZsrO85KE8wcuVb2y1iFLspTkKAPxD20Fuhf4TJYS/FVfjEi/esvU4sptTdLVjQ==}
dev: false dev: false
/@halo-dev/richtext-editor/0.0.0-alpha.16_vue@3.2.45: /@halo-dev/richtext-editor/0.0.0-alpha.16_vue@3.2.45:

View File

@ -2,7 +2,7 @@
import { VButton, VModal, VSpace } from "@halo-dev/components"; import { VButton, VModal, VSpace } from "@halo-dev/components";
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import { computed, ref, watch } from "vue"; import { computed, ref, watch } from "vue";
import type { Menu, MenuItem } from "@halo-dev/api-client"; import type { Menu, MenuItem, Ref } from "@halo-dev/api-client";
import { apiClient } from "@/utils/api-client"; import { apiClient } from "@/utils/api-client";
import { reset } from "@formkit/core"; import { reset } from "@formkit/core";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
@ -56,20 +56,16 @@ const handleSaveMenuItem = async () => {
try { try {
saving.value = true; saving.value = true;
const menuItemSource = menuItemSources.find( const menuItemRef = menuItemRefs.find(
(source) => source.value === selectedMenuItemSource.value (ref) => ref.ref?.kind === selectedRefKind.value
); );
if (menuItemSource) { if (menuItemRef) {
const { ref } = menuItemSource; formState.value.spec.targetRef = {
if (ref) { ...menuItemRef.ref,
formState.value.spec[ref] = { name: selectedRefName.value,
version: "content.halo.run/v1alpha1",
kind: menuItemSource.kind,
name: selectedRef.value as string,
}; };
} }
}
if (isUpdateMode.value) { if (isUpdateMode.value) {
const { data } = const { data } =
@ -123,8 +119,8 @@ const onVisibleChange = (visible: boolean) => {
const handleResetForm = () => { const handleResetForm = () => {
formState.value = cloneDeep(initialFormState); formState.value = cloneDeep(initialFormState);
selectedMenuItemSource.value = menuItemSources[0].value; selectedRefKind.value = "";
selectedRef.value = ""; selectedRefName.value = "";
selectedParentMenuItem.value = ""; selectedParentMenuItem.value = "";
reset("menuitem-form"); reset("menuitem-form");
}; };
@ -137,7 +133,7 @@ watch(
setFocus("displayNameInput"); setFocus("displayNameInput");
if (!props.menuItem) { if (!props.menuItem) {
selectedRef.value = ""; selectedRefName.value = "";
} }
} else { } else {
handleResetForm(); handleResetForm();
@ -152,79 +148,88 @@ watch(
formState.value = cloneDeep(menuItem); formState.value = cloneDeep(menuItem);
// Set Ref related // Set Ref related
const { postRef, categoryRef, tagRef, singlePageRef } = const { targetRef } = formState.value.spec;
formState.value.spec;
if (postRef) { if (!targetRef) {
selectedMenuItemSource.value = "post"; return;
selectedRef.value = postRef.name;
} }
if (categoryRef) { selectedRefName.value = targetRef.name;
selectedMenuItemSource.value = "category"; selectedRefKind.value = targetRef.kind as string;
selectedRef.value = categoryRef.name;
}
if (tagRef) {
selectedMenuItemSource.value = "tag";
selectedRef.value = tagRef.name;
}
if (singlePageRef) {
selectedMenuItemSource.value = "singlePage";
selectedRef.value = singlePageRef.name;
}
} else { } else {
handleResetForm(); handleResetForm();
} }
} }
); );
// MenuItem Ref interface MenuItemRef {
interface MenuItemSource {
label: string; label: string;
value: string; inputType?: string;
ref?: "postRef" | "categoryRef" | "tagRef" | "singlePageRef"; ref?: Ref;
kind?: "Post" | "Category" | "Tag" | "SinglePage";
} }
const menuItemSources: MenuItemSource[] = [ const baseRef: Ref = {
group: "content.halo.run",
version: "v1alpha1",
name: "",
};
const menuItemRefs: MenuItemRef[] = [
{ {
label: "自定义链接", label: "自定义链接",
value: "custom",
}, },
{ {
label: "文章", label: "文章",
value: "post", inputType: "postSelect",
ref: "postRef", ref: {
...baseRef,
kind: "Post", kind: "Post",
}, },
},
{ {
label: "自定义页面", label: "自定义页面",
value: "singlePage", inputType: "singlePageSelect",
ref: "singlePageRef", ref: {
...baseRef,
kind: "SinglePage", kind: "SinglePage",
}, },
},
{ {
label: "分类", label: "分类",
value: "category", inputType: "categorySelect",
ref: "categoryRef", ref: {
kind: "Post", ...baseRef,
kind: "Category",
},
}, },
{ {
label: "标签", label: "标签",
value: "tag", inputType: "tagSelect",
ref: "tagRef", ref: {
...baseRef,
kind: "Tag", kind: "Tag",
}, },
},
]; ];
const selectedMenuItemSource = ref<string>(menuItemSources[0].value); const menuItemRefsMap = menuItemRefs.map((menuItemRef) => {
return {
label: menuItemRef.label,
value: menuItemRef.ref?.kind,
};
});
const selectedRef = ref<string>(""); const selectedRef = computed(() => {
return menuItemRefs.find(
(menuItemRef) => menuItemRef.ref?.kind === selectedRefKind.value
);
});
const selectedRefKind = ref<string>("");
const selectedRefName = ref<string>("");
const onMenuItemSourceChange = () => { const onMenuItemSourceChange = () => {
selectedRef.value = ""; selectedRefName.value = "";
}; };
</script> </script>
<template> <template>
@ -252,8 +257,8 @@ const onMenuItemSourceChange = () => {
/> />
<FormKit <FormKit
v-model="selectedMenuItemSource" v-model="selectedRefKind"
:options="menuItemSources" :options="menuItemRefsMap"
:disabled="isUpdateMode" :disabled="isUpdateMode"
label="类型" label="类型"
type="select" type="select"
@ -261,7 +266,7 @@ const onMenuItemSourceChange = () => {
/> />
<FormKit <FormKit
v-if="selectedMenuItemSource === 'custom'" v-if="!selectedRefKind"
id="displayNameInput" id="displayNameInput"
v-model="formState.spec.displayName" v-model="formState.spec.displayName"
label="名称" label="名称"
@ -271,7 +276,7 @@ const onMenuItemSourceChange = () => {
/> />
<FormKit <FormKit
v-if="selectedMenuItemSource === 'custom'" v-if="!selectedRefKind"
v-model="formState.spec.href" v-model="formState.spec.href"
label="链接地址" label="链接地址"
type="text" type="text"
@ -280,37 +285,13 @@ const onMenuItemSourceChange = () => {
/> />
<FormKit <FormKit
v-if="selectedMenuItemSource === 'post'" v-if="selectedRef?.ref"
v-model="selectedRef" :id="selectedRef.inputType"
placeholder="请选择文章" :key="selectedRef.inputType"
label="文章" v-model="selectedRefName"
type="postSelect" :placeholder="`请选择${selectedRef.label}`"
validation="required" :label="selectedRef.label"
/> :type="selectedRef.inputType"
<FormKit
v-if="selectedMenuItemSource === 'singlePage'"
v-model="selectedRef"
label="自定义页面"
type="singlePageSelect"
validation="required"
/>
<FormKit
v-if="selectedMenuItemSource === 'tag'"
v-model="selectedRef"
placeholder="请选择标签"
label="标签"
type="tagSelect"
validation="required"
/>
<FormKit
v-if="selectedMenuItemSource === 'category'"
v-model="selectedRef"
placeholder="请选择分类"
label="分类"
type="categorySelect"
validation="required" validation="required"
/> />
</FormKit> </FormKit>

View File

@ -48,19 +48,20 @@ function onDelete(menuItem: MenuTreeItem) {
emit("delete", menuItem); emit("delete", menuItem);
} }
const TargetRef = {
Post: "文章",
SinglePage: "页面",
Category: "分类",
Tag: "标签",
};
function getMenuItemRefDisplayName(menuItem: MenuTreeItem) { function getMenuItemRefDisplayName(menuItem: MenuTreeItem) {
if (menuItem.spec.postRef) { const { kind } = menuItem.spec.targetRef || {};
return "文章";
} if (kind && TargetRef[kind]) {
if (menuItem.spec.singlePageRef) { return TargetRef[kind];
return "自定义页面";
}
if (menuItem.spec.categoryRef) {
return "分类";
}
if (menuItem.spec.tagRef) {
return "标签";
} }
return undefined; return undefined;
} }
</script> </script>
@ -89,7 +90,7 @@ function getMenuItemRefDisplayName(menuItem: MenuTreeItem) {
</div> </div>
</template> </template>
<template #start> <template #start>
<VEntityField :title="menuItem.status.displayName"> <VEntityField :title="menuItem.status?.displayName">
<template #extra> <template #extra>
<VTag v-if="getMenuItemRefDisplayName(menuItem)"> <VTag v-if="getMenuItemRefDisplayName(menuItem)">
{{ getMenuItemRefDisplayName(menuItem) }} {{ getMenuItemRefDisplayName(menuItem) }}