feat:【mall】diy editor 的 hot-zone 代码优化(100%)完成商品分类的支持

This commit is contained in:
YunaiV
2025-10-28 23:21:07 +08:00
parent 05dc2c7eb2
commit fe7a69f570
4 changed files with 63 additions and 51 deletions

View File

@@ -3,32 +3,33 @@ import { computed, onMounted, ref } from 'vue';
import { handleTree } from '@vben/utils';
import { ElTreeSelect } from 'element-plus';
import { getCategoryList } from '#/api/mall/product/category';
/** 商品分类选择组件 */
defineOptions({ name: 'ProductCategorySelect' });
const props = defineProps({
// ID
modelValue: {
type: [Number, Array<Number>],
default: undefined,
},
//
}, // ID
multiple: {
type: Boolean,
default: false,
},
//
}, //
parentId: {
type: Number,
default: undefined,
},
}, //
});
/** 分类选择 */
const emit = defineEmits(['update:modelValue']);
const categoryList = ref<any[]>([]); //
/** 选中的分类 ID */
const selectCategoryId = computed({
get: () => {
@@ -40,7 +41,6 @@ const selectCategoryId = computed({
});
/** 初始化 */
const categoryList = ref<any[]>([]); //
onMounted(async () => {
const data = await getCategoryList({
parentId: props.parentId,
@@ -49,20 +49,19 @@ onMounted(async () => {
});
</script>
<template>
<el-tree-select
<ElTreeSelect
v-model="selectCategoryId"
:data="categoryList"
node-key="id"
:props="{
children: 'children',
label: 'name',
value: 'id',
isLeaf: 'leaf',
emitPath: false,
}"
:multiple="multiple"
:show-checkbox="multiple"
class="w-1/1"
node-key="id"
check-strictly
default-expand-all
class="w-full"
placeholder="请选择商品分类"
/>
</template>

View File

@@ -0,0 +1 @@
export { default as ProductCategorySelect } from './category-select.vue';

View File

@@ -8,9 +8,15 @@ import { nextTick, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { getUrlNumberValue } from '@vben/utils';
import { ElButton, ElScrollbar, ElTooltip } from 'element-plus';
import {
ElButton,
ElForm,
ElFormItem,
ElScrollbar,
ElTooltip,
} from 'element-plus';
import ProductCategorySelect from '#/views/mall/product/category/components/product-category-select.vue';
import { ProductCategorySelect } from '#/views/mall/product/category/components/';
import { APP_LINK_GROUP_LIST, APP_LINK_TYPE_ENUM } from './data';
@@ -33,9 +39,7 @@ const groupBtnRefs = ref<ButtonInstance[]>([]); // 分组引用列表
const detailSelectDialog = ref<{
id?: number;
type?: APP_LINK_TYPE_ENUM;
visible: boolean;
}>({
visible: false,
id: undefined,
type: undefined,
}); // 详情选择对话框
@@ -48,6 +52,14 @@ const [Modal, modalApi] = useVbenModal({
},
});
const [DetailSelectModal, detailSelectModalApi] = useVbenModal({
onConfirm() {
detailSelectModalApi.close();
},
});
defineExpose({ open });
/** 打开弹窗 */
async function open(link: string) {
activeAppLink.value.path = link;
@@ -69,8 +81,6 @@ async function open(link: string) {
}
}
defineExpose({ open });
/** 处理 APP 链接选中 */
function handleAppLinkSelected(appLink: AppLink) {
if (!isSameLink(appLink.path, activeAppLink.value.path)) {
@@ -78,7 +88,6 @@ function handleAppLinkSelected(appLink: AppLink) {
}
switch (appLink.type) {
case APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST: {
detailSelectDialog.value.visible = true;
detailSelectDialog.value.type = appLink.type;
// 返显
detailSelectDialog.value.id =
@@ -86,6 +95,7 @@ function handleAppLinkSelected(appLink: AppLink) {
'id',
`http://127.0.0.1${activeAppLink.value.path}`,
) || undefined;
detailSelectModalApi.open();
break;
}
default: {
@@ -144,41 +154,41 @@ function isSameLink(link1: string, link2: string) {
/** 处理详情选择 */
function handleProductCategorySelected(id: number) {
// TODO @AI这里有点问题activeAppLink 地址;
// 生成 activeAppLink
const url = new URL(activeAppLink.value.path, 'http://127.0.0.1');
// 修改 id 参数
url.searchParams.set('id', `${id}`);
// 排除域名
activeAppLink.value.path = `${url.pathname}${url.search}`;
// 关闭对话框
detailSelectDialog.value.visible = false;
// 重置 id
// 关闭对话框,并重置 id
detailSelectModalApi.close();
detailSelectDialog.value.id = undefined;
}
</script>
<template>
<Modal title="选择链接" class="w-[65%]">
<div class="flex h-[500px] gap-2">
<!-- 左侧分组列表 -->
<ElScrollbar
wrap-class="h-full"
ref="groupScrollbar"
view-class="flex flex-col"
class="border-r border-gray-200 pr-2"
>
<ElButton
v-for="(group, groupIndex) in APP_LINK_GROUP_LIST"
:key="groupIndex"
class="ml-0 mr-4 w-[90px] justify-start"
:class="[{ active: activeGroup === group.name }]"
ref="groupBtnRefs"
:text="activeGroup !== group.name"
:type="activeGroup === group.name ? 'primary' : 'default'"
@click="handleGroupSelected(group.name)"
<div class="flex flex-col">
<!-- 左侧分组列表 -->
<ElScrollbar
wrap-class="h-full"
ref="groupScrollbar"
view-class="flex flex-col"
class="border-r border-gray-200 pr-2"
>
{{ group.name }}
</ElButton>
</ElScrollbar>
<ElButton
v-for="(group, groupIndex) in APP_LINK_GROUP_LIST"
:key="groupIndex"
class="!ml-0 mb-1 mr-4 !justify-start"
:class="[{ active: activeGroup === group.name }]"
ref="groupBtnRefs"
:text="activeGroup !== group.name"
:type="activeGroup === group.name ? 'primary' : 'default'"
@click="handleGroupSelected(group.name)"
>
{{ group.name }}
</ElButton>
</ElScrollbar>
</div>
<!-- 右侧链接列表 -->
<ElScrollbar
class="h-full flex-1 pl-2"
@@ -219,9 +229,9 @@ function handleProductCategorySelected(id: number) {
</div>
</Modal>
<el-dialog v-model="detailSelectDialog.visible" title="" width="50%">
<el-form class="min-h-[200px]">
<el-form-item
<DetailSelectModal title="选择分类" class="w-[65%]">
<ElForm class="min-h-[200px]">
<ElFormItem
label="选择分类"
v-if="
detailSelectDialog.type === APP_LINK_TYPE_ENUM.PRODUCT_CATEGORY_LIST
@@ -232,7 +242,7 @@ function handleProductCategorySelected(id: number) {
:parent-id="0"
@update:model-value="handleProductCategorySelected"
/>
</el-form-item>
</el-form>
</el-dialog>
</ElFormItem>
</ElForm>
</DetailSelectModal>
</template>

View File

@@ -167,11 +167,13 @@ const setHeight = (item: HotZoneItemProperty, height: number) => {
const activeHotZone = ref<HotZoneItemProperty>();
const appLinkDialogRef = ref();
/** 显示 App 链接选择对话框 */
const handleShowAppLinkDialog = (hotZone: HotZoneItemProperty) => {
activeHotZone.value = hotZone;
appLinkDialogRef.value.open(hotZone.url);
};
/** 处理 App 链接选择变更 */
const handleAppLinkChange = (appLink: AppLink) => {
if (!appLink || !activeHotZone.value) {
return;