3.5.7.2 自定义母版

母版是什么

在业务系统中,母版是一种全局通用的组件,用于包裹每个页面的元素。这个概念类似于 PPT 中的母版,它定义了页面的整体结构、样式和布局,使得系统具有一致的外观和风格。

特点:

  1. 全局通用:母版是全局性的,适用于系统中的每个页面,确保一致性的用户体验。

  2. 包裹元素:母版包裹每个页面的元素,定义了整体的结构和布局。

  3. 外观一致性:通过统一的母版设计,系统达到外观和风格的一致性。

与 PPT 母版的类比:

在母版的概念上,与 PPT 中的母版类似,都是用于定义整体结构和样式,确保每个页面都具有一致的外观。

默认母版范围:

image.png

图3-5-7-20 默认母版范围

作用场景

在系统中,我们提供了多个纬度的母版,包括全局、应用和页面纬度。这样的设计允许根据不同的业务场景选择合适的母版纬度,以满足不同层次的定制需求。

母版纬度:

  1. 全局母版:

    • 覆盖系统中所有页面,确保全局的一致性和统一的用户体验。
    • 定义全局性的结构、样式和布局。
  2. 应用母版:

    • 适用于特定应用或模块,定制化程度介于全局和页面之间。
    • 允许在不同应用间实现一定的差异化。
  3. 页面母版:

    • 面向具体页面,提供最大的定制化空间。
    • 允许在不同页面中定义不同的结构和样式。

选择纬度:

  • 业务场景决定:根据具体的业务场景和需求选择合适的母版纬度。
  • 定制化需求:如果需要全局一致性,选择全局母版;如果在应用层面有特定需求,选择应用母版;如果需要最大的灵活性和定制化,选择页面母版。

参数说明:

在系统中,使用 registerMask 注册母版时,需要提供两个参数。第一个参数是母版的 XML,第二个参数用于控制母版的注册行为,包括 module、moduleName、model 和 actionName。

  1. 母版 XML(第一个参数):

    • 提供母版的 XML 描述,定义了母版的结构和样式。
  2. 控制参数(第二个参数):

    • module:指定模块的名称。
    • moduleName:指定模块的显示名称。
    • model:指定母版所属的模型。
    • actionName:指定母版的操作名称,可以是字符串或字符串数组。

全局母版

可以使用 registerMask 注册母版。当第二个参数为 {} 时,即代表注册全局母版。

示例工程目录

以下是需关注的工程目录示例,并确保导入导出依赖正确:

image.png

图3-5-7-21 全局纬度注册母版工程目录示例

示例代码

以下是一个示例代码:

import { registerMask } from '@kunlun/dependencies';

/**
 * mask: 在做系统时,我们通常会把外层的布局(菜单、顶部导航)等抽出公共组件,公共组件会抽离全局通用。类似ppt母版的概念即为Mask
 * registerMask 第二个入参为{}即注册了全局得母版
 *
 * 和默认母版相比移除右上角消息、语言切换、用户
 * `<block>
 *     <widget widget="notification" />
 *     <widget widget="divider" />
 *     <widget widget="language" />
 *     <widget widget="divider" />
 *     <widget widget="user" />
 * </block>`
 */
const registerGlobalMask = () => {
    registerMask(`
    <mask>
        <multi-tabs />
        <header>
            <widget widget="app-switcher" />
        </header>
        <container>
            <sidebar>
                <widget widget="nav-menu" height="100%" />
            </sidebar>
            <content>
                <breadcrumb />
                <block width="100%">
                    <widget width="100%" widget="main-view" />
                </block>
            </content>
        </container>
    </mask>`, {});
}

registerGlobalMask();

图3-5-7-22 全局纬度注册母版代码示例

复制这段代码执行下registerGlobalMask()试试看吧

效果

右上角消息、语言切换、用户被移除。

image.png

图3-5-7-23 全局纬度注册母版效果示例

应用母版

在系统中,可以使用 registerMask 注册母版。当第二个参数为 {moduleName: 'resource'} 时,即注册了 resource(资源)应用的母版。

示例工程目录

以下是需关注的工程目录示例,更新导出./moduleMask:

image.png

图3-5-7-24 应用纬度注册母版工程目录示例

示例代码

以下是一个示例代码:

/**
 * registerMask 第二个入参为{moduleName: 'resource'}即注册了resource(资源)应用的母版
 *
 * resource来源: 通常是浏览器url上的module
 *
 * 和默认模版相比拿掉了菜单
 * `<sidebar>
 *    <widget widget="nav-menu" height="100%" />
 *  </sidebar>`
 * */
const registerModuleMask = () => {
    registerMask(`<mask>
    <multi-tabs />
    <header>
        <widget widget="app-switcher" />
        <block>
            <widget widget="notification" />
            <widget widget="divider" />
            <widget widget="language" />
            <widget widget="divider" />
            <widget widget="user" />
        </block>
    </header>
    <container>
        <content>
            <breadcrumb />
            <block width="100%">
                <widget width="100%" widget="main-view" />
            </block>
        </content>
    </container>
</mask>`, { moduleName: 'resource'})
}

registerModuleMask();

图3-5-7-25 应用纬度注册母版代码示例

在这个示例中,通过将第二个参数设置为 {moduleName: 'resource'},实现了注册 resource 应用的母版。该母版包含了特定于 resource 应用的全局结构和布局,并在示例中去掉了菜单部分。

这样的设计使得可以根据不同应用注册不同的母版,以满足应用层面的定制需求。

效果

image.png

图3-5-7-26 应用纬度注册母版效果示例

页面母版

在系统中,可以使用 registerMask 注册母版。当第二个参数为 {moduleName: 'resource', model: 'resource.ResourceRegionProxyModel'} 时,即注册了 resource(资源)应用和 这个应用下ResourceRegionProxyModel(地区)模型的母版。

示例工程目录

以下是需关注的工程目录示例,更新导出./viewMask:

image.png

图3-5-7-27 页面纬度注册母版工程目录示例

示例代码

以下是一个示例代码:

/**
 * registerMask 第二个入参为{moduleName: 'resource', model: 'resource.ResourceRegionProxyModel'}即注册了resource(资源)和resource.ResourceRegionProxyModel(地区)模型的母版
 *
 * resource来源: 通常是浏览器url上的module
 * model来源:  通常是浏览器url上的model
 *
 * 拿掉菜单
 * `<sidebar>
 *    <widget widget="nav-menu" height="100%" />
 *  </sidebar>`
 *
 *  拿掉appFounder
 *  `<widget widget="app-switcher" />`
 * */
const registerViewMask = () => {
  registerMask(`<mask>
    <multi-tabs />
    <header>
        <block>
            <widget widget="notification" />
            <widget widget="divider" />
            <widget widget="language" />
            <widget widget="divider" />
            <widget widget="user" />
        </block>
    </header>
    <container>
        <content>
            <breadcrumb />
            <block width="100%">
                <widget width="100%" widget="main-view" />
            </block>
        </content>
    </container>
</mask>`, { moduleName: 'resource', model: 'resource.ResourceRegionProxyModel'})
}
registerViewMask();

图3-5-7-28 页面纬度注册母版代码示例

在这个示例中,通过将第二个参数设置为 {moduleName: 'resource', model: 'resource.ResourceRegionProxyModel'},实现了注册 Resource 应用和 ResourceRegionProxyModel 模型的母版。该母版包含了特定于这两个条件的全局结构和布局,并在示例中去掉了菜单和应用切换部分。

效果

image.png

图3-5-7-29 页面纬度注册母版效果示例

这样的设计使得可以根据不同应用和模型注册不同的母版,以满足不同层次的定制需求

扩展母版

在系统中,除了平台内置的母版组件和布局外,开发者还可以自由地添加自定义的组件和布局,以决定应用的个性化。以下是一些示例代码和说明:

注册母版组件

在这个示例中,我们注册了一个名为 custom-mask-widget 的自定义组件,并使用 CustomMaskWidget 类初始化了该组件。

示例工程目录

以下是需关注的工程目录示例,更新导出./widget:

image.png

图3-5-7-30 扩展母版工程目录示例

示例代码

以下是代码示例和相应的组件实现:

1. 注册自定义组件:

import { SPI, MaskWidget } from '@kunlun/dependencies'
import CustomMaskWidgetVue from './MaskWidget.vue'

@SPI.ClassFactory(MaskWidget.Token({ widget: 'custom-mask-widget' }))
export class CustomMaskWidget extends MaskWidget {
  public initialize(props) {
    super.initialize(props);
    this.setComponent(CustomMaskWidgetVue);
    return this;
  }
}

图3-5-7-31 注册自定义组件(TS)示例

在这段代码中,我们使用 @SPI.ClassFactory 注解来创建 CustomMaskWidget 类,并使用 MaskWidget.Token 注入组件的标识。通过 setComponent 方法,我们将组件与 CustomMaskWidgetVue 相关联。

2. 自定义组件实现(MaskWidget.vue):

  <template>
    <div class="mask-widget-wrapper">
      <h1>Mask组件</h1>
    </div>
  </template>

  <script lang="ts">
    import { defineComponent } from 'vue'

    export default defineComponent({
      inheritAttrs: false,
      name: 'CustomMaskWidgetVue'
    })
  </script>

  <style lang="scss">
    .mask-widget-wrapper {
      display: flex;
      align-items: center;
      background-color: var(--oio-disable-color);
      h1 {
        color: red;
      }
    }
  </style>

图3-5-7-32 注册自定义组件(Vue)示例

在 MaskWidget.vue 文件中,我们定义了 CustomMaskWidgetVue 组件的模板、逻辑和样式。这个组件简单地展示了一个包含标题的容器。

通过这个示例,我们展示了如何使用 SPI 和 Vue 来注册和实现自定义组件,以满足系统中的个性化需求

自定义母版

在这个示例中,我们注册了一个全局母版,并将自定义组件 custom-mask-widget 与母版结合。

示例工程目录

以下是需关注的工程目录示例,新导出了./globalMask:

image.png

图3-5-7-33 自定义母版工程目录示例

示例代码

以下是代码示例:

const registerGlobalMask = () => {
  registerMask(`
    <mask>
        <multi-tabs />
        <header>
            <widget widget="language" />
+            <widget widget="custom-mask-widget" />
        </header>
        <container>
            <sidebar>
                <widget widget="nav-menu" height="100%" />
            </sidebar>
            <content>
                <breadcrumb />
                <block width="100%">
                    <widget width="100%" widget="main-view" />
                </block>
            </content>
        </container>
    </mask>`, {});
}

registerGlobalMask();

图3-5-7-34 自定义母版组件使用示例

在这段代码中,我们使用 registerMask 注册了一个全局母版,其中包含了多个内置组件和布局元素。通过 的方式,我们将自定义组件 custom-mask-widget 添加到了母版的头部(header)中

效果

image.png

图3-5-7-35 自定义母版效果示例

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

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

(0)
史, 昂的头像史, 昂数式管理员
上一篇 2024年5月23日 am9:13
下一篇 2024年5月23日 am9:15

相关推荐

  • 4.1.19 框架之网关协议-后端占位符

    在我们日常开发中会有碰到一些特殊场景,需要由前端来传一些如“当前用户Id”、“当前用户code”诸如此类只有后端才知道值的参数,那么后端占位符就是来解决类似问题的。如前端传${currentUserId},后端会自动替换为当前用户Id。 Step1 后端定义占位符 我们新建一个UserPlaceHolder继承AbstractPlaceHolderParser,用namespace来定义一个“currentUserId”的占位符,其对应值由value()决定为“PamirsSession.getUserId().toString()”,active要为真才有效,priority为优先级 package pro.shushi.pamirs.demo.core.placeholder; import org.springframework.stereotype.Component; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.user.api.AbstractPlaceHolderParser; @Component public class UserPlaceHolder extends AbstractPlaceHolderParser { @Override protected String value() { return PamirsSession.getUserId().toString(); } @Override public Integer priority() { return 10; } @Override public Boolean active() { return Boolean.TRUE; } @Override public String namespace() { return "currentUserId"; } } 图4-1-19-1 后端定义占位符 Step2 前端使用后端占位符 我们经常在o2m和m2m中会设置domain来过滤数据,这里案例就是在field中设置来过滤条件,domain="createUid == $#{currentUserId}",注意这里用的是$#{currentUserId} 而不是${currentUserId},这是前端为了区分真正变量和后端占位符,提交的时候会把#过滤掉提交。修改宠物达人表格视图的Template中search部分 <template slot="search" cols="4"> <field data="name" label="达人"/> <field data="petTalentSex" multi="true" label="达人性别"/> <field data="creater" /> <!– <field data="petShops" label="宠物商店" domain="createUid == ${activeRecord.creater.id}"/>–> <field data="petShops" label="宠物商店" domain="createUid == $#{currentUserId}"/> <field data="dataStatus" label="数据状态" multi="true"> <options> <option name="DRAFT" displayName="草稿" value="DRAFT" state="ACTIVE"/> <option name="NOT_ENABLED" displayName="未启用" value="NOT_ENABLED" state="ACTIVE"/> <option name="ENABLED" displayName="已启用" value="ENABLED" state="ACTIVE"/> <option name="DISABLED" displayName="已禁用" value="DISABLED" state="ACTIVE"/> </options> </field> <field data="createDate" label="创建时间"/> <field data="unStore" /> </template> 图4-1-19-2 前端使用后端占位符 Step3 重启看效果 请求上都带上了createUid==${currentUserId} 图4-1-19-3 示例效果

    2024年5月23日
    96800
  • 4.1.25 框架之搜索引擎

    一、使用场景 在碰到大数据量并且需要全文检索的场景,我们在分布式架构中基本会架设ElasticSearch来作为一个常规解决方案。在oinone体系中增强模型就是应对这类场景,其背后也是整合了ElasticSearch。 二、整体介绍 oinone与es整合设计图 图4-1-25-1 Oinone与es整合设计图 基础环境安装 Canal安装 详见4.1.10【函数之触发与定时】一文 修改Canal配置并重启 新增Canal的实例【destinaion: pamirs】,监听分表模型的binlog【filter: demo.demo_core_sharding_model……】用于增量同步 pamirs: middleware: data-source: jdbc-url: jdbc:mysql://localhost:3306/canal_tsdb?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=false&useSSL=false&requireSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: oinone canal: ip: 127.0.0.1 port: 1111 metricsPort: 1112 zkClusters: – 127.0.0.1:2181 destinations: – destinaion: pamirschangedata name: pamirschangedata desc: pamirschangedata slaveId: 1235 filter: demo\.demo_core_pet_talent dbUserName: root dbPassword: oinone memoryStorageBufferSize: 65536 topic: CHANGE_DATA_EVENT_TOPIC dynamicTopic: false dbs: – { address: 127.0.0.1, port: 3306 } – destinaion: pamirs id: 1234 name: pamirs desc: pamirs slaveId: 1234 filter: demo\.demo_core_sharding_model_0,demo\.demo_core_sharding_model_1,demo\.demo_core_sharding_model_2,demo\.demo_core_sharding_model_3,demo\.demo_core_sharding_model_4,demo\.demo_core_sharding_model_5,demo\.demo_core_sharding_model_6,demo\.demo_core_sharding_model_7 dbUserName: root dbPassword: oinone memoryStorageBufferSize: 65536 topic: BINLOG_EVENT_TOPIC dynamicTopic: false dbs: – { address: 127.0.0.1, port: 3306 } tsdb: enable: true jdbcUrl: "jdbc:mysql://127.0.0.1:3306/canal_tsdb" userName: root password: oinone mq: rocketmq rocketmq: namesrv: 127.0.0.1:9876 retryTimesWhenSendFailed: 5 dubbo: application: name: canal-server version: 1.0.0 registry: address: zookeeper://127.0.0.1:2181 protocol: name: dubbo port: 20881 scan: base-packages: pro.shushi server: address: 0.0.0.0 port: 10010 sessionTimeout: 3600 图4-1-25-2 修改Canal配置并重启 ES安装 下载安装包官方下载地址,也可以直接下载elasticsearch-8.4.1-darwin-x86_64.tar.gz.txt(361.7 MB),下载后去除后缀.txt,然后解压文件 替换安装目录/config下的[elasticsearch.yml](elasticsearch)(1 KB),主要是文件中追加了三个配置 xpack.security.enabled: false xpack.security.http.ssl.enabled: false xpack.security.transport.ssl.enabled: false 图4-1-25-3 elasticsearc.yml追加三个配置 启动 a. 导入环境变量(ES运行时需要JDK18及以上版本JDK运行环境, ES安装包中包含了一个JDK18版本) # export JAVA_HOME=/Users/oinone/Documents/oinone/es/elasticsearch-8.4.1/jdk.app/Contents/Home/ export JAVA_HOME=ES解压安装目录/jdk.app/Contents/Home/ 图4-1-25-4 导入环境变量 b. 运行ES ## nohup /Users/oinone/Documents/oinone/es/elasticsearch-8.4.1/bin/elasticsearch >> $TMPDIR/elastic.log 2>&1 & nohup ES安装目录/bin/elasticsearch >> $TMPDIR/elastic.log 2>&1 & 图4-1-25-5 运行ES 停止ES lsof…

    2024年5月23日
    1.1K00
  • 3.4.2 函数的开放级别与类型

    一、函数开放级别 我们在日常开发中通常会因为安全性,为方法定义不同的开放层级,或者通过应用分层把需要对web开放的接口统一定义在一个独立的应用中。oinone也提供类似的策略,所有逻辑都通过Function来归口统一管理,所以在Function是可以定义其开放级别有API、REMOTE、LOCAL三种类型,配置可多选。 四种自定义新增方式与开放级别的对应关系 函数 本地调用(LOCAL) 远程调用(REMOTE) 开放(API) 伴随模型新增函数 支持 支持【默认】 支持 独立新增函数绑定到模型 支持 支持【默认】 支持 独立新增函数只作公共逻辑单元 支持 支持【默认】 伴随ServerAction新增函数 必选 表3-4-2-1 四种自定义新增方式与开放级别的对应关系 远程调用(REMOTE) 如果函数的开放级别为本地调用,则不会发布远程服务和注册远程服务消费者 非数据管理器函数 提供者:如果函数定义在当前部署包的启动应用中,则主动发布远程服务提供者。 消费者:如果函数定义在部署依赖包中但未在当前部署包的启动应用中,则系统会默认注册远程消费者。发布注册的远程服务使用命名空间和函数编码进行路由。 所以非数据管理器函数的消费者并不需要感知该服务是否是本地提供还是远程提供。而服务提供者也不需要手动注册远程服务。 数据管理器类函数 提供者:如果数据管理器函数所在模型定义在当前部署包的启动应用中,则系统会主动发布数据管理器的远程服务作为数据管理器的远程服务提供者; 消费者:如果模型定义在部署依赖包中但未在当前部署包的启动应用中,则系统会主动注册数据管理器的远程服务消费者。 所以数据管理器类函数的消费者与服务提供者并不需要感知函数的远程调用。 二、函数类型 函数的类型语义分为:增、删、改、查,在编程模式下目前用于Function为API级别,生成GraphQL的Schema时放在query还是mutation。查放在query,其余放mutation。 三、函数分类 TBD 在无代码编辑器中,函数分类主要用函数选择的分类管理。

    Oinone 7天入门到精通 2024年5月23日
    1.1K00
  • 3.2.3 应用中心

    在App Finder 中点击应用中心可以进入oinone的应用中心,可以看到oinone平台所有应用列表、应用大屏、以及技术可视化。 一、应用列表 标准版本不支持在线安装,只能通过boot工程的yml文件来配置安装模块。在 www.oinone.top 官方SaaS平台客户可以在线管理应用生命周期如:安装、升级、卸载。同时针对已安装应用可以进行无代码设计(前提安装了设计器),针对应用类的模块则可进行收藏,收藏后会在App Finder中的我收藏的应用中出现。在应用列表中可以看到我们已经安装的应用以及模块,我们oinoneDemo工程也在其中。 图3-2-35 Oinone的应用列表 图3-2-36 应用收藏后会在App Finder的【我收藏的应用】中出现 二、应用大屏 但我们的测试应用没有设置应用类目,则无法在应用大屏中呈现。 图3-2-37 未设置应用类目则无法在应用大屏中呈现 三、技术可视化 在技术可视化页面,出展示已经安装模块的元数据,并进行分类呈现 图3-2-38 云数据分类呈现

    2024年5月23日
    1.4K00
  • 合作伙伴中心

    合作伙伴中心包含“公司、个人、部门、岗位、员工”五个菜单。其中公司、个人为合作伙伴,是创建组织架构的前置条件;部门、岗位、员工为组织架构,是选择的公司下的内部架构。 合作伙伴 公司页面中包含常规的增删改查和查看详情。 公司的创建页面如下: 个人暂不支持创建。 组织架构 同样菜单中包含常规的增删改查和查看详情。 组织架构可以依次创建部门、岗位、员工。对应关系为,一个部门下有多个岗位,一个员工可以归属于多个部门和多个岗位。 部门创建页面如下: 岗位创建页面如下: 员工创建页面如下: 合作伙伴中心创建的员工会自动生成可登录的用户并进行绑定。 在用户中心创建的用户仅为可登录用户无法操作管理员工、关联部门。 流程设计器中可选到的操作人分类为“员工、部门、角色”。

    2024年6月20日
    94800

Leave a Reply

登录后才能评论