91206763创建于 2025年8月4日历史提交
<template>
    <div class="auxiliary-line common-content-height">
        <el-form :model="form" label-width="70">
            <template v-if="!isNest">
                <common-content-top :value="form.content_top"></common-content-top>
                <div class="divider-line"></div>
            </template>
            <card-container class="card-container">
                <div class="mb-12">展示设置</div>
                <el-form-item label="导航样式">
                    <el-radio-group v-model="form.nav_style">
                        <el-radio value="image_with_text">图片加文字</el-radio>
                        <el-radio value="image">图片</el-radio>
                        <el-radio value="text">文字</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="显示设置">
                    <el-radio-group v-model="form.single_line">
                        <el-radio :value="3">三列展示</el-radio>
                        <el-radio :value="4">四列展示</el-radio>
                        <el-radio :value="5">五列展示</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="展示样式">
                    <el-radio-group v-model="form.display_style">
                        <el-radio value="fixed">固定显示</el-radio>
                        <el-radio value="slide">分页滑动</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item v-if="form.display_style === 'slide'" label="显示行数">
                    <el-radio-group v-model="form.row">
                        <el-radio :value="1">1行</el-radio>
                        <el-radio :value="2">2行</el-radio>
                        <el-radio :value="3">3行</el-radio>
                        <el-radio :value="4">4行</el-radio>
                    </el-radio-group>
                </el-form-item>
            </card-container>
            <div class="divider-line"></div>
            <card-container class="card-container">
                <div class="mb-12 flex-row align-c jc-sb">内容设置<div class="flex-row gap-10"><span class="classify-style" @click="classify_remove_all">清空</span><span class="classify-style" @click="classify_add">从分类添加</span></div></div>
                <div class="tips mt-10 mb-20 size-12">最多添加{{ form.nav_content_list.length }}张图片,建议尺寸90*90px</div>
                <div class="nav-list">
                    <drag :data="form.nav_content_list" type="card" :space-col="27" model-type="nav-group" :model-index="tabs_active_index" @remove="remove" @on-sort="on_sort" @click="tabs_list_click">
                        <template #default="{ row, index}">
                            <div class="flex-1 flex-col gap-10">
                                <div class="flex-row align-c jc-c w h is-newline">
                                    <upload v-model="row.img" :limit="1" size="72"></upload>
                                    <div class="flex-col flex-1 jc-c gap-20">
                                        <el-form-item label="标题" class="mb-0" label-width="50">
                                            <el-input v-model="row.title" placeholder="请输入标题" maxlength="10" show-word-limit clearable></el-input>
                                        </el-form-item>
                                        <el-form-item label="链接" class="w mb-0" label-width="50">
                                            <url-value v-model="row.link"></url-value>
                                        </el-form-item>
                                    </div>
                                </div>
                                <div v-if="!isEmpty(row.subscript) && !isEmpty(row.tabs_name)" class="not-label-width flex-col gap-10 w h">
                                    <!-- // 角标开关 -->
                                    <el-form-item label="角标" label-width="40" class="mb-0">
                                        <el-switch v-model="row.subscript.content.seckill_subscript_show" active-value="1" inactive-value="0"></el-switch>
                                    </el-form-item>
                                    <!-- 内容设置 -->
                                    <template v-if="tabs_active_index == index">
                                        <el-form v-if="row.subscript.content.seckill_subscript_show == '1'" :model="row.subscript.style" label-width="60">
                                            <el-tabs v-model="row.tabs_name" class="content-tabs" @tab-change="tabs_change(index)">
                                                <el-tab-pane label="内容设置" name="content">
                                                    <el-form-item label-width="0">
                                                        <div class="flex-col gap-10 w h">
                                                            <el-form-item label="类型" label-width="40">
                                                                <el-radio-group v-model="row.subscript.content.subscript_type">
                                                                    <el-radio value="text">文本</el-radio>
                                                                    <el-radio value="img-icon">图片或图标</el-radio>
                                                                </el-radio-group>
                                                            </el-form-item>
                                                            <el-form-item v-if="row.subscript.content.subscript_type != 'text'" label-width="40">
                                                                <upload v-model="row.subscript.content.subscript_img_src" v-model:icon-value="row.subscript.content.subscript_icon_class" is-icon :limit="1" size="50"></upload>
                                                            </el-form-item>
                                                            <el-form-item v-if="row.subscript.content.subscript_type == 'text'" label-width="40">
                                                                <el-input v-model="row.subscript.content.subscript_text" placeholder="请输入秒杀文字" clearable></el-input>
                                                            </el-form-item>
                                                        </div>
                                                    </el-form-item>
                                                </el-tab-pane>
                                                <el-tab-pane label="样式设置" name="styles">
                                                    <subscript-styles :value="row.subscript.style" :data="row.subscript.content" type="nav-group"></subscript-styles>
                                                </el-tab-pane>
                                            </el-tabs>
                                        </el-form>
                                    </template>
                                </div>
                            </div>
                        </template>
                    </drag>
                </div>
                <el-button class="mt-20 mb-20 w" @click="add">+添加</el-button>
            </card-container>
        </el-form>
        <category-dialog v-model:dialog-visible="dialogVisible" @confirm_event="confirm_event"></category-dialog>
    </div>
</template>
<script setup lang="ts">
import { get_math } from "@/utils";
import { cloneDeep, isEmpty } from "lodash";
import subscriptStyle from '@/config/const/subscript-style';

interface Props {
    value: nav_group_content;
    isNest?: boolean;
}
const props = withDefaults(defineProps<Props>(),{
    value: () => ({
        content_top: {},
        display_style: 'fixed',
        nav_style: 'image_with_text',
        single_line: 4,
        row: 1,
        nav_content_list: [
            {
                id: get_math(), // 唯一标识使用,避免使用index作为唯一标识导致渲染节点出现问题
                img: [],
                title: '',
                link: {},
                tabs_name: 'content',
                // 角标配置
                subscript: {
                    content: {
                        seckill_subscript_show: '0',
                        subscript_type: 'text',
                        subscript_img_src: [],
                        subscript_icon_class: '',
                        subscript_text: '角标',
                    },
                    style: {
                        ...subscriptStyle,
                        padding_top: 0,
                        padding_bottom: 0,
                        padding_left: 0,
                        padding_right: 0,
                    }
                }
            },
            {
                id: get_math(), // 唯一标识使用,避免使用index作为唯一标识导致渲染节点出现问题
                img: [],
                title: '',
                link: {},
                tabs_name: 'content',
                // 角标配置
                subscript: {
                    content: {
                        seckill_subscript_show: '0',
                        subscript_type: 'text',
                        subscript_img_src: [],
                        subscript_icon_class: '',
                        subscript_text: '角标',
                    },
                    style: {
                        ...subscriptStyle,
                        padding_top: 0,
                        padding_bottom: 0,
                        padding_left: 0,
                        padding_right: 0,
                    }
                }
            },
            {
                id: get_math(), // 唯一标识使用,避免使用index作为唯一标识导致渲染节点出现问题
                img: [],
                title: '',
                link: {},
                tabs_name: 'content',
                // 角标配置
                subscript: {
                    content: {
                        seckill_subscript_show: '0',
                        subscript_type: 'text',
                        subscript_img_src: [],
                        subscript_icon_class: '',
                        subscript_text: '角标',
                    },
                    style: {
                        ...subscriptStyle,
                        padding_top: 0,
                        padding_bottom: 0,
                        padding_left: 0,
                        padding_right: 0,
                    }
                }
            },
            {
                id: get_math(), // 唯一标识使用,避免使用index作为唯一标识导致渲染节点出现问题
                img: [],
                title: '',
                link: {},
                tabs_name: 'content',
                // 角标配置
                subscript: {
                    content: {
                        seckill_subscript_show: '0',
                        subscript_type: 'text',
                        subscript_img_src: [],
                        subscript_icon_class: '',
                        subscript_text: '角标',
                    },
                    style: {
                        ...subscriptStyle,
                        padding_top: 0,
                        padding_bottom: 0,
                        padding_left: 0,
                        padding_right: 0,
                    }
                }
            }
        ],
        isNest: false,
    })
});

const state = reactive({
    form: props.value
});
const { form } = toRefs(state);
const tabs_active_index = ref(0);
onBeforeMount(() => {
    tabs_active_index.value = 0;
    // 历史数据处理一下,避免有新增字段导致报错
    form.value.nav_content_list.forEach((item: any) => {
        item.tabs_name = !isEmpty(item.tabs_name) ? item.tabs_name : 'content',
        // 角标配置
        item.subscript = !isEmpty(item.subscript) ? item.subscript : 
            { 
                content: {
                    seckill_subscript_show: '0',
                    subscript_type: 'text',
                    subscript_img_src: [],
                    subscript_icon_class: '',
                    subscript_text: '角标',
                },
                style: {
                    ...subscriptStyle,
                    padding_top: 0,
                    padding_bottom: 0,
                    padding_left: 0,
                    padding_right: 0,
                }
            }
    });
});
const add = () => {
    form.value.nav_content_list.push({
        id: get_math(),
        img: [],
        title: '',
        link: {},
        tabs_name: 'content',
        // 角标配置
        subscript: {
            content: {
                seckill_subscript_show: '0',
                subscript_type: 'text',
                subscript_img_src: [],
                subscript_icon_class: '',
                subscript_text: '角标',
            },
            style: {
                ...subscriptStyle,
                padding_top: 0,
                padding_bottom: 0,
                padding_left: 0,
                padding_right: 0,
            }
        }
    });
    tabs_active_index.value = form.value.nav_content_list.length - 1;
    set_offset_top(tabs_active_index.value);
}
const remove = (index: number) => {
    if (form.value.nav_content_list.length > 0) {
        form.value.nav_content_list.splice(index, 1);
        if (form.value.nav_content_list.length > index) {
            tabs_active_index.value = index;
        } else {
            tabs_active_index.value = index - 1;
        }
    } else {
        tabs_active_index.value = 0;
    }
    set_offset_top(tabs_active_index.value);
}
// 拖拽更新之后,更新数据
const on_sort = (new_list: nav_group[]) => {
    form.value.nav_content_list = new_list;
}
//#region 弹窗相关
const dialogVisible = ref(false);
const classify_add = () => {
    dialogVisible.value = true;
}
// 清空全部
const classify_remove_all = () => {
    form.value.nav_content_list = [];
    tabs_active_index.value = 0;
}

interface categoryList extends pageLinkList {
    image: string;
}
const confirm_event = (list: categoryList[]) => {
    list.forEach(item => {
        // 如果图片为空,则为空数组
        const img = !isEmpty(item.image) ? [{ id: Number(item.id), url: item.image, original: item.name, title: item.name, ext: '.png', type: 'img' }] : [];
        form.value.nav_content_list.push({
            id: get_math(),
            img: img,
            title: item?.name || '',
            link: {
                id: Number(item.id),
                name: item.name,
                page: `/pages/goods-search/goods-search?category_id=${ item.id }`
            },
            tabs_name: 'content',
            // 角标配置
            subscript: {
                content: {
                    seckill_subscript_show: '0',
                    subscript_type: 'text',
                    subscript_img_src: [],
                    subscript_icon_class: '',
                    subscript_text: '角标',
                },
                style: {
                    ...subscriptStyle,
                    padding_top: 0,
                    padding_bottom: 0,
                    padding_left: 0,
                    padding_right: 0,
                }
            }
        });
    });
}
//#endregion
//#region 选项卡展开收起
const emits = defineEmits(['set_offset_top']);
//#region 获取offsetTop的位置
// 获取offsetTop的位置
const set_offset_top = (index: number) => {
    setTimeout(() => {
        const elements = Array.from(document.querySelectorAll('.nav-list .flex.gap-y-16.re'));
        if (elements && elements.length > 0) {
            elements.forEach((element: any, index1: number) => {
                if (index == index1) {
                    const offsetTop = element.offsetTop;
                    if (offsetTop != null) {
                        emits('set_offset_top', offsetTop);
                    }
                }
            })
        }
    }, 0)
}
// 选项卡中的tab切换
const tabs_change = (index: number) => {
    set_offset_top(index);
}
const tabs_list_click = (item: any, index: number) => {
    if (tabs_active_index.value !== index) {
        set_offset_top(index);
    }
    tabs_active_index.value = index;
}
//#endregion
</script>
<style lang="scss" scoped>
:deep(.size-12.cr-9.mt-10) {
    display: none;
}
.tips {
    color: $cr-info-dark;
}
.classify-style {
    cursor: pointer;
    color: $cr-main;
}
.not-label-width {
    :deep(.el-form-item__label) {
       width: 60px;
    }
    .card {
       padding: 0 !important;
    }
}
:deep(.content-tabs) {
    .flex-row.is-newline {
        flex-direction: column !important;
        align-items: flex-start;
    }
}
</style>