1413 lines
52 KiB
JavaScript
1413 lines
52 KiB
JavaScript
(function () {
|
||
var ASSET_BASE = './assets/other/';
|
||
var COMMON_FALLBACK = {
|
||
loading: 'Loading',
|
||
rule: 'rule',
|
||
rewards: 'Rewards',
|
||
balance: 'Balance',
|
||
noDate: 'No more data',
|
||
balanceNotEnough: 'Insufficient balance',
|
||
rewardUnavailable: 'Rewards are not available yet',
|
||
requestFailed: 'Request failed',
|
||
};
|
||
var WHEEL_FALLBACK = {
|
||
classic: 'Classic',
|
||
inLove: 'luxury',
|
||
advanced: 'Advanced',
|
||
historyRecord: 'History Record',
|
||
rewardTips:
|
||
'Congratulations on receiving: A precious gift worth {} gold coins! Already put in the backpack',
|
||
drawAgain: 'Draw again',
|
||
totalRewards: 'total rewards:',
|
||
userAward: 'Congratulations to {1} for receiving the {2} award',
|
||
rule1: '1. Select a wheel and draw with coins.',
|
||
rule2: '2. Rewards are issued to the backpack after a successful draw.',
|
||
rule3: '3. This activity has no relationship with Apple or Google.',
|
||
};
|
||
var TABS = [
|
||
{ key: 'classic', labelKey: 'classic' },
|
||
{ key: 'luxury', labelKey: 'inLove' },
|
||
{ key: 'advanced', labelKey: 'advanced' },
|
||
];
|
||
var CONFIGS = {
|
||
classic: {
|
||
key: 'classic',
|
||
amountKey: 'luckyBoxDrawAmount',
|
||
enabledKey: 'luckyBoxEnabled',
|
||
pageSize: 10,
|
||
type: 'grid',
|
||
gridClass: 'grid-classic',
|
||
stageClass: 'wheel-classic',
|
||
lightPrefix: 'lucky_box_',
|
||
minSpeed: 2000,
|
||
slotCount: 8,
|
||
sequence: [1, 2, 3, 5, 8, 7, 6, 4, 1, 2, 3, 5, 8, 7, 6, 4, 1],
|
||
},
|
||
luxury: {
|
||
key: 'luxury',
|
||
amountKey: 'middleLuckyBoxDrawAmount',
|
||
enabledKey: 'middleLuckyBoxEnabled',
|
||
pageSize: 20,
|
||
type: 'round',
|
||
gridClass: 'grid-luxury',
|
||
stageClass: 'wheel-luxury',
|
||
lightPrefix: 'lucky_box_tow_',
|
||
hasMarqueeBox: true,
|
||
},
|
||
advanced: {
|
||
key: 'advanced',
|
||
amountKey: 'advancedLuckyBoxDrawAmount',
|
||
enabledKey: 'advancedLuckyBoxEnabled',
|
||
pageSize: 10,
|
||
type: 'grid',
|
||
gridClass: 'grid-advanced',
|
||
stageClass: 'wheel-advanced',
|
||
minSpeed: 1000,
|
||
hasMarqueeBox: true,
|
||
slotCount: 12,
|
||
sequence: [1, 2, 3, 4, 6, 8, 12, 11, 10, 9, 7, 5, 1],
|
||
},
|
||
};
|
||
|
||
function query() {
|
||
var params = new URLSearchParams(window.location.search || '');
|
||
var hash = window.location.hash || '';
|
||
if (hash.indexOf('?') >= 0) {
|
||
new URLSearchParams(hash.split('?').slice(1).join('?')).forEach(
|
||
function (value, key) {
|
||
if (!params.has(key)) params.set(key, value);
|
||
}
|
||
);
|
||
}
|
||
return params;
|
||
}
|
||
|
||
function readQuery(name) {
|
||
return query().get(name) || '';
|
||
}
|
||
|
||
function toast(message) {
|
||
if (window.HyAppToast && window.HyAppToast.show) {
|
||
window.HyAppToast.show(message);
|
||
return;
|
||
}
|
||
window.alert(message);
|
||
}
|
||
|
||
function stateFor() {
|
||
return {
|
||
rewards: [],
|
||
gridItems: [],
|
||
activeIndex: null,
|
||
isSpinning: false,
|
||
spinInterval: null,
|
||
spinSpeed: 50,
|
||
targetIndex: null,
|
||
goldBtn: [
|
||
{ name: '1 Time', value: 1 },
|
||
{ name: '10 Time', value: 10 },
|
||
{ name: '50 Time', value: 50 },
|
||
],
|
||
activeBtnIndex: 1,
|
||
showRule: false,
|
||
showRecord: false,
|
||
showReward: false,
|
||
currentReward: { rewardValue: 0, rewards: [] },
|
||
drawAmount: 0,
|
||
historyRecord: [],
|
||
roomId: '',
|
||
loading: false,
|
||
finished: true,
|
||
pageNo: 1,
|
||
isInit: false,
|
||
pageLoading: false,
|
||
drawFailed: false,
|
||
currentBackground: 'light',
|
||
backgroundInterval: null,
|
||
rotateDeg: 0,
|
||
rotationTimer: null,
|
||
};
|
||
}
|
||
|
||
function envelopeData(response) {
|
||
if (response && Object.prototype.hasOwnProperty.call(response, 'data'))
|
||
return response.data;
|
||
return response;
|
||
}
|
||
|
||
function firstPresentValue(source, keys) {
|
||
source = source || {};
|
||
for (var index = 0; index < keys.length; index += 1) {
|
||
var value = source[keys[index]];
|
||
if (value !== undefined && value !== null && value !== '')
|
||
return value;
|
||
}
|
||
return '';
|
||
}
|
||
|
||
function normalizeCompareValue(value) {
|
||
return String(value || '')
|
||
.trim()
|
||
.toLowerCase();
|
||
}
|
||
|
||
function resolveAssetUrl(url) {
|
||
var value = String(url || '').trim();
|
||
if (!value) return '';
|
||
if (
|
||
/^(https?:)?\/\//i.test(value) ||
|
||
/^(data|blob):/i.test(value) ||
|
||
value.indexOf('/') === 0 ||
|
||
value.indexOf('./') === 0 ||
|
||
value.indexOf('../') === 0
|
||
)
|
||
return value;
|
||
return ASSET_BASE + value;
|
||
}
|
||
|
||
function isDynamicAssetUrl(url) {
|
||
var clean = String(url || '')
|
||
.split('?')[0]
|
||
.split('#')[0];
|
||
return /\.(svga|pag|mp4|webm|mov)$/i.test(clean);
|
||
}
|
||
|
||
function positiveModulo(value, size) {
|
||
return ((value % size) + size) % size;
|
||
}
|
||
|
||
function roundPrizeAngle(index, count) {
|
||
var sectorAngle = 360 / Math.max(1, count || 1);
|
||
// 奖品图标本身按这个角度排布,指针停止也必须使用同一个基准,否则会停在扇区中间而不是奖品上。
|
||
return index * sectorAngle + sectorAngle / 50;
|
||
}
|
||
|
||
function normalizeImageObject(source, keys, fallbackKey) {
|
||
var target = Object.assign({}, source || {});
|
||
var image = firstPresentValue(target, keys);
|
||
if (image) target[fallbackKey] = resolveAssetUrl(image);
|
||
return target;
|
||
}
|
||
|
||
function normalizeGridItem(item) {
|
||
var target = Object.assign({}, item || {});
|
||
var merchandise = normalizeImageObject(
|
||
target.merchandise || target,
|
||
[
|
||
'coverUrl',
|
||
'cover',
|
||
'resourceCover',
|
||
'avatar',
|
||
'icon',
|
||
'imageUrl',
|
||
],
|
||
'coverUrl'
|
||
);
|
||
target.merchandise = merchandise;
|
||
return target;
|
||
}
|
||
|
||
function parseJSON(value) {
|
||
if (!value || typeof value !== 'string') return {};
|
||
try {
|
||
return JSON.parse(value);
|
||
} catch (error) {
|
||
return {};
|
||
}
|
||
}
|
||
|
||
function normalizeWheelReward(item) {
|
||
var target = Object.assign({}, item || {});
|
||
var metadata = parseJSON(
|
||
firstPresentValue(target, ['metadataJson', 'metadata_json'])
|
||
);
|
||
var rewardType = firstPresentValue(target, [
|
||
'rewardType',
|
||
'reward_type',
|
||
]);
|
||
var metadataResourceId = firstPresentValue(metadata, [
|
||
'resource_id',
|
||
'resourceId',
|
||
]);
|
||
var rewardId =
|
||
firstPresentValue(target, [
|
||
'rewardId',
|
||
'reward_id',
|
||
'resourceId',
|
||
'resource_id',
|
||
]) || metadataResourceId;
|
||
var metadataAssetUrl = firstPresentValue(metadata, [
|
||
'asset_url',
|
||
'assetUrl',
|
||
]);
|
||
var previewUrl =
|
||
firstPresentValue(metadata, ['preview_url', 'previewUrl']) ||
|
||
(isDynamicAssetUrl(metadataAssetUrl) ? '' : metadataAssetUrl) ||
|
||
firstPresentValue(target, [
|
||
'coverUrl',
|
||
'cover',
|
||
'resourceCover',
|
||
'avatar',
|
||
'icon',
|
||
'imageUrl',
|
||
'previewUrl',
|
||
'preview_url',
|
||
]);
|
||
var animationUrl = firstPresentValue(metadata, [
|
||
'animation_url',
|
||
'animationUrl',
|
||
]);
|
||
if (
|
||
!isDynamicAssetUrl(animationUrl) &&
|
||
isDynamicAssetUrl(metadataAssetUrl)
|
||
) {
|
||
animationUrl = metadataAssetUrl;
|
||
}
|
||
var displayName = firstPresentValue(target, [
|
||
'displayName',
|
||
'display_name',
|
||
'name',
|
||
'rewardName',
|
||
]);
|
||
var rewardCoins = Number(
|
||
firstPresentValue(target, [
|
||
'rewardCoins',
|
||
'reward_coins',
|
||
'value',
|
||
]) || 0
|
||
);
|
||
var displayValue = Number(
|
||
firstPresentValue(target, [
|
||
'displayValue',
|
||
'display_value',
|
||
'rewardValue',
|
||
'reward_value',
|
||
'value',
|
||
'rewardCoins',
|
||
'reward_coins',
|
||
]) || 0
|
||
);
|
||
var rewardCount = Number(
|
||
firstPresentValue(target, [
|
||
'rewardCount',
|
||
'reward_count',
|
||
'count',
|
||
]) || 1
|
||
);
|
||
|
||
target.id =
|
||
firstPresentValue(target, ['id', 'tierId', 'tier_id']) ||
|
||
rewardId ||
|
||
displayName;
|
||
target.tierId = firstPresentValue(target, ['tierId', 'tier_id']);
|
||
target.rewardId = rewardId;
|
||
target.rewardConfigId = firstPresentValue(target, [
|
||
'rewardConfigId',
|
||
'reward_config_id',
|
||
]);
|
||
target.resourceId =
|
||
firstPresentValue(target, ['resourceId', 'resource_id']) ||
|
||
metadataResourceId;
|
||
target.rewardType = rewardType;
|
||
target.value = displayValue || rewardCoins || rewardCount;
|
||
target.displayGoldAmount = target.value;
|
||
target.rewardCount = rewardCount;
|
||
target.count = rewardCount;
|
||
target.name = displayName;
|
||
target.coverUrl = resolveAssetUrl(previewUrl);
|
||
target.animationUrl =
|
||
rewardType === 'coin' ? '' : resolveAssetUrl(animationUrl);
|
||
target.merchandise = {
|
||
name: displayName,
|
||
coverUrl: target.coverUrl,
|
||
animationUrl: target.animationUrl,
|
||
};
|
||
return normalizeGridItem(target);
|
||
}
|
||
|
||
function normalizeWheelRewards(data) {
|
||
data = data || {};
|
||
var items = Array.isArray(data)
|
||
? data
|
||
: data.rewards || data.tiers || (data.config && data.config.tiers);
|
||
return Array.isArray(items)
|
||
? items.map(normalizeWheelReward).map(normalizeGridItem)
|
||
: [];
|
||
}
|
||
|
||
function visibleWheelRewards(data, config) {
|
||
var items = normalizeWheelRewards(data);
|
||
var slotCount = Number(config && config.slotCount);
|
||
// H5 格子数量是固定视觉契约:classic 只有 8 个外圈奖品位,center 是抽奖按钮。
|
||
// 如果旧配置或缓存仍返回第 9 个奖品,前端不渲染多余格子,避免按钮被奖品占位或抽奖动画索引错位。
|
||
return slotCount > 0 ? items.slice(0, slotCount) : items;
|
||
}
|
||
|
||
function normalizeRewardItem(item) {
|
||
var target = normalizeImageObject(
|
||
item,
|
||
[
|
||
'coverUrl',
|
||
'cover',
|
||
'resourceCover',
|
||
'avatar',
|
||
'icon',
|
||
'imageUrl',
|
||
'previewUrl',
|
||
'preview_url',
|
||
],
|
||
'coverUrl'
|
||
);
|
||
var metadata = parseJSON(
|
||
firstPresentValue(target, ['metadataJson', 'metadata_json'])
|
||
);
|
||
var assetUrl =
|
||
firstPresentValue(metadata, ['asset_url', 'assetUrl']) ||
|
||
firstPresentValue(target, ['assetUrl', 'asset_url']);
|
||
if (isDynamicAssetUrl(target.coverUrl)) target.coverUrl = '';
|
||
if (!target.coverUrl && assetUrl && !isDynamicAssetUrl(assetUrl)) {
|
||
target.coverUrl = resolveAssetUrl(assetUrl);
|
||
}
|
||
var animationUrl =
|
||
firstPresentValue(metadata, ['animation_url', 'animationUrl']) ||
|
||
firstPresentValue(target, ['animationUrl', 'animation_url']);
|
||
if (!isDynamicAssetUrl(animationUrl) && isDynamicAssetUrl(assetUrl)) {
|
||
animationUrl = assetUrl;
|
||
}
|
||
target.animationUrl = isDynamicAssetUrl(animationUrl)
|
||
? resolveAssetUrl(animationUrl)
|
||
: '';
|
||
return target;
|
||
}
|
||
|
||
function rewardCountValue(item) {
|
||
var value = Number(
|
||
firstPresentValue(item, ['count', 'rewardCount', 'reward_count']) ||
|
||
0
|
||
);
|
||
return value > 0 ? value : 1;
|
||
}
|
||
|
||
function rewardGroupKey(item) {
|
||
item = item || {};
|
||
var metadata = parseJSON(
|
||
firstPresentValue(item, ['metadataJson', 'metadata_json'])
|
||
);
|
||
var metadataResourceId = firstPresentValue(metadata, [
|
||
'resource_id',
|
||
'resourceId',
|
||
]);
|
||
return [
|
||
firstPresentValue(item, [
|
||
'resourceId',
|
||
'resource_id',
|
||
'rewardId',
|
||
'reward_id',
|
||
'id',
|
||
]) || metadataResourceId,
|
||
firstPresentValue(item, [
|
||
'rewardType',
|
||
'reward_type',
|
||
'resourceType',
|
||
'resource_type',
|
||
]) ||
|
||
firstPresentValue(metadata, ['resource_type', 'resourceType']),
|
||
firstPresentValue(item, ['animationUrl', 'animation_url']),
|
||
firstPresentValue(item, [
|
||
'coverUrl',
|
||
'cover_url',
|
||
'previewUrl',
|
||
'preview_url',
|
||
'cover',
|
||
]),
|
||
firstPresentValue(item, [
|
||
'name',
|
||
'displayName',
|
||
'display_name',
|
||
'rewardName',
|
||
'reward_name',
|
||
]),
|
||
rewardDisplayValue(item),
|
||
]
|
||
.map(function (value) {
|
||
return normalizeCompareValue(value);
|
||
})
|
||
.join('|');
|
||
}
|
||
|
||
function aggregateRewardItems(items) {
|
||
var map = {};
|
||
var list = [];
|
||
(items || []).forEach(function (item) {
|
||
var key = rewardGroupKey(item);
|
||
var count = rewardCountValue(item);
|
||
if (!map[key]) {
|
||
map[key] = Object.assign({}, item, {
|
||
count: 0,
|
||
rewardCount: 0,
|
||
});
|
||
list.push(map[key]);
|
||
}
|
||
map[key].count += count;
|
||
map[key].rewardCount = map[key].count;
|
||
});
|
||
return list;
|
||
}
|
||
|
||
function normalizeHistoryRecord(record) {
|
||
var target = Object.assign({}, record || {});
|
||
var rewards = Array.isArray(target.rewards) ? target.rewards : [];
|
||
target.rewards = rewards.map(normalizeRewardItem);
|
||
return target;
|
||
}
|
||
|
||
function normalizeHintItem(item) {
|
||
return normalizeImageObject(
|
||
item,
|
||
[
|
||
'avatar',
|
||
'coverUrl',
|
||
'cover',
|
||
'resourceCover',
|
||
'icon',
|
||
'imageUrl',
|
||
],
|
||
'avatar'
|
||
);
|
||
}
|
||
|
||
function prizePreviewSource(item) {
|
||
item = item || {};
|
||
var merchandise = item.merchandise || {};
|
||
var assetUrl =
|
||
firstPresentValue(merchandise, ['assetUrl', 'asset_url']) ||
|
||
firstPresentValue(item, ['assetUrl', 'asset_url']);
|
||
var animationUrl =
|
||
firstPresentValue(merchandise, ['animationUrl', 'animation_url']) ||
|
||
firstPresentValue(item, ['animationUrl', 'animation_url']);
|
||
if (!isDynamicAssetUrl(animationUrl) && isDynamicAssetUrl(assetUrl)) {
|
||
animationUrl = assetUrl;
|
||
}
|
||
var coverUrl =
|
||
firstPresentValue(merchandise, [
|
||
'coverUrl',
|
||
'cover',
|
||
'previewUrl',
|
||
'preview_url',
|
||
]) ||
|
||
firstPresentValue(item, [
|
||
'coverUrl',
|
||
'cover',
|
||
'resourceCover',
|
||
'previewUrl',
|
||
'preview_url',
|
||
'avatar',
|
||
'icon',
|
||
'imageUrl',
|
||
]) ||
|
||
(isDynamicAssetUrl(assetUrl) ? '' : assetUrl);
|
||
animationUrl = resolveAssetUrl(animationUrl);
|
||
return {
|
||
animationUrl: isDynamicAssetUrl(animationUrl) ? animationUrl : '',
|
||
coverUrl: resolveAssetUrl(coverUrl),
|
||
};
|
||
}
|
||
|
||
function normalizeDrawResult(data) {
|
||
var target = Object.assign({ rewardValue: 0, rewards: [] }, data || {});
|
||
var rewards = Array.isArray(target.rewards) ? target.rewards : [];
|
||
target.rawRewards = rewards.slice();
|
||
if (
|
||
rewards.length === 0 &&
|
||
firstPresentValue(target, [
|
||
'selectedTierId',
|
||
'selected_tier_id',
|
||
'rewardType',
|
||
'reward_type',
|
||
'rewardId',
|
||
'reward_id',
|
||
])
|
||
) {
|
||
rewards = [normalizeWheelReward(target)];
|
||
target.rawRewards = [Object.assign({}, data || {})];
|
||
}
|
||
target.rewards = rewards
|
||
.map(normalizeWheelReward)
|
||
.map(normalizeRewardItem);
|
||
target.rewards = aggregateRewardItems(target.rewards);
|
||
if (target.rewards.length > 0) {
|
||
var aggregateValue = target.rewards.reduce(function (sum, item) {
|
||
return sum + rewardDisplayValue(item) * rewardCountValue(item);
|
||
}, 0);
|
||
if (aggregateValue > 0) target.rewardValue = aggregateValue;
|
||
}
|
||
return target;
|
||
}
|
||
|
||
function normalizeWalletBalance(payload) {
|
||
var data = envelopeData(payload) || {};
|
||
var list = Array.isArray(data)
|
||
? data
|
||
: data.balances || data.values || data.list || [];
|
||
var info = Array.isArray(list)
|
||
? list.find(function (item) {
|
||
var type = firstPresentValue(item, [
|
||
'asset_type',
|
||
'assetType',
|
||
'walletType',
|
||
'type',
|
||
]);
|
||
return String(type || '').toUpperCase() === 'COIN';
|
||
})
|
||
: null;
|
||
return info
|
||
? Number(
|
||
firstPresentValue(info, [
|
||
'available_amount',
|
||
'availableAmount',
|
||
'balance',
|
||
'amount',
|
||
]) || 0
|
||
)
|
||
: 0;
|
||
}
|
||
|
||
function createCommandID(prefix) {
|
||
var random = '';
|
||
if (window.crypto && window.crypto.getRandomValues) {
|
||
var values = new Uint32Array(2);
|
||
window.crypto.getRandomValues(values);
|
||
random = values[0].toString(36) + values[1].toString(36);
|
||
} else {
|
||
random = Math.random().toString(36).slice(2);
|
||
}
|
||
return (
|
||
String(prefix || 'wheel') +
|
||
'_' +
|
||
Date.now().toString(36) +
|
||
'_' +
|
||
random
|
||
);
|
||
}
|
||
|
||
function firstDrawReward(drawResult) {
|
||
drawResult = drawResult || {};
|
||
if (
|
||
Array.isArray(drawResult.rawRewards) &&
|
||
drawResult.rawRewards.length > 0
|
||
)
|
||
return drawResult.rawRewards[0];
|
||
if (Array.isArray(drawResult.records) && drawResult.records.length > 0)
|
||
return drawResult.records[0];
|
||
if (Array.isArray(drawResult.rewards) && drawResult.rewards.length > 0)
|
||
return drawResult.rewards[0];
|
||
return null;
|
||
}
|
||
|
||
function rewardDisplayValue(reward) {
|
||
var metadata = parseJSON(
|
||
firstPresentValue(reward, ['metadataJson', 'metadata_json'])
|
||
);
|
||
return Number(
|
||
firstPresentValue(reward, [
|
||
'value',
|
||
'displayValue',
|
||
'display_value',
|
||
'displayGoldAmount',
|
||
'goldAmount',
|
||
'rewardValue',
|
||
'reward_value',
|
||
'rewardCoins',
|
||
'reward_coins',
|
||
'amount',
|
||
]) ||
|
||
firstPresentValue(metadata, [
|
||
'display_value',
|
||
'displayValue',
|
||
'coin_price',
|
||
'coinPrice',
|
||
'price',
|
||
'value',
|
||
]) ||
|
||
0
|
||
);
|
||
}
|
||
|
||
function gridItemDisplayValue(item) {
|
||
return Number(
|
||
firstPresentValue(item, [
|
||
'value',
|
||
'displayGoldAmount',
|
||
'goldAmount',
|
||
]) || 0
|
||
);
|
||
}
|
||
|
||
function resolveRewardTargetIndex(gridItems, drawResult) {
|
||
var reward = firstDrawReward(drawResult);
|
||
if (!reward || !Array.isArray(gridItems) || gridItems.length === 0)
|
||
return 0;
|
||
var rewardMetadata = parseJSON(
|
||
firstPresentValue(reward, ['metadataJson', 'metadata_json'])
|
||
);
|
||
var metadataResourceId = firstPresentValue(rewardMetadata, [
|
||
'resource_id',
|
||
'resourceId',
|
||
]);
|
||
var rewardId = normalizeCompareValue(
|
||
firstPresentValue(reward, [
|
||
'id',
|
||
'tierId',
|
||
'tier_id',
|
||
'selectedTierId',
|
||
'selected_tier_id',
|
||
'rewardId',
|
||
'reward_id',
|
||
'rewardConfigId',
|
||
'reward_config_id',
|
||
'resourceId',
|
||
'resource_id',
|
||
]) || metadataResourceId
|
||
);
|
||
var rewardName = normalizeCompareValue(
|
||
firstPresentValue(reward, [
|
||
'name',
|
||
'resourceName',
|
||
'resource_name',
|
||
'rewardName',
|
||
'reward_name',
|
||
]) ||
|
||
firstPresentValue(rewardMetadata, [
|
||
'resource_name',
|
||
'resourceName',
|
||
'resource_code',
|
||
'resourceCode',
|
||
])
|
||
);
|
||
var rewardCover = normalizeCompareValue(
|
||
firstPresentValue(reward, [
|
||
'coverUrl',
|
||
'cover_url',
|
||
'cover',
|
||
'resourceCover',
|
||
'resource_cover',
|
||
'previewUrl',
|
||
'preview_url',
|
||
]) ||
|
||
firstPresentValue(rewardMetadata, [
|
||
'preview_url',
|
||
'previewUrl',
|
||
'asset_url',
|
||
'assetUrl',
|
||
])
|
||
);
|
||
var rewardValue = rewardDisplayValue(reward);
|
||
|
||
function matchBy(predicate) {
|
||
for (var index = 0; index < gridItems.length; index += 1) {
|
||
if (predicate(gridItems[index] || {})) return index;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
var byId = rewardId
|
||
? matchBy(function (item) {
|
||
return (
|
||
normalizeCompareValue(
|
||
firstPresentValue(item, [
|
||
'id',
|
||
'rewardId',
|
||
'reward_id',
|
||
'rewardConfigId',
|
||
'reward_config_id',
|
||
'resourceId',
|
||
'resource_id',
|
||
])
|
||
) === rewardId
|
||
);
|
||
})
|
||
: -1;
|
||
if (byId >= 0) return byId;
|
||
|
||
var byCoverValue = rewardCover
|
||
? matchBy(function (item) {
|
||
var merchandise = item.merchandise || {};
|
||
return (
|
||
normalizeCompareValue(
|
||
firstPresentValue(merchandise, ['coverUrl', 'cover'])
|
||
) === rewardCover &&
|
||
(!rewardValue ||
|
||
gridItemDisplayValue(item) === rewardValue)
|
||
);
|
||
})
|
||
: -1;
|
||
if (byCoverValue >= 0) return byCoverValue;
|
||
|
||
var byNameValue = rewardName
|
||
? matchBy(function (item) {
|
||
var merchandise = item.merchandise || {};
|
||
return (
|
||
normalizeCompareValue(
|
||
firstPresentValue(merchandise, [
|
||
'name',
|
||
'resourceName',
|
||
'resource_name',
|
||
'rewardName',
|
||
'reward_name',
|
||
])
|
||
) === rewardName &&
|
||
(!rewardValue ||
|
||
gridItemDisplayValue(item) === rewardValue)
|
||
);
|
||
})
|
||
: -1;
|
||
if (byNameValue >= 0) return byNameValue;
|
||
|
||
var byValue = rewardValue
|
||
? matchBy(function (item) {
|
||
return gridItemDisplayValue(item) === rewardValue;
|
||
})
|
||
: -1;
|
||
return byValue >= 0 ? byValue : 0;
|
||
}
|
||
|
||
new Vue({
|
||
el: '#app',
|
||
data: function () {
|
||
return {
|
||
tabs: TABS,
|
||
currentLanguage: 'en',
|
||
currentPage: 'classic',
|
||
userBalance: 0,
|
||
pageLoading: true,
|
||
enabled: {
|
||
classic: true,
|
||
luxury: true,
|
||
advanced: true,
|
||
},
|
||
preview: {
|
||
open: false,
|
||
coverUrl: '',
|
||
animationUrl: '',
|
||
animationReady: false,
|
||
},
|
||
pages: {
|
||
classic: stateFor(),
|
||
luxury: stateFor(),
|
||
advanced: stateFor(),
|
||
},
|
||
};
|
||
},
|
||
computed: {
|
||
active: function () {
|
||
return this.pages[this.currentPage];
|
||
},
|
||
currentConfig: function () {
|
||
return CONFIGS[this.currentPage];
|
||
},
|
||
pageClass: function () {
|
||
return this.currentConfig.stageClass;
|
||
},
|
||
durationSpeed: function () {
|
||
var count = this.active.rewards.length || 1;
|
||
return 10 * count + 's';
|
||
},
|
||
marqueeRewards: function () {
|
||
return this.active.rewards.concat(this.active.rewards);
|
||
},
|
||
balanceEnough: function () {
|
||
return (
|
||
this.userBalance >=
|
||
this.active.goldBtn[this.active.activeBtnIndex].value *
|
||
this.active.drawAmount
|
||
);
|
||
},
|
||
},
|
||
created: function () {
|
||
this.currentLanguage = this.resolveLanguage();
|
||
document.documentElement.lang = this.currentLanguage;
|
||
document.documentElement.dir =
|
||
this.currentLanguage === 'ar' ? 'rtl' : 'ltr';
|
||
this.currentPage = this.firstPageFromURL();
|
||
this.initRoomID();
|
||
this.loadData();
|
||
},
|
||
beforeDestroy: function () {
|
||
this.closePrizePreview();
|
||
if (this.previewPlayer && this.previewPlayer.destroy) {
|
||
this.previewPlayer.destroy();
|
||
}
|
||
Object.keys(this.pages).forEach(
|
||
function (key) {
|
||
this.stopTimers(this.pages[key]);
|
||
}.bind(this)
|
||
);
|
||
},
|
||
methods: {
|
||
resolveLanguage: function () {
|
||
if (window.HyAppI18n && window.HyAppI18n.lang)
|
||
return window.HyAppI18n.lang();
|
||
return readQuery('appLanguage') || readQuery('lang') || 'en';
|
||
},
|
||
t: function (key) {
|
||
var fullKey = 'wheel.' + key;
|
||
var fallback = WHEEL_FALLBACK[key] || fullKey;
|
||
return window.HyAppI18n && window.HyAppI18n.t
|
||
? window.HyAppI18n.t(fullKey, fallback)
|
||
: fallback;
|
||
},
|
||
common: function (key) {
|
||
var fullKey = 'wheel.common.' + key;
|
||
var fallback = COMMON_FALLBACK[key] || key;
|
||
return window.HyAppI18n && window.HyAppI18n.t
|
||
? window.HyAppI18n.t(fullKey, fallback)
|
||
: fallback;
|
||
},
|
||
replaceOne: function (key, value) {
|
||
return this.t(key).replace(/{}/g, value);
|
||
},
|
||
replaceTwo: function (key, first, second) {
|
||
return this.t(key)
|
||
.replace(/\{1}/g, first)
|
||
.replace(/\{2}/g, second);
|
||
},
|
||
asset: function (name) {
|
||
return ASSET_BASE + name;
|
||
},
|
||
rewardTotalValue: function (drawResult) {
|
||
drawResult = drawResult || {};
|
||
var directValue = Number(
|
||
firstPresentValue(drawResult, [
|
||
'rewardValue',
|
||
'reward_value',
|
||
'totalValue',
|
||
'total_value',
|
||
]) || 0
|
||
);
|
||
if (directValue > 0) return directValue;
|
||
// 弹窗展示必须以当前聚合奖品为准:多抽会先合并相同资源,兜底重算可覆盖旧接口未返回总价值的情况。
|
||
return (drawResult.rewards || []).reduce(function (sum, item) {
|
||
return (
|
||
sum + rewardDisplayValue(item) * rewardCountValue(item)
|
||
);
|
||
}, 0);
|
||
},
|
||
formatRewardValue: function (value) {
|
||
var number = Number(value || 0);
|
||
return Number.isFinite(number)
|
||
? Math.floor(number).toLocaleString('en-US')
|
||
: '0';
|
||
},
|
||
rewardTotalText: function (drawResult) {
|
||
return this.formatRewardValue(
|
||
this.rewardTotalValue(drawResult)
|
||
);
|
||
},
|
||
ensurePreviewPlayer: function () {
|
||
var target = this.$refs.previewEffect;
|
||
if (!target || !window.HyAppEffectPlayer) return null;
|
||
if (
|
||
this.previewPlayer &&
|
||
this.previewPlayer.container === target
|
||
)
|
||
return this.previewPlayer;
|
||
if (this.previewPlayer && this.previewPlayer.destroy) {
|
||
this.previewPlayer.destroy();
|
||
}
|
||
this.previewPlayer = window.HyAppEffectPlayer.create(target, {
|
||
activeClass: 'is-active',
|
||
fit: 'contain',
|
||
loop: true,
|
||
muted: true,
|
||
svgaScript: '../../common/vendor/svga.min.js',
|
||
waitForWindowLoad: false,
|
||
});
|
||
return this.previewPlayer;
|
||
},
|
||
openPrizePreview: function (item) {
|
||
var source = prizePreviewSource(item);
|
||
if (!source.animationUrl && !source.coverUrl) return;
|
||
this.closePrizePreview();
|
||
this.preview = {
|
||
open: true,
|
||
coverUrl: source.coverUrl,
|
||
animationUrl: source.animationUrl,
|
||
animationReady: false,
|
||
};
|
||
// 动态资源优先,但必须保留静态图兜底;播放器加载失败时用户仍能看到预览图,不出现空黑层。
|
||
this.$nextTick(function () {
|
||
if (!this.preview.animationUrl) return;
|
||
var player = this.ensurePreviewPlayer();
|
||
if (!player) return;
|
||
var animationUrl = this.preview.animationUrl;
|
||
player
|
||
.play(animationUrl, {
|
||
svgaScript: '../../common/vendor/svga.min.js',
|
||
waitForWindowLoad: false,
|
||
})
|
||
.then(
|
||
function () {
|
||
if (
|
||
this.preview.open &&
|
||
this.preview.animationUrl === animationUrl
|
||
) {
|
||
this.preview.animationReady = true;
|
||
}
|
||
}.bind(this)
|
||
)
|
||
.catch(
|
||
function () {
|
||
if (
|
||
this.preview.open &&
|
||
this.preview.animationUrl === animationUrl
|
||
) {
|
||
this.preview.animationReady = false;
|
||
}
|
||
}.bind(this)
|
||
);
|
||
});
|
||
},
|
||
closePrizePreview: function () {
|
||
if (this.previewPlayer) this.previewPlayer.stop();
|
||
this.preview = {
|
||
open: false,
|
||
coverUrl: '',
|
||
animationUrl: '',
|
||
animationReady: false,
|
||
};
|
||
},
|
||
firstPageFromURL: function () {
|
||
var page = readQuery('wheel') || readQuery('tab') || '';
|
||
var hash = window.location.hash || '';
|
||
if (page === 'middle') page = 'luxury';
|
||
if (!page && hash.indexOf('advanced') !== -1) page = 'advanced';
|
||
if (!page && hash.indexOf('middle') !== -1) page = 'luxury';
|
||
return CONFIGS[page] ? page : 'classic';
|
||
},
|
||
initRoomID: function () {
|
||
var roomId = readQuery('roomId') || readQuery('room_id') || '';
|
||
Object.keys(this.pages).forEach(
|
||
function (key) {
|
||
this.pages[key].roomId = roomId;
|
||
}.bind(this)
|
||
);
|
||
},
|
||
wheelAPI: function () {
|
||
if (!window.HyAppAPI || !window.HyAppAPI.activityWheel) {
|
||
return null;
|
||
}
|
||
return window.HyAppAPI.activityWheel;
|
||
},
|
||
loadData: function () {
|
||
this.pageLoading = true;
|
||
return this.getUserWalletInfo()
|
||
.then(
|
||
function () {
|
||
this.pageLoading = false;
|
||
this.loadPageData(this.currentPage);
|
||
}.bind(this)
|
||
)
|
||
.catch(
|
||
function () {
|
||
// 钱包接口依赖登录态,失败时不能让活动页白屏;后续抽奖仍会由余额判断和服务端扣费共同拦截。
|
||
this.pageLoading = false;
|
||
this.loadPageData(this.currentPage);
|
||
}.bind(this)
|
||
);
|
||
},
|
||
getUserWalletInfo: function () {
|
||
if (!window.HyAppAPI || !window.HyAppAPI.wallet)
|
||
return Promise.reject(new Error('HyAppAPI unavailable'));
|
||
return window.HyAppAPI.wallet.balances('COIN').then(
|
||
function (res) {
|
||
this.userBalance = normalizeWalletBalance(res);
|
||
}.bind(this)
|
||
);
|
||
},
|
||
loadPageData: function (page) {
|
||
var state = this.pages[page];
|
||
var config = CONFIGS[page];
|
||
this.configHandle(state, config);
|
||
this.recordsHandle(state, config);
|
||
this.userRecordsHandle(state, config);
|
||
},
|
||
rewardsListHandle: function (state, config) {
|
||
var api = this.wheelAPI();
|
||
if (!api)
|
||
return Promise.reject(new Error('HyAppAPI unavailable'));
|
||
return api
|
||
.config(config.key)
|
||
.then(
|
||
function (res) {
|
||
state.isInit = true;
|
||
var data = envelopeData(res) || {};
|
||
var drawPrice = Number(
|
||
firstPresentValue(data, [
|
||
'drawPriceCoins',
|
||
'draw_price_coins',
|
||
'drawPrice',
|
||
'draw_price',
|
||
]) || 0
|
||
);
|
||
if (drawPrice > 0) state.drawAmount = drawPrice;
|
||
this.enabled[config.key] =
|
||
firstPresentValue(data, [
|
||
'enabled',
|
||
config.enabledKey,
|
||
]) !== false;
|
||
// 后端配置来自资源组:金币只要求预览图字段为空也能展示金额,礼物/道具/装扮则统一读取 metadata 的预览图和动态图。
|
||
state.gridItems = this.enabled[config.key]
|
||
? visibleWheelRewards(data, config)
|
||
: [];
|
||
}.bind(this)
|
||
)
|
||
.catch(function (error) {
|
||
state.isInit = true;
|
||
state.gridItems = [];
|
||
console.warn('wheel rewards load failed', error);
|
||
});
|
||
},
|
||
drawHandle: function (state, config) {
|
||
var api = this.wheelAPI();
|
||
if (!api) {
|
||
state.drawFailed = true;
|
||
this.stopSpinning(state);
|
||
toast(this.common('requestFailed'));
|
||
return Promise.resolve();
|
||
}
|
||
return api
|
||
.draw(config.key, {
|
||
command_id: createCommandID(config.key),
|
||
amount:
|
||
state.goldBtn[state.activeBtnIndex].value *
|
||
state.drawAmount,
|
||
times: state.goldBtn[state.activeBtnIndex].value,
|
||
roomId: state.roomId,
|
||
})
|
||
.then(
|
||
function (res) {
|
||
var data = normalizeDrawResult(envelopeData(res));
|
||
state.drawFailed = false;
|
||
if (data.coin_balance_after !== undefined) {
|
||
this.userBalance = Number(
|
||
data.coin_balance_after || 0
|
||
);
|
||
} else {
|
||
this.getUserWalletInfo();
|
||
}
|
||
this.recordsHandle(state, config);
|
||
state.currentReward = data;
|
||
state.targetIndex = resolveRewardTargetIndex(
|
||
state.gridItems,
|
||
data
|
||
);
|
||
}.bind(this)
|
||
)
|
||
.catch(
|
||
function (error) {
|
||
state.drawFailed = true;
|
||
this.stopSpinning(state);
|
||
toast(
|
||
error.message || this.common('requestFailed')
|
||
);
|
||
}.bind(this)
|
||
);
|
||
},
|
||
recordsHandle: function (state, config) {
|
||
var api = this.wheelAPI();
|
||
if (!api) return Promise.resolve();
|
||
state.loading = true;
|
||
if (state.isInit) state.pageNo += 1;
|
||
return api
|
||
.history(config.key, {
|
||
pageNo: state.pageNo,
|
||
pageSize: config.pageSize,
|
||
})
|
||
.then(function (res) {
|
||
var data = envelopeData(res) || {};
|
||
var records = Array.isArray(data.records)
|
||
? data.records
|
||
: [];
|
||
if (records.length === 0) state.finished = true;
|
||
state.loading = false;
|
||
// 历史记录和中奖弹窗使用同一批奖品字段,统一标准化后再追加,分页加载不会把裸文件名带进 DOM。
|
||
state.historyRecord = state.historyRecord.concat(
|
||
records.map(normalizeHistoryRecord)
|
||
);
|
||
})
|
||
.catch(function () {
|
||
state.loading = false;
|
||
state.finished = true;
|
||
});
|
||
},
|
||
userRecordsHandle: function (state, config) {
|
||
var api = this.wheelAPI();
|
||
if (!api) return Promise.resolve();
|
||
return api
|
||
.hints(config.key)
|
||
.then(function (res) {
|
||
var data = envelopeData(res) || {};
|
||
if (Array.isArray(data.values))
|
||
state.rewards = data.values.map(normalizeHintItem);
|
||
})
|
||
.catch(function () {
|
||
state.rewards = [];
|
||
});
|
||
},
|
||
configHandle: function (state, config) {
|
||
return this.rewardsListHandle(state, config).then(
|
||
function () {
|
||
if (!this.enabled[this.currentPage])
|
||
this.handleSelect(this.firstEnabledPage());
|
||
}.bind(this)
|
||
);
|
||
},
|
||
firstEnabledPage: function () {
|
||
for (var index = 0; index < TABS.length; index += 1) {
|
||
if (this.enabled[TABS[index].key]) return TABS[index].key;
|
||
}
|
||
return 'classic';
|
||
},
|
||
handleGoldBtn: function (index) {
|
||
this.active.activeBtnIndex = index;
|
||
},
|
||
handleSelect: function (tab) {
|
||
if (!CONFIGS[tab] || !this.enabled[tab]) return;
|
||
this.currentPage = tab;
|
||
if (!this.pages[tab].gridItems.length) this.loadPageData(tab);
|
||
},
|
||
startLottery: function () {
|
||
var state = this.active;
|
||
var config = this.currentConfig;
|
||
if (!state.gridItems.length || state.drawAmount <= 0) {
|
||
toast(this.common('rewardUnavailable'));
|
||
return;
|
||
}
|
||
if (!this.balanceEnough) {
|
||
toast(this.common('balanceNotEnough'));
|
||
return;
|
||
}
|
||
if (state.isSpinning) return;
|
||
state.showReward = false;
|
||
state.drawFailed = false;
|
||
state.isInit = false;
|
||
state.finished = false;
|
||
state.pageNo = 1;
|
||
state.historyRecord = [];
|
||
state.targetIndex = null;
|
||
state.activeIndex = null;
|
||
if (config.type === 'round') this.backgroundChange(state);
|
||
this.startSpinning(state, config);
|
||
this.drawHandle(state, config);
|
||
this.stopShowReward(state, config);
|
||
},
|
||
startSpinning: function (state, config) {
|
||
if (config.type === 'round') {
|
||
this.startRoundSpinning(state);
|
||
return;
|
||
}
|
||
state.isSpinning = true;
|
||
var sequenceIndex = 0;
|
||
var spinCount = 0;
|
||
var maxFastSpins = 25;
|
||
var speedIncrement = 100;
|
||
var minSpeed = config.minSpeed;
|
||
state.spinInterval = window.setInterval(
|
||
function () {
|
||
state.activeIndex = config.sequence[sequenceIndex] - 1;
|
||
sequenceIndex =
|
||
(sequenceIndex + 1) % config.sequence.length;
|
||
spinCount += 1;
|
||
if (config.key === 'classic') {
|
||
state.currentBackground =
|
||
state.currentBackground === 'light'
|
||
? 'light2'
|
||
: 'light';
|
||
}
|
||
if (
|
||
spinCount > maxFastSpins &&
|
||
state.targetIndex !== null
|
||
) {
|
||
state.spinSpeed += speedIncrement;
|
||
if (
|
||
Math.abs(
|
||
state.activeIndex - state.targetIndex
|
||
) <= 4
|
||
)
|
||
state.spinSpeed += speedIncrement * 2;
|
||
if (
|
||
state.activeIndex === state.targetIndex &&
|
||
state.spinSpeed >= minSpeed
|
||
)
|
||
this.stopSpinning(state);
|
||
}
|
||
}.bind(this),
|
||
state.spinSpeed
|
||
);
|
||
},
|
||
startRoundSpinning: function (state) {
|
||
var startWait = Date.now();
|
||
var waitStartDeg = state.rotateDeg;
|
||
state.isSpinning = true;
|
||
if (state.rotationTimer)
|
||
window.cancelAnimationFrame(state.rotationTimer);
|
||
|
||
var animateToTarget = function () {
|
||
var count = Math.max(1, state.gridItems.length || 1);
|
||
var targetIndex = Number(state.targetIndex || 0);
|
||
var duration = 4200;
|
||
var startTime = Date.now();
|
||
var startDeg = state.rotateDeg;
|
||
var currentDeg = positiveModulo(startDeg, 360);
|
||
var targetBaseDeg = roundPrizeAngle(targetIndex, count);
|
||
var forwardDelta = positiveModulo(
|
||
targetBaseDeg - currentDeg,
|
||
360
|
||
);
|
||
// 指针转盘必须等接口给出真实 targetIndex 后,从当前角度继续正向缓停到奖品图标角度;不能归零或使用假结果。
|
||
var targetDeg = startDeg + 360 * 6 + forwardDelta;
|
||
var animate = function () {
|
||
var elapsed = Date.now() - startTime;
|
||
var progress = Math.min(1, elapsed / duration);
|
||
var easedProgress = this.roundStopEase(progress);
|
||
state.rotateDeg =
|
||
startDeg + (targetDeg - startDeg) * easedProgress;
|
||
if (progress >= 1) {
|
||
state.isSpinning = false;
|
||
state.rotateDeg = targetDeg;
|
||
state.rotationTimer = null;
|
||
this.showDrawReward(state);
|
||
return;
|
||
}
|
||
state.rotationTimer =
|
||
window.requestAnimationFrame(animate);
|
||
}.bind(this);
|
||
animate();
|
||
}.bind(this);
|
||
|
||
var waitForTarget = function () {
|
||
if (
|
||
state.targetIndex !== null &&
|
||
state.targetIndex !== undefined
|
||
) {
|
||
animateToTarget();
|
||
return;
|
||
}
|
||
state.rotateDeg =
|
||
waitStartDeg + ((Date.now() - startWait) / 1000) * 720;
|
||
state.rotationTimer =
|
||
window.requestAnimationFrame(waitForTarget);
|
||
};
|
||
waitForTarget();
|
||
},
|
||
customEase: function (value) {
|
||
return value < 0.5
|
||
? 2 * value * value
|
||
: 1 - Math.pow(-2 * value + 2, 3) / 2;
|
||
},
|
||
roundStopEase: function (value) {
|
||
return 1 - Math.pow(1 - value, 4);
|
||
},
|
||
backgroundChange: function (state) {
|
||
state.backgroundInterval = window.setInterval(function () {
|
||
state.currentBackground =
|
||
state.currentBackground === 'light'
|
||
? 'light2'
|
||
: 'light';
|
||
}, 100);
|
||
},
|
||
showDrawReward: function (state) {
|
||
if (state.drawFailed || state.targetIndex === null) return;
|
||
if (
|
||
state.targetIndex !== null &&
|
||
state.targetIndex !== undefined &&
|
||
typeof state.activeIndex === 'number'
|
||
) {
|
||
state.activeIndex = state.targetIndex;
|
||
}
|
||
state.showReward = true;
|
||
state.isInit = true;
|
||
window.clearInterval(state.backgroundInterval);
|
||
},
|
||
stopShowReward: function (state, config) {
|
||
if (config && config.type === 'round') return;
|
||
window.setTimeout(
|
||
function () {
|
||
this.showDrawReward(state);
|
||
}.bind(this),
|
||
3300
|
||
);
|
||
},
|
||
stopSpinning: function (state) {
|
||
this.stopTimers(state);
|
||
state.isSpinning = false;
|
||
state.spinSpeed = 50;
|
||
state.activeIndex =
|
||
state.targetIndex !== null &&
|
||
state.targetIndex !== undefined
|
||
? state.targetIndex
|
||
: null;
|
||
},
|
||
stopTimers: function (state) {
|
||
window.clearInterval(state.spinInterval);
|
||
window.clearInterval(state.backgroundInterval);
|
||
if (state.rotationTimer)
|
||
window.cancelAnimationFrame(state.rotationTimer);
|
||
state.spinInterval = null;
|
||
state.rotationTimer = null;
|
||
},
|
||
getPrizePosition: function (index) {
|
||
var count = Math.max(1, this.active.gridItems.length || 1);
|
||
var radius = 150;
|
||
var center = { x: 50, y: 50 };
|
||
var itemAngle = roundPrizeAngle(index, count);
|
||
var angle = (itemAngle * Math.PI) / 180;
|
||
var distance = radius * 0.25;
|
||
var x = center.x + Math.sin(angle) * distance;
|
||
var y = center.y - Math.cos(angle) * distance;
|
||
var textRotation = itemAngle;
|
||
return {
|
||
left: x + '%',
|
||
top: y + '%',
|
||
transform:
|
||
'translate(-50%, -50%) rotate(' + textRotation + 'deg)',
|
||
};
|
||
},
|
||
buttonStyle: function (index) {
|
||
if (this.currentPage !== 'luxury') return {};
|
||
var name =
|
||
'lucky_box_tow_' +
|
||
(index === this.active.activeBtnIndex ? '' : 'un') +
|
||
'btn' +
|
||
(index + 1) +
|
||
'.png';
|
||
return { backgroundImage: 'url(' + this.asset(name) + ')' };
|
||
},
|
||
pointerStyle: function () {
|
||
if (this.currentPage !== 'luxury') return {};
|
||
return { '--pointer-rotate': this.active.rotateDeg + 'deg' };
|
||
},
|
||
formatDate: function (time, format) {
|
||
if (!time) return '';
|
||
var date = new Date(
|
||
Number(time) || String(time).replace(/-/g, '/')
|
||
);
|
||
function zero(value) {
|
||
return (value < 10 ? '0' : '') + value;
|
||
}
|
||
return (format || 'yyyy-MM-dd HH:mm:ss').replace(
|
||
/yyyy|MM|dd|HH|mm|ss/g,
|
||
function (token) {
|
||
if (token === 'yyyy') return zero(date.getFullYear());
|
||
if (token === 'MM') return zero(date.getMonth() + 1);
|
||
if (token === 'dd') return zero(date.getDate());
|
||
if (token === 'HH') return zero(date.getHours());
|
||
if (token === 'mm') return zero(date.getMinutes());
|
||
return zero(date.getSeconds());
|
||
}
|
||
);
|
||
},
|
||
},
|
||
});
|
||
})();
|