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

一、背景: 后端接口返回数据以\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.totalconst data = response.data.listif (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   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3019682.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

嘎嘎好用的虚拟键盘第二弹之中文输入法

之前还在为不用研究输入中文而暗自窃喜 这不新需求就来了&#xff08;新需求不会迟到 它只是在路上飞一会儿&#xff09; 找到了个博主分享的代码 是好使的 前端-xyq 已经和原作者申请转载了 感谢~~ 原作者地址&#xff1a;https://www.cnblogs.com/linjiangxian/p/16223681.h…

日志打印传值 传引用 右值引用性能测试(Linux/QNX)

结论 Linux平台和qnx平台优化后传值性能都是比传引用的差&#xff0c;也比传右值的差&#xff0c;因此传参时有必要传递引用。 测试代码 #include <cstdint> #include <ctime> #include <string>#ifdef __linux__#define ITERATIONS 10000000 #else#defin…

《Linux运维总结:ARM64架构CPU基于docker-compose一离线部署rabbitmq 3.10.25容器版镜像模式集群工具》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面向不通的客户安装我们的业务系统&…

最新闲鱼小众蓝海虚拟资源,单号日入300+,三天必起店,矩阵放大月入1-2W

详情介绍 本项目售卖的虚拟资源非常小众&#xff0c;宅男的最爱&#xff0c;并且市场一片蓝海&#xff01;只需一步手机&#xff0c;随时随地操作项目&#xff0c;流量巨大&#xff0c;安装教程方法操作三天必起店&#xff0c;消息多到回不过来&#xff0c;一天轻松出个大几十单…

Stable Diffusion Ai绘画模型推荐:二次元Coriander_Mix v1大模型推荐

负tag嵌入式:EasyNegative,badhandv4 此模型经测试是写实偏3D的效果 画质灰暗的话请加&#xff1a;VAE840000 或者负tag&#xff1a;(watermark:2),(blurry:2),fat,paintings,sketches,(worst quality:2),(low quality:2),(normal quality:2),((monochrome)), ((grayscale))…

韩国站群服务器如何提升网站性能与用户体验?

韩国站群服务器如何提升网站性能与用户体验? 在当今数字化时代&#xff0c;网站性能和用户体验对于吸引和保留用户至关重要。为了提供快速、稳定和优质的服务&#xff0c;越来越多的网站管理员开始利用韩国站群服务器来优化其网站性能。本文将探讨如何利用韩国站群服务器来提…

PLM系统推荐:产品全生命周期管理最佳解决方案

PLM系统推荐&#xff1a;产品全生命周期管理最佳解决方案 在当今日益竞争激烈的市场环境中&#xff0c;企业如何高效管理其产品设计、开发和生命周期变得尤为重要。产品生命周期管理&#xff08;PLM&#xff09;系统正是为解决这一难题而诞生的。本文将为您详细介绍几款值得推荐…

AI换脸原理(6)——人脸分割介绍

一、介绍 人脸分割是计算机视觉和图像处理领域的一项重要任务,它主要涉及到将图像中的人脸区域从背景或其他非人脸区域中分离出来。这一技术具有广泛的应用场景,如人脸识别、图像编辑、虚拟背景替换等。 在计算机视觉(CV)领域,经典的分割技术可以主要划分为三类:语义分…

Baidu Comate:智能编码助手,助力编程效率飞跃

文章目录 Baidu Comate智能助手简介安装Baidu ComateBaidu Comate主要功能代码智能补全编程知识问答官方插件函数注释行间注释生成单测代码解释调优建议函数拆分清空对话框help AutoWork工具箱 总结 Baidu Comate智能助手简介 Baidu Comate&#xff0c;Coding Mate Powered by …

临时有事无法及时签字盖章?试试用契约锁设置“代理人”

遇到“领导休假中、在开重要会议、外出考察或者主任医生手术中等”一段时间内不方便或者无法及时签字盖章的情况怎么办&#xff1f;业务推进不了只能干等&#xff1f; 契约锁电子签及印控平台支持印章、签名“临时授权”、“代理签署”&#xff0c;实现指定人、指定时间段、指定…

深入探究MySQL常用的存储引擎

前言 MySQL是一个广泛使用的开源关系型数据库管理系统&#xff0c;它支持多种存储引擎。存储引擎决定了MySQL数据库如何存储、检索和管理数据。不同的存储引擎具有不同的特点、性能表现和适用场景。选择适合的存储引擎对于优化数据库性能、确保数据完整性和安全性至关重要。本…

寻找最佳App分发平台:小猪APP分发脱颖而出

在当今移动应用市场日益饱和的环境下&#xff0c;选择一个合适的App分发平台对于开发者来说至关重要。这不仅关系到应用能否快速触达目标用户&#xff0c;还直接影响到品牌的塑造与市场份额的争夺。本文将深入探讨几大关键因素&#xff0c;帮助开发者判断哪个App分发平台最适合…

Educational Codeforces Round 165 (Div. 2) A~E

A.Two Friends (思维) 题意&#xff1a; 小 A A A想开一个派对。他有 n n n个朋友&#xff0c;他希望至少有 2 2 2个朋友参加他的派对。 i i i 这个朋友最好的朋友是 p i p_i pi​ 。所有的 p i p_i pi​ 都是不同的&#xff0c;对于每一个 i ∈ [ 1 , n ] i \in [1, n] …

【已解决】ModuleNotFoundError: No module named ‘IPython‘

&#x1f60e; 作者介绍&#xff1a;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff0c;视频号&#xff1a;AI-行者Sun &#x1f388; 本文专栏&#xff1a;本文收录于《AI实战中的各种bug…

STL速查

容器 (Containers) 图解容器 支持随机访问 stringarrayvectordeque支持支持支持支持 string 类 构造函数 string(); ------创建一个空的字符串 例如: string str;string(const char* s); ------使用字符串s初始化string(const string& str); ------拷贝构造 赋值操作…

Linux内核定时器Timer的学习

前言 这段时间我会把内核的小模块复习起来并记录成文章给大家发表出来,方便大家来学习&#xff0c;大家感兴趣的话可以点赞关注下,顺便说下想第一时间看我的文章的话可以点击公众号主页右上角有个设为星标&#xff0c;以免错过好文。先从定时器开始学习。 内核定时器简介 定时器…

AC/DC电源模块在医疗设备领域的应用探讨

BOSHIDA AC/DC电源模块在医疗设备领域的应用探讨 AC/DC电源模块是一种将交流电转换为直流电的设备&#xff0c;广泛应用于各种电子设备中。在医疗设备领域&#xff0c;AC/DC电源模块的应用具有重要意义。本文将探讨AC/DC电源模块在医疗设备中的应用&#xff0c;并分析其优势和…

【mysql】mysql单表查询、多表查询、分组查询、子查询等案例详细解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【web网页制作】html+css旅游家乡河南开封主题网页制作(4页面)【附源码】

HTMLCSS家乡河南主题网页目录 &#x1f354;涉及知识&#x1f964;写在前面&#x1f367;一、网页主题&#x1f333;二、页面效果Page1 首页Page2 开封游玩Page 3 开封美食Page4 留言 &#x1f308; 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 &#x1f40b;四…

SpringBoot启动时自动执行方法的方式

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 在springBoot中我们…