Commit 6dc1c171 authored by tao355667's avatar tao355667

feat: refine contact UI and admin filters

parent 424c9f87
......@@ -15,6 +15,7 @@ let currentUser = null;
let consultationTeachers = [];
let staffAccounts = [];
let activeConsultationUser = null;
let articleRecords = [];
const consultationStatusLabels = { unprocessed: "未处理", added: "已添加", not_added: "未添加" };
const ADMIN_STATE_KEY = "qiyouxue-admin-state";
......@@ -563,15 +564,16 @@ function applyStatus(element, status) {
element.textContent = label;
}
async function loadArticles() {
const articles = await api("/articles").catch((error) => { alert(error.message); return []; });
function renderArticles() {
const list = $("#article-list");
list.innerHTML = "";
const pending = articles.filter((item) => item.publishStatus !== "live").length;
$("#pending-badge").textContent = `${pending} 篇草稿待发布`;
$("#pending-badge").classList.toggle("hidden", pending === 0);
if (!articles.length) { list.innerHTML = '<div class="empty">还没有文章,点击“新建文章”开始。</div>'; return; }
for (const article of articles) {
if (!articleRecords.length) { list.innerHTML = '<div class="empty">还没有文章,点击“新建文章”开始。</div>'; return; }
const selectedStatus = $("#article-status-filter").value;
const visibleArticles = selectedStatus === "all"
? articleRecords
: articleRecords.filter((item) => item.publishStatus === selectedStatus);
if (!visibleArticles.length) { list.innerHTML = '<div class="empty">当前筛选条件下没有文章。</div>'; return; }
for (const article of visibleArticles) {
const card = document.createElement("article");
card.className = "article-row";
card.innerHTML = '<div class="article-summary"><h2></h2><p><span class="category"></span><span class="updated"></span><span class="status"></span></p></div><div class="row-actions"></div>';
......@@ -589,6 +591,16 @@ async function loadArticles() {
}
}
async function loadArticles() {
articleRecords = await api("/articles").catch((error) => { alert(error.message); return []; });
const pending = articleRecords.filter((item) => item.publishStatus !== "live").length;
$("#pending-badge").textContent = `${pending} 篇草稿待发布`;
$("#pending-badge").classList.toggle("hidden", pending === 0);
renderArticles();
}
$("#article-status-filter").addEventListener("change", renderArticles);
function listAction(label, className, action) {
const button = document.createElement("button");
button.type = "button";
......
......@@ -47,6 +47,10 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
.view-head p { margin: 0 0 5px; color: var(--primary-dark); font-size: 11px; font-weight: 700; letter-spacing: .16em; }
.view-head h1 { margin: 0; font-size: 30px; }
.view-actions { display: flex; gap: 9px; }
.article-toolbar { align-items: center; justify-content: space-between; gap: 18px; }
.article-status-filter { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 13px; }
.article-status-filter > span { white-space: nowrap; }
.article-status-filter select { width: 156px; min-height: 40px; padding-block: 8px; }
.import-status { min-height: 20px; margin: -16px 0 12px; color: var(--muted); font-size: 13px; text-align: right; }
.article-list { display: grid; gap: 10px; }
.article-row { padding: 18px 20px; display: flex; align-items: center; justify-content: space-between; gap: 20px; background: white; border: 1px solid var(--border); border-radius: 14px; }
......@@ -182,6 +186,7 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
.metric-grid small { color: var(--muted); font-size: 12px; }
.metric-grid strong { color: #12365f; font-size: 20px; }
.table-card { overflow-x: auto; overflow-y: hidden; background: white; border: 1px solid var(--border); border-radius: 10px; scrollbar-color: #b8c7d8 #f2f5f8; scrollbar-width: thin; }
.table-card .empty { border: 0; border-radius: 0; }
.table-card::-webkit-scrollbar { height: 9px; }
.table-card::-webkit-scrollbar-track { background: #f2f5f8; }
.table-card::-webkit-scrollbar-thumb { background: #b8c7d8; border: 2px solid #f2f5f8; border-radius: 999px; }
......@@ -283,6 +288,8 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
@media (max-width: 760px) {
.topbar, .view-head, .article-row { align-items: flex-start; flex-direction: column; }
.top-actions { width: 100%; flex-wrap: wrap; }
.article-toolbar { align-items: stretch; flex-direction: column; }
.article-status-filter { justify-content: space-between; }
.view-actions { width: 100%; }
.view-actions button { flex: 1; }
.field-row, .editor-grid { grid-template-columns: 1fr; }
......
......@@ -22,16 +22,31 @@ import { site } from "../data/site";
<div class="contact-dialog__panel">
<button class="contact-dialog__close" type="button" data-phone-dialog-close aria-label="关闭官方电话信息">×</button>
<div class="phone-dialog__heading">
<span>OFFICIAL CONTACT</span>
<h2 id="phone-dialog-title">官方电话</h2>
<p>课程咨询、教师匹配与服务安排,欢迎致电了解。</p>
<h2 id="phone-dialog-title">官方联系方式</h2>
<p>课程咨询、服务反馈与商务合作,可通过以下官方渠道联系我们。</p>
</div>
<a class="phone-dialog__number" href={`tel:${site.contact.phone}`}>{site.contact.phoneDisplay}</a>
<div class="phone-dialog__details">
<span>服务时间:周一至周日 · 7×24 小时</span>
<div class="official-contact-list">
<section class="official-contact-item official-contact-item--phone">
<span>客服电话</span>
<a href={`tel:${site.contact.phone}`}>{site.contact.phoneDisplay}</a>
<p>课程咨询与服务反馈</p>
</section>
<section class="official-contact-item">
<span>微信小程序</span>
<strong>启优学一对一</strong>
<p>搜索小程序名称提交预约</p>
</section>
<section class="official-contact-item">
<span>联系邮箱</span>
<a href={`mailto:${site.contact.email}`}>{site.contact.email}</a>
<p>商务合作与服务反馈</p>
</section>
<section class="official-contact-item">
<span>官方网站</span>
<a href={`https://${site.contact.website}`}>{site.contact.website}</a>
<p>官方课程与服务信息</p>
</section>
</div>
<a class="phone-dialog__call" href={`tel:${site.contact.phone}`}>立即拨打</a>
</div>
</dialog>
......
......@@ -18,5 +18,5 @@ const webPageLd = { "@context": "https://schema.org", "@type": "WebPage", "@id":
const pageLd = Array.isArray(jsonLd) ? jsonLd : [jsonLd]; const serializedLd = JSON.stringify([organizationLd, websiteLd, webPageLd, ...pageLd.filter((item) => Object.keys(item).length > 0)]).replace(/</g, "\\u003c");
---
<!doctype html><html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><meta name="theme-color" content="#1473E6" /><meta name="color-scheme" content="light" /><title>{metaTitle}</title><meta name="description" content={metaDescription} /><meta name="keywords" content={metaKeywords} /><meta name="robots" content={noindex ? "noindex,nofollow" : "index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1"} /><link rel="canonical" href={canonical} />{prevUrl && <link rel="prev" href={prevUrl} />}{nextUrl && <link rel="next" href={nextUrl} />}<link rel="icon" href="/favicon.png" type="image/png" sizes="512x512" /><link rel="apple-touch-icon" href="/favicon.png" /><link rel="manifest" href="/site.webmanifest" /><link rel="alternate" hreflang="zh-CN" href={canonical} /><link rel="alternate" hreflang="x-default" href={canonical} /><meta property="og:type" content={ogType} /><meta property="og:title" content={metaTitle} /><meta property="og:description" content={metaDescription} /><meta property="og:url" content={canonical} /><meta property="og:image" content={ogImage} /><meta property="og:image:alt" content={imageAlt} /><meta property="og:site_name" content={site.brand.name} /><meta property="og:locale" content="zh_CN" />{publishedTime && <meta property="article:published_time" content={publishedTime} />}{modifiedTime && <meta property="article:modified_time" content={modifiedTime} />}{articleSection && <meta property="article:section" content={articleSection} />}{articleAuthor && <meta property="article:author" content={articleAuthor} />}<meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content={metaTitle} /><meta name="twitter:description" content={metaDescription} /><meta name="twitter:image" content={ogImage} /><script type="application/ld+json" set:html={serializedLd} is:inline></script></head><body><a class="skip-link" href="#main-content">跳到主要内容</a><slot /><ContactDialog /><script is:inline>
const header=document.querySelector('[data-header]');const syncHeader=()=>header?.classList.toggle('is-scrolled',scrollY>12);addEventListener('scroll',syncHeader,{passive:true});syncHeader();const observer='IntersectionObserver'in window?new IntersectionObserver(entries=>entries.forEach(entry=>{if(entry.isIntersecting){entry.target.classList.add('is-visible');observer.unobserve(entry.target)}}),{threshold:.08}):null;document.querySelectorAll('[data-reveal]').forEach(el=>observer?observer.observe(el):el.classList.add('is-visible'));document.querySelectorAll('[data-mobile-nav] a').forEach(link=>link.addEventListener('click',()=>link.closest('details')?.removeAttribute('open')));const dialog=document.querySelector('[data-contact-dialog]');const phoneDialog=document.querySelector('[data-phone-dialog]');const teacherDialog=document.querySelector('[data-teacher-dialog]');const phoneTrigger=document.querySelector('[data-phone-contact]');const form=dialog?.querySelector('[data-consultation-form]');const copyWechat=teacherDialog?.querySelector('[data-copy-teacher-wechat]');const resetConsultation=()=>{form?.reset();const error=dialog?.querySelector('[data-consultation-error]');if(error)error.textContent=''};document.addEventListener('click',event=>{const trigger=event.target.closest('[data-open-contact]');if(!dialog||!trigger)return;event.preventDefault();resetConsultation();dialog.showModal();dialog.querySelector('#consultation-phone')?.focus()});phoneTrigger?.addEventListener('click',event=>{if(matchMedia('(max-width:760px)').matches)return;event.preventDefault();phoneDialog?.showModal()});dialog?.querySelector('[data-contact-dialog-close]')?.addEventListener('click',()=>dialog.close());phoneDialog?.querySelector('[data-phone-dialog-close]')?.addEventListener('click',()=>phoneDialog.close());teacherDialog?.querySelector('[data-teacher-dialog-close]')?.addEventListener('click',()=>teacherDialog.close());[dialog,phoneDialog,teacherDialog].forEach(item=>item?.addEventListener('click',event=>{if(event.target===item)item.close()}));copyWechat?.addEventListener('click',async()=>{const value=teacherDialog.querySelector('[data-teacher-wechat]').textContent.trim();if(!value)return;try{await navigator.clipboard.writeText(value);copyWechat.textContent='已复制';setTimeout(()=>{copyWechat.textContent='复制'},1600)}catch{copyWechat.textContent='复制失败';setTimeout(()=>{copyWechat.textContent='复制'},1600)}});form?.addEventListener('submit',async event=>{event.preventDefault();const phone=String(new FormData(form).get('phone')||'').replace(/\s+/g,'');const error=dialog.querySelector('[data-consultation-error]');const submit=form.querySelector('button[type="submit"]');error.textContent='';if(!/^1[3-9]\d{9}$/.test(phone)){error.textContent='请输入正确的 11 位手机号';return}submit.disabled=true;submit.textContent='正在领取…';try{const response=await fetch('/api/cms/consultations/claim',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({phone,source:'免费领取学情分析',page:location.href})});const result=await response.json();if(!response.ok)throw new Error(result.error||'提交失败,请稍后重试');teacherDialog.querySelector('[data-teacher-name]').textContent=result.teacher.name;teacherDialog.querySelector('[data-teacher-title]').textContent=result.teacher.title;teacherDialog.querySelector('[data-teacher-qr]').src=result.teacher.qrCodeUrl;teacherDialog.querySelector('[data-teacher-wechat]').textContent=result.teacher.wechat||'';teacherDialog.querySelector('[data-teacher-wechat-wrap]').classList.toggle('hidden',!result.teacher.wechat);copyWechat.textContent='复制';dialog.close();teacherDialog.showModal()}catch(requestError){error.textContent=requestError.message}finally{submit.disabled=false;submit.textContent='立即领取'}});
</script><a class="floating-phone" href={`tel:${site.contact.phone}`} data-phone-contact aria-label={`官方电话 ${site.contact.phoneDisplay},点击查看联系信息或拨号`}><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7.2 4.5 5.4 5.8c-.8.6-.9 1.7-.6 2.6 1.7 5.2 5.1 8.6 10.3 10.3.9.3 2 0 2.6-.6l1.3-1.8c.4-.5.3-1.2-.2-1.6l-2.7-2.2c-.5-.4-1.2-.3-1.6.1l-1.1 1.3c-2-1-3.7-2.7-4.7-4.7l1.3-1.1c.4-.4.5-1.1.1-1.6L8.8 4.7c-.4-.5-1.1-.6-1.6-.2Z" /></svg><span>官方电话</span></a><button class="floating-consultation" type="button" data-open-contact aria-label="在线咨询,打开学情分析表单"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5h16v11H9l-5 3v-14Z" /></svg><span>在线咨询</span><i aria-hidden="true">1</i></button></body></html>
const header=document.querySelector('[data-header]');const syncHeader=()=>header?.classList.toggle('is-scrolled',scrollY>12);addEventListener('scroll',syncHeader,{passive:true});syncHeader();const observer='IntersectionObserver'in window?new IntersectionObserver(entries=>entries.forEach(entry=>{if(entry.isIntersecting){entry.target.classList.add('is-visible');observer.unobserve(entry.target)}}),{threshold:.08}):null;document.querySelectorAll('[data-reveal]').forEach(el=>observer?observer.observe(el):el.classList.add('is-visible'));document.querySelectorAll('[data-mobile-nav] a').forEach(link=>link.addEventListener('click',()=>link.closest('details')?.removeAttribute('open')));const dialog=document.querySelector('[data-contact-dialog]');const phoneDialog=document.querySelector('[data-phone-dialog]');const teacherDialog=document.querySelector('[data-teacher-dialog]');const form=dialog?.querySelector('[data-consultation-form]');const copyWechat=teacherDialog?.querySelector('[data-copy-teacher-wechat]');const resetConsultation=()=>{form?.reset();const error=dialog?.querySelector('[data-consultation-error]');if(error)error.textContent=''};document.addEventListener('click',event=>{const trigger=event.target.closest('[data-open-contact]');if(!dialog||!trigger)return;event.preventDefault();resetConsultation();dialog.showModal();dialog.querySelector('#consultation-phone')?.focus()});document.addEventListener('click',event=>{if(!event.target.closest('[data-phone-contact]'))return;phoneDialog?.showModal()});dialog?.querySelector('[data-contact-dialog-close]')?.addEventListener('click',()=>dialog.close());phoneDialog?.querySelector('[data-phone-dialog-close]')?.addEventListener('click',()=>phoneDialog.close());teacherDialog?.querySelector('[data-teacher-dialog-close]')?.addEventListener('click',()=>teacherDialog.close());[dialog,phoneDialog,teacherDialog].forEach(item=>item?.addEventListener('click',event=>{if(event.target===item)item.close()}));copyWechat?.addEventListener('click',async()=>{const value=teacherDialog.querySelector('[data-teacher-wechat]').textContent.trim();if(!value)return;try{await navigator.clipboard.writeText(value);copyWechat.textContent='已复制';setTimeout(()=>{copyWechat.textContent='复制'},1600)}catch{copyWechat.textContent='复制失败';setTimeout(()=>{copyWechat.textContent='复制'},1600)}});form?.addEventListener('submit',async event=>{event.preventDefault();const phone=String(new FormData(form).get('phone')||'').replace(/\s+/g,'');const error=dialog.querySelector('[data-consultation-error]');const submit=form.querySelector('button[type="submit"]');error.textContent='';if(!/^1[3-9]\d{9}$/.test(phone)){error.textContent='请输入正确的 11 位手机号';return}submit.disabled=true;submit.textContent='正在领取…';try{const response=await fetch('/api/cms/consultations/claim',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({phone,source:'免费领取学情分析',page:location.href})});const result=await response.json();if(!response.ok)throw new Error(result.error||'提交失败,请稍后重试');teacherDialog.querySelector('[data-teacher-name]').textContent=result.teacher.name;teacherDialog.querySelector('[data-teacher-title]').textContent=result.teacher.title;teacherDialog.querySelector('[data-teacher-qr]').src=result.teacher.qrCodeUrl;teacherDialog.querySelector('[data-teacher-wechat]').textContent=result.teacher.wechat||'';teacherDialog.querySelector('[data-teacher-wechat-wrap]').classList.toggle('hidden',!result.teacher.wechat);copyWechat.textContent='复制';dialog.close();teacherDialog.showModal()}catch(requestError){error.textContent=requestError.message}finally{submit.disabled=false;submit.textContent='立即领取'}});
</script><button class="floating-phone floating-phone--desktop" type="button" data-phone-contact aria-label="官方电话,查看官方联系方式"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7.2 4.5 5.4 5.8c-.8.6-.9 1.7-.6 2.6 1.7 5.2 5.1 8.6 10.3 10.3.9.3 2 0 2.6-.6l1.3-1.8c.4-.5.3-1.2-.2-1.6l-2.7-2.2c-.5-.4-1.2-.3-1.6.1l-1.1 1.3c-2-1-3.7-2.7-4.7-4.7l1.3-1.1c.4-.4.5-1.1.1-1.6L8.8 4.7c-.4-.5-1.1-.6-1.6-.2Z" /></svg><span>官方电话</span></button><a class="floating-phone floating-phone--mobile" href={`tel:${site.contact.phone}`} aria-label={`拨打官方电话 ${site.contact.phoneDisplay}`}><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7.2 4.5 5.4 5.8c-.8.6-.9 1.7-.6 2.6 1.7 5.2 5.1 8.6 10.3 10.3.9.3 2 0 2.6-.6l1.3-1.8c.4-.5.3-1.2-.2-1.6l-2.7-2.2c-.5-.4-1.2-.3-1.6.1l-1.1 1.3c-2-1-3.7-2.7-4.7-4.7l1.3-1.1c.4-.4.5-1.1.1-1.6L8.8 4.7c-.4-.5-1.1-.6-1.6-.2Z" /></svg><span>官方电话</span></a><button class="floating-consultation" type="button" data-open-contact aria-label="在线咨询,打开学情分析表单"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5h16v11H9l-5 3v-14Z" /></svg><span>在线咨询</span><i aria-hidden="true">1</i></button></body></html>
......@@ -66,7 +66,10 @@
</main>
<main id="list-view" class="view hidden content-role">
<div class="view-toolbar"><div class="view-actions"><button id="manage-categories" class="ghost">管理分类</button><button id="import-article" class="ghost">导入文件</button><button id="new-article" class="primary">+ 新建文章</button></div></div>
<div class="view-toolbar article-toolbar">
<label class="article-status-filter" for="article-status-filter"><span>发布状态</span><select id="article-status-filter" aria-label="按发布状态筛选文章"><option value="all">全部状态</option><option value="live">已上线</option><option value="new-draft">新建未发布</option><option value="edited-draft">修改未发布</option></select></label>
<div class="view-actions"><button id="manage-categories" class="ghost">管理分类</button><button id="import-article" class="ghost">导入文件</button><button id="new-article" class="primary">+ 新建文章</button></div>
</div>
<input id="article-file" class="hidden" type="file" accept=".md,.docx,text/markdown,application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
<p id="import-status" class="import-status" aria-live="polite"></p>
<div id="article-list" class="article-list"></div>
......
......@@ -3,7 +3,7 @@
.eyebrow{display:flex;align-items:center;gap:10px;margin-bottom:16px;color:var(--brand-blue);font-size:11px;font-weight:700;letter-spacing:.16em}.eyebrow>span{width:28px;height:2px;background:var(--brand-accent)}.eyebrow--light,.section-heading--light .eyebrow{color:#d8eefb}.section-heading{max-width:700px}.section-heading--center{margin-inline:auto;text-align:center}.section-heading--center .eyebrow{justify-content:center}.section-heading h2{margin-bottom:20px;font-size:clamp(34px,4vw,54px);font-weight:600;letter-spacing:-.025em}.section-heading>p{margin:0;color:var(--text-secondary);font-size:17px}.section-heading--light h2{color:#fff}.section-heading--light>p{color:#c9deea}.section-intro-row{display:flex;align-items:end;justify-content:space-between;gap:50px;margin-bottom:48px}.text-link{color:var(--brand-blue);font-weight:600;white-space:nowrap}.text-link span{color:var(--brand-accent)}.text-link--light{color:#fff}
.button{display:inline-flex;align-items:center;justify-content:center;gap:12px;min-height:52px;padding:0 25px;border:1px solid var(--brand-blue);border-radius:9px;color:#fff;background:var(--brand-blue);font-size:14px;font-weight:600;letter-spacing:.02em;transition:background .2s,border-color .2s,box-shadow .2s,color .2s,transform .2s}.button:hover{border-color:var(--primary-hover);background:var(--primary-hover);transform:translateY(-2px)}.button--small{min-height:42px;padding:0 18px;font-size:13px}.button--accent{border-color:var(--brand-accent);color:var(--text-primary);background:var(--brand-accent)}.button--accent:hover{border-color:var(--accent-hover);background:var(--accent-hover)}.button--outline{color:var(--brand-blue);background:#fff}.button--outline:hover{color:#fff}.button--ghost{border-color:rgba(255,255,255,.55);background:transparent}.button--white{border-color:#fff;color:var(--brand-blue-dark);background:#fff}.button--white:hover{border-color:#fff;color:#0b5eba;background:#edf6ff;box-shadow:0 9px 22px rgba(6,52,105,.2)}.hero__actions{display:flex;flex-wrap:wrap;gap:12px}
.site-header{position:sticky;z-index:100;top:0;height:76px;border-bottom:1px solid rgba(220,232,239,.8);background:rgba(252,253,252,.96);transition:box-shadow .25s}.site-header.is-scrolled{box-shadow:0 8px 24px rgba(7,59,131,.08)}.site-header__inner{display:flex;align-items:center;height:100%;gap:24px}.brand{width:132px;height:62px;overflow:hidden}.brand img{width:100%;height:100%;object-fit:cover;object-position:center}.desktop-nav{margin-left:auto}.desktop-nav>ul{display:flex;margin:0;padding:0;list-style:none}.nav-item{position:relative}.nav-link{position:relative;display:block;padding:27px 13px 24px;color:#304957;font-size:14px;font-weight:650}.nav-link::after{position:absolute;right:13px;bottom:16px;left:13px;height:2px;content:"";background:var(--brand-accent);transform:scaleX(0);transition:transform .25s}.nav-link:hover,.nav-link[aria-current=page]{color:var(--brand-blue)}.nav-link:hover::after,.nav-link[aria-current=page]::after{transform:scaleX(1)}.nav-dropdown{position:absolute;top:calc(100% - 4px);left:50%;visibility:hidden;width:220px;padding-top:10px;opacity:0;transform:translate(-50%,8px);transition:.2s}.nav-item:hover .nav-dropdown,.nav-item:focus-within .nav-dropdown{visibility:visible;opacity:1;transform:translate(-50%,0)}.nav-dropdown ul{margin:0;padding:8px;border:1px solid var(--border);border-radius:10px;background:#fff;box-shadow:var(--shadow-hover);list-style:none}.nav-dropdown a{display:flex;justify-content:space-between;padding:10px 12px;border-radius:7px;font-size:13px}.nav-dropdown a:hover{color:var(--brand-blue);background:var(--bg-blue-soft)}.mobile-nav{display:none;margin-left:auto}.mobile-nav summary{display:grid;width:40px;height:40px;padding:10px;cursor:pointer;list-style:none}.mobile-nav summary span{height:2px;background:var(--brand-blue-dark)}
.home-hero{overflow:hidden;padding:56px 0 0;background:#fff}.home-hero__grid{display:grid;grid-template-columns:1.08fr .92fr;align-items:center;gap:20px}.hero-label{display:flex;align-items:center;margin-bottom:20px;color:var(--brand-blue);font-size:14px;font-weight:600}.home-hero h1{margin-bottom:25px;font-size:clamp(30px,2.65vw,40px);line-height:1.32;letter-spacing:-.03em}.home-hero h1 span,.home-hero h1 em{display:block;white-space:nowrap}.home-hero h1 em,.page-hero h1 em{color:var(--brand-blue);font-style:normal}.home-hero__copy{position:relative;z-index:2}.home-hero__copy>p{max-width:600px;margin-bottom:32px;color:var(--text-secondary);font-size:18px}.hero__proof{display:flex;flex-wrap:wrap;gap:16px;margin-top:30px}.hero__proof span{display:flex;align-items:center;gap:8px;color:var(--text-secondary);font-size:13px}.hero__proof span::before{width:6px;height:6px;border-radius:50%;content:"";background:var(--brand-accent)}.home-hero__visual{position:relative;margin-left:-36px}.image-frame{position:relative;overflow:hidden;background:#fff}.image-frame img{width:100%;aspect-ratio:1.22;object-fit:cover;mix-blend-mode:multiply;-webkit-mask-image:radial-gradient(ellipse 83% 86% at 55% 50%,#000 58%,rgba(0,0,0,.9) 72%,transparent 100%);mask-image:radial-gradient(ellipse 83% 86% at 55% 50%,#000 58%,rgba(0,0,0,.9) 72%,transparent 100%)}.stage-ruler{display:flex;align-items:center;justify-content:center;gap:25px;margin-top:32px;padding:20px 0;border-top:1px solid var(--divider);color:var(--brand-blue-dark);font-size:14px;font-weight:750}.stage-ruler i{width:5px;height:5px;border-radius:50%;background:var(--brand-accent)}
.home-hero{overflow:hidden;padding:56px 0 0;background:#fff}.home-hero__grid{display:grid;grid-template-columns:1.08fr .92fr;align-items:center;gap:20px}.hero-label{display:flex;align-items:center;margin-bottom:20px;color:var(--brand-blue);font-size:14px;font-weight:600}.home-hero h1{margin-bottom:25px;font-size:clamp(30px,2.65vw,40px);line-height:1.32;letter-spacing:-.03em}.home-hero h1 span,.home-hero h1 em{display:block;white-space:nowrap}.home-hero h1 em,.page-hero h1 em{color:var(--brand-blue);font-style:normal}.home-hero__copy{position:relative;z-index:2}.home-hero__copy>p{max-width:600px;margin-bottom:32px;color:var(--text-secondary);font-size:18px}.hero__proof{display:flex;flex-wrap:wrap;gap:16px;margin-top:30px}.hero__proof span{display:flex;align-items:center;gap:8px;color:var(--text-secondary);font-size:13px}.hero__proof span::before{width:6px;height:6px;border-radius:50%;content:"";background:var(--brand-accent)}.home-hero__visual{position:relative;margin-left:-36px}.image-frame{position:relative;overflow:hidden;background:#fff}.image-frame::after{position:absolute;inset:-1px;z-index:1;pointer-events:none;content:"";background:linear-gradient(90deg,#fff 0,rgba(255,255,255,.82) 7%,transparent 23%,transparent 77%,rgba(255,255,255,.38) 91%,#fff 100%),linear-gradient(180deg,#fff 0,rgba(255,255,255,.42) 9%,transparent 24%,transparent 75%,rgba(255,255,255,.72) 91%,#fff 100%)}.image-frame img{width:100%;aspect-ratio:1.22;object-fit:cover;mix-blend-mode:multiply;-webkit-mask-image:radial-gradient(ellipse 94% 94% at 56% 50%,#000 50%,rgba(0,0,0,.96) 63%,rgba(0,0,0,.5) 82%,transparent 100%);mask-image:radial-gradient(ellipse 94% 94% at 56% 50%,#000 50%,rgba(0,0,0,.96) 63%,rgba(0,0,0,.5) 82%,transparent 100%)}.stage-ruler{display:flex;align-items:center;justify-content:center;gap:25px;margin-top:32px;padding:20px 0;border-top:1px solid var(--divider);color:var(--brand-blue-dark);font-size:14px;font-weight:750}.stage-ruler i{width:5px;height:5px;border-radius:50%;background:var(--brand-accent)}
.subject-overview{background:#fff}.subject-overview__head{max-width:920px;margin:0 auto 62px;text-align:center}.subject-overview__label{margin-bottom:14px;color:var(--brand-blue);font-size:14px;font-weight:600}.subject-overview__head h2{margin-bottom:22px;font-size:clamp(38px,4.8vw,64px);font-weight:600;line-height:1.18;letter-spacing:-.04em}.subject-overview__lead{max-width:760px;margin:0 auto 22px;color:var(--brand-blue);font-size:19px;font-weight:600}.subject-overview__intro{max-width:900px;margin:0 auto;color:var(--text-secondary);font-size:16px}.subject-overview__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.subject-card{display:flex;min-height:190px;padding:30px;align-items:flex-start;gap:22px;border:1px solid transparent;border-radius:18px;background:var(--subject-bg);box-shadow:0 8px 28px rgba(20,115,230,.05);transition:transform .2s,box-shadow .2s,border-color .2s}.subject-card:hover{border-color:var(--subject-border);box-shadow:0 14px 34px rgba(20,115,230,.1);transform:translateY(-3px)}.subject-card__icon{display:grid;width:56px;height:56px;place-items:center;flex:0 0 auto;border-radius:15px;color:var(--subject-color);background:rgba(255,255,255,.76)}.subject-card__icon svg{width:32px;height:32px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}.subject-overview__grid h3{margin:3px 0 12px;color:var(--subject-title);font-size:27px;font-weight:600}.subject-overview__grid p{margin:0;color:var(--text-secondary);font-size:14px}.subject-card--blue{--subject-bg:#eef6ff;--subject-color:#1473e6;--subject-title:#145da8;--subject-border:#b9d8fb}.subject-card--rose{--subject-bg:#fff1f3;--subject-color:#c64d67;--subject-title:#9d3550;--subject-border:#f1c4ce}.subject-card--orange{--subject-bg:#fff5e9;--subject-color:#d87827;--subject-title:#a95718;--subject-border:#f2d1ad}.subject-card--indigo{--subject-bg:#edf3ff;--subject-color:#456fc2;--subject-title:#31569e;--subject-border:#c5d4f2}.subject-card--green{--subject-bg:#edf8ef;--subject-color:#3d9460;--subject-title:#287344;--subject-border:#bfdfc8}.subject-card--purple{--subject-bg:#f5f0fb;--subject-color:#8055aa;--subject-title:#643b8a;--subject-border:#d9c7e9}
.stat-band{padding:46px 0;background:#eaf4ff}.stat-grid{display:grid;grid-template-columns:repeat(4,1fr)}.stat-grid>div{padding:0 30px;border-right:1px solid #c8def5;text-align:center}.stat-grid>div:last-child{border:0}.stat-grid strong{display:block;color:var(--brand-blue);font-size:clamp(30px,4vw,48px);font-weight:700;letter-spacing:-.03em}.stat-grid p{margin:8px 0 0;color:#315575;font-size:13px}.data-note{max-width:900px;margin:24px auto 0;color:#67819a;font-size:11px;text-align:center}.need-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}.need-card{display:flex;min-height:280px;padding:28px;flex-direction:column;border:1px solid var(--border);border-radius:16px;background:#fff;box-shadow:var(--shadow-card);transition:.25s}.need-card:hover{border-color:#b9d7fa;box-shadow:var(--shadow-hover);transform:translateY(-3px)}.need-card h3{margin:12px 0 14px;font-size:27px}.need-card p{color:var(--text-secondary)}.need-card>strong{margin-top:auto;color:var(--brand-blue);font-size:13px}.need-scope{display:grid;grid-template-columns:auto 1fr;gap:14px 28px;align-items:center;margin-top:22px;padding:24px 28px;border:1px solid var(--border);border-radius:14px;background:rgba(255,255,255,.72)}.need-scope>strong{color:var(--brand-blue);font-size:14px}.need-scope>div{display:flex;flex-wrap:wrap;gap:8px}.need-scope span{padding:6px 10px;border-radius:6px;color:#315575;background:#fff;font-size:12px}.need-scope p{grid-column:2;margin:0;color:var(--text-muted);font-size:12px}.learning-map{display:grid;grid-template-columns:.9fr 1.1fr;gap:90px}.learning-map__copy{position:sticky;top:120px;align-self:start}.learning-map__copy .button{margin-top:30px}.learning-map__steps article{padding:26px 0;border-bottom:1px solid var(--divider)}.learning-map__steps h3{margin:0 0 8px;font-size:24px}.learning-map__steps p{margin:0;color:var(--text-secondary)}.teacher-section{background:#eaf4ff}.teacher-layout{display:grid;grid-template-columns:1fr .9fr;gap:80px;align-items:center}.teacher-layout h2{margin-bottom:22px;font-size:clamp(38px,4.6vw,60px);letter-spacing:-.04em}.teacher-layout h2 em{color:var(--brand-blue);font-style:normal}.teacher-layout>div>p{color:var(--text-secondary);font-size:17px}.teacher-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:26px}.teacher-tags span{padding:7px 11px;border:1px solid #bfd8f3;border-radius:6px;color:#315575;background:#fff;font-size:12px}.teacher-ledger{padding:26px;border:1px solid #c8def5;border-radius:18px;background:#fff;color:var(--text-primary);box-shadow:var(--shadow-card)}.ledger-head{padding-bottom:20px;border-bottom:2px solid var(--brand-blue)}.teacher-ledger>div:not(:first-child){padding:16px 0;border-bottom:1px solid var(--divider)}.feedback-layout{display:grid;grid-template-columns:1fr 1fr;gap:90px;align-items:center}.feedback-board{overflow:hidden;border:1px solid #cfe3fb;border-radius:16px;background:#fff;box-shadow:var(--shadow-card)}.feedback-board__head{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;color:#fff;background:#1473e6}.feedback-board__head span{font-size:12px}.feedback-score{display:flex;align-items:center;justify-content:space-between;padding:18px 24px;border-bottom:1px solid var(--divider)}.feedback-score strong{color:var(--brand-blue)}.feedback-board ul{margin:0;padding:8px 24px 20px;list-style:none}.feedback-board li{padding:16px 0;border-bottom:1px solid var(--divider)}.feedback-board li:last-child{border:0}.feedback-board li p{margin:4px 0 0;color:var(--text-secondary);font-size:13px}.feedback-points{display:flex;flex-wrap:wrap;gap:9px;margin-top:26px}.feedback-points span{padding:8px 12px;border:1px solid #cfe3fb;border-radius:8px;background:#fff;color:var(--brand-blue-dark);font-size:12px;font-weight:750}.faq-preview,.faq-layout{display:grid;grid-template-columns:.65fr 1.35fr;gap:80px}.faq-preview>div:first-child{position:sticky;top:110px;align-self:start}.faq-list details{border-bottom:1px solid var(--border)}.faq-list summary{display:grid;grid-template-columns:1fr 24px;gap:14px;align-items:center;padding:23px 0;cursor:pointer;list-style:none}.faq-list summary>strong{font-size:17px}.faq-list summary>i{position:relative;width:18px;height:18px}.faq-list summary>i::before,.faq-list summary>i::after{position:absolute;top:8px;left:3px;width:12px;height:2px;content:"";background:var(--brand-blue)}.faq-list summary>i::after{transform:rotate(90deg);transition:.2s}.faq-list details[open] summary>i::after{transform:none}.faq-list details>div{padding:0 38px 20px 0;color:var(--text-secondary)}
.page-hero{min-height:430px;padding:92px 0 78px;background:var(--bg-blue-soft)}.page-hero__inner{max-width:930px}.breadcrumb{margin-bottom:34px;color:var(--text-muted);font-size:12px}.breadcrumb a:hover{color:var(--brand-blue)}.page-hero h1{margin-bottom:24px;font-size:clamp(45px,6vw,72px);line-height:1.12;letter-spacing:-.055em}.page-hero p{max-width:760px;margin:0;color:var(--text-secondary);font-size:18px}.anchor-nav{position:sticky;z-index:20;top:76px;border-block:1px solid var(--border);background:rgba(255,255,255,.96)}.anchor-nav .container{display:grid;grid-template-columns:repeat(4,1fr)}.anchor-nav a{padding:18px;border-right:1px solid var(--border);color:var(--text-secondary);font-size:13px;text-align:center}.anchor-nav a span{margin-right:8px;color:var(--brand-blue)}.service-list{display:grid;gap:18px}.service-detail{scroll-margin-top:150px;border:1px solid var(--border);border-radius:16px;background:#fff}.service-detail__content{display:grid;grid-template-columns:.85fr 1.15fr;gap:60px;padding:46px}.service-detail__summary h2{margin-bottom:16px;font-size:40px}.service-detail__summary .lead{color:var(--text-secondary);font-size:17px}.service-detail__delivery ul{margin:0 0 24px;padding:0;list-style:none}.service-detail__delivery li{display:flex;gap:12px;padding:12px 0;border-bottom:1px solid var(--divider);color:var(--text-secondary)}.service-detail__delivery li span{color:var(--brand-blue);font-weight:900}.capability-pills{display:flex;flex-wrap:wrap;gap:8px}.capability-pills span{padding:7px 11px;border-radius:6px;background:var(--bg-blue-soft);color:var(--brand-blue);font-size:12px}.stage-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:45px}.stage-grid article{padding:32px;border-top:4px solid var(--brand-accent);background:var(--bg-blue-soft)}.stage-grid span{color:var(--brand-blue);font-size:12px}.stage-grid h3{margin:18px 0 9px;font-size:32px}.stage-grid p{margin:0;color:var(--text-secondary)}
......@@ -132,10 +132,10 @@
.contact-hero .breadcrumb a:hover{color:#fff}
/* 固定咨询入口:让在线咨询始终保持在页面可操作范围内。 */
.floating-consultation{position:fixed;right:24px;bottom:24px;z-index:90;display:inline-flex;width:198px;height:62px;align-items:center;justify-content:center;gap:11px;padding:0 22px;border:0;border-radius:32px;color:#fff;background:#1d2b49;box-shadow:0 12px 26px rgba(20,37,68,.2);cursor:pointer;font-size:20px;font-weight:700;letter-spacing:.02em;transition:transform .2s,box-shadow .2s,background .2s}.floating-consultation svg{width:25px;height:25px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.floating-consultation:hover{background:#14213a;box-shadow:0 16px 30px rgba(20,37,68,.27);transform:translateY(-2px)}.floating-consultation:focus-visible{outline:3px solid rgba(20,115,230,.42);outline-offset:4px}.floating-consultation i{position:absolute;top:-7px;right:-4px;display:grid;width:28px;height:28px;place-items:center;border-radius:50%;color:#fff;background:#ff4f5d;font-size:14px;font-style:normal;font-weight:700;box-shadow:0 2px 6px rgba(255,79,93,.22)}
.floating-phone{position:fixed;right:24px;bottom:98px;z-index:90;display:inline-flex;width:198px;height:62px;align-items:center;justify-content:center;gap:11px;padding:0 22px;border:0;border-radius:32px;color:#fff;background:#ff7900;box-shadow:0 12px 26px rgba(204,92,0,.2);font-size:20px;font-weight:700;letter-spacing:.02em;text-decoration:none;transition:transform .2s,box-shadow .2s,background .2s}.floating-phone svg{width:25px;height:25px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.floating-phone:hover{background:#e86d00;box-shadow:0 16px 30px rgba(204,92,0,.27);transform:translateY(-2px)}.floating-phone:focus-visible{outline:3px solid rgba(255,121,0,.35);outline-offset:4px}
.contact-dialog--phone{width:min(440px,calc(100% - 28px))}.contact-dialog--phone .contact-dialog__panel{padding:32px 34px 28px}.phone-dialog__heading>span{display:block;margin-bottom:8px;color:#e86d00;font-size:10px;font-weight:800;letter-spacing:.16em}.phone-dialog__heading h2{margin:0 0 8px;color:#1e3248;font-size:29px}.phone-dialog__heading p{margin:0;color:#66798a;font-size:14px;line-height:1.7}.phone-dialog__number{display:block;margin:24px 0 18px;color:#1e3248;font-size:30px;font-weight:750;letter-spacing:.04em}.phone-dialog__details{display:grid;gap:5px;padding:14px 0;border-top:1px solid #e2eaf0;border-bottom:1px solid #e2eaf0;color:#718393;font-size:12px;line-height:1.6}.phone-dialog__details a{color:var(--brand-blue)}.phone-dialog__call{display:flex;min-height:44px;margin-top:20px;align-items:center;justify-content:center;border-radius:9px;color:#fff;background:#ff7900;font-size:14px;font-weight:700;transition:background .2s,transform .2s}.phone-dialog__call:hover{background:#e86d00;transform:translateY(-1px)}
@media(max-width:760px){.floating-phone{right:16px;bottom:150px;width:148px;height:56px;gap:9px;padding:0 18px;font-size:18px}.floating-phone svg{width:23px;height:23px}.floating-consultation{right:16px;bottom:84px;width:148px;height:56px;gap:9px;padding:0 18px;font-size:18px}.floating-consultation svg{width:23px;height:23px}.floating-consultation i{top:-6px;right:-3px;width:26px;height:26px;font-size:13px}}
.floating-consultation{position:fixed;right:24px;bottom:24px;z-index:90;display:inline-flex;width:164px;height:52px;align-items:center;justify-content:center;gap:9px;padding:0 18px;border:0;border-radius:27px;color:#fff;background:#1d2b49;box-shadow:0 10px 22px rgba(20,37,68,.18);cursor:pointer;font-size:16px;font-weight:700;letter-spacing:.02em;transition:transform .2s,box-shadow .2s,background .2s}.floating-consultation svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.floating-consultation:hover{background:#14213a;box-shadow:0 14px 26px rgba(20,37,68,.25);transform:translateY(-2px)}.floating-consultation:focus-visible{outline:3px solid rgba(20,115,230,.42);outline-offset:4px}.floating-consultation i{position:absolute;top:-6px;right:-3px;display:grid;width:24px;height:24px;place-items:center;border-radius:50%;color:#fff;background:#ff4f5d;font-size:12px;font-style:normal;font-weight:700;box-shadow:0 2px 6px rgba(255,79,93,.22)}
.floating-phone{position:fixed;right:24px;bottom:88px;z-index:90;display:inline-flex;width:164px;height:52px;align-items:center;justify-content:center;gap:9px;padding:0 18px;border:0;border-radius:27px;color:#fff;background:#ff7900;box-shadow:0 10px 22px rgba(204,92,0,.18);cursor:pointer;font-family:inherit;font-size:16px;font-weight:700;letter-spacing:.02em;text-decoration:none;transition:transform .2s,box-shadow .2s,background .2s}.floating-phone--mobile{display:none}.floating-phone svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.floating-phone:hover{background:#e86d00;box-shadow:0 14px 26px rgba(204,92,0,.25);transform:translateY(-2px)}.floating-phone:focus-visible{outline:3px solid rgba(255,121,0,.35);outline-offset:4px}
.contact-dialog--phone{width:min(620px,calc(100% - 28px))}.contact-dialog--phone .contact-dialog__panel{padding:34px 36px 32px}.phone-dialog__heading{padding-right:42px}.phone-dialog__heading h2{margin:0 0 8px;color:#1e3248;font-size:29px}.phone-dialog__heading p{max-width:500px;margin:0;color:#66798a;font-size:14px;line-height:1.7}.official-contact-list{display:grid;grid-template-columns:1fr 1fr;margin-top:25px;overflow:hidden;border:1px solid #dbe6ef;border-radius:14px;background:#fff}.official-contact-item{min-width:0;padding:20px 21px;border-bottom:1px solid #e3ebf2}.official-contact-item:nth-child(odd){border-right:1px solid #e3ebf2}.official-contact-item:nth-last-child(-n+2){border-bottom:0}.official-contact-item>span{display:block;margin-bottom:7px;color:#748596;font-size:11px;font-weight:700}.official-contact-item>a,.official-contact-item>strong{display:block;overflow-wrap:anywhere;color:#1e3248;font-size:17px;font-weight:750;line-height:1.45}.official-contact-item>a:hover{color:var(--brand-blue)}.official-contact-item--phone>a{color:var(--brand-blue);font-size:22px;letter-spacing:.025em}.official-contact-item>p{margin:6px 0 0;color:#7c8b99;font-size:11px;line-height:1.55}
@media(max-width:760px){.floating-phone{right:16px;bottom:138px;width:132px;height:48px;gap:8px;padding:0 14px;font-size:15px}.floating-phone--desktop{display:none}.floating-phone--mobile{display:inline-flex}.floating-phone svg{width:20px;height:20px}.floating-consultation{right:16px;bottom:80px;width:132px;height:48px;gap:8px;padding:0 14px;font-size:15px}.floating-consultation svg{width:20px;height:20px}.floating-consultation i{top:-5px;right:-2px;width:22px;height:22px;font-size:11px}.official-contact-list{grid-template-columns:1fr}.official-contact-item:nth-child(odd){border-right:0}.official-contact-item:nth-last-child(2){border-bottom:1px solid #e3ebf2}.official-contact-item:last-child{border-bottom:0}}
@media(max-width:1080px){
.subject-stage-grid article{min-height:365px}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment