airpredict/apps/web/src/pages/Landing.vue

216 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="lp">
<!-- NAV -->
<header class="nav">
<div class="nav-in">
<a class="brand" @click="scrollTop">
<span class="brand-logo"><LeafIcon /></span>
<span><span class="brand-tt">污染物预测系统</span><br><span class="brand-sub">INDOOR AIR · 装修污染</span></span>
</a>
<nav class="nav-links">
<a @click="scrollTo('news')">资讯科普</a>
<a @click="scrollTo('cases')">治理案例</a>
<a @click="scrollTo('how')">如何使用</a>
<a @click="openPredict">污染源识别</a>
<a @click="goPro">专业看板</a>
</nav>
<span class="nav-sp"></span>
<a class="btn btn-primary" @click="openPredict">免费试算<ArrowIcon /></a>
</div>
</header>
<!-- HERO -->
<section class="hero">
<div class="wrap hero-grid">
<div>
<span class="eyebrow"><span class="pip"></span>对照 GB/T 18883-2022 GB 50325-2020 双国标</span>
<h1>装修住得安心,<br>从一次<em>污染预测</em>开始</h1>
<p class="hero-lead">输入房间环境与所用材料,系统用稳态质量平衡公式预测甲醛TVOC 6 项污染物浓度,判定是否超标,并溯源到具体污染材料,给出整改建议</p>
<div class="hero-cta">
<a class="btn btn-primary btn-lg" @click="openPredict">免费预测甲醛 · TVOC<ArrowIcon /></a>
<a class="btn btn-lg" @click="scrollTo('cases')">查看治理案例</a>
</div>
<div class="hero-tags">
<span class="hero-tag"><CheckIcon />无需上门,先估后测</span>
<span class="hero-tag"><CheckIcon />公式可溯源</span>
<span class="hero-tag"><CheckIcon />材料数据库支撑</span>
</div>
</div>
<div class="hero-visual">
<div class="img-ph hero-img">室内 / 装修实景照片</div>
<div class="hero-badge"><b>6 </b><span>污染物预测</span></div>
</div>
</div>
</section>
<!-- STATS -->
<section class="stats">
<div class="stats-in">
<div class="stat" v-for="s in stats" :key="s.t"><b>{{ s.n }}</b><span>{{ s.t }}</span></div>
</div>
</section>
<!-- NEWS CAROUSEL -->
<section class="sec" id="news">
<div class="wrap">
<div class="sec-head">
<div><div class="sec-tag">资讯 · 科普</div><h2 class="sec-h">读懂装修污染,先把知识装进脑子</h2></div>
<a class="btn" @click="openPredict">全部文章</a>
</div>
<div class="carousel" @mouseenter="stop" @mouseleave="start">
<div class="cviewport">
<div class="ctrack" :style="{ transform: `translateX(${-cur * 100}%)` }">
<article class="cslide" v-for="(n, i) in news" :key="i">
<div class="cslide-img"><span class="cslide-tag">{{ n.tag }}</span><div class="img-ph">资讯配图</div></div>
<div class="cslide-body">
<div class="cslide-date">{{ n.date }}</div>
<h3>{{ n.title }}</h3>
<p>{{ n.desc }}</p>
<span class="cslide-more">阅读全文<ArrowIcon /></span>
</div>
</article>
</div>
</div>
<button class="cnav prev" @click="prev"><ChevronIcon dir="left" /></button>
<button class="cnav next" @click="next"><ChevronIcon dir="right" /></button>
</div>
<div class="cdots">
<button v-for="(n, i) in news" :key="i" class="cdot" :class="{ on: i === cur }" @click="go(i)"></button>
</div>
</div>
</section>
<!-- CASES -->
<section class="sec" id="cases" style="background:var(--bg2);">
<div class="wrap">
<div class="sec-head">
<div><div class="sec-tag">治理案例</div><h2 class="sec-h">预测 → 溯源 → 整改,看得见的下降</h2><p class="sec-sub">真实流程演示:从预测超标,到锁定主要污染材料,再到整改复测达标。</p></div>
</div>
<div class="cases-grid">
<article class="case" v-for="(c, i) in cases" :key="i">
<div class="img-ph">案例实景图</div>
<div class="case-b">
<div class="case-type">{{ c.type }}</div>
<h4>{{ c.name }}</h4>
<div class="case-meta">{{ c.meta }}</div>
<div class="ba">
<div class="ba-row"><span class="k">治理前</span><div class="ba-track"><div class="ba-fill" :style="{ width: c.w1 + '%', background: 'var(--bad)' }"></div></div><span class="v" style="color:var(--bad)">{{ c.v1 }}</span></div>
<div class="ba-row"><span class="k">治理后</span><div class="ba-track"><div class="ba-fill" :style="{ width: c.w2 + '%', background: 'var(--good)' }"></div></div><span class="v" style="color:var(--good)">{{ c.v2 }}</span></div>
</div>
<div class="case-foot"><span class="chip chip-good">{{ c.chip }}</span><span class="lk">查看溯源<ArrowIcon small /></span></div>
</div>
</article>
</div>
</div>
</section>
<!-- HOW -->
<section class="sec" id="how">
<div class="wrap">
<div class="sec-head"><div><div class="sec-tag">如何使用</div><h2 class="sec-h">三步,得到一份可溯源的预测报告</h2></div></div>
<div class="steps">
<div class="step" v-for="(s, i) in steps" :key="i">
<div class="step-n">{{ i + 1 }}</div><h4>{{ s.h }}</h4><p>{{ s.p }}</p>
<div class="step-ar" v-if="i < steps.length - 1"><ArrowIcon /></div>
</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="sec" style="padding-top:0;">
<div class="wrap">
<div class="ctaband">
<div style="position:relative;z-index:2;">
<h2>现在就免费预测<br>你家会不会甲醛超标</h2>
<p>无需上门,输入材料即可估算。先估后测,把检测的钱花在刀刃上。</p>
</div>
<div style="display:flex;gap:14px;position:relative;z-index:2;">
<a class="btn btn-primary btn-lg" @click="openPredict">免费开始预测</a>
<a class="btn btn-lg" @click="goPro">查看专业看板</a>
</div>
<div class="deco"></div>
</div>
</div>
</section>
<!-- FOOTER -->
<footer class="footer">
<div class="footer-in">
<div class="brand">
<span class="brand-logo"><LeafIcon /></span>
<span class="brand-tt">室内装修工程污染物预测系统</span>
</div>
<div>依据 GB/T 18883-2022 · GB 50325-2020 · 预测结果仅供参考,以 CMA 检测为准</div>
</div>
</footer>
<PhoneAuthModal :open="authOpen" @ok="onAuthed" @cancel="authOpen = false" />
</div>
</template>
<script setup lang="ts">
import { h, onBeforeUnmount, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import PhoneAuthModal from '../components/PhoneAuthModal.vue';
const router = useRouter();
// 内联图标
const LeafIcon = () => h('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', 'stroke-width': '2', 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }, [h('path', { d: 'M4 20c10 2 16-4 16-14 0 0-8-2-12 2-3 3-3 7-1 9 3-4 6-6 9-7' })]);
const ArrowIcon = (props: any) => h('svg', { viewBox: '0 0 24 24', width: props.small ? 15 : undefined, height: props.small ? 15 : undefined, fill: 'none', stroke: 'currentColor', 'stroke-width': '2.2', 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }, [h('path', { d: 'M5 12h14M13 6l6 6-6 6' })]);
const CheckIcon = () => h('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', 'stroke-width': '2', 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }, [h('path', { d: 'M20 6L9 17l-5-5' })]);
const ChevronIcon = (props: any) => h('svg', { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', 'stroke-width': '2.4', 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }, [h('path', { d: props.dir === 'left' ? 'M15 5l-7 7 7 7' : 'M9 5l7 7-7 7' })]);
const stats = [
{ n: '28+', t: '在管装修项目' },
{ n: '2,400+', t: '累计预测次数' },
{ n: '6 项', t: '污染物 · 甲醛/苯/TVOC/氨/氡/VOC' },
{ n: '2 部', t: '国标依据 · 18883 / 50325' },
];
const news = [
{ tag: '政策解读', date: '专栏 · 2026.05', title: '两大国标怎么读?GB/T 18883 与 GB 50325 的差别', desc: '一个是"住进去后"的室内空气质量标准,一个是"交工验收时"的工程控制标准——限值与采样条件并不相同,看懂它们才能判断房子到底达不达标。' },
{ tag: '科普', date: '专栏 · 2026.04', title: '新装住宅的甲醛,为什么能持续释放 315 年?', desc: '人造板里的脲醛树脂胶会缓慢分解释放甲醛,释放周期长、受温湿度影响大。短期通风只能降一时浓度,真正的关键在源头材料的选择。' },
{ tag: '指南', date: '专栏 · 2026.03', title: '夏天为什么更容易超标?温度与释放速率', desc: '温度每升高若干度,材料的甲醛释放速率会明显增大。这也是"冬天测达标、夏天又超标"的原因。预测时把环境温湿度纳入计算,结果才靠谱。' },
{ tag: '方法', date: '专栏 · 2026.02', title: '先预测,再决定要不要做 CMA 检测', desc: '上门检测有成本。用本系统先做一次免费预测、定位高风险房间与主要污染材料,再有针对性地安排第三方 CMA 检测,省钱也更有的放矢。' },
];
const cases = [
{ type: '住宅 · I类民用建筑', name: '锦绣华庭 · 主卧', meta: '主源:多层实木复合地板 · 人造板衣柜', w1: 82, v1: '0.18', w2: 36, v2: '0.08', chip: '甲醛达标' },
{ type: '住宅 · I类民用建筑', name: '翠湖天地 · 儿童房', meta: '主源:人造板衣柜 · 壁纸基膜', w1: 95, v1: '0.21', w2: 32, v2: '0.07', chip: '甲醛达标' },
{ type: '酒店客房 · II类民用建筑', name: '云栖精选酒店 · 标准间', meta: '主源:木器漆饰面 · 软包', w1: 90, v1: '0.72', w2: 58, v2: '0.46', chip: 'TVOC达标' },
];
const steps = [
{ h: '录入房间与材料', p: '选择房间、填写面积层高与通风换气率,勾选所用装修材料及用量。' },
{ h: '公式计算浓度', p: '按稳态质量平衡 C = Σ(EFᵢ·Aᵢ)/(n·V) 计算 6 项污染物浓度,对照国标判定达标。' },
{ h: '溯源与整改建议', p: '若超标,公式溯源出贡献最大的材料并排序,给出通风或换材的可行整改方案。' },
];
// 轮播
const cur = ref(0);
let timer: any = null;
function go(n: number) { cur.value = (n + news.length) % news.length; }
function next() { go(cur.value + 1); start(); }
function prev() { go(cur.value - 1); start(); }
function start() { stop(); timer = setInterval(() => go(cur.value + 1), 5500); }
function stop() { if (timer) clearInterval(timer); timer = null; }
onMounted(start);
onBeforeUnmount(stop);
function scrollTop() { window.scrollTo({ top: 0, behavior: 'smooth' }); }
function scrollTo(id: string) { document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' }); }
function goPro() { router.push(localStorage.getItem('token') ? '/home' : '/login'); }
// 预测入口 → 手机注册
const authOpen = ref(false);
function openPredict() {
if (localStorage.getItem('token')) router.push('/source');
else authOpen.value = true;
}
function onAuthed() {
authOpen.value = false;
router.push('/source');
}
</script>
<style src="../styles/landing.css"></style>