自定义前端拦截器

某种情况下,我们需要通过自定义请求拦截器来做自己的逻辑处理,平台内置了一些拦截器

登录拦截器LoginRedirectInterceptor

重定向到登录拦截器LoginRedirectInterceptor

import { UrlHelper, IResponseErrorResult, LoginRedirectInterceptor } from '@kunlun/dependencies';

export class BizLoginRedirectInterceptor extends LoginRedirectInterceptor {
  /**
   * 重定向到登录页
   * @param response 错误响应结果
   * @return 是否重定向成功
   */
  public redirectToLogin(response: IResponseErrorResult): boolean {
    if (window.parent === window) {
      const redirect_url = location.pathname;
      // 可自定义跳转路径
      location.href = `${UrlHelper.appendBasePath('login')}?redirect_url=${redirect_url}`;
    } else {
      // iframe页面的跳转
      window.open(`${window.parent.location.origin}/#/login`, '_top');
    }
    return true;
  }
}

请求成功拦截器RequestSuccessInterceptor

请求失败拦截器 RequestErrorInterceptor

网络请求异常拦截器 NetworkErrorInterceptor

当我们需要重写某个拦截器的时候,只需要继承对应的拦截器,然后重写里面的方法即可

// 自定义登录拦截器
export class CustomLoginRedirectInterceptor extends LoginRedirectInterceptor{
    public error(response: IResponseErrorResult) {
        // 自己的逻辑处理

        return true // 必写
    }
}

// 自定义请求成功拦截器
export class CustomRequestSuccessInterceptor extends RequestSuccessInterceptor{
    public success(response: IResponseErrorResult) {
        // 自己的逻辑处理
        return true // 必写
    }
}

// 自定义请求失败拦截器
export class CustomRequestErrorInterceptor extends RequestErrorInterceptor{
    public error(response: IResponseErrorResult) {
        const { errors } = response;

    if (errors && errors.length) {
      const notPermissionCodes = [
        SystemErrorCode.NO_PERMISSION_ON_MODULE,
        SystemErrorCode.NO_PERMISSION_ON_VIEW,
        SystemErrorCode.NO_PERMISSION_ON_MODULE_ENTRY,
        SystemErrorCode.NO_PERMISSION_ON_HOMEPAGE
      ];

      /**
       * 用来处理重复的错误提示
       */
      const executedMessages: string[] = [];

      for (const errorItem of errors) {
        const errorCode = errorItem.extensions?.errorCode;
        if (!notPermissionCodes.includes(errorCode as any)) {
          const errorMessage = errorItem.extensions?.messages?.[0]?.message || errorItem.message;

          if (!executedMessages.includes(errorMessage)) {
            // 自己的逻辑处理
          }

          executedMessages.push(errorMessage);
        }
      }
    }

    return true;
  }
}

// 自定义网络请求异常拦截器
export class CustomNetworkErrorInterceptor extends NetworkErrorInterceptor{
      public error(response: IResponseErrorResult) {
            const { networkError } = response;
            if (networkError) {
            const { name, message } = networkError;
            if (name && message) {
                // 自己的逻辑处理
            }
            return false;
            }
            return true;
  }
}

当拦截器的代码写完后,需要在启动工程里面的main.ts导入它

// main.ts
import MyInterceptor from './MyInterceptor.ts'
import BizLoginRedirectInterceptor from './BizLoginRedirectInterceptor.ts'

// 使用拦截器

VueOioProvider({
    ...
    http: {
        url: '',
        interceptor: {
            loginRedirect: new BizLoginRedirectInterceptor(),
            requestError: new MyInterceptor() // 这里的key是requestError,是因为我自定义的是错误拦截器,大家根据自己自定的拦截器选择对应的key
        }
    }
})

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

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

Like (0)
oinone's avataroinone
Previous 2023年6月20日 pm4:07
Next 2023年11月2日 pm1:58

相关推荐

  • 如何在自有前端工程中使用gql请求?

    场景 客户在个性化程度比较高的h5工程中想使用平台的服务端能力,这个时候需要调用后端的gql请求,此时需要引入平台的请求库依赖 npm的package.json中加入依赖 此文档以4.x举例,使用其他版本的请自行修改版本号 "dependencies": { "@kunlun/request": "~4.3.0", "@kunlun/state": "~4.3.0" } 使用示例 import { HttpClient } from ‘@kunlun/request’ const http = HttpClient.getInstance() http.setBaseURL(”) export const login = (data) => { const gqlBody = `mutation { pamirsUserTransientMutation { login(user: {login: “${data.username}”, password: “${data.password}”}) { broken errorMsg errorCode errorField } } }` return http.mutate(‘user’, gqlBody) } 注意事项 开发环境记得配置oinone请求的路由转发规则,这里以vite.config.js举例 import { defineConfig } from ‘vite’ export default defineConfig({ server: { port: 8088, open: true, proxy: { ‘/pamirs’: { changeOrigin: true, // 服务端请求地址 target: ‘http://127.0.0.1:8091’ } } } })

    2023年11月1日
    1.7K00
  • 表格新增空行或者按照数据如何复制行

    场景 描述 新增按钮点击后表格出现空行,不带业务数据,需要有行内编辑 如何实现 第一步 在layout目录下新增copyTable组件,组件代码如下 import { BaseElementWidget, SPI, TableWidget, Widget } from '@kunlun/dependencies'; import { OioNotification } from '@kunlun/vue-ui-antd'; @SPI.ClassFactory(BaseElementWidget.Token({ widget: 'copy-table-row' })) export class CopyTableWidget extends TableWidget { @Widget.BehaviorSubContext(Symbol("$$TABLE_COPY_CB"), {}) private tableCopySub; @Widget.BehaviorSubContext(Symbol("$$TABLE_DELETE_CB")) private tableDeleteSub; @Widget.Reactive() @Widget.Provide() protected get editorMode(): any { return 'manual' } public async copyRowData(row,currentRow) { // 获取vxetable 实例 const tableRef = this.getTableInstance()!.getOrigin(); if (tableRef) { // 有复制未保存数据,如何处理? const insertData = tableRef.getInsertRecords(); if(insertData.length > 0){ OioNotification.warning("警告","请检查未保存数据!") return; } const { row: newRow } = await tableRef.insertAt(row,currentRow) // 插入一条数据并触发校验, 其中字段名称可以替换 await tableRef.setEditCell(newRow, 'city') } } public async deleteRowData(row) { // 获取vxetable 实例 const tableRef = this.getTableInstance()!.getOrigin(); if (tableRef) { // 有复制未保存数据,如何处理? console.log(row, 'remove row') tableRef.remove(row) // 插入一条数据并触发校验 } } async mounted() { super.mounted(); this.tableCopySub.subject.next({copyCb: (row,currentRow) => this.copyRowData(row,currentRow)}) this.tableDeleteSub.subject.next({deleteCb: (row) => this.deleteRowData(row)}) } } 第二步 在action目录下覆盖新增按钮或者复制行按钮;代码如下 import {ActionWidget, ClickResult, ReturnPromise, SPI, Widget} from "@kunlun/dependencies"; @SPI.ClassFactory( ActionWidget.Token({ model: 'resource.k2.Model0000001211', // 替换对应模型 name: 'uiView57c25f66fac9439089d590a4ac47f027' // 替换对应action的name }) ) export class CopyRow extends ActionWidget{ @Widget.BehaviorSubContext(Symbol("$$TABLE_COPY_CB")) private tableCopySub; private tableCopyCb; @Widget.Method() public clickAction(): ReturnPromise<ClickResult> { // 按照某一条数据复制行, 按钮在行内 // let data = JSON.parse(JSON.stringify(this.activeRecords?.[0])); // 复制行删除id // if(data) { // delete…

    2024年7月15日
    3.7K00
  • 列表视图、卡片视图切换

    在日常项目开发中,我们可能会遇到当前视图是个表格,通过某个操作按钮将它变成卡片的形式. 这篇文章将带大家实现这种功能。通过上面两张图片可以看到出来不管是表格还是卡片,它都在当前的视图里面,所以我们需要一个视图容器来包裹表格跟卡片,并且表格可以使用平台默认的表格渲染,我们只需要自定义卡片即可。 我们用资源模块下面的国家菜单来实现这么一个功能这是对应的URL: http://localhost:8080/page;module=resource;viewType=TABLE;model=resource.ResourceCountry;action=resource%23%E5%9B%BD%E5%AE%B6;scene=resource%23%E5%9B%BD%E5%AE%B6;target=OPEN_WINDOW;menu=%7B%22selectedKeys%22:%5B%22%E5%9B%BD%E5%AE%B6%22%5D,%22openKeys%22:%5B%22%E5%9C%B0%E5%9D%80%E5%BA%93%22,%22%E5%9C%B0%E5%8C%BA%22%5D%7D 源码下载 views 创建外层的视图容器 刚刚我们讲过,不管是表格还是卡片,它都在当前的视图里面,所以我们需要写一个视图容器来包裹它们,并且对应的容器里面允许拆入表格跟卡片,我们先创建TableWithCardViewWidget.ts // TableWithCardViewWidget.ts import { BaseElementWidget, SPI, Widget } from '@kunlun/dependencies'; import TableWithCardView from './TableWithCardView.vue'; enum ListViewType { TABLE = 'table', CARD = 'card' } @SPI.ClassFactory( BaseElementWidget.Token({ widget: 'TableWithCardViewWidget' }) ) export class TableWithCardViewWidget extends BaseElementWidget { @Widget.Reactive() private listViewType: ListViewType = ListViewType.TABLE; // 当前视图展示的类型,是展示卡片还是表格 public initialize(props) { if (!props.slotNames) { props.slotNames = ['tableWidget', 'cardWidget']; } super.initialize(props); this.setComponent(TableWithCardView); return this; } } 在TableWithCardViewWidget中的initialize函数中,我们定义了两个插槽: tableWidget、cardWidget,所以需要在对应的vue文件里面里接收这两个插槽 <template> <div class="list-view-wrapper"> <!– 表格插槽 –> <div style="height: 100%" v-if="listViewType === 'table'"> <slot name="tableWidget" /> </div> <!– 卡片插槽 –> <div v-if="listViewType === 'card'"> <slot name="cardWidget"></slot> </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ props: ['listViewType', 'onChangeViewType'], inheritAttrs: false, setup(props, context) { const onChangeViewType = (listViewType) => { props.onChangeViewType(listViewType); }; } }); </script> 这样一来,我们就定义好了视图容器,接下来就是通过自定义layout的方式注册该容器 layout注册 import { registerLayout, ViewType } from '@kunlun/dependencies'; registerLayout( `<view type="TABLE"> <pack widget="group"> <view type="SEARCH"> <element widget="search" cols="4" slot="search"/> </view> </pack> <pack widget="group" slot="tableGroup" style="position: relative"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="TableWithCardViewWidget"> <template slot="tableWidget"> <element widget="table" slot="table" datasource-provider="true"> <element widget="expandColumn" slot="expandRow" /> <xslot name="fields" />…

    2024年10月16日
    3.2K01
  • 前端6.2.x升级指南

    升级背景 从 6.2.x 版本开始,平台底层核心代码已全面开源(设计器相关代码除外),本次升级涉及包名变更和配置调整,以下是详细的升级步骤 1. 更新 .npmrc 配置 修改当前项目根目录 .npmrc 文件,内容如下: registry=https://registry.npmmirror.com/ @oinone:registry=http://nexus.shushi.pro/repository/kunlun/ @kunlun:registry=http://nexus.shushi.pro/repository/kunlun/ shamefully-hoist=true legacy-peer-deps=true link-workspace-packages = true prefer-workspace-packages = true recursive-install = true lockfile=true 2. 包名变更 以前的包是 @kunlun/xxxx,现在的包名是@oinone/kunlun开头,所以需要全部替换修改。 旧包名 新包名 @kunlun/dependencies @oinone/kunlun-dependencies @kunlun/vue-ui-antd @oinone/kunlun-vue-ui-antd 3. 升级依赖版本 修改所有 package.json 中更新所有平台相关依赖: – "@kunlun/dependencies": "~5.7.0" + "@oinone/kunlun-dependencies": "~6.2.0" boot工程的package.json新增devDependencies依赖 "devDependencies": { "@types/lodash": "4.14.182", "@types/lodash-es": "4.17.6", ….. } 4. 更新代码引用 全局搜索并替换代码中的所有 @kunlun/ 为 @oinone/kunlun- 完整的 main.ts import 'ant-design-vue/dist/antd.min.css'; import 'element-plus/dist/index.css'; import '@oinone/kunlun-vue-ui-antd/dist/oinone-kunlun-vue-ui-antd.css'; import '@oinone/kunlun-vue-ui-el/dist/oinone-kunlun-vue-ui-el.css'; import '@oinone/kunlun-designer-common/dist/oinone-kunlun-designer-common.css'; import '@oinone/kunlun-model-designer/dist/oinone-kunlun-model-designer.css'; import '@oinone/kunlun-workflow-designer/dist/oinone-kunlun-workflow-designer.css'; import '@oinone/kunlun-workflow/dist/oinone-kunlun-workflow.css'; import '@oinone/kunlun-data-designer/dist/oinone-kunlun-data-designer.css'; import '@oinone/kunlun-microflow-designer/dist/oinone-kunlun-microflow-designer.css'; import 'reflect-metadata'; import ElementPlus from 'element-plus'; import { App } from 'vue'; import { VueOioProvider, RuntimeContextManager } from '@oinone/kunlun-dependencies'; // 设计器 import '@oinone/kunlun-ui-designer-dependencies'; import '@oinone/kunlun-print-designer-dependencies'; import '@oinone/kunlun-workflow'; import '@oinone/kunlun-workflow-designer'; import '@oinone/kunlun-model-designer'; import '@oinone/kunlun-data-designer'; import '@oinone/kunlun-data-designer-open-pc'; import '@oinone/kunlun-eip-dependencies'; import '@oinone/kunlun-ai-dependencies'; import '@oinone/kunlun-microflow-designer'; import '@oinone/kunlun-designer-common-ee'; // 下面三个依赖是当前工程的包,请根据实际场景修改 import '@ss/oinone'; import '@ss/admin-widget'; import '@ss/project'; VueOioProvider( { browser: { title: 'Oinone – 构你想象!', favicon: 'https://pamirs.oss-cn-hangzhou.aliyuncs.com/pamirs/image/default_favicon.ico' } }, [ () => { /// 获取当前vue实例 const app = RuntimeContextManager.createOrReplace().frameworkInstance as App; } ] ); 当配置全部修改完成后,重写安装依赖 # 清理旧依赖 pnpm clean # 安装新依赖 pnpm install

    2025年6月17日
    88000
  • 【界面设计器】树形表格

    阅读之前 你应该: 熟悉模型的增删改查相关内容。【界面设计器】模型增删改查基础

    2024年4月19日
    1.5K00

Leave a Reply

Please Login to Comment