简介:苹果CMSv10首涂第30套模板是一套可深度DIY装修的视频站点主题,面向使用苹果CMS搭建影视/资源站的站长,无需改代码即可像装修淘宝店一样,对首页、栏目页、详情页、播放页进行模块化布局与配色调整,内置10多个模块并支持添加、修改、删除、排序,导航和图标按钮也能灵活配置。主题采用CSS3与H5特性编写,全部原创手写样式、未依赖框架,流式布局与移动端细节优化让页面加载更轻快,操作体验更顺滑。压缩包共141个文件,以html模板、php后端逻辑、css/js样式脚本为主,另有png/gif图标素材与woff/ttf字体文件,整体仅5.54MB,结构简洁便于二开。目前已有315人学习下载,适合想快速搭建个性化苹果CMS站点、又希望保留灵活装修能力的站长使用。
1. 苹果CMS v10首涂第30套DIY主题模板:先弄懂装修逻辑再动手
苹果CMS v10主题模板,能让你像给淘宝店铺装修一样调整整站页面,这句话不是广告,而是首涂第30套这包模板的默认能力。它没有把页面输出写死在HTML里,而是把首页、栏目页、详情页、播放页拆成独立模块,通过/template/shoutu30/admin/admin.php进入装修后台,添加、修改、删除、拖动模块后,前台模板按配置重新组装。对用苹果v10搭视频站的站长和PHP开发者来说,这等于把“找程序员改模板”变成“后台点两下”。新手不需要完全理解苹果CMS模板标签也能完成页面调整,熟手则能透过这套主题理解可视化装修背后的数据结构,属于一套能拿来做二开参考的实用模板素材。
2. 模板目录结构与页面装配原理
动手前,我先从目录结构判断它和普通苹果CMS主题的差异。这套主题的根目录是/template/shoutu30/,里面既放了前台CSS,也放了后台装修用的PHP和UI资源,说明它在设计上就是“前台渲染 + 后台管理”共用一套资源。搞清楚哪些文件被前台加载、哪些只服务后台,是避免后续页面样式错乱的第一步。
2.1 主题根目录下各文件该放在哪里
下载解包后,文件清单里至少能看到[点击查最新更新].bat、layui.css、style.css、ui.css、swiper.min.css、layer.css、demo.css、laydate.css、iconfont.css、code.css。实际安装时,主题文件会被放到苹果CMS的模板目录下,我习惯先按这个结构整理:
/template/shoutu30/ ├── index.html # 首页模板 ├── article.html # 详情页模板 ├── type.html # 栏目页模板 ├── play.html # 播放页模板 ├── css/ │ ├── style.css # 前台基础样式 │ ├── ui.css # UI组件样式 │ ├── iconfont.css # 图标字体样式 │ └── code.css # 代码高亮样式 ├── js/ │ ├── jquery.min.js │ ├── swiper.min.js # 轮播组件 │ └── common.js └── admin/ ├── admin.php # 装修后台入口 ├── layui.css ├── layer.css ├── laydate.css └── demo.css[点击查最新更新].bat是Windows下的更新说明脚本,看了里面的内容再动手。layui.css、layer.css、laydate.css、demo.css这组是后台管理界面用的,不要放进前台页面的公共头部。swiper.min.css和swiper.min.js配套加载,控制轮播样式和滑动行为。
注意:具体文件命名可能和打包习惯有关,但查找思路是一致的——先确认admin目录是否存在,再逐个打开前台.html模板,看它到底引用了哪些css/js文件。
2.2 模板引擎如何把模块配置变成HTML
苹果CMS v10基于PHP,模板文件里混着HTML和模板标签。例如详情页常见的标签是这种写法:
<div class="detail-title"> <h1>{$vod.name}</h1> <span>导演:{$vod.director}</span> </div>这里的{$vod.name}不是普通变量,而是模板引擎占位符,渲染时会被替换成当前影片的name字段。装修主题更进一步:它让“模块配置”也成为模板变量。后台保存的模块数组,大致长这样:
$modules = [ [ 'name' => 'banner', 'title' => '首页Banner', 'sort' => 1, 'config' => [ 'data_source' => 'type', 'data_id' => 1, 'show_num' => 5, ], ], ];前台模板遍历这个数组,把每个模块的HTML片段按sort顺序拼接。常见做法是在模板里写一个循环:
<?php if (!empty($modules)): ?> <?php foreach ($modules as $module): ?> <section class="widget-<?php echo $module['name']; ?>"> <?php if ($module['name'] == 'banner'): ?> <div class="banner-box"> <!-- 这里放轮播结构 --> </div> <?php elseif ($module['name'] == 'hot'): ?> <ul class="hot-list"> <!-- 这里放热播榜 --> </ul> <?php endif; ?> </section> <?php endforeach; ?> <?php endif; ?>这段循环需要一个$modules变量来源,要么由admin.php写入苹果CMS的配置表,要么写入独立的JSON文件。两种方式各有适用场景,我总结了区别:
| 存储方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 数据库配置表 | 修改即时生效,不用处理文件权限 | 每次保存多一条SQL,需要做缓存 | 线上环境,多人维护 |
| 独立JSON文件 | 方便备份和版本控制,定位问题简单 | 目录需要写权限,并发写可能丢数据 | 本地开发,单机部署 |
配置存数据库还是文件,直接影响你后续改排序的方式。数据库方案在后台“模块管理”里直接改数字即可,文件方案则要保证PHP进程有权限写theme_config.json,否则保存按钮会报500。
2.3 前台资源和后台UI资源必须分开加载
很多人第一次弄这个模板,会把layui.css误加到前台公共模板,结果首页、详情页全部变成layui风格,按钮和表单全变了。避免这个问题,要在index.html等前台模板里只引入下面这组:
<link rel="stylesheet" href="{$theme}style.css"> <link rel="stylesheet" href="{$theme}ui.css"> <link rel="stylesheet" href="{$theme}iconfont.css">style.css定基础样式,ui.css覆盖组件细节,iconfont.css提供图标字体,顺序不要互换。swiper.min.css只在有轮播的页面引入,code.css如果帖子或详情页里用到代码高亮再引入。
如何确认当前页面到底加载了哪些CSS?打开浏览器开发者工具,在Elements面板里看<head>区的<link>列表。如果出现layui.css,马上在模板代码里搜索“layui”,把它从前台公共模板移除,再清理一次苹果CMS缓存即可。
3. 后台装修实现:模块增删排序与导航按钮配置
这一章我会把装修后台的核心逻辑拆开。你不需要完全重写这套代码,但理解了数据结构和保存流程,遇到“模块保存后不见了”或者“排序没反应”时,能更快定位问题。
3.1 自定义菜单入口与权限校验
苹果CMS v10后台支持自定义菜单,可以把外链挂到左侧导航。首涂30套的管理入口是/template/shoutu30/admin/admin.php,你需要在苹果CMS后台的菜单管理里加上这条记录:
菜单名称:首涂30套装修 链接地址:/template/shoutu30/admin/admin.php路径要写站内相对路径,不要写http://开头的完整地址,否则后台会把它当成外部站点。保存后左侧菜单会出现“首涂30套装修”,点击进入装修后台。
这个PHP文件放在模板目录下,意味着知道路径的人都可以直接访问,所以文件顶部一定要有登录校验。常见做法是复用苹果CMS后台的会话,类似这样:
<?php session_start(); if (empty($_SESSION['admin_id']) && empty($_SESSION['admin_name'])) { exit('请先在苹果CMS后台登录后再访问'); } define('SHOUTU_ADMIN', true);这段代码先取后台登录时写入的会话字段,没登录直接退出。字段名admin_id和admin_name要和你本机实际打印出来的$_SESSION保持一致,如果后台登录后写的是user_id,这里就要跟着改。
3.2 模块添加、删除、排序的数据表设计
可视化装修的本质是把页面变成配置数据。我一般会给模块建一张独立的表,字段不复杂,重点在排序和状态:
CREATE TABLE `mac_shoutu_module` ( `id` int(11) NOT NULL AUTO_INCREMENT, `page` varchar(20) NOT NULL DEFAULT 'index', `module_name` varchar(30) NOT NULL, `module_type` varchar(30) NOT NULL, `module_config` text NOT NULL, `sort` int(11) NOT NULL DEFAULT 0, `status` tinyint(1) NOT NULL DEFAULT 1, PRIMARY KEY (`id`), KEY `idx_page_status_sort` (`page`,`status`,`sort`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;page字段区分首页、栏目页、详情页、播放页,module_type指的是模块类型,比如banner、hot、video_list。module_config存JSON字符串,保存时用json_encode写入,读取时用json_decode还原为数组。sort字段的值越小越靠前,status为0时该模块不渲染。
模块类型和常用参数的对应关系,我整理成了一张表:
| module_type | 用途 | 常用配置参数 |
|---|---|---|
| banner | 首页顶部轮播 | 数据来源、轮播数量、切换间隔 |
| hot | 热播榜 | 分类ID、排序字段、显示条数 |
| category | 分类入口 | 显示哪些分类、图标类名 |
| video_list | 视频列表 | 数据来源、每页条数、是否显示标题 |
拖拽排序保存时,前端会提交排序后的id数组,后台接收后按顺序更新sort值:
if (isset($_POST['sort_ids'])) { $sortList = array_map('intval', $_POST['sort_ids']); foreach ($sortList as $index => $id) { $db->exec("UPDATE mac_shoutu_module SET sort = {$index} WHERE id = {$id}"); } exit(json_encode(['code' => 1, 'msg' => '排序已保存'])); }这里array_map('intval', $_POST['sort_ids'])必须加,它能把数组里每个元素转成整数,防止把字符串拼进SQL造成注入。每个UPDATE单独执行虽然看起来不够高效,但模块数量一般不会超过几十条,实际性能可以接受。
3.3 导航和图标按钮的自定义逻辑
导航在装修后台里通常是一组可增删的重复项。保存的数据结构是标准数组:
$navItems = [ [ 'title' => '首页', 'link' => '/', 'target' => '_self', 'icon' => 'icon-shouye' ], [ 'title' => '电影', 'link' => '/index.php/vod/type/id/1.html', 'target' => '_self', 'icon' => 'icon-movie' ], ];前台渲染时输出固定HTML结构,图标和标题都由后台数据决定:
<a href="{$item.link}" target="{$item.target}"> <i class="iconfont {$item.icon}"></i> <span>{$item.title}</span> </a>这里的{$item.icon}会直接进入class属性,如果后台没有校验就保存了带引号的恶意字符串,页面很容易被插入额外标签。稳妥的做法是白名单过滤,只允许预设图标类名出现:
$allowedIcons = ['icon-shouye', 'icon-movie', 'icon-news', 'icon-live', 'icon-fenlei']; if (!in_array($icon, $allowedIcons, true)) { $icon = 'icon-shouye'; }白名单校验比strip_tags更可靠,因为图标本身就是从一个固定集合里选的,不需要允许任意值。
4. 流式布局与移动端适配的CSS3实现
首涂30套强调原创手写样式、未使用框架,这句话落在CSS上,意味着布局和断点全部要自己控制。真正写起来并不难,关键是掌握流式布局的几个核心断点,以及移动端点击、滚动的细节。
4.1 从固定宽到流式栅格
移动端适配的第一步,是容器宽度不再写死像素,而是用百分比配合断点。我一般用这种写法:
.container { width: 100%; padding: 0 15px; } @media (min-width: 768px) { .container { width: 720px; margin: 0 auto; } } @media (min-width: 992px) { .container { width: 960px; } } @media (min-width: 1200px) { .container { width: 1200px; } }默认手机端占满宽度,768px以上切换到固定宽度并居中,避免大屏上内容被拉得过宽。对应栅格列数也可以这样设置:
| 屏幕宽度 | 容器宽度 | 推荐栅格列数 | 适配对象 |
|---|---|---|---|
| 小于768px | 100% | 2列 | 手机 |
| 768px 到 991px | 720px | 3列 | 平板竖屏 |
| 992px 到 1199px | 960px | 4列 | 平板横屏、小笔记本 |
| 大于等于1200px | 1200px | 6列 | 桌面 |
列表区域用grid实现比较省事:
.module-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; } @media (min-width: 768px) { .module-list { grid-template-columns: repeat(4, 1fr); } } @media (min-width: 1200px) { .module-list { grid-template-columns: repeat(6, 1fr); } }repeat(2, 1fr)表示两等分,gap替代老的margin方案,间距不会因为某一列有浮动而被挤掉。流式布局不要用float加固定width拼列数,改用flex/grid后模块总数不够也不会出现最后一行错位。
4.2 移动端点击、滚动的细节处理
手机端打开苹果CMS页面,最常见的两个问题:点击卡片时出现灰色闪烁,列表滚动不跟手。CSS层面可以这样处理:
* { -webkit-tap-highlight-color: transparent; } body { -webkit-overflow-scrolling: touch; } .swiper-wrapper { transform: translateZ(0); backface-visibility: hidden; }tap-highlight-color去掉点击高亮,-webkit-overflow-scrolling让iOS上的滚动更接近原生手感,translateZ(0)触发GPU加速,让轮播滑动更顺。不过GPU加速不能滥用,所有元素都加反而会浪费内存。
轮播组件用的是swiper.min.js,初始化参数会直接影响体验:
new Swiper('.banner-swiper', { autoplay: { delay: 3000, disableOnInteraction: false }, loop: true, speed: 600, pagination: { el: '.banner-pagination', clickable: true } });disableOnInteraction: false表示用户手动滑动后不停下自动播放,loop: true要求至少三张图,图片只有一张时最好关掉循环。clickable: true允许点击分页小圆点跳转,这是移动端用户的习惯操作。
4.3 图片懒加载与缩略图尺寸
苹果CMS视频封面字段是{$vod.pic},原图可能很大,不优化会拖慢首屏。可以在图片标签上直接加原生懒加载属性:
<img src="{$vod.pic}" loading="lazy" class="lazy-img" alt="{$vod.name}">loading="lazy"是浏览器原生功能,不需要额外JS,滚动到可视区域才加载。CSS给图片一个占位底色,避免懒加载过程中出现大面积空白:
.lazy-img { width: 100%; height: auto; background: #f0f0f0; transition: opacity .3s; }如果封面是固定海报比例,强烈建议用aspect-ratio固定盒子高度,避免图片加载完成后把页面往下顶:
.poster-card { aspect-ratio: 2 / 3; object-fit: cover; }aspect-ratio比老旧的padding-top百分比方案直观,而且不会因为图片高度不统一出现模块错位。
5. 换皮与排错实战:样式失效、模块丢失与后台菜单不显示
这章我直接列出拿到首涂30套后最常见的几个坑,以及对应的排查指令。如果你已经装好模板但页面没有变化,从第一个问题开始查。
5.1 安装后页面没变化,先检查模板目录和缓存
苹果CMS后台的“系统”->“模板管理”里,默认模板必须切换成shoutu30。切换后如果前台还是旧样式,多半是缓存没清。清缓存不要只看后台按钮,还要去runtime/目录手工确认:
find runtime -type f -name "*.php" -delete这条命令只删PHP缓存文件,不动模板源文件。清理后再刷新前台,如果页面结构有变化但样式不对,继续看下面。
5.2 正文没有样式,检查是否错误引入了layui
页面能出内容但所有按钮、卡片都像被重置过,大概率是前台模板引入了后台UI样式。搜索整套模板里所有.html文件:
grep -r "layui" /template/shoutu30 --include="*.html"一旦发现输出里有layui.css或layer.css,把它们从前台模板的公共头部<link>中删掉,只保留style.css、ui.css、iconfont.css和必要的swiper.min.css。这组后台样式只给/template/shoutu30/admin/admin.php用。
5.3 模块排序保存后不生效,多半是缓存层在作怪
我在用这套主题时,把模块配置写进了数据库,前台读取后又套了一层Redis缓存。后台改完排序,前台还是旧顺序,就是因为没清Redis。排查命令:
redis-cli keys 'mac*' | head -20 redis-cli flushdbflushdb会清空当前库所有key,线上环境不要随便执行,最好先keys看看有哪些缓存,只删和mac_shoutu相关的:
redis-cli --scan --pattern '*shoutu*' | xargs -r redis-cli del删除后再刷新页面,排序就会按新sort值走。如果还是不对,打开浏览器开发者工具查看网络请求,确认模块配置接口返回的是新数据。
5.4 模块丢失时先检测JSON格式
模块配置如果存的是JSON文件,保存后突然丢失,多是把module_config写成了非法JSON。用PHP命令行验证最直接:
php -r "var_dump(json_decode(file_get_contents('theme_config.json'), true));"返回NULL说明JSON解析失败,回退到更早的格式化结构,注意中文双引号不要被编辑器自动替换成全角。修复后重新保存,再把文件权限调整为0644、目录调整为0755。
5.5 无限制版在本地部署时需要注意伪静态
这个包标注了无限制版,去掉域名校验后本地开发确实方便,但本地Nginx如果没配好伪静态,后台菜单链接可能打不开。确保站点伪静态规则允许/template/shoutu30/admin/admin.php这种路径被直接命中:
location ~ /template/.*\.php$ { include fastcgi_params; fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }这段配置可以放在server段里,让template目录下的PHP文件绕过普通前台路由规则。配好后重启Nginx,再访问后台装修入口,正常就能看到模块管理页。如果还是404,检查Nginx的location顺序,把带\.php$的规则放在catch-all规则之前。
本文还有配套的精品资源,点击获取