打造专属首页:StarPay 首页模板开发教程

打造专属首页:StarPay 首页模板开发教程

适用版本:V2.0.0 及以上 | 适合人群:已部署StarPay并准备定制首页的开发者

StarPay 是一套可自行部署的聚合支付系统。除了系统自带的几套首页模板外,你完全可以 从零开发属于自己的首页模板 ——模板即一个普通文件夹,放进 public/web/home/ 目录、后台一键启用即可生效,无需改动任何 PHP 源码。本文将从机制原理讲起,手把手带你完成一个完整的自定义模板。

一、模板机制是怎么工作的?

首页的渲染链路非常简单,一共三步:

  1. 扫描 :系统会扫描 public/web/home/ 下所有「合法」的模板目录,展示在后台的「首页模板」列表中(每个模板的截图、名称、描述、版本都会展示出来)。
  2. 选择 :管理员在后台选中某个模板,系统会把模板目录名保存到配置项 home_temp 中。
  3. 渲染 :用户访问首页时,控制器读取 home_temp ,定位到 public/web/home/{模板目录}/index.html ,用 ThinkPHP 模板引擎渲染后输出给浏览器。
    所以对你(模板开发者)来说, 唯一要做的就是:创建一个模板目录,写好里面的文件 。系统会自动识别并允许用户在后台启用。

二、目录结构与必备文件

一个完整的首页模板目录结构如下:

public/web/home/
└── mytheme/                    # 模板目录名(建议小写英文,不要有空格和特殊符号)
    ├── index.html              # 首页模板文件(必填,ThinkPHP 模板语法)
    ├── style.css               # 样式文件(必填,且文件头部必须带主题元信息)
    ├── screenshot.png          # 后台列表展示的模板预览图(建议 800x600 左右)
    ├── js/                     # 可选:你的脚本目录
    │   └── main.js
    └── images/                 # 可选:模板用到的本地图片
        └── banner.png

三个要点:

  • 目录名就是模板的唯一标识 ,后台用它来定位模板,也用它作为配置值保存。
  • index.html 是渲染入口,使用 ThinkPHP 模板语法 (不是纯静态 HTML)。
  • style.css 是模板的“身份证”,系统只认带元信息的样式文件。

三、style.css 头部元信息(模板的“身份证”)

后台在扫描模板时,会读取 style.css 文件头部的注释 ,从中解析出三个字段: ThemeName (名称)、 Description (描述)、 Version (版本)。 三个字段缺一不可 ,否则该目录不会被识别为有效模板。

参考 aurora 模板的写法:

/*
ThemeName=MyTheme-我的主题
Description=这是我的第一个自定义首页模板
Version=V1.0.0
*/

解析规则说明:

字段含义说明
ThemeName模板名称后台列表里展示的名称,可中文
Description模板描述后台列表里的简介文字
Version版本号建议形如 V1.0.0

注意:元信息必须写在 CSS 文件 最开头的 /* */ 注释块内 ,一行一个字段,格式为 字段名=值 。写完之后,即使样式内容为空,模板也能被识别。

四、模板里可以使用的变量

这是开发的核心部分。系统在渲染 index.html 时会注入两类数据: 系统配置 和 首页数据数组 。

4.1 系统配置:getConfig()[‘xxx’]

在模板中通过 {:getConfig()[‘键名’]} 语法即可输出任意系统配置。最常用的几个键:

键名含义示例写法
sitename站点名称{:getConfig()['sitename']}
title站点副标题{:getConfig()['title']}
keySEO关键词<meta name="keywords" content="{:getConfig()['key']}">
desc站点描述<meta name="description" content="{:getConfig()['desc']}">
logo站点 Logo 地址<img src="{:getConfig()['logo']}">
favicon网站图标地址<link rel="icon" href="{:getConfig()['favicon']}">
index_popup首页弹窗 HTML 内容见下方示例
icp备案号页脚常见

这些配置全部由站长在后台「系统设置」里维护,你的模板会自动读取,无需写死。

4.2 首页数据数组:$index_array

控制器在渲染前会组装一个 $index_array 数组,里面包含导航、登录状态、公告三类数据。

① 顶部导航: $index_array[‘nav’]

数据来自「导航管理」表(状态为启用、按排序升序)。每条导航包含字段:

字段含义
name导航名称
url导航链接地址
is_target是否新窗口打开(1=新窗口)

在模板中循环输出:

{volist name="index_array.nav" id="vo"}
  <a {if condition="$vo.is_target == 1"} target="_blank" {/if} href="{$vo.url}">{$vo.name}</a>
{/volist}

② 登录状态: $index_array[‘is_login’]

值为 1 表示用户已登录, 0 表示未登录。可以用它来做「用户中心 / 登录注册」按钮的切换:

<?php if ($index_array['is_login'] == 1): ?>
  <a href="/User/Index">用户中心</a>
<?php else: ?>
  <a href="/User/Login">登录 / 注册</a>
<?php endif; ?>

③ 公告列表: $index_array[‘news1’] / news2 / news3

分别对应后台「公告管理」中类型为 1 / 2 / 3 的公告,每类最多 5 条。每条公告包含 title (标题)、 color (标题颜色)、 content (内容)、 create_time (发布时间)等字段。示例:
温馨提示:以上数据均以“导航、登录按钮”为最常见用法。公告栏属于可选项,模板里不展示公告也完全没问题。

{volist name="index_array.news1" id="vo"}
  <a href="javascript:;" style="color:{$vo.color}">{$vo.title}</a>
{/volist}

五、静态资源引用规则(重要!)

模板里引用自己目录下的 CSS/JS/图片时, 路径必须以 /web/home/{$resource}/ 开头 ,其中 {$resource} 就是当前模板的目录名(系统自动注入的变量)。

以 aurora 模板为例:

<link rel="stylesheet" href="/web/home/{$resource}/style.css">
<script src="/web/home/{$resource}/js/main.js"></script>
<img src="/web/home/{$resource}/images/banner.png">

为什么不能写死目录名? 两个原因:

  1. 模板目录名由用户上传时决定,可能会被改动(比如从 mytheme 改名成 my-theme-v2 );
  2. 将来模板被打包分发到其他站点时,目录名可能与开发时不一致。
    使用 {$resource} 动态拼接,无论目录叫什么,资源都能正确加载。

六、实战:从零开发一个极简模板

下面我们动手创建一个名为 mytheme 的完整模板,包含导航栏、登录按钮、Hero 区、页脚和公告栏。

第 1 步:创建目录与样式文件

在 public/web/home/ 下创建目录 mytheme/ ,然后创建 style.css :

/*
ThemeName=MyTheme-极简首页
Description=极简风格的首页模板,适合快速上线
Version=V1.0.0
*/

:root {
  --primary: #2563eb;
  --bg: #f6f8fc;
  --text: #0f172a;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
  background: var(--bg);
  color: var(--text);
}

.container { width: min(1200px, 92vw); margin: 0 auto; }

.site-header {
  background: #fff;
  border-bottom: 1px solid #e5e9f2;
  padding: 14px 0;
}

.nav { display: flex; align-items: center; justify-content: space-between; }

.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.brand-logo { height: 36px; }
.brand-text { font-size: 20px; font-weight: 700; }

.nav-links { display: flex; align-items: center; gap: 20px; }
.nav-links a { text-decoration: none; color: #475569; font-size: 14px; }
.nav-links a:hover { color: var(--primary); }

.btn { display: inline-block; padding: 10px 22px; border-radius: 8px; text-decoration: none; }
.btn-primary { background: var(--primary); color: #fff; }

.hero { padding: 80px 0; text-align: center; }
.hero h1 { font-size: 42px; margin-bottom: 16px; }
.hero p { color: #64748b; font-size: 16px; }

.news { margin: 40px 0; }
.news-card { background: #fff; border-radius: 12px; padding: 20px 24px; box-shadow: 0 2px 8px rgba(15, 23, 42, .06); }
.news-title { font-size: 18px; font-weight: 700; margin-bottom: 12px; }
.news-list li { list-style: none; padding: 8px 0; border-bottom: 1px dashed #eef1f6; }
.news-list a { color: #334155; text-decoration: none; font-size: 14px; }

.site-footer { background: #0f172a; color: #94a3b8; text-align: center; padding: 24px 0; font-size: 13px; margin-top: 60px; }
</style>

第 2 步:编写 index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{:getConfig()['sitename']} - {:getConfig()['title']}</title>
  <meta name="keywords" content="{:getConfig()['key']}">
  <meta name="description" content="{:getConfig()['desc']}">
  <link rel="icon" type="image/x-icon" href="{:getConfig()['favicon']}">
  <link rel="stylesheet" href="/web/home/{$resource}/style.css">
</head>
<body>

  <header class="site-header">
    <div class="container nav">
      <a href="/" class="brand">
        <img class="brand-logo" src="{:getConfig()['logo']}" alt="{:getConfig()['sitename']}">
        <span class="brand-text">{:getConfig()['sitename']}</span>
      </a>
      <nav class="nav-links">
        {volist name="index_array.nav" id="vo"}
          <a {if condition="$vo.is_target == 1"} target="_blank" {/if} href="{$vo.url}">{$vo.name}</a>
        {/volist}
        <?php if ($index_array['is_login'] == 1): ?>
          <a class="btn btn-primary" href="/User/Index">用户中心</a>
        <?php else: ?>
          <a class="btn btn-primary" href="/User/Login">登录 / 注册</a>
        <?php endif; ?>
      </nav>
    </div>
  </header>

  <main>
    <section class="hero">
      <div class="container">
        <h1>{:getConfig()['sitename']}</h1>
        <p>{:getConfig()['desc']}</p>
        <p style="margin-top:24px;">
          <a class="btn btn-primary" href="/User/Login">立即接入</a>
        </p>
      </div>
    </section>

    <section class="news">
      <div class="container news-card">
        <div class="news-title">系统公告</div>
        <ul class="news-list">
          {volist name="index_array.news1" id="vo"}
            <li><a href="javascript:;" style="color:{$vo.color}">{$vo.title}</a></li>
          {/volist}
        </ul>
      </div>
    </section>
  </main>

  <footer class="site-footer">
    <div class="container">© {:getConfig()['sitename']} 保留所有权利{notempty name="getConfig()['icp']"} | {:getConfig()['icp']}{/notempty}</div>
  </footer>

</body>
</html>

第 3 步:放一张预览图

在 mytheme/ 目录下放一张 screenshot.png 截图(可以先浏览器预览后截图,尺寸建议 800×600 以上),这样后台列表里就能看到模板的预览效果。

第 4 步:在后台启用

  1. 进入后台 → 首页模板 ;
  2. 列表中应能看到「MyTheme-极简首页」以及你上传的截图;
  3. 点击「设置」即可一键启用,访问前台首页立即生效。

七、补充说明:首页弹窗(可选功能)

系统提供「首页公告弹窗」能力,后台配置项 index_popup 里填写的 HTML 会在首页弹出展示。如果你想让模板支持这个功能,可以参考 aurora 模板的做法:用 {:getConfig()[‘index_popup’]} 渲染弹窗内容,配合 sessionStorage 实现“同一天只弹一次”。

核心片段:

<?php if (!empty(getConfig()['index_popup'])): ?>
  <div id="home-index-popup" style="display:none; ...">
    <div><?php echo getConfig()['index_popup']; ?></div>
  </div>
<?php endif; ?>

完整逻辑建议直接参考自带的 aurora 模板源码( public/web/home/aurora/index.html 底部),它已经处理好了空内容判断、会话去重、关闭按钮等细节,是最佳范例。

八、常见问题 FAQ

Q1:为什么后台看不到我创建的模板? 依次排查:① 目录必须放在 public/web/home/ 下;② 目录内必须有 style.css ;③ style.css 头部必须同时包含 ThemeName 、 Description 、 Version 三个字段;④ 如果开了 PHP OPcache/模板缓存,可稍等片刻或清一下缓存再看。

Q2:模板目录名能是中文吗? 不建议。目录名会写入数据库配置、参与 URL 拼装,建议只用小写英文字母、数字和下划线。

Q3: index.html 里能用完整的 PHP 吗? 只能用模板引擎支持的语法( {:函数()} 、 {$变量} 、 {volist} 、 {if} 等)以及少量内联 标签。凡是涉及数据查询的业务逻辑,都应交给系统控制器完成,模板里只负责展示系统注入好的变量。

Q4:删不掉我自己上传的模板怎么办? 后台「首页模板」列表里,系统内置的 default 、 old 、 aurora 三个模板受保护、不允许删除;其余模板可在后台直接删除,也可以手动删除对应的目录。

Q5:我的模板能分享/出售给别人吗? 可以。一个模板就是 public/web/home/{目录名}/ 下的一堆文件,把整个目录打包成 zip 发给别人,对方解压放到自己的 public/web/home/ 目录即可。如果接入应用商店体系, home-theme 类型的安装包也会被自动安装到 public/web/home/ 目录,实现一键分发。

九、小结

开发 StarPay 首页模板的本质,就是 写一个放在 public/web/home/{模板名}/ 下的目录 :

文件作用是否必填
index.html首页页面模板(ThinkPHP 模板语法)✅ 必填
style.css 样式文件,头部带 ThemeName/Description/Version 元信息✅ 必填
screenshot.png后台列表预览图✅ 建议
js/ 、 images/ 等模板配套资源,用 /web/home/{$resource}/ 引用可选

掌握了目录结构、元信息、注入变量、资源引用四个知识点,你就能开发出任何风格的首页模板。动手试试吧,期待看到你的作品!

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容