wangfumin 6 месяцев назад
Родитель
Сommit
aeef482f2e

+ 1 - 0
index.html

@@ -8,6 +8,7 @@
   </head>
   <body>
     <div id="app"></div>
+    <script src="/lib/js/jssdk.js"></script>
     <script type="module" src="/src/main.js"></script>
   </body>
 </html>

+ 816 - 0
public/lib/js/jssdk.js

@@ -0,0 +1,816 @@
+;((e, n) => {
+  'function' == typeof define && (define.amd || define.cmd)
+    ? define(function () {
+        return n(e)
+      })
+    : n(e, !0)
+})(this, function (r, e) {
+  var a, c, n, i, t, o, s, d, l, u, p, f, m, g, h, S, y, I, v, _, w, T
+  if (!r.jWeixin)
+    return (
+      (a = {
+        config: 'preVerifyJSAPI',
+        onMenuShareTimeline: 'menu:share:timeline',
+        onMenuShareAppMessage: 'menu:share:appmessage',
+        onMenuShareQQ: 'menu:share:qq',
+        onMenuShareWeibo: 'menu:share:weiboApp',
+        onMenuShareQZone: 'menu:share:QZone',
+        previewImage: 'imagePreview',
+        getLocation: 'geoLocation',
+        openProductSpecificView: 'openProductViewWithPid',
+        addCard: 'batchAddCard',
+        openCard: 'batchViewCard',
+        chooseWXPay: 'getBrandWCPayRequest',
+        openEnterpriseRedPacket: 'getRecevieBizHongBaoRequest',
+        startSearchBeacons: 'startMonitoringBeacons',
+        stopSearchBeacons: 'stopMonitoringBeacons',
+        onSearchBeacons: 'onBeaconsInRange',
+        consumeAndShareCard: 'consumedShareCard',
+        openAddress: 'editAddress',
+      }),
+      (c = (() => {
+        var e,
+          n = {}
+        for (e in a) n[a[e]] = e
+        return n
+      })()),
+      (i = (n = r.document).title),
+      (t = navigator.userAgent.toLowerCase()),
+      (f = navigator.platform.toLowerCase()),
+      (o = !(!f.match('mac') && !f.match('win'))),
+      (s = -1 != t.indexOf('wxdebugger')),
+      (d = -1 != t.indexOf('micromessenger')),
+      (l = -1 != t.indexOf('android')),
+      (u = -1 != t.indexOf('iphone') || -1 != t.indexOf('ipad')),
+      (p = (f = t.match(/micromessenger\/(\d+\.\d+\.\d+)/) || t.match(/micromessenger\/(\d+\.\d+)/))
+        ? f[1]
+        : ''),
+      (m = { initStartTime: L(), initEndTime: 0, preVerifyStartTime: 0, preVerifyEndTime: 0 }),
+      (g = {
+        version: 1,
+        appId: '',
+        initTime: 0,
+        preVerifyTime: 0,
+        networkType: '',
+        isPreVerifyOk: 1,
+        systemType: u ? 1 : l ? 2 : -1,
+        clientVersion: p,
+        url: encodeURIComponent(location.href),
+      }),
+      (h = {}),
+      (S = { _completes: [] }),
+      (y = { state: 0, data: {} }),
+      O(function () {
+        m.initEndTime = L()
+      }),
+      (I = !1),
+      (v = []),
+      (_ = {
+        config: function (e) {
+          C('config', (h = e))
+          var o = !1 !== h.check
+          O(function () {
+            if (o)
+              k(
+                a.config,
+                { verifyJsApiList: A(h.jsApiList), verifyOpenTagList: A(h.openTagList) },
+                ((S._complete = function (e) {
+                  ;(m.preVerifyEndTime = L()), (y.state = 1), (y.data = e)
+                }),
+                (S.success = function (e) {
+                  g.isPreVerifyOk = 0
+                }),
+                (S.fail = function (e) {
+                  S._fail ? S._fail(e) : (y.state = -1)
+                }),
+                (t = S._completes).push(function () {
+                  B()
+                }),
+                (S.complete = function (e) {
+                  for (var n = 0, i = t.length; n < i; ++n) t[n]()
+                  S._completes = []
+                }),
+                S),
+              ),
+                (m.preVerifyStartTime = L())
+            else {
+              y.state = 1
+              for (var e = S._completes, n = 0, i = e.length; n < i; ++n) e[n]()
+              S._completes = []
+            }
+            var t
+          }),
+            _.invoke ||
+              ((_.invoke = function (e, n, i) {
+                r.WeixinJSBridge && WeixinJSBridge.invoke(e, P(n), i)
+              }),
+              (_.on = function (e, n) {
+                r.WeixinJSBridge && WeixinJSBridge.on(e, n)
+              }))
+        },
+        ready: function (e) {
+          ;(0 != y.state || (S._completes.push(e), !d && h.debug)) && e()
+        },
+        error: function (e) {
+          p < '6.0.2' || (-1 == y.state ? e(y.data) : (S._fail = e))
+        },
+        checkJsApi: function (e) {
+          k(
+            'checkJsApi',
+            { jsApiList: A(e.jsApiList) },
+            ((e._complete = function (e) {
+              l && (i = e.checkResult) && (e.checkResult = JSON.parse(i))
+              var n,
+                i = e,
+                t = i.checkResult
+              for (n in t) {
+                var o = c[n]
+                o && ((t[o] = t[n]), delete t[n])
+              }
+            }),
+            e),
+          )
+        },
+        onMenuShareTimeline: function (e) {
+          M(
+            a.onMenuShareTimeline,
+            {
+              complete: function () {
+                k(
+                  'shareTimeline',
+                  {
+                    title: e.title || i,
+                    desc: e.title || i,
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                    type: e.type || 'link',
+                    data_url: e.dataUrl || '',
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        onMenuShareAppMessage: function (n) {
+          M(
+            a.onMenuShareAppMessage,
+            {
+              complete: function (e) {
+                'favorite' === e.scene
+                  ? k('sendAppMessage', {
+                      title: n.title || i,
+                      desc: n.desc || '',
+                      link: n.link || location.href,
+                      img_url: n.imgUrl || '',
+                      type: n.type || 'link',
+                      data_url: n.dataUrl || '',
+                    })
+                  : k(
+                      'sendAppMessage',
+                      {
+                        title: n.title || i,
+                        desc: n.desc || '',
+                        link: n.link || location.href,
+                        img_url: n.imgUrl || '',
+                        type: n.type || 'link',
+                        data_url: n.dataUrl || '',
+                      },
+                      n,
+                    )
+              },
+            },
+            n,
+          )
+        },
+        onMenuShareQQ: function (e) {
+          M(
+            a.onMenuShareQQ,
+            {
+              complete: function () {
+                k(
+                  'shareQQ',
+                  {
+                    title: e.title || i,
+                    desc: e.desc || '',
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        onMenuShareWeibo: function (e) {
+          M(
+            a.onMenuShareWeibo,
+            {
+              complete: function () {
+                k(
+                  'shareWeiboApp',
+                  {
+                    title: e.title || i,
+                    desc: e.desc || '',
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        onMenuShareQZone: function (e) {
+          M(
+            a.onMenuShareQZone,
+            {
+              complete: function () {
+                k(
+                  'shareQZone',
+                  {
+                    title: e.title || i,
+                    desc: e.desc || '',
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        updateTimelineShareData: function (e) {
+          k('updateTimelineShareData', { title: e.title, link: e.link, imgUrl: e.imgUrl }, e)
+        },
+        updateAppMessageShareData: function (e) {
+          k(
+            'updateAppMessageShareData',
+            { title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl },
+            e,
+          )
+        },
+        startRecord: function (e) {
+          k('startRecord', {}, e)
+        },
+        stopRecord: function (e) {
+          k('stopRecord', {}, e)
+        },
+        onVoiceRecordEnd: function (e) {
+          M('onVoiceRecordEnd', e)
+        },
+        playVoice: function (e) {
+          k('playVoice', { localId: e.localId }, e)
+        },
+        pauseVoice: function (e) {
+          k('pauseVoice', { localId: e.localId }, e)
+        },
+        stopVoice: function (e) {
+          k('stopVoice', { localId: e.localId }, e)
+        },
+        onVoicePlayEnd: function (e) {
+          M('onVoicePlayEnd', e)
+        },
+        uploadVoice: function (e) {
+          k(
+            'uploadVoice',
+            { localId: e.localId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        downloadVoice: function (e) {
+          k(
+            'downloadVoice',
+            { serverId: e.serverId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        translateVoice: function (e) {
+          k(
+            'translateVoice',
+            { localId: e.localId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        chooseImage: function (e) {
+          k(
+            'chooseImage',
+            {
+              scene: '1|2',
+              count: e.count || 9,
+              sizeType: e.sizeType || ['original', 'compressed'],
+              sourceType: e.sourceType || ['album', 'camera'],
+            },
+            ((e._complete = function (e) {
+              if (l) {
+                var n = e.localIds
+                try {
+                  n && (e.localIds = JSON.parse(n))
+                } catch (e) {}
+              }
+            }),
+            e),
+          )
+        },
+        getLocation: function (e) {},
+        getLocation: function (e) {
+          ;(e = e || {}),
+            k(
+              a.getLocation,
+              { type: e.type || 'wgs84' },
+              ((e._complete = function (e) {
+                delete e.type
+              }),
+              e),
+            )
+        },
+        previewImage: function (e) {
+          k(a.previewImage, { current: e.current, urls: e.urls }, e)
+        },
+        uploadImage: function (e) {
+          k(
+            'uploadImage',
+            { localId: e.localId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        downloadImage: function (e) {
+          k(
+            'downloadImage',
+            { serverId: e.serverId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        getLocalImgData: function (e) {
+          !1 === I
+            ? ((I = !0),
+              k(
+                'getLocalImgData',
+                { localId: e.localId },
+                ((e._complete = function (e) {
+                  var n
+                  ;(I = !1), 0 < v.length && ((n = v.shift()), wx.getLocalImgData(n))
+                }),
+                e),
+              ))
+            : v.push(e)
+        },
+        getNetworkType: function (e) {
+          k(
+            'getNetworkType',
+            {},
+            ((e._complete = function (e) {
+              var n = e,
+                e = n.errMsg,
+                i = ((n.errMsg = 'getNetworkType:ok'), n.subtype)
+              if ((delete n.subtype, i)) n.networkType = i
+              else {
+                var i = e.indexOf(':'),
+                  t = e.substring(i + 1)
+                switch (t) {
+                  case 'wifi':
+                  case 'edge':
+                  case 'wwan':
+                    n.networkType = t
+                    break
+                  default:
+                    n.errMsg = 'getNetworkType:fail'
+                }
+              }
+            }),
+            e),
+          )
+        },
+        openLocation: function (e) {
+          k(
+            'openLocation',
+            {
+              latitude: e.latitude,
+              longitude: e.longitude,
+              name: e.name || '',
+              address: e.address || '',
+              scale: e.scale || 28,
+              infoUrl: e.infoUrl || '',
+            },
+            e,
+          )
+        },
+        hideOptionMenu: function (e) {
+          k('hideOptionMenu', {}, e)
+        },
+        showOptionMenu: function (e) {
+          k('showOptionMenu', {}, e)
+        },
+        closeWindow: function (e) {
+          k('closeWindow', {}, (e = e || {}))
+        },
+        hideMenuItems: function (e) {
+          k('hideMenuItems', { menuList: e.menuList }, e)
+        },
+        showMenuItems: function (e) {
+          k('showMenuItems', { menuList: e.menuList }, e)
+        },
+        hideAllNonBaseMenuItem: function (e) {
+          k('hideAllNonBaseMenuItem', {}, e)
+        },
+        showAllNonBaseMenuItem: function (e) {
+          k('showAllNonBaseMenuItem', {}, e)
+        },
+        scanQRCode: function (e) {
+          k(
+            'scanQRCode',
+            {
+              needResult: (e = e || {}).needResult || 0,
+              scanType: e.scanType || ['qrCode', 'barCode'],
+            },
+            ((e._complete = function (e) {
+              var n
+              u &&
+                (n = e.resultStr) &&
+                ((n = JSON.parse(n)), (e.resultStr = n && n.scan_code && n.scan_code.scan_result))
+            }),
+            e),
+          )
+        },
+        openAddress: function (e) {
+          k(
+            a.openAddress,
+            {},
+            ((e._complete = function (e) {
+              ;((e = e).postalCode = e.addressPostalCode),
+                delete e.addressPostalCode,
+                (e.provinceName = e.proviceFirstStageName),
+                delete e.proviceFirstStageName,
+                (e.cityName = e.addressCitySecondStageName),
+                delete e.addressCitySecondStageName,
+                (e.countryName = e.addressCountiesThirdStageName),
+                delete e.addressCountiesThirdStageName,
+                (e.detailInfo = e.addressDetailInfo),
+                delete e.addressDetailInfo
+            }),
+            e),
+          )
+        },
+        openProductSpecificView: function (e) {
+          k(
+            a.openProductSpecificView,
+            { pid: e.productId, view_type: e.viewType || 0, ext_info: e.extInfo },
+            e,
+          )
+        },
+        addCard: function (e) {
+          for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+            var r = n[t],
+              r = { card_id: r.cardId, card_ext: r.cardExt }
+            i.push(r)
+          }
+          k(
+            a.addCard,
+            { card_list: i },
+            ((e._complete = function (e) {
+              if ((n = e.card_list)) {
+                for (var n, i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
+                  var o = n[i]
+                  ;(o.cardId = o.card_id),
+                    (o.cardExt = o.card_ext),
+                    (o.isSuccess = !!o.is_succ),
+                    delete o.card_id,
+                    delete o.card_ext,
+                    delete o.is_succ
+                }
+                ;(e.cardList = n), delete e.card_list
+              }
+            }),
+            e),
+          )
+        },
+        chooseCard: function (e) {
+          k(
+            'chooseCard',
+            {
+              app_id: h.appId,
+              location_id: e.shopId || '',
+              sign_type: e.signType || 'SHA1',
+              card_id: e.cardId || '',
+              card_type: e.cardType || '',
+              card_sign: e.cardSign,
+              time_stamp: e.timestamp + '',
+              nonce_str: e.nonceStr,
+            },
+            ((e._complete = function (e) {
+              ;(e.cardList = e.choose_card_info), delete e.choose_card_info
+            }),
+            e),
+          )
+        },
+        openCard: function (e) {
+          for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+            var r = n[t],
+              r = { card_id: r.cardId, code: r.code }
+            i.push(r)
+          }
+          k(a.openCard, { card_list: i }, e)
+        },
+        consumeAndShareCard: function (e) {
+          k(a.consumeAndShareCard, { consumedCardId: e.cardId, consumedCode: e.code }, e)
+        },
+        chooseWXPay: function (e) {
+          k(a.chooseWXPay, x(e), e), B({ jsApiName: 'chooseWXPay' })
+        },
+        openEnterpriseRedPacket: function (e) {
+          k(a.openEnterpriseRedPacket, x(e), e)
+        },
+        startSearchBeacons: function (e) {
+          k(a.startSearchBeacons, { ticket: e.ticket }, e)
+        },
+        stopSearchBeacons: function (e) {
+          k(a.stopSearchBeacons, {}, e)
+        },
+        onSearchBeacons: function (e) {
+          M(a.onSearchBeacons, e)
+        },
+        openEnterpriseChat: function (e) {
+          k('openEnterpriseChat', { useridlist: e.userIds, chatname: e.groupName }, e)
+        },
+        launchMiniProgram: function (e) {
+          k(
+            'launchMiniProgram',
+            {
+              targetAppId: e.targetAppId,
+              path: ((e) => {
+                var n
+                if ('string' == typeof e && 0 < e.length)
+                  return (
+                    (n = e.split('?')[0]),
+                    (n += '.html'),
+                    void 0 !== (e = e.split('?')[1]) ? n + '?' + e : n
+                  )
+              })(e.path),
+              envVersion: e.envVersion,
+            },
+            e,
+          )
+        },
+        openBusinessView: function (e) {
+          k(
+            'openBusinessView',
+            {
+              businessType: e.businessType,
+              queryString: e.queryString || '',
+              envVersion: e.envVersion,
+            },
+            ((e._complete = function (n) {
+              if (l) {
+                var e = n.extraData
+                if (e)
+                  try {
+                    n.extraData = JSON.parse(e)
+                  } catch (e) {
+                    n.extraData = {}
+                  }
+              }
+            }),
+            e),
+          )
+        },
+        miniProgram: {
+          navigateBack: function (e) {
+            ;(e = e || {}),
+              O(function () {
+                k('invokeMiniProgramAPI', { name: 'navigateBack', arg: { delta: e.delta || 1 } }, e)
+              })
+          },
+          navigateTo: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'navigateTo', arg: { url: e.url } }, e)
+            })
+          },
+          redirectTo: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'redirectTo', arg: { url: e.url } }, e)
+            })
+          },
+          switchTab: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'switchTab', arg: { url: e.url } }, e)
+            })
+          },
+          reLaunch: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'reLaunch', arg: { url: e.url } }, e)
+            })
+          },
+          postMessage: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'postMessage', arg: e.data || {} }, e)
+            })
+          },
+          getEnv: function (e) {
+            O(function () {
+              e({ miniprogram: 'miniprogram' === r.__wxjs_environment })
+            })
+          },
+        },
+      }),
+      (w = 1),
+      (T = {}),
+      n.addEventListener(
+        'error',
+        function (e) {
+          var n, i, t
+          l ||
+            ((t = (n = e.target).tagName),
+            (i = n.src),
+            'IMG' != t && 'VIDEO' != t && 'AUDIO' != t && 'SOURCE' != t) ||
+            (-1 != i.indexOf('wxlocalresource://') &&
+              (e.preventDefault(),
+              e.stopPropagation(),
+              (t = n['wx-id']) || ((t = w++), (n['wx-id'] = t)),
+              T[t] ||
+                ((T[t] = !0),
+                wx.ready(function () {
+                  wx.getLocalImgData({
+                    localId: i,
+                    success: function (e) {
+                      n.src = e.localData
+                    },
+                  })
+                }))))
+        },
+        !0,
+      ),
+      n.addEventListener(
+        'load',
+        function (e) {
+          var n
+          l ||
+            ((n = (e = e.target).tagName),
+            'IMG' != n && 'VIDEO' != n && 'AUDIO' != n && 'SOURCE' != n) ||
+            ((n = e['wx-id']) && (T[n] = !1))
+        },
+        !0,
+      ),
+      e && (r.wx = r.jWeixin = _),
+      _
+    )
+  function k(n, e, i) {
+    r.WeixinJSBridge
+      ? WeixinJSBridge.invoke(n, P(e), function (e) {
+          V(n, e, i)
+        })
+      : C(n, i)
+  }
+  function M(n, i, t) {
+    r.WeixinJSBridge
+      ? WeixinJSBridge.on(n, function (e) {
+          t && t.trigger && t.trigger(e), V(n, e, i)
+        })
+      : C(n, t || i)
+  }
+  function P(e) {
+    return (
+      ((e = e || {}).appId = h.appId),
+      (e.verifyAppId = h.appId),
+      (e.verifySignType = 'sha1'),
+      (e.verifyTimestamp = h.timestamp + ''),
+      (e.verifyNonceStr = h.nonceStr),
+      (e.verifySignature = h.signature),
+      e
+    )
+  }
+  function x(e) {
+    return {
+      timeStamp: e.timestamp + '',
+      nonceStr: e.nonceStr,
+      package: e.package,
+      paySign: e.paySign,
+      signType: e.signType || 'SHA1',
+    }
+  }
+  function V(e, n, i) {
+    ;('openEnterpriseChat' != e && 'openBusinessView' !== e) || (n.errCode = n.err_code),
+      delete n.err_code,
+      delete n.err_desc,
+      delete n.err_detail
+    var t = n.errMsg,
+      e =
+        (t ||
+          ((t = n.err_msg),
+          delete n.err_msg,
+          (t = ((e, n) => {
+            var i,
+              t = c[e]
+            return (
+              t && (e = t),
+              (t = 'ok'),
+              n &&
+                ((i = n.indexOf(':')),
+                ('access denied' !=
+                  (t = (t = (t =
+                    -1 !=
+                    (t =
+                      -1 !=
+                      (t =
+                        'failed' == (t = 'confirm' == (t = n.substring(i + 1)) ? 'ok' : t)
+                          ? 'fail'
+                          : t).indexOf('failed_')
+                        ? t.substring(7)
+                        : t).indexOf('fail_')
+                      ? t.substring(5)
+                      : t).replace(/_/g, ' ')).toLowerCase()) &&
+                  'no permission to execute' != t) ||
+                  (t = 'permission denied'),
+                '' == (t = 'config' == e && 'function not exist' == t ? 'ok' : t)) &&
+                (t = 'fail'),
+              (n = e + ':' + t)
+            )
+          })(e, t)),
+          (n.errMsg = t)),
+        (i = i || {})._complete && (i._complete(n), delete i._complete),
+        (t = n.errMsg || ''),
+        h.debug && !i.isInnerInvoke && alert(JSON.stringify(n)),
+        t.indexOf(':'))
+    switch (t.substring(e + 1)) {
+      case 'ok':
+        i.success && i.success(n)
+        break
+      case 'cancel':
+        i.cancel && i.cancel(n)
+        break
+      default:
+        i.fail && i.fail(n)
+    }
+    i.complete && i.complete(n)
+  }
+  function A(e) {
+    if (e) {
+      for (var n = 0, i = e.length; n < i; ++n) {
+        var t = e[n],
+          t = a[t]
+        t && (e[n] = t)
+      }
+      return e
+    }
+  }
+  function C(e, n) {
+    var i
+    !h.debug ||
+      (n && n.isInnerInvoke) ||
+      ((i = c[e]) && (e = i),
+      n && n._complete && delete n._complete,
+      console.log('"' + e + '",', n || ''))
+  }
+  function B(n) {
+    var i
+    o ||
+      s ||
+      h.debug ||
+      p < '6.0.2' ||
+      g.systemType < 0 ||
+      ((i = new Image()),
+      (g.appId = h.appId),
+      (g.initTime = m.initEndTime - m.initStartTime),
+      (g.preVerifyTime = m.preVerifyEndTime - m.preVerifyStartTime),
+      _.getNetworkType({
+        isInnerInvoke: !0,
+        success: function (e) {
+          g.networkType = e.networkType
+          e =
+            'https://open.weixin.qq.com/sdk/report?v=' +
+            g.version +
+            '&o=' +
+            g.isPreVerifyOk +
+            '&s=' +
+            g.systemType +
+            '&c=' +
+            g.clientVersion +
+            '&a=' +
+            g.appId +
+            '&n=' +
+            g.networkType +
+            '&i=' +
+            g.initTime +
+            '&p=' +
+            g.preVerifyTime +
+            '&u=' +
+            g.url +
+            '&jsapi_name=' +
+            (n ? n.jsApiName : '')
+          i.src = e
+        },
+      }))
+  }
+  function L() {
+    return new Date().getTime()
+  }
+  function O(e) {
+    d &&
+      (r.WeixinJSBridge
+        ? e()
+        : n.addEventListener && n.addEventListener('WeixinJSBridgeReady', e, !1))
+  }
+})

src/utils/modelLoad/4dage.js → public/modelLoad/4dage.js


+ 12 - 0
src/utils/modelLoad/model.html

@@ -16,6 +16,18 @@
   <body>
     <div id="ui"></div>
     <script>
+      function getQueryVariable(variable) {
+        var query = window.location.search.substring(1)
+        var vars = query.split('&')
+        for (var i = 0; i < vars.length; i++) {
+          var pair = vars[i].split('=')
+          if (pair[0] == variable) {
+            return decodeURIComponent(pair[1])
+          }
+        }
+        return null
+      }
+
       let m = getQueryVariable('m')
 
       // window.autoRotate = true; // 是否自动旋转

+ 6 - 1
src/App.vue

@@ -39,5 +39,10 @@ onMounted(() => {
 </template>
 
 <style scoped>
-/* 全局样式可以在这里添加 */
+@media (min-width: 1024px) {
+  body {
+    display: flex;
+    place-items: center;
+  }
+}
 </style>

+ 11 - 0
src/api/indexPage.js

@@ -148,6 +148,17 @@ const museumApi = {
       method: 'post',
     })
   },
+
+  // 获取微信JSSDK配置
+  getWxJssdkConfig(url) {
+    return request({
+      url: '/museum/wxMini/getWxJssdkConfig',
+      method: 'get',
+      params: {
+        url: url,
+      },
+    })
+  },
 }
 
 export { museumApi }

BIN
src/assets/exhibition/online-kz.png


+ 2 - 8
src/assets/main.css

@@ -1,7 +1,7 @@
 @import './base.css';
 
 #app {
-  max-width: 1280px;
+  /* max-width: 1280px; */
   margin: 0 auto;
   padding: 0;
   font-weight: normal;
@@ -17,7 +17,7 @@ a,
   padding: 3px;
 }
 .home-tabar {
-  height: calc(100vh - 78px) !important;
+  height: calc(100vh - 90px) !important;
 }
 .notMargin {
   margin: 0 !important;
@@ -33,10 +33,4 @@ a,
     display: flex;
     place-items: center;
   }
-
-  #app {
-    display: grid;
-    grid-template-columns: 1fr 1fr;
-    padding: 0 2rem;
-  }
 }

+ 11 - 4
src/components/TabBar.vue

@@ -67,7 +67,7 @@ const switchTab = (path) => {
   const isPreviewMode = route.query.preview === '1'
 
   // 如果是预览模式且要跳转到'我的'页面,则阻止跳转
-  if (isPreviewMode && path === '/user') {
+  if (path === '/user') {
     return
   }
 
@@ -85,9 +85,9 @@ const switchTab = (path) => {
 
 <style lang="scss" scoped>
 .tab-bar {
-  position: fixed;
-  bottom: 0;
-  left: 0;
+  // position: fixed;
+  // bottom: 0;
+  // left: 0;
   width: 100%;
   height: 78px;
   display: flex;
@@ -123,4 +123,11 @@ const switchTab = (path) => {
   font-size: 14px;
   color: #412A12;
 }
+
+@media (min-width: 1024px) {
+  .tab-bar {
+    display: flex;
+    place-items: center;
+  }
+}
 </style>

+ 2 - 2
src/router/index.js

@@ -5,8 +5,8 @@ const router = createRouter({
   routes: [
     {
       path: '/',
-      name: 'loading',
-      component: () => import('@/views/loading/index.vue'),
+      name: 'root',
+      redirect: '/indexPage',
     },
     {
       path: '/indexPage',

+ 816 - 0
src/utils/jssdk.js

@@ -0,0 +1,816 @@
+;((e, n) => {
+  'function' == typeof define && (define.amd || define.cmd)
+    ? define(function () {
+        return n(e)
+      })
+    : n(e, !0)
+})(this, function (r, e) {
+  var a, c, n, i, t, o, s, d, l, u, p, f, m, g, h, S, y, I, v, _, w, T
+  if (!r.jWeixin)
+    return (
+      (a = {
+        config: 'preVerifyJSAPI',
+        onMenuShareTimeline: 'menu:share:timeline',
+        onMenuShareAppMessage: 'menu:share:appmessage',
+        onMenuShareQQ: 'menu:share:qq',
+        onMenuShareWeibo: 'menu:share:weiboApp',
+        onMenuShareQZone: 'menu:share:QZone',
+        previewImage: 'imagePreview',
+        getLocation: 'geoLocation',
+        openProductSpecificView: 'openProductViewWithPid',
+        addCard: 'batchAddCard',
+        openCard: 'batchViewCard',
+        chooseWXPay: 'getBrandWCPayRequest',
+        openEnterpriseRedPacket: 'getRecevieBizHongBaoRequest',
+        startSearchBeacons: 'startMonitoringBeacons',
+        stopSearchBeacons: 'stopMonitoringBeacons',
+        onSearchBeacons: 'onBeaconsInRange',
+        consumeAndShareCard: 'consumedShareCard',
+        openAddress: 'editAddress',
+      }),
+      (c = (() => {
+        var e,
+          n = {}
+        for (e in a) n[a[e]] = e
+        return n
+      })()),
+      (i = (n = r.document).title),
+      (t = navigator.userAgent.toLowerCase()),
+      (f = navigator.platform.toLowerCase()),
+      (o = !(!f.match('mac') && !f.match('win'))),
+      (s = -1 != t.indexOf('wxdebugger')),
+      (d = -1 != t.indexOf('micromessenger')),
+      (l = -1 != t.indexOf('android')),
+      (u = -1 != t.indexOf('iphone') || -1 != t.indexOf('ipad')),
+      (p = (f = t.match(/micromessenger\/(\d+\.\d+\.\d+)/) || t.match(/micromessenger\/(\d+\.\d+)/))
+        ? f[1]
+        : ''),
+      (m = { initStartTime: L(), initEndTime: 0, preVerifyStartTime: 0, preVerifyEndTime: 0 }),
+      (g = {
+        version: 1,
+        appId: '',
+        initTime: 0,
+        preVerifyTime: 0,
+        networkType: '',
+        isPreVerifyOk: 1,
+        systemType: u ? 1 : l ? 2 : -1,
+        clientVersion: p,
+        url: encodeURIComponent(location.href),
+      }),
+      (h = {}),
+      (S = { _completes: [] }),
+      (y = { state: 0, data: {} }),
+      O(function () {
+        m.initEndTime = L()
+      }),
+      (I = !1),
+      (v = []),
+      (_ = {
+        config: function (e) {
+          C('config', (h = e))
+          var o = !1 !== h.check
+          O(function () {
+            if (o)
+              k(
+                a.config,
+                { verifyJsApiList: A(h.jsApiList), verifyOpenTagList: A(h.openTagList) },
+                ((S._complete = function (e) {
+                  ;(m.preVerifyEndTime = L()), (y.state = 1), (y.data = e)
+                }),
+                (S.success = function (e) {
+                  g.isPreVerifyOk = 0
+                }),
+                (S.fail = function (e) {
+                  S._fail ? S._fail(e) : (y.state = -1)
+                }),
+                (t = S._completes).push(function () {
+                  B()
+                }),
+                (S.complete = function (e) {
+                  for (var n = 0, i = t.length; n < i; ++n) t[n]()
+                  S._completes = []
+                }),
+                S),
+              ),
+                (m.preVerifyStartTime = L())
+            else {
+              y.state = 1
+              for (var e = S._completes, n = 0, i = e.length; n < i; ++n) e[n]()
+              S._completes = []
+            }
+            var t
+          }),
+            _.invoke ||
+              ((_.invoke = function (e, n, i) {
+                r.WeixinJSBridge && WeixinJSBridge.invoke(e, P(n), i)
+              }),
+              (_.on = function (e, n) {
+                r.WeixinJSBridge && WeixinJSBridge.on(e, n)
+              }))
+        },
+        ready: function (e) {
+          ;(0 != y.state || (S._completes.push(e), !d && h.debug)) && e()
+        },
+        error: function (e) {
+          p < '6.0.2' || (-1 == y.state ? e(y.data) : (S._fail = e))
+        },
+        checkJsApi: function (e) {
+          k(
+            'checkJsApi',
+            { jsApiList: A(e.jsApiList) },
+            ((e._complete = function (e) {
+              l && (i = e.checkResult) && (e.checkResult = JSON.parse(i))
+              var n,
+                i = e,
+                t = i.checkResult
+              for (n in t) {
+                var o = c[n]
+                o && ((t[o] = t[n]), delete t[n])
+              }
+            }),
+            e),
+          )
+        },
+        onMenuShareTimeline: function (e) {
+          M(
+            a.onMenuShareTimeline,
+            {
+              complete: function () {
+                k(
+                  'shareTimeline',
+                  {
+                    title: e.title || i,
+                    desc: e.title || i,
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                    type: e.type || 'link',
+                    data_url: e.dataUrl || '',
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        onMenuShareAppMessage: function (n) {
+          M(
+            a.onMenuShareAppMessage,
+            {
+              complete: function (e) {
+                'favorite' === e.scene
+                  ? k('sendAppMessage', {
+                      title: n.title || i,
+                      desc: n.desc || '',
+                      link: n.link || location.href,
+                      img_url: n.imgUrl || '',
+                      type: n.type || 'link',
+                      data_url: n.dataUrl || '',
+                    })
+                  : k(
+                      'sendAppMessage',
+                      {
+                        title: n.title || i,
+                        desc: n.desc || '',
+                        link: n.link || location.href,
+                        img_url: n.imgUrl || '',
+                        type: n.type || 'link',
+                        data_url: n.dataUrl || '',
+                      },
+                      n,
+                    )
+              },
+            },
+            n,
+          )
+        },
+        onMenuShareQQ: function (e) {
+          M(
+            a.onMenuShareQQ,
+            {
+              complete: function () {
+                k(
+                  'shareQQ',
+                  {
+                    title: e.title || i,
+                    desc: e.desc || '',
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        onMenuShareWeibo: function (e) {
+          M(
+            a.onMenuShareWeibo,
+            {
+              complete: function () {
+                k(
+                  'shareWeiboApp',
+                  {
+                    title: e.title || i,
+                    desc: e.desc || '',
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        onMenuShareQZone: function (e) {
+          M(
+            a.onMenuShareQZone,
+            {
+              complete: function () {
+                k(
+                  'shareQZone',
+                  {
+                    title: e.title || i,
+                    desc: e.desc || '',
+                    img_url: e.imgUrl || '',
+                    link: e.link || location.href,
+                  },
+                  e,
+                )
+              },
+            },
+            e,
+          )
+        },
+        updateTimelineShareData: function (e) {
+          k('updateTimelineShareData', { title: e.title, link: e.link, imgUrl: e.imgUrl }, e)
+        },
+        updateAppMessageShareData: function (e) {
+          k(
+            'updateAppMessageShareData',
+            { title: e.title, desc: e.desc, link: e.link, imgUrl: e.imgUrl },
+            e,
+          )
+        },
+        startRecord: function (e) {
+          k('startRecord', {}, e)
+        },
+        stopRecord: function (e) {
+          k('stopRecord', {}, e)
+        },
+        onVoiceRecordEnd: function (e) {
+          M('onVoiceRecordEnd', e)
+        },
+        playVoice: function (e) {
+          k('playVoice', { localId: e.localId }, e)
+        },
+        pauseVoice: function (e) {
+          k('pauseVoice', { localId: e.localId }, e)
+        },
+        stopVoice: function (e) {
+          k('stopVoice', { localId: e.localId }, e)
+        },
+        onVoicePlayEnd: function (e) {
+          M('onVoicePlayEnd', e)
+        },
+        uploadVoice: function (e) {
+          k(
+            'uploadVoice',
+            { localId: e.localId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        downloadVoice: function (e) {
+          k(
+            'downloadVoice',
+            { serverId: e.serverId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        translateVoice: function (e) {
+          k(
+            'translateVoice',
+            { localId: e.localId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        chooseImage: function (e) {
+          k(
+            'chooseImage',
+            {
+              scene: '1|2',
+              count: e.count || 9,
+              sizeType: e.sizeType || ['original', 'compressed'],
+              sourceType: e.sourceType || ['album', 'camera'],
+            },
+            ((e._complete = function (e) {
+              if (l) {
+                var n = e.localIds
+                try {
+                  n && (e.localIds = JSON.parse(n))
+                } catch (e) {}
+              }
+            }),
+            e),
+          )
+        },
+        getLocation: function (e) {},
+        getLocation: function (e) {
+          ;(e = e || {}),
+            k(
+              a.getLocation,
+              { type: e.type || 'wgs84' },
+              ((e._complete = function (e) {
+                delete e.type
+              }),
+              e),
+            )
+        },
+        previewImage: function (e) {
+          k(a.previewImage, { current: e.current, urls: e.urls }, e)
+        },
+        uploadImage: function (e) {
+          k(
+            'uploadImage',
+            { localId: e.localId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        downloadImage: function (e) {
+          k(
+            'downloadImage',
+            { serverId: e.serverId, isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1 },
+            e,
+          )
+        },
+        getLocalImgData: function (e) {
+          !1 === I
+            ? ((I = !0),
+              k(
+                'getLocalImgData',
+                { localId: e.localId },
+                ((e._complete = function (e) {
+                  var n
+                  ;(I = !1), 0 < v.length && ((n = v.shift()), wx.getLocalImgData(n))
+                }),
+                e),
+              ))
+            : v.push(e)
+        },
+        getNetworkType: function (e) {
+          k(
+            'getNetworkType',
+            {},
+            ((e._complete = function (e) {
+              var n = e,
+                e = n.errMsg,
+                i = ((n.errMsg = 'getNetworkType:ok'), n.subtype)
+              if ((delete n.subtype, i)) n.networkType = i
+              else {
+                var i = e.indexOf(':'),
+                  t = e.substring(i + 1)
+                switch (t) {
+                  case 'wifi':
+                  case 'edge':
+                  case 'wwan':
+                    n.networkType = t
+                    break
+                  default:
+                    n.errMsg = 'getNetworkType:fail'
+                }
+              }
+            }),
+            e),
+          )
+        },
+        openLocation: function (e) {
+          k(
+            'openLocation',
+            {
+              latitude: e.latitude,
+              longitude: e.longitude,
+              name: e.name || '',
+              address: e.address || '',
+              scale: e.scale || 28,
+              infoUrl: e.infoUrl || '',
+            },
+            e,
+          )
+        },
+        hideOptionMenu: function (e) {
+          k('hideOptionMenu', {}, e)
+        },
+        showOptionMenu: function (e) {
+          k('showOptionMenu', {}, e)
+        },
+        closeWindow: function (e) {
+          k('closeWindow', {}, (e = e || {}))
+        },
+        hideMenuItems: function (e) {
+          k('hideMenuItems', { menuList: e.menuList }, e)
+        },
+        showMenuItems: function (e) {
+          k('showMenuItems', { menuList: e.menuList }, e)
+        },
+        hideAllNonBaseMenuItem: function (e) {
+          k('hideAllNonBaseMenuItem', {}, e)
+        },
+        showAllNonBaseMenuItem: function (e) {
+          k('showAllNonBaseMenuItem', {}, e)
+        },
+        scanQRCode: function (e) {
+          k(
+            'scanQRCode',
+            {
+              needResult: (e = e || {}).needResult || 0,
+              scanType: e.scanType || ['qrCode', 'barCode'],
+            },
+            ((e._complete = function (e) {
+              var n
+              u &&
+                (n = e.resultStr) &&
+                ((n = JSON.parse(n)), (e.resultStr = n && n.scan_code && n.scan_code.scan_result))
+            }),
+            e),
+          )
+        },
+        openAddress: function (e) {
+          k(
+            a.openAddress,
+            {},
+            ((e._complete = function (e) {
+              ;((e = e).postalCode = e.addressPostalCode),
+                delete e.addressPostalCode,
+                (e.provinceName = e.proviceFirstStageName),
+                delete e.proviceFirstStageName,
+                (e.cityName = e.addressCitySecondStageName),
+                delete e.addressCitySecondStageName,
+                (e.countryName = e.addressCountiesThirdStageName),
+                delete e.addressCountiesThirdStageName,
+                (e.detailInfo = e.addressDetailInfo),
+                delete e.addressDetailInfo
+            }),
+            e),
+          )
+        },
+        openProductSpecificView: function (e) {
+          k(
+            a.openProductSpecificView,
+            { pid: e.productId, view_type: e.viewType || 0, ext_info: e.extInfo },
+            e,
+          )
+        },
+        addCard: function (e) {
+          for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+            var r = n[t],
+              r = { card_id: r.cardId, card_ext: r.cardExt }
+            i.push(r)
+          }
+          k(
+            a.addCard,
+            { card_list: i },
+            ((e._complete = function (e) {
+              if ((n = e.card_list)) {
+                for (var n, i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
+                  var o = n[i]
+                  ;(o.cardId = o.card_id),
+                    (o.cardExt = o.card_ext),
+                    (o.isSuccess = !!o.is_succ),
+                    delete o.card_id,
+                    delete o.card_ext,
+                    delete o.is_succ
+                }
+                ;(e.cardList = n), delete e.card_list
+              }
+            }),
+            e),
+          )
+        },
+        chooseCard: function (e) {
+          k(
+            'chooseCard',
+            {
+              app_id: h.appId,
+              location_id: e.shopId || '',
+              sign_type: e.signType || 'SHA1',
+              card_id: e.cardId || '',
+              card_type: e.cardType || '',
+              card_sign: e.cardSign,
+              time_stamp: e.timestamp + '',
+              nonce_str: e.nonceStr,
+            },
+            ((e._complete = function (e) {
+              ;(e.cardList = e.choose_card_info), delete e.choose_card_info
+            }),
+            e),
+          )
+        },
+        openCard: function (e) {
+          for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
+            var r = n[t],
+              r = { card_id: r.cardId, code: r.code }
+            i.push(r)
+          }
+          k(a.openCard, { card_list: i }, e)
+        },
+        consumeAndShareCard: function (e) {
+          k(a.consumeAndShareCard, { consumedCardId: e.cardId, consumedCode: e.code }, e)
+        },
+        chooseWXPay: function (e) {
+          k(a.chooseWXPay, x(e), e), B({ jsApiName: 'chooseWXPay' })
+        },
+        openEnterpriseRedPacket: function (e) {
+          k(a.openEnterpriseRedPacket, x(e), e)
+        },
+        startSearchBeacons: function (e) {
+          k(a.startSearchBeacons, { ticket: e.ticket }, e)
+        },
+        stopSearchBeacons: function (e) {
+          k(a.stopSearchBeacons, {}, e)
+        },
+        onSearchBeacons: function (e) {
+          M(a.onSearchBeacons, e)
+        },
+        openEnterpriseChat: function (e) {
+          k('openEnterpriseChat', { useridlist: e.userIds, chatname: e.groupName }, e)
+        },
+        launchMiniProgram: function (e) {
+          k(
+            'launchMiniProgram',
+            {
+              targetAppId: e.targetAppId,
+              path: ((e) => {
+                var n
+                if ('string' == typeof e && 0 < e.length)
+                  return (
+                    (n = e.split('?')[0]),
+                    (n += '.html'),
+                    void 0 !== (e = e.split('?')[1]) ? n + '?' + e : n
+                  )
+              })(e.path),
+              envVersion: e.envVersion,
+            },
+            e,
+          )
+        },
+        openBusinessView: function (e) {
+          k(
+            'openBusinessView',
+            {
+              businessType: e.businessType,
+              queryString: e.queryString || '',
+              envVersion: e.envVersion,
+            },
+            ((e._complete = function (n) {
+              if (l) {
+                var e = n.extraData
+                if (e)
+                  try {
+                    n.extraData = JSON.parse(e)
+                  } catch (e) {
+                    n.extraData = {}
+                  }
+              }
+            }),
+            e),
+          )
+        },
+        miniProgram: {
+          navigateBack: function (e) {
+            ;(e = e || {}),
+              O(function () {
+                k('invokeMiniProgramAPI', { name: 'navigateBack', arg: { delta: e.delta || 1 } }, e)
+              })
+          },
+          navigateTo: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'navigateTo', arg: { url: e.url } }, e)
+            })
+          },
+          redirectTo: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'redirectTo', arg: { url: e.url } }, e)
+            })
+          },
+          switchTab: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'switchTab', arg: { url: e.url } }, e)
+            })
+          },
+          reLaunch: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'reLaunch', arg: { url: e.url } }, e)
+            })
+          },
+          postMessage: function (e) {
+            O(function () {
+              k('invokeMiniProgramAPI', { name: 'postMessage', arg: e.data || {} }, e)
+            })
+          },
+          getEnv: function (e) {
+            O(function () {
+              e({ miniprogram: 'miniprogram' === r.__wxjs_environment })
+            })
+          },
+        },
+      }),
+      (w = 1),
+      (T = {}),
+      n.addEventListener(
+        'error',
+        function (e) {
+          var n, i, t
+          l ||
+            ((t = (n = e.target).tagName),
+            (i = n.src),
+            'IMG' != t && 'VIDEO' != t && 'AUDIO' != t && 'SOURCE' != t) ||
+            (-1 != i.indexOf('wxlocalresource://') &&
+              (e.preventDefault(),
+              e.stopPropagation(),
+              (t = n['wx-id']) || ((t = w++), (n['wx-id'] = t)),
+              T[t] ||
+                ((T[t] = !0),
+                wx.ready(function () {
+                  wx.getLocalImgData({
+                    localId: i,
+                    success: function (e) {
+                      n.src = e.localData
+                    },
+                  })
+                }))))
+        },
+        !0,
+      ),
+      n.addEventListener(
+        'load',
+        function (e) {
+          var n
+          l ||
+            ((n = (e = e.target).tagName),
+            'IMG' != n && 'VIDEO' != n && 'AUDIO' != n && 'SOURCE' != n) ||
+            ((n = e['wx-id']) && (T[n] = !1))
+        },
+        !0,
+      ),
+      e && (r.wx = r.jWeixin = _),
+      _
+    )
+  function k(n, e, i) {
+    r.WeixinJSBridge
+      ? WeixinJSBridge.invoke(n, P(e), function (e) {
+          V(n, e, i)
+        })
+      : C(n, i)
+  }
+  function M(n, i, t) {
+    r.WeixinJSBridge
+      ? WeixinJSBridge.on(n, function (e) {
+          t && t.trigger && t.trigger(e), V(n, e, i)
+        })
+      : C(n, t || i)
+  }
+  function P(e) {
+    return (
+      ((e = e || {}).appId = h.appId),
+      (e.verifyAppId = h.appId),
+      (e.verifySignType = 'sha1'),
+      (e.verifyTimestamp = h.timestamp + ''),
+      (e.verifyNonceStr = h.nonceStr),
+      (e.verifySignature = h.signature),
+      e
+    )
+  }
+  function x(e) {
+    return {
+      timeStamp: e.timestamp + '',
+      nonceStr: e.nonceStr,
+      package: e.package,
+      paySign: e.paySign,
+      signType: e.signType || 'SHA1',
+    }
+  }
+  function V(e, n, i) {
+    ;('openEnterpriseChat' != e && 'openBusinessView' !== e) || (n.errCode = n.err_code),
+      delete n.err_code,
+      delete n.err_desc,
+      delete n.err_detail
+    var t = n.errMsg,
+      e =
+        (t ||
+          ((t = n.err_msg),
+          delete n.err_msg,
+          (t = ((e, n) => {
+            var i,
+              t = c[e]
+            return (
+              t && (e = t),
+              (t = 'ok'),
+              n &&
+                ((i = n.indexOf(':')),
+                ('access denied' !=
+                  (t = (t = (t =
+                    -1 !=
+                    (t =
+                      -1 !=
+                      (t =
+                        'failed' == (t = 'confirm' == (t = n.substring(i + 1)) ? 'ok' : t)
+                          ? 'fail'
+                          : t).indexOf('failed_')
+                        ? t.substring(7)
+                        : t).indexOf('fail_')
+                      ? t.substring(5)
+                      : t).replace(/_/g, ' ')).toLowerCase()) &&
+                  'no permission to execute' != t) ||
+                  (t = 'permission denied'),
+                '' == (t = 'config' == e && 'function not exist' == t ? 'ok' : t)) &&
+                (t = 'fail'),
+              (n = e + ':' + t)
+            )
+          })(e, t)),
+          (n.errMsg = t)),
+        (i = i || {})._complete && (i._complete(n), delete i._complete),
+        (t = n.errMsg || ''),
+        h.debug && !i.isInnerInvoke && alert(JSON.stringify(n)),
+        t.indexOf(':'))
+    switch (t.substring(e + 1)) {
+      case 'ok':
+        i.success && i.success(n)
+        break
+      case 'cancel':
+        i.cancel && i.cancel(n)
+        break
+      default:
+        i.fail && i.fail(n)
+    }
+    i.complete && i.complete(n)
+  }
+  function A(e) {
+    if (e) {
+      for (var n = 0, i = e.length; n < i; ++n) {
+        var t = e[n],
+          t = a[t]
+        t && (e[n] = t)
+      }
+      return e
+    }
+  }
+  function C(e, n) {
+    var i
+    !h.debug ||
+      (n && n.isInnerInvoke) ||
+      ((i = c[e]) && (e = i),
+      n && n._complete && delete n._complete,
+      console.log('"' + e + '",', n || ''))
+  }
+  function B(n) {
+    var i
+    o ||
+      s ||
+      h.debug ||
+      p < '6.0.2' ||
+      g.systemType < 0 ||
+      ((i = new Image()),
+      (g.appId = h.appId),
+      (g.initTime = m.initEndTime - m.initStartTime),
+      (g.preVerifyTime = m.preVerifyEndTime - m.preVerifyStartTime),
+      _.getNetworkType({
+        isInnerInvoke: !0,
+        success: function (e) {
+          g.networkType = e.networkType
+          e =
+            'https://open.weixin.qq.com/sdk/report?v=' +
+            g.version +
+            '&o=' +
+            g.isPreVerifyOk +
+            '&s=' +
+            g.systemType +
+            '&c=' +
+            g.clientVersion +
+            '&a=' +
+            g.appId +
+            '&n=' +
+            g.networkType +
+            '&i=' +
+            g.initTime +
+            '&p=' +
+            g.preVerifyTime +
+            '&u=' +
+            g.url +
+            '&jsapi_name=' +
+            (n ? n.jsApiName : '')
+          i.src = e
+        },
+      }))
+  }
+  function L() {
+    return new Date().getTime()
+  }
+  function O(e) {
+    d &&
+      (r.WeixinJSBridge
+        ? e()
+        : n.addEventListener && n.addEventListener('WeixinJSBridgeReady', e, !1))
+  }
+})

+ 39 - 8
src/views/collection/collectDetail.vue

@@ -25,11 +25,15 @@
       <!-- 模型展示 -->
       <div v-if="activeTab === 'model'" class="model-viewer">
         <div class="model-container">
-          <iframe id="ifr" :src="`/src/utils/modelLoad/model.html?m=${getFieldValue(artifactData, 'modelFile')}`"
+          <iframe id="ifr" v-if="getFieldValue(artifactData, 'modelFile')"
+            :src="`https://sit-kelamayi.4dage.com/model.html?m=${getFieldValue(artifactData, 'modelFile')}`"
             frameborder="0"></iframe>
+          <div v-else class="no-video">
+            <div class="no-video-text">暂无模型</div>
+          </div>
         </div>
         <!-- 放大镜图标 -->
-        <div class="zoom-icon" @click="toggleZoom">
+        <div v-if="getFieldValue(artifactData, 'modelFile')" class="zoom-icon" @click="toggleZoom">
           <el-icon :size="24">
             <ZoomIn v-if="!isZoomed" />
             <ZoomOut v-else />
@@ -40,8 +44,8 @@
       <!-- 视频展示 -->
       <div v-if="activeTab === 'video'" class="video-viewer">
         <div class="video-container">
-          <video style="height: 96%;" v-if="getFieldValue(artifactData, 'videoFile')" controls
-            :poster="getFieldValue(artifactData, 'img')">
+          <video width="320" height="240" v-if="getFieldValue(artifactData, 'videoFile')" controls
+            x5-video-player-type="h5" playsinline webkit-playsinline>
             <source :src="getFieldValue(artifactData, 'videoFile')" type="video/mp4">
             您的浏览器不支持视频播放。
           </video>
@@ -56,13 +60,13 @@
         <div class="image-container">
           <el-carousel
             v-if="getFieldValue(artifactData, 'imageFiles') && getFieldValue(artifactData, 'imageFiles').length > 0"
-            height="100%" indicator-position="outside" arrow="hover">
+            height="90%" indicator-position="outside" arrow="hover">
             <el-carousel-item v-for="(image, index) in getFieldValue(artifactData, 'imageFiles')" :key="index">
               <img :src="image" :alt="`文物图片${index + 1}`" class="carousel-image">
             </el-carousel-item>
           </el-carousel>
-          <div v-else class="no-image">
-            <img src="@/assets/indexPage/zhanweitu.png" alt="暂无图片" class="placeholder-image">
+          <div v-else class="no-video">
+            <div class="no-video-text">暂无图片</div>
           </div>
         </div>
       </div>
@@ -191,7 +195,7 @@ onMounted(() => {
 }
 
 .top-navigation {
-  position: fixed;
+  position: absolute;
   top: 0;
   left: 0;
   right: 0;
@@ -201,6 +205,16 @@ onMounted(() => {
   z-index: 100;
 }
 
+@media (min-width: 1024px) {
+  .collect-detail-container {
+    width: 400px;
+  }
+
+  .top-navigation {
+    max-width: 400px;
+  }
+}
+
 .back-button {
   width: 40px;
   height: 40px;
@@ -323,6 +337,12 @@ onMounted(() => {
   }
 }
 
+.video-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
 .zoom-icon {
   position: absolute;
   bottom: 36px;
@@ -423,4 +443,15 @@ onMounted(() => {
     }
   }
 }
+
+.no-video {
+  height: 96%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  .no-video-text {
+    color: #fff;
+  }
+}
 </style>

+ 7 - 1
src/views/collection/index.vue

@@ -183,6 +183,12 @@ onMounted(async () => {
   box-sizing: border-box;
 }
 
+@media (min-width: 1024px) {
+  .collection-container {
+    width: 400px;
+  }
+}
+
 .top-section {
   position: sticky;
   top: 0;
@@ -267,7 +273,7 @@ onMounted(async () => {
 
 .content-section {
   padding: 15px;
-  height: calc(100vh - 200px);
+  height: calc(100vh - 230px);
   overflow-y: auto;
   -webkit-overflow-scrolling: touch;
 }

+ 69 - 19
src/views/exhibition/allDetailsShow.vue

@@ -13,11 +13,12 @@
     <!-- 详情内容 -->
     <div v-else-if="detailData" :class="['detail-content', isFrom == 'weixin' ? 'notMargin' : '']">
       <!--标题 -->
-      <div class=" detail-title">{{ detailData.title || '克拉玛依市博物馆' }}</div>
+      <div class=" detail-title">{{ (isPreviewMode && detailData.titleB) ? detailData.titleB : (detailData.title ||
+        '克拉玛依市博物馆') }}</div>
 
       <!-- 时间 -->
-      <div class="detail-time" v-if="fromtype != 'museum' && (detailData.createTime || detailData.publishTime)">
-        {{ formatTimeWithDash(detailData.createTime || detailData.publishTime) }}
+      <div class="detail-time" v-if="fromtype != 'museum' && (detailData.publish || detailData.publishB)">
+        {{ formatTimeWithDash(isPreviewMode ? (detailData.publishB || detailData.publish) : detailData.publish) }}
       </div>
       <div v-else class="line"></div>
       <!-- 主图 -->
@@ -26,21 +27,22 @@
       </div> -->
 
       <!-- 处理后的内容 -->
-      <div class="detail-text" v-if="detailData.content || detailData.context">
+      <div class="detail-text" v-if="isPreviewMode ? (detailData.contextB || detailData.context) : detailData.context">
         <div v-html="processedContent" class="processed-html-content"></div>
       </div>
 
-      <!-- 描述 -->
-      <div class="detail-description" v-else-if="detailData.description">
-        {{ detailData.description }}
-      </div>
-
       <!-- 展览特有按钮 -->
-      <div class="exhibition-actions" v-if="fromtype === 'exhibition'">
-        <button class="online-exhibition-btn" @click="goToOnlineExhibition">
-          <img src="@/assets/exhibition/icon_in.png" alt="线上观展" class="btn-icon">
+      <div class="exhibition-actions"
+        v-if="fromtype === 'exhibition' && ((isPreviewMode && detailData.webSiteB) || detailData.webSite)">
+        <div class="online-exhibition-btn" @click="goToOnlineExhibition(detailData)">
+          <img src="@/assets/exhibition/online-kz.png" alt="线上观展" class="btn-icon">
           线上观展
-        </button>
+        </div>
+      </div>
+      <div v-if="detailData.personCount > 0 && fromtype == 'activity'" class="active-preview-btn">
+        <a class="preview-btn">
+          活动预约
+        </a>
       </div>
     </div>
 
@@ -69,7 +71,7 @@ const isFrom = ref('')
 
 // 检查是否为预览模式
 const isPreviewMode = computed(() => {
-  return route.query.preview === '1'
+  return route.query.preview == '1'
 })
 
 // 处理后的HTML内容
@@ -108,10 +110,18 @@ const goBack = () => {
 }
 
 // 跳转到线上观展
-const goToOnlineExhibition = () => {
-  // 这里可以根据实际需求跳转到线上观展页面
-  // 例如:router.push('/online-exhibition/' + detailData.value.id)
-  console.log('跳转到线上观展', detailData.value)
+const goToOnlineExhibition = (detailData) => {
+  let targetUrl
+  // 如果URL包含preview=1参数,优先使用webSiteB
+  if (isPreviewMode.value && detailData.webSiteB) {
+    targetUrl = detailData.webSiteB
+  } else {
+    targetUrl = detailData.webSite
+  }
+
+  if (targetUrl) {
+    window.open(targetUrl, '_blank')
+  }
 }
 
 // 加载详情数据
@@ -176,12 +186,18 @@ onMounted(() => {
 .detail-container {
   position: relative;
   height: 100vh;
-  padding: 20px;
+  padding: 20px 20px 40px 20px;
   background: url('@/assets/indexPage/bg.png') no-repeat;
   background-size: cover;
   overflow-y: auto;
 }
 
+@media (min-width: 1024px) {
+  .detail-container {
+    width: 400px;
+  }
+}
+
 .back-button {
   position: absolute;
   top: 20px;
@@ -334,6 +350,31 @@ onMounted(() => {
   }
 }
 
+.active-preview-btn {
+  height: 60px;
+  position: fixed;
+  bottom: 14px;
+  left: 0;
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-top: 30px;
+
+  .preview-btn {
+    display: inline-block;
+    width: 320px;
+    height: 60px;
+    background: #B1967B;
+    width: 280px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    border-radius: 50px;
+  }
+}
+
 /* 处理后的HTML内容样式 */
 .processed-html-content {
 
@@ -364,6 +405,10 @@ onMounted(() => {
     transition: transform 0.3s ease;
   }
 
+  :deep(.image-wrap) {
+    width: 100%;
+  }
+
   :deep(.content-image:hover) {
     transform: scale(1.02);
   }
@@ -377,10 +422,15 @@ onMounted(() => {
 
   /* 处理后的视频容器样式 */
   :deep(.processed-video) {
+    width: 100%;
     margin: 20px 0;
     text-align: center;
   }
 
+  :deep(.video-wrap) {
+    width: 100%;
+  }
+
   /* 通用媒体容器样式 */
   :deep(.media-wrap) {
     position: relative;

+ 50 - 22
src/views/exhibition/index.vue

@@ -2,10 +2,13 @@
   <div :class="['exhibition-container', !isFromParam ? 'home-tabar' : '']">
     <!-- 轮播图部分 -->
     <div class="carousel-section">
-      <el-carousel type="card" height="160px" indicator-position="none" :interval="5000">
+      <el-carousel height="160px" :interval="4000">
         <el-carousel-item v-for="(item, index) in carouselList" :key="index" @click="goToDetail(item.exhibitId)">
-          <img :src="getFieldValue(item, 'img') || '@/assets/indexPage/zhanweitu.png'" alt="展览图片"
-            class="carousel-img" />
+          <img :src="getFieldValue(item, 'img')" alt="展览图片" class="carousel-img" />
+          <div class="online-exhibition" v-if="getFieldValue(item, 'webSite')" @click.stop="goToOnlineExhibition(item)">
+            <img class="online-icon" src="@/assets/exhibition/online-kz.png" alt="线上观展" />
+            <span class="online-text">线上观展</span>
+          </div>
         </el-carousel-item>
       </el-carousel>
     </div>
@@ -173,16 +176,33 @@ const handleScroll = async () => {
 
 // 跳转到详情页面
 const goToDetail = (id) => {
+  const query = {
+    id: id,
+    type: 'exhibition',
+    isFromPage: 'exhibition'
+  }
+
+  // 如果当前页面有preview=1参数,跳转时也要带上
+  if (isPreviewMode.value) {
+    query.preview = '1'
+  }
+
   router.push({
     path: '/allDetailsShow',
-    query: {
-      id: id,
-      type: 'exhibition',
-      isFromPage: 'exhibition'
-    }
+    query: query
   })
 }
-
+const goToOnlineExhibition = (item) => {
+  let url;
+  if (isPreviewMode.value) {
+    url = item.webSiteB || item.webSite
+  } else {
+    url = item.webSite
+  }
+  if (url) {
+    window.open(url, '_blank')
+  }
+}
 // 初始化
 onMounted(async () => {
   // 获取轮播图数据
@@ -196,31 +216,39 @@ onMounted(async () => {
 <style lang="scss" scoped>
 .exhibition-container {
   height: calc(100vh); // 减去底部导航栏高度
-  padding-top: 16px;
   overflow-y: auto;
   background: url('@/assets/indexPage/bg.png') no-repeat;
   background-size: cover;
   box-sizing: border-box;
 }
 
+@media (min-width: 1024px) {
+  .exhibition-container {
+    width: 400px;
+  }
+}
+
 .carousel-section {
   margin-bottom: 20px;
 
-  :deep(.el-carousel__item--card) {
-    width: 80%;
-  }
-
-  :deep(.el-carousel__item) {
-    border-radius: 8px;
-    overflow: hidden;
+  :depp(.el-carousel__item) {
+    position: relative;
   }
 
-  :deep(.el-carousel__item--card.is-active) {
-    transform: translateX(46.5px) scale(1) !important;
-  }
+  .online-exhibition {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    cursor: pointer;
+    z-index: 1;
 
-  :deep(.el-carousel__container) {
-    margin-left: -12px;
+    .online-text {
+      color: #fff;
+    }
   }
 }
 

+ 8 - 2
src/views/indexPage/activePreview.vue

@@ -79,14 +79,20 @@ const goToActivePage = () => {
 .active-preview-container {
   height: 100vh;
   padding-bottom: 78px;
-  background: linear-gradient(180deg, #F5EEE2 0%, #E0D2B4 100%), linear-gradient(180deg, rgba(224, 210, 180, 0) 0%, #E0D2B4 100%);
+  background: url('@/assets/indexPage/bg.png') no-repeat;
   background-size: cover;
-  background-position: center;
+  box-sizing: border-box;
   position: relative;
   color: #412A12;
   overflow-y: auto;
 }
 
+@media (min-width: 1024px) {
+  .active-preview-container {
+    width: 400px;
+  }
+}
+
 .back-button {
   position: absolute;
   top: 20px;

+ 18 - 9
src/views/indexPage/components/activePage.vue

@@ -5,9 +5,9 @@
       <div class="divider"></div>
       <div class="select-moon">
         <div class="morning-moon">
-          <button class="next-btn" @click="goNext">
+          <div class="next-btn" @click="goNext">
             下一步
-          </button>
+          </div>
         </div>
       </div>
     </div>
@@ -50,7 +50,7 @@ export default defineComponent({
 <style lang="scss" scoped>
 .preview-contain {
   height: 100vh;
-  background: url('@/assets/indexPage/bg.png') no-repeat center center;
+  background: url('@/assets/indexPage/bg.png') no-repeat;
   background-size: cover;
   overflow: auto;
 
@@ -67,9 +67,9 @@ export default defineComponent({
   }
 
   .select-moon {
-    position: fixed;
-    width: 90%;
-    bottom: 24px;
+    // position: fixed;
+    // width: 90%;
+    // bottom: 24px;
     margin-top: 16px;
 
     .moon-time {
@@ -81,8 +81,7 @@ export default defineComponent({
 
     .morning-moon {
       display: flex;
-      flex-direction: column;
-      gap: 12px;
+      width: 100%; // 确保按钮占满父元素的宽度
 
       .time-card {
         position: relative;
@@ -139,6 +138,10 @@ export default defineComponent({
       }
 
       .next-btn {
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
         background: #B1967B;
         color: white;
         border: none;
@@ -150,6 +153,7 @@ export default defineComponent({
         margin-top: 20px;
         transition: all 0.3s ease;
 
+
         &:disabled {
           background: #ccc;
           cursor: not-allowed;
@@ -162,4 +166,9 @@ export default defineComponent({
     }
   }
 }
-</style>
+
+// @media (min-width: 1024px) {
+//   .preview-contain {
+//     width: 400px;
+//   }
+// }</style>

+ 19 - 12
src/views/indexPage/components/activePeople.vue

@@ -69,7 +69,7 @@
 
       <!-- 下一步按钮 -->
       <div class="next-button-container">
-        <button class="next-btn" @click="submitReservation" :disabled="!isFormValid">下一步</button>
+        <div class="next-btn" @click="submitReservation" :disabled="!isFormValid">下一步</div>
       </div>
     </div>
 
@@ -89,7 +89,7 @@
         </div>
       </div>
       <div class="existing-actions">
-        <button class="confirm-btn" @click="confirmExistingVisitors">确定</button>
+        <div class="confirm-btn" @click="confirmExistingVisitors">确定</div>
       </div>
     </div>
 
@@ -512,14 +512,17 @@ onMounted(() => {
 }
 
 .existing-actions {
-  position: fixed;
-  bottom: 20px;
-  left: 20px;
-  right: 20px;
-  z-index: 100;
+  // position: fixed;
+  // bottom: 20px;
+  // left: 20px;
+  // right: 20px;
+  // z-index: 100;
 }
 
 .confirm-btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
   width: 100%;
   padding: 15px;
   background-color: #B1967B;
@@ -531,14 +534,18 @@ onMounted(() => {
 }
 
 .next-button-container {
-  position: fixed;
-  bottom: 20px;
-  left: 20px;
-  right: 20px;
-  z-index: 100;
+  padding: 24px 24px 0 24px;
+  // position: fixed;
+  // bottom: 20px;
+  // left: 20px;
+  // right: 20px;
+  // z-index: 100;
 }
 
 .next-btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
   width: 100%;
   padding: 15px;
   background-color: #B1967B;

+ 63 - 62
src/views/indexPage/components/visitPeople.vue

@@ -22,19 +22,17 @@
         <div v-for="(visitor, index) in visitors" :key="index" class="visitor-card">
           <div class="visitor-header">
             <span class="visitor-title">参观人信息{{ index + 1 }}</span>
-            <button class="delete-btn" @click="removeVisitor(index)"><el-icon :size="20"><Delete style="margin-right: 4px;" /></el-icon>删除</button>
+            <button class="delete-btn" @click="removeVisitor(index)"><el-icon :size="20">
+                <Delete style="margin-right: 4px;" />
+              </el-icon>删除</button>
           </div>
-          
+
           <el-form :model="visitor" class="visitor-form">
             <div class="form-item">
               <div class="form-label">姓名</div>
               <div class="form-input">
-                <el-input 
-                  v-model="visitor.name" 
-                  placeholder="请输入您的姓名"
-                  @blur="validateName(index)"
-                  :class="['bottom-line-input', visitor.nameError ? 'error-line' : '']"
-                />
+                <el-input v-model="visitor.name" placeholder="请输入您的姓名" @blur="validateName(index)"
+                  :class="['bottom-line-input', visitor.nameError ? 'error-line' : '']" />
                 <div v-if="visitor.nameError" class="error-msg">{{ visitor.nameError }}</div>
               </div>
             </div>
@@ -42,12 +40,8 @@
             <div class="form-item">
               <div class="form-label">电话号码</div>
               <div class="form-input">
-                <el-input 
-                  v-model="visitor.phone" 
-                  placeholder="请输入11位数字"
-                  @blur="validatePhone(index)"
-                  :class="['bottom-line-input', visitor.phoneError ? 'error-line' : '']"
-                />
+                <el-input v-model="visitor.phone" placeholder="请输入11位数字" @blur="validatePhone(index)"
+                  :class="['bottom-line-input', visitor.phoneError ? 'error-line' : '']" />
                 <div v-if="visitor.phoneError" class="error-msg">{{ visitor.phoneError }}</div>
               </div>
             </div>
@@ -55,11 +49,7 @@
             <div class="form-item">
               <div class="form-label">证件类型</div>
               <div class="form-input">
-                <el-select 
-                  v-model="visitor.idType" 
-                  placeholder="请选择证件类型"
-                  :class="['bottom-line-select']"
-                >
+                <el-select v-model="visitor.idType" placeholder="请选择证件类型" :class="['bottom-line-select']">
                   <el-option label="身份证" value="身份证" />
                 </el-select>
               </div>
@@ -68,12 +58,8 @@
             <div class="form-item">
               <div class="form-label">证件号码</div>
               <div class="form-input">
-                <el-input 
-                  v-model="visitor.idNumber" 
-                  placeholder="请输入18位证件编码"
-                  @blur="validateIdNumber(index)"
-                  :class="['bottom-line-input', visitor.idNumberError ? 'error-line' : '']"
-                />
+                <el-input v-model="visitor.idNumber" placeholder="请输入18位证件编码" @blur="validateIdNumber(index)"
+                  :class="['bottom-line-input', visitor.idNumberError ? 'error-line' : '']" />
                 <div v-if="visitor.idNumberError" class="error-msg">{{ visitor.idNumberError }}</div>
               </div>
             </div>
@@ -83,19 +69,15 @@
 
       <!-- 下一步按钮 -->
       <div class="next-button-container">
-        <button class="next-btn" @click="submitReservation" :disabled="!isFormValid">下一步</button>
+        <div class="next-btn" @click="submitReservation" :disabled="!isFormValid">下一步</div>
       </div>
     </div>
 
     <!-- 选择已有参观人页面 -->
     <div v-if="showExistingPage" class="existing-page">
       <div class="existing-visitors-list">
-        <div 
-          v-for="(existingVisitor, index) in existingVisitors" 
-          :key="index" 
-          class="existing-visitor-item"
-          @click="toggleExistingVisitor(index)"
-        >
+        <div v-for="(existingVisitor, index) in existingVisitors" :key="index" class="existing-visitor-item"
+          @click="toggleExistingVisitor(index)">
           <div class="visitor-info">
             <div class="visitor-name">姓名:{{ existingVisitor.name }}</div>
             <div class="visitor-id">证件号:{{ existingVisitor.idNumber }}</div>
@@ -107,7 +89,7 @@
         </div>
       </div>
       <div class="existing-actions">
-        <button class="confirm-btn" @click="confirmExistingVisitors">确定</button>
+        <div class="confirm-btn" @click="confirmExistingVisitors">确定</div>
       </div>
     </div>
 
@@ -115,7 +97,9 @@
     <div v-if="showSuccessModal" class="modal-overlay" @click="closeSuccessModal">
       <div class="success-modal" @click.stop>
         <div class="success-icon">
-          <el-icon :size="40"><Check /></el-icon>
+          <el-icon :size="40">
+            <Check />
+          </el-icon>
         </div>
         <div class="success-text">预约成功</div>
         <button class="success-btn" @click="closeSuccessModal">确认</button>
@@ -156,12 +140,12 @@ const existingVisitors = ref([
 // 计算属性
 const isFormValid = computed(() => {
   if (visitors.value.length === 0) return false
-  return visitors.value.every(visitor => 
-    visitor.name && 
-    visitor.phone && 
-    visitor.idNumber && 
-    !visitor.nameError && 
-    !visitor.phoneError && 
+  return visitors.value.every(visitor =>
+    visitor.name &&
+    visitor.phone &&
+    visitor.idNumber &&
+    !visitor.nameError &&
+    !visitor.phoneError &&
     !visitor.idNumberError
   )
 })
@@ -232,7 +216,7 @@ const toggleExistingVisitor = (index) => {
 
 const confirmExistingVisitors = () => {
   const selectedVisitors = existingVisitors.value.filter(visitor => visitor.selected)
-  
+
   selectedVisitors.forEach(existingVisitor => {
     if (visitors.value.length < 5) {
       visitors.value.push({
@@ -246,12 +230,12 @@ const confirmExistingVisitors = () => {
       })
     }
   })
-  
+
   // 重置选择状态
   existingVisitors.value.forEach(visitor => {
     visitor.selected = false
   })
-  
+
   // 隐藏已有参观人页面,回到新增参观人页面
   showExistingPage.value = false
 }
@@ -261,11 +245,11 @@ const submitReservation = async () => {
     alert('请完善所有参观人信息')
     return
   }
-  
+
   try {
     // 模拟API调用
     await new Promise(resolve => setTimeout(resolve, 1000))
-    
+
     // 显示成功弹窗
     showSuccessModal.value = true
   } catch (error) {
@@ -293,11 +277,13 @@ onMounted(() => {
 
 .date-info {
   position: relative;
-  .bg-img{
+
+  .bg-img {
     width: 100%;
     height: 100%;
     object-fit: cover;
   }
+
   margin: 16px;
 }
 
@@ -311,11 +297,13 @@ onMounted(() => {
   text-align: left;
 }
 
-.date-label, .time-label {
+.date-label,
+.time-label {
   font-size: 16px;
   color: #333;
   margin: 5px 0;
-  .title{
+
+  .title {
     color: #B1967B;
   }
 }
@@ -327,7 +315,8 @@ onMounted(() => {
   margin-bottom: 20px;
 }
 
-.add-new-btn, .select-existing-btn {
+.add-new-btn,
+.select-existing-btn {
   flex: 1;
   padding: 12px;
   border: none;
@@ -358,7 +347,7 @@ onMounted(() => {
   border-radius: 8px;
   padding: 20px 20px 10px 20px;
   margin-bottom: 15px;
-  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
 
 .visitor-header {
@@ -420,6 +409,7 @@ onMounted(() => {
   box-shadow: none;
   background: transparent;
 }
+
 .bottom-line-input :deep(.el-input__inner) {
   text-align: right;
 }
@@ -432,6 +422,7 @@ onMounted(() => {
   border-bottom-color: rgba(88, 71, 53, 0.6);
   box-shadow: none;
 }
+
 .error-line :deep(.el-input__wrapper) {
   border-bottom-color: #F45151;
   box-shadow: none;
@@ -454,6 +445,7 @@ onMounted(() => {
   border-bottom-color: rgba(88, 71, 53, 0.6);
   box-shadow: none;
 }
+
 .error-line :deep(.el-select__wrapper) {
   border-bottom-color: #F45151;
   box-shadow: none;
@@ -485,7 +477,7 @@ onMounted(() => {
   border-radius: 8px;
   margin-bottom: 10px;
   cursor: pointer;
-  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
 
 .existing-visitor-item:hover {
@@ -496,7 +488,9 @@ onMounted(() => {
   flex: 1;
 }
 
-.visitor-name, .visitor-id, .visitor-phone {
+.visitor-name,
+.visitor-id,
+.visitor-phone {
   font-size: 14px;
   color: #333;
   margin-bottom: 5px;
@@ -519,14 +513,17 @@ onMounted(() => {
 }
 
 .existing-actions {
-  position: fixed;
-  bottom: 20px;
-  left: 20px;
-  right: 20px;
-  z-index: 100;
+  // position: fixed;
+  // bottom: 20px;
+  // left: 20px;
+  // right: 20px;
+  // z-index: 100;
 }
 
 .confirm-btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
   width: 100%;
   padding: 15px;
   background-color: #B1967B;
@@ -538,14 +535,18 @@ onMounted(() => {
 }
 
 .next-button-container {
-  position: fixed;
-  bottom: 20px;
-  left: 20px;
-  right: 20px;
-  z-index: 100;
+  margin: 24px 24px 0 24px;
+  // position: fixed;
+  // bottom: 20px;
+  // left: 20px;
+  // right: 20px;
+  // z-index: 100;
 }
 
 .next-btn {
+  display: flex;
+  justify-content: center;
+  align-items: center;
   width: 100%;
   padding: 15px;
   background-color: #B1967B;

+ 57 - 24
src/views/indexPage/index.vue

@@ -3,7 +3,7 @@
   <div v-else :class="['home-container', !isFromParam ? 'home-tabar' : '']">
     <!-- 轮播图区域 -->
     <div class="carousel-section">
-      <el-carousel height="180px" indicator-position="none" :interval="5000">
+      <el-carousel height="180px" indicator-position="bottom" :interval="4000">
         <el-carousel-item v-for="item in bannerData" :key="item.carouselId">
           <img :src="getImg(item)" :alt="getTitle(item) || '轮播图'" class="carousel-img">
         </el-carousel-item>
@@ -12,11 +12,11 @@
 
     <!-- 功能区域 -->
     <div class="function-section">
-      <div class="function-item" @click="handleFunctionClick('visit')">
+      <div class="function-item" :class="{ 'disabled': isPreviewMode }" @click="handleFunctionClick('visit')">
         <img src="@/assets/indexPage/visit.png" alt="预约参观" class="function-icon">
         <span class="function-text">预约参观</span>
       </div>
-      <div class="function-item" @click="handleFunctionClick('activity')">
+      <div class="function-item" :class="{ 'disabled': isPreviewMode }" @click="handleFunctionClick('activity')">
         <img src="@/assets/indexPage/activity.png" alt="活动预约" class="function-icon">
         <span class="function-text">活动预约</span>
       </div>
@@ -152,6 +152,11 @@ const getIndexImg = (item) => {
 
 // 功能点击处理
 const handleFunctionClick = (type) => {
+  // 预览模式下禁止点击
+  if (isPreviewMode.value && !['map', 'introduce'].includes(type)) {
+    return
+  }
+
   console.log(`点击了${type}功能`)
   // 根据不同功能跳转到不同页面或显示不同内容
   switch (type) {
@@ -183,15 +188,17 @@ const handleFunctionClick = (type) => {
 const viewMore = (section) => {
   console.log(`查看更多${section}`)
   // 根据不同区块跳转到对应的列表页
+  const query = isPreviewMode.value ? { preview: '1' } : {}
+
   switch (section) {
     case 'exhibition':
-      router.push('/exhibition')
+      router.push({ path: '/exhibition', query })
       break
     case 'recommended':
-      router.push({ name: 'news' })
+      router.push({ name: 'news', query })
       break
     case 'activity':
-      router.push({ name: 'activity' })
+      router.push({ name: 'activity', query })
       break
   }
 }
@@ -200,13 +207,17 @@ const viewMore = (section) => {
 const viewExhibition = (exhibition) => {
   console.log(`查看展览${exhibition.exhibitId}详情`)
   // 跳转到展览详情页
+  const query = {
+    id: exhibition.exhibitId,
+    type: 'exhibition',
+    isFromPage: 'indexPage'
+  }
+  if (isPreviewMode.value) {
+    query.preview = '1'
+  }
   router.push({
     path: '/allDetailsShow',
-    query: {
-      id: exhibition.exhibitId,
-      type: 'exhibition',
-      isFromPage: 'indexPage'
-    }
+    query
   })
 }
 
@@ -214,13 +225,17 @@ const viewExhibition = (exhibition) => {
 const viewActivity = (active) => {
   console.log(`查看活动${active.activityId}详情`)
   // 跳转到活动详情页
+  const query = {
+    id: active.activityId,
+    type: 'activity',
+    isFromPage: 'indexPage'
+  }
+  if (isPreviewMode.value) {
+    query.preview = '1'
+  }
   router.push({
     path: '/allDetailsShow',
-    query: {
-      id: active.activityId,
-      type: 'activity',
-      isFromPage: 'indexPage'
-    }
+    query
   })
 }
 
@@ -228,13 +243,17 @@ const viewActivity = (active) => {
 const viewNews = (news) => {
   console.log(`查看资讯${news.informationId}详情`)
   // 跳转到资讯详情页
+  const query = {
+    id: news.informationId,
+    type: 'information',
+    isFromPage: 'indexPage'
+  }
+  if (isPreviewMode.value) {
+    query.preview = '1'
+  }
   router.push({
     path: '/allDetailsShow',
-    query: {
-      id: news.informationId,
-      type: 'information',
-      isFromPage: 'indexPage'
-    }
+    query
   })
 }
 
@@ -266,7 +285,7 @@ onMounted(() => {
 
     // 使用组合式函数初始化所有数据,可以传入动态参数
     initAllData({
-      bannerParams: { pageNum: 1, pageSize: 10, status: statusValue },
+      bannerParams: { pageNum: 1, pageSize: 5, status: statusValue },
       newsParams: { pageNum: 1, pageSize: 3, status: statusValue },
       exhibitionParams: { pageNum: 1, pageSize: 5, status: statusValue },
       activeParams: { pageNum: 1, pageSize: 5, status: statusValue }
@@ -279,8 +298,15 @@ onMounted(() => {
 .home-container {
   height: calc(100vh); // 减去底部导航栏高度
   overflow-y: auto;
-  background: url('@/assets/indexPage/bg.png') no-repeat center top;
-  background-size: 100% auto;
+  background: url('@/assets/indexPage/bg.png') no-repeat;
+  background-size: cover;
+  box-sizing: border-box;
+}
+
+@media (min-width: 1024px) {
+  .home-container {
+    width: 400px;
+  }
 }
 
 .home-not-overflow {
@@ -311,6 +337,7 @@ onMounted(() => {
     flex-direction: column;
     align-items: center;
     width: 22%;
+    cursor: pointer;
 
     .function-icon {
       width: 56px;
@@ -322,6 +349,12 @@ onMounted(() => {
       font-size: 16px;
       color: #B1967B;
     }
+
+    &.disabled {
+      opacity: 0.5;
+      cursor: not-allowed;
+      pointer-events: none;
+    }
   }
 }
 

+ 30 - 16
src/views/indexPage/visitPreview.vue

@@ -3,13 +3,13 @@
     <div class="back-button" @click="router.replace('/indexPage')">
       <img src="@/assets/indexPage/icon_back.png" alt="">
     </div>
-    
+
     <div class="header-image">
       <img src="@/assets/indexPage/zhanweitu.png" alt="预约参观" class="main-image" />
     </div>
     <div class="reservation-info">
       <h2>预约须知</h2>
-      
+
       <div class="time-info">
         <div class="time-section">
           <span span="time-title">开馆时间</span>
@@ -26,15 +26,17 @@
           <div class="stop-desc">停止检票</div>
         </div>
       </div>
-      
+
       <div class="time-note">周一闭馆(法定节假日除外,除夕、正月初一闭馆)。</div>
-      
+
       <h3 class="reservation-title">预约参观</h3>
       <div class="reservation-rules">
-        <p class="rule-content">①所有观众(包括享受优待政策的观众及其陪同人员)<span class="notic">均须实名预约</span>。放票时间为<span class="notic">每日18:00,可提前7日(不包括当日)通过官方微信小程序预约</span>,预约时段分为上午(9:00-13:00)和下午(12:00-16:00),当天不再放票;</p>
-        <p class="rule-content">②参观当日须按照预约时段入馆参观,错过预约时段将谢绝入馆。<span class="notic">同一证件号</span>当天可进出馆2次,预约上午票的观众首次入馆时间必须在13:00前;</p>
+        <p class="rule-content">①所有观众(包括享受优待政策的观众及其陪同人员)<span class="notic">均须实名预约</span>。放票时间为<span
+            class="notic">每日18:00,可提前7日(不包括当日)通过官方微信小程序预约</span>,预约时段分为上午(9:00-13:00)和下午(12:00-16:00),当天不再放票;</p>
+        <p class="rule-content">②参观当日须按照预约时段入馆参观,错过预约时段将谢绝入馆。<span
+            class="notic">同一证件号</span>当天可进出馆2次,预约上午票的观众首次入馆时间必须在13:00前;</p>
       </div>
-      
+
       <div class="reservation-button">
         <div class="btn-reserve" @click="startPreview">参观预约</div>
         <div class="btn-people">我的参观人</div>
@@ -48,7 +50,7 @@ import { useRouter } from 'vue-router'
 
 const router = useRouter()
 const startPreview = () => {
-  router.push({name: 'startPreview'})
+  router.push({ name: 'startPreview' })
 }
 </script>
 
@@ -70,14 +72,16 @@ const startPreview = () => {
   width: 40px;
   height: 40px;
   border-radius: 50%;
-  
+
   img {
     width: 40px;
     height: 40px;
   }
 }
+
 .header-image {
   height: 240px;
+
   .main-image {
     width: 100%;
     height: 100%;
@@ -86,12 +90,15 @@ const startPreview = () => {
 
 .reservation-info {
   position: absolute;
+  width: 100%;
   top: 200px;
   height: calc(100vh - 200px);
   background: #E0D2B4;
   border-top-left-radius: 30px;
   border-top-right-radius: 30px;
   padding: 30px;
+  overflow: auto;
+
   .reservation-info h2 {
     font-size: 20px;
     margin-bottom: 20px;
@@ -104,21 +111,25 @@ const startPreview = () => {
     justify-content: space-between;
     margin-bottom: 10px;
   }
+
   .time-title {
     font-size: 14px;
     color: #B1967B;
   }
+
   .time-value {
     font-size: 40px;
     font-weight: bold;
     color: #94765A;
   }
-  .line{
+
+  .line {
     height: 2px;
     width: 13px;
     background: #584735;
     margin: 24px 6px 0 6px;
   }
+
   .divider {
     height: 50px;
     width: 2px;
@@ -157,9 +168,11 @@ const startPreview = () => {
     line-height: 1.5;
     color: #B1967B;
     margin-bottom: 20px;
-    .rule-content{
+
+    .rule-content {
       color: #B1967B;
-      .notic{
+
+      .notic {
         color: #94765A;
         font-weight: bold;
       }
@@ -179,7 +192,7 @@ const startPreview = () => {
 
 .btn-reserve {
   background: url('@/assets/indexPage/preview-btn.png');
-  width: 330px;
+  width: 100%;
   height: 93px;
   border-radius: 5px;
   display: flex;
@@ -188,13 +201,14 @@ const startPreview = () => {
   background-size: 100% auto;
   color: #fff;
 }
-.btn-people{
+
+.btn-people {
   display: flex;
   justify-content: center;
   align-items: center;
-  width: 330px;
+  width: 100%;
   height: 64px;
-  background: rgba(255,255,255,0.5);
+  background: rgba(255, 255, 255, 0.5);
   border-radius: 5px 5px 5px 5px;
   border: 1px solid #94765A;
   margin-top: 10px;

+ 34 - 14
src/views/user/map.vue

@@ -13,7 +13,7 @@
     <!-- 详情内容 -->
     <div v-else-if="detailData" class="detail-content">
       <!-- 标题 -->
-      <div class="detail-title">{{ detailData.title || '展馆地图' }}</div>
+      <div class="detail-title">{{ getFieldValue(detailData, 'title') || '展馆地图' }}</div>
 
       <!-- 时间 -->
       <!-- <div class="detail-time" v-if="detailData.createTime || detailData.publishTime">
@@ -27,8 +27,8 @@
       </div>
 
       <!-- 描述 -->
-      <div class="detail-description" v-else-if="detailData.description">
-        {{ detailData.description }}
+      <div class="detail-description" v-else-if="getFieldValue(detailData, 'description')">
+        {{ getFieldValue(detailData, 'description') }}
       </div>
     </div>
 
@@ -39,7 +39,7 @@
     </div>
 
     <!-- 导航前往按钮 -->
-    <div class="map-button">
+    <div class="map-button" @click="openNavitor">
       <img class="btn-bg" src="@/assets/components/btn_05.png" alt="">
       <p class="btn-title">
         <span><el-icon :size="20">
@@ -65,24 +65,38 @@ const shouldShowBackButton = computed(() => {
   return route.query.isFrom !== 'weixin'
 })
 
+// 检查是否为预览模式
+const isPreviewMode = computed(() => {
+  return route.query.preview === '1'
+})
+
+// 获取字段值的通用方法,优先获取带B后缀的字段
+const getFieldValue = (item, fieldName) => {
+  if (isPreviewMode.value) {
+    return item[fieldName + 'B'] || item[fieldName]
+  }
+  return item[fieldName]
+}
+
 // 响应式数据
 const loading = ref(false)
 const detailData = ref(null)
 
 // 处理后的HTML内容
 const processedContent = computed(() => {
-  const content = detailData.value?.content || detailData.value?.context
+  const content = getFieldValue(detailData.value, 'content') || getFieldValue(detailData.value, 'context')
   return content ? processHtmlContent(content) : ''
 })
-
-// 格式化时间(横线分隔)
-const formatTimeWithDash = (timeStr) => {
-  if (!timeStr) return ''
-  const date = new Date(timeStr)
-  const year = date.getFullYear()
-  const month = String(date.getMonth() + 1).padStart(2, '0')
-  const day = String(date.getDate()).padStart(2, '0')
-  return `${year}-${month}-${day}`
+// 导航前往
+const openNavitor = () => {
+  wx.openLocation({
+    latitude: 45, // 纬度,浮点数,范围为90 ~ -90
+    longitude: 83, // 经度,浮点数,范围为180 ~ -180。
+    name: '克拉玛依博物馆', // 位置名
+    address: '克拉玛依博物馆', // 地址详情说明
+    scale: 1, // 地图缩放级别,整型值,范围从1~28。默认为最大
+    infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转
+  })
 }
 
 // 返回上一页
@@ -130,6 +144,12 @@ onMounted(() => {
   overflow-y: auto;
 }
 
+@media (min-width: 1024px) {
+  .detail-container {
+    width: 400px;
+  }
+}
+
 .back-button {
   position: absolute;
   top: 20px;