首页工具区替换为已上架应用宫格: /api/mp/apps 动态渲染(排除授权示例), 点击带身份跳转, 前8个+展开收起 (v26090719)

This commit is contained in:
2026-09-08 01:42:03 +08:00
parent c59c7a71c7
commit 90f28b8ec9
3 changed files with 90 additions and 60 deletions

View File

@@ -170,6 +170,72 @@
location.href = u;
}
/* ================= 首页工具区 = 已上架应用宫格 =================
数据:box_app /api/mp/apps(应用管理统一维护图标/名称/链接)。
范围:isPublished=1 且有 url;排除授权示例(wx-h5-demo,开发者用的)。
交互:默认前 8 个,「所有工具 ›/展开全部工具」展开收起;点击带身份跳转。 */
function appTileColor(name) {
const PALETTE = ['#F2917A', '#E8A2B8', '#8FB4E3', '#7FC8A9', '#E3B771', '#A99BD1', '#73BFB2', '#DE8F6E'];
let h = 0;
for (let i = 0; i < (name || '').length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
return PALETTE[h % PALETTE.length];
}
function jumpApp(url) {
haptic();
const oid = hashParam('openid');
const uid = hashParam('unionid');
const q = [];
if (oid) q.push('openid=' + encodeURIComponent(oid));
if (uid) q.push('unionid=' + encodeURIComponent(uid));
if (q.length) url += (url.indexOf('?') >= 0 ? '&' : '?') + q.join('&');
if (oid) url += '#openid=' + encodeURIComponent(oid);
location.href = url;
}
function renderAppGrid(apps) {
const grid = $('#appGrid'), moreBtn = $('#appMore'), dockAll = $('#dockAll');
if (!grid) return;
grid.innerHTML = apps.map(a => {
const ico = a.logo || a.icon || '';
const name = a.name || a.identifier || '应用';
const color = a.colorTheme || appTileColor(name);
const img = ico ? '<img src="' + ico + '" alt="" loading="lazy">' : (name.slice(0, 1));
return '<button class="app-tile ripple" data-url="' + encodeURIComponent(a.url) + '">' +
'<span class="app-ico" style="background:' + color + '">' + img + '</span>' +
'<span class="app-tile-name">' + name + '</span></button>';
}).join('');
/* 磁贴点击(事件委托,innerHTML 重建后不用重绑) */
grid.onclick = function (e) {
const t = e.target.closest('.app-tile');
if (t && t.dataset.url) jumpApp(decodeURIComponent(t.dataset.url));
};
if (apps.length > 8) {
moreBtn.style.display = 'block';
dockAll.style.display = '';
}
}
function toggleAppGrid() {
const grid = $('#appGrid'), moreBtn = $('#appMore'), dockAll = $('#dockAll');
const ex = grid.classList.toggle('expanded');
moreBtn.style.display = ex ? 'none' : 'block';
dockAll.textContent = ex ? '收起 ›' : '所有工具 ›';
haptic();
}
function loadPublishedApps() {
fetch('/api/mp/apps?isPublished=1&pageSize=200')
.then(r => (r.ok ? r.json() : null))
.then(d => {
const items = (d && d.result && d.result.items) || [];
const apps = items
.filter(a => a.url && !/wx-h5-demo/i.test(a.url)) /* 排除授权示例 */
.sort((x, y) => (x.seq || 0) - (y.seq || 0) || (x.no || 0) - (y.no || 0));
renderAppGrid(apps);
})
.catch(function () { /* 拉不到就保持空宫格,不影响其余页面 */ });
}
$('#appMore').addEventListener('click', toggleAppGrid);
$('#dockAll').addEventListener('click', toggleAppGrid);
loadPublishedApps();
function go(name) {
/* 「档案」先跳孕期档案 H5(一期屏蔽内置档案屏,原因见 goArchiveH5 注释) */
if (name === 'archive') { goArchiveH5(); return; }