mirror of https://github.com/halo-dev/halo
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
parent
9f23b78fd9
commit
ebeba0fb52
|
@ -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",
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) }}
|
||||||
|
|
Loading…
Reference in New Issue