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}

image.png

图4-1-19-3 示例效果

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

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

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

相关推荐

  • 6.4 国际化之多语言

    多语言是国际化中大家最常面对的问题,我们需要对应用的页面结构元素进行翻译,也需要对系统内容进行翻译比如:菜单、数据字典等,甚至还会业务数据进行翻译。但不管什么翻译需求,我们在实现上基本可以归类为前端翻译和后端翻译。前端翻译顾名思义是在前端根据用户选择语言对内容进行翻译,反之就是后端翻译。本文会带着大家了解oinone的前端翻译与后端翻译 准备工作 pamirs-demo-boot的pom文件中引入pamirs-translate包依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-translate</artifactId> </dependency> pamirs-demo-boot的application-dev.yml文件中增加配置pamirs.boot.modules增加translate,即在启动模块中增加translate模块 pamirs: boot: modules: – translate 后端翻译(使用) 这里通过对菜单的翻译来带大家了解翻译模块 Step1 新增翻译记录 切换应用到translate模块,点击新增翻译。 选择新增翻译生效模块 选择翻译的模型为:菜单模型 源语言选择中文,目标选择English 添加翻译项目: 源术语为:商店 翻译值为:shop 状态为:激活 Step2 查看效果 应用切换到Demo模块,在右上角切换语言至英语 后端翻译(自定义模型的翻译) 在前面菜单的翻译中,似乎我们什么都没做就可以正常通过翻译模块完成多语言的切换了。是不是真如我们想象的一样,当然不是。是因为Menu模型的displayName字段加上@Field(translate = true)注解。 Step1 为PetType模型的name字段增加翻译注解 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.base.IdModel; @Model.MultiTable(typeField = "kind") @Model.model(PetType.MODEL_MODEL) @Model(displayName="品种",labelFields = {"name"}) public class PetType extends IdModel { public static final String MODEL_MODEL="demo.PetType"; @Field(displayName = "品种名" , translate = true) private String name; @Field(displayName = "宠物分类") private String kind; } Step2 重启应用查看效果 切换应用到translate模块,点击新增翻译 切换应用到Demo模块,切换中英文,查看效果 前端翻译 还记得我们前端第一个自定义动作吗?会弹出“oinone第一个自定义Action,啥也没干”,我们要对它进行翻译。 Step1 修改前端DoNothingActionWidget.ts import translateValueByKey 提示语用translateValueByKey加上翻译 const confirmRs = executeConfirm(translateValueByKey(\’oinone第一个自定义Action,啥也没干\’)||\’oinone第一个自定义Action,啥也没干\’); 前端更多翻译工具请见前端高级特性-框架之翻译工具 import { Action, ActionContextType, ActionWidget, executeConfirm, IClientAction, SPI, ViewType, Widget, translateValueByKey } from '@kunlun/dependencies'; @SPI.ClassFactory(ActionWidget.Token({ name: 'demo.doNothing' })) export class DoNothingActionWidget extends ActionWidget { @Widget.Method() public async clickAction() { const confirmRs = executeConfirm(translateValueByKey('oinone第一个自定义Action,啥也没干')||'oinone第一个自定义Action,啥也没干'); } } //定义动作元数据 Action.registerAction('*', { displayName: '啥也没干', name: 'demo.doNothing', id: 'demo.doNothing', contextType: ActionContextType.ContextFree, bindingType: [ViewType.Table] } as IClientAction); Step2 新增翻译记录 前端翻译的翻译记录对应的模型可以随意找一个放。但要注意几点: 不要找有字读配置translate = true的模型,因为会影响后端翻译性能。 最好统一到一个模型中,便于后续管理。这里大家可以自定义一个无有业务访问且本身无需要翻译的模型来挂载,避免性能损失 Step3 刷新远程资源生成前端语言文件 Step4 新增或修改.env 前端在项目根目录下新增或修改.env,可以参考.env.example文件。通过.env文件为前端配置oss文件路径,针对I18N_OSS_URL配置项。真实前端访问翻译语言文件的路径规则为:http://bucket.downloadUrl/mainDir/租户/translate/模块/语言文件。 yaml文件中oss配置的文件路径:http://pamirs.oss-cn-hangzhou.aliyuncs.com/upload/demo/ 租户/translate/模块/语言文件 前端会自动根据上下文组织 # 后端api配置 # API_BASE_URL=http://127.0.0.1:8090 # 下面是国际化语言的cdn配置,默认用当前请求链接下的路径: /pamirs/translate/${module}/i18n_${lang}.js I18N_OSS_URL=http://pamirs.oss-cn-hangzhou.aliyuncs.com/upload/demo Step5 重启前端应用看效果 对语言进行中英文切换,进入宠狗达人页面,点击【第一个自定义Action】,查看前端翻译效果

    2024年5月23日
    1.6K20
  • 接口日志

    记录每个PAPI接口执行日志,接口的响应结果、执行时间、执行时长等信息,可查看接口详情。 接口详情

    2023年5月23日
    1.2K00
  • 3.5.7.4 自定义页面

    页面是什么 在Oinone前端体系中,页面是一个核心概念,它代表着终端用户所看到的当前视图。这个视图可以有多种形式,主要取决于页面是如何定义和构建的。在深入理解页面之前,我们需要了解两个关键的功能:自定义布局 和 自定义母版。 作用场景 自定义布局 提供了布局调整的强大功能,但在某些情况下,它可能无法完全满足特定的需求。这时,自定义页面就显得尤为重要。自定义页面是对 自定义布局 的补充,允许开发者从更深层次自由地控制和设计用户界面。 当标准布局无法实现所需的视觉效果或功能时,自定义页面提供了更高的灵活性。开发者可以通过自定义页面来实现独特的布局设计,添加特定的交互元素,或者整合复杂的业务逻辑,以创造独特且丰富的用户体验。 自定义页面 自定义视图组件允许开发者定义和使用特定于业务需求的视图布局。下面是一个具体的示例,展示了如何定义、注册和使用通过 setComponent 结合 TypeScript 和 Vue 的自定义视图组件。 示例工程目录 以下是需关注的工程目录示例,main.ts更新导入./view: 图3-5-7-48 自定义页面工程目录示例 1. 定义 TypeScript 组件 首先,我们定义了一个名为 CustomViewWidget 的 TypeScript 组件,并在该组件中通过 setComponent 结合 Vue 单文件组件。 import { BaseElementWidget, BaseElementViewWidget, SPI, ViewWidget } from '@kunlun/dependencies'; import CustomViewVue from './CustomView.vue'; @SPI.ClassFactory(BaseElementWidget.Token({ widget: 'CustomViewWidget' })) export class CustomViewWidget extends BaseElementViewWidget { public initialize(props) { super.initialize(props); this.setComponent(CustomViewVue); return this; } } 图3-5-7-49 定义TypeScript组件代码示例 2. Vue 单文件组件 其次,我们创建了对应的 Vue 单文件组件 CustomView.vue,用于展示自定义视图的具体内容。 <template> <div class="custom-view-wrapper"> <h1>自定义视图</h1> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ inheritAttrs: false, name: 'ViewComponentVue' }); </script> <style lang="scss"> .custom-view-wrapper {} </style> 图3-5-7-50 定义Vue组件代码示例 3. 注册自定义视图布局 接下来,我们使用 registerLayout 函数注册了一个表格视图布局,并在其中引入了通过 setComponent 结合的自定义视图组件。 import { registerLayout, ViewType } from "@kunlun/dependencies"; export const registerCustomView = () => { registerLayout( ` <view type="TABLE"> <element widget="CustomViewWidget" /> </view> `, { viewType: ViewType.Table, moduleName: 'resource', model: 'resource.ResourceCountryGroup' } ); }; registerCustomView(); 图3-5-7-51 注册自定义视图布局代码示例 效果 图3-5-7-52 自定义页面效果示例 4. 自定义视图在表格中的应用 当我们注册了自定义视图后,它就可以在表格视图中被使用。在表格视图的布局中,我们通过 标签将自定义视图嵌套在表格中,从而覆盖了表格的默认布局 5. 入参一致性 值得强调的是,registerLayout 函数和自定义布局的规则是一致的,这意味着开发者可以在自定义布局中使用与 registerLayout 相同的入参规则,从而实现更加灵活和统一的视图布局设计 与内置组件结合 1. 注册视图元素布局 首先,我们使用 registerLayout 函数注册了一个表格视图的布局。这个布局包含了搜索框、操作栏、以及一个自定义视图组件。 import { registerLayout, ViewType } from "@kunlun/dependencies"; import { CustomViewWidget } from…

    2024年5月23日
    1.4K00
  • 页面

    1. 页面介绍 页面是增删改查数据的入口,数据信息的填写、查看都需要通过页面来展示、交互。页面设计是界面设计器的功能之一,提供页面搭建功能,以实现数据的录入、查看/查询、搜索等等。 2. 页面列表 进入界面设计器,默认会打开以卡片形式管理页面的列表。 如图,页面卡片上可预览到的信息分别有页面标题、页面缩略图、视图类型、页面对应模型名称、页面描述。 「页面标题、页面描述」作用是通过文字定义页面的名称以及对页面进行详细描述。 「页面缩略图」是自行上传的图片,用于在页面列表通过图片预览当前页面的大致布局样式。若未上传,将显示系统默认的图片,点此查看缩略图上传。 「视图类型」通过业务角度(运营管理、官网门户、商城等,目前提供了运营管理一种业务类型)进行分类。运营管理中包括表单、表格、详情、画廊、树视图。 表单常应用于数据的创建、编辑页; 表格可理解为数据的列表查看页面,除了常规表格外,本版本支持树表、级联高级视图; 详情用于设计数据的详情页; 画廊是以卡片形式呈现内容; 树视图是包括树表、级联高级视图; 表格-树表、树视图-树表两者之间的区别:表格-树表的主模型是表格的模型,树视图-树表的主模型是树表的模型、左侧表格是展开的内容; 3. 添加页面 操作添加页面,首先需要选择添加方式。目前提供了1种添加页面方式:直接创建。 3.1 直接创建 直接创建时,弹框中填写页面的基本信息,填写完成后进入页面设计页。 4. 页面操作 4.1 设计页面 操作设计页面后直接进入该页面的设计页面,可对组件布局、交互、属性进行设置。 4.2 编辑 操作编辑弹出页面的基本信息弹框,可对当前页面的基本信息进行编辑修改。 可修改的基本信息包括页面标题、操作栏位置、页面分组、页面描述。 4.3 查看被引用的信息 4.3.1 什么是引用? 页面与页面或页面与菜单之间的若存在交互则称为具有引用关系。 举例1:【页面A】中的一个「跳转动作」配置了跳转【页面B】,则称页面B被页面A引用,在页面B下可查看被引用信息。 举例2:比如【菜单1】绑定了【页面C】,则称页面C被菜单1引用,在页面C下可查看被引用信息。 4.3.2 查看的引用信息是什么? 引用信息分别有“存在引用关系的视图”、“存在引用关系的菜单”。页面下操作查看被引用信息,是查看当前页面被引用情况,如上述举例1,页面B被引用,而页面A非被引用,所以只可以在页面B下查看到“存在引用关系的视图”。 4.4 隐藏/可见 对于暂时不使用的页面,可以进行隐藏(隐藏后可再设置可见)的操作。 4.4.1 隐藏/可见会有哪些影响? 隐藏后该页面在跳转动作选择页面和菜单绑定页面时,不可见,已被使用的不受影响。再次操作可见后,即可选择到。 4.4.2 隐藏后的页面找不到了? 若需要对隐藏的页面进行操作,但是在列表未查找到某个隐藏的页面,请切换「是否可见」筛选项,页面列表默认展示所有“可见”的页面,切换为“全部”或“隐藏”,即可找到隐藏的页面。 4.5 删除 对于不再使用且没有被引用信息的页面,可以将页面删除。页面删除后无法恢复,请谨慎操作,对于不确定是否要彻底删除的页面,建议先操作隐藏。 删除前请确保当前页面没有引用关系! 5. 页面搜索 卡片上方是页面筛选和搜索区域,可通过应用、模型、业务类型、视图类型、自定义/系统、可见/隐藏等等筛选页面;搜索时仅支持使用页面名称进行搜索。同时筛选条件也具备记忆功能,即上一次在页面列表的筛选条件是哪些,再次进入页面列表,筛选条件默认为上次的条件。 其中自定义页面是所有人工添加的页面,系统页面为非人工添加的页面,由系统默认生成,只可用于查看,不可编辑、删除或设计。 6. 页面分组管理 6.1 页面分组 当页面过多时,可以自定义添加15个分组,将页面进行归类管理。默认展示全部分组,点击「全部」展开所有分组,点击分组进行分组下的页面查看或管理分组。 6.2 管理分组 展开分组后,点击「管理分组」,出现弹框,在弹框中可以修改分组名称、添加分组、删除分组。 6.2.1 添加分组 操作「+页面分组」,可以直接输入分组名称后回车以添加一个新分组,或快捷选择其他应用使用的分组。最多添加15个分组。 6.2.2 修改分组 双击分组标签,即可对已有分组进行名称的修改。若分组在其他应用也使用,则在其他应用内,该分组名称同步变化。 6.2.3 删除分组 若分组下有页面或分组有被其他应用使用,则分组无法删除。

    2024年6月20日
    1.2K00
  • 3.3.9 字段类型之关系与引用

    有关系与引用类型才让oinone具备完整的描述模型与模型间关系的能力 在PetShop以及其代理模型中已经上用到了O2M、M2O字段,分别如petItems(PetItem)和create(PamrisUser)字段,但是没有过多的讲解。本文重点举例RELATED、M2M、O2M,至于M2O留给大家自行尝试。 一、引用类型(举例) 业务类型 Java类型 数据库类型 规则说明 RELATED 基本类型或关系类型 不存储或varchar、text 引用字段【数据库规则】:点表达式最后一级对应的字段类型;数据库字段值默认为Java字段的序列化值,默认使用JSON序列化【前端交互规则】:点表达式最后一级对应的字段控件类型 表3-3-9-1 字段引用类型 Step1 修改PetShopProxy类 为PetShopProxy类新增一个引用字段relatedShopName,并加上@Field.Related("shopName")注解 为PetShopProxy类新增一个引用字段createrId,并加上@Field.Related({"creater","id"})注解 package pro.shushi.pamirs.demo.api.proxy; import pro.shushi.pamirs.demo.api.model.PetShop; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.enmu.ModelTypeEnum; import pro.shushi.pamirs.user.api.model.PamirsUser; @Model.model(PetShopProxy.MODEL_MODEL) @Model.Advanced(type = ModelTypeEnum.PROXY) @Model(displayName = "宠物店铺代理模型",summary="宠物店铺代理模型") public class PetShopProxy extends PetShop { public static final String MODEL_MODEL="demo.PetShopProxy"; @Field.many2one @Field(displayName = "创建者",required = true) @Field.Relation(relationFields = {"createUid"},referenceFields = {"id"}) private PamirsUser creater; @Field.Related("shopName") @Field(displayName = "引用字段shopName") private String relatedShopName; @Field.Related({"creater","id"}) @Field(displayName = "引用创建者Id") private String createrId; } 图3-3-9-1 修改PetShopProxy类 Step2 重启系统查看效果 我们发现商店管理-列表页面多出了两个有值字段:引用字段shopName和引用创建者Id 图3-3-9-2 商店管理-列表页面新增两个有值字段 二、关系类型 业务类型 Java类型 数据库类型 规则说明 O2O 模型/DataMap 不存储或varchar、text 一对一关系 M2O 模型/DataMap 不存储或varchar、text 多对一关系 O2M List<模型/DataMap> 不存储或varchar、text 一对多关系 M2M List<模型/DataMap> 不存储或varchar、text 多对多关系 表3-3-9-2 字段关系类型 多值字段或者关系字段需要存储,默认使用JSON格式序列化。多值字段数据库字段类型默认为varchar(1024);关系字段数据库字段类型默认为text。 关系字段 关联关系用于描述模型间的关联方式: 多对一关系,主要用于明确从属关系 一对多关系,主要用于明确从属关系 多对多关系,主要用于弱依赖关系的处理,提供中间模型进行关联关系的操作 一对一关系,主要用于多表继承和行内合并数据 图3-3-9-3 字段关联关系 名词解释 关联关系比较重要的名词解释如下: 关联关系:使用relation表示,模型间的关联方式的一种描述,包括关联关系类型、关联关系双边的模型和关联关系的读写 关联关系字段:业务类型ttype为O2O、O2M、M2O或M2M的字段 关联模型:使用references表示,自身模型关联的模型 关联字段:使用referenceFields表示,关联模型的字段,表示关联模型的哪些字段与自身模型的哪些字段建立关系 关系模型:自身模型 关系字段:使用relationFields表示,自身模型的字段,表示自身模型的哪些字段与关联模型的哪些字段建立关系 中间模型,使用through表示,只有多对多存在中间模型,模型的relationship=true 举例M2M关系类型 多对多关系,主要用于弱依赖关系的处理,提供中间模型进行关联关系的操作。这也是在业务开发中很常见用于描述单据间关系,该例子会举例两种方式描述多对多关系中间表,一是中间表没有在系统显示定义模型,二种是中间表显示定义模型。第一种往往仅是维护多对多关系,第二种往往用于多对多关系中间表自身也需要管理有业务含义,中间表模型还经常额外增加其他字段。 一是中间表没有在系统显示定义模型:如果出现跨模块的场景,在分布式环境下两个模块独立启动,有可能会导致系统关系表被删除的情况发生,因为没有显示定义中间表模型,中间表的模型所属模块会根据两边模型的名称计算,如果刚好被计算到非关系字段所属模型的模块。那么单独启动非关系字段所属模型的模块,则会导致删除关系表。 为什么不直接把中间表的模型所属模块设置为关系字段所属模型的模块?因为如果这样做,当模型两边都定义了多对多关系字段则会导致M2M关系表的所属模块出现混乱。 所以这里建议大家都选用:第二种中间表显示定义模型,不论扩展性还是适应性都会好很多。请用:through=XXXRelationModel.MODEL_MODEL 或者 throughClass=XXXRelationModel.class Step1 新建宠物达人模型,并分别为宠物商品和宠物商店增加 到宠物达人模型的字段 新建宠物达人模型PetTalent package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(PetTalent.MODEL_MODEL) @Model(displayName = "宠物达人",summary="宠物达人",labelFields ={"name"}) public class PetTalent extends AbstractDemoIdModel{ public static final String MODEL_MODEL="demo.PetTalent"; @Field(displayName = "达人") private String name; } 图3-3-9-4 新建宠物达人模型PetTalent 修改宠物商品模型,新增many2many字段petTalents,类型为List ,并加上注解@Field.many2many(relationFields = {"petItemId"},referenceFields = {"petTalentId"},through = PetItemRelPetTalent.MODEL_MODEL),through为指定关联中间表。 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.demo.api.tmodel.PetItemDetail; import pro.shushi.pamirs.meta.annotation.Field; import…

    2024年5月23日
    1.4K00

Leave a Reply

登录后才能评论