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://www.hqwc.cn/news/702527.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百度文心一言 java 支持流式输出,Springboot+ sse的demo

参考&#xff1a;GitHub - mmciel/wenxin-api-java: 百度文心一言Java库&#xff0c;支持问答和对话&#xff0c;支持流式输出和同步输出。提供SpringBoot调用样例。提供拓展能力。 1、依赖 <dependency> <groupId>com.baidu.aip</groupId> <artifactId…

品牌银饰售卖|基于SSM+vue的品牌银饰售卖平台的设计与实现(源码+数据库+文档)

品牌银饰售卖平台 目录 基于SSM&#xff0b;vue的品牌银饰售卖平台的设计与实现 一、前言 二、系统设计 三、系统功能设计 1前台功能模块 2后台功能模块 5.2.1管理员功能模块 5.2.2用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题…

ansible——playbook

一、playbook定义 Ansible Playbook是设定自动化任务的一种蓝图&#xff0c;可在无需人工干预或有限干预的前提下执行复杂的IT操作。Ansible Playbook对一组或一类共同构成 Ansible 清单的主机执行。 Ansible Playbook本质上是一些框架&#xff0c;是一些预先编写的代码&#x…

Linux —— 线程控制

Linux —— 线程控制 创建多个线程线程的优缺点优点缺点 pthread_self进程和线程的关系pthread_exit 线程等待pthread_ join线程的返回值线程分离pthread_detach 线程取消pthread_cancel pthread_t 的理解 我们今天接着来学习线程&#xff1a; 创建多个线程 我们可以结合以前…

地平线X3开发板Swap使用说明

准备好旭日X3派、连接好网络 并验证系统版本 rootubuntu:~# cat /etc/version x3j3_lnx_db_20220622 输入以下指令系统更新&#xff08;其他版本同理&#xff0c;依赖项报错可至资源中心更新系统镜像或输入命令解决&#xff09;&#xff1a; apt update apt upgrade reboo…

将jar打包成exe可安装程序,并在html页面唤醒

一、exe4j将jar打包成exe 1.exe4j下载 下载地址&#xff1a;https://www.ej-technologies.com/download/exe4j/files 2.exe4j打包jar 2.1. welcome 可以选择历史配置&#xff0c;新增则直接下一步 2.2. project type选择“jar in exe” mode 2.3. application info设置应用…

springboot引入第三方jar包本地lib并打包

1&#xff1a;在项目根目录创建lib目录并放入第三方lib包 -- project ----lib &#xff08;放在这儿&#xff09; ----src ----target2&#xff1a;pom中引入第三方lib <!-- 引入magus模块 --><dependency><groupId>org.jeecg.msgus</groupId><art…

PADS:生成自交叉平面区域

根据板外形铺铜方法&#xff1a; pads根据板外形铺铜_铺铜如何根据板子形状改变-CSDN博客 根据板外形创建平面区域出现问题&#xff1a; 解决方法&#xff1a;去找结构&#xff0c;让他把出图之前把线合并了

[自动化]pyautogui的使用

目录 环境 包的版本 前置知识 鼠标控制函数 屏幕与鼠标位置 size() position() OnScreen() 鼠标移动 moveTo() move() 鼠标拖动 dragTo() drag() mouseDown()按下鼠标 mouseUp()松开鼠标 鼠标滚动 scroll() 键盘控制函数 write() press() keyDown()和keyU…

等保2.0的全面解读与实施策略

《网络安全等级保护基本要求》&#xff08;等保2.0&#xff09;是中华人民共和国国家安全部于2019年6月发布的网络安全等级保护标准。该标准规定了我国关键信息基础设施的网络安全等级保护要求和评估标准&#xff0c;对于保障我国网络安全具有重要的意义。下面是对等保2.0的全面…

【数据结构】数据结构大汇总 {数据结构的分类总结:定义和特性、实现方式、操作与复杂度、适用场景、相关算法、应用实例}

一、线性结构 1.1 顺序表 定义和特性&#xff1a;顺序表是一种线性表的存储结构&#xff0c;它采用一段地址连续的存储单元依次存储线性表中的元素。顺序表具有随机访问的特性&#xff0c;即可以通过元素的下标直接访问元素。 实现方式&#xff1a;顺序表可以通过数组来实现&…

数据治理框架下,如何实现高效且安全的数据提取与分析

一、引言 随着数字化时代的到来&#xff0c;数据已成为企业运营和决策的核心资产。然而&#xff0c;数据的复杂性和多样性也为企业带来了数据提取与分析的挑战。为了实现数据的有效利用&#xff0c;并确保数据的安全性&#xff0c;需要在数据治理框架下构建高效且安全的数据提…