guoziyun 1 year ago
parent
commit
4af78c6613
11 changed files with 819 additions and 41 deletions
  1. 2 0
      app.js
  2. 24 6
      config/translate.js
  3. 90 6
      dist/stylesheets/header.css
  4. 58 0
      dist/stylesheets/styles.css
  5. 75 0
      routes/tooltricks.js
  6. 397 0
      test/article.html
  7. 83 0
      views/article.ejs
  8. 13 6
      views/footer.ejs
  9. 59 13
      views/header.ejs
  10. 11 10
      views/index.ejs
  11. 7 0
      views/tag-cloud.ejs

+ 2 - 0
app.js

@@ -81,6 +81,8 @@ app.use('/proxy', require('./routes/proxy'));
 
 app.use('/', require('./routes/index'));
 
+app.use('/tools-tricks', require('./routes/tooltricks'));
+
 app.use('/download', require('./routes/res/download'));
 
 

+ 24 - 6
config/translate.js

@@ -31,15 +31,15 @@ let commonDescription = {
 }
 
 let introTitle = {
-  zh: '打造全球最好的填色页网站',
-  en: 'Build The Best Coloring Pages Website In The World',
-  es: 'Construye el mejor sitio web de páginas de colorear del mundo',
-  pt: 'Construa o melhor site de páginas de colorir do mundo',
-  ja: '世界で最高の着色用ページのサイトを築きます',
+  zh: '欢迎来到涂色乐园',
+  en: 'Welcome Coloring Page',
+  es: 'Página de Colorear de Bienvenida',
+  pt: 'Página de Desenho para Colorir de Boas-Vindas',
+  ja: 'ようこそ 着色ページ',
 }
 
 let introText = {
-  zh: '是一个专业的填色页网站,涂画爱好者的乐园。拥有数量最多(超过 15000 多页)且类型最为全面的填色页资源。它每日更新,适合大人和小孩,你可以找到任何你想要的填色页。它们全部都是免费的,你可以下载、打印,分享。此外,它还有在线游戏的功能,可以在线涂色(数字填色)。我们支持网页浏览器和移动应用客户端,您可以随时随地畅玩!',
+  zh: '是涂画爱好者的乐园。拥有数量最多(超过 15000 多页)且类型最为全面的填色页资源。它每日更新,适合大人和小孩,你可以找到任何你想要的填色页。它们全部都是免费的,你可以下载、打印,分享。此外,它还有在线游戏的功能,可以在线涂色(数字填色)。我们支持网页浏览器和移动应用客户端,您可以随时随地畅玩!',
   en: 'A professional coloring page website, a paradise for coloring enthusiasts. It boasts the largest collection (over 15,000 pages) and most comprehensive range of coloring page resources. Updated daily, suitable for both adults and kids. All coloring pages are free for download, printing, and sharing. Additionally, it features online games for digital coloring (paint by number). We supports both web browsers and mobile apps, you can play anywhere anytime!',
   es: 'Un sitio web profesional de páginas para colorear, un paraíso para los entusiastas del coloreado. Cuenta con la colección más grande (más de 15,000 páginas) y la gama más completa de recursos de páginas para colorear. Actualizado diariamente, adecuado tanto para adultos como para niños. Todas las páginas para colorear son gratuitas para descargar, imprimir y compartir. Además, ofrece juegos en línea de coloreado digital (colorear por números). ¡Somos compatibles con navegadores web y aplicaciones móviles, puedes jugar en cualquier lugar y en cualquier momento!',
   pt: 'Um site profissional de páginas para colorir, um paraíso para entusiastas da coloração. Possui a maior coleção (mais de 15.000 páginas) e a gama mais abrangente de recursos de páginas para colorir. Atualizado diariamente, adequado tanto para adultos quanto para crianças. Todas as páginas para colorir são gratuitas para download, impressão e compartilhamento. Além disso, oferece jogos online de colorir digital (pintura por números). Somos compatíveis com navegadores da web e aplicativos móveis, você pode jogar em qualquer lugar e a qualquer hora!',
@@ -693,6 +693,22 @@ let coloringPageCategories = {
   ja: '塗り絵ページのカテゴリー',
 }
 
+let COLORINGPAGES = {
+  zh: '填色页',
+  en: 'COLORING PAGES',
+  es: 'PÁGINAS PARA COLOREAR',
+  pt: 'PÁGINAS PARA COLORIR',
+  ja: '着色用ページ',
+}
+
+let TOOLSTRICKS = {
+  zh: '工具 & 技巧',
+  en: 'TOOLS & TRICKS',
+  es: 'HERRAMIENTAS Y TRUCOS',
+  pt: 'FERRAMENTAS E TRUQUES',
+  ja: 'ツールとテクニック',
+}
+
 
 
 let translate = {
@@ -782,6 +798,8 @@ let translate = {
   sound,
   vibrate,
   autoNext,
+  COLORINGPAGES,
+  TOOLSTRICKS,
 }
 
 

+ 90 - 6
dist/stylesheets/header.css

@@ -1,7 +1,7 @@
 .header {
   padding: 0px 10px 0px 10px;
   display: flex;
-  height: 60px;
+  height: 80px;
   justify-content: space-between;
   align-items: center;
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
@@ -14,13 +14,23 @@
 
 .header-left {
   display: flex;
+  flex: 0 0 auto; /* 两侧不伸缩,保持内容宽度 */
   flex-direction: row;
   justify-content: space-around;
   align-items: center;
 }
 
+.header-center {
+  display: flex;
+  flex: 1; /* 中间部分占据剩余空间 */
+  flex-direction: row;
+  justify-content: space-evenly;
+  align-items: center;
+}
+
 .header-right {
   display: flex;
+  flex: 0 0 auto; /* 两侧不伸缩,保持内容宽度 */
   flex-direction: row;
   justify-content: space-around;
   align-items: center;
@@ -37,6 +47,69 @@
   background-color: #e5e5e5;
 }
 
+.menu {
+  color: black;
+  font-size: 18px;
+  font-weight: bold;
+  cursor: pointer;
+  text-decoration: none;
+}
+
+
+.pc-dropdown {
+  position: relative;
+  display: inline-block;
+  z-index: 200;
+}
+
+/* 下拉内容初始隐藏 */
+.pc-dropdown-content {
+  display: none;
+  position: absolute;
+  background-color: #ffffff;
+  font-size: 16px;
+  font-weight: lighter;
+  min-width: 200px;
+  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
+  z-index: 1;
+}
+
+/* 下拉菜单项样式 */
+.pc-dropdown-content a {
+  color: black;
+  padding: 12px 16px;
+  text-decoration: none;
+  display: block;
+}
+
+.pc-dropdown-content a.selected {
+  color: black;
+  font-weight: bold;
+  font-size: 18px;
+}
+
+
+/* 鼠标悬停时改变按钮文字颜色 */
+.menu:hover {
+  color: #3e8eff; /* 改变字体颜色 */
+  transition: color 0.3s ease; /* 添加颜色过渡效果 */
+  text-decoration: underline;
+}
+
+/* 鼠标悬停时显示下拉菜单 */
+.menu:hover .pc-dropdown-content {
+  display: block;
+}
+
+/* 下拉菜单项悬停效果 */
+.pc-dropdown-content a:hover {
+  color: #3e8eff;
+}
+
+
+
+
+/**************** 手机端的下拉框效果 **************/
 .dropdown {
   position: relative;
   display: inline-block;
@@ -132,14 +205,18 @@
 }
 
 
-/* 当屏幕宽度大于768px时显示搜索框 */
+/* 当屏幕宽度大于768px时 */
 @media (min-width: 768px) {
+  .mobi-only {
+    display: none;
+  }
+
   .search-container {
     display: block;
-    max-width: 600px;
-    min-width: 400px;
-    margin: 0 auto;
-    padding: 16px;
+    max-width: 500px;
+    min-width: 300px;
+    /* margin: 0 auto;
+    padding: 16px; */
   }
 
   .search-box {
@@ -171,5 +248,12 @@
   }
 }
 
+/* for mobile */
+@media (max-width: 768px) {
+  .header-center {
+    display: none;
+  }
+}
+
 
 

+ 58 - 0
dist/stylesheets/styles.css

@@ -337,3 +337,61 @@ body {
   z-index: 10;
 }
 
+
+footer {
+  color: color;
+  padding: 1rem;
+  text-align: center;
+  height: 60px;
+  border-top: 1px solid #ccc;
+}
+
+.footer-links {
+  display: flex;
+  justify-content: center;
+  gap: 2rem;
+  margin-bottom: 1rem;
+}
+
+.footer-links a {
+  color: black;
+  text-decoration: none;
+  transition: color 0.3s ease;
+  position: relative;
+  padding: 0.5rem;
+  font-size: 20px;
+  font-weight: bold;
+}
+
+.footer-links a:hover {
+  color: #3e8eff;
+}
+
+.footer-links a::after {
+  content: '';
+  position: absolute;
+  width: 0;
+  height: 2px;
+  bottom: 0;
+  left: 0;
+  background-color: #3e8eff;
+  transition: width 0.3s ease;
+}
+
+.footer-links a:hover::after {
+  width: 100%;
+}
+
+@media (max-width: 768px) {
+  .footer-links {
+      flex-direction: column;
+      gap: 0.5rem;
+  }
+  
+  footer {
+      padding: 1rem 0.5rem;
+      height: auto;
+  }
+  
+}
+

+ 75 - 0
routes/tooltricks.js

@@ -0,0 +1,75 @@
+var express = require('express');
+var router = express.Router();
+const models = require('../models');
+const config = require('../config/app');
+const redis = require('../libs/redis');
+const categories = require('../config/category');
+const { tags, tagsHashMap, getTagSeoTitle, getTagSeoDescription, getTagH1Title } = require('../config/tag');
+const languages = require('../config/language');
+const translate = require('../config/translate');
+const meta = require('../config/meta');
+const utils = require('../libs/utils');
+const DailyFactory = require('../models/daily-factory');
+const datefns = require('date-fns');
+const { format } = require('date-fns');
+const { getListBuilder } = require('../libs/pager');
+
+const CACHE_PREFIX = "tooltricks_v1";
+// const CACHE_EXPIRES = 60; // 60s刷新一次
+const CACHE_EXPIRES = 600;
+
+
+// tools-tricks
+router.get('/', function (req, res, next) {
+  (async function () {
+
+
+    let cacheKey = `${CACHE_PREFIX}_${req.originalUrl}`;
+    let htmlData = await redis.getAsync(cacheKey);
+    if (!htmlData) {
+      let lang = utils.lang.ensureLanguage(req.params.lang);
+      if (!req.cookies.lang || req.cookies.lang != lang) {
+        res.cookie('lang', lang, config.cookie);
+      }
+      let title = 'titletitle';
+      let description = 'description-description';
+
+      let data = {
+        title,
+        description,
+        languages,
+        translate,
+        lang,
+        uri: req.originalUrl,
+      };
+
+      // 渲染EJS模板到内存中
+      res.render('article', data, async (err, html) => {
+        if (err) {
+          // 如果渲染出错,调用next()传递错误
+          return next(err);
+        }
+
+        // 渲染成功,存redis, 发送数据到客户端
+        htmlData = html;
+        try {
+          await redis.set(cacheKey, htmlData, 'EX', CACHE_EXPIRES);
+        } catch (e) {
+          console.error(e);
+        }
+
+        res.send(htmlData);
+      });
+    } else {
+      // 缓存命中, 直接发送缓存数据
+      res.set({ 'X-From-Cache': 'true' });
+      res.send(htmlData);
+    }
+
+  })().catch(next);
+
+});
+
+
+
+module.exports = router;

+ 397 - 0
test/article.html

@@ -0,0 +1,397 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Cozymaxxing with Coloring Pages</title>
+  <style>
+    :root {
+      --primary-color: #e68a00;
+      --secondary-color: #f5f0e1;
+      --text-color: #333;
+      --light-text: #666;
+      --accent-color: #8b5a2b;
+      --background-color: #fffaf0;
+    }
+
+    * {
+      margin: 0;
+      padding: 0;
+      box-sizing: border-box;
+      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+    }
+
+    body {
+      background-color: var(--background-color);
+      color: var(--text-color);
+      line-height: 1.6;
+      padding: 0;
+      margin: 0;
+    }
+
+    .container {
+      max-width: 1200px;
+      margin: 0 auto;
+      padding: 0 20px;
+    }
+
+    header {
+      background-color: var(--primary-color);
+      color: white;
+      padding: 40px 0;
+      text-align: center;
+      position: relative;
+      overflow: hidden;
+    }
+
+    header::after {
+      content: "";
+      position: absolute;
+      bottom: -20px;
+      left: 0;
+      width: 100%;
+      height: 40px;
+      background-color: var(--background-color);
+      clip-path: polygon(0 100%, 100% 0, 100% 100%);
+    }
+
+    .header-content {
+      position: relative;
+      z-index: 2;
+    }
+
+    h1 {
+      font-size: 2.5rem;
+      margin-bottom: 10px;
+      font-weight: 700;
+    }
+
+    .date {
+      font-size: 1rem;
+      color: rgba(255, 255, 255, 0.9);
+      font-style: italic;
+    }
+
+    main {
+      padding: 50px 0;
+    }
+
+    section {
+      margin-bottom: 60px;
+      background-color: white;
+      border-radius: 10px;
+      padding: 30px;
+      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
+    }
+
+    h2 {
+      color: var(--primary-color);
+      margin-bottom: 20px;
+      padding-bottom: 10px;
+      border-bottom: 2px solid var(--secondary-color);
+      font-size: 2rem;
+    }
+
+    h3 {
+      color: var(--accent-color);
+      margin: 25px 0 15px;
+      font-size: 1.5rem;
+    }
+
+    p {
+      margin-bottom: 15px;
+      color: var(--text-color);
+    }
+
+    ul {
+      margin-left: 20px;
+      margin-bottom: 20px;
+    }
+
+    li {
+      margin-bottom: 10px;
+    }
+
+    .highlight {
+      background-color: var(--secondary-color);
+      padding: 2px 5px;
+      border-radius: 3px;
+      font-weight: 500;
+    }
+
+    .tips-grid {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+      gap: 20px;
+      margin: 30px 0;
+    }
+
+    .tip-card {
+      background-color: var(--secondary-color);
+      padding: 20px;
+      border-radius: 8px;
+      transition: transform 0.3s ease;
+    }
+
+    .tip-card:hover {
+      transform: translateY(-5px);
+    }
+
+    .tip-card h4 {
+      color: var(--accent-color);
+      margin-bottom: 10px;
+      font-size: 1.2rem;
+    }
+
+    .coloring-pages {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+      gap: 25px;
+      margin: 30px 0;
+    }
+
+    .page-card {
+      background-color: white;
+      border-radius: 8px;
+      overflow: hidden;
+      box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
+      transition: all 0.3s ease;
+    }
+
+    .page-card:hover {
+      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
+      transform: translateY(-5px);
+    }
+
+    .page-image {
+      height: 200px;
+      background-color: #f0f0f0;
+      overflow: hidden;
+      position: relative;
+    }
+
+    .page-image img {
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+      transition: transform 0.5s ease;
+    }
+
+    .page-card:hover .page-image img {
+      transform: scale(1.05);
+    }
+
+    .page-content {
+      padding: 15px;
+    }
+
+    .page-title {
+      font-weight: 600;
+      margin-bottom: 8px;
+      color: var(--accent-color);
+    }
+
+    .page-category {
+      font-size: 0.85rem;
+      color: var(--light-text);
+      background-color: var(--secondary-color);
+      display: inline-block;
+      padding: 3px 8px;
+      border-radius: 15px;
+    }
+
+    footer {
+      background-color: var(--accent-color);
+      color: white;
+      text-align: center;
+      padding: 30px 0;
+    }
+
+    .footer-content {
+      max-width: 600px;
+      margin: 0 auto;
+    }
+
+    .footer-content p {
+      margin-bottom: 10px;
+    }
+
+    @media (max-width: 768px) {
+      h1 {
+        font-size: 2rem;
+      }
+
+      h2 {
+        font-size: 1.7rem;
+      }
+
+      h3 {
+        font-size: 1.3rem;
+      }
+
+      section {
+        padding: 20px;
+      }
+
+      .tips-grid,
+      .coloring-pages {
+        grid-template-columns: 1fr;
+      }
+    }
+  </style>
+</head>
+
+<body>
+  <header>
+    <div class="container header-content">
+      <h1>The Staple You Need to Maximize Cozymaxxing — And It’s Free</h1>
+      <div class="date">2025-04-29 00:00:00</div>
+    </div>
+  </header>
+
+  <main class="container">
+    <section>
+      <h2>What is Cozymaxxing?</h2>
+      <p>Cozymaxxing is the practice of fueling personal happiness by leaning into comfort. Turning warm fuzzy feelings
+        into an indulgent experience is the heart of the routine, with one major payoff: stress relief.</p>
+      <p>Like cozymaxxing, coloring is known to reduce stress by calming the mind and offering a low-stakes creative
+        activity. So it only seems natural for these two worlds to collide. (Peacefully and slowly, of course!)</p>
+      <p>When cozymaxxing meets coloring, you are layering these comforting elements into your self-care routine—like a
+        metaphorical bundle of blankets. The result allows you to embrace your needs for comfort and creativity being
+        met in an environment that’s low pressure and calm.</p>
+    </section>
+
+    <section>
+      <h2>Cozymaxxing Your Environment</h2>
+      <p>Cozymaxxing can be all about decluttering, but don’t let a sudden to-do list stop you from enjoying a calm
+        moment when you need it most. Work with what you’ve got. Find a room or spot where you can allow yourself to
+        feel free to be comfortable. Incorporate a few creature comforts into your environment that bring a warm and
+        peaceful vibe.</p>
+
+      <div class="tips-grid">
+        <div class="tip-card">
+          <h4>Lighting</h4>
+          <p>Setting the tone is key, so consider how lighting affects your mood. Portable and rechargeable dimmable
+            lights can be taken wherever you enjoy your relaxing coloring pages. They bring a nice glow without
+            overwhelming the space.</p>
+        </div>
+
+        <div class="tip-card">
+          <h4>Scents</h4>
+          <p>Scents are personal, and your preferences can be driven by your mood or season. A pine tree candle in
+            December exudes coziness, but then there are times when a light floral, like gardenia, is the right scent
+            for the moment.</p>
+        </div>
+
+        <div class="tip-card">
+          <h4>Textiles</h4>
+          <p>Add your favorite blanket to the mix. It can be a weighted blanket, a faux fur throw, or your own
+            handcrafted design. You can’t go wrong when it checks boxes for being in a fabric you adore, at a size you
+            like, and keeps you at just the perfect level of toasty.</p>
+        </div>
+      </div>
+    </section>
+
+    <section>
+      <h2>Cozymaxxing Your Workflow</h2>
+      <p>Before cooking, chefs lay out their tools and ingredients in a way that allows them to work effectively. The
+        process has a name, "mise en place," which means "putting in place." So consider incorporating your own mise en
+        place to your coloring routine.</p>
+
+      <h3>Supplies</h3>
+      <p>Gather the supplies you want to use for the coloring session. Experiment with limiting yourself to one or two
+        mediums, like alcohol markers and gel pens, to stave off decision paralysis.</p>
+
+      <h3>Palette</h3>
+      <p>If you’re stuck on how to pick a color scheme for your page, don’t stress. There are different tools you can
+        use to get out of a rut.</p>
+      <p>Test out digital resources like <span class="highlight">Colour Palette Generator</span>, which picks random
+        palettes in one click. Sarah Renae Clark’s Color Cube and Color Catalog offer both tangible and digital
+        solutions that allow you be intentional in the search for the right color palette.</p>
+
+      <h3>Do Not Disturb</h3>
+      <p>Whether you’re working on your iPad or by hand, don’t forget to put your devices on silent or set them to Do
+        Not Disturb.</p>
+      <p>It’s not about shutting off the world (you’re a part of it after all). It’s about honing in on one big piece of
+        it: you. Take the time to give time to yourself.</p>
+    </section>
+
+    <section>
+      <h2>Cozy Coloring Pages</h2>
+      <p>To color a la cozymaxxing, you need the key ingredient: cozy coloring pages! These free coloring pages fit the
+        bill for when you want to carve out space to create warm vibes all around.</p>
+
+      <div class="coloring-pages">
+        <div class="page-card">
+          <div class="page-image">
+            <img src="https://via.placeholder.com/500/333/fff?text=Kawaii+Coloring" alt="Kawaii Coloring Page">
+          </div>
+          <div class="page-content">
+            <div class="page-category">Kawaii</div>
+            <div class="page-title">Girl and Bunny Cozy Coloring Page</div>
+          </div>
+        </div>
+
+        <div class="page-card">
+          <div class="page-image">
+            <img src="https://via.placeholder.com/500/333/fff?text=Kawaii+Cat" alt="Kawaii Cat Coloring Page">
+          </div>
+          <div class="page-content">
+            <div class="page-category">Kawaii</div>
+            <div class="page-title">Adorable Cat Juice Box Shop Coloring Page</div>
+          </div>
+        </div>
+
+        <div class="page-card">
+          <div class="page-image">
+            <img src="https://via.placeholder.com/500/333/fff?text=Aesthetic+Tea" alt="Aesthetic Tea Coloring Page">
+          </div>
+          <div class="page-content">
+            <div class="page-category">Aesthetic</div>
+            <div class="page-title">Warm Tea and Honey Cozy Coloring Page</div>
+          </div>
+        </div>
+
+        <div class="page-card">
+          <div class="page-image">
+            <img src="https://via.placeholder.com/500/333/fff?text=Spa+Retreat" alt="Spa Retreat Coloring Page">
+          </div>
+          <div class="page-content">
+            <div class="page-category">Aesthetic</div>
+            <div class="page-title">Spa Retreat Comforting Coloring Page</div>
+          </div>
+        </div>
+
+        <div class="page-card">
+          <div class="page-image">
+            <img src="https://via.placeholder.com/500/333/fff?text=Autumn+Fairy" alt="Autumn Fairy Coloring Page">
+          </div>
+          <div class="page-content">
+            <div class="page-category">Fairy</div>
+            <div class="page-title">Cozy Autumn Fairy Coloring Page</div>
+          </div>
+        </div>
+
+        <div class="page-card">
+          <div class="page-image">
+            <img src="https://via.placeholder.com/500/333/fff?text=Mushroom+Fairy" alt="Mushroom Fairy Coloring Page">
+          </div>
+          <div class="page-content">
+            <div class="page-category">Fairy</div>
+            <div class="page-title">Dreamy Mushroom Fairy Coloring Page</div>
+          </div>
+        </div>
+      </div>
+    </section>
+  </main>
+
+  <footer>
+    <div class="container footer-content">
+      <p>Create your cozy coloring experience today</p>
+      <p>© 2025 CozyColoringPages. All rights reserved.</p>
+    </div>
+  </footer>
+</body>
+
+</html>

+ 83 - 0
views/article.ejs

@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html lang="zh">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>文章模板</title>
+  <!-- <link rel="stylesheet" href="/stylesheets/header.css"> -->
+  <style>
+    :root {
+      --space-unit: 8px;
+      --font-base: 1.1rem;
+    }
+
+    body {
+      font-family: system-ui;
+      line-height: 1.6;
+      padding: 0 1rem;
+      max-width: 1200px;
+      margin: 0 auto;
+    }
+
+    h1 {
+      font-size: clamp(2rem, 5vw, 2.5rem);
+      margin: calc(var(--space-unit) * 3) 0;
+    }
+
+    h2 {
+      font-size: 1.8rem;
+      margin: 2.5rem 0 1.5rem;
+    }
+
+    h3 {
+      font-size: 1.4rem;
+      border-bottom: 1px solid #eee;
+      padding-bottom: 0.5rem;
+      margin: 1rem 0;
+    }
+
+    p {
+      font-size: var(--font-base);
+      margin-bottom: 1.5em;
+    }
+
+    img {
+      max-width: 100%;
+      height: auto;
+    }
+
+    @media (min-width: 768px) {
+      body {
+        padding: 0 2rem;
+      }
+
+      .article-grid {
+        display: grid;
+        grid-template-columns: 3fr 1fr;
+        gap: 2rem;
+      }
+
+      .float-right {
+        float: right;
+        margin-left: 2rem;
+        shape-outside: margin-box;
+      }
+    }
+  </style>
+</head>
+
+<body>
+  <article class="article-grid">
+    <h1>主标题</h1>
+    <section>
+      <h2>一级标题</h2>
+      <img src="/assets/icon/logo_1024x1024.png" class="float-right" alt="示例图片">
+      <p>正文内容...</p>
+      <h3>二级标题</h3>
+      <p>更多内容...</p>
+    </section>
+  </article>
+</body>
+
+</html>

+ 13 - 6
views/footer.ejs

@@ -1,7 +1,14 @@
-<div class="tag-cloud">
-    <% tags.forEach(item=> { %>
-        <a href="/<%= lang %>/tag/<%= item.tag %>" class="tag" style="color: <%= item.color %>;">
-            <%= item.title[lang] %>
+<footer>
+    <div class="footer-links">
+        <a href="/<%= lang %>/info#about">
+            <%= translate.about[lang] %>
         </a>
-        <% }); %>
-</div>
+        <a href="/<%= lang %>/info#contact">
+            <%= translate.contactUs[lang] %>
+        </a>
+        <a href="/policy.html">
+            <%= translate.policy[lang] %>
+        </a>
+    </div>
+    <p>Copyright &copy; 2025 Art Number Coloring All Rights Reserved.</p>
+</footer>

+ 59 - 13
views/header.ejs

@@ -1,6 +1,6 @@
 <header class="header">
   <div class="header-left">
-    <div class="dropdown">
+    <div class="mobi-only dropdown">
       <svg class="dropbtn" style="margin-right: 5px;" width="24px" height="24px" viewBox="0 0 24 24" fill="none"
         xmlns="http://www.w3.org/2000/svg">
         <path opacity="0.5" d="M21 6L3 6" stroke="#1C274C" stroke-width="2.0" stroke-linecap="round" />
@@ -69,17 +69,61 @@
   </div>
 
 
-  <div class="search-container">
-    <form action="/<%= lang %>/search" method="GET" class="search-box">
-      <input type="text" name="search" placeholder="Search...">
-      <button type="submit">
-        <svg fill="#000000" width="16px" height="16px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-          <path
-            d="M12.027 9.92L16 13.95 14 16l-4.075-3.976A6.465 6.465 0 0 1 6.5 13C2.91 13 0 10.083 0 6.5 0 2.91 2.917 0 6.5 0 10.09 0 13 2.917 13 6.5a6.463 6.463 0 0 1-.973 3.42zM1.997 6.452c0 2.48 2.014 4.5 4.5 4.5 2.48 0 4.5-2.015 4.5-4.5 0-2.48-2.015-4.5-4.5-4.5-2.48 0-4.5 2.014-4.5 4.5z"
-            fill-rule="evenodd" />
-        </svg>
-      </button>
-    </form>
+  <div class="header-center">
+    <div class="menu">
+      <div>
+        <span>
+          <%= translate.COLORINGPAGES[lang] %>
+        </span>
+        <span><svg class="ast-arrow-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+            version="1.1" x="0px" y="0px" width="15px" height="10px" viewBox="57 35.171 26 16.043"
+            enable-background="new 57 35.171 26 16.043" xml:space="preserve">
+            <path d="M57.5,38.193l12.5,12.5l12.5-12.5l-2.5-2.5l-10,10l-10-10L57.5,38.193z"></path>
+          </svg></span>
+      </div>
+      <div class="pc-dropdown-content">
+        <a href="/<%= lang %>" class="<%= uri == `/${lang}` ? 'selected' : '' %>">
+          <%= translate.homePage[lang] %>
+        </a>
+        <a href="/<%= lang %>/gallery" class="<%= uri.includes(`/${lang}/gallery`) ? 'selected' : '' %>">
+          <%= translate.gallery[lang] %>
+        </a>
+        <a href="/<%= lang %>/videos" class="<%= uri.includes(`/${lang}/videos`) ? 'selected' : '' %>">
+          <%= translate.videoPage[lang] %>
+        </a>
+        <a href="/<%= lang %>/tag" class="<%= uri.includes(`/${lang}/tag`) ? 'selected' : '' %>">
+          <%= translate.coloringPageCategories[lang] %>
+        </a>
+        <a href="/<%= lang %>/albums" class="<%= uri.includes(`/${lang}/albums`) ? 'selected' : '' %>">
+          <%= translate.album[lang] %>
+        </a>
+        <a href="/<%= lang %>/special" class="<%= uri.includes(`/${lang}/special`) ? 'selected' : '' %>">
+          <%= translate.special[lang] %>
+        </a>
+        <a href="/<%= lang %>/artists" class="<%= uri.includes(`/${lang}/artist`) ? 'selected' : '' %>">
+          <%= translate.coloringPageArtists[lang] %>
+        </a>
+      </div>
+    </div>
+    <div class="menu">
+      <%= translate.TOOLSTRICKS[lang] %>
+    </div>
+    <a class="menu" href="/<%= lang %>/info#app">
+      <%= translate.app[lang] %>
+    </a>
+
+    <div class="search-container">
+      <form action="/<%= lang %>/search" method="GET" class="search-box">
+        <input type="text" name="search" placeholder="Search...">
+        <button type="submit">
+          <svg fill="#000000" width="16px" height="16px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+            <path
+              d="M12.027 9.92L16 13.95 14 16l-4.075-3.976A6.465 6.465 0 0 1 6.5 13C2.91 13 0 10.083 0 6.5 0 2.91 2.917 0 6.5 0 10.09 0 13 2.917 13 6.5a6.463 6.463 0 0 1-.973 3.42zM1.997 6.452c0 2.48 2.014 4.5 4.5 4.5 2.48 0 4.5-2.015 4.5-4.5 0-2.48-2.015-4.5-4.5-4.5-2.48 0-4.5 2.014-4.5 4.5z"
+              fill-rule="evenodd" />
+          </svg>
+        </button>
+      </form>
+    </div>
   </div>
 
 
@@ -119,7 +163,9 @@
     </div>
 
     <!-- <a href="/<%= lang %>/app" class="header-right-btn"><%= translate.app[lang] %></a>-->
-    <a href="/<%= lang %>/myworks" class="header-right-btn"><%= translate.my[lang] %></a>
+    <a href="/<%= lang %>/myworks" class="header-right-btn">
+      <%= translate.my[lang] %>
+    </a>
   </div>
 
 </header>

+ 11 - 10
views/index.ejs

@@ -49,16 +49,17 @@
 
 <body>
   <%- include('header') %>
-    <%- include('intro-section') %>
-    <%- include('video-story-section') %>
-    <%- include('tag-section') %>
-    <%- include('latest-section') %>
-    <%- include('album-section') %>
-    <%- include('designer-section') %>
-    <%- include('special-section') %>
-    <%- include('footer') %>
-    <%- include('cookie-banner') %>
-    <div style="height: 50px;"></div>
+  <%- include('intro-section') %>
+  <%- include('video-story-section') %>
+  <%- include('tag-section') %>
+  <%- include('latest-section') %>
+  <%- include('album-section') %>
+  <%- include('designer-section') %>
+  <%- include('special-section') %>
+  <%- include('tag-cloud') %>
+  <%- include('footer') %>
+  <%- include('cookie-banner') %>
+  <div style="height: 50px;"></div>
 
   <script src="/scripts/progress.js"></script>
 </body>

+ 7 - 0
views/tag-cloud.ejs

@@ -0,0 +1,7 @@
+<div class="tag-cloud">
+    <% tags.forEach(item=> { %>
+        <a href="/<%= lang %>/tag/<%= item.tag %>" class="tag" style="color: <%= item.color %>;">
+            <%= item.title[lang] %>
+        </a>
+        <% }); %>
+</div>