首页 前端知识 vue 文本中的\n 、<br>换行显示

vue 文本中的\n 、<br>换行显示

2024-06-06 10:06:38 前端知识 前端哥 47 2 我要收藏

一、背景: 后端接口返回数据以\n 作为换行符,前端显示时候需要换行显示;

demo:

 <p style="white-space: pre-wrap;">{{ info }}</p>
 data() {
   return {
     info: '1、优化图片\n  2、   优化时间\n'
   }
 },

项目上:

效果:

接口数据直接获取:

<template>
    <div style="white-space: pre-wrap;">{{logDataInfo}}
        </div>
      </div>
</tempalte>

<script lang="ts">
methods: {

loadMore(){
try {
        const response = await API.Defect.logDetailsData({
          page: this.currentPage,
          pageSize: this.pageSize,
          fileId: id
        })
        this.logTotal = response.data.total
        const data = response.data.list
        if (data) {
          this.logDataInfo = data
         
        } 
      } catch (error) {
        warn(error, true)
      }

}

}

</script>

注意: style中white-sapce: pre-wrap; 一定要添加;

white-space学习

接口数据res.data.list :

"<template>\n  <div class=\"graph-container\">\n    <PageHeader title=\"覆盖率图谱\">\n      <template slot=\"button-items\">\n        <SearchInputVue :keyword.sync=\"keyword\" @trigger-event=\"getInitGraphData(1)\" placeholder=\"输入类名过滤\" />\n      </template>\n    </PageHeader>\n    <div id=\"relationGraphDiv\" style=\"height: calc(100vh - 160px)\">\n      <RelationGraph ref=\"seeksRelationGraph\" :options=\"graphOptions\">\n        <template slot=\"node\" slot-scope=\"{ node }\">\n          <div :class=\"`node-container node-type-${node.data.category}`\" @click=\"nodeClick(node.data)\">\n            <div v-if=\"node.data.category !== 0\" class=\"node-title\">\n              <div v-if=\"node.data.category === 2\" class=\"node-title-top\">\n                {{ node.data.name }}\n                <span v-if=\"node.data.path\" :title=\"node.data.path\" style=\"font-size: 12px\">({{ node.data.path }})</span>\n              </div>\n              <div v-if=\"node.data.category !== 2\">{{ node.data.name }}</div>\n              <div v-if=\"node.data.category === 2\" :title=\"node.data.params\" style=\"font-size: 12px\">{{ node.data.params }}</div>\n            </div>\n            <div v-if=\"node.data.category !== 0\" class=\"node-info\">\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">行覆盖率</div>\n                <div :class=\"`level-${node.data.linesLevel}`\">{{ node.data.lines }}%</div>\n              </div>\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">分支覆盖率</div>\n                <div :class=\"`level-${node.data.branchesLevel}`\">{{ node.data.branches }}%</div>\n              </div>\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">函数覆盖率</div>\n                <div :class=\"`level-${node.data.functionsLevel}`\">{{ node.data.functions }}%</div>\n              </div>\n            </div>\n            <div v-if=\"node.data.category === 0\" class=\"node-begin\">{{ node.data.name }}</div>\n          </div>\n        </template>\n      </RelationGraph>\n    </div>\n  </div>\n</template>\n<script lang=\"ts\">\nimport Vue from 'vue'\nimport { mapGetters } from 'vuex'\nimport RelationGraph from 'relation-graph'\nimport { Loading } from 'element-ui'\n\nimport API from '@/api'\nimport { warn } from '@/utils/common'\n// import AnbanButtonVue from '@/components/Button/AnbanButton.vue'\nimport SearchInputVue from '@/components/Input/SearchInput.vue'\n\nimport PageHeader from '@/components/pageHeader/index.vue'\n\nexport default Vue.extend({\n  name: 'CoverageGraph',\n  components: {\n    PageHeader,\n    SearchInputVue,\n    RelationGraph\n  },\n  data() {\n    return {\n      rawData: {\n        nodes: [],\n        links: []\n      },\n      renderData: {\n        nodes: [] as any[],\n        links: [] as { from: string; to: string; text?: string }[]\n      },\n      unLoadExpandNodes: [] as string[],\n      height: document.body.clientHeight - 124,\n      graphOptions: {\n        layouts: [\n          {\n            label: '布局',\n            layoutName: 'tree',\n            layoutClassName: 'seeks-layout-center',\n            from: 'left',\n            defaultNodeShape: 2,\n            distance_coefficient: 1,\n            defaultLineShape: 4,\n            defaultNodeBorderWidth: 0,\n            defaultLineColor: '#cccccc',\n            defaultNodeColor: '#43a2f1',\n            min_per_width: '400',\n            min_per_height: '300'\n          }\n        ],\n        defaultExpandHolderPosition: 'right',\n        zoomToFitWhenRefresh: false,\n        moveToCenterWhenRefresh: true\n      },\n      keyword: ''\n    }\n  },\n  computed: {\n    ...mapGetters(['currentModuleInfo', 'currentInstanceInfo'])\n  },\n  mounted() {\n    if (this.$route.query.path) {\n      this.keyword = decodeURIComponent(this.$route.query.path as string)\n    }\n    this.getInitGraphData(0)\n  },\n  methods: {\n    /**\n     * 获得init数据(api)\n     */\n    async getInitGraphData(type: number) {\n      if (type === 1 && !this.keyword.trim()) {\n        this.renderData.nodes = this.rawData.nodes\n        this.renderData.links = this.rawData.links\n        this.renderGraphData()\n        return\n      }\n      const loadingInstance = Loading.service({\n        target: '#relationGraphDiv',\n        text: '数据加载中'\n      })\n      try {\n        const { data } = await API.Instance.getCoverageGraphRootData({\n          instanceId: this.currentInstanceInfo.id,\n          name: this.keyword,\n          id: ''\n        })\n        setTimeout(() => loadingInstance.close(), 500)\n        if (!data.length) {\n          if (type === 0) {\n            this.$message.warning('暂无覆盖率图谱数据')\n          } else {\n            this.$message.warning(`暂无 ${this.keyword} 相关类名`)\n          }\n          return\n        }\n        const initNode = {\n          id: 'initId',\n          data: {\n            name: this.currentModuleInfo.projectName,\n            category: 0\n          }\n        }\n        this.mergeOriginalData(type, data, initNode)\n        this.renderGraphData()\n      } catch (error) {\n        warn(error, true)\n        loadingInstance.close()\n      }\n    },\n    mergeOriginalData(type: number, data: any[], rootNode: any) {\n      const links = []\n      const unLoadExpandNodes: string[] = []\n      const apiNodes = data.reduce((merge, item) => {\n        const parentId = `id_${item.name}_${new Date().getTime()}`\n        const parentNode = {\n          id: parentId,\n          data: {\n            id: parentId,\n            name: item.name,\n            category: 1,\n            branches: item.branches === 'NaN' || !item.branches ? 0 : item.branches.toFixed(2),\n            branchesLevel: this.coverageLevel(item.branches),\n            functions: item.functions === 'NaN' || !item.functions ? 0 : item.functions.toFixed(2),\n            functionsLevel: this.coverageLevel(item.functions),\n            lines: item.lines === 'NaN' || !item.lines ? 0 : item.lines.toFixed(2),\n            linesLevel: this.coverageLevel(item.lines)\n          }\n        }\n        const parentLink = {\n          from: rootNode.id,\n          to: parentId,\n          text: rootNode.id === 'initId' ? `exec: ${item.execute_count || 0}` : '',\n          useTextPath: true\n        }\n        merge.push(parentNode)\n        links.push(parentLink)\n        if (item.methods && item.methods.length) {\n          item.methods.forEach(method => {\n            const childId = `id_${method.name}_${method.path}_${new Date().getTime()}`\n            unLoadExpandNodes.push(childId)\n            const child = {\n              id: childId,\n              data: {\n                id: childId,\n                className: item.name,\n                name: method.name,\n                path: method.path,\n                category: 2,\n                params: method.params,\n                branches: method.branches === 'NaN' || !method.branches ? 0 : method.branches.toFixed(2),\n                branchesLevel: this.coverageLevel(method.branches),\n                functions: method.functions === 'NaN' || !method.functions ? 0 : method.functions.toFixed(2),\n                functionsLevel: this.coverageLevel(method.functions),\n                lines: method.lines === 'NaN' || !method.lines ? 0 : method.lines.toFixed(2),\n                linesLevel: this.coverageLevel(method.lines)\n              }\n            }\n            const link = {\n              from: parentId,\n              to: childId\n              // text: `exec: ${method.execute_count || 0}`,\n              // useTextPath: true\n            }\n            merge.push(child)\n            links.push(link)\n          })\n        }\n        return merge\n      }, [])\n      const nodes = type === 0 || type === 1 ? [rootNode, ...apiNodes] : apiNodes\n      if (type === 0) {\n        // 初始化\n        this.rawData.nodes = nodes\n        this.rawData.links = links\n        this.renderData.nodes = nodes\n        this.renderData.links = links\n        this.unLoadExpandNodes = unLoadExpandNodes\n      } else if (type === 1) {\n        // 过滤\n        this.renderData.nodes = nodes\n        this.renderData.links = links\n        this.unLoadExpandNodes = unLoadExpandNodes\n      } else if (type === 2) {\n        // 增加\n        this.rawData.nodes = [...this.rawData.nodes, ...nodes]\n        this.rawData.links = [...this.rawData.links, ...links]\n        this.unLoadExpandNodes = [...this.unLoadExpandNodes, ...unLoadExpandNodes]\n        this.addGraphData(nodes, links)\n      }\n    },\n    coverageLevel(rate: number) {\n      if (typeof rate !== 'number') return 0\n      return rate === 0 ? 0 : rate < 60 ? 1 : rate < 90 ? 2 : 3\n    },\n    renderGraphData() {\n      const __graph_json_data = {\n        rootId: 'initId',\n        nodes: this.renderData.nodes,\n        lines: this.renderData.links\n      }\n      console.log(__graph_json_data)\n      this.$refs.seeksRelationGraph.setJsonData(__graph_json_data)\n      this.$refs.seeksRelationGraph.refresh()\n    },\n    addGraphData(nodes, links) {\n      const __graph_json_data = {\n        rootId: 'initId',\n        nodes,\n        links\n      }\n      this.$refs.seeksRelationGraph.appendJsonData(__graph_json_data)\n    },\n    async nodeClick(nodeData: any) {\n      console.log(nodeData)\n      if (this.unLoadExpandNodes.includes(nodeData.id)) {\n        // 未加载过子路径\n        await this.getExpandData(nodeData.id, nodeData.className, nodeData.name, nodeData.params)\n      }\n    },\n    /**\n     * 增加子节点\n     */\n    async getExpandData(id: string, className: string, methodName: string, params: any) {\n      if (!this.unLoadExpandNodes.includes(id)) return\n      const loadingInstance = Loading.service({\n        target: '#relationGraphDiv',\n        text: '数据加载中'\n      })\n      try {\n        const { data } = await API.Instance.getCoverageGrapChildhData({\n          instanceId: this.currentInstanceInfo.id,\n          className,\n          methodName,\n          params: encodeURIComponent(params)\n        })\n        setTimeout(() => loadingInstance.close(), 500)\n        if (data.length) {\n          this.mergeOriginalData(2, data, { id })\n        }\n        this.unLoadExpandNodes = this.unLoadExpandNodes.filter(nodeId => nodeId !== id)\n      } catch (error) {\n        warn(error, true)\n        loadingInstance.close()\n      }\n    }\n  }\n})\n</script>\n<style lang=\"stylus\" Scope>\n.node-container {\n  width: 240px;\n  height: 105px;\n  box-sizing: border-box;\n  background: #3F51B5;\n  border-radius: 4px;\n  background-color: #484750;\n  overflow: hidden;\n  &.node-type-0 {\n    width: auto;\n    padding: 0 32px;\n    line-height: 105px;\n    font-size: 20px;\n    font-weight: 700;\n  }\n  &.node-type-1 {\n    .node-title {\n      height: 57px;\n      background: #387dff;\n      color: #fff;\n      word-break: break-all;\n      white-space: unset;\n      line-height: 18px;\n    }\n  }\n  .node-title-top {\n    padding-bottom: 4px;\n    border-bottom: 1px solid #484750;\n    margin-bottom: 4px;\n  }\n  .node-title {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    background-color: #aabee3;\n    padding: 8px 12px;\n    color: #232529;\n    text-align: left;\n  }\n  .node-info {\n    display: flex;\n    font-size: 12px;\n    justify-content: space-between;\n    padding: 8px;\n    .node-info-name {\n      margin-bottom: 4px;\n    }\n    .level-1 {\n      color: #FF4455;\n    }\n    .level-2 {\n      color: #FE7C4B;\n    }\n    .level-3 {\n      color: #49C721;\n    }\n    .level-0 {\n      color: #aabee3;\n    }\n  }\n}\n</style>\n<style lang=\"stylus\">\n.c-current-zoom {\n  color: #999999 !important;\n}\n.relation-graph .rel-map {\n  background-color: #1a1919 !important;\n}\n.relation-graph .rel-toolbar .c-mb-button:hover {\n  background-color: rgba(153, 153, 153, 0.5) !important;\n}\n.relation-graph .rel-node-checked {\n  width: 100% !important;\n  box-shadow: 0 0px 5px 2px #2196F3 !important;\n}\n.el-loading-mask {\n  background-color: rgba(34, 34, 34, 0.8) !important;\n}\n</style>\n<template>\n  <div class=\"graph-container\">\n    <PageHeader title=\"覆盖率图谱\">\n      <template slot=\"button-items\">\n        <SearchInputVue :keyword.sync=\"keyword\" @trigger-event=\"getInitGraphData(1)\" placeholder=\"输入类名过滤\" />\n      </template>\n    </PageHeader>\n    <div id=\"relationGraphDiv\" style=\"height: calc(100vh - 160px)\">\n      <RelationGraph ref=\"seeksRelationGraph\" :options=\"graphOptions\">\n        <template slot=\"node\" slot-scope=\"{ node }\">\n          <div :class=\"`node-container node-type-${node.data.category}`\" @click=\"nodeClick(node.data)\">\n            <div v-if=\"node.data.category !== 0\" class=\"node-title\">\n              <div v-if=\"node.data.category === 2\" class=\"node-title-top\">\n                {{ node.data.name }}\n                <span v-if=\"node.data.path\" :title=\"node.data.path\" style=\"font-size: 12px\">({{ node.data.path }})</span>\n              </div>\n              <div v-if=\"node.data.category !== 2\">{{ node.data.name }}</div>\n              <div v-if=\"node.data.category === 2\" :title=\"node.data.params\" style=\"font-size: 12px\">{{ node.data.params }}</div>\n            </div>\n            <div v-if=\"node.data.category !== 0\" class=\"node-info\">\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">行覆盖率</div>\n                <div :class=\"`level-${node.data.linesLevel}`\">{{ node.data.lines }}%</div>\n              </div>\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">分支覆盖率</div>\n                <div :class=\"`level-${node.data.branchesLevel}`\">{{ node.data.branches }}%</div>\n              </div>\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">函数覆盖率</div>\n                <div :class=\"`level-${node.data.functionsLevel}`\">{{ node.data.functions }}%</div>\n              </div>\n            </div>\n            <div v-if=\"node.data.category === 0\" class=\"node-begin\">{{ node.data.name }}</div>\n          </div>\n        </template>\n      </RelationGraph>\n    </div>\n  </div>\n</template>\n<script lang=\"ts\">\nimport Vue from 'vue'\nimport { mapGetters } from 'vuex'\nimport RelationGraph from 'relation-graph'\nimport { Loading } from 'element-ui'\n\nimport API from '@/api'\nimport { warn } from '@/utils/common'\n// import AnbanButtonVue from '@/components/Button/AnbanButton.vue'\nimport SearchInputVue from '@/components/Input/SearchInput.vue'\n\nimport PageHeader from '@/components/pageHeader/index.vue'\n\nexport default Vue.extend({\n  name: 'CoverageGraph',\n  components: {\n    PageHeader,\n    SearchInputVue,\n    RelationGraph\n  },\n  data() {\n    return {\n      rawData: {\n        nodes: [],\n        links: []\n      },\n      renderData: {\n        nodes: [] as any[],\n        links: [] as { from: string; to: string; text?: string }[]\n      },\n      unLoadExpandNodes: [] as string[],\n      height: document.body.clientHeight - 124,\n      graphOptions: {\n        layouts: [\n          {\n            label: '布局',\n            layoutName: 'tree',\n            layoutClassName: 'seeks-layout-center',\n            from: 'left',\n            defaultNodeShape: 2,\n            distance_coefficient: 1,\n            defaultLineShape: 4,\n            defaultNodeBorderWidth: 0,\n            defaultLineColor: '#cccccc',\n            defaultNodeColor: '#43a2f1',\n            min_per_width: '400',\n            min_per_height: '300'\n          }\n        ],\n        defaultExpandHolderPosition: 'right',\n        zoomToFitWhenRefresh: false,\n        moveToCenterWhenRefresh: true\n      },\n      keyword: ''\n    }\n  },\n  computed: {\n    ...mapGetters(['currentModuleInfo', 'currentInstanceInfo'])\n  },\n  mounted() {\n    if (this.$route.query.path) {\n      this.keyword = decodeURIComponent(this.$route.query.path as string)\n    }\n    this.getInitGraphData(0)\n  },\n  methods: {\n    /**\n     * 获得init数据(api)\n     */\n    async getInitGraphData(type: number) {\n      if (type === 1 && !this.keyword.trim()) {\n        this.renderData.nodes = this.rawData.nodes\n        this.renderData.links = this.rawData.links\n        this.renderGraphData()\n        return\n      }\n      const loadingInstance = Loading.service({\n        target: '#relationGraphDiv',\n        text: '数据加载中'\n      })\n      try {\n        const { data } = await API.Instance.getCoverageGraphRootData({\n          instanceId: this.currentInstanceInfo.id,\n          name: this.keyword,\n          id: ''\n        })\n        setTimeout(() => loadingInstance.close(), 500)\n        if (!data.length) {\n          if (type === 0) {\n            this.$message.warning('暂无覆盖率图谱数据')\n          } else {\n            this.$message.warning(`暂无 ${this.keyword} 相关类名`)\n          }\n          return\n        }\n        const initNode = {\n          id: 'initId',\n          data: {\n            name: this.currentModuleInfo.projectName,\n            category: 0\n          }\n        }\n        this.mergeOriginalData(type, data, initNode)\n        this.renderGraphData()\n      } catch (error) {\n        warn(error, true)\n        loadingInstance.close()\n      }\n    },\n    mergeOriginalData(type: number, data: any[], rootNode: any) {\n      const links = []\n      const unLoadExpandNodes: string[] = []\n      const apiNodes = data.reduce((merge, item) => {\n        const parentId = `id_${item.name}_${new Date().getTime()}`\n        const parentNode = {\n          id: parentId,\n          data: {\n            id: parentId,\n            name: item.name,\n            category: 1,\n            branches: item.branches === 'NaN' || !item.branches ? 0 : item.branches.toFixed(2),\n            branchesLevel: this.coverageLevel(item.branches),\n            functions: item.functions === 'NaN' || !item.functions ? 0 : item.functions.toFixed(2),\n            functionsLevel: this.coverageLevel(item.functions),\n            lines: item.lines === 'NaN' || !item.lines ? 0 : item.lines.toFixed(2),\n            linesLevel: this.coverageLevel(item.lines)\n          }\n        }\n        const parentLink = {\n          from: rootNode.id,\n          to: parentId,\n          text: rootNode.id === 'initId' ? `exec: ${item.execute_count || 0}` : '',\n          useTextPath: true\n        }\n        merge.push(parentNode)\n        links.push(parentLink)\n        if (item.methods && item.methods.length) {\n          item.methods.forEach(method => {\n            const childId = `id_${method.name}_${method.path}_${new Date().getTime()}`\n            unLoadExpandNodes.push(childId)\n            const child = {\n              id: childId,\n              data: {\n                id: childId,\n                className: item.name,\n                name: method.name,\n                path: method.path,\n                category: 2,\n                params: method.params,\n                branches: method.branches === 'NaN' || !method.branches ? 0 : method.branches.toFixed(2),\n                branchesLevel: this.coverageLevel(method.branches),\n                functions: method.functions === 'NaN' || !method.functions ? 0 : method.functions.toFixed(2),\n                functionsLevel: this.coverageLevel(method.functions),\n                lines: method.lines === 'NaN' || !method.lines ? 0 : method.lines.toFixed(2),\n                linesLevel: this.coverageLevel(method.lines)\n              }\n            }\n            const link = {\n              from: parentId,\n              to: childId\n              // text: `exec: ${method.execute_count || 0}`,\n              // useTextPath: true\n            }\n            merge.push(child)\n            links.push(link)\n          })\n        }\n        return merge\n      }, [])\n      const nodes = type === 0 || type === 1 ? [rootNode, ...apiNodes] : apiNodes\n      if (type === 0) {\n        // 初始化\n        this.rawData.nodes = nodes\n        this.rawData.links = links\n        this.renderData.nodes = nodes\n        this.renderData.links = links\n        this.unLoadExpandNodes = unLoadExpandNodes\n      } else if (type === 1) {\n        // 过滤\n        this.renderData.nodes = nodes\n        this.renderData.links = links\n        this.unLoadExpandNodes = unLoadExpandNodes\n      } else if (type === 2) {\n        // 增加\n        this.rawData.nodes = [...this.rawData.nodes, ...nodes]\n        this.rawData.links = [...this.rawData.links, ...links]\n        this.unLoadExpandNodes = [...this.unLoadExpandNodes, ...unLoadExpandNodes]\n        this.addGraphData(nodes, links)\n      }\n    },\n    coverageLevel(rate: number) {\n      if (typeof rate !== 'number') return 0\n      return rate === 0 ? 0 : rate < 60 ? 1 : rate < 90 ? 2 : 3\n    },\n    renderGraphData() {\n      const __graph_json_data = {\n        rootId: 'initId',\n        nodes: this.renderData.nodes,\n        lines: this.renderData.links\n      }\n      console.log(__graph_json_data)\n      this.$refs.seeksRelationGraph.setJsonData(__graph_json_data)\n      this.$refs.seeksRelationGraph.refresh()\n    },\n    addGraphData(nodes, links) {\n      const __graph_json_data = {\n        rootId: 'initId',\n        nodes,\n        links\n      }\n      this.$refs.seeksRelationGraph.appendJsonData(__graph_json_data)\n    },\n    async nodeClick(nodeData: any) {\n      console.log(nodeData)\n      if (this.unLoadExpandNodes.includes(nodeData.id)) {\n        // 未加载过子路径\n        await this.getExpandData(nodeData.id, nodeData.className, nodeData.name, nodeData.params)\n      }\n    },\n    /**\n     * 增加子节点\n     */\n    async getExpandData(id: string, className: string, methodName: string, params: any) {\n      if (!this.unLoadExpandNodes.includes(id)) return\n      const loadingInstance = Loading.service({\n        target: '#relationGraphDiv',\n        text: '数据加载中'\n      })\n      try {\n        const { data } = await API.Instance.getCoverageGrapChildhData({\n          instanceId: this.currentInstanceInfo.id,\n          className,\n          methodName,\n          params: encodeURIComponent(params)\n        })\n        setTimeout(() => loadingInstance.close(), 500)\n        if (data.length) {\n          this.mergeOriginalData(2, data, { id })\n        }\n        this.unLoadExpandNodes = this.unLoadExpandNodes.filter(nodeId => nodeId !== id)\n      } catch (error) {\n        warn(error, true)\n        loadingInstance.close()\n      }\n    }\n  }\n})\n</script>\n<style lang=\"stylus\" Scope>\n.node-container {\n  width: 240px;\n  height: 105px;\n  box-sizing: border-box;\n  background: #3F51B5;\n  border-radius: 4px;\n  background-color: #484750;\n  overflow: hidden;\n  &.node-type-0 {\n    width: auto;\n    padding: 0 32px;\n    line-height: 105px;\n    font-size: 20px;\n    font-weight: 700;\n  }\n  &.node-type-1 {\n    .node-title {\n      height: 57px;\n      background: #387dff;\n      color: #fff;\n      word-break: break-all;\n      white-space: unset;\n      line-height: 18px;\n    }\n  }\n  .node-title-top {\n    padding-bottom: 4px;\n    border-bottom: 1px solid #484750;\n    margin-bottom: 4px;\n  }\n  .node-title {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    background-color: #aabee3;\n    padding: 8px 12px;\n    color: #232529;\n    text-align: left;\n  }\n  .node-info {\n    display: flex;\n    font-size: 12px;\n    justify-content: space-between;\n    padding: 8px;\n    .node-info-name {\n      margin-bottom: 4px;\n    }\n    .level-1 {\n      color: #FF4455;\n    }\n    .level-2 {\n      color: #FE7C4B;\n    }\n    .level-3 {\n      color: #49C721;\n    }\n    .level-0 {\n      color: #aabee3;\n    }\n  }\n}\n</style>\n<style lang=\"stylus\">\n.c-current-zoom {\n  color: #999999 !important;\n}\n.relation-graph .rel-map {\n  background-color: #1a1919 !important;\n}\n.relation-graph .rel-toolbar .c-mb-button:hover {\n  background-color: rgba(153, 153, 153, 0.5) !important;\n}\n.relation-graph .rel-node-checked {\n  width: 100% !important;\n  box-shadow: 0 0px 5px 2px #2196F3 !important;\n}\n.el-loading-mask {\n  background-color: rgba(34, 34, 34, 0.8) !important;\n}\n</style>\n<template>\n  <div class=\"graph-container\">\n    <PageHeader title=\"覆盖率图谱\">\n      <template slot=\"button-items\">\n        <SearchInputVue :keyword.sync=\"keyword\" @trigger-event=\"getInitGraphData(1)\" placeholder=\"输入类名过滤\" />\n      </template>\n    </PageHeader>\n    <div id=\"relationGraphDiv\" style=\"height: calc(100vh - 160px)\">\n      <RelationGraph ref=\"seeksRelationGraph\" :options=\"graphOptions\">\n        <template slot=\"node\" slot-scope=\"{ node }\">\n          <div :class=\"`node-container node-type-${node.data.category}`\" @click=\"nodeClick(node.data)\">\n            <div v-if=\"node.data.category !== 0\" class=\"node-title\">\n              <div v-if=\"node.data.category === 2\" class=\"node-title-top\">\n                {{ node.data.name }}\n                <span v-if=\"node.data.path\" :title=\"node.data.path\" style=\"font-size: 12px\">({{ node.data.path }})</span>\n              </div>\n              <div v-if=\"node.data.category !== 2\">{{ node.data.name }}</div>\n              <div v-if=\"node.data.category === 2\" :title=\"node.data.params\" style=\"font-size: 12px\">{{ node.data.params }}</div>\n            </div>\n            <div v-if=\"node.data.category !== 0\" class=\"node-info\">\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">行覆盖率</div>\n                <div :class=\"`level-${node.data.linesLevel}`\">{{ node.data.lines }}%</div>\n              </div>\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">分支覆盖率</div>\n                <div :class=\"`level-${node.data.branchesLevel}`\">{{ node.data.branches }}%</div>\n              </div>\n              <div class=\"node-info-item\">\n                <div class=\"node-info-name\">函数覆盖率</div>\n                <div :class=\"`level-${node.data.functionsLevel}`\">{{ node.data.functions }}%</div>\n              </div>\n            </div>\n            <div v-if=\"node.data.category === 0\" class=\"node-begin\">{{ node.data.name }}</div>\n          </div>\n        </template>\n      </RelationGraph>\n    </div>\n  </div>\n</template>\n<script lang=\"ts\">\nimport Vue from 'vue'\nimport { mapGetters } from 'vuex'\nimport RelationGraph from 'relation-graph'\nimport { Loading } from 'element-ui'\n\nimport API from '@/api'\nimport { warn } from '@/utils/common'\n// import AnbanButtonVue from '@/components/Button/AnbanButton.vue'\nimport SearchInputVue from '@/components/Input/SearchInput.vue'\n\nimport PageHeader from '@/components/pageHeader/index.vue'\n\nexport default Vue.extend({\n  name: 'CoverageGraph',\n  components: {\n    PageHeader,\n    SearchInputVue,\n    RelationGraph\n  },\n  data() {\n    return {\n      rawData: {\n        nodes: [],\n        links: []\n      },\n      renderData: {\n        nodes: [] as any[],\n        links: [] as { from: string; to: string; text?: string }[]\n      },\n      unLoadExpandNodes: [] as string[],\n      height: document.body.clientHeight - 124,\n      graphOptions: {\n        layouts: [\n          {\n            label: '布局',\n            layoutName: 'tree',\n            layoutClassName: 'seeks-layout-center',\n            from: 'left',\n            defaultNodeShape: 2,\n            distance_coefficient: 1,\n            defaultLineShape: 4,\n            defaultNodeBorderWidth: 0,\n            defaultLineColor: '#cccccc',\n            defaultNodeColor: '#43a2f1',\n            min_per_width: '400',\n            min_per_height: '300'\n          }\n        ],\n        defaultExpandHolderPosition: 'right',\n        zoomToFitWhenRefresh: false,\n        moveToCenterWhenRefresh: true\n      },\n      keyword: ''\n    }\n  },\n  computed: {\n    ...mapGetters(['currentModuleInfo', 'currentInstanceInfo'])\n  },\n  mounted() {\n    if (this.$route.query.path) {\n      this.keyword = decodeURIComponent(this.$route.query.path as string)\n    }\n    this.getInitGraphData(0)\n  },\n  methods: {\n    /**\n     * 获得init数据(api)\n     */\n    async getInitGraphData(type: number) {\n      if (type === 1 && !this.keyword.trim()) {\n        this.renderData.nodes = this.rawData.nodes\n        this.renderData.links = this.rawData.links\n        this.renderGraphData()\n        return\n      }\n      const loadingInstance = Loading.service({\n        target: '#relationGraphDiv',\n        text: '数据加载中'\n      })\n      try {\n        const { data } = await API.Instance.getCoverageGraphRootData({\n          instanceId: this.currentInstanceInfo.id,\n          name: this.keyword,\n          id: ''\n        })\n        setTimeout(() => loadingInstance.close(), 500)\n        if (!data.length) {\n          if (type === 0) {\n            this.$message.warning('暂无覆盖率图谱数据')\n          } else {\n            this.$message.warning(`暂无 ${this.keyword} 相关类名`)\n          }\n          "

二、br 换行(可以使用v-html)

demo:

<p v-html="info"></p>
data() {
   return {
     activeName: 'first',
     info: '1、优化批量上传图片<br/>2、优  化时间'
   }
 },

三、把br替换成\n换行

<p style="white-space: pre-wrap;">{{changeLine(info)}}</p>

data(){
	return{
		info: '1、优化批量上传图片<br/>2、优化时间'
	}
},
methods:{
	changeLine(str){
		return str.replace(/<br>/g,'\n')
	}
}

附带:

参考文章:https://blog.csdn.net/qq_41287158/article/details/117588459   

转载请注明出处或者链接地址:https://www.qianduange.cn//article/11083.html
标签
评论
发布的文章
大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!