$(document).ready(function() {
// 立即显示默认信息
$('#siteName').text("应用商店");
// 预加载数据
setTimeout(loadData, 0);
let allApps = [];
const PAGE_SIZE = 15;
let currentPage = 1;
let currentApps = [];
// 添加下载弹窗相关函数
function showDownloadModal(app) {
// 从页面元素中获取 rawURL
const rawURL = $('a[href^="ESign://addsource?url="]').attr('href').replace('ESign://addsource?url=', '');
// 从PHP配置中获取下载选项
const downloadOptions = [{"url":"ESign:\/\/addsource?url=","image":"\/app\/images\/easy-sign.png","text":"\u8f7b\u677e\u7b7e\u6e90\u4e0b\u8f7d"},{"url":"nsk-sign:\/\/addsource?url=","image":"\/app\/images\/universal-sign.png","text":"\u5168\u80fd\u7b7e\u6e90\u4e0b\u8f7d"},{"url":"wnq-signtool:\/\/addsource?url=","image":"\/app\/images\/all-sign.png","text":"\u4e07\u80fd\u7b7e\u6e90\u4e0b\u8f7d"},{"url":"hillmountios:\/\/addsource?url=","image":"\/app\/images\/hillmountios.png","text":"\u841d\u535c\u7b7e\u6e90\u4e0b\u8f7d"},{"url":"https:\/\/xiaoluobo.ioszs.my\/","image":"\/app\/images\/certificate.png","text":"\u8d2d\u4e70\u4e2a\u4eba\u8bc1\u4e66"}];
// 生成下载选项HTML
let downloadOptionsHtml = '';
downloadOptions.forEach(option => {
const url = option.url.includes('url=')
? option.url + rawURL
: option.url;
downloadOptionsHtml += `
${option.text}
`;
});
// 添加联系客服选项
downloadOptionsHtml += `
联系客服
`;
// 创建弹窗HTML
const modalHtml = `
${app.lock === '0' ?
`
请选择下载方式
` :
`
添加到软件源下载!有事联系客服!
`}
${downloadOptionsHtml}
`;
// 添加到body
$('body').append(modalHtml);
// 绑定关闭事件
$('.download-modal-close, .download-modal-backdrop').on('click', function() {
$('.download-modal-container').remove();
});
// 如果是免费应用,添加直接下载按钮
if (app.lock === '0' && app.downloadURL) {
$('.download-options').prepend(`
直接下载
`);
// 直接下载按钮点击事件
$('.direct-download').on('click', function() {
showToast('开始下载...', 'success');
$('.download-modal-container').remove();
});
}
}
function loadData() {
$.ajax({
url: '/api/list',
method: 'GET',
dataType: 'json',
success: function(response) {
// 先更新站点信息
updateSiteInfo(response);
if (!response || !response.apps) {
showError('API 返回的数据格式错误');
return;
}
// 处理应用数据
allApps = Array.isArray(response.apps) ? response.apps : Object.values(response.apps || {});
// 格式化数据
allApps = allApps.map(app => ({
versionDate: app.versionDate || new Date().toISOString(),
size: app.size || 0,
...app
}));
// 初始显示"最近7天更新"
const now = new Date();
const weekAgo = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));
currentApps = allApps
.filter(app => {
const updateDate = new Date(app.versionDate);
return updateDate >= weekAgo;
})
.sort((a, b) => new Date(b.versionDate) - new Date(a.versionDate))
.slice(0, PAGE_SIZE * 2);
renderApps(currentApps, true);
updateStats(allApps);
},
error: function(xhr, status, error) {
console.error('请求失败:', status, error);
showError('网络错误: ' + (xhr.status || '未知'));
}
});
}
function updateAdditionalInfo(data) {
// 解析消息中的时间信息
const refreshTimeMatch = data.message.match(/您上次刷新时间:([^❤]+)/);
const expireTimeMatch = data.message.match(/解锁码到期时间:([^❤]+)/);
const appCountMatch = data.message.match(/软件源个数:(\d+)/);
// 更新额外信息显示
$('#additionalInfo').html(`
上次刷新: ${refreshTimeMatch ? refreshTimeMatch[1].trim() : '未知'}
到期时间: ${expireTimeMatch ? expireTimeMatch[1].trim() : '未知'}
资源总数: ${appCountMatch ? appCountMatch[1] : '0'}个
`);
}
function updateStats(apps) {
const totalApps = apps.length;
const now = new Date();
const weekAgo = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));
// 计算最近7天更新的应用数量
const recentlyUpdated = apps.filter(app => {
const updateDate = new Date(app.versionDate);
return updateDate >= weekAgo;
}).length;
const freeApps = apps.filter(app => app.lock === '0').length;
const paidApps = totalApps - freeApps;
$('#appStats').html(`
总计应用:${totalApps}
近期更新:${recentlyUpdated}
免费应用:${freeApps}
付费应用:${paidApps}
`);
}
function renderApps(apps, isNewFilter = false) {
const appList = $('#appList');
const skeleton = $('#skeletonLoader');
if (isNewFilter) {
// 显示骨架屏
skeleton.show();
appList.empty();
// 延迟渲染以避免阻塞UI
setTimeout(() => {
skeleton.hide();
const fragment = document.createDocumentFragment();
apps.forEach(app => {
const card = $(createAppCard(app))[0];
fragment.appendChild(card);
});
appList.append(fragment);
// 控制加载更多按钮
$('#loadMoreBtn').toggle(apps.length >= PAGE_SIZE);
}, 100);
} else {
// 追加更多应用
const fragment = document.createDocumentFragment();
apps.forEach(app => {
const card = $(createAppCard(app))[0];
fragment.appendChild(card);
});
appList.append(fragment);
}
}
function filterApps(type) {
currentPage = 1;
if (type === 'all') {
// 近期更新:只显示最近7天更新的应用
const now = new Date();
const weekAgo = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));
currentApps = allApps
.filter(app => {
const updateDate = new Date(app.versionDate);
return updateDate >= weekAgo;
})
.sort((a, b) => new Date(b.versionDate) - new Date(a.versionDate));
} else {
// 其他分类:根据type值精确匹配
currentApps = allApps
.filter(app => {
// 确保正确处理类型0
const appType = app.type === 0 ? 0 : parseInt(app.type) || 0;
const filterType = type === '0' ? 0 : parseInt(type) || 0;
return appType === filterType;
})
.sort((a, b) => new Date(b.versionDate) - new Date(a.versionDate));
}
renderApps(currentApps, true);
}
function formatFileSize(bytes) {
if (bytes === 0 || !bytes) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
const now = new Date();
const diff = now - date;
const oneDay = 24 * 60 * 60 * 1000;
const oneWeek = 7 * oneDay;
if (date.toDateString() === now.toDateString()) {
return `今天 ${date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}`;
}
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() - 1);
if (date.toDateString() === yesterday.toDateString()) {
return `昨天 ${date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}`;
}
if (diff < oneWeek) {
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
return `${weekdays[date.getDay()]} ${date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}`;
}
if (date.getFullYear() === now.getFullYear()) {
return date.toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
}).replace('/', '-');
}
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
}).replace('/', '-').replace('/', '-');
}
function createAppCard(app) {
const appType = app.type === 0 ? 0 : parseInt(app.type) || 0;
return `
${getTypeBadge(app.type)}
${app.versionDescription}
`;
}
$(document).on('click', '.btn-download', function(e) {
e.preventDefault();
e.stopPropagation();
const appData = $(this).data('app');
if (!appData) return;
if (appData.lock === '0' && !appData.downloadURL) {
showToast('暂无下载地址,请稍后再试', 'info');
return;
}
showDownloadModal(appData);
});
window.showToast = function(message, type = 'info') {
$('.toast-container').remove();
const toast = `
`;
$('body').append(toast);
setTimeout(() => {
$('.toast-container').fadeOut(300, function() {
$(this).remove();
});
}, 3000);
};
function getToastIcon(type) {
const icons = {
success: 'fa-check-circle',
warning: 'fa-exclamation-circle',
error: 'fa-times-circle',
info: 'fa-info-circle'
};
return icons[type] || icons.info;
}
function getTypeBadge(type) {
const typeNum = type === 0 ? 0 : parseInt(type) || 0;
const types = {
0: ['默认', 'fas fa-star'],
1: ['应用', 'fas fa-mobile-alt'],
2: ['游戏', 'fas fa-gamepad'],
3: ['影音', 'fas fa-film'],
4: ['工具', 'fas fa-tools'],
5: ['插件', 'fas fa-puzzle-piece']
};
const [text, icon] = types[typeNum] || ['未知', 'fas fa-question'];
return `
${text}
`;
}
function showError(message) {
alert(message);
}
const searchInput = $('#searchInput');
const clearSearch = $('#clearSearch');
let searchTimeout;
function handleSearch() {
const searchTerm = searchInput.val().toLowerCase().trim();
clearSearch.toggle(searchTerm.length > 0);
if (searchTerm) {
$('.category-btn').removeClass('active');
} else {
$('.category-btn[data-type="all"]').addClass('active');
}
currentPage = 1;
currentApps = allApps
.filter(app => {
return (app.name.toLowerCase().includes(searchTerm) ||
app.versionDescription.toLowerCase().includes(searchTerm));
})
.sort((a, b) => new Date(b.versionDate) - new Date(a.versionDate));
renderApps(currentApps, true);
}
searchInput.on('input', function() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(handleSearch, 300);
});
clearSearch.click(function() {
searchInput.val('');
handleSearch();
searchInput.focus();
});
$('.category-btn').click(function() {
$('.category-btn').removeClass('active');
$(this).addClass('active');
searchInput.val('');
clearSearch.hide();
filterApps($(this).data('type'));
});
$(document).on('click', '#loadMoreBtn', function() {
currentPage++;
renderApps(currentApps);
});
function updateSiteInfo(data) {
if (!data) return;
// 更新站点图标和名称
if (data.name) {
$('#siteName').text(data.name);
}
if (data.sourceicon) {
$('#sourceicon')
.attr('src', data.sourceicon)
.on('error', function() {
$(this).attr('src', '/app/images/default-icon.png');
})
.css('display', 'block');
}
// 更新签名工具链接
if (data.sourceURL) {
$('a[href^="ESign://addsource?url="]').attr('href', `ESign://addsource?url=${data.sourceURL}`);
$('a[href^="nsk-sign://addsource?url="]').attr('href', `nsk-sign://addsource?url=${data.sourceURL}`);
$('a[href^="wnq-signtool://addsource?url="]').attr('href', `wnq-signtool://addsource?url=${data.sourceURL}`);
$('a[href^="hillmountios://addsource?url="]').attr('href', `hillmountios://addsource?url=${data.sourceURL}`);
}
// 更新支付链接 - 确保正确处理{payURL}占位符
if (data.payURL) {
// 替换所有包含{payURL}的链接
$('a[href*="{payURL}"]').each(function() {
$(this).attr('href', data.payURL);
});
// 替换href="{payURL}"的链接
$('a[href="{payURL}"]').attr('href', data.payURL);
}
// 更新额外信息
if (data.message) {
updateAdditionalInfo(data);
}
}
loadData();
});