3.5.7.8 自定义菜单栏

在业务中,可能会遇到需要对菜单栏的交互或UI做全新设计的需求,这个时候可以自定义菜单栏组件支持。

首先继承平台的CustomMenuWidget 组件,将自己vue文件设置到component处

import { NavMenu, SPI, ViewWidget } from '@kunlun/dependencies';
import Component from './CustomMenu.vue';

@SPI.ClassFactory(
  ViewWidget.Token({
    // 这里的widget跟平台的组件一样,这样才能覆盖平台的组件
    widget: 'nav-menu'
  })
)
export class CustomMenuWidget extends NavMenu {

  public initialize(props) {
    super.initialize(props);
    this.setComponent(Component);
    return this;
  }
}

vue文件中继承平台的props,编写自定义页面代码

export const NavMenuProps = {
  /**
   * 当前模块
   */
  module: {
    type: Object as PropType<IModule | null>
  },
  /**
   * 树结构的菜单
   */
  menus: {
    type: Array as PropType<IResolvedMenu[]>,
    default: () => []
  },
  /**
   * 菜单类型,现在支持垂直、水平、和内嵌模式三种
   */
  mode: {
    type: String as PropType<'vertical' | 'horizontal' | 'inline'>,
    default: 'inline'
  },
  /**
   * 菜单栏是否折叠收起
   */
  collapsed: {
    type: Boolean,
    default: false
  },
  /**
   * 当前展开的 SubMenu 菜单项 key 数组
   */
  openKeys: {
    type: Array as PropType<string[]>,
    default: () => []
  },
  /**
   * 当前选中的菜单项 key 数组
   */
  selectKeys: {
    type: Array as PropType<string[]>,
    default: () => []
  },
  /**
   * 菜单搜索下拉选中菜单项
   */
  selectMenuBySearch: {
    type: Function as PropType<(menuName: String) => void>
  },
  /**
   * 选中菜单项
   */
  selectMenu: {
    type: Function as PropType<(menuName: String) => Promise<void>>
  },
  /**
   * SubMenu 展开/关闭的回调
   */
  openChange: {
    type: Function as PropType<(openKeys: string[]) => void>
  },
  /**
   * 菜单栏折叠的回调
   */
  onChangeCollapsed: {
    type: Function as PropType<(collapsed: boolean) => Promise<void>>
  }
};
<template>
  <div class="k-oinone-menu-wrapper custom-menu">
    <div class="menu-search" v-if="module && mode === 'inline' && !collapsed">
      <a-select
        ref="menuSelectSearch"
        dropdown-class-name="ui-designer-select-global"
        option-filter-prop="label"
        placeholder="搜索菜单"
        :show-search="true"
        @change="innerSearchSelect"
      >
        <a-select-option
          v-for="opt in module.allMenus.filter((_f) => _f.viewAction)"
          :key="opt.name"
          :value="opt.name"
          :label="opt.displayName"
        >
          {{ opt.displayName }}
        </a-select-option>
        <template #suffixIcon>
          <oio-icon icon="oinone-sousuo" size="14px" color="var(--oio-menu-default-icon-color)" />
        </template>
      </a-select>
    </div>
    <div class="menu-area oio-scrollbar">
      <div class="menu-content" :class="collapsed && 'collapsed'">
        <template v-for="item in menus" :key="item.key">
          <template v-if="!item.children || !item.children.length">
            <div :key="item.key" :title="item.title" class="root-menu" @click="selectMenu(item.key)">
              {{ item.title }}
            </div>
          </template>
          <template v-else>
            <div class="menu-group">
              <div class="root-menu" :title="item.title">{{ item.title }}</div>
              <div class="sub-menus">
                <template v-for="subItem in item.children" :key="subItem.key">
                  <div class="sub-menu" :title="subItem.title" @click="selectMenu(subItem.key)">
                    {{ subItem.title }}
                  </div>
                </template>
              </div>
            </div>
          </template>
        </template>
      </div>
    </div>

    <div class="menu-footer" :class="collapsed && 'collapsed'">
      <div class="menu-toggle-collapsed" @click="onChangeCollapsed(!collapsed)">
        <span class="collapsed-icon">
          <oio-icon
            :icon="collapsed ? 'oinone-menu-caidanzhankai' : 'oinone-menu-caidanshouqi'"
            size="16px"
            color="var(--oio-menu-default-icon-color)"
          />
        </span>
        <span v-show="!collapsed" class="collapsed-text">点击收起菜单</span>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, nextTick } from 'vue';
import { OioIcon, NavMenuProps } from '@kunlun/dependencies';

export default defineComponent({
  props: {
    ...NavMenuProps
  },
  components: {
    OioIcon
  },
  setup(props) {
    const DEFAULT_MENU_ICON = 'oinone-menu-caidanmoren';

    onMounted(async () => {
      await nextTick();
      props.onChangeCollapsed?.(false);
    });

    const menuSelectSearch = ref();
    const innerSearchSelect = (menuName) => {
      props.selectMenuBySearch?.(menuName);
      menuSelectSearch.value?.blur?.();
    };
    return {
      DEFAULT_MENU_ICON,
      menuSelectSearch,
      innerSearchSelect
    };
  }
});
</script>
<style lang="scss">
.custom-menu {
  .root-menu,
  .sub-menu {
    text-indent: 12px;
    cursor: pointer;
    &:hover {
      background: rgba(var(--oio-primary-color-rgb), 0.1);
    }
  }
  .sub-menus {
    padding-left: 20px;
  }
}
</style>

文件目录结构如下图

image.png

最后再到运行路径中导入该组件

这里以启动工程的 main.ts 举例,如果运行时未看到该组件的效果,请检查是否正确导入到运行时的路径中

image.png

以上自定义菜单栏的页面效果如下(该组件仅供演示,所以未实现3级菜单,可自行用子组件实现)

image.png

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9271.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
史, 昂's avatar史, 昂数式管理员
Previous 2024年5月23日 am9:07
Next 2024年5月23日 am9:09

相关推荐

  • 流程触发

    1. 流程触发 新增的流程设计页面默认包含两个节点,一个是流程的触发节点:确定流程开始的条件;另一个是流程结束的节点。 流程触发方式有模型触发、定时触发、日期触发三种方式,未设置流程触发方式时无法继续添加后续流程节点,同时无法进行流程发布,如左下图。触发方式设置完成后,可从左侧菜单栏拖入或流程箭头中的加号点击添加节点动作,如右下图。 1.1 模型触发 模型触发适用于模型中的数据字段变化开始流程的场景,比如员工请假审批流程。 模型触发的场景有数据的增删改,也可以对模型中的单个或多个字段进行条件筛选,若包含更新数据的场景可以设置选择更新字段,只有设置的字段更新才会触发流程,若不设置选择更新字段或者筛选条件,则模型中任一字段发生设置场景的变化时都会触发流程。 1.2 定时触发 定时触发适用于周期性调用流程的场景,比如仓库周期性盘点的流程。 需要设置一个流程第一次执行的时间,配置好循环的周期间隔。特殊的是选择周为周期时,当前周选中的日期也会执行流程。例:开始时间:2022-01-14(周四) 循环周期间隔:1周 自定义设置为周一到周五,则2022-01-15(本周五)也会执行流程操作。 1.3 日期触发 日期触发适用于模型中的日期时间字段引发流程的场景,比如给员工发生日祝福短信的流程。 设置日期触发时,若指定字段只包含日期,则必须要指定时刻,如左下图。例如给员工发生日祝福短信时根据模型中的员工生日数据获取到了执行流程的日期,需要制定开始该流程执行的具体时刻。若指定字段包含日期和时间,则不填写指定时刻时默认按照字段中的时刻开始执行流程,如右下图。例如办理业务后短信回访收集评价时根据模型中的业务完成时间,立即或延时发送短息。

    2024年6月20日
    2.3K00
  • 5.2 CDM之工程模式

    两种工程模式介绍 oinone推荐的两种工程模式都保留互联网特性,如跟业务无关的基础平台还是采用平台化思路建设。二种侧重点差异如下 第一种:比较适合企业采用多供应商联合开发场景,先以业务区分,各个业务线有独立的领域平台,最大限度保持不同业务线的独立性,有利于各个业务线独立发展(目前oinone上层星空系列产品采用这种工程模式,因为我们期望的时候帮助企业构建软件生态,必然要考虑不同供应商联合开发场景) 第二种:比较接近传统互联网架构,先按平台领域区分,如商品领域:商品平台做总工程,但里面按业务区分模块分子工程来保持业务相互独立,相对于第一种把领域的代码放一起,带来好处强化大家思考模型通用性。但不适用于跨公司主体间配合。 图5-2-1 Oinone-CDM的两种工程模式 注意事项: oinone兼容传统互联网架构 不管哪种模式,都需要解决CDM的维护问题 CDM维护的常见问题: Q:CDM层缺少模型怎么办? A:CDM层模型是逐步完善和丰富的。如果是特定业务自己需要的模型,这类模型无通用性。则加到自己的工程中;如果是通用的,则架构组确定是否需要纳入到CDM。 Q:CDM层已有的模型缺少字段怎么办? A:CDM层模型的字段也是逐步完善和丰富的,通用的字段在架构组确定后也会被吸收进来 Q:CDM层不同业务线相互影响怎么办? A:扩展字段最好带上自有前缀标志,如果觉得通用则提交架构组走模型缺少字段加入 Q:CDM层某模型新增加了的字段,但原先业务线已经加了相同含义字段 A:业务线可以把自己的字段related到CDM增加的新字段,并做数据迁移

    2024年5月23日
    2.1K00
  • 4.2.5 框架之网络请求-Request

    在中后台业务场景中,大部分的请求时候是可以被枚举的,比如创建、删除、更新、查询。在上文中,我们讲了httpClient如何自定义请求,来实现自己的业务诉求。本文中讲到的Request是离业务更近一步的封装,他提供了开箱即用的API,比如insertOne、updateOne,它是基于HttpClient做的二次封装,当你熟悉Request时,在中后台的业务场景中,所有的业务接口自定义将事半功倍。 一、Request详细介绍 元数据-model 获取模型实例 import { getModel } from '@kunlun/dependencies' getModel('modelName'); 图4-2-5-1 获取模型实例 清除所有缓存的模型 import { cleanModelCache } from '@kunlun/dependencies' cleanModelCache(); 图4-2-5-2 清除所有缓存的模型 元数据-module 获取应用实例,包含应用入口和菜单 import { queryModuleByName } from '@kunlun/dependencies' queryModuleByName('moduleName') 图4-2-5-3 获取应用实例 查询当前用户所有的应用 import { loadModules } from '@kunlun/dependencies' loadModules() 图4-2-5-4 查询当前用户所有的应用 query 分页查询 import { queryPage } from '@kunlun/dependencies' queryPage(modelName, { pageSize: 15, // 一次查询几条 currentPage, 1, // 当前页码 condition?: '' // 查询条件 maxDepth?: 1, // 查几层模型出来,如果有2,会把所有查询字段的关系字段都查出来 sort?: []; // 排序规则 }, fields, variables, context) 图4-2-5-5 分页查询 自定义分页查询-可自定义后端接口查询数据 import { customQueryPage } from '@kunlun/dependencies' customQueryPage(modelName, methodName, { pageSize: 15, // 一次查询几条 currentPage, 1, // 当前页码 condition?: '' // 查询条件 maxDepth?: 1, // 查几层模型出来,如果有2,会把所有查询字段的关系字段都查出来 sort?: []; // 排序规则 }, fields, variables, context) 图4-2-5-6 自定义分页查询 查询一条-根据params匹配出一条数据 import { queryOne } from '@kunlun/dependencies' customQueryPage(modelName, params, fields, variables, context) 图4-2-5-7 根据params匹配出一条数据 自定义查询 import { customQuery } from '@kunlun/dependencies' customQuery(methodName, modelName, record, fields, variables, context) 图4-2-5-8 自定义查询 update import { updateOne } from '@kunlun/dependencies' updateOne(modelName, record, fields, variables, context) 图4-2-5-9 update insert import { insertOne } from '@kunlun/dependencies' insertOne(modelName, record, fields, variables, context) 图4-2-5-10 insert delete import { deleteOne } from '@kunlun/dependencies'…

    2024年5月23日
    1.8K00

Leave a Reply

Please Login to Comment