欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

前端監(jiān)控方案詳解以及最佳實(shí)踐

 更新時(shí)間:2025年09月15日 09:35:12   作者:咔咔庫奇  
前端性能監(jiān)控是一種用于實(shí)時(shí)監(jiān)控前端用戶行為和響應(yīng)時(shí)間數(shù)據(jù)的技術(shù),這篇文章主要介紹了前端監(jiān)控方案以及最佳實(shí)踐的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、前端監(jiān)控方案是什么?

前端監(jiān)控方案是一套系統(tǒng)化的工具和流程,用于收集、分析和報(bào)告網(wǎng)站或Web應(yīng)用在前端運(yùn)行時(shí)的各種性能指標(biāo)、錯(cuò)誤日志、用戶行為等數(shù)據(jù)。它通常包括以下幾個(gè)核心模塊:

  1. 性能監(jiān)控:頁面加載時(shí)間、資源加載時(shí)間、首屏渲染時(shí)間等
  2. 錯(cuò)誤監(jiān)控:JavaScript錯(cuò)誤、資源加載失敗、API請(qǐng)求錯(cuò)誤等
  3. 行為監(jiān)控:用戶點(diǎn)擊流、頁面跳轉(zhuǎn)、功能使用情況等
  4. 體驗(yàn)監(jiān)控:白屏率、卡頓情況、網(wǎng)絡(luò)狀況等
  5. 業(yè)務(wù)監(jiān)控:關(guān)鍵業(yè)務(wù)流程轉(zhuǎn)化率、特定功能使用率等

二、為什么要做前端監(jiān)控方案?

  1. 提升用戶體驗(yàn)

    • 及時(shí)發(fā)現(xiàn)并解決性能瓶頸,減少頁面加載時(shí)間
    • 快速定位和修復(fù)前端錯(cuò)誤,避免影響用戶操作
  2. 保障業(yè)務(wù)穩(wěn)定性

    • 實(shí)時(shí)監(jiān)控線上問題,快速響應(yīng)
    • 減少因前端問題導(dǎo)致的業(yè)務(wù)損失
  3. 數(shù)據(jù)驅(qū)動(dòng)優(yōu)化

    • 基于真實(shí)用戶數(shù)據(jù)優(yōu)化產(chǎn)品
    • 分析用戶行為,指導(dǎo)產(chǎn)品決策
  4. 降低故障影響

    • 快速發(fā)現(xiàn)問題并告警
    • 通過監(jiān)控?cái)?shù)據(jù)評(píng)估問題影響范圍
  5. 提高開發(fā)效率

    • 減少"無法復(fù)現(xiàn)"的問題
    • 提供詳盡的錯(cuò)誤上下文,加速問題排查

三、如何做好前端監(jiān)控方案?

1. 搭建完善的監(jiān)控體系

基礎(chǔ)層監(jiān)控:

  • 使用Performance API收集性能指標(biāo)
  • 通過window.onerrorunhandledrejection捕獲錯(cuò)誤
  • 利用MutationObserver監(jiān)測(cè)DOM變化

代碼實(shí)現(xiàn)示例:

// 性能監(jiān)控
const perfData = window.performance.timing;
const loadTime = perfData.loadEventEnd - perfData.navigationStart;

// 錯(cuò)誤監(jiān)控
window.addEventListener('error', (e) => {
  logError({
    msg: e.message,
    file: e.filename,
    line: e.lineno,
    col: e.colno,
    stack: e.error?.stack
  });
});

// 未捕獲的Promise異常
window.addEventListener('unhandledrejection', (e) => {
  logError({
    msg: e.reason?.message || 'Unhandled promise rejection',
    stack: e.reason?.stack
  });
});

2. 選擇合適的監(jiān)控工具

自建方案:

  • 使用Sentry、ELK等開源工具搭建
  • 自主開發(fā)數(shù)據(jù)收集和分析系統(tǒng)

商業(yè)方案:

  • 國內(nèi):阿里云ARMS、騰訊云前端性能監(jiān)控、Fundebug
  • 國外:New Relic、Datadog、LogRocket

3. 關(guān)鍵指標(biāo)定義與采集

核心性能指標(biāo):

  • FP (First Paint):首次繪制
  • FCP (First Contentful Paint):首次內(nèi)容繪制
  • LCP (Largest Contentful Paint):最大內(nèi)容繪制
  • FID (First Input Delay):首次輸入延遲
  • CLS (Cumulative Layout Shift):累計(jì)布局偏移

錯(cuò)誤采集策略:

  • JavaScript運(yùn)行時(shí)錯(cuò)誤
  • 資源加載失敗
  • API請(qǐng)求異常
  • 自定義業(yè)務(wù)錯(cuò)誤

4. 數(shù)據(jù)上報(bào)優(yōu)化

上報(bào)策略:

// 使用requestIdleCallback在空閑時(shí)段上報(bào)
window.requestIdleCallback(() => {
  reportData(analyticsData);
});

// 或使用sendBeacon在頁面卸載時(shí)可靠上報(bào)
window.addEventListener('unload', () => {
  navigator.sendBeacon('/log', analyticsData);
});

優(yōu)化技巧:

  • 數(shù)據(jù)聚合,減少請(qǐng)求次數(shù)
  • 本地緩存,失敗重試
  • 采樣上報(bào),降低服務(wù)器壓力
  • 差異化上報(bào),生產(chǎn)/開發(fā)環(huán)境不同策略

5. 數(shù)據(jù)分析與可視化

  • 建立統(tǒng)一的數(shù)據(jù)看板
  • 設(shè)置合理的告警閾值
  • 實(shí)現(xiàn)趨勢(shì)分析和對(duì)比分析
  • 關(guān)聯(lián)多維度數(shù)據(jù)(如錯(cuò)誤率與瀏覽器版本)

6. 建立問題處理流程

  1. 告警機(jī)制:設(shè)置合理的告警閾值和通知渠道
  2. 問題分類:根據(jù)嚴(yán)重程度和影響范圍分級(jí)處理
  3. 快速定位:提供完整的錯(cuò)誤上下文(用戶信息、設(shè)備信息、操作路徑等)
  4. 閉環(huán)處理:從發(fā)現(xiàn)到解決的完整跟蹤

7. 持續(xù)優(yōu)化監(jiān)控方案

  • 定期回顧監(jiān)控指標(biāo)的有效性
  • 根據(jù)業(yè)務(wù)變化調(diào)整監(jiān)控重點(diǎn)
  • 優(yōu)化數(shù)據(jù)采集和上報(bào)策略
  • 提升監(jiān)控系統(tǒng)的性能和穩(wěn)定性

8. 深入具體的前端監(jiān)控方案實(shí)施指南

1)、前端監(jiān)控方案核心模塊詳解

1. 性能監(jiān)控深度實(shí)施

核心指標(biāo)采集方案:

// 使用PerformanceObserver獲取現(xiàn)代性能指標(biāo)
const perfObserver = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    switch (entry.entryType) {
      case 'paint':
        if (entry.name === 'first-paint') {
          metrics.FP = entry.startTime;
        } else if (entry.name === 'first-contentful-paint') {
          metrics.FCP = entry.startTime;
        }
        break;
      case 'largest-contentful-paint':
        metrics.LCP = entry.renderTime || entry.loadTime;
        break;
      case 'layout-shift':
        if (!entry.hadRecentInput) {
          metrics.CLS += entry.value;
        }
        break;
    }
  }
});

// 監(jiān)控的指標(biāo)類型
perfObserver.observe({entryTypes: ['paint', 'largest-contentful-paint', 'layout-shift']});

// 傳統(tǒng)性能指標(biāo)兼容方案
if (window.performance && performance.timing) {
  const pt = performance.timing;
  metrics.DNS = pt.domainLookupEnd - pt.domainLookupStart;
  metrics.TCP = pt.connectEnd - pt.connectStart;
  metrics.TTFB = pt.responseStart - pt.requestStart;
}

首屏?xí)r間計(jì)算優(yōu)化方案:

  1. 基于MutationObserver的首屏判定
const firstScreenObserver = new MutationObserver(() => {
  const viewportHeight = window.innerHeight;
  const viewportWidth = window.innerWidth;
  // 計(jì)算首屏區(qū)域內(nèi)元素
});
  1. 基于圖像識(shí)別的首屏計(jì)算(復(fù)雜但準(zhǔn)確)

2. 錯(cuò)誤監(jiān)控全面覆蓋方案

完整錯(cuò)誤捕獲體系:

// 1. 同步錯(cuò)誤捕獲
window.onerror = function(msg, url, line, col, error) {
  reportError({
    type: 'SYNC_ERROR',
    msg, url, line, col,
    stack: error?.stack
  });
};

// 2. 異步錯(cuò)誤捕獲
window.addEventListener('error', (event) => {
  if (event.target && (event.target.src || event.target.href)) {
    reportError({
      type: 'RESOURCE_ERROR',
      tag: event.target.tagName,
      url: event.target.src || event.target.href
    });
  }
}, true); // 使用捕獲階段

// 3. Promise異常捕獲
window.addEventListener('unhandledrejection', (event) => {
  reportError({
    type: 'PROMISE_ERROR',
    reason: event.reason?.message,
    stack: event.reason?.stack
  });
});

// 4. 框架級(jí)錯(cuò)誤捕獲(以Vue為例)
Vue.config.errorHandler = (err, vm, info) => {
  reportError({
    type: 'VUE_ERROR',
    error: err.toString(),
    component: vm?._name,
    lifecycleHook: info,
    stack: err.stack
  });
};

// 5. 跨域腳本錯(cuò)誤處理
<script crossorigin="anonymous" onerror="handleScriptError(event)"></script>

3. 用戶行為追蹤精細(xì)化方案

點(diǎn)擊熱力圖實(shí)現(xiàn):

document.addEventListener('click', (e) => {
  const target = e.target;
  const path = getXPath(target);
  const position = {
    x: e.pageX,
    y: e.pageY,
    viewport: `${window.innerWidth}x${window.innerHeight}`
  };
  
  reportBehavior({
    type: 'CLICK',
    path,
    position,
    timestamp: Date.now(),
    text: getElementText(target)
  });
});

function getXPath(element) {
  // 生成元素的XPath路徑
}

頁面停留時(shí)間計(jì)算:

let lastActiveTime = Date.now();
document.addEventListener('mousemove', updateActiveTime);
document.addEventListener('keypress', updateActiveTime);

function updateActiveTime() {
  const now = Date.now();
  const duration = now - lastActiveTime;
  if (duration > 3000) { // 非活躍超過3秒
    reportBehavior({
      type: 'INACTIVITY',
      duration
    });
  }
  lastActiveTime = now;
}

2)、數(shù)據(jù)上報(bào)高級(jí)策略

1. 高效上報(bào)機(jī)制實(shí)現(xiàn)

class Reporter {
  constructor() {
    this.queue = [];
    this.maxRetry = 3;
    this.batchSize = 5;
    this.timer = null;
    this.url = 'https://report.example.com/api';
  }
  
  add(data) {
    this.queue.push(data);
    if (this.queue.length >= this.batchSize) {
      this.send();
    } else {
      this.startTimer();
    }
  }
  
  startTimer() {
    if (!this.timer) {
      this.timer = setTimeout(() => {
        this.send();
        this.timer = null;
      }, 5000); // 5秒延遲上報(bào)
    }
  }
  
  async send() {
    if (this.queue.length === 0) return;
    
    const dataToSend = [...this.queue];
    this.queue = [];
    
    try {
      await fetch(this.url, {
        method: 'POST',
        body: JSON.stringify(dataToSend),
        headers: {'Content-Type': 'application/json'},
        keepalive: true // 確保頁面卸載時(shí)也能發(fā)送
      });
    } catch (err) {
      // 失敗重試邏輯
      if (this.retryCount < this.maxRetry) {
        this.queue.unshift(...dataToSend);
        this.retryCount++;
        setTimeout(() => this.send(), 1000 * this.retryCount);
      }
    }
  }
  
  // 頁面卸載時(shí)強(qiáng)制上報(bào)
  setupUnloadReport() {
    window.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'hidden') {
        this.send();
      }
    });
    
    window.addEventListener('pagehide', () => {
      if (navigator.sendBeacon) {
        const data = JSON.stringify(this.queue);
        navigator.sendBeacon(this.url, data);
      } else {
        this.send();
      }
    });
  }
}

2. 數(shù)據(jù)采樣與壓縮策略

// 采樣率控制(1%采樣)
const shouldSample = () => Math.random() < 0.01;

// 數(shù)據(jù)壓縮方案
function compressData(data) {
  // 1. 移除空字段
  const filtered = Object.fromEntries(
    Object.entries(data).filter(([_, v]) => v != null)
  );
  
  // 2. 縮短字段名
  const mapping = {
    timestamp: 'ts',
    userAgent: 'ua',
    // ...其他字段映射
  };
  
  // 3. 數(shù)值型數(shù)據(jù)精度控制
  if (filtered.loadTime) {
    filtered.loadTime = Math.round(filtered.loadTime);
  }
  
  return filtered;
}

3)、監(jiān)控系統(tǒng)架構(gòu)設(shè)計(jì)

1. 完整技術(shù)棧推薦

組件類型推薦方案特點(diǎn)說明
數(shù)據(jù)收集自研SDK + Sentry兼顧靈活性和專業(yè)性
數(shù)據(jù)傳輸WebSocket + HTTP/2提升傳輸效率
數(shù)據(jù)存儲(chǔ)Elasticsearch + ClickHouse兼顧搜索和分析需求
實(shí)時(shí)計(jì)算Flink + Kafka低延遲處理
可視化Grafana + Kibana專業(yè)可視化
告警系統(tǒng)Prometheus Alertmanager靈活配置告警規(guī)則

2. 服務(wù)端處理流程

  1. 接收層:Nginx負(fù)載均衡 + 數(shù)據(jù)校驗(yàn)
  2. 解析層:日志解析(Logstash/Flink)
  3. 存儲(chǔ)層
    • 實(shí)時(shí)數(shù)據(jù):Elasticsearch(檢索)
    • 聚合數(shù)據(jù):ClickHouse(分析)
    • 原始數(shù)據(jù):HDFS/S3(歸檔)
  4. 計(jì)算層
    • 實(shí)時(shí)計(jì)算:Flink
    • 離線計(jì)算:Spark
  5. 應(yīng)用層
    • API服務(wù)
    • 告警服務(wù)
    • 數(shù)據(jù)導(dǎo)出

4)、具體業(yè)務(wù)場景實(shí)施案例

電商平臺(tái)監(jiān)控方案

關(guān)鍵監(jiān)控點(diǎn):

  1. 購物車流程

    • 添加商品成功率
    • 結(jié)算按鈕點(diǎn)擊率
    • 優(yōu)惠券應(yīng)用異常
  2. 支付流程

    • 支付頁面加載時(shí)間
    • 支付接口錯(cuò)誤率
    • 支付成功轉(zhuǎn)化率

實(shí)施代碼:

// 支付流程監(jiān)控
const paymentSteps = {
  start: 0,
  loaded: 0,
  submitted: 0,
  completed: 0
};

// 標(biāo)記支付流程節(jié)點(diǎn)
function markPaymentStep(step) {
  paymentSteps[step] = Date.now();
  
  if (step === 'completed') {
    reportPaymentFlow({
      loadTime: paymentSteps.loaded - paymentSteps.start,
      submitTime: paymentSteps.submitted - paymentSteps.loaded,
      processTime: paymentSteps.completed - paymentSteps.submitted,
      paymentMethod: getSelectedPaymentMethod()
    });
  }
}

// 支付錯(cuò)誤監(jiān)控
paymentForm.addEventListener('submit', async (e) => {
  try {
    markPaymentStep('submitted');
    const result = await submitPayment();
    markPaymentStep('completed');
  } catch (err) {
    reportError({
      type: 'PAYMENT_ERROR',
      error: err.message,
      step: 'payment_submission',
      formData: getFormData()
    });
  }
});

5)、性能優(yōu)化專項(xiàng)方案

1. 長任務(wù)監(jiān)控

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.duration > 50) { // 超過50ms的任務(wù)
      reportLongTask({
        duration: entry.duration,
        startTime: entry.startTime,
        container: entry.attribution[0]?.containerSrc
      });
    }
  }
});
observer.observe({entryTypes: ['longtask']});

2. 內(nèi)存泄漏檢測(cè)

setInterval(() => {
  const memory = performance.memory;
  if (memory) {
    if (memory.usedJSHeapSize > memory.jsHeapSizeLimit * 0.7) {
      reportMemoryWarning({
        used: memory.usedJSHeapSize,
        total: memory.totalJSHeapSize,
        limit: memory.jsHeapSizeLimit
      });
    }
  }
}, 10000); // 每10秒檢查一次

6)、監(jiān)控質(zhì)量保障措施

  1. 監(jiān)控系統(tǒng)自監(jiān)控

    • 上報(bào)成功率監(jiān)控
    • 數(shù)據(jù)處理延遲監(jiān)控
    • 存儲(chǔ)空間預(yù)警
  2. 數(shù)據(jù)一致性校驗(yàn)

    // 客戶端生成數(shù)據(jù)指紋
    function generateDataChecksum(data) {
      const str = JSON.stringify(data);
      let hash = 0;
      for (let i = 0; i < str.length; i++) {
        hash = ((hash << 5) - hash) + str.charCodeAt(i);
        hash |= 0; // Convert to 32bit integer
      }
      return hash;
    }
    
  3. 監(jiān)控?cái)?shù)據(jù)測(cè)試方案

    • 單元測(cè)試驗(yàn)證數(shù)據(jù)采集
    • E2E測(cè)試驗(yàn)證完整流程
    • 壓力測(cè)試驗(yàn)證上報(bào)性能

7)、前沿監(jiān)控技術(shù)探索

  1. Web Vitals RUM:真實(shí)用戶核心指標(biāo)監(jiān)控
  2. Crash Reporting:應(yīng)用崩潰分析
  3. Predictive Monitoring:基于機(jī)器學(xué)習(xí)的異常預(yù)測(cè)
  4. Session Replay:用戶會(huì)話重現(xiàn)技術(shù)
  5. Distributed Tracing:前后端全鏈路追蹤

通過以上具體實(shí)施方案,可以構(gòu)建一個(gè)專業(yè)級(jí)的前端監(jiān)控系統(tǒng),不僅能發(fā)現(xiàn)表面問題,更能深入診斷性能瓶頸和體驗(yàn)問題,為業(yè)務(wù)發(fā)展提供堅(jiān)實(shí)的數(shù)據(jù)支撐。

四、最佳實(shí)踐建議

  1. 用戶隱私保護(hù):匿名化處理敏感數(shù)據(jù),遵守GDPR等法規(guī)
  2. 漸進(jìn)式實(shí)施:從核心指標(biāo)開始,逐步完善
  3. 跨團(tuán)隊(duì)協(xié)作:與后端、運(yùn)維團(tuán)隊(duì)共享監(jiān)控?cái)?shù)據(jù)
  4. 監(jiān)控監(jiān)控系統(tǒng):確保監(jiān)控系統(tǒng)自身的高可用性
  5. 文檔與培訓(xùn):完善使用文檔,定期團(tuán)隊(duì)培訓(xùn)

到此這篇關(guān)于前端監(jiān)控方案詳解以及最佳實(shí)踐的文章就介紹到這了,更多相關(guān)前端監(jiān)控方案內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue3使用ResizeObserver監(jiān)聽元素的尺寸寬度變化

    Vue3使用ResizeObserver監(jiān)聽元素的尺寸寬度變化

    要監(jiān)聽 div 寬度的變化,可以使用 ResizeObserver 接口,ResizeObserver 允許你觀察一個(gè)或多個(gè)元素的尺寸變化,并在發(fā)生變化時(shí)執(zhí)行回調(diào)函數(shù),所以本文給大家介紹了Vue3如何使用ResizeObserver監(jiān)聽元素的尺寸寬度變化,需要的朋友可以參考下
    2024-08-08
  • VUE中v-on:click事件中獲取當(dāng)前dom元素的代碼

    VUE中v-on:click事件中獲取當(dāng)前dom元素的代碼

    這篇文章主要介紹了VUE中v-on:click事件中獲取當(dāng)前dom元素的代碼,文中同時(shí)給大家提到了v-on:click獲取當(dāng)前事件對(duì)象元素的方法,需要的朋友可以參考下
    2018-08-08
  • vue的v-if里實(shí)現(xiàn)調(diào)用函數(shù)

    vue的v-if里實(shí)現(xiàn)調(diào)用函數(shù)

    這篇文章主要介紹了vue的v-if里實(shí)現(xiàn)調(diào)用函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 通過vue.extend實(shí)現(xiàn)消息提示彈框的方法記錄

    通過vue.extend實(shí)現(xiàn)消息提示彈框的方法記錄

    這篇文章主要給大家介紹了關(guān)于通過vue.extend實(shí)現(xiàn)消息提示彈框的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • vue使用axios實(shí)現(xiàn)文件上傳進(jìn)度的實(shí)時(shí)更新詳解

    vue使用axios實(shí)現(xiàn)文件上傳進(jìn)度的實(shí)時(shí)更新詳解

    最近在學(xué)習(xí)axios,然后項(xiàng)目就用到了,所以這篇文章主要給大家介紹了關(guān)于vue中利用axios實(shí)現(xiàn)文件上傳進(jìn)度的實(shí)時(shí)更新的相關(guān)資料,文中先對(duì)axios進(jìn)行了簡單的介紹,方法大家理解學(xué)習(xí),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • elementUI 動(dòng)態(tài)生成幾行幾列的方法示例

    elementUI 動(dòng)態(tài)生成幾行幾列的方法示例

    這篇文章主要介紹了elementUI 動(dòng)態(tài)生成幾行幾列的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Vuex的基本概念、項(xiàng)目搭建以及入坑點(diǎn)

    Vuex的基本概念、項(xiàng)目搭建以及入坑點(diǎn)

    Vuex是一個(gè)專門為Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式,這篇文章主要介紹了Vuex的基本概念、項(xiàng)目搭建以及入坑點(diǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • vuedraggable拖拽到目標(biāo)區(qū)域?qū)崿F(xiàn)過程解析

    vuedraggable拖拽到目標(biāo)區(qū)域?qū)崿F(xiàn)過程解析

    這篇文章主要為大家介紹了vuedraggable拖拽到目標(biāo)區(qū)域?qū)崿F(xiàn)過程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 解決element-ui庫的el-row的gutter=10間距失效問題

    解決element-ui庫的el-row的gutter=10間距失效問題

    這篇文章主要介紹了解決element-ui庫的el-row的gutter=10間距失效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • vue引入新版 vue-awesome-swiper插件填坑問題

    vue引入新版 vue-awesome-swiper插件填坑問題

    這篇文章主要介紹了vue引入新版 vue-awesome-swiper插件填坑問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01

最新評(píng)論