用iframe实现单个系统页面在多个系统中复用

背景:

因为领导决策,将 A 系统复制出一份代码改头换面变成 B 系统,并要求在 B 系统开发一个模块给供应商使用,开发完了,好的,现在领导又想要把这个页面搬到 A 系统给公司内部工程师使用了。。。。。。

矛盾点:

  1. 如果直接将文件复制过来用,以后每次更新都要两边改,维护特别困难;

  2. 如果把这个页面单独封装成一个大的组件去复用,工作量更加是无敌庞大。

遂:直接 iframe 嵌入

这样做可以实现只在一个地方维护该模块,大大减少工作量。

前提是:

  1. 已经再三确认,以后 A、B 系统中的这个页面是一致的,不会进行差异化定制;

  2. 各项细小的操作权限和 B 系统中的保持一致,直接在后台中对B系统的权限规则进行勾选

问题:

  1. 测试服和正式服的页面地址不同;

  2. 页面存在顶部和侧面菜单栏

解决:

  1. 在 A 系统中新增一个路由,指向一个放着 iframe 的Vue文件;
html 复制代码
<template>
  <div class="chat-container">
    <iframe
      :src="src"
      frameborder="0"
      width="100%"
      height="100%"
      id="myiframe"
      sandbox="allow-scripts allow-same-origin allow-forms"
      @load="handleIframeLoad"
    />
  </div>
</template>

<script>
export default {
  name: 'FQATest',
  components: {},
  props: {},
  data() {
    return {}
  },
  computed: {
    src() {
      // 尝试添加参数来跳过有问题的认证流程
      const baseUrl = process.env.NODE_ENV === 'production'
        ? '正式服页面地址'
        : '测试服页面地址'

      return `${baseUrl}?skipAuth=true&bypassTokenCheck=true`
    }
  },
  created() {},
  mounted() {
  },
  methods: {
    handleIframeLoad() {
      // 添加错误捕获
      const iframe = document.getElementById('myiframe')
      iframe.contentWindow.onerror = function(msg, url, line) {
        console.log('iframe错误:', msg, url, line)
        return true // 阻止错误冒泡
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.chat-container {
  height: calc(100vh - 85px);
}
</style>
  1. 在 B 系统中的 Layout 布局组件中进行环境判断,如果是在 iframe 嵌套环境下,那么只显示主内容,否则正常显示(有顶部和侧边菜单栏)。

核心代码:

html 复制代码
<template>
<div>

  <!-- 系统内部 -->
  <div :class="classObj" class="app-wrapper" v-if="!iframeEmbedded">
    <div
      v-if="device === 'mobile' && sidebar.opened"
      class="drawer-bg"
      @click="handleClickOutside"
    />
    <sidebar class="sidebar-container" />
    <div class="main-container">
      <div v-if="showHeader" :class="{ 'fixed-header': fixedHeader }">
        <navbar />
        <tags-view v-if="needTagsView" />
      </div>
      <app-main />
    </div>
  </div>

  <!-- 被嵌入iframe -->
  <div v-else>
    <app-main />
  </div>
</div>
</template>

逻辑判断:

javascript 复制代码
  data() {
    return {
      iframeEmbedded: false // 是否被iframe嵌入
    }
  },
  mounted() {
    this.checkIframeEmbedded()
  },
  methods: {
    // 检测是否被iframe嵌入
    checkIframeEmbedded() {
      try {
        // 方法1: 检查window.self和window.top是否相同
        if (window.self !== window.top) {
          this.iframeEmbedded = true
          console.log('✅ 检测到iframe嵌入: window.self !== window.top',this.iframeEmbedded)
          return true
        }

        // 方法2: 检查window.frameElement是否存在
        if (window.frameElement) {
          this.iframeEmbedded = true
          console.log('✅ 检测到iframe嵌入: window.frameElement存在',this.iframeEmbedded)
          return true
        }

        // 方法3: 检查URL参数中是否包含iframe标识
        const urlParams = new URLSearchParams(window.location.search)
        if (urlParams.has('iframe') || urlParams.has('embedded')) {
          this.iframeEmbedded = true
          console.log('✅ 检测到iframe嵌入: URL参数包含iframe标识',this.iframeEmbedded)
          return true
        }

        // 方法4: 检查referrer是否来自同一域名(可选)
        if (document.referrer && document.referrer !== '' &&
            document.referrer !== window.location.href) {
          // 如果referrer存在且不是当前页面,可能是被嵌入
          const currentDomain = window.location.hostname
          const referrerDomain = new URL(document.referrer).hostname
          if (referrerDomain !== currentDomain) {
            this.iframeEmbedded = true
            console.log('✅ 检测到iframe嵌入: referrer来自不同域名',this.iframeEmbedded)
            return true
          }
        }
        this.iframeEmbedded = false
        console.log('❌ 未检测到iframe嵌入',this.iframeEmbedded)
        return false
      } catch (error) {
        // 如果出现跨域错误,说明被iframe嵌入
        console.log('iframe检测出现错误,可能被嵌入:', error)
        this.iframeEmbedded = true
        return true
      }
    },
  }

这样就大功告成啦!以后只需要在 B 系统中维护该模块即可,A 系统这边也会同步更新。

相关推荐
zhangrelay10 小时前
三分钟云课实践速通--数字电子技术-数电--SimulIDE
linux·笔记·学习·ubuntu·simulide
泽克10 小时前
3.5 电梯工程安装技术
笔记
玛卡巴卡ldf10 小时前
【Springboot升级AI】(大模型部署)LangChain4j、会话记忆、隔离消失持久化问题、ollama、RAG知识库、Tools工具
java·开发语言·人工智能·spring boot·后端·springboot
zmzb010310 小时前
C++课后习题训练记录Day120
开发语言·c++
涵涵(互关)10 小时前
GoView各项目文件中的相关语法3
前端·vue.js·typescript
李白的天不白10 小时前
vs code -- uniapp gets
前端
吴声子夜歌10 小时前
Vue3——网络框架Axios的应用
javascript·vue3·axios
05候补工程师10 小时前
【408计网笔记】传输层与应用层高频考点:TCP/UDP特性、端口映射与交互逻辑
网络·经验分享·笔记·网络协议·tcp/ip·考研·udp
tjl521314_2110 小时前
01C++ 类定义与访问控制(封装)
java·开发语言·c++
lifewange10 小时前
CNode API v1 完整接口文档(JSON 规范整理)
java·前端·json