3.5.3 Action的类型

各类动作我们都碰到过,但都没有展开讲过。这篇文章我们来系统介绍下oinone涉及到的所有Action类型。

一、动作类型

  • 服务器动作ServerAction
  • 类似于Spring MVC的控制器Controller,通过模型编码和动作名称路由,定义存储模型或代理模型将为该模型自动生成动作名称为consturct,queryOne,queryPage,create,update,delete,deleteWithFieldBatch的服务器动作。定义传输模型将为该模型自动生成动作名称为consturct的服务器动作
  • 窗口动作ViewAction
  • 站内跳转,通过模型编码和动作名称路由。系统将为存储模型和代理模型自动生成动作名称为redirectDetailPage的跳转详情页窗口动作,动作名称为redirectListPage的跳转列表页窗口动作,动作名称为redirectCreatePage的跳转新增页窗口动作,动作名称为redirectUpdatePage的跳转更新页窗口动作。
  • 跳转动作UrlAction
  • 外链跳转
  • 客户端动作ClientAction
  • 调用客户端函数

二、默认动作

  • 如果在UI层级,有开放新增语义函数,则会默认生成新增的窗口动作ViewAction,跳转到新增页面
  • 如果在UI层级,有开放更新语义函数,则会默认生成修改的窗口动作ViewAction,跳转到更新页面
  • 如果在UI层级,有开放删除语义函数,则会默认生成删除的客户端动作ClientAction,弹出删除确认对话框

三、第一个服务器动作ServerAction

回顾第一个ServerAction

第一个ServerAction是在3.3.2【模型的类型】一文中的“代理模型”部分出现的,再来看下当时的定义代码

package pro.shushi.pamirs.demo.core.action;

……引用类

@Model.model(PetShopProxy.MODEL_MODEL)
@Component
public class PetShopProxyAction extends DataStatusBehavior<PetShopProxy> {

    @Override
    protected PetShopProxy fetchData(PetShopProxy data) {
        return data.queryById();
    }
    @Action(displayName = "启用")
    public PetShopProxy dataStatusEnable(PetShopProxy data){
        data = super.dataStatusEnable(data);
        data.updateById();
        return data;
    }

……其他代码

}

图3-5-3-1 回顾第一个ServerAction

  1. @Action注解将创建服务器动作,并@Model.model绑定

  2. 自定义ServerAction请勿使用get、set、unset开头命名方法或toString命名方法

ServerAction之校验(举例)

Step1 为动作配置校验表达式

使用@Validation注解为PetShopProxyAction的dataStatusEnable服务端动作进行校验表达式配置

package pro.shushi.pamirs.demo.core.action;

……引用类

@Model.model(PetShopProxy.MODEL_MODEL)
@Component
public class PetShopProxyAction extends DataStatusBehavior<PetShopProxy> {

    @Override
    protected PetShopProxy fetchData(PetShopProxy data) {
        return data.queryById();
    }
    @Validation(ruleWithTips = {
            @Validation.Rule(value = "!IS_BLANK(data.code)", error = "编码为必填项"),
            @Validation.Rule(value = "LEN(data.shopName) < 128", error = "名称过长,不能超过128位"),
    })
    @Action(displayName = "启用")
    public PetShopProxy dataStatusEnable(PetShopProxy data){
        data = super.dataStatusEnable(data);
        data.updateById();
        return data;
    }

……其他代码

}

图3-5-3-2 为动作配置校验表达式

注:

  1. ruleWithTips可以声明多个校验规则及错误提示;

  2. IS_BLANK和LEN为内置文本函数,更多内置函数详见4.1.12【函数之内置函数与表达式】一文;

  3. 当内置函数不满足时参考4.1.13【Action之校验】一文。

Step2 重启看效果

在商店管理页面点击【启用】得到了预期返回错误信息,显示"编码为必填项"

3.5.3 Action的类型

图3-5-3-3 在商店管理页面点击启用得到了预期返回错误信息

ServerAction之前端展示规则(举例)

既然后端对ServerAction发起提交做了校验,那能不能在前端就不展示呢?当然可以,我们现在就来试下。

Step1 配置PetShopProxyAction的dataStatusEnable的前端出现规则

用注解@Action.Advanced(invisible="!(activeRecord.code !== undefined && !IS_BLANK(activeRecord.code))")来表示,注意这里配对invisible是给前端识别的,所以写法上跟后端的校验有些不一样,但如内置函数IS_BLANK这些是前后端一致实现的,activeRecord在前端用于表示当前记录。

package pro.shushi.pamirs.demo.core.action;

……引用类

@Model.model(PetShopProxy.MODEL_MODEL)
@Component
public class PetShopProxyAction extends DataStatusBehavior<PetShopProxy> {

    @Override
    protected PetShopProxy fetchData(PetShopProxy data) {
        return data.queryById();
    }
    @Validation(ruleWithTips = {
            @Validation.Rule(value = "!IS_BLANK(data.code)", error = "编码为必填项"),
            @Validation.Rule(value = "LEN(data.name) < 128", error = "名称过长,不能超过128位"),
    })
    @Action(displayName = "启用")
    @Action.Advanced(invisible="!(activeRecord.code !== undefined && !IS_BLANK(activeRecord.code))")
    public PetShopProxy dataStatusEnable(PetShopProxy data){
        data = super.dataStatusEnable(data);
        data.updateById();
        return data;
    }

……其他代码

}

图3-5-3-4 配置PetShopProxyAction的dataStatusEnable的前端出现规则

Step2 重启看效果

我们发现店铺编码为空的记录,没有了【启用】的操作按钮

3.5.3 Action的类型

图3-5-3-5 店铺编码为空的记录没有启用操作按钮

ServerAction配置说明

常用配合

  1. contextType设置动作上下文类型

a. SINGLE(默认)——单行,常用于列表页(展示在每行末尾的操作栏中)和表单页(展示在页面上方)

b. BATCH——多行,常用于列表页(展示在表格上方按钮区)

c. SINGLE_AND_BATCH——单行或多行,常用于列表页(展示在表格上方按钮区)

d. CONTEXT_FREE——上下文无关,常用于列表页(展示在表格上方按钮区)

  1. bindingType设置按钮所在页面类型(以下仅说明常用类型,详见ViewTypeEnum)

a. TABLE——列表页

b. GALLERY——画廊

c. FORM——表单页

d. DETAIL——详情页

e. CUSTOM——自定义页

注解大全

@Action
├── displayName 显示名称
├── summary 摘要摘要
├── contextType 动作上下文,可选项详见ActionContextTypeEnum
├── bindingType 所在页面类型,可选项详见ViewTypeEnum
├── Advanced 更多配置
│ ├── name 技术名称,默认Java方法名
│ ├── args 参数,默认java参数
│ ├── type 方法类型,默认UPDATE,可选项详见FunctionTypeEnum
│ ├── language 方法实现语言,默认JAVA,可选项详见FunctionLanguageEnum
│ └── invisible 隐藏规则
│ └── bindingView 绑定特定视图
│ └── priority 展示顺序

四、第一个窗口动作ViewAction

回顾第一个ViewAction

第一个ViewAction是在3.3.2【模型的类型】一文中的“传输模型”部分出现的,再来看下当时的定义代码。

package pro.shushi.pamirs.demo.core.init;

……引用类

@Component
public class DemoModuleMetaDataEditor implements MetaDataEditor {
    @Override
    public void edit(AppLifecycleCommand command, Map<String, Meta> metaMap) {
        InitializationUtil util = InitializationUtil.get(metaMap, DemoModule.MODULE_MODULE,DemoModule.MODULE_NAME);
        if(util==null){
            return;
        }
        ……其他代码
        //初始化自定义前端行为
        viewActionInit(util);
        ……其他代码
    }
    private void viewActionInit(InitializationUtil util){
        util.createViewAction("demo_petShop_batch_update","批量更新数据状态", PetShopProxy.MODEL_MODEL,
                InitializationUtil.getOptions(ViewTypeEnum.TABLE), PetShopBatchUpdate.MODEL_MODEL,ViewTypeEnum.FORM, ActionContextTypeEnum.SINGLE_AND_BATCH
                , ActionTargetEnum.DIALOG,null,null);
    }
     ……其他代码
}

图3-5-3-6 回顾第一个ViewAction

createViewAction参数详解(建议更换为注解方式)

参数名 类型 说明
name String 技术名称,唯一建要求
displayName String 展示名称
originModel String ViewAction的绑定模型
originViewTypes List ViewAction在绑定模型的哪些视图类型上展示
targetModel String ViewAction跳转到的目标模型
targetViewType ViewTypeEnum ViewAction跳转到的目标模型的什么类型视图
contextType ActionContextTypeEnum ViewAction在绑定模型视图上设置展示的动作上下文类型SINGLE(默认)——单行,常用于列表页(展示在每行末尾的操作栏中)和表单页(展示在页面上方)BATCH——多行,常用于列表页(展示在表格上方按钮区)SINGLE_AND_BATCH——单行或多行,常用于列表页(展示在表格上方按钮区)CONTEXT_FREE——上下文无关,常用于列表页(展示在表格上方按钮区)
pageTarget ActionTargetEnum 页面打开方式 ROUTER:页面路由 DIALOG:页面弹窗 OPEN_WINDOW:打开新窗口DRAWER:打开抽屉
resViewName String ViewAction跳转到的目标模型的指定视图的名称,该视图的类型需要跟targetViewType一致
title String 页面标题
非createViewAction方法的参数,但是ViewAction模型有的属性,可在调用createViewAction以后,在通过setXX属性方法来设置对应属性字段值
priority Intget 展示顺序
bindingView String 绑定特定视图
invisible String 隐藏规则
load String 对于特殊模型的窗口动作进行定制化的加载方式
filter String 代表后端过滤,是一定会加上的过滤条件,用户无感知
domain String 代表前端过滤,是默认会加上的过滤条件,用户可以去除该搜索条件

表3-5-3-1 createViewAction参数详解

注解见:@UxRouteButton(action = @UxAction(),value = @UxRoute())

ViewAction高级参数-Load(下个版本支持)

一般用于以下场景:

  1. 对于特殊模型的窗口动作进行定制化的加载方式。

  2. 不同模型间跳转时,可根据上一个模型的数据内容加载另一个模型的数据内容。

使用初始化工具类设置Load函数:

util.modifyViewAction(TestModele.MODEL_MODEL, InitializationUtil.DEFAULT_CREATE,
        viewAction -> viewAction.setLoad("createPageLoad"));

图3-5-3-7 使用初始化工具类设置Load函数

注:

所示修改窗口动作方法将TestModel模型的默认创建页的加载函数从construct函数改为了createPageLoad函数。

替代方案:构建模型子类,通过子类来重写construct方法

ViewAction高级参数filter和domain(举例)

filter当前版本支持,domain下个版本支持,之所以放一起讲是因为这是过滤的两种形态。

  1. filter代表后端过滤,是一定会加上的过滤条件,用户无感知

  2. domain代表前端过滤,是默认会加上的过滤条件,用户可以去除该搜索条件

Step1 修改自定义pet_talent_table.xml查询条件增加name字段

<view name="tableView" model="demo.PetTalent" cols="1" type="TABLE" enableSequence="true" layout="petTalentTableLayout">
    ……其他代码
    <template slot="search"  cols="4">
        <field data="name" label="达人"/>
        <field data="dataStatus" label="数据状态">
            <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="创建时间"/>
    </template>
</view>

图3-5-3-8 修改自定义pet_talent_table.xml查询条件增加name字段

Step2 为宠物达人模型的两个菜单入口分配置filter和domain

把【宠物达人】菜单调整为三个菜单【宠物达人1】、【宠物达人2】、【宠物达人3】分别设置filter和domain

  1. 修改以菜单【宠物达人1】为入口的ViewAction的filter:

    1. @UxRoute(filter = "name =like= \'老\'")字符串要符合RSQL
  2. 修改以菜单【宠狗达人2】为入口的ViewAction的domain:

    1. @UxRoute(domain = "name =like= \'老\'") 字符串要符合RSQL
  3. 修改以菜单【宠狗达人3】跟函数结合,设置时间默认过滤条件:

    1. @UxRoute(domain = "createDate =ge= \'${ADD_DAY(NOW_STR(),-7)}\' and createDate =lt= \'${NOW_STR()}\'") 字符串要符合RSQL

    2. createDate =ge= \'${ADD_DAY(NOW_STR(),-7)}\' and createDate =lt= \'${NOW_STR()}\'

      1. 用到函数需要用${}装饰;

      2. 更多函数详见4.1.12【函数之内置函数与表达式】一文。

  4. domain的操作符需要跟页面搜索字段定义的操作符一致,比如name字符串字段搜索默认操作符是=like=,如果配置成其他则无效。

@UxMenu("宠物达人1")@UxRoute(value = PetTalent.MODEL_MODEL,filter = "name =like= '老'") class PetTalentMenu{}
@UxMenu("宠物达人2")@UxRoute(value = PetTalent.MODEL_MODEL,domain = "name =like= '老'") class PetTalent2Menu{}
@UxMenu("宠物达人3")@UxRoute(value = PetTalent.MODEL_MODEL,domain = "createDate =ge= '${ADD_DAY(NOW_STR(),-7)}' and createDate =lt= '${NOW_STR()}'") class PetTalent3Menu{}

图3-5-3-9 两个菜单入口分配置filter和domain

Step3 重启看效果

因为【宠物达人1】对应ViewAction加的是Filter,所以只能看到达人名称带“老”字的记录

3.5.3 Action的类型

图3-5-3-10 宠物达人1搜索记录

因为【宠物达人2】对应ViewAction加的是Domain,前端搜索栏里【达人】字段搜索条件为“老”字,达人名称带“老”字的记录,可以手工删除再次搜索全部数据

3.5.3 Action的类型

图3-5-3-11 宠物达人2搜索记录

因为【宠物达人3】对应ViewAction加的是Domain,前端搜索栏里【创建时间】字段带近7天过滤条件,可以手工删除再次搜索全部数据

3.5.3 Action的类型

图3-5-3-12 宠物达人3搜索记录

五、第一个跳转动作UrlAction

回顾第一个UrlAction

在3.5.1【构建第一个Menu】一文中用@UxMenu.url定义了一个百度的菜单,该菜单背后就是一个普通的UrlAction

@UxMenu("Oinone官网")@UxLink(value = "http://www.oinone.top",openType= ActionTargetEnum.OPEN_WINDOW) class SsLink{}

图3-5-3-13 回顾第一个UrlAction

URL计算表达式(暂不支持)

@UxMenu("百度") @UxLink(value = "http://www.baidu.com?wd=${activeRecord.technicalName}",openType= ActionTargetEnum.OPEN_WINDOW) class BaiduLink{}

图3-5-3-14 URL计算表达式

Compute函数(暂不支持)

@UxMenu("百度") @UxLink(value = "http://www.baidu.com",openType= ActionTargetEnum.OPEN_WINDOW,context = {@Prop(name="wd",value= "activeRecord.technicalName"),compute="computeSearchUrl"}) class BaiduLink{}

@Model.model(PetTalent.MODEL_MODEL)
public class PetTalentAction {

    @Function(openLevel = FunctionOpenEnum.API, summary = "计算搜索Url")
    @Function.Advanced(type = FunctionTypeEnum.QUERY)
    public String computeSearchUrl(TestModel data) {
        return "https://www.baidu.com/s?wd=" + data.getName();
    }
}

图3-5-3-15 Compute函数

注:

  1. 代码所示创建链接动作含义为:以新标签页方式跳转至指定URL,该URL值来自于调用后端computeSearchUrl方法的返回值。

六、第一个客户端动作ClientAction

基础客户端动作(举例)

给批量修改店铺状态弹出页面增加一个【自定义返回】和【自定义关闭】按钮,这里注意contextType只能配置为“ActionContextTypeEnum.SINGLE”,因为Form默认只展示contextType为SINGLE的Action

Step1 在PetShopBatchUpdateAction增加@UxClientButton注解

@Model.model(PetShopBatchUpdate.MODEL_MODEL)
@UxClientButton(action = @UxAction(name = "demo_back_test", label = "自定义返回",contextType = ActionContextTypeEnum.SINGLE,bindingType = ViewTypeEnum.FORM),value = @UxClient(value = "$$internal_GotoListTableRouter"))
@UxClientButton(action = @UxAction(name = "demo_close_test", label = "自定义关闭",contextType = ActionContextTypeEnum.SINGLE,bindingType = ViewTypeEnum.FORM),value = @UxClient(value = "$$internal_DialogCancel"))
@Component
public class PetShopBatchUpdateAction {
}

图3-5-3-16 在PetShopBatchUpdateAction增加@UxClientButton注解

Step2 重启看效果

3.5.3 Action的类型

图3-5-3-17 示例效果

前端动作之组合动作(举例)

通过自定义View的Template来设置组合动作,同时学习下自定义视图时如何设置需要展示Action,还是以批量修改店铺状态弹出页面为例子,我们只展示一个组合动作按钮【组合动作】,它包含表单校验、提交、关闭并刷新主视图等行为动作

Step1 自定义弹出框View

  1. 在views/demo_core/template路径下增加一个名为pet_shop_batch_update_form.xml文件

  2. 再通过数据库查看默认页面定义,找到base_view表,过滤条件设置为model =\'demo.PetShopBatchUpdate\',我们就看到该模型下对应的所有view,这些是系统根据该模型的ViewAction对应生成的默认视图,找到类型为【表单(type = FORM)】的记录,查看template字段,复制给pet_shop_batch_update_form.xml文件

  3. 把【<template slot="actions" autoFill="true"/>】替换成以下内容

    <template slot="actions" >
        <action actionType="composition" label="组合动作">
            <action actionType="client" name="$$internal_ValidateForm" />
            <action name="conform" />
            <action actionType="client" name="$$internal_GotoListTableRouter" />
        </action>
    </template>

图3-5-3-18 替换

Step2 重启看效果

这个页面只保留了【组合动作】一个按钮,其他没有配置的按钮就会隐藏掉。

3.5.3 Action的类型

图3-5-3-19 未配置的按钮均会被隐藏

平台默认前端动作:

有元数据定义名的建议最好用元数据名,比如平台默认前端导入动作“$$internal_GotoListImportDialog”可以用“internalGotoListImportDialog”来替代,这样的好处是管理一致,比如权限等功能设置.

<!-- <action name="$$internal_GotoListImportDialog" label="导入" /> 可以用下面方式替代,可以用于权限 -->
<action name="internalGotoListImportDialog" label="导入" />

图3-5-3-20 “$$internal_GotoListImportDialog”可用“internalGotoListImportDialog”替代

name 适用场景 功能描述 元数据定义名
$$internal_GotoListTableRouter 通用 返回上一个页面 internalGotoListTableRouter
$$internal_DeleteOne 关系字段表格 删除绑定的表格的选中数据 internalDeleteOne
$$internal_DialogCancel 弹窗 关闭当前弹窗
$$internal_ReloadData 弹窗 刷新当前主视图组件
$$internal_ListInsertOneAndCloseDialog 通用 打开一个创建弹窗
$$internal_GotoM2MListDialog 多对多关系 表格 打开M2M表格的创建弹窗
$$internal_GotoO2MCreateDialog 一对多关系 表格 打开O2M表格的创建弹窗
$$internal_GotoO2MEditDialog 一对多关系 表格 打开O2M表格的编辑弹窗
$$internal_ListInsertOneAndBackToList 表单 校验表单数据,提交到后端,返回表格(新建)
$$internal_ListUpdateOneAndBackToList 表单 校验表单数据,提交到后端,返回表格(更新)
$$internal_ValidateForm 表单 校验当前表单
$$internal_GotoListExportDialog 一般用于表格 数据导出的action internal_GotoListImportDialog
$$internal_GotoListImportDialog 一般用于表格 数据导入的action internalGotoListImportDialog

表3-5-3-2 平台默认前端动作

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

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

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

相关推荐

  • 4.2.7 框架之翻译工具

    一、说明 Oinone目前的默认文案是中文,如果需要使用其他语言,Oinone也提供一系列的翻译能力。 二、定义语言文件 在src/local下新增一个名为zh_cn.ts文件: 图4-2-7-1 语言文件 编辑zh_cn.ts文件,增加以下内容: const zhCN = { demo: { test: '这是测试' } } export default zhCN 图4-2-7-2 语言内容格式示意 在mian.ts注册语言资源: import { LanguageType, registryLanguage} from '@kunlun/dependencies'; import Zh_cn from './local/zh_cn' registryLanguage(LanguageType['zh-CN'], Zh_cn); 图4-2-7-3 注册语言 三、Vue模板使用 <template> <div class="petFormWrapper"> <form :model="formState" @finish="onFinish"> <a-form-item :label="translate('demo.test')" id="name" name="kind" :rules="[{ required: true, message: '请输入品种种类!', trigger: 'focus' }]"> <a-input v-model:value="formState.kind" @input="(e) => onNameChange(e, 'kind')" /> <span style="color: red">{{ getServiceError('kind') }}</span> </a-form-item> <a-form-item label="品种名" id="name" name="name" :rules="[{ required: true, message: '请输入品种名!', trigger: 'focus' }]"> <a-input v-model:value="formState.name" @input="(e) => onNameChange(e, 'name')" /> <span style="color: red">{{ getServiceError('name') }}</span> </a-form-item> </form> </div> </template> <script lang="ts"> import { defineComponent, reactive } from 'vue'; import { Form } from 'ant-design-vue'; export default defineComponent({ // 引入translate props: ['onChange', 'reloadData', 'serviceErrors', 'translate'], components: { Form }, setup(props) { const formState = reactive({ kind: '', name: '', }); const onFinish = () => { console.log(formState); }; const onNameChange = (event, name) => { props.onChange(name, event.target.value); }; const reloadData = async () => { await props.reloadData(); }; const getServiceError = (name: string) => { const error = props.serviceErrors.find(error => error.name === name);…

    2024年5月23日
    1.7K00
  • 1.2 Oinone的致敬

    占在巨人的肩膀上,天地孤影任我行 1.2.1 数字化时代Oinone接棒Odoo 在数字化时代,中国在互联网化的应用、技术的领先毋庸置疑,但在软件的工程化、产品化输出方面仍有许多改进的空间。这时,我了解到了Odoo——一个国外非常优秀的开源ERP厂商,全球ERP用户数量排名第一,百级别员工服务全球客户。Odoo的工程化能力和商业模式深深吸引了我,它是软件行业典型的产品制胜和长期主义者的胜利之一。 在2019年,也就是数式刚成立的时候,我们跟很多投资人聊起公司的对标是谁,我不是要成为数字化时代的SAP,而是要成为Odoo。然而,当时大部分国内投资人并不了解Odoo,尽管它已经是全球最大的ERP厂商之一,因为当时Odoo还没有明确的估值。直到2021年7月份获得Summit Partners的2.15亿美元投资后,Odoo才正式成为IT独角兽企业。 Odoo对我们提供了极大的启示,因此我们致敬Odoo,同样选择开源,每年对产品进行升级发布。如今,Odoo15已经发布,而Oinone也已推出第三版,恰好相隔12年,这是一个时代的接棒,从信息化升迁至数字化。 1.2.2Oinone与Odoo的不同之处 技术方面的不同 在技术上,Oinone和Odoo有相同之处,也有不同之处。它们都基于元数据驱动的软件系统,但是它们在如何让元数据运作的机制上存在巨大差异。Odoo是企业管理场景的单体应用,而Oinone则致力于企业商业场景的云原生应用。因此,它们在技术栈的选择、前后端协议设计、架构设计等方面存在差异。 场景方面的不同 在场景上,Oinone和Odoo呈现许多差异。相对于SAP这些老牌ERP厂商,Odoo算是西方在企业级软件领域的后起之秀,其软件构建方式、开源模式和管理理念在国外取得了非凡的成就。然而,在国内,Odoo并没有那么成功或者并没有那么知名。国内做Odoo的伙伴普遍认为,Odoo与中国用户的交互风格不符,收费模式设计以及外汇管制使商业活动受到限制,本地化服务不到位,国内生态没有形成合力,伙伴们交流合作都非常少。另外,Odoo在场景方面主要围绕内部流程管理,与国内老牌ERP如用友、金蝶重叠,市场竞争激烈。相比之下,Oinone看准了企业视角由内部管理转向业务在线、生态在线(协同)带来的新变化,聚焦新场景,利用云、端等新技术的发展,从企业内外部协同入手,以业务在线驱动企业管理流程升级。它先立足于国内,做好国内生态服务,再着眼未来的国际化。 无代码设计器的定位 在无代码设计器的定位上,Odoo的无代码设计器是一个非常轻量的辅助工具,因为ERP场景下,一个企业实施完以后基本几年不会变,流程稳定度非常高。相反,Oinone为适应"企业业务在线化后,所有的业务变化与创新都需要通过系统来触达上下游,从而敏捷响应快速创新"的时代背景,重点打造出五大设计器。(如下图1-2所示)。 图1-2 Oinone五大设计器 在数字化时代中国软件将接棒世界,而Oinone也要接棒Odoo,把数字化业务与技术的最佳实践赋能给企业,帮助企业数字化转型不走弯路!

    2024年5月23日
    2.5K00
  • 3.5.2.1 整体介绍

    虽然我们有小眼睛可以让用户自定义展示字段和排序喜好,以及通过权限控制行、列展示,但在我们日常业务开发中还是会对页面进行调整,以满足业务方的对交互友好和便捷性的要求。本节会在如何自定义之前我们先介绍页面结构与逻辑,再带小伙伴一起完成自定义view的Template和Layout,以及整个母版的Template和Layout 页面的构成讲解 页面交互拓扑图 页面交互拓扑图 图3-5-2-1 页面交互拓扑图 注:页面逻辑交互拓扑图说明 模块作为主切换入口 模块决定菜单列表 菜单切换触发点击action 前端根据Mask、View进行渲染, a. Mask是母版是确定了主题、非主内容分发区域所使用组件和主内容分发区域联动方式的页面模板。全局、应用、视图动作、视图都可以通过mask属性指定母版 bMask和View都是有layout定义和template定义合并而成,系统会提供默认母版,以及为每种视图提供默认layout c. layout与template通过插槽进行匹配 Action根据不同类型做出不同访问后端服务、url跳转、页面路由、发起客户端动作等 Aciton路由可以指定Mask、视图组件的layout、template a. 当layout没有指定的时候则用系统默认的 b. 当template没有指定的时候,且视图组件相同类型有多条记录时,根据优先级选取 Mask和视图组件的layout优先级(视图组件>视图动作 > 应用 > 全局) 默认母版以及各类视图组件 母版布局 默认母版基础布局base-layout <mask layout="default"> <header slot="header"/> <container slot="main" name="main"> <sidebar slot="sidebar"/> <container slot="content"/> </container> <footer slot="footer"/> </mask> 图3-5-2-2 默认母版基础布局base-layout 母版template <mask layout="default"> <mask name="defaultMask"> <template slot="header"> <container name="appBar"> <element widget="logo"/> <element widget="appFinder"/> </container> <container name="operationBar"> <element widget="notification"/> <element widget="dividerVertical"/> <element widget="languages"/> </container> <element widget="userProfile"/> </template> <template slot="sidebar"> <element widget="navMenu"/> </template> <template slot="content"> <element widget="breadcrumb"/> <element widget="mainView"/> </template> </mask> 图3-5-2-3 母版template 注: 上例中因为名称为main的插槽不需要设置更多的属性,所以在template中缺省了main插槽的template标签。 最终可执行视图 <mask name="defaultMask"> <header> <container name="appBar"> <element widget="logo"/> <element widget="appFinder"/> </container> <container name="operationBar"> <element widget="notification"/> <element widget="dividerVertical"/> <element widget="languages"/> </container> <element widget="userProfile"/> </header> <container name="main"> <sidebar name="sidebar"> <element widget="navMenu"/> </sidebar> <container name="content"> <element widget="breadcrumb"/> <element widget="mainView"/> </container> </container> <footer/> </mask> 图3-5-2-4 最终可执行视图 表格视图布局 默认表格视图基础布局base-layout <view type="table"> <view type="search"> <element widget="search" slot="search"> <xslot name="fields" slotSupport="field" /> </element> </view> <pack widget="fieldset"> <element widget="actionBar" slot="actions" slotSupport="action" /> <element widget="table" slot="table"> <xslot name="fields" slotSupport="field" /> <element widget="actionsColumn" slot="actionsColumn"> <xslot name="rowActions" slotSupport="action" /> </element> </element> </pack> </view> 图3-5-2-5 默认表格视图基础布局base-layout 注:table标签的子标签为column组件,如果field填充到元数据插槽fields没有column组件将自动包裹column组件。 表格视图template <view type="table" model="xxx" name="tableViewExample">…

    2024年5月23日
    1.6K00
  • 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> }, /**…

    2024年5月23日
    2.1K00
  • 3.5.6.4 动作的配置

    在3.5.3【Action的类型】一文中,我们介绍Action的几种类型,以及组合动作。 通用配置 配置项 可选值 默认值 作用 name 动作名称 label 显示名称 icon 图标 type primary defaultlink primary 按钮类型样式,支持主要样式、次要样式以及链接样式。 bizStyle defaultsuccesswarningdangerinfo default 按钮业务样式,支持成功(green)、警告(yellow)、危险(red)、信息(grey)四种样式。 invisible truefalse condition false 展示规则,有简单的true/false显隐,也支持复杂的表达式 disabled truefalse condition 根据动作上下文类型进行自动推断 是否禁用自动推断规则:当上下文类型为【单行】时,相当于使用表达式LIST_COUNT(context.activeRecords) != 1当上下文类型为【多行】时,相当于使用表达式LIST_COUNT(context.activeRecords) <= 1当上下文类型为【单行或多行】时,相当于使用表达式LIST_COUNT(context.activeRecords) == 0 disabledTitle string 根据动作上下文类型进行自动推断 禁用悬浮提示 表3-5-6-12 动作通用配置 二次确认配置 二次确认框默认支持两种模式,对话框和气泡框; 对话框 图3-5-6-51 对话框提示 气泡框 图3-5-6-52 气泡框警告 配置项 配置项 可选值 默认值 作用 备注 confirm string 二次确认提示文字 配置后开启二次确认 confirmType POPPER(气泡提示框) MODAL(对话框) POPPER 确认框类型 confirmPosition TM(按钮上方) BM(按钮下方) LM(按钮左侧) RM(按钮右侧) BM 确认框位置 气泡框该配置生效 enterText 确定 确定按钮文字 cancelText 取消 取消按钮文字 表3-5-6-13 配置项 弹出层动作配置(窗口动作ViewAction) 目前平台对于弹出层支持了两种展示形式。弹窗(modal/dialog)和抽屉(drawer) 支持两种配置方式【内嵌视图配置】和【引用已有页面】,内嵌视图配置优先于引用已有页面。 内嵌视图配置 该配置对于弹窗和抽屉均适用。 <action name="窗口动作名称" label="创建"> <view model="模型编码" type="form"> <template slot="form" widget="form"> <field data="id" invisible="true" /> <field data="code" label="编码" widget="Input" /> <field data="name" label="名称" widget="Input" /> </template> <template slot="footer"> <action name="$$internal_DialogCancel" label="关闭" type="default" /> <action name="create" label="确定" /> </template> </view> </action> 图3-5-6-53 内嵌视图配置 引用已有页面配置 该配置对于弹窗和抽屉均适用。 <view model="模型编码" type="form"> <template slot="form" widget="form"> <field data="id" invisible="true" /> <field data="code" label="编码" widget="Input" /> <field data="name" label="名称" widget="Input" /> </template> <template slot="footer"> <action name="$$internal_DialogCancel" label="关闭" type="default" /> <action name="create" label="确定" /> </template> </view> 图3-5-6-54 引用已有页面示例 <action name="窗口动作名称" label="创建" resViewName="$viewName$" /> 图3-5-6-55 引用已有页面 弹窗 当窗口动作的路由方式(target)为dialog时,内嵌视图/引用页面将以弹窗形式展示在页面上。 配置项 配置项 可选值 默认值 作用 title…

    2024年5月23日
    1.4K00

Leave a Reply

Please Login to Comment