安全(P0) - 发布包签名:新增 scripts/package_keygen.php、scripts/package_verify.php、 ywxapp\service\PackageVerifier;FrameworkService::apply() 解压前强制验签 (ywxapp.framework_package_verify,默认开启) - JWT 收紧:config/jwt.php 移除公开默认密钥,JwtService::assertStrongSecret() 校验非空 / 长度≥32 / 已知弱值;.env.production.example 键名由 JWT_SECRET_KEY 修正为 JWT_SECRET - /api/v1/Article:免登录白名单收窄为只读接口,写操作字段白名单 + assertOwner() 越权校验 - 开发者令牌:查找接口不再回显明文、统一失败文案 + 限流 - TemplateInstaller:文件名白名单 + realpath 归一化 + 目录内断言,修复 Zip Slip;补 use ZipArchive - 后台登录:接入验证码、失败锁定与登录限流(config/ratelimit.php) - 缓存 / Session 驱动可由 .env 覆盖(CACHE_DRIVER / SESSION_TYPE),集群部署改 redis - paycenter 支付日志开关改为 PAY_LOG,不再跟随 APP_DEBUG 工程化 / 交付 - 新增 CHANGELOG.md 与 .env.production.example;composer.lock 入库锁定依赖版本 - 插件离线安装 CLI 增加 --uid,后台上传安装透传 uid,付费插件授权校验可通过 - 授权拒绝文案区分「未携带 uid」与「未找到有效授权」,便于排障 - .gitignore 放行 .env.production.example / .env.addon.example / .gitattributes / public/.htaccess 结构 - appmall 由 addon/appmall 迁移为独立应用 app/appmall(市场 / 开发者中心 / 审核 / 分润)
221 lines
11 KiB
HTML
221 lines
11 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>{$seo.title|default='网址导航 - 首页'}</title>
|
||
<meta name="keywords" content="{$seo.keywords|default='网址导航,常用网址,上网导航'}">
|
||
<meta name="description" content="{$seo.description|default='简洁实用的网址导航,支持分类管理、搜索聚合、我的导航与暗黑模式'}">
|
||
<link rel="canonical" href="{$siteUrl|default=''}/haonav/index.html">
|
||
{notempty name="jsonld"}<script type="application/ld+json">{$jsonld|raw}</script>{/notempty}
|
||
{include file="public/styles" /}
|
||
<link rel="stylesheet" href="/static/haonav/css/nav-page-index.css">
|
||
<link rel="manifest" href="/static/haonav/manifest.json">
|
||
<meta name="theme-color" content="#667eea">
|
||
</head>
|
||
|
||
<body>
|
||
<!-- 顶部导航栏 -->
|
||
{assign name="navActive" value="index" /}
|
||
{assign name="navSearch" value="engine" /}
|
||
{assign name="navExtras" value="1" /}
|
||
{assign name="navUser" value="1" /}
|
||
{include file="public/navbar" /}
|
||
|
||
<div class="main-content">
|
||
<!-- 广告位:首页顶部 -->
|
||
{notempty name="ads.home_top"}
|
||
<div class="ad-box ad-home-top">
|
||
<span class="ad-label">广告</span>
|
||
{volist name="ads.home_top" id="ad"}
|
||
{if $ad.type == 1}
|
||
<a class="ad-item" href="/haonav/ad/click?id={$ad.id}" target="_blank" rel="nofollow">
|
||
<img src="{$ad.image}" alt="{$ad.title}" loading="lazy">
|
||
</a>
|
||
{else/}
|
||
{$ad.code|raw}
|
||
{/if}
|
||
{/volist}
|
||
</div>
|
||
{/notempty}
|
||
|
||
<!-- 顶部小组件:天气 + 实时热搜 -->
|
||
<div class="widget-row">
|
||
<div class="weather-widget" id="weatherWidget" style="display:none;">
|
||
<span class="w-city" id="wCity"></span>
|
||
<span class="w-type" id="wType"></span>
|
||
<span class="w-temp" id="wTemp"></span>
|
||
<span class="w-tips" id="wTips"></span>
|
||
</div>
|
||
<div class="hotsearch-widget" id="hotSearchWidget" style="display:none;">
|
||
<div class="hs-head"><span>🔥 实时热搜</span> <span class="hs-tabs" id="hsTabs">
|
||
<a data-src="baidu" class="active">百度</a>
|
||
<a data-src="weibo">微博</a>
|
||
<a data-src="zhihu">知乎</a>
|
||
</span></div>
|
||
<ol class="hs-list" id="hotSearchList"></ol>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 我的导航(收藏) -->
|
||
<div class="mynav">
|
||
<div class="mynav-head">
|
||
<h3>⭐ 我的导航 <span class="tip" id="myNavTip">(点击卡片上的 ★ 收藏,可拖拽排序)</span></h3>
|
||
<button class="nav-btn" id="favShareBtn" title="生成分享链接,把收藏夹分享给好友">🔗 分享收藏夹</button>
|
||
</div>
|
||
<div class="mynav-list" id="myNavList"></div>
|
||
<div class="mynav-empty" id="myNavEmpty">还没有收藏,点击任意网址卡片右上角的 ★ 添加到这里~</div>
|
||
</div>
|
||
|
||
<!-- 热门推荐 -->
|
||
<div class="hot-recommend">
|
||
<h3>🔥 热门推荐</h3>
|
||
<div class="hot-grid">
|
||
{volist name='hotspot' id='vo'}
|
||
<div class="hot-item">
|
||
<a href="{:url('[haonav_site]',['id'=>$vo.id])}" target="_blank" style="display:flex;align-items:center;gap:10px;text-decoration:none;color:inherit;flex:1;min-width:0;">
|
||
<span class="hot-icon"><img src="{$vo.show_icon}" loading="lazy" alt="{$vo.title}"></span>
|
||
<span class="hot-info">
|
||
<h4>{$vo.title}</h4>
|
||
<p>{$vo.description |default='暂无描述'}</p>
|
||
{if $vo.rating_count > 0}<span class="website-rating">⭐ {$vo.rating} ({$vo.rating_count})</span>{/if}
|
||
</span>
|
||
</a>
|
||
<span class="qr-btn js-qr" data-url="{$vo.url}" title="二维码">▦</span>
|
||
</div>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
|
||
{volist name="data" id="vo" key="k"}
|
||
<!-- 分类区块 -->
|
||
<div class="category-block" id="cat-{$k}">
|
||
<div class="section-title">
|
||
<h2>📋 <a href="{:url('[haonav_category]',['id'=>$vo.id])}" target="_blank"> {$vo.title} </a></h2>
|
||
|
||
<div class="sub-title"> <a href="{:url('[haonav_category]',['id'=>$vo.id])}"><span>全部</span></a></div>
|
||
</div>
|
||
|
||
<!-- 首页只展示一级分类下的全部链接,二级分类在分类页展示 -->
|
||
{notempty name="vo.links"}
|
||
<div class="sub-category">
|
||
<div class="website-grid">
|
||
{volist name="vo.links" id="site"}
|
||
<div class="website-card" data-sid="{$site.id}">
|
||
<span class="fav-btn js-fav" data-id="{$site.id}" data-title="{$site.title}" data-url="{$site.url}" data-icon="{$site.show_icon}" title="收藏">★</span>
|
||
<span class="qr-btn js-qr" data-url="{$site.url}" title="二维码">▦</span>
|
||
<a href="{:url('[haonav_site]',['id'=>$vo.id])}" target="_blank" title="{$site.title}" style="text-decoration:none;color:inherit;display:block;">
|
||
<div class="website-icon"><img src="{$site.show_icon}" loading="lazy" alt="{$site.title}"></div>
|
||
<div class="website-name">{$site.title}</div>
|
||
{if $site.rating_count > 0}<div class="website-rating">⭐ {$site.rating}<span class="rc">({$site.rating_count})</span></div>{/if}
|
||
</a>
|
||
</div>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
</div>
|
||
{/volist}
|
||
|
||
<!-- 友情链接 / 推荐 -->
|
||
<div class="hot-recommend">
|
||
<div class="section-title"><h2>🤝 友情链接</h2></div>
|
||
<div class="hot-grid">
|
||
{volist name='links' id='vo'}
|
||
<div class="hot-item">
|
||
<a href="{$vo.url}" target="_blank" style="display:flex;align-items:center;gap:10px;text-decoration:none;color:inherit;flex:1;min-width:0;">
|
||
<span class="hot-icon"><img src="{$vo.show_icon}" loading="lazy" alt="{$vo.title}"></span>
|
||
<span class="hot-info">
|
||
<h4>{$vo.title}</h4>
|
||
<p>{$vo.description |default='暂无描述'}</p>
|
||
{if $vo.rating_count > 0}<span class="website-rating">⭐ {$vo.rating} ({$vo.rating_count})</span>{/if}
|
||
</span>
|
||
</a>
|
||
<span class="qr-btn js-qr" data-url="{$vo.url}" title="二维码">▦</span>
|
||
</div>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
<!-- 广告位:首页底部 -->
|
||
{notempty name="ads.home_bottom"}
|
||
<div class="ad-box ad-home-bottom">
|
||
<span class="ad-label">广告</span>
|
||
{volist name="ads.home_bottom" id="ad"}
|
||
{if $ad.type == 1}
|
||
<a class="ad-item" href="/haonav/ad/click?id={$ad.id}" target="_blank" rel="nofollow">
|
||
<img src="{$ad.image}" alt="{$ad.title}" loading="lazy">
|
||
</a>
|
||
{else/}
|
||
{$ad.code|raw}
|
||
{/if}
|
||
{/volist}
|
||
</div>
|
||
{/notempty}
|
||
</div>
|
||
|
||
<!-- 底部 -->
|
||
<div class="footer">
|
||
<p>© 2026 网址导航 - 让上网更简单 | <a href="/haonav/apply.html">申请收录</a> | <a href="/haonav/apply.html">广告合作</a> | <a href="#" rel="nofollow">关于我们</a></p>
|
||
<p><a target="_blank" rel="nofollow" href="http://beian.miit.gov.cn/">{$siteConf.beian |default='蜀ICP备2022005627号-3'}</a></p>
|
||
</div>
|
||
|
||
<!-- 二维码弹层 -->
|
||
<div class="qr-mask" id="qrMask">
|
||
<div class="qr-box">
|
||
<img id="qrImg" src="" alt="二维码">
|
||
<p id="qrText"></p>
|
||
<span class="close">关闭</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 收藏夹分享弹层 -->
|
||
<div class="qr-mask" id="favShareMask">
|
||
<div class="qr-box" style="max-width:460px;text-align:left;">
|
||
<h3 style="margin:0 0 14px;">🔗 分享我的收藏夹</h3>
|
||
<label style="display:flex;align-items:center;gap:8px;font-size:14px;margin-bottom:12px;cursor:pointer;">
|
||
<input type="checkbox" id="favShareToggle"> 开启分享(关闭后链接立即失效)
|
||
</label>
|
||
<input type="text" id="favShareTitle" placeholder="分享页标题,如:我的常用网址" maxlength="100"
|
||
style="width:100%;padding:9px 12px;border:1px solid var(--nav-border,#ddd);border-radius:8px;font-size:14px;margin-bottom:12px;box-sizing:border-box;">
|
||
<div id="favShareLinkBox" style="display:none;">
|
||
<div style="display:flex;gap:8px;">
|
||
<input type="text" id="favShareLink" readonly
|
||
style="flex:1;padding:9px 12px;border:1px solid var(--nav-border,#ddd);border-radius:8px;font-size:13px;box-sizing:border-box;">
|
||
<button class="nav-btn nav-btn-primary" id="favShareCopy">复制</button>
|
||
</div>
|
||
<p style="font-size:12px;color:var(--nav-muted);margin:8px 0 0;">被访问 <b id="favShareViews">0</b> 次 · <a href="#" id="favShareReset">重置链接</a>(旧链接失效)</p>
|
||
</div>
|
||
<p id="favShareMsg" style="font-size:13px;color:var(--nav-muted);margin:12px 0 0;"></p>
|
||
<div style="text-align:right;margin-top:16px;"><span class="close" style="cursor:pointer;color:var(--nav-primary);">关闭</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 登录 / 注册 弹层由全局组件 auth.js 自动注入,无需在此书写 -->
|
||
|
||
<!-- 设为首页 / 收藏本站 提示弹层 -->
|
||
<div class="qr-mask" id="homeTipMask">
|
||
<div class="qr-box" style="max-width:440px;text-align:left;">
|
||
<h3 style="margin:0 0 12px;">📌 把导航带在身边</h3>
|
||
<p style="margin:0 0 8px;font-size:14px;"><b>收藏本站:</b>按 <kbd>Ctrl</kbd> + <kbd>D</kbd>(Mac:<kbd>⌘</kbd> + <kbd>D</kbd>)加入书签。</p>
|
||
<p style="margin:0 0 8px;font-size:14px;"><b>设为浏览器首页:</b></p>
|
||
<ol style="margin:0 0 8px;padding-left:20px;font-size:13px;line-height:1.8;color:var(--nav-muted,#666);">
|
||
<li>Chrome / Edge:设置 → 启动时 → 打开特定网页,填入本站地址</li>
|
||
<li>Firefox:设置 → 主页 → 自定义网址,填入本站地址</li>
|
||
</ol>
|
||
<p style="margin:0 0 4px;font-size:13px;color:var(--nav-muted,#666);">本站地址:<span id="homeTipUrl" style="user-select:all;"></span></p>
|
||
<span class="close">关闭</span>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="/static/haonav/js/nav-core.js"></script>
|
||
<script src="/static/haonav/js/nav-theme.js"></script>
|
||
<script src="/static/haonav/js/nav-festival.js"></script>
|
||
<script src="/static/haonav/js/nav-fav.js"></script>
|
||
<script src="/static/haonav/js/nav-search.js"></script>
|
||
<script src="/static/haonav/js/nav-widgets.js"></script>
|
||
<script src="/static/haonav/js/auth.js"></script>
|
||
</body>
|
||
|
||
</html>
|