1012414140@qq.com
2026-10-16 1e106aedda95d0df26ce9909da2761cde2105d32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
  <title>峰峰矿区智慧停车</title>
 
  <!--
    样式文件:主源用国内阿里云 npmmirror(移动/联通/电信网络稳定可达),
    加载失败自动切回 jsdelivr。CSS 失败不会导致白屏,仅样式异常。
  -->
  <link rel="stylesheet"
        href="https://registry.npmmirror.com/element-ui/2.15.14/files/lib/theme-chalk/index.css"
        onerror="this.onerror=null;this.href='https://cdn.jsdelivr.net/npm/element-ui@2.15.14/lib/theme-chalk/index.css'">
  <link rel="stylesheet"
        href="https://registry.npmmirror.com/view-design/4.7.0/files/dist/styles/iview.css"
        onerror="this.onerror=null;this.href='https://cdn.jsdelivr.net/npm/view-design@4.7.0/dist/styles/iview.css'">
 
  <style>
    /* 首屏加载占位(Vue 挂载后会自动替换掉 #app 内的内容) */
    #app-loading{position:fixed;top:0;left:0;right:0;bottom:0;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#f5f7fa;color:#606266;font-size:15px;z-index:9998}
    #app-loading .spin{width:38px;height:38px;margin-bottom:14px;border:3px solid #dcdfe6;border-top-color:#409eff;border-radius:50%;animation:appspin .8s linear infinite}
    @keyframes appspin{to{transform:rotate(360deg)}}
    /* 资源全部加载失败时的提示层,替代“纯白屏” */
    #fatal-mask{display:none;position:fixed;top:0;left:0;right:0;bottom:0;inset:0;z-index:9999;background:#fff;align-items:center;justify-content:center;padding:30px;box-sizing:border-box}
    #fatal-mask .box{max-width:420px;text-align:center;color:#303133}
    #fatal-mask .ico{font-size:44px;color:#f56c6c;margin-bottom:14px}
    #fatal-mask .msg{font-size:15px;line-height:1.7;color:#606266;margin-bottom:20px;word-break:break-all}
    #fatal-mask button{padding:10px 34px;font-size:15px;color:#fff;background:#409eff;border:none;border-radius:4px;outline:none}
    #fatal-mask button:active{background:#3a8ee6}
  </style>
 
  <script>
    /*
     * 基础库(Vue / ElementUI / ViewUI / ECharts)多源容灾加载器
     *
     * 背景:这些库通过 webpack externals 外置,业务包执行强依赖对应的全局变量。
     * 之前只引用 cdn.jsdelivr.net 一个源,该域名在国内手机蜂窝网络(4G/5G)下
     * 经常被 DNS 污染 / 连接重置,脚本加载失败后 window.Vue 为 undefined,
     * 业务包执行立即报错,#app 永远为空,表现为手机白屏。
     *
     * 策略:国内 npmmirror 为主源,jsdelivr、bootcdn 依次兜底;
     * 用“外链脚本 + 紧随其后的内联检测脚本”成对输出,保证严格的加载顺序,
     * 业务包(webpack 注入在 body 末尾)一定在所有基础库就绪后才执行。
     */
    window.__cdnTry = function (globalName, urls, idx) {
      if (window[globalName]) return true;
      if (idx >= urls.length) {
        (window.__CDN_FAILED__ = window.__CDN_FAILED__ || []).push(globalName);
        return false;
      }
      document.write('<script src="' + urls[idx] + '"><\/script>');
      document.write('<script>window.__cdnTry("' + globalName + '",' + JSON.stringify(urls) + ',' + (idx + 1) + ');<\/script>');
    };
 
    /* 白屏兜底:记录脚本错误,超时后若基础库仍未就绪则给出可见提示 */
    window.__lastError__ = '';
    window.addEventListener('error', function (e) {
      if (e && e.message) {
        window.__lastError__ = e.message + (e.filename ? ('(' + e.filename.split('/').pop() + ':' + e.lineno + ')') : '');
      }
    }, true);
    window.addEventListener('unhandledrejection', function (e) {
      var r = e && e.reason;
      window.__lastError__ = 'Promise异常: ' + (r && r.message ? r.message : String(r));
    });
    window.__showFatal = function (msg) {
      var mask = document.getElementById('fatal-mask');
      var loading = document.getElementById('app-loading');
      if (loading) loading.style.display = 'none';
      if (mask) {
        document.getElementById('fatal-msg').textContent = msg;
        mask.style.display = 'flex';
      }
    };
    setTimeout(function () {
      /* 注意:view-design 的 UMD 包在浏览器下挂载的全局名是小写 iview,不是 ViewUI */
      var required = ['Vue', 'ELEMENT', 'iview', 'echarts'];
      var labels = { Vue: 'Vue', ELEMENT: 'ElementUI', iview: 'ViewUI', echarts: 'ECharts' };
      var missing = required.filter(function (n) { return !window[n]; });
      if (missing.length) {
        window.__showFatal('静态资源加载失败,页面无法启动(缺少:' + missing.map(function (n) { return labels[n]; }).join('、') +
          ')。请切换 WiFi 或 4G/5G 网络后重试。' +
          (window.__lastError__ ? ('\n' + window.__lastError__) : ''));
        return;
      }
      /* 库齐全但 12 秒仍未挂载,通常是业务包/接口异常,也要让用户看到而不是白屏 */
      setTimeout(function () {
        var loading = document.getElementById('app-loading');
        if (loading && loading.parentNode) {
          window.__showFatal('页面加载超时,请点击重试。' +
            (window.__lastError__ ? ('\n' + window.__lastError__) : ''));
        }
      }, 12000);
    }, 8000);
  </script>
</head>
<body>
  <div id="app"><div id="app-loading"><div class="spin"></div><div>正在加载,请稍候…</div></div></div>
 
  <div id="fatal-mask">
    <div class="box">
      <div class="ico">!</div>
      <div class="msg" id="fatal-msg">静态资源加载失败,请重试。</div>
      <button type="button" onclick="location.reload()">重新加载</button>
    </div>
  </div>
 
  <script>
    (function () {
      /* 顺序不能变:Vue -> ElementUI -> ViewUI -> ECharts */
      var LIBS = [
        ['Vue', [
          'https://registry.npmmirror.com/vue/2.7.16/files/dist/vue.min.js',
          'https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.min.js',
          'https://cdn.bootcdn.net/ajax/libs/vue/2.7.16/vue.min.js'
        ]],
        ['ELEMENT', [
          'https://registry.npmmirror.com/element-ui/2.15.14/files/lib/index.js',
          'https://cdn.jsdelivr.net/npm/element-ui@2.15.14/lib/index.js',
          'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.js'
        ]],
        ['iview', [
          'https://registry.npmmirror.com/view-design/4.7.0/files/dist/iview.min.js',
          'https://cdn.jsdelivr.net/npm/view-design@4.7.0/dist/iview.min.js',
          'https://cdn.bootcdn.net/ajax/libs/view-design/4.7.0/iview.min.js'
        ]],
        ['echarts', [
          'https://registry.npmmirror.com/echarts/5.4.3/files/dist/echarts.min.js',
          'https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js',
          'https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.min.js'
        ]]
      ];
      LIBS.forEach(function (lib) {
        var name = lib[0], urls = lib[1];
        document.write('<script src="' + urls[0] + '"><\/script>');
        document.write('<script>window.__cdnTry("' + name + '",' + JSON.stringify(urls) + ',1);<\/script>');
      });
    })();
  </script>
</body>
</html>