如何设计公用跳转动作(类似导入导出动作)

背景

设计一个公共动作,在界面设计器可以拖到页面里,点击之后跳转指定页面。就像导入导出一样。

实现思路

元数据计算时,初始化跳转动作,为本模块以及依赖于本模块的所有模块生成该跳转动作。实现所有模型都有该跳转动作的元数据。

代码示例:

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

import com.google.common.collect.Lists;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.boot.base.enmu.ActionTargetEnum;
import pro.shushi.pamirs.boot.base.enmu.ActionTypeEnum;
import pro.shushi.pamirs.boot.base.model.ViewAction;
import pro.shushi.pamirs.boot.common.api.command.AppLifecycleCommand;
import pro.shushi.pamirs.boot.common.extend.MetaDataEditor;
import pro.shushi.pamirs.core.common.InitializationUtil;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.dto.meta.Meta;
import pro.shushi.pamirs.meta.api.dto.meta.MetaData;
import pro.shushi.pamirs.meta.domain.model.ModelDefinition;
import pro.shushi.pamirs.meta.enmu.ActionContextTypeEnum;
import pro.shushi.pamirs.meta.enmu.SystemSourceEnum;
import pro.shushi.pamirs.meta.enmu.ViewTypeEnum;
import pro.shushi.pamirs.top.api.TopModule;
import pro.shushi.pamirs.top.api.model.Teacher;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class DemoModuleAppInstall implements MetaDataEditor {
    @Override
    public void edit(AppLifecycleCommand command, Map<String, Meta> metaMap) {
        InitializationUtil util = InitializationUtil.get(metaMap, TopModule.MODULE_MODULE, TopModule.MODULE_NAME);
        if (util == null) {
            return;
        }
        if (MapUtils.isEmpty(metaMap)) {
            return;
        }

        Set<String> dependencyFileModels = metaMap.values().stream()
                .filter(v -> v.getData().containsKey(TopModule.MODULE_MODULE))
                .map(Meta::getModule)
                .collect(Collectors.toSet());
        for (String module : metaMap.keySet()) {
            if (!dependencyFileModels.contains(module)) {
                // 不依赖本模块,不生成跳转动作
                continue;
            }
            Meta meta = metaMap.get(module);
            MetaData metaData = meta.getCurrentModuleData();
            List<ModelDefinition> modelList = metaData.getDataList(ModelDefinition.MODEL_MODEL);
            for (ModelDefinition data : modelList) {
                makeDefaultModelViewAction(meta, data, dependencyFileModels);
            }
        }
    }

    // 跳转的xml模版 name
    public static final String DEFAULT_VIEW_NAME = "fixed_teacher_table";

    private void makeDefaultModelViewAction(Meta meta, ModelDefinition data, Set<String> dependencyFileModels) {
        if (!dependencyFileModels.contains(data.getModule())) {
            // 当前模块使用了其他模块的模型,对方模块未依赖本模块,不生成跳转动作
            return;
        }
        Map<String, Object> context = new HashMap<>();
        context.put("model", "'" + data.getModel() + "'");
        // 创建 跳转表格页面 viewAction,根据实际需求更改
        makeDefaultViewAction(meta, data,
                "teacherListDialog",
                "教师表格",
                null,
                ActionContextTypeEnum.CONTEXT_FREE,
                ViewTypeEnum.TABLE, 99,
                Teacher.MODEL_MODEL, DEFAULT_VIEW_NAME, ActionTargetEnum.DIALOG,
                context);
    }

    private void makeDefaultViewAction(Meta meta, ModelDefinition data,
                                             String viewActionName,
                                             String displayName,
                                             String title,
                                             ActionContextTypeEnum contextType,
                                             ViewTypeEnum viewType,
                                             int priority,
                                             String resModel,
                                             String resViewName,
                                             ActionTargetEnum target,
                                             Map<String, Object> context) {
        String sign = ViewAction.sign(data.getModel(), viewActionName);
        ViewAction defaultViewAction = meta.getData().get(data.getModule())
                .getDataItem(ViewAction.MODEL_MODEL, sign);
        boolean newAction = false;
        if (null == defaultViewAction) {
            defaultViewAction = new ViewAction();
            newAction = true;
        }
        if (newAction || SystemSourceEnum.MANUAL.equals(defaultViewAction.getSystemSource())) {
            defaultViewAction.setDisplayName(displayName)
                    .setLabel(defaultViewAction.getDisplayName())
                    .setName(viewActionName)
                    .setModel(data.getModel());
            defaultViewAction.setTitle(title)
                    .setViewType(viewType)
                    .setTarget(Optional.ofNullable(target).orElse(ActionTargetEnum.ROUTER))
                    .setResModel(resModel)
                    .setResViewName(resViewName)
                    .setResModule(null)
                    .setResModuleName(null)
                    .setContextType(contextType)
                    .setActionType(ActionTypeEnum.VIEW)
                    .setBindingType(Lists.newArrayList(ViewTypeEnum.TABLE))
                    .setContext(context)
                    .setPriority(priority)
                    .setSystemSource(SystemSourceEnum.MANUAL);
            defaultViewAction.setSign(sign);
            if (newAction) {
                defaultViewAction.construct();
                meta.getData().get(data.getModule()).addData(defaultViewAction);
            } else {
                defaultViewAction.disableMetaCompleted();
            }
        }
    }
}

xml模版示例,默认模版文件放到/pamirs/views/模块编码/template下面

可以利用界面设计器生成需要的跳转页面。在base_view表里面根据model以及title查询,template字段就是xml模版。拷贝出来之后,在view标签里指定一个name(即上文的DEFAULT_VIEW_NAME),然后保存为xml文件放到resource/pamirs/views/模块编码/template路径下面

<view model="top.Teacher" name = "fixed_teacher_table"  type="table">
    <template colSpan="FULL" slot="search">
        <field colSpan="QUARTER" data="enumType" widget="Select"/>
        <field allowClear="true" autoFillOptions="true" colSpan="QUARTER" data="professionalId" label="科目id" showThousandth="false" statistics="false" widget="Integer"/>
    </template>
    <template colSpan="FULL" cols="24" slot="tableGroup"/>
    <template slot="actionBar">
        <action label="导入" name="internalGotoListImportDialog"/>
        <action label="导出" name="internalGotoListExportDialog" sync="true"/>
        <action label="打印" name="internalGotoPrintDialog"/>
    </template>
    <template checkbox="true" colSpan="FULL" defaultPageSize="OPTION_2" enableSequence="false" filter="" inlineActiveCount="THREE" slot="table" sortable="false">
        <field allowClear="true" autoFillOptions="true" colSpan="HALF" data="teacherName" label="教师名字" patternType="NONE" showCount="false" type="TEXT" widget="Input"/>
        <field allowClear="true" autoFillOptions="true" colSpan="HALF" data="field00001" invisible="true" label="嵌入网页" patternType="NONE" showCount="false" type="TEXT" widget="Input"/>
        <field allowClear="true" autoFillOptions="true" colSpan="HALF" data="readStatus" label="读取状态" optionColorStyle="COLORFUL" widget="Select">
            <options>
                <option displayName="未读" label="未读" name="NO_READ"/>
                <option displayName="结束" label="结束" name="READ"/>
            </options>
        </field>
        <field data="createDate" widget="DateTimePicker"/>
        <field data="writeDate" widget="DateTimePicker"/>
        <template slot="rowActions" colSpan="FULL">
        </template>
        <field data="id" invisible="true"/>
    </template>
</view>

效果:

如何设计公用跳转动作(类似导入导出动作)

Oinone社区 作者:yexiu原创文章,如若转载,请注明出处:https://doc.oinone.top/other/22199.html

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

Like (0)
yexiu's avataryexiu数式员工
Previous 2025年10月13日 pm3:50
Next 2025年11月10日 am10:37

相关推荐

  • Oinone 初级学习路径

    文档说明 文档链接 介绍Oinone前端相关知识点 前端基础学习路径 介绍Oinone后端相关知识点 后端基础学习路径 介绍平台基础组件 平台基础组件 介绍平台设计器常用场景实操 设计器基础学习路径 设计器实操案例示例 7.2 实战训练(积分发放)

    2024年6月15日
    1.7K00
  • 前端自定义组件之锚点分组

    本文将讲解如何通过自定义,实现锚点组件。这个锚点组件会根据界面设计器拖入的分组,动态解析出锚点。 实现路径 整体的实现思路是界面设计器拖个容器类的组件(这里以选项卡为例),自定义这个选项卡,往选项卡里拖拽的每个分组,每个锚点的名称是分组的标题。 1. 界面设计器拖出页面 我们界面设计器拖个选项卡组件,然后在选项页里拖拽任意多个分组。完成后点击右上角九宫格,选中选项卡,填入组件 api 名称,作用是把选项卡切换成我们自定义的锚点分组组件,这里的 api 名称和自定义组件的 widget 对应。最后发布页面,并绑定菜单。 2. 组件实现 widget 组件重写了选项卡,核心函数 renderGroups,通过 DslRender.render 方法渲染界面设计器拖拽的分组。 import { BasePackWidget, DslDefinition, DslRender, SPI, Widget } from '@oinone/kunlun-dependencies'; import TabsParseGroup from './TabsParseGroup.vue'; function fetchGroupChildren(widgets?: DslDefinition[], level = 1): DslDefinition[] { if (!widgets) { return []; } const children: DslDefinition[] = []; for (const widget of widgets) { if (widget.widget === 'group') { children.push(widget); } else if (level >= 1) { fetchGroupChildren(widget.widgets, level – 1).forEach((child) => children.push(child)); } } return children; } @SPI.ClassFactory( BasePackWidget.Token({ widget: 'TabsParseGroup' }) ) export class TabsParseGroupWidget extends BasePackWidget { public initialize(props) { super.initialize(props); this.setComponent(TabsParseGroup); return this; } // 获取分组的子元素 public get groupChildren(): DslDefinition[] { return fetchGroupChildren(this.template?.widgets); } @Widget.Reactive() public get groupTitles() { return this.groupChildren.map((group) => group.title); } // 根据容器子元素渲染左侧 @Widget.Method() public renderGroups() { if (this.groupChildren && this.groupChildren.length) { return this.groupChildren.map((group) => DslRender.render(group)); } } } vue组件核心内容是用component :is属性,渲染出配置的分组组件 <template> <div class="TabsParseGroup"> <a-anchor :affix="false"> <a-anchor-link v-for="(item, index) in groupTitles" :href="`#default-group-${index}`" :title="item" /> </a-anchor> <div v-for="(item, index) in groupComponents" :id="`default-group-${index}`"> <component :is="item" /> </div> </div> </template> <script lang="ts"> import { computed, defineComponent, PropType } from 'vue'; export default…

    2025年7月8日
    58900
  • 如何实现业务表格跳转页面设计器设计器页面

    后端实现 代理继承界面设计器视图模型 @Model.model(MyView.MODEL_MODEL) @Model(displayName = "视图代理") @Model.Advanced(type = ModelTypeEnum.PROXY) public class MyView extends UiDesignerViewProxy { public static final String MODEL_MODEL = "hr.simple.MyView"; @Field.Integer @Field(displayName = "页面布局ID") private Long uiDesignerViewLayoutId; } 重写查询接口,返回页面布局ID,重写创建接口,实现创建页面逻辑。 package pro.shushi.pamirs.top.core.action; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import pro.shushi.pamirs.boot.base.constants.ViewConstants; import pro.shushi.pamirs.boot.base.enmu.ActionTargetEnum; import pro.shushi.pamirs.boot.base.ux.annotation.action.UxAction; import pro.shushi.pamirs.boot.base.ux.annotation.action.UxRoute; import pro.shushi.pamirs.boot.base.ux.annotation.button.UxRouteButton; import pro.shushi.pamirs.framework.connectors.data.sql.Pops; import pro.shushi.pamirs.framework.connectors.data.sql.query.LambdaQueryWrapper; import pro.shushi.pamirs.meta.annotation.Action; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.meta.api.dto.condition.Pagination; import pro.shushi.pamirs.meta.api.dto.wrapper.IWrapper; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.meta.constant.FunctionConstants; import pro.shushi.pamirs.meta.enmu.*; import pro.shushi.pamirs.top.api.model.MyView; import pro.shushi.pamirs.ui.designer.api.designe.UiDesignerViewLayoutService; import pro.shushi.pamirs.ui.designer.model.UiDesignerViewLayout; import pro.shushi.pamirs.ui.designer.pmodel.UiDesignerViewLayoutProxy; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author Yexiu at 20:39 on 2025/3/27 */ @Component @Model.model(MyView.MODEL_MODEL) public class MyViewAction { @Autowired private UiDesignerViewLayoutService uiDesignerViewLayoutService; @Action.Advanced(name = FunctionConstants.create, managed = true) @Action(displayName = "创建", summary = "添加", bindingType = ViewTypeEnum.FORM) @Function(name = FunctionConstants.create) @Function.fun(FunctionConstants.create) public MyView create(MyView data) { UiDesignerViewLayoutProxy uiDesignerViewLayoutProxy = new UiDesignerViewLayoutProxy(); uiDesignerViewLayoutProxy.setBizType(data.getBizType()); uiDesignerViewLayoutProxy.setDesignerActionBarType(data.getDesignerActionBarType()); uiDesignerViewLayoutProxy.setViewType(data.getType()); uiDesignerViewLayoutProxy.setModel(data.getModel()); uiDesignerViewLayoutProxy.setModule(PamirsSession.getServApp()); uiDesignerViewLayoutProxy.setViewTitle(data.getTitle()); uiDesignerViewLayoutProxy.setUsingDefaultView(data.getLoadLayout()); UiDesignerViewLayoutProxy saveUiDesigner = uiDesignerViewLayoutService.create(uiDesignerViewLayoutProxy); data.setDesignerViewId(saveUiDesigner.getId()); return data; } @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "查询列表") @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.API, FunctionOpenEnum.LOCAL}) public Pagination<MyView> queryPage(Pagination<MyView> page, IWrapper<MyView> queryWrapper) { LambdaQueryWrapper<MyView> wrapper = Pops.<MyView>lambdaQuery().from(MyView.MODEL_MODEL) .eq(MyView::getSys, Boolean.FALSE) .eq(MyView::getSystemSource, SystemSourceEnum.UI); Pagination<MyView> myViewPagination = new MyView().queryPage(page, wrapper); List<MyView> content…

    2025年3月31日
    66900
  • 后台嵌入其他系统的界面,设计器:嵌入网页组件

    管理后台如何新增Iframe嵌入其他系统的界面: 1、新建一个模型。模型中有放【url】的字段2、3、切换组件4、点击发布5、测试环境验证下,后端那个字段返回嵌入的【url】就可以展示这个url的内容了6、最后效果如下:

    2024年12月27日
    2.0K00

Leave a Reply

Please Login to Comment