Excel导出模块翻译值

由于目前翻译资源导出只可以导出应用资源,无法导出模块资源,所以暂时提供以下方法导出模块资源。
6.2.11、5.7.4.20 之前版本验证

方案一:

导出环境覆盖以下类

package pro.shushi.pamirs.translate.template.imports;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.file.api.context.ExcelDefinitionContext;
import pro.shushi.pamirs.file.api.entity.ExcelExportFetchDataContext;
import pro.shushi.pamirs.file.api.extpoint.impl.DefaultExcelExportFetchDataExtPoint;
import pro.shushi.pamirs.file.api.model.ExcelExportTask;
import pro.shushi.pamirs.framework.connectors.data.sql.Pops;
import pro.shushi.pamirs.framework.connectors.data.sql.query.LambdaQueryWrapper;
import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper;
import pro.shushi.pamirs.meta.annotation.Ext;
import pro.shushi.pamirs.meta.annotation.ExtPoint;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.Models;
import pro.shushi.pamirs.meta.api.dto.wrapper.IWrapper;
import pro.shushi.pamirs.meta.common.lambda.LambdaUtil;
import pro.shushi.pamirs.meta.common.util.PStringUtils;
import pro.shushi.pamirs.meta.constant.SqlConstants;
import pro.shushi.pamirs.meta.domain.module.ModuleDefinition;
import pro.shushi.pamirs.resource.api.enmu.TranslationApplicationScopeEnum;
import pro.shushi.pamirs.resource.api.model.ResourceTranslation;
import pro.shushi.pamirs.resource.api.model.ResourceTranslationItem;
import pro.shushi.pamirs.translate.constant.TranslateConstants;
import pro.shushi.pamirs.translate.proxy.TranslationItemExportProxy;
import pro.shushi.pamirs.translate.service.TranslationDslNodeVisitor;
import pro.shushi.pamirs.translate.template.TranslateTemplate;
import pro.shushi.pamirs.translate.utils.UniversalParser;

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

import static pro.shushi.pamirs.translate.constant.TranslateConstants.FIELD_TO_EXCLUDE;

/**
 * @author Adamancy Zhang
 * @date 2020-11-04 18:09
 */
@Slf4j
@Component
@Ext(ExcelExportTask.class)
@SuppressWarnings({"unchecked"})
public class ResourceTranslationExportExtPoint extends DefaultExcelExportFetchDataExtPoint {

    private String resLangCodeColumn = PStringUtils.fieldName2Column(LambdaUtil.fetchFieldName(ResourceTranslationItem::getResLangCode));
    private String langCodeColumn = PStringUtils.fieldName2Column(LambdaUtil.fetchFieldName(ResourceTranslationItem::getLangCode));
    private String moduleColumn = PStringUtils.fieldName2Column(LambdaUtil.fetchFieldName(ResourceTranslationItem::getModule));

    @Override
    @ExtPoint.Implement(expression = "context.name=="" + TranslateTemplate.TEMPLATE_NAME + "" && context.model=="" + ResourceTranslation.MODEL_MODEL + """)
    public List<Object> fetchExportData(ExcelExportTask exportTask, ExcelDefinitionContext context) {
        ArrayList<Object> objects = new ArrayList<>();
        Map<String, Object> queryData = exportTask.getConditionWrapper().getQueryData();

        TranslationItemExportProxy data = JSON.parseObject(JSON.toJSONString(queryData), TranslationItemExportProxy.class);
        LambdaQueryWrapper<TranslationItemExportProxy> queryWrapper = Pops.<TranslationItemExportProxy>lambdaQuery()
                .from(TranslationItemExportProxy.MODEL_MODEL)
                .eq(StringUtils.isNotBlank(data.getModule()), ResourceTranslationItem::getModule, data.getModule())
                .eq(ResourceTranslationItem::getResLangCode, TranslateConstants.RES_LANG_CODE)
                .eq(StringUtils.isNotBlank(data.getLangCode()), ResourceTranslationItem::getLangCode, data.getLangCode())
                .eq(data.getState() != null, ResourceTranslationItem::getState, data.getState())
                .like(StringUtils.isNotBlank(data.getResLangInclude()), ResourceTranslationItem::getOrigin, data.getResLangInclude())
                .like(StringUtils.isNotBlank(data.getTargetInclude()), ResourceTranslationItem::getTarget, data.getResLangInclude());

        Map<String, String> moduleNameMap = Models.origin().queryListByWrapper(Pops.<ModuleDefinition>lambdaQuery()
                        .from(ModuleDefinition.MODEL_MODEL)
                        .eq(StringUtils.isNotBlank(data.getModule()), ModuleDefinition::getModule, data.getModule()))
                .stream()
                .collect(Collectors.toMap(ModuleDefinition::getModule, ModuleDefinition::getDisplayName, (_a, _b) -> _a));
        ModuleDefinition moduleDefinition = new ModuleDefinition();
        moduleDefinition.setModule(TranslateConstants.PUBLIC_RESOURCE);
        moduleDefinition = moduleDefinition.queryOne();
        moduleNameMap.put(moduleDefinition.getModule(), moduleDefinition.getDisplayName());

        List<TranslationItemExportProxy> translationItemExportProxies = new ArrayList<>();
        //TODO 源语言无法识别请在YAML 中直接配置
        switch (data.getIsTranslate()) {
            case TRANSLATED:
                queryWrapper.eq(data.getScope() != null, ResourceTranslationItem::getScope, data.getScope()).isNotNull(ResourceTranslationItem::getTarget);
                translationItemExportProxies = new TranslationItemExportProxy().queryList(queryWrapper);
                Models.origin().listFieldQuery(translationItemExportProxies, TranslationItemExportProxy::getTranslation);
                if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                    for (TranslationItemExportProxy item : translationItemExportProxies) {
                        item.setModule(Optional.ofNullable(item.getModule()).map(moduleNameMap::get).orElse(item.getModule()));
                        item.setComments(Optional.ofNullable(item.getTranslation().getComments()).orElse(""));
                    }
                }
                if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                    objects.add(translationItemExportProxies);
                }
                break;
            case NOT_TRANSLATED:
                translationItemExportProxies = new TranslationItemExportProxy().queryList(queryWrapper);
                if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                    translationItemExportProxies = new TranslationItemExportProxy().listFieldQuery(translationItemExportProxies, TranslationItemExportProxy::getTranslation);
                }
                if (TranslationApplicationScopeEnum.GLOBAL.equals(data.getScope()) || Boolean.TRUE.equals(data.getState())
                        || StringUtils.isNotBlank(data.getTargetInclude()) || StringUtils.isNotBlank(data.getResLangInclude())) {
                    break;
                }
                //解析XML
                Map<String, Set<String>> translationContext = parseXmlAndModelAndEnumAndErrorInfo(data, moduleNameMap);

                // 初始化结果容器
                List<TranslationItemExportProxy> noTranslateItems = new ArrayList<>();
                Map<Boolean, Map<String, List<String>>> origins = new HashMap<>();
                origins.put(true, new HashMap<>());
                origins.put(false, new HashMap<>());

                // 单次遍历处理两个操作
                translationItemExportProxies.forEach(item -> {
                    // 处理第一个过滤和收集操作
                    if (StringUtils.isEmpty(item.getTarget()) && Boolean.TRUE.equals(Optional.ofNullable(item.getSystem()).orElse(Boolean.FALSE))) {
                        item.setModule(Optional.ofNullable(item.getModule()).map(moduleNameMap::get).orElse(item.getModule()));
                        item.setState(false);
                        item.setComments("");
                        item.setLangCode(Optional.ofNullable(data.getLangCode()).orElse(""));
                        item.setResLangCode(TranslateConstants.RES_LANG_CODE);
                        noTranslateItems.add(item);
                    }

                    // 处理分类和收集操作
                    if (TranslationApplicationScopeEnum.GLOBAL.equals(item.getScope()) || TranslationApplicationScopeEnum.MODULE.equals(item.getScope())) {
                        boolean isGlobal = TranslationApplicationScopeEnum.GLOBAL.equals(item.getScope());
                        String module = isGlobal ? "" : item.getModule();

                        origins.computeIfAbsent(isGlobal, k -> new HashMap<>())
                                .computeIfAbsent(module, k -> new ArrayList<>())
                                .add(item.getOrigin());
                    }
                });

                List<String> overallOrigins = origins.get(true).get("");
                Map<String, List<String>> applicationOrigins = origins.get(false);

                for (Map.Entry<String, Set<String>> entry : translationContext.entrySet()) {
                    if (applicationOrigins.containsKey(entry.getKey())) {
                        List<String> list = applicationOrigins.get(entry.getKey());
                        entry.getValue().removeAll(list);
                        entry.getValue().removeAll(overallOrigins);
                    }
                }

                //生成系统中未翻译的字段
                translationItemExportProxies = getTranslationItemExportProxies(moduleNameMap, translationContext, data);
                translationItemExportProxies.addAll(noTranslateItems);
                if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                    objects.add(translationItemExportProxies);
                }
                break;
            default:
                List<TranslationItemExportProxy> result = new ArrayList<>();
                queryWrapper.eq(data.getScope() != null, ResourceTranslationItem::getScope, data.getScope());
                translationItemExportProxies = new TranslationItemExportProxy().queryList(queryWrapper);
                if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                    translationItemExportProxies = new TranslationItemExportProxy().listFieldQuery(translationItemExportProxies, TranslationItemExportProxy::getTranslation);
                }

                if (TranslationApplicationScopeEnum.GLOBAL.equals(data.getScope()) || Boolean.TRUE.equals(data.getState()) || StringUtils.isNotBlank(data.getTargetInclude())) {
                    if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                        for (TranslationItemExportProxy item : translationItemExportProxies) {
                            item.setModule(Optional.ofNullable(item.getModule()).map(moduleNameMap::get).orElse(item.getModule()));
                            item.setComments(Optional.ofNullable(item.getTranslation()).map(ResourceTranslation::getComments).orElse(null));
                        }
                        result.addAll(translationItemExportProxies);
                        objects.add(result);
                    }
                    break;
                }
                Map<String, Set<String>> tContext = parseXmlAndModelAndEnumAndErrorInfo(data, moduleNameMap);

                Map<Boolean, Map<String, List<String>>> origins0 = translationItemExportProxies.stream()
                        .filter(item -> TranslationApplicationScopeEnum.GLOBAL.equals(item.getScope()) || TranslationApplicationScopeEnum.MODULE.equals(item.getScope()))
                        .collect(Collectors.partitioningBy(
                                item -> TranslationApplicationScopeEnum.GLOBAL.equals(item.getScope()),
                                Collectors.groupingBy(
                                        item -> TranslationApplicationScopeEnum.MODULE.equals(item.getScope()) ? item.getModule() : "",
                                        Collectors.mapping(TranslationItemExportProxy::getOrigin, Collectors.toList())
                                )
                        ));

                List<String> overOrigins = origins0.get(true).getOrDefault("", Collections.emptyList());
                Map<String, List<String>> applicationsOrigins = origins0.get(false);

                for (Map.Entry<String, Set<String>> entry : tContext.entrySet()) {
                    if (applicationsOrigins.containsKey(entry.getKey())) {
                        List<String> list = applicationsOrigins.get(entry.getKey());
                        entry.getValue().removeAll(list);
                        entry.getValue().removeAll(overOrigins);
                    }
                }

                //生成系统中未翻译的字段
                List<TranslationItemExportProxy> noTranslation = getTranslationItemExportProxies(moduleNameMap, tContext, data);
                if (CollectionUtils.isNotEmpty(translationItemExportProxies)) {
                    for (TranslationItemExportProxy item : translationItemExportProxies) {
                        item.setModule(Optional.ofNullable(item.getModule()).map(moduleNameMap::get).orElse(item.getModule()));
                        item.setComments(Optional.ofNullable(item.getTranslation()).map(ResourceTranslation::getComments).orElse(null));
                    }
                    result.addAll(translationItemExportProxies);
                }
                if (CollectionUtils.isNotEmpty(noTranslation)) {
                    result.addAll(noTranslation);
                }
                objects.add(result);
                break;
        }
        return objects;
    }

    private Map<String, Set<String>> parseXmlAndModelAndEnumAndErrorInfo(TranslationItemExportProxy data, Map<String, String> moduleNameMap) {
        //解析XML
        TranslationDslNodeVisitor translationVisitor = UniversalParser.getTranslationDslNodeVisitor(data);
        Map<String, Set<String>> tContext = translationVisitor.context;
        //解析模型
        UniversalParser.parseModel(moduleNameMap, tContext, data.getModule());
        //解析枚举
        UniversalParser.parseModelEnum(moduleNameMap, tContext, data.getModule());
        //解析错误信息
        UniversalParser.parseErrorInfo(moduleNameMap, tContext, data.getModule());
        return tContext;
    }

    /**
     * 生成系统中未翻译的字段
     *
     * @param moduleNameMap      模块编码与名称的映射
     * @param translationContext 需要翻译的字段
     * @param data
     * @return
     */
    private static List<TranslationItemExportProxy> getTranslationItemExportProxies(Map<String, String> moduleNameMap, Map<String, Set<String>> translationContext, TranslationItemExportProxy data) {
        List<TranslationItemExportProxy> translationItemExportProxies = new ArrayList<>();

        for (Map.Entry<String, Set<String>> entry : translationContext.entrySet()) {
            for (String origin : entry.getValue()) {
                if (FIELD_TO_EXCLUDE.contains(origin.toLowerCase())) {
                    continue;
                }
                if (StringUtils.isNotBlank(data.getResLangInclude())) {
                    if (origin.contains(data.getResLangInclude())) {
                        TranslationItemExportProxy item = new TranslationItemExportProxy();
                        item.setModule(Optional.ofNullable(entry.getKey()).map(moduleNameMap::get).orElse(entry.getKey()));
                        item.setResLangCode(TranslateConstants.RES_LANG_CODE);
                        item.setLangCode(Optional.ofNullable(data.getLangCode()).orElse(""));
                        item.setOrigin(origin);
                        item.setState(false);
                        item.setScope(TranslationApplicationScopeEnum.MODULE);
                        item.setComments("");
                        translationItemExportProxies.add(item);
                    }
                } else {
                    TranslationItemExportProxy item = new TranslationItemExportProxy();
                    item.setModule(Optional.ofNullable(entry.getKey()).map(moduleNameMap::get).orElse(entry.getKey()));
                    item.setResLangCode(TranslateConstants.RES_LANG_CODE);
                    item.setLangCode(Optional.ofNullable(data.getLangCode()).orElse(""));
                    item.setOrigin(origin);
                    item.setState(false);
                    item.setScope(TranslationApplicationScopeEnum.MODULE);
                    item.setComments("");
                    translationItemExportProxies.add(item);

                }
            }
        }
        return translationItemExportProxies;
    }

    @Override
    protected IWrapper<?> queryBefore(ExcelExportFetchDataContext context, IWrapper<?> wrapper) {
        wrapper.setModel(ResourceTranslation.MODEL_MODEL);
        List<?> translations = Models.data().queryListByWrapper(wrapper);

        QueryWrapper<ResourceTranslationItem> itemWrapper = Pops.query();
        itemWrapper.setModel(ResourceTranslationItem.MODEL_MODEL);

        if (CollectionUtils.isEmpty(translations)) {
            itemWrapper.lt(SqlConstants.ID, 0);
        } else {
            itemWrapper.in(
                    Lists.newArrayList(resLangCodeColumn, langCodeColumn, moduleColumn),
                    translations.stream()
                            .map(i -> ((ResourceTranslation) i).getResLangCode())
                            .collect(Collectors.toList()),
                    translations.stream()
                            .map(i -> ((ResourceTranslation) i).getLangCode())
                            .collect(Collectors.toList()),
                    translations.stream()
                            .map(i -> ((ResourceTranslation) i).getModule())
                            .collect(Collectors.toList())
            );
        }
        return itemWrapper;
    }
}
package pro.shushi.pamirs.translate.action;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.core.common.WrapperHelper;
import pro.shushi.pamirs.framework.connectors.cdn.factory.FileClientFactory;
import pro.shushi.pamirs.framework.connectors.data.sql.query.LambdaQueryWrapper;
import pro.shushi.pamirs.framework.gateways.rsql.RSQLHelper;
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.constant.FunctionConstants;
import pro.shushi.pamirs.meta.enmu.FunctionOpenEnum;
import pro.shushi.pamirs.meta.enmu.FunctionTypeEnum;
import pro.shushi.pamirs.translate.constant.TranslateConstants;
import pro.shushi.pamirs.translate.proxy.TranslationModuleProxy;

import java.util.List;

@Component
@Model.model(TranslationModuleProxy.MODEL_MODEL)
public class TranslationModuleProxyAction {

    @Function.Advanced(type = FunctionTypeEnum.QUERY)
    @Function.fun(FunctionConstants.queryPage)
    @Function(openLevel = {FunctionOpenEnum.LOCAL, FunctionOpenEnum.REMOTE, FunctionOpenEnum.API})
    public Pagination<TranslationModuleProxy> queryPage(Pagination<TranslationModuleProxy> page, IWrapper<TranslationModuleProxy> queryWrapper) {
        String displayName = RSQLHelper.getFieldValue(TranslationModuleProxy.MODEL_MODEL, queryWrapper.getOriginRsql(), TranslationModuleProxy::getDisplayName).orElse("");
        LambdaQueryWrapper<TranslationModuleProxy> qw = WrapperHelper.lambda(queryWrapper);

        if (StringUtils.isEmpty(displayName) || TranslateConstants.PUBLIC_RESOURCE_NAME.contains(displayName.replace("%", ""))) {
            qw.or(item -> item.eq(TranslationModuleProxy::getModule, TranslateConstants.PUBLIC_RESOURCE));
        }

        Pagination<TranslationModuleProxy> translationModuleProxyPagination = new TranslationModuleProxy().queryPage(page, qw);
        TranslationModuleProxy translationModuleProxy = null;
        List<TranslationModuleProxy> content = translationModuleProxyPagination.getContent();
        if (CollectionUtils.isNotEmpty(content)) {
            for (TranslationModuleProxy moduleProxy : content) {
                if (TranslateConstants.PUBLIC_RESOURCE.equals(moduleProxy.getModule())) {
                    translationModuleProxy = moduleProxy;
                }
                String logo = moduleProxy.getLogo();
                if (StringUtils.isBlank(logo)) {
                    logo = FileClientFactory.getClient().getStaticUrl() + "/oinone/static/images/default.png";
                }
                moduleProxy.setLogo(logo);
            }
        }
        if (translationModuleProxy != null) {
            content.remove(translationModuleProxy);
            content.add(0, translationModuleProxy);
        }
        return translationModuleProxyPagination;
    }
}

替换完毕之后即可在 翻译 - 导出 页面导出模块资源。

方案二:如无法替换文件,可使用以下方案

与翻译的导出全部翻译项类似,需要通过工具发起后端服务请求,拿到导入导出翻译Excel模版,添加模版翻译项。(查看路径:文件--导出任务)

{
  translationItemExportProxyQuery {
    export(
      data: {isTranslate: ALL, module: "top_demo", state: true, langCode: null}
    ) {
      isTranslate
      moduleDefinition {
        displayName
        module
        id
      }
      module
      state
      lang {
        code
        name
        id
      }
      langCode
      scope
      resLangInclude
      targetInclude
      id
    }
  }
}

参数说明:isTranslate 是否全部翻译项;module 模块编码;state 是否激活

修改翻译文件

拿到导出的翻译文件之后,将模版里的应用名字由 模块编码 替换为 模块展示名字,全部替换之后方可成功导入
Excel导出模块翻译值

导入翻译项

进入 翻译 — 导入翻译文件 导入修改后的翻译文件。

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

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

(0)
yexiu的头像yexiu数式员工
上一篇 2025年8月14日 pm5:55
下一篇 2025年8月22日 am10:51

相关推荐

  • Oinone 初级学习路径

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

    2024年6月15日
    1.2K00
  • SSO单点登录(5.3.x — 6.2.x)

    SSO相关 1、SSO服务端:在应用中找到【单点登录】,创建一个应用标识2、SSO登录认证,选择grant_type=password,后面带上用户名和密码。参考下面的链接(POST请求):http://127.0.0.1:8190/pamirs/sso/authorize?redirect_uri=http://127.0.0.1:8193/page;module=ysps;model=ysps.notify.ProjectPosting;action=homepage;scene=homepage;target=OPEN_WINDOW;path=/ysps/homepage&response_type=code&client_id=替换为已创建的应用唯一标识&grant_type=password&username=admin&password=admin 其中: redirect_uri是认证通过后的跳转,目前的场景可忽略 client_id替换为在单点登录也上创建的应用唯一标识 认证方式grant_type=password固定,后面是实际的用户名和密码 操作步骤: 请求服务端工程SSO登录认证,会返回token信息,拿着这个信息去客户端工程访问即可。 请求服务端工程返回token信息: curl –location –request POST ‘http://127.0.0.1:8190/pamirs/sso/authorize’ \ –header ‘User-Agent: Apifox/1.0.0 (https://apifox.com)’ \ –header ‘Accept: */*’ \ –header ‘Host: 127.0.0.1:8190’ \ –header ‘Connection: keep-alive’ \ –header ‘Content-Type: application/x-www-form-urlencoded’ \ –header ‘Cookie: pamirs_uc_session_id=88fd2459446a4a20ab0a505bdaf78ebe’ \ –data-urlencode ‘appkey=1d2195bac42e44e895ea8e030aaa4e52’ \ –data-urlencode ‘appSecret=JNEyibFBIb2N3tdLmW/M9bnpf120/I6fFMMf86OQlP/wlL5qhJCF3KdAKHlJT0jECmXmJRfTCSlnmB5cWHRsenNGND+TMoXObzDPK7umxazCnaZYiW7JDeuZUOzqskhBPkEJSURAZR5xu1c6UYv542BlHAPsEi+ujnKeCYcKiFHyw7fIB1aijNyCz8d9teUEGYYTtYTXoNp/4Ts8AIJn8xkTjvEq6V9uYOExDEuYGxMgN76ZaiwpbT5387eZy4XCDIy0XWfZo/kv7X+s+rjwlsxWA7jp1w5dDaRmSd4rPO2GSEcL64Pje/Ct5xznhNwH6T5KDd2BLfbZikonh624nqW4hdlVxx/EQUpYp6Yc4Wet6b/DkggCVIZPpcO9pSuRJoC2jGPMrGHM3vYR0YtfFqCJ2/x3m/lQr2v+bP4pGzcRuuCy2tyOZA1uurA23xlssehz4geGiJArkpAUKKUkcafx+dLWODHOcgBKBz6wY38PAcbLkgn6gK6lmmR7cUiDmzmEEor6pYb64YG6tPmpm4AQeBoQYrsyCorA4Ds08nAiPFWUCXcHQCVUbHPTOwHHChFO1lXH/VjkfDv0OI1CD8mZI7ZeK794aIBZdvQGCI+ayQU+5CD1asDNg/M01nnNdWKB7rS9rMvbUOlSNguboAgRbiz3pEAxGJrZUPvkDHM=’ { “access_token”: “eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3NDQyNTk2MTcsInN1YiI6IntcImNsaWVudElkXCI6XCJwYW1pcnNfMjc5YjcwMDBlNDE3NDMxMmFmNDAyMDM0YjhlZjFhOWRcIixcInJhbmRvbUFrSWRcIjpcIjM0MDBiYzY0Njk1MzQzODA4ZTlhNmZhNWRmZjU0MTc2XCIsXCJvcGVuSWRcIjpcIjEwMDAxXCJ9In0.iJ-meyxAGW189Y3aK9Z2rMbf9_MsTKVTfnf3XsDR4iq6qvCGYkiq5197r4A54wwdKAzPZ-iDgkQOjWDh8AYu4A”, “token_type”: null, “refresh_token”: “eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3NDQ4NTcyMTcsInN1YiI6IntcImRhdGVUaW1lXCI6XCIxNzQ0MjUyNDE3NDc3XCIsXCJjbGllbnRJZFwiOlwicGFtaXJzXzI3OWI3MDAwZTQxNzQzMTJhZjQwMjAzNGI4ZWYxYTlkXCIsXCJvcGVuSWRcIjpcIjEwMDAxXCJ9In0.TZaK8OuPKudd3YX6AF23m7aplJF7OQlBEDkj0AnPkQdw7aja2WhS7q-VwjPfhqSmfAp-oaaUIcN7Zlune9VLTA”, “expires_in”: 7200, “refresh_token_expiresIn”: 604800 } 发起客户端工程请求。 注意:请求Headers中需携带token参数信息,token为服务端工程返回token信息,且请求时Authorization参数需加上标识 Bearer+空格 –header 'loginType: OAUTH' –header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3NDQyMDYwNjUsInN1YiI6IntcImNsaWVudElkXCI6XCJwYW1pcnNfMjc5YjcwMDBlNDE3NDMxMmFmNDAyMDM0YjhlZjFhOWRcIixcInJhbmRvbUFrSWRcIjpcImEzZWZkNjZkMDNlNjQ5MDY4OGU4Y2FhYmIwNjZmZGU4XCIsXCJvcGVuSWRcIjpcIjEwMDAxXCJ9In0.gapCpvM8PCit1oSHv-zJ2tATkCuVQBzqWGebvBcUX2O0bqP9aAhVqQxdNLM19vCqP5s3CXoNk-xzMUu-mo-hSg' curl –location –request POST ‘http://127.0.0.1:8092/pamirs/base’ \ –header ‘loginType: OAUTH’ \ –header ‘Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3NDQyMDYwNjUsInN1YiI6IntcImNsaWVudElkXCI6XCJwYW1pcnNfMjc5YjcwMDBlNDE3NDMxMmFmNDAyMDM0YjhlZjFhOWRcIixcInJhbmRvbUFrSWRcIjpcImEzZWZkNjZkMDNlNjQ5MDY4OGU4Y2FhYmIwNjZmZGU4XCIsXCJvcGVuSWRcIjpcIjEwMDAxXCJ9In0.gapCpvM8PCit1oSHv-zJ2tATkCuVQBzqWGebvBcUX2O0bqP9aAhVqQxdNLM19vCqP5s3CXoNk-xzMUu-mo-hSg’ \ –header ‘User-Agent: Apifox/1.0.0 (https://apifox.com)’ \ –header ‘Content-Type: application/json’ \ –data-raw ‘{“query”:”mutation {\n teacherMutation {\n queryTea(\n data: {id: 672564120180166836, teacherName: \”““`\”, readStatus: NO_READ, createDate: \”2024-11-05 11:30:36\”, writeDate: \”2024-11-05 11:30:36\”, createUid: 10001, writeUid: 10001}\n ) {\n id\n teacherName\n enumType\n petStoreId\n professionalId\n professional {\n professionalName\n id\n }\n readStatus\n nonStoredField\n createDate\n writeDate\n createUid\n writeUid\n }\n }\n}\n”,”variables”:{}}’ SSO服务端工程(5.3.X以上版本支持) 1、服务端工程依赖 1.1 pom依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-sso-oauth2-server</artifactId> </dependency> 1.2 application.yml配置文件里面添加sso启动模块。 pamirs: boot: modules: – sso SSO客户端工程(5.3.X以上版本支持) 1、客户端工程依赖 客户端工程即需要加入SSO的应用 1.1 pom依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-sso-oauth2-client</artifactId> </dependency> 1.2 application.yml配置 pamirs: sso: enabled: true client: # SSO服务端提供 client-id: pamirs_1fb51c50acbb4842b36844c5fbdc8d25 # SSO服务端提供 client-secret: B3ySNQEJdD8kZXuwmtaUtbWTo1vlIevmd0t4MIqRHfuM8VXzkMcs6YOox6cPPIESAL3yd2xQa+SCBNbLwYchQYSJonGPpvAmqapc5ZdskPicNENc8T2vTAMkc/YgvgUUK4U+/OuP5PrtRKC536nNXIZy1VHdf+whi44qOgd4RQYN0sIrog70CXsDQP3/2CHkcXWVRCqvZa/4mFmL1SBhQ+TLAIQg0jXlWr4lThUdL/X9M0YFXBaLJPKTlKi9l7K/8kTdJL2IgvSpByU0kGXjk0O/jZRBq1bHd/ZsC3Rw4kjiygIdxfL7Q/lw1/WAZ5XXibc5dlylUsnSJBZ9I4ZeCWq7lEZj//ctR7WZJCCeqi8rmCu+N2FQvye7kgiFIoZTFMNSRhW7ZMBBrsoJuf6DGWGvXvBE9w3P/IVFJMDmsopNbbFYTRcmY5e5tc775OCGMQDrW6j8IitTrOdRYzie0S2Jj9+Xw+Va1sEQLXWj0tBNQ9Tzv7fnRr5D6EBNtXra1TntKrvH/quBI5ujncBZXZ2cfEoMjFSw38edoTA8WPJv10WUA5EZsvfxqJLEiXFriJ9nleUBbCvL3Zuggn64CW4cH8mxGk7qvHQvXmwmp8phKyoKa8UDfDD2x7eNW3oNcQUMz+gdGNF5dNXt4iArpYK5/xktpLxdCM5Yz7SpHoc= # login-url和login-url根据实际情况修改 login-url: http://test1.oinone.top:9095/login logout-url: https://test1.oinone.top:9095/pamirs/sso/logout expires:…

    2025年4月25日
    53800
  • 导入导出支持国际化语言分隔符

    需求 导出 Excel 时,所有整数、小数字段需要加千分位分隔符显示 例如:10000 导出成 10,000。 只影响“导出的显示效果”,不改变原始数据的语义。 实现思路 通过修改“ Excel 默认导出模版”的平台逻辑,将整型字段模版定义为文本类型,并自定义导出扩展,将所有整型字段的数据根据国际化配置进行分割。 代码示例 自定义导出扩展,分割整型字段 注意 所有已有的导出扩展必须修改继承类ExcelExportSameQueryPageTemplate<Object> –> GlobalExportExt<Object> 否则,已有的导出扩展生成的Excel将无法正常格式化整型字段。 package pro.shushi.pamirs.top.core.temp.exports; import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Component; import pro.shushi.pamirs.file.api.context.ExcelDefinitionContext; import pro.shushi.pamirs.file.api.entity.EasyExcelBlockDefinition; import pro.shushi.pamirs.file.api.entity.EasyExcelCellDefinition; import pro.shushi.pamirs.file.api.entity.EasyExcelSheetDefinition; import pro.shushi.pamirs.file.api.extpoint.ExcelExportFetchDataExtPoint; import pro.shushi.pamirs.file.api.extpoint.impl.ExcelExportSameQueryPageTemplate; import pro.shushi.pamirs.file.api.model.ExcelExportTask; import pro.shushi.pamirs.meta.annotation.Ext; import pro.shushi.pamirs.meta.annotation.ExtPoint; import pro.shushi.pamirs.meta.api.dto.config.ModelFieldConfig; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.meta.enmu.TtypeEnum; import pro.shushi.pamirs.meta.util.FieldUtils; import pro.shushi.pamirs.resource.api.model.ResourceLang; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @Component @Ext(ExcelExportTask.class) public class GlobalExportExt<T> extends ExcelExportSameQueryPageTemplate<T> implements ExcelExportFetchDataExtPoint { @ExtPoint.Implement(priority = 1) @Override public List<Object> fetchExportData(ExcelExportTask exportTask, ExcelDefinitionContext context) { List<Object> results = super.fetchExportData(exportTask, context); if (CollectionUtils.isEmpty(results)) { return results; } return dataFormat(context, results); } public static List<Object> dataFormat(ExcelDefinitionContext context, List<Object> results) { ResourceLang resourceLang = new ResourceLang().setCode(PamirsSession.getLang()).queryOne(); if (resourceLang == null) { return results; } // 小数分隔符 String decimalPoint = resourceLang.getDecimalPoint(); // 整数分隔符 String thousandsSep = resourceLang.getThousandsSep(); // 数字分组规则(每组多少位,比如 "3") String groupingRule = resourceLang.getGroupingRule(); // 解析 groupSize,只做一次 int groupSize = 3; if (groupingRule != null && groupingRule.matches("\\d+")) { try { groupSize = Integer.parseInt(groupingRule); } catch (NumberFormatException ignore) { } } boolean needGroup = groupSize > 0 && thousandsSep != null && !thousandsSep.isEmpty(); //…

    2025年11月18日
    35000
  • 前端学习路径

    准备工作 环境准备-1h安装基础环境,需要Node和PNPM如果已经安装检查对应版本,体验阶段建议版本保持一致 克隆一个空工程-0.5h全新工程 注意事项-0.5h静态资源解压,如果还没有对应的后端服务。可以使用:https://demo.oinone.top(Oinone演示环境),账号密码:admin/admin 前端基础 1.1.1了解组件-3h– 组件如何开发– 组件如何复用– 组件如何嵌套 1.1.2 更近一步-5h– 构建更复杂的工作台– 如何发起后端请求– 构建一个通用的图表组件 1.1.3 深入了解概念-5h– 通用概念、名词解释– 页面渲染原理– 组件执行原理 1.1.4业务实战-实现通用的甘特图组件-8h– 怎么与第三方结合– 如何在开源组件上接入Oinone, 并复用 1.1.5 业务实战-实现通用的画廊组件-6h–如何更近一步复用–基础学习结束 前端进阶 2.1.1代码和无代码如何结合-4h– 了解无代码如何使用和基础概念 2.1.2使用无代码搭建增删改查-8h– 了解无代码如何使用和基础概念 最后一步 当您实现玩基础和进阶的所有的效果,Oinone的整体使用您已经大致掌握了,接下来您可以找一个当前业务的场景来实现它把!

    2025年9月1日
    91700
  • 流程和任务状态说明文档

    一、工作流实例状态说明 INIT:新的流程创建时,执行工作流实例前的状态。 PROCESSING:发起的新的流程之后,结束之前的状态。 FINISHED:整个流程结束后的状态。 ERROR:流程异常时的状态。 RECALL: 撤销流程实例时的状态 CLOSE:关闭流程实例时(流程撤销)的状态。 一、工作流实例通过状态说明 FILLED:流程走到填写节点,填写人填写过后的状态。 PASS:审批同意操作后的状态。 REJECT:审批结果被拒绝(审批节点结束后)的状态。 ING:新的流程创建时,执行工作流实例前的状态。 ERROR:流程异常时的状态。 RECALL:撤销流程实例时的状态。 RECALL_PASS:无 RECALL_REJECT:无 RECALL_FILLED:无 FALLBACK:已退回时标识抄送/工作流实例为已退回时的状态。 FALLBACK_PASS:无 FALLBACK_REJECT:无 FALLBACK_FILLED:无 TRANSFER:无 CLOSE:关闭流程实例时((流程撤销))的状态。

    2025年6月24日
    41700

Leave a Reply

登录后才能评论