初始化兜爸心选 App 官网项目(构建与发布)

- src/:从线上 shop.douba.top/public/app 拉取的页面源码(v0.3.8)
- 版本号、更新日期、安装包大小改为模板变量,统一由 site.config.json 管理,
  安装包大小在构建时从 APK 实际字节数计算
- scripts/build.mjs:构建到 dist/,校验 APK、模板变量与资源引用
- scripts/deploy.mjs:与线上比对差异 → 上传 → 备份 → 原子切换 → 线上验证
- scripts/rollback.mjs、scripts/preview.mjs:回滚与本地预览
- AGENTS.md:项目说明、发版流程与服务器/nginx 约定

由 AI 助手协助完成。
This commit is contained in:
douba
2026-10-29 06:20:35 +00:00
commit 72648b4914
29 changed files with 1899 additions and 0 deletions

71
src/main.js Normal file
View File

@@ -0,0 +1,71 @@
/* 兜爸心选官网 · 轻交互(无依赖) */
(function () {
document.documentElement.classList.add('js');
var nav = document.getElementById('nav');
var onScroll = function () {
if (!nav) return;
nav.classList.toggle('is-stuck', window.scrollY > 24);
};
onScroll();
window.addEventListener('scroll', onScroll, { passive: true });
var items = document.querySelectorAll('[data-reveal]');
if ('IntersectionObserver' in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) {
e.target.classList.add('is-in');
io.unobserve(e.target);
}
});
}, { rootMargin: '0px 0px -12% 0px', threshold: 0.12 });
items.forEach(function (el) { io.observe(el); });
} else {
items.forEach(function (el) { el.classList.add('is-in'); });
}
// 同一时间只展开一个 FAQ
var qas = document.querySelectorAll('.qa');
qas.forEach(function (d) {
d.addEventListener('toggle', function () {
if (!d.open) return;
qas.forEach(function (o) { if (o !== d) o.open = false; });
});
});
// 首屏手机屏:6 张界面截图自动轮换(悬停暂停 / 切后台暂停 / 尊重"减少动效")
(function () {
var box = document.getElementById('heroSlides');
if (!box) return;
var slides = Array.prototype.slice.call(box.querySelectorAll('.hs-slide'));
if (slides.length < 2) return;
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)');
var idx = 0, timer = null, hover = false;
function show(n) {
slides[idx].classList.remove('is-on');
idx = (n + slides.length) % slides.length;
slides[idx].classList.add('is-on');
}
function stop() { if (timer) { clearInterval(timer); timer = null; } }
function start() {
stop();
if (reduce.matches) return;
timer = setInterval(function () {
if (hover || document.hidden) return;
show(idx + 1);
}, 4200);
}
box.addEventListener('mouseenter', function () { hover = true; });
box.addEventListener('mouseleave', function () { hover = false; });
document.addEventListener('visibilitychange', function () { if (!document.hidden) start(); });
if (reduce.addEventListener) reduce.addEventListener('change', start);
start();
})();
// 外链统一安全属性
document.querySelectorAll('a[href^="http"]').forEach(function (a) {
a.rel = 'noopener';
});
})();