commit 952d3be4a98f28e6e2e348239f1f23867fe50a47 Author: whitechiina <1293616053@qq.com> Date: Mon Apr 27 16:48:12 2026 +0800 first commit diff --git a/.lanhu-home.png b/.lanhu-home.png new file mode 100644 index 0000000..60f80f8 Binary files /dev/null and b/.lanhu-home.png differ diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..ba00ee5 --- /dev/null +++ b/App.vue @@ -0,0 +1,78 @@ + + + diff --git a/api/assets.js b/api/assets.js new file mode 100644 index 0000000..0e44df0 --- /dev/null +++ b/api/assets.js @@ -0,0 +1,850 @@ +import serviceConfig from "../config/service"; +import request from "../utils/request"; + +function createError(message, raw) { + return { + message: message || "接口请求失败", + raw: raw, + }; +} + +function toNumber(value) { + const number = Number(value || 0); + return Number.isFinite(number) ? number : 0; +} + +function toFixedNumber(value, digits) { + return toNumber(value).toFixed(digits); +} + +function formatHomeNumber(value, digits) { + const number = toNumber(value); + + if (digits > 0) { + const fixed = number.toFixed(digits); + const parts = fixed.split("."); + parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); + return parts.join("."); + } + + return Math.round(number) + .toString() + .replace(/\B(?=(\d{3})+(?!\d))/g, ","); +} + +function isSuccessPayload(payload) { + if (!payload || typeof payload !== "object") { + return false; + } + + const statusCode = + payload.code !== undefined ? Number(payload.code) : Number(payload.status); + + return statusCode === 200; +} + +function unwrapPayload(payload, fallbackMessage) { + if (isSuccessPayload(payload)) { + return payload.data; + } + + if (payload && typeof payload === "object") { + throw createError( + payload.msg || payload.message || fallbackMessage || "接口请求失败", + payload, + ); + } + + throw createError(fallbackMessage || "接口返回异常", payload); +} + +async function fetchPayload(options, fallbackMessage) { + try { + const payload = await request(options); + return unwrapPayload(payload, fallbackMessage); + } catch (error) { + if (error && error.message) { + throw error; + } + + throw createError(fallbackMessage || "接口请求失败", error); + } +} + +function createRequestOptions(baseOptions, requestOptions) { + return Object.assign({}, baseOptions, requestOptions || {}); +} + +function normalizeTicker(data) { + const close = toNumber(data && (data.close || data.cnyPrice)); + const lastDayClose = toNumber(data && data.lastDayClose); + const rawChange = data && data.change; + let change = typeof rawChange === "string" ? rawChange : ""; + + if (!change) { + if (close && lastDayClose) { + const percent = ((close - lastDayClose) / lastDayClose) * 100; + const prefix = percent >= 0 ? "+" : ""; + change = prefix + percent.toFixed(2) + "%"; + } else { + change = "0.00%"; + } + } + + return { + symbol: (data && data.symbol) || "BMT/CNY", + close: close, + cnyPrice: + (data && data.cnyPrice) || (close ? close.toFixed(2) : "0.00"), + lastDayClose: lastDayClose, + change: change, + }; +} + +function normalizeBalances(data) { + return { + points: toNumber(data && data.point), + power: toNumber(data && data.c_power), + bmt: toNumber(data && data.bmt_num), + withdrawableBmt: toNumber(data && data.bmt_num), + voucher: toNumber(data && data.coin), + coupon: toNumber(data && data.diamond_balance), + }; +} + +function buildHomeOverview(balanceData, tickerData) { + const balances = normalizeBalances(balanceData); + const ticker = normalizeTicker(tickerData); + + return { + title: "数字资产", + ticker: ticker, + topStats: [ + { + key: "wallet-bmt", + title: "可提取BMT", + value: toFixedNumber(balances.withdrawableBmt, 2), + unit: "BMT", + accent: "gold", + }, + { + key: "ticker", + title: "BMT实时价格", + value: toFixedNumber(ticker.close || ticker.cnyPrice, 3), + unit: "CNY/BMT", + accent: "green", + }, + ], + quickAssets: [ + { + key: "points", + title: "积分", + value: formatHomeNumber(balances.points, 0), + accent: "gold", + }, + { + key: "voucher", + title: "抵用券", + value: formatHomeNumber(balances.voucher, 2), + accent: "rose", + }, + { + key: "coupon", + title: "消费券", + value: formatHomeNumber(balances.coupon, 0), + accent: "teal", + }, + { + key: "power", + title: "算力", + value: formatHomeNumber(balances.power, 0), + accent: "violet", + }, + ], + features: [ + { + key: "bmt-exchange", + title: "BMT兑换", + desc: "积分与算力兑换 BMT", + accent: "mint", + }, + { + key: "power-exchange", + title: "算力兑换", + desc: "抵用券与消费券兑换算力", + accent: "amber", + }, + { + key: "transfer", + title: "转赠中心", + desc: "积分或算力转赠好友", + accent: "indigo", + }, + { + key: "withdraw", + title: "BMT提取", + desc: "钱包中的 BMT 可提取到交易所进行交易", + accent: "pink", + }, + { + key: "points-convert", + title: "积分转换", + desc: "释放中的积分转换为可用积分", + accent: "pink", + }, + ], + notice: + "数字资产是您在平台上的虚拟资产,请谨慎管理;BMT可在交易所中进行交易。", + }; +} + +function buildTransferTips(feePercent) { + const percentText = toNumber(feePercent) || 10; + + return { + points: [ + "只能转赠100的整数倍", + "凌晨0点-凌晨01点系统维护不可赠送", + "转赠系统会扣除" + percentText + "%的手续费", + ], + power: [ + "只能转赠1的整数倍", + "转赠系统会扣除" + percentText + "%的手续费", + ], + }; +} + +function buildWalletList(address) { + const normalizedAddress = String(address || "").trim(); + + if (!normalizedAddress) { + return []; + } + + return [ + { + id: "default-wallet", + name: serviceConfig.WALLET_NAME, + address: normalizedAddress, + isDefault: true, + }, + ]; +} + +function buildWalletPayload(address) { + return { + wallets: buildWalletList(address), + instructions: [ + "点击交易所 App 底部“资产”进入钱包页", + "搜索或输入大写字母 BMT", + "点击“充币 / 充值”进入收款地址页面", + "复制钱包地址后回填到当前页面", + ], + }; +} + +function formatTransferRecordNumber(value) { + const number = toNumber(value); + return formatHomeNumber(number, Number.isInteger(number) ? 0 : 2); +} + +function getTransferRecordUnit(item) { + return Number(item && item.type) === 0 ? "算力" : "积分"; +} + +function getTransferRecordTone(item) { + return Number(item && item.io_type) === 1 ? "success" : "danger"; +} + +function getTransferRecordTag(item) { + return Number(item && item.io_type) === 1 ? "收" : "赠"; +} + +function getTransferRecordDirection(item) { + return Number(item && item.io_type) === 1 ? "转入" : "转出"; +} + +function getTransferRecordTitle(item) { + const unit = getTransferRecordUnit(item); + return Number(item && item.io_type) === 1 ? unit + "获赠" : unit + "转赠"; +} + +function getTransferRecordSymbol(item) { + return Number(item && item.io_type) === 1 ? "+" : "-"; +} + +function getTransferRecordAmount(item) { + const numberText = formatTransferRecordNumber(item && item.num); + return getTransferRecordSymbol(item) + numberText; +} + +function getTransferRecordFee(item) { + if ( + item && + item.fee !== undefined && + item.fee !== null && + String(item.fee).trim() !== "" + ) { + return toNumber(item.fee); + } + + return (toNumber(item && item.num) * toNumber(item && item.fee_percent)) / 100; +} + +function getTransferRecordFeeText(item) { + const percent = toNumber(item && item.fee_percent); + const unit = getTransferRecordUnit(item); + const feeText = formatTransferRecordNumber(getTransferRecordFee(item)); + + if (percent > 0) { + return ( + "手续费 " + + feeText + + " " + + unit + + " (" + + formatTransferRecordNumber(percent) + + "%)" + ); + } + + return "手续费 " + feeText + " " + unit; +} + +function getTransferRecordBalance(item) { + const unit = getTransferRecordUnit(item); + return "结余 " + toFixedNumber(item && item.balance, 2) + " " + unit; +} + +function getTransferRecordBalanceLabel(item) { + const unit = getTransferRecordUnit(item); + return "剩余" + unit + ":" + formatTransferRecordNumber(item && item.balance); +} + +function mapTransferRecords(list) { + return (Array.isArray(list) ? list : []).map(function (item) { + return { + id: item.order_sn || item.id || String(Math.random()), + title: item.title || getTransferRecordTitle(item), + subtitle: item.order_sn ? "单号 " + item.order_sn : getTransferRecordDirection(item), + time: item.add_time || "", + amount: getTransferRecordAmount(item), + balance: getTransferRecordBalance(item), + balanceLabel: getTransferRecordBalanceLabel(item), + assetLabel: getTransferRecordUnit(item), + feeText: getTransferRecordFeeText(item), + directionLabel: getTransferRecordDirection(item), + actionSymbol: getTransferRecordSymbol(item), + orderSn: item.order_sn || "", + tag: getTransferRecordTag(item), + tone: getTransferRecordTone(item), + cardTone: getTransferRecordTone(item), + }; + }); +} + +function mapPointsConvertRecords(list) { + return (Array.isArray(list) ? list : []).map(function (item) { + const numberText = toFixedNumber(item.number, 2); + const transferCoinText = toFixedNumber(item.transfer_coin_num, 0); + const releaseTotal = + item && + item.userBillRelease && + item.userBillRelease.total !== undefined && + item.userBillRelease.total !== null + ? String(item.userBillRelease.total) + : ""; + + return { + id: String(item.id || ""), + title: item.title || "积分记录", + subtitle: "可转数量 " + transferCoinText, + time: item.add_time || "", + amount: "+" + numberText, + balance: releaseTotal ? "释放总量 " + releaseTotal : "", + tag: "积", + tone: "success", + }; + }); +} + +function buildDefaultLedger(type, balances) { + const map = { + power: { + title: "兑换记录", + subtitle: "算力兑换记录", + }, + bmt: { + title: "兑换记录", + subtitle: "BMT兑换记录", + }, + withdraw: { + title: "提取记录", + subtitle: "BMT提取流水", + }, + coupon: { + title: "消费券", + subtitle: "当前消费券 " + toFixedNumber(balances.coupon, 2), + }, + voucher: { + title: "抵用券记录", + subtitle: "可用抵用券 " + toFixedNumber(balances.voucher, 2), + }, + }; + + return { + type: type, + title: map[type].title, + subtitle: map[type].subtitle, + records: [], + }; +} + +function normalizeTransferTarget(data, fallbackId) { + if (data && typeof data === "object" && !Array.isArray(data)) { + const id = String(data.uid || data.id || fallbackId || "").trim(); + if (!id) { + throw createError("未查询到好友", data); + } + + return { + id: id, + nickname: + data.nickname || data.nick_name || data.username || "用户" + id, + phone: data.mobile || data.phone || "ID已通过校验", + avatar: data.avatar || data.headimg || "", + }; + } + + if (data === true) { + const id = String(fallbackId || "").trim(); + if (!id) { + throw createError("未查询到好友", data); + } + + return { + id: id, + nickname: "用户" + id, + phone: "ID已通过校验", + avatar: "", + }; + } + + throw createError("未查询到好友", data); +} + +function sumBy(list, key) { + return (Array.isArray(list) ? list : []).reduce(function (total, item) { + return total + toNumber(item && item[key]); + }, 0); +} + +async function fetchPriceData(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.price, + }, requestOptions), + "实时价格加载失败", + ); +} + +async function fetchHomeBalanceData(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.homeBalance, + }, requestOptions), + "首页资产加载失败", + ); +} + +async function fetchBmtPowerRateData(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.bmtRedeemPowerRate, + }, requestOptions), + "兑换比例加载失败", + ); +} + +async function fetchTransferFeeData(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.transferFee, + }, requestOptions), + "手续费比例加载失败", + ); +} + +async function fetchWalletAddressData(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.walletDetail, + }, requestOptions), + "钱包加载失败", + ); +} + +async function fetchPointsConvertList(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.pointsConvertList, + data: { + interval: serviceConfig.POINTS_CONVERT_INTERVAL, + }, + }, requestOptions), + "积分转换列表加载失败", + ); +} + +async function fetchTransferLedgerData(requestOptions) { + return fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.transferLedger, + }, requestOptions), + "转赠记录加载失败", + ); +} + +export async function fetchAssetHome(requestOptions) { + const result = await Promise.all([ + fetchPriceData(requestOptions), + fetchHomeBalanceData(requestOptions), + ]); + return buildHomeOverview(result[1], result[0]); +} + +export async function fetchPointsConvertDetail(requestOptions) { + const result = await Promise.all([ + fetchHomeBalanceData(requestOptions), + fetchPointsConvertList(requestOptions), + ]); + const balances = normalizeBalances(result[0]); + const pointList = Array.isArray(result[1] && result[1].list) + ? result[1].list + : []; + + return { + availablePoints: toFixedNumber(balances.points, 2), + pendingPoints: toFixedNumber(sumBy(pointList, "number"), 0), + ids: pointList + .map(function (item) { + return item && item.id; + }) + .filter(Boolean), + tips: [ + "释放中的积分,转换成可用积分后,方可兑换BMT;", + "凌晨0点-凌晨1点积分系统维护不可兑换。", + ], + }; +} + +export async function submitAssetPointsConvert(payload, requestOptions) { + const ids = Array.isArray(payload && payload.ids) ? payload.ids : []; + + if (!ids.length) { + throw createError("暂无可转换积分"); + } + + await fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.pointsConvertSubmit, + method: "POST", + data: { + ids: ids.join(","), + type: 1, + }, + }, requestOptions), + "积分转换失败", + ); + + return { + success: true, + message: "转换成功", + }; +} + +export async function fetchTransferDetail(requestOptions) { + const result = await Promise.all([ + fetchHomeBalanceData(requestOptions), + fetchTransferFeeData(requestOptions), + ]); + const balances = normalizeBalances(result[0]); + const feePercent = toNumber(result[1] && result[1].r) || 10; + + return { + balances: { + points: toFixedNumber(balances.points, 0), + power: toFixedNumber(balances.power, 0), + }, + feePercent: feePercent, + tips: buildTransferTips(feePercent), + }; +} + +export async function searchTransferUser(uid, requestOptions) { + const keyword = String(uid || "").trim(); + if (!keyword) { + throw createError("请输入被赠人ID"); + } + + const data = await fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.transferUser, + method: "POST", + data: { + uid: keyword, + }, + }, requestOptions), + "查询好友失败", + ); + + return normalizeTransferTarget(data, keyword); +} + +export async function submitAssetTransfer(payload, requestOptions) { + const transferType = payload && payload.type === "power" ? "power" : "points"; + const targetId = String(payload && payload.targetId ? payload.targetId : "").trim(); + const amount = toNumber(payload && payload.amount); + + if (!targetId) { + throw createError("请选择被赠送人"); + } + + if (!amount) { + throw createError("请输入转赠数量"); + } + + const result = await Promise.all([ + fetchTransferFeeData(requestOptions), + fetchPayload( + createRequestOptions({ + url: + transferType === "power" + ? serviceConfig.ENDPOINTS.transferPowerSubmit + : serviceConfig.ENDPOINTS.transferPointsSubmit, + method: "POST", + data: { + uid: targetId, + number: String(amount), + }, + }, requestOptions), + "转赠失败", + ), + ]); + const feePercent = toNumber(result[0] && result[0].r) || 10; + const fee = (amount * feePercent) / 100; + const received = amount - fee; + + return { + success: true, + fee: toFixedNumber(fee, 2), + received: toFixedNumber(received, 2), + }; +} + +export async function fetchPowerExchangeDetail(requestOptions) { + const result = await Promise.all([ + fetchPriceData(requestOptions), + fetchHomeBalanceData(requestOptions), + ]); + const ticker = normalizeTicker(result[0]); + const balances = normalizeBalances(result[1]); + + return { + ticker: ticker, + balances: { + coupon: toFixedNumber(balances.coupon, 2), + voucher: toFixedNumber(balances.voucher, 2), + power: toFixedNumber(balances.power, 0), + }, + tips: [ + "算力 = 抵用券或消费券 ÷ BMT实时价格;", + "抵用券和消费券总数小于100券的不可兑换;", + "算力用于兑换BMT使用。", + ], + }; +} + +export async function submitAssetPowerExchange(payload, requestOptions) { + const mode = payload && payload.mode === "coupon" ? "coupon" : "voucher"; + const amount = toNumber(payload && payload.amount); + + if (!amount) { + throw createError("请输入兑换数量"); + } + + await fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.powerExchangeSubmit, + method: "POST", + data: { + type: mode === "coupon" ? 1 : 0, + number: String(amount), + }, + }, requestOptions), + "算力兑换失败", + ); + + return { + success: true, + }; +} + +export async function fetchBmtExchangeDetail(requestOptions) { + const result = await Promise.all([ + fetchPriceData(requestOptions), + fetchHomeBalanceData(requestOptions), + fetchBmtPowerRateData(requestOptions), + ]); + const ticker = normalizeTicker(result[0]); + const balances = normalizeBalances(result[1]); + const powerRate = toNumber(result[2]); + + return { + ticker: ticker, + powerRate: powerRate, + balances: { + points: toFixedNumber(balances.points, 0), + power: toFixedNumber(balances.power, 2), + bmt: toFixedNumber(balances.bmt, 2), + voucher: toFixedNumber(balances.voucher, 2), + coupon: toFixedNumber(balances.coupon, 2), + }, + tips: [ + "BMT=输入的积分数量,提交时会同步校验所需算力。", + "兑换所需算力按后端返回比例实时计算。", + "只能兑换100的整数倍,小于100积分不可兑换。", + "凌晨0点至凌晨1点积分系统维护期间不可兑换。", + ], + }; +} + +export async function submitAssetBmtExchange(payload, requestOptions) { + const amount = toNumber(payload && payload.amount); + + if (!amount) { + throw createError("请输入积分数量"); + } + + await fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.bmtExchangeSubmit, + method: "POST", + data: { + number: String(amount), + }, + }, requestOptions), + "BMT兑换失败", + ); + + return { + success: true, + }; +} + +export async function fetchWithdrawDetail(requestOptions) { + const result = await Promise.all([ + fetchPriceData(requestOptions), + fetchHomeBalanceData(requestOptions), + fetchWalletAddressData(requestOptions), + ]); + const ticker = normalizeTicker(result[0]); + const balances = normalizeBalances(result[1]); + const walletPayload = buildWalletPayload(result[2] && result[2].address); + + return { + ticker: ticker, + withdrawableBmt: toFixedNumber(balances.withdrawableBmt, 2), + wallets: walletPayload.wallets, + defaultWallet: walletPayload.wallets[0] || null, + }; +} + +export function submitAssetWithdraw(payload, requestOptions) { + return Promise.reject( + createError("当前接口文档未提供 BMT 提取提交接口"), + ); +} + +export async function fetchLedgerDetail(type, requestOptions) { + if (type === "transfer") { + const data = await fetchTransferLedgerData(requestOptions); + return { + type: type, + title: "转赠记录", + subtitle: "积分与算力转赠流水", + records: mapTransferRecords(data && data.list), + }; + } + + if (type === "points") { + const result = await Promise.all([ + fetchHomeBalanceData(requestOptions), + fetchPointsConvertList(requestOptions), + ]); + const balances = normalizeBalances(result[0]); + const pointList = Array.isArray(result[1] && result[1].list) + ? result[1].list + : []; + + return { + type: type, + title: "我的积分", + subtitle: "可转换积分记录", + summary: { + label: "有效积分", + value: toFixedNumber(balances.points, 0), + }, + records: mapPointsConvertRecords(pointList), + }; + } + + const homeData = await fetchHomeBalanceData(requestOptions); + const balances = normalizeBalances(homeData); + return buildDefaultLedger(type, balances); +} + +export async function fetchWalletDetail(requestOptions) { + const data = await fetchWalletAddressData(requestOptions); + return buildWalletPayload(data && data.address); +} + +export async function saveAssetWallet(payload, requestOptions) { + const address = String(payload && payload.address ? payload.address : "").trim(); + + if (!address) { + throw createError("请输入钱包地址"); + } + + await fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.walletSave, + method: "POST", + data: { + address: address, + }, + }, requestOptions), + "保存失败", + ); + + return { + success: true, + }; +} + +export async function deleteAssetWallet(id, requestOptions) { + await fetchPayload( + createRequestOptions({ + url: serviceConfig.ENDPOINTS.walletSave, + method: "POST", + data: { + address: "", + }, + }, requestOptions), + "删除失败", + ); + + return { + success: true, + }; +} diff --git a/components/asset-confirm-popup.vue b/components/asset-confirm-popup.vue new file mode 100644 index 0000000..263c96b --- /dev/null +++ b/components/asset-confirm-popup.vue @@ -0,0 +1,267 @@ + + + + + diff --git a/components/asset-page-shell.vue b/components/asset-page-shell.vue new file mode 100644 index 0000000..243b573 --- /dev/null +++ b/components/asset-page-shell.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/components/asset-record-list.vue b/components/asset-record-list.vue new file mode 100644 index 0000000..ff489be --- /dev/null +++ b/components/asset-record-list.vue @@ -0,0 +1,184 @@ + + + + + diff --git a/components/wallet-action-popup.vue b/components/wallet-action-popup.vue new file mode 100644 index 0000000..97e09c2 --- /dev/null +++ b/components/wallet-action-popup.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/config/service.js b/config/service.js new file mode 100644 index 0000000..74edb41 --- /dev/null +++ b/config/service.js @@ -0,0 +1,25 @@ +const serviceConfig = { + BASE_URL: "https://tpoint.agrimedia.cn", + TIMEOUT: 10000, + WALLET_NAME: "海南农综交易所", + POINTS_CONVERT_INTERVAL: "0,999999999", + ENDPOINTS: { + price: "/api/hn/getPrice", + homeBalance: "/api/hn/getAllBalance", + powerExchangeSubmit: "/api/hn/redeem/power", + bmtRedeemPowerRate: "/api/hn/redeem/getRedeemPowerRate", + bmtExchangeSubmit: "/api/hn/redeem/redeem_bmt", + transferFee: "/api/hn/transfer/getProp", + transferUser: "/api/hn/transfer/getUserInfo", + transferPowerSubmit: "/api/hn/transfer/transferPower", + transferPointsSubmit: "/api/hn/transfer/transferPoint", + transferLedger: "/api/hn/transfer/transferList", + walletDetail: "/api/hn/wallet/getWalletAddress", + walletSave: "/api/hn/wallet/saveAddress", + pointsConvertList: "/api/integral/transferList", + pointsConvertSubmit: "/api/integral/doTransfer", + pointsConvertInfo: "/api/integral/transferInfo", + }, +}; + +export default serviceConfig; diff --git a/index.html b/index.html new file mode 100644 index 0000000..2501934 --- /dev/null +++ b/index.html @@ -0,0 +1,29 @@ + + + + + + + + + + + +
+ + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..c1caf36 --- /dev/null +++ b/main.js @@ -0,0 +1,22 @@ +import App from './App' + +// #ifndef VUE3 +import Vue from 'vue' +import './uni.promisify.adaptor' +Vue.config.productionTip = false +App.mpType = 'app' +const app = new Vue({ + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..721e850 --- /dev/null +++ b/manifest.json @@ -0,0 +1,72 @@ +{ + "name" : "白马交易所", + "appid" : "__UNI__3EC3CC8", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2" +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..e3ae41e --- /dev/null +++ b/pages.json @@ -0,0 +1,75 @@ +{ + "pages": [ + //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/transfer", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/power-exchange", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/bmt-exchange", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/withdraw", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/points-convert", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/ledger", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/wallet", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + }, + { + "path": "pages/assets/wallet-form", + "style": { + "navigationStyle": "custom", + "backgroundColor": "#191E32" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "white", + "navigationBarTitleText": "数字资产", + "navigationBarBackgroundColor": "#191E32", + "backgroundColor": "#191E32" + }, + "uniIdRouter": {} +} diff --git a/pages/assets/bmt-exchange.vue b/pages/assets/bmt-exchange.vue new file mode 100644 index 0000000..c47bc32 --- /dev/null +++ b/pages/assets/bmt-exchange.vue @@ -0,0 +1,694 @@ + + + + + diff --git a/pages/assets/ledger.vue b/pages/assets/ledger.vue new file mode 100644 index 0000000..5534109 --- /dev/null +++ b/pages/assets/ledger.vue @@ -0,0 +1,474 @@ + + + + + diff --git a/pages/assets/points-convert.vue b/pages/assets/points-convert.vue new file mode 100644 index 0000000..559f9f8 --- /dev/null +++ b/pages/assets/points-convert.vue @@ -0,0 +1,337 @@ + + + + + diff --git a/pages/assets/power-exchange.vue b/pages/assets/power-exchange.vue new file mode 100644 index 0000000..ad6ba08 --- /dev/null +++ b/pages/assets/power-exchange.vue @@ -0,0 +1,743 @@ + + + + + diff --git a/pages/assets/transfer.vue b/pages/assets/transfer.vue new file mode 100644 index 0000000..276e9f7 --- /dev/null +++ b/pages/assets/transfer.vue @@ -0,0 +1,793 @@ + + + + + diff --git a/pages/assets/wallet-form.vue b/pages/assets/wallet-form.vue new file mode 100644 index 0000000..078f732 --- /dev/null +++ b/pages/assets/wallet-form.vue @@ -0,0 +1,367 @@ + + + + + diff --git a/pages/assets/wallet.vue b/pages/assets/wallet.vue new file mode 100644 index 0000000..a0b3fc0 --- /dev/null +++ b/pages/assets/wallet.vue @@ -0,0 +1,371 @@ + + + + + diff --git a/pages/assets/withdraw.vue b/pages/assets/withdraw.vue new file mode 100644 index 0000000..18a8037 --- /dev/null +++ b/pages/assets/withdraw.vue @@ -0,0 +1,667 @@ + + + + + diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..83e0c71 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,620 @@ + + + + + diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..b5771e2 Binary files /dev/null and b/static/logo.png differ diff --git a/styles/common.scss b/styles/common.scss new file mode 100644 index 0000000..59f6316 --- /dev/null +++ b/styles/common.scss @@ -0,0 +1,509 @@ +@import "./tokens.scss"; + +.asset-page { + background: #191e32; + color: $asset-text-main; +} + +.section-label { + margin: 0 0 20rpx; + font-size: 36rpx; + font-weight: 600; + color: $asset-text-main; +} + +.section-subtitle { + margin-top: 8rpx; + font-size: 24rpx; + line-height: 1.6; + color: $asset-text-muted; +} + +.glass-panel { + border: 1px solid rgba(143, 167, 207, 0.16); + border-radius: 16rpx; + background: linear-gradient( + 180deg, + rgba(54, 62, 96, 0.94), + rgba(39, 50, 84, 0.92) + ); + box-shadow: $asset-shadow; +} + +.paper-panel { + border: 1px solid rgba(149, 162, 220, 0.16); + border-radius: 16rpx; + background: linear-gradient( + 180deg, + rgba(54, 62, 96, 0.94), + rgba(39, 50, 84, 0.92) + ); + box-shadow: $asset-shadow; + color: $asset-text-main; +} + +.panel-block { + padding: 20rpx 18rpx; +} + +.hero-chip-row { + display: flex; + flex-wrap: wrap; + margin: 20rpx 0 0; +} + +.hero-chip { + display: inline-flex; + align-items: center; + padding: 12rpx 18rpx; + margin: 0 16rpx 16rpx 0; + border-radius: 999rpx; + background: rgba(255, 255, 255, 0.08); + font-size: 22rpx; + color: $asset-text-main; +} + +.hero-chip__dot { + width: 12rpx; + height: 12rpx; + margin-right: 12rpx; + border-radius: 50%; + background: $asset-accent; + box-shadow: 0 0 18rpx rgba(76, 201, 255, 0.6); +} + +.summary-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-gap: 20rpx; +} + +.summary-card { + padding: 24rpx; + border-radius: 28rpx; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(143, 167, 207, 0.12); +} + +.summary-card__title { + font-size: 24rpx; + color: $asset-text-muted; +} + +.summary-card__value { + display: flex; + align-items: baseline; + margin-top: 14rpx; + font-size: 44rpx; + font-weight: 700; + line-height: 1; +} + +.summary-card__unit { + margin-left: 10rpx; + font-size: 24rpx; + font-weight: 500; + color: $asset-text-subtle; +} + +.summary-card__desc { + margin-top: 14rpx; + font-size: 22rpx; + line-height: 1.5; + color: $asset-text-subtle; +} + +.feature-list { + margin-top: 8rpx; +} + +.feature-cell { + display: flex; + align-items: center; + justify-content: space-between; + padding: 24rpx 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.feature-cell:last-child { + border-bottom: 0; + padding-bottom: 0; +} + +.feature-cell__main { + flex: 1; + min-width: 0; +} + +.feature-cell__title { + font-size: 30rpx; + font-weight: 600; + color: $asset-text-main; +} + +.feature-cell__desc { + margin-top: 8rpx; + font-size: 22rpx; + line-height: 1.5; + color: rgba(255, 255, 255, 0.6); +} + +.feature-cell__arrow { + margin-left: 20rpx; + font-size: 36rpx; + font-weight: 600; + color: rgba(255, 255, 255, 0.4); +} + +.action-row { + display: flex; + align-items: center; +} + +.tab-row { + display: flex; + padding: 6rpx; + border-radius: 999rpx; + background: rgba(17, 27, 54, 0.54); +} + +.tab-chip { + flex: 1; + padding: 16rpx 0; + border-radius: 999rpx; + text-align: center; + font-size: 24rpx; + color: rgba(255, 255, 255, 0.64); +} + +.tab-chip.is-active { + background: linear-gradient(135deg, #7e6cff 0%, #6b56f6 100%); + color: #ffffff; + box-shadow: 0 14rpx 22rpx rgba(93, 79, 225, 0.22); +} + +.info-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-gap: 18rpx; +} + +.info-box { + padding: 20rpx; + border-radius: 14rpx; + background: rgba(29, 39, 68, 0.52); + border: 1px solid rgba(255, 255, 255, 0.06); +} + +.info-box__label { + font-size: 22rpx; + color: $asset-text-subtle; +} + +.info-box__value { + margin-top: 10rpx; + font-size: 34rpx; + font-weight: 700; + color: $asset-text-main; +} + +.field-card { + padding: 18rpx; + border-radius: 14rpx; + background: rgba(29, 39, 68, 0.52); + border: 1px solid rgba(255, 255, 255, 0.08); +} + +.field-row { + display: flex; + align-items: center; + justify-content: space-between; +} + +.field-label { + font-size: 24rpx; + color: rgba(255, 255, 255, 0.62); +} + +.field-value { + font-size: 28rpx; + font-weight: 600; + color: $asset-text-main; +} + +.field-helper { + margin-top: 10rpx; + font-size: 22rpx; + line-height: 1.6; + color: rgba(255, 255, 255, 0.6); +} + +.text-input { + width: 100%; + margin-top: 16rpx; + padding: 20rpx 22rpx; + border-radius: 14rpx; + background: rgba(18, 25, 48, 0.72); + border: 1px solid rgba(255, 255, 255, 0.1); + font-size: 30rpx; + color: $asset-text-main; +} + +.chip-selector { + display: flex; + flex-wrap: wrap; + margin-top: 16rpx; +} + +.chip-selector__item { + padding: 14rpx 24rpx; + margin: 0 16rpx 16rpx 0; + border-radius: 999rpx; + background: rgba(18, 25, 48, 0.72); + border: 1px solid rgba(255, 255, 255, 0.08); + font-size: 24rpx; + color: rgba(255, 255, 255, 0.64); +} + +.chip-selector__item.is-active { + background: rgba(126, 108, 255, 0.22); + border-color: rgba(126, 108, 255, 0.28); + color: $asset-text-main; +} + +.hint-list { + margin: 8rpx 0 0; +} + +.hint-item { + display: flex; + margin-top: 14rpx; + font-size: 22rpx; + line-height: 1.7; + color: rgba(255, 255, 255, 0.62); +} + +.hint-item__index { + margin-right: 10rpx; + color: $asset-accent-strong; + font-weight: 600; +} + +.button-row { + display: flex; + align-items: center; +} + +.button-row .secondary-button { + margin-right: 20rpx; +} + +.primary-button { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 84rpx; + border: 0; + border-radius: 999rpx; + background: linear-gradient(135deg, #7e6cff 0%, #6b56f6 100%); + box-shadow: 0 14rpx 24rpx rgba(93, 79, 225, 0.22); + font-size: 30rpx; + font-weight: 700; + color: #ffffff; +} + +.secondary-button { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 84rpx; + border-radius: 999rpx; + border: 1px solid rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.06); + font-size: 30rpx; + font-weight: 600; + color: $asset-text-main; +} + +.button-link { + font-size: 24rpx; + font-weight: 600; + color: rgba(221, 230, 255, 0.86); +} + +.meta-pair { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 18rpx; + font-size: 24rpx; +} + +.meta-pair__label { + color: rgba(255, 255, 255, 0.62); +} + +.meta-pair__value { + color: $asset-text-main; + font-weight: 600; +} + +.danger-text { + color: $asset-danger; +} + +.success-text { + color: $asset-success; +} + +.warning-text { + color: $asset-warning; +} + +.wallet-card { + padding: 20rpx 18rpx; + border-radius: 16rpx; + background: linear-gradient( + 180deg, + rgba(54, 62, 96, 0.94), + rgba(39, 50, 84, 0.92) + ); + border: 1px solid rgba(149, 162, 220, 0.16); +} + +.wallet-name { + font-size: 28rpx; + font-weight: 700; + color: $asset-text-main; +} + +.wallet-address { + margin-top: 14rpx; + font-size: 24rpx; + line-height: 1.7; + word-break: break-all; + color: $asset-text-muted; +} + +.wallet-footer { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 20rpx; +} + +.wallet-badge { + padding: 8rpx 16rpx; + border-radius: 999rpx; + background: rgba(126, 108, 255, 0.18); + font-size: 20rpx; + color: #dfe7ff; +} + +.empty-panel { + padding: 36rpx 28rpx; + border: 1px solid rgba(149, 162, 220, 0.16); + border-radius: 16rpx; + background: linear-gradient( + 180deg, + rgba(54, 62, 96, 0.94), + rgba(39, 50, 84, 0.92) + ); + text-align: center; +} + +.empty-title { + font-size: 30rpx; + font-weight: 700; + color: $asset-text-main; +} + +.empty-desc { + margin-top: 14rpx; + font-size: 24rpx; + line-height: 1.7; + color: $asset-text-muted; +} + +.page-hero { + display: flex; + flex-direction: column; + align-items: center; + padding: 12rpx 0 20rpx; +} + +.page-hero__mark { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 110rpx; + height: 110rpx; + border-radius: 50%; + background: linear-gradient(180deg, #1f4a72 0%, #1a3464 100%); +} + +.page-hero__ring { + position: absolute; + left: 50%; + top: 50%; + border-radius: 50%; + transform: translate(-50%, -50%); +} + +.page-hero__ring--outer { + width: 110rpx; + height: 110rpx; + border: 4rpx solid rgba(63, 220, 255, 0.9); + box-shadow: 0 0 0 6rpx rgba(80, 225, 255, 0.08); +} + +.page-hero__ring--inner { + width: 88rpx; + height: 88rpx; + border: 3rpx solid rgba(98, 231, 255, 0.42); +} + +.page-hero__text { + position: relative; + z-index: 1; + font-size: 52rpx; + font-weight: 800; + font-style: italic; + color: #42d9ff; +} + +.page-hero__value { + margin-top: 16rpx; + font-size: 24rpx; + font-weight: 700; + color: $asset-text-main; +} + +.page-hero__desc { + margin-top: 8rpx; + font-size: 20rpx; + line-height: 1.6; + color: rgba(255, 255, 255, 0.66); + text-align: center; +} + +.submit-wrap { + display: flex; + flex-direction: column; + align-items: center; + padding: 24rpx 0 8rpx; +} + +.submit-wrap .primary-button { + width: 360rpx; +} + +.record-link { + margin-top: 18rpx; + font-size: 22rpx; + text-decoration: underline; + color: rgba(222, 232, 255, 0.86); +} diff --git a/styles/tokens.scss b/styles/tokens.scss new file mode 100644 index 0000000..c05b4c3 --- /dev/null +++ b/styles/tokens.scss @@ -0,0 +1,27 @@ +$asset-bg-deep: #08162e; +$asset-bg-mid: #10264a; +$asset-bg-soft: #173664; +$asset-panel: rgba(18, 39, 77, 0.96); +$asset-panel-soft: rgba(21, 45, 88, 0.9); +$asset-paper: #edf4ff; +$asset-paper-card: #ffffff; +$asset-paper-line: rgba(34, 64, 110, 0.12); +$asset-text-main: #ffffff; +$asset-text-muted: rgba(255, 255, 255, 0.78); +$asset-text-subtle: #8fa7cf; +$asset-text-dark: #112446; +$asset-text-grey: #6e83a7; +$asset-accent: #4cc9ff; +$asset-accent-strong: #5a71ff; +$asset-accent-soft: rgba(76, 201, 255, 0.12); +$asset-success: #5ad7a1; +$asset-warning: #ffbf66; +$asset-danger: #ff7285; +$asset-radius-lg: 28rpx; +$asset-radius-xl: 36rpx; +$asset-shadow: 0 24rpx 60rpx rgba(0, 0, 0, 0.18); +$asset-shadow-soft: 0 18rpx 40rpx rgba(8, 22, 46, 0.12); +$asset-space-sm: 16rpx; +$asset-space-md: 24rpx; +$asset-space-lg: 32rpx; +$asset-space-xl: 40rpx; diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js new file mode 100644 index 0000000..5fec4f3 --- /dev/null +++ b/uni.promisify.adaptor.js @@ -0,0 +1,13 @@ +uni.addInterceptor({ + returnValue (res) { + if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { + return res; + } + return new Promise((resolve, reject) => { + res.then((res) => { + if (!res) return resolve(res) + return res[0] ? reject(res[0]) : resolve(res[1]) + }); + }); + }, +}); \ No newline at end of file diff --git a/uni.scss b/uni.scss new file mode 100644 index 0000000..62eb87b --- /dev/null +++ b/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16px; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/utils/request.js b/utils/request.js new file mode 100644 index 0000000..b79ec37 --- /dev/null +++ b/utils/request.js @@ -0,0 +1,100 @@ +import serviceConfig from "../config/service"; +import { getCurrentWebviewToken } from "./webview-token"; + +let loadingCount = 0; + +function isAbsoluteUrl(url) { + return /^https?:\/\//i.test(url || ""); +} + +function buildRequestUrl(url) { + if (isAbsoluteUrl(url)) { + return url; + } + + return serviceConfig.BASE_URL + url; +} + +function showGlobalLoading(options) { + if (!options || !options.showLoading) { + return false; + } + + loadingCount += 1; + + if (loadingCount === 1) { + uni.showLoading({ + title: options.loadingText || "加载中", + mask: options.loadingMask !== false, + }); + } + + return true; +} + +function hideGlobalLoading(shouldHide) { + if (!shouldHide) { + return; + } + + loadingCount = Math.max(0, loadingCount - 1); + + if (loadingCount === 0) { + uni.hideLoading(); + } +} + +export default function request(options) { + const method = options.method || "GET"; + const defaultContentType = + method === "POST" + ? "application/x-www-form-urlencoded; charset=UTF-8" + : "application/json"; + const token = getCurrentWebviewToken(); + const requestHeader = Object.assign( + { + "Content-Type": defaultContentType, + }, + options.header || {}, + ); + + if (token) { + const bearerToken = "Bearer " + token; + requestHeader["Authori-zation"] = bearerToken; + requestHeader.Authorization = bearerToken; + } + const shouldHandleLoading = showGlobalLoading(options); + + return new Promise(function (resolve, reject) { + uni.request({ + url: buildRequestUrl(options.url), + method: method, + data: options.data || {}, + header: requestHeader, + timeout: serviceConfig.TIMEOUT, + success: function (response) { + const statusCode = response.statusCode || 0; + if (statusCode >= 200 && statusCode < 300) { + resolve(response.data); + return; + } + + reject({ + statusCode: statusCode, + message: (response.data && response.data.message) || "接口请求失败", + raw: response, + }); + }, + fail: function (error) { + reject({ + statusCode: 0, + message: error.errMsg || "网络异常", + raw: error, + }); + }, + complete: function () { + hideGlobalLoading(shouldHandleLoading); + }, + }); + }); +} diff --git a/utils/webview-token.js b/utils/webview-token.js new file mode 100644 index 0000000..027dc48 --- /dev/null +++ b/utils/webview-token.js @@ -0,0 +1,62 @@ +function findTokenInText(text) { + if (!text) { + return ""; + } + + const queryIndex = text.indexOf("?"); + if (queryIndex === -1) { + return ""; + } + + const rawQueryText = text.slice(queryIndex + 1); + const hashIndex = rawQueryText.indexOf("#"); + const queryText = + hashIndex === -1 ? rawQueryText : rawQueryText.slice(0, hashIndex); + const search = new URLSearchParams(queryText); + return search.get("token") || ""; +} + +export function extractTokenFromUrl(url) { + if (!url) { + return ""; + } + + const directToken = findTokenInText(url); + if (directToken) { + return directToken; + } + + const hashIndex = url.indexOf("#"); + if (hashIndex === -1) { + return ""; + } + + return findTokenInText(url.slice(hashIndex + 1)); +} + +export function getCurrentWebviewUrl() { + // #ifdef H5 + return window.location.href || ""; + // #endif + + // #ifdef APP-PLUS + if (typeof plus === "undefined" || !plus.webview) { + return ""; + } + + const currentWebview = + plus.webview.currentWebview() || plus.webview.getLaunchWebview(); + + if (!currentWebview || typeof currentWebview.getURL !== "function") { + return ""; + } + + return currentWebview.getURL() || ""; + // #endif + + return ""; +} + +export function getCurrentWebviewToken() { + return extractTokenFromUrl(getCurrentWebviewUrl()); +}