| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- {% extends "base.html" %}
- {% block title %}逐鹿导航 - 首页{% endblock %}
- {% block content %}
- <section class="search-area py-4">
- <div class="d-flex justify-content-center">
- <form method="GET" action="{{ url_for('search') }}" class="search-form w-100" style="max-width:600px;">
- <div class="search-box d-flex align-items-center shadow-sm w-100">
- <input type="text" name="q" class="form-control search-input"
- placeholder="🔍 输入关键词搜索网站..." value="{{ search_query or '' }}">
- <button class="btn btn-primary rounded-circle ms-2 btn-search" type="submit">
- <i class="bi bi-search"></i>
- </button>
- </div>
- <div class="search-engine mt-3 text-center">
- <div class="btn-group" role="group">
- {% for name, label in {'bing':'必应','baidu':'百度','google':'谷歌','local':'本地'}.items() %}
- <input type="radio" class="btn-check" name="search-engine" id="engine-{{ name }}" value="{{ name }}"
- autocomplete="off" {% if name == saved_engine %}checked{% endif %}>
- <label class="btn btn-outline-primary btn-sm rounded-pill" for="engine-{{ name }}">{{ label }}</label>
- {% endfor %}
- </div>
- </div>
- </form>
- </div>
- </section>
- <!-- ==================== 公共站点和分类 ==================== -->
- <section class="content-section container py-4">
- {# ===== 公共站点 ===== #}
- {% if public_sites %}
- {% set pub_cats_dict = {} %}
- {% for site in public_sites %}
- {% set cat_name = site.category.name if site.category else '未分类' %}
- {% if cat_name not in pub_cats_dict %}
- {% set pub_cats_dict = pub_cats_dict.update({cat_name: [site]}) or pub_cats_dict %}
- {% else %}
- {% set _ = pub_cats_dict[cat_name].append(site) %}
- {% endif %}
- {% endfor %}
- {% for cat_name, cat_sites in pub_cats_dict.items() %}
- <div class="category mb-4 p-3 bg-white rounded shadow-sm">
- <h4 class="category-title mb-3">
- <span class="category-accent" data-cat="{{ cat_name }}"></span>{{ cat_name }}
- </h4>
- <div class="sites-grid">
- {% for site in cat_sites %}
- <div class="site-card">
- <a href="{{ site.url }}" target="_blank" class="card-link">
- <div class="card site-item">
- <div class="card-top">
- {% if site.custom_icon %}
- <img src="{{ site.custom_icon }}" onerror="this.src='{{ url_for('static', filename='images/default-icon.png') }}'" class="favicon-img" alt="icon">
- {% elif site.icon %}
- <img src="{{ site.icon }}" onerror="this.src='{{ url_for('static', filename='images/default-icon.png') }}'" class="favicon-img" alt="icon">
- {% else %}
- <img src="{{ url_for('static', filename='images/default-icon.png') }}" class="favicon-img" alt="icon">
- {% endif %}
- <div class="site-info">
- <h6 class="site-name">{{ site.name }}</h6>
- {% if site.description %}
- <p class="site-desc">{{ site.description }}</p>
- {% endif %}
- </div>
- </div>
- </div>
- </a>
- </div>
- {% endfor %}
- </div>
- </div>
- {% endfor %}
- {% else %}
- {# 如果没有公共站点,显示空状态 #}
- <div class="empty text-center py-5">
- <i class="bi bi-bookmark display-3 text-muted"></i>
- <h5 class="text-secondary mt-3">暂无公共站点</h5>
- <p class="text-muted small">暂时没有可展示的公共站点,敬请期待</p>
- </div>
- {% endif %}
- </section>
- {% endblock %}
- {% block scripts %}
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
- <style>
- body { background-color:#f5f7fa; font-family:"PingFang SC","Microsoft YaHei","Noto Sans SC",sans-serif; color:#333; }
- /* 分类标题 */
- .category-title {
- font-weight:600;
- font-size:1.1rem;
- display:flex;
- align-items:center;
- }
- .category-accent { width:5px; height:18px; border-radius:3px; margin-right:8px; display:inline-block; }
- /* 网格布局 */
- .sites-grid { display:grid; grid-template-columns:repeat(5,1fr); gap:14px; text-align:left; align-items:stretch; }
- .site-card { transition: transform 0.2s ease, box-shadow 0.3s ease; text-align:left; height:100%; }
- .site-card:hover { transform: translateY(-4px); }
- /* 卡片 */
- .card.site-item {
- border:1px solid transparent;
- border-radius:10px;
- background:rgba(255,255,255,0.95);
- backdrop-filter:blur(3px);
- box-shadow:0 2px 6px rgba(0,0,0,0.05);
- transition: all 0.3s ease;
- display:flex; flex-direction:column; justify-content:space-between; align-items:flex-start; height:100%; padding:0.7rem 0.8rem;
- }
- .card.site-item:hover {
- border-color:rgba(64,158,255,0.4);
- box-shadow:0 6px 14px rgba(64,158,255,0.25);
- transform: translateY(-4px);
- }
- /* 卡片内容 */
- .card-top { display:flex; align-items:center; gap:0.55rem; }
- .favicon-img { width:40px; height:40px; border-radius:8px; flex-shrink:0; object-fit:cover; transition:transform 0.25s ease; }
- .card.site-item:hover .favicon-img { transform:scale(1.1); }
- .site-info { flex:1; text-align:left; }
- /* 文字样式 */
- .site-name { font-size:0.95rem; font-weight:normal; color:#333; line-height:1.35; margin-bottom:0.1rem; }
- .site-desc { font-size:0.8rem; color:#777; line-height:1.35; margin:0; }
- /* 响应式 */
- @media (max-width:1200px){.sites-grid{grid-template-columns:repeat(4,1fr);}}
- @media (max-width:992px){.sites-grid{grid-template-columns:repeat(3,1fr);}}
- @media (max-width:768px){
- .sites-grid{grid-template-columns:repeat(2,1fr); gap:10px;}
- .favicon-img{width:34px;height:34px;}
- .site-name{font-size:0.9rem;}
- .site-desc{font-size:0.75rem;}
- }
- @media (max-width:480px){.sites-grid{grid-template-columns:repeat(1,1fr);}}
- </style>
- <script>
- const engineMap = { 'baidu':'https://www.baidu.com/s?wd=','bing':'https://www.bing.com/search?q=','google':'https://www.google.com/search?q=' };
- document.addEventListener('DOMContentLoaded', () => {
- const form = document.querySelector('.search-form');
- const input = document.querySelector('.search-input');
- const engineRadios = document.querySelectorAll('input[name="search-engine"]');
- const categoryAccents = document.querySelectorAll('.category-accent');
- const gradients = [
- ['#409EFF','#66b1ff'],
- ['#67C23A','#95d475'],
- ['#E6A23C','#f3c56b'],
- ['#F56C6C','#f89898'],
- ['#8E44AD','#b57edc'],
- ['#1ABC9C','#48C9B0'],
- ['#2D8CF0','#5CADFF']
- ];
- function hashStringToIndex(str, max) {
- let hash = 0;
- for (let i=0;i<str.length;i++) hash = (hash*31 + str.charCodeAt(i)) >>> 0;
- return hash % max;
- }
- categoryAccents.forEach(el => {
- const idx = hashStringToIndex(el.dataset.cat, gradients.length);
- const g = gradients[idx];
- el.style.background = `linear-gradient(135deg, ${g[0]}, ${g[1]})`;
- });
- function setEngineCookie(value) { document.cookie = `search-engine=${value}; max-age=${30 * 24 * 3600}; path=/`; }
- engineRadios.forEach(radio => { radio.addEventListener('change', ()=>setEngineCookie(radio.value)); });
- form.addEventListener('submit', e => {
- const engine = document.querySelector('input[name="search-engine"]:checked').value;
- setEngineCookie(engine);
- const query = input.value.trim();
- if(engine!=='local'){ e.preventDefault(); if(query) window.open(engineMap[engine]+encodeURIComponent(query),'_blank'); }
- else if(!query){ e.preventDefault(); alert('请输入搜索关键词'); }
- });
- });
- </script>
- {% endblock %}
|