【问题标题】:Angular 7 AmCharts PDF fontAngular 7 AmCharts PDF 字体
【发布时间】:2020-02-06 09:23:43
【问题描述】:

我正在使用 Angular 7 和 AmCharts,并且正在导出 PDF(使用包含的 pdfmake 库),但我无法更改生成的 PDF 的默认字体。我已经使用我需要的字体创建了vfs_fonts.js,并将其包含在scripts 部分的angular.json 中。在我生成报告的组件中,我执行以下操作:

let pdfMake = res[0];

pdfMake.fonts = {
    "Open Sans": {
        "normal": 'OpenSans-Regular.ttf',
        "bold": 'OpenSans-Bold.ttf',
        "italics": 'OpenSans-Italic.ttf',
        "bolditalics": 'OpenSans-BoldItalic.ttf'
    }
}

let doc = {
    header: this.drawHeader(),
    footer: this.drawFooter(),
    pageSize: "A4",
    pageOrientation: "portrait",
    pageMargins: [40, 80, 40, 60],
    content: [],
    defaultStyle: {
        font: "Open Sans"
    }
};

但我收到以下错误:

ERROR Error: Uncaught (in promise): Error: Font 'Open Sans' in style 'normal' is not defined in the font section of the document definition.
Error: Font 'Open Sans' in style 'normal' is not defined in the font section of the document definition

我该如何解决?谢谢

【问题讨论】:

标签: angular amcharts


【解决方案1】:

我在更改 pdf make library 的字体时遇到了同样的问题。我使用以下步骤解决了这个问题。

首先,下载您需要的字体的 .ttf 文件。

第 1 步)
转到以下路径-> node_modules -> pdfmake

第 2 步)
pdfmake 目录下,创建名为 examples 的文件夹。转到 examples 文件夹并在其中创建一个文件夹名称 fonts

第 3 步) 现在将下载的 .ttf 文件粘贴到字体文件夹中。 (path_to_paste_ttf_File : node_modules/pdfmake/examples/fonts)

将文件粘贴到该文件夹​​后。继续第 4 步

第 4 步)
转到终端中提到的字体文件夹的路径查看下面的图像终端路径以供参考。

第 5 步)
完成 step4 后,朗姆酒 gulb buildFonts 。您的输出将如下图所示。

一旦你成功构建了你的字体。
转到生成 pdf 的组件的 .ts 文件。

.ts 文件内

import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;


async generatePdf(value){
        pdfMake.fonts = {
            Roboto: {
                normal: 'Roboto-Regular.ttf',
                bold: 'Roboto-Medium.ttf',
                italics: 'Roboto-Italic.ttf',
                bolditalics: 'Roboto-MediumItalic.ttf'
            }
        };
        const documentDefinition = await this.getDocumentDefinition();
        pdfMake.createPdf(documentDefinition).open();
    }
    getDocumentDefinition(){
        return {
            content: (...),
              defaultStyle: {
                    font: 'yourFontName' //in this case it's roboto.
            }
        }               
    }

这解决了我的问题,如果您遇到任何困难,请告诉我。
更多参考,关注official document

【讨论】:

  • 再说一次,我没有使用独立的 pdfmake 库,我使用的是 INSIDE AMCharts 库中的 pdfmake 库,所以我不能这样做
  • 但毕竟你关心的是 pdfmake library fonts 。那你为什么不使用它呢?
【解决方案2】:

有关如何在客户端 here 上使用自定义字体的 Pdfmake 文档。


vfs_fonts.js 文件格式类似于:

this.pdfMake = this.pdfMake || {}; this.pdfMake.vfs = {
  "Roboto-Italic.ttf": "AAEAAAASAQAABAAgR0RFRtRX1"
}

因此,你应该像下面这样定义它:

window.pdfMake.vfs["OpenSans-Regular.ttf"] = "BASE 64 HERE";
window.pdfMake.vfs["OpenSans-Bold.ttf"] = "BASE 64 HERE";
window.pdfMake.vfs["OpenSans-Italic.ttf"] = "BASE 64 HERE";
window.pdfMake.vfs["OpenSans-BoldItalic.ttf"] = "BASE 64 HERE";

之后,还需要赋值pdfMake.fonts:

开放式无变体: https://fonts.google.com/specimen/Open+Sans?selection.family=Open+Sans:400,400i,600i,700

pdfMake.fonts = {
    // Make sure you define all 4 components - normal, bold, italics, bolditalics - (even if they all point to the same font file)
    "Open Sans": {  <======================= TRY WITH "OpenSans" too
        "normal": 'OpenSans-Regular.ttf',
        "bold": 'OpenSans-Bold.ttf',
        "italics": 'OpenSans-Italic.ttf',
        "bolditalics": 'OpenSans-BoldItalic.ttf'
    }
};

另一种可能的解决方案:(不确定是否有效)

let pdfMake = res[0];
let pdfFonts = require('./vfs_fonts');

pdfMake.addVirtualFileSystem(pdfFonts);

【讨论】:

    【解决方案3】:

    这可能是由于Open Sans 中的空格所致。试试改成OpenSans

    【讨论】:

      【解决方案4】:

      您可以使用 amcharts 使用的相同 pdfmake 库,但您需要在 npm 安装后使用 gulp 生成上面答案中提到的字体,存在承诺问题,所以我替换了语法只是为了快速解决问题,所以你有转到位于项目根目录的 node_modules 中的 pdfmake 文件夹并运行 npm install ,然后在示例目录中创建字体文件夹 -> 示例/字体并在那里复制您的 ttf 字体,然后运行 ​​gulp 文件,该文件将为您提供 vfs_fonts.js 文件。

      你需要编辑这个文件并改变

      this.pdfMake = this.pdfMake || {}; pdfMake.vfs = {}

      导出常量 pdfMake={ vfs : { }};如此屏幕截图所示:

      并像这样适当地结束密钥:

      而不是这个};

      之后,您可以在此处使用 montserrat 字体查看我使用下面的 amchart 自定义内容演示制作的完整工作代码:

      import { Component, NgZone } from "@angular/core";
      import * as am4core from "@amcharts/amcharts4/core";
      import * as am4charts from "@amcharts/amcharts4/charts";
      import am4themes_animated from "@amcharts/amcharts4/themes/animated";
      import am4themes_dataviz from "@amcharts/amcharts4/themes/dataviz";
      
      import * as pdfFontsVfs from "../../node_modules/pdfmake/build/vfs_fonts";
      am4core.useTheme(am4themes_animated);
      
      // Themes
      am4core.useTheme(am4themes_animated);
      am4core.useTheme(am4themes_dataviz);
      
      @Component({
        selector: "app",
        templateUrl: "./app.component.html",
        styleUrls: ["./app.component.css"]
      })
      
      export class AppComponent {
        private chart: am4charts.XYChart;
        private chart2: am4charts.XYChart;
        private chart3: am4charts.XYChart;
        private chart4: am4charts.PieChart;
        constructor(private zone: NgZone) {}
      
        ngAfterViewInit() {
          this.zone.runOutsideAngular(() => {
      
          /**
           * Chart 1
           */
      
          // Create chart instance
          var chart = am4core.create("chartdiv", am4charts.XYChart);
      
          // Add data
          chart.data = [{
            "date": new Date(2018, 0, 1),
            "value": 450,
            "value2": 362,
            "value3": 699
          }, {
            "date": new Date(2018, 0, 2),
            "value": 269,
            "value2": 450,
            "value3": 841
          }, {
            "date": new Date(2018, 0, 3),
            "value": 700,
            "value2": 358,
            "value3": 699
          }, {
            "date": new Date(2018, 0, 4),
            "value": 490,
            "value2": 367,
            "value3": 500
          }, {
            "date": new Date(2018, 0, 5),
            "value": 500,
            "value2": 485,
            "value3": 369
          }, {
            "date": new Date(2018, 0, 6),
            "value": 550,
            "value2": 354,
            "value3": 250
          }, {
            "date": new Date(2018, 0, 7),
            "value": 420,
            "value2": 350,
            "value3": 600
          }];
      
          // Create axes
          var categoryAxis = chart.xAxes.push(new am4charts.DateAxis());
          categoryAxis.renderer.grid.template.location = 0;
          categoryAxis.renderer.labels.template.disabled = true;
          categoryAxis.renderer.minGridDistance = 30;
      
          var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
          valueAxis.renderer.labels.template.disabled = true;
      
      
      
          this.createSeries("value", "Series #1",chart);
          this.createSeries("value2", "Series #2",chart);
          this.createSeries("value3", "Series #3",chart);
          this.chart = chart;
      
          /**
           * Chart 2
           */
      
          // Create chart instance
          var chart2 = am4core.create("chartdiv2", am4charts.XYChart);
          chart2.paddingBottom = 25;
      
          // Add data
          chart2.data = [{
            "country": "USA",
            "visits": 3025
          }, {
            "country": "China",
            "visits": 1882
          }, {
            "country": "Japan",
            "visits": 1809
          }, {
            "country": "Germany",
            "visits": 1322
          }, {
            "country": "UK",
            "visits": 1122
          }, {
            "country": "France",
            "visits": 1114
          }, {
            "country": "India",
            "visits": 984
          }];
      
          // Create axes
          var categoryAxis2 = chart2.xAxes.push(new am4charts.CategoryAxis());
          categoryAxis2.dataFields.category = "country";
          categoryAxis2.renderer.grid.template.location = 0;
          categoryAxis2.renderer.minGridDistance = 30;
          categoryAxis2.renderer.labels.template.disabled = true;
      
          var valueAxis = chart2.yAxes.push(new am4charts.ValueAxis());
          valueAxis.renderer.labels.template.disabled = true;
      
          // Create series
          var series = chart2.series.push(new am4charts.ColumnSeries());
          series.sequencedInterpolation = true;
          series.dataFields.valueY = "visits";
          series.dataFields.categoryX = "country";
          series.columns.template.strokeWidth = 0;
      
          series.columns.template.column.cornerRadiusTopLeft = 10;
          series.columns.template.column.cornerRadiusTopRight = 10;
      
          // on hover, make corner radiuses bigger
          var hoverState = series.columns.template.column.states.create("hover");
          hoverState.properties.cornerRadiusTopLeft = 0;
          hoverState.properties.cornerRadiusTopRight = 0;
          hoverState.properties.fillOpacity = 1;
      
          series.columns.template.adapter.add("fill", (fill, target)=>{
            return chart.colors.getIndex(target.dataItem.index);
          });
          this.chart2 = chart2;
          /**
           * Chart 3
           */
      
          // Create chart instance
          var chart3 = am4core.create("chartdiv3", am4charts.XYChart);
          chart3.paddingBottom = 25;
      
          // Add percent sign to all numbers
          chart3.numberFormatter.numberFormat = "#.3'%'";
      
          // Add data
          chart3.data = [{
              "country": "USA",
              "year2004": 3.5,
              "year2005": 4.2
          }, {
              "country": "UK",
              "year2004": 1.7,
              "year2005": 3.1
          }, {
              "country": "Canada",
              "year2004": 2.8,
              "year2005": 2.9
          }, {
              "country": "Japan",
              "year2004": 2.6,
              "year2005": 2.3
          }, {
              "country": "France",
              "year2004": 1.4,
              "year2005": 2.1
          }, {
              "country": "Brazil",
              "year2004": 2.6,
              "year2005": 4.9
          }];
      
          // Create axes
          var categoryAxis3 = chart3.xAxes.push(new am4charts.CategoryAxis());
          categoryAxis3.dataFields.category = "country";
          categoryAxis3.renderer.grid.template.location = 0;
          categoryAxis3.renderer.minGridDistance = 30;
          categoryAxis3.renderer.labels.template.disabled = true;
      
          var valueAxis3 = chart3.yAxes.push(new am4charts.ValueAxis());
          valueAxis3.renderer.labels.template.disabled = true;
      
          // Create series
          var series3 = chart3.series.push(new am4charts.ColumnSeries());
          series3.dataFields.valueY = "year2004";
          series3.dataFields.categoryX = "country";
          series3.clustered = false;
      
          series3.columns.template.column.cornerRadiusTopLeft = 10;
          series3.columns.template.column.cornerRadiusTopRight = 10;
      
          var series2 = chart3.series.push(new am4charts.ColumnSeries());
          series2.dataFields.valueY = "year2005";
          series2.dataFields.categoryX = "country";
          series2.clustered = false;
          series2.columns.template.width = am4core.percent(50);
      
          series2.columns.template.column.cornerRadiusTopLeft = 6;
          series2.columns.template.column.cornerRadiusTopRight = 6;
          this.chart3 = chart3;
          /**
           * Chart 4
           */
      
          // Create chart
          var chart4 = am4core.create("chartdiv4", am4charts.PieChart);
          chart4.padding(0, 0, 0, 0);
      
          chart4.data = [
            {
              country: "Lithuania",
              value: 260
            },
            {
              country: "Czech Republic",
              value: 230
            },
            {
              country: "Ireland",
              value: 200
            },
            {
              country: "Germany",
              value: 165
            },
            {
              country: "Australia",
              value: 139
            },
            {
              country: "Austria",
              value: 128
            }
          ];
      
          var series4 = chart4.series.push(new am4charts.PieSeries());
          series4.dataFields.value = "value";
          series4.dataFields.radiusValue = "value";
          series4.dataFields.category = "country";
          series4.slices.template.cornerRadius = 6;
          series4.colors.step = 3;
          series4.radius = am4core.percent(100);
          series4.labels.template.disabled = true;
          series4.ticks.template.disabled = true;
          this.chart4 = chart4;
          });
        }
      
      
        /**
         * Function that exports PDF
         */
      
        async savePDF() {
      
            var res = [];
            var fonts =  {
              "Montserrat": {
               normal: "Montserrat-Regular.ttf",
               bold: "Montserrat-Bold.ttf",
               italics: "Montserrat-Italic.ttf",
               bolditalics: "Montserrat-BoldItalic.ttf"
             }
           };
            var PdfMake = await this.chart.exporting.pdfmake;
      
      
      
      
      
            PdfMake.vfs = pdfFontsVfs.pdfMake.vfs;
            PdfMake.addVirtualFileSystem = pdfFontsVfs;
            PdfMake.fonts = fonts;
      
            res[1] = await this.chart.exporting.getImage("png");
            res[2] = await this.chart2.exporting.getImage("png");
            res[3] = await this.chart3.exporting.getImage("png");
            res[4] = await this.chart4.exporting.getImage("png");
      
            // pdfmake is ready
      
            // Create document template
            var doc = {
              pageSize: "A4",
              pageOrientation: "portrait",
              pageMargins: [30, 30, 30, 30],
              content: [],
              defaultStyle:{
                font: "Montserrat"
              }
            };
      
            doc.content.push({
              text: "In accumsan velit in orci tempor",
              fontSize: 20,
              bold: true,
              margin: [0, 20, 0, 15]
            });
      
            doc.content.push({
              text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sem quam, sodales ac volutpat sed, vestibulum id quam. Sed quis arcu non elit fringilla mattis. Sed auctor mi sed efficitur vehicula. Sed bibendum odio urna, quis lobortis dui luctus ac. Duis eu lacus sodales arcu tincidunt ultrices viverra a risus. Vivamus justo massa, malesuada quis pellentesque ut, placerat in massa. Nunc bibendum diam justo, in consequat ipsum fringilla ac. Praesent porta nibh ac arcu viverra, at scelerisque neque venenatis. Donec aliquam lorem non ultrices ultrices. Aliquam efficitur eros quis tortor condimentum, id pellentesque metus iaculis. Aenean at consequat neque, a posuere lectus. In eu libero magna. Pellentesque molestie tellus nec nisi molestie, eu dignissim lacus tristique. Sed tellus nulla, suscipit a velit non, mattis dictum metus. Curabitur mi mi, convallis nec libero quis, venenatis vestibulum ante.",
              fontSize: 15,
              margin: [0, 0, 0, 15]
            });
      
            doc.content.push({
              text: "Aliquam lacinia justo",
              fontSize: 20,
              bold: true,
              margin: [0, 20, 0, 15]
            });
      
            doc.content.push({
              image: res[1],
              width: 530
            });
      
            doc.content.push({
              text: "Phasellus suscipit in diam a interdum",
              fontSize: 20,
              bold: true,
              margin: [0, 20, 0, 15]
            });
      
            doc.content.push({
              table: {
                headerRows: 1,
                widths: [ "*", "*", "*", "*" ],
                body: [
                  [
                    { text: "USA", bold: true },
                    { text: "Japan", bold: true },
                    { text: "France", bold: true },
                    { text: "Mexico", bold: true }
                  ],
                  [ "2500", "2500", "2200", "1200" ],
                  [ "800", "1200", "990", "708" ],
                  [ "2100", "2150", "900", "1260" ],
                ]
              }
            });
      
            doc.content.push({
              text: "Duis sed efficitur mauris",
              fontSize: 20,
              bold: true,
              margin: [0, 20, 0, 15]
            });
      
            doc.content.push({
              columns: [{
                image: res[2],
                width: 250
              }, {
                image: res[3],
                width: 250
              }],
              columnGap: 30
            });
      
            doc.content.push({
              text: "Aliquam semper lacinia",
              fontSize: 20,
              bold: true,
              margin: [0, 20, 0, 15]
            });
      
            doc.content.push({
              columns: [{
                image: res[4],
                width: 150
              }, {
                stack: [{
                  text: "Maecenas congue leo vel tortor faucibus, non semper odio viverra. In ac libero rutrum libero elementum blandit vel in orci. Donec sit amet nisl ac eros mollis molestie. Curabitur ut urna vitae turpis bibendum malesuada sit amet imperdiet orci. Etiam pulvinar quam at lorem pellentesque congue. Integer sed odio enim. Maecenas eu nulla justo. Sed quis enim in est sodales facilisis non sed erat. Aenean vel ornare urna. Praesent viverra volutpat ex a aliquet.",
                  fontSize: 15,
                  margin: [0, 0, 0, 15]
                }, {
             text: "Fusce sed quam pharetra, ornare ligula id, maximus risus. Integer dignissim risus in placerat mattis. Fusce malesuada dui ut lectus ultricies, et sollicitudin nisl placerat. In dignissim elit in pretium lobortis. Fusce ornare enim at metus laoreet, ut convallis elit lacinia. Maecenas pharetra aliquet mi. Nulla orci nunc, egestas id nisi ut, volutpat sollicitudin mi.",
              fontSize: 15,
              margin: [0, 0, 0, 15]
            }],
            width: "*"
          }],
          columnGap: 30
        });
      
          await  PdfMake.createPdf(doc,null, fonts,pdfFontsVfs.pdfMake.vfs).download("report.pdf");
      
      
        }
      
        // Create series
        createSeries(field, name, chart) {
          console.log(chart);
          var series = chart.series.push(new am4charts.LineSeries());
          series.dataFields.valueY = field;
          series.dataFields.dateX = "date";
          series.name = name;
          series.tooltipText = "{dateX}: [b]{valueY}[/]";
          series.strokeWidth = 3;
      
          var bullet = series.bullets.push(new am4charts.CircleBullet());
          bullet.circle.stroke = am4core.color("#fff");
          bullet.circle.strokeWidth = 3;
          bullet.circle.radius = 7;
        }
        ngOnDestroy() {
          this.zone.runOutsideAngular(() => {
            if (this.chart) {
              this.chart.dispose();
              ...dispose other charts
            }
          });
        }
      }
      

      而 webpack 配置是:

      const HtmlWebpackPlugin = require('html-webpack-plugin');
      
      module.exports = {
          entry: './src/main.ts',
          resolve: {
              extensions: ['.ts', '.js']
          },
          module: {
              rules: [
                  {
                      test: /\.ts$/,
                      use: ['ts-loader', 'angular2-template-loader'],
                      exclude: [ /node_modules/, /pdfmake.js$/ ]
                  },
                  {
                      test: /\.(html|css)$/,
                      use: 'raw-loader'
                  }
              ]
          },
          plugins: [
              new HtmlWebpackPlugin({ template: './src/index.html' })
          ],
      
      }
      

      而 html 是:

          <div class="main">
      
        <input type="button" value="Save as PDF" (click)="savePDF()" />
      
      <h1>In accumsan velit in orci tempor</h1>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sem quam, sodales ac volutpat sed, vestibulum id quam. Sed quis arcu non elit fringilla mattis. Sed auctor mi sed efficitur vehicula. Sed bibendum odio urna, quis lobortis dui luctus ac. Duis eu lacus sodales arcu tincidunt ultrices viverra a risus. Vivamus justo massa, malesuada quis pellentesque ut, placerat in massa. Nunc bibendum diam justo, in consequat ipsum fringilla ac. Praesent porta nibh ac arcu viverra, at scelerisque neque venenatis. Donec aliquam lorem non ultrices ultrices. Aliquam efficitur eros quis tortor condimentum, id pellentesque metus iaculis. Aenean at consequat neque, a posuere lectus. In eu libero magna. Pellentesque molestie tellus nec nisi molestie, eu dignissim lacus tristique. Sed tellus nulla, suscipit a velit non, mattis dictum metus. Curabitur mi mi, convallis nec libero quis, venenatis vestibulum ante.</p>
      <h2>Aliquam lacinia justo</h2>
      <div id="chartdiv" class="chart"></div>
      
      <h2>Phasellus suscipit in diam a interdum</h2>
      <table>
        <tr>
          <th>USA</th>
          <th>Japan</th>
          <th>France</th>
          <th>Mexico</th>
        </tr>
        <tr>
          <td>2500</td>
          <td>1900</td>
          <td>2200</td>
          <td>1200</td>
        </tr>
        <tr>
          <td>800</td>
          <td>1200</td>
          <td>990</td>
          <td>708</td>
        </tr>
        <tr>
          <td>2100</td>
          <td>2150</td>
          <td>900</td>
          <td>1260</td>
        </tr>
      </table>
      
      <h2>Duis sed efficitur mauris</h2>
      <div>
        <div class="col">
          <div id="chartdiv2" class="chart"></div>
        </div>
        <div class="col">
          <div id="chartdiv3" class="chart"></div>
        </div>
      </div>
      
      <br>
      <h2>Aliquam semper lacinia</h2>
      <div id="chartdiv4" class="chart"></div>
      <p>Maecenas congue leo vel tortor faucibus, non semper odio viverra. In ac libero rutrum libero elementum blandit vel in orci. Donec sit amet nisl ac eros mollis molestie. Curabitur ut urna vitae turpis bibendum malesuada sit amet imperdiet orci. Etiam pulvinar quam at lorem pellentesque congue. Integer sed odio enim. Maecenas eu nulla justo. Sed quis enim in est sodales facilisis non sed erat. Aenean vel ornare urna. Praesent viverra volutpat ex a aliquet.</p>
      
      <p>Fusce sed quam pharetra, ornare ligula id, maximus risus. Integer dignissim risus in placerat mattis. Fusce malesuada dui ut lectus ultricies, et sollicitudin nisl placerat. In dignissim elit in pretium lobortis. Fusce ornare enim at metus laoreet, ut convallis elit lacinia. Maecenas pharetra aliquet mi. Nulla orci nunc, egestas id nisi ut, volutpat sollicitudin mi.</p>
      
      </div>
      

      而 package.json 是:

          {
          "name": "angular-7-tutorial",
          "version": "1.0.0",
          "scripts": {
              "start": "webpack-dev-server --mode development --open"
          },
          "dependencies": {
              "@amcharts/amcharts4": "^4.9.1",
              "@angular/common": "^7.2.13",
              "@angular/compiler": "^7.2.13",
              "@angular/core": "^7.2.13",
              "@angular/forms": "^7.2.13",
              "@angular/platform-browser": "^7.2.13",
              "@angular/platform-browser-dynamic": "^7.2.13",
              "@angular/router": "^7.2.13",
              "core-js": "^3.0.1",
              "rxjs": "^6.4.0",
              "zone.js": "^0.9.0"
          },
          "devDependencies": {
              "@types/node": "^11.13.5",
              "angular2-template-loader": "^0.6.2",
              "html-webpack-plugin": "^3.2.0",
              "raw-loader": "^1.0.0",
              "ts-loader": "^5.3.3",
              "typescript": "^3.4.4",
              "webpack": "^4.30.0",
              "webpack-cli": "^3.3.0",
              "webpack-dev-server": "^3.3.1"
          }
      }
      

      和文件夹结构:

      我理解的是语法冲突和承诺未解决的故障,防止图表 pdf 不加载自定义字体。如果您看到默认的 amcharts vs_fonts 文件,您将看到可能导致问题的导出默认语法。其次检查您的字体文件是否没有损坏。 希望这会帮助你。谢谢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-06
        • 2019-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多