更新网站架构

This commit is contained in:
李志强 2026-03-09 16:35:17 +08:00
parent 4cbc52c51b
commit bf0daf987b
180 changed files with 60682 additions and 491 deletions

View File

@ -0,0 +1,227 @@
<?php
declare(strict_types=1);
namespace app\admin\controller\Cms\Domain;
use app\admin\BaseController;
use think\facade\Db;
use think\Request;
use app\model\System\SystemDomainPool;
/**
* 主域名池管理控制器
*/
class DomainPoolController extends BaseController
{
/**
* 获取域名池列表
*/
public function index(Request $request)
{
$page = $request->param('page', 1, 'int');
$pageSize = $request->param('pageSize', 10, 'int');
$mainDomain = $request->param('main_domain', '');
$status = $request->param('status', '');
$where = [['delete_time', '=', null]];
if ($mainDomain) {
$where[] = ['main_domain', 'like', "%$mainDomain%"];
}
if ($status !== '' && $status !== null) {
$where[] = ['status', '=', $status];
}
$list = SystemDomainPool::where($where)
->page($page, $pageSize)
->order('id', 'desc')
->select()
->toArray();
$total = SystemDomainPool::where($where)
->count();
return json([
'code' => 200,
'msg' => 'success',
'data' => [
'list' => $list,
'total' => $total
]
]);
}
/**
* 获取启用状态的主域名列表(供租户选择)
*/
public function getEnabledDomains()
{
$list = SystemDomainPool::where('status', 1)
->where('delete_time', null)
->select()
->toArray();
return json([
'code' => 200,
'msg' => 'success',
'data' => $list
]);
}
/**
* 创建主域名
*/
public function create(Request $request)
{
$mainDomain = $request->param('main_domain', '');
if (empty($mainDomain)) {
return json([
'code' => 400,
'msg' => '主域名不能为空'
]);
}
// 检查域名是否已存在
$exists = SystemDomainPool::where('main_domain', $mainDomain)
->where('delete_time', null)
->find();
if ($exists) {
return json([
'code' => 400,
'msg' => '该域名已存在'
]);
}
$now = date('Y-m-d H:i:s');
$id = SystemDomainPool::insertGetId([
'main_domain' => $mainDomain,
'status' => 1,
'create_time' => $now,
'update_time' => $now
]);
return json([
'code' => 200,
'msg' => '创建成功',
'data' => ['id' => $id]
]);
}
/**
* 编辑主域名
*/
public function update(Request $request)
{
$id = $request->param('id', 0, 'int');
$mainDomain = $request->param('main_domain', '');
$status = $request->param('status', null);
if ($id <= 0) {
return json([
'code' => 400,
'msg' => '参数错误'
]);
}
if (empty($mainDomain)) {
return json([
'code' => 400,
'msg' => '主域名不能为空'
]);
}
// 检查域名是否与其他记录重复
$exists = SystemDomainPool::where('main_domain', $mainDomain)
->where('id', '<>', $id)
->where('delete_time', null)
->find();
if ($exists) {
return json([
'code' => 400,
'msg' => '该域名已存在'
]);
}
$data = [
'main_domain' => $mainDomain,
'update_time' => date('Y-m-d H:i:s')
];
if ($status !== null) {
$data['status'] = $status;
}
SystemDomainPool::where('id', $id)->update($data);
return json([
'code' => 200,
'msg' => '更新成功'
]);
}
/**
* 删除主域名(软删除)
*/
public function delete($id)
{
if ($id <= 0) {
return json([
'code' => 400,
'msg' => '参数错误'
]);
}
SystemDomainPool::where('id', $id)
->update([
'delete_time' => date('Y-m-d H:i:s')
]);
return json([
'code' => 200,
'msg' => '删除成功'
]);
}
/**
* 切换主域名状态
*/
public function toggleStatus(Request $request)
{
$id = $request->param('id', 0, 'int');
if ($id <= 0) {
return json([
'code' => 400,
'msg' => '参数错误'
]);
}
$domain = SystemDomainPool::where('id', $id)
->find();
if (!$domain) {
return json([
'code' => 404,
'msg' => '域名不存在'
]);
}
$newStatus = $domain['status'] == 1 ? 0 : 1;
SystemDomainPool::where('id', $id)
->update([
'status' => $newStatus,
'update_time' => date('Y-m-d H:i:s')
]);
return json([
'code' => 200,
'msg' => '状态更新成功',
'data' => ['status' => $newStatus]
]);
}
}

View File

@ -0,0 +1,311 @@
<?php
declare(strict_types=1);
namespace app\admin\controller\Cms\Domain;
use app\admin\BaseController;
use think\facade\Db;
use think\Request;
use think\facade\Session;
/**
* 租户域名绑定控制器
*/
class TenantDomainController extends BaseController
{
/**
* 获取租户域名列表(管理员查看所有)
*/
public function index(Request $request)
{
$page = $request->param('page', 1, 'int');
$pageSize = $request->param('pageSize', 10, 'int');
$tenantId = $request->param('tenant_id', 0, 'int');
$status = $request->param('status', '');
$subDomain = $request->param('sub_domain', '');
$where = [['delete_time', '=', null]];
if ($tenantId > 0) {
$where[] = ['tenant_id', '=', $tenantId];
}
if ($status !== '' && $status !== null) {
$where[] = ['status', '=', $status];
}
if ($subDomain) {
$where[] = ['sub_domain', 'like', "%$subDomain%"];
}
$list = Db::name('mete_tenant_domain')
->where($where)
->page($page, $pageSize)
->order('id', 'desc')
->select()
->toArray();
$total = Db::name('mete_tenant_domain')
->where($where)
->count();
// 获取租户名称
$tenantIds = array_column($list, 'tenant_id');
$tenants = [];
if ($tenantIds) {
$tenantList = Db::name('mete_tenant')
->whereIn('id', $tenantIds)
->select()
->toArray();
$tenants = array_column($tenantList, null, 'id');
}
// 附加租户名称
foreach ($list as &$item) {
$item['tenant_name'] = $tenants[$item['tenant_id']]['tenant_name'] ?? '';
}
return json([
'code' => 200,
'msg' => 'success',
'data' => [
'list' => $list,
'total' => $total
]
]);
}
/**
* 获取当前租户的域名列表(租户端)
*/
public function myDomains(Request $request)
{
$tid = $request->param('tid', 0, 'int');
if ($tid <= 0) {
return json([
'code' => 400,
'msg' => '租户ID不能为空'
]);
}
$list = Db::name('mete_tenant_domain')
->where('tenant_id', $tid)
->where('delete_time', null)
->order('id', 'desc')
->select()
->toArray();
return json([
'code' => 200,
'msg' => 'success',
'data' => $list
]);
}
/**
* 租户申请二级域名
*/
public function apply(Request $request)
{
$tid = $request->param('tenant_id', 0, 'int');
$subDomain = $request->param('sub_domain', '');
$mainDomain = $request->param('main_domain', '');
if ($tid <= 0) {
return json([
'code' => 400,
'msg' => '租户ID不能为空'
]);
}
if (empty($subDomain)) {
return json([
'code' => 400,
'msg' => '二级域名前缀不能为空'
]);
}
if (empty($mainDomain)) {
return json([
'code' => 400,
'msg' => '请选择主域名'
]);
}
// 验证域名格式(只能包含字母、数字、连字符)
if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/', $subDomain)) {
return json([
'code' => 400,
'msg' => '二级域名前缀格式不正确'
]);
}
// 检查主域名是否存在且启用
$mainDomainInfo = Db::name('mete_system_domain_pool')
->where('main_domain', $mainDomain)
->where('status', 1)
->where('delete_time', null)
->find();
if (!$mainDomainInfo) {
return json([
'code' => 400,
'msg' => '主域名不存在或已禁用'
]);
}
// 检查二级域名是否已被使用
$exists = Db::name('mete_tenant_domain')
->where('sub_domain', $subDomain)
->where('main_domain', $mainDomain)
->where('delete_time', null)
->find();
if ($exists) {
return json([
'code' => 400,
'msg' => '该二级域名已被使用'
]);
}
$fullDomain = $subDomain . '.' . $mainDomain;
$now = date('Y-m-d H:i:s');
$id = Db::name('mete_tenant_domain')->insertGetId([
'tenant_id' => $tid,
'sub_domain' => $subDomain,
'main_domain' => $mainDomain,
'full_domain' => $fullDomain,
'status' => 0, // 审核中
'create_time' => $now,
'update_time' => $now
]);
return json([
'code' => 200,
'msg' => '申请提交成功,等待审核',
'data' => ['id' => $id]
]);
}
/**
* 审核租户域名(通过/拒绝)
*/
public function audit(Request $request)
{
$id = $request->param('id', 0, 'int');
$action = $request->param('action', ''); // 'approve' 或 'reject'
if ($id <= 0) {
return json([
'code' => 400,
'msg' => '参数错误'
]);
}
$domain = Db::name('mete_tenant_domain')
->where('id', $id)
->find();
if (!$domain) {
return json([
'code' => 404,
'msg' => '域名不存在'
]);
}
if ($domain['status'] != 0) {
return json([
'code' => 400,
'msg' => '该域名已审核过了'
]);
}
$newStatus = $action === 'approve' ? 1 : 2; // 1-已生效 2-已拒绝
Db::name('mete_tenant_domain')
->where('id', $id)
->update([
'status' => $newStatus,
'update_time' => date('Y-m-d H:i:s')
]);
$msg = $action === 'approve' ? '审核通过' : '已拒绝';
return json([
'code' => 200,
'msg' => $msg
]);
}
/**
* 禁用/启用租户域名
*/
public function toggleStatus(Request $request)
{
$id = $request->param('id', 0, 'int');
if ($id <= 0) {
return json([
'code' => 400,
'msg' => '参数错误'
]);
}
$domain = Db::name('mete_tenant_domain')
->where('id', $id)
->find();
if (!$domain) {
return json([
'code' => 404,
'msg' => '域名不存在'
]);
}
// 只有已生效的域名才能被禁用
if ($domain['status'] != 1) {
return json([
'code' => 400,
'msg' => '只有已生效的域名才能被禁用'
]);
}
// 切换为禁用状态
Db::name('mete_tenant_domain')
->where('id', $id)
->update([
'status' => 2,
'update_time' => date('Y-m-d H:i:s')
]);
return json([
'code' => 200,
'msg' => '已禁用'
]);
}
/**
* 删除租户域名(软删除)
*/
public function delete($id)
{
if ($id <= 0) {
return json([
'code' => 400,
'msg' => '参数错误'
]);
}
Db::name('mete_tenant_domain')
->where('id', $id)
->update([
'delete_time' => date('Y-m-d H:i:s')
]);
return json([
'code' => 200,
'msg' => '删除成功'
]);
}
}

View File

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace app\admin\controller; namespace app\admin\controller\Cms\Theme;
use app\admin\BaseController; use app\admin\BaseController;
use app\service\ThemeService; use app\service\ThemeService;
@ -20,14 +20,18 @@ class ThemeController extends BaseController
$this->themeService = new ThemeService(); $this->themeService = new ThemeService();
} }
/** /**
* 获取模板列表(后台管理) * 获取模板列表(后台管理)
* @return \think\response\Json * @return \think\response\Json
*/ */
public function index() public function index()
{ {
$tid = Request::get('tid', 0, 'int');
$themes = $this->themeService->getThemeList(); $themes = $this->themeService->getThemeList();
$currentTheme = $this->themeService->getCurrentTheme(); $currentTheme = $this->themeService->getCurrentTheme($tid);
return json([ return json([
'code' => 200, 'code' => 200,
@ -45,6 +49,7 @@ class ThemeController extends BaseController
*/ */
public function switch() public function switch()
{ {
$tid = Request::post('tid', 0, 'int');
$themeKey = Request::post('theme_key', ''); $themeKey = Request::post('theme_key', '');
if (empty($themeKey)) { if (empty($themeKey)) {
@ -54,7 +59,7 @@ class ThemeController extends BaseController
]); ]);
} }
$result = $this->themeService->switchTheme($themeKey); $result = $this->themeService->switchTheme($tid, $themeKey);
if ($result) { if ($result) {
return json([ return json([
@ -75,9 +80,10 @@ class ThemeController extends BaseController
*/ */
public function getData() public function getData()
{ {
$tid = Request::get('tid', 0, 'int');
$themeKey = Request::get('theme_key', ''); $themeKey = Request::get('theme_key', '');
$themeData = $this->themeService->getThemeData($themeKey ?: null); $themeData = $this->themeService->getThemeData($tid, $themeKey ?: null);
return json([ return json([
'code' => 200, 'code' => 200,
@ -92,6 +98,7 @@ class ThemeController extends BaseController
*/ */
public function saveData() public function saveData()
{ {
$tid = Request::post('tid', 0, 'int');
$themeKey = Request::post('theme_key', ''); $themeKey = Request::post('theme_key', '');
$fieldKey = Request::post('field_key', ''); $fieldKey = Request::post('field_key', '');
$fieldValue = Request::post('field_value', ''); $fieldValue = Request::post('field_value', '');
@ -103,7 +110,7 @@ class ThemeController extends BaseController
]); ]);
} }
$result = $this->themeService->saveThemeField($themeKey, $fieldKey, $fieldValue); $result = $this->themeService->saveThemeField($tid, $themeKey, $fieldKey, $fieldValue);
if ($result) { if ($result) {
return json([ return json([

View File

@ -13,6 +13,8 @@ use think\db\exception\DbException;
use think\Request; use think\Request;
use app\model\Tenant\Tenant; use app\model\Tenant\Tenant;
use app\model\AdminUser; use app\model\AdminUser;
use app\model\Template\TemplateSiteConfig;
use app\model\Template\TemplateSiteConfig;
class TenantController extends BaseController class TenantController extends BaseController
{ {
@ -64,6 +66,9 @@ class TenantController extends BaseController
$data = $this->request->post(); $data = $this->request->post();
$tenant = Tenant::create($data); $tenant = Tenant::create($data);
if ($tenant) { if ($tenant) {
// 创建租户默认数据
$this->createTenantDefaultData($tenant->id);
return json([ return json([
'code' => 200, 'code' => 200,
'msg' => '创建成功', 'msg' => '创建成功',
@ -76,6 +81,24 @@ class TenantController extends BaseController
]); ]);
} }
} }
/**
* 创建租户默认数据
* @param int $tenantId 租户ID
*/
private function createTenantDefaultData(int $tenantId)
{
$now = date('Y-m-d H:i:s');
// 创建租户默认模板配置
TemplateSiteConfig::create([
'tid' => $tenantId,
'key' => 'current_theme',
'value' => 'default',
'create_time' => $now,
'update_time' => $now
]);
}
/** /**
* 编辑租户 * 编辑租户

View File

@ -0,0 +1,22 @@
<?php
use think\facade\Route;
// 主域名池管理路由
Route::group('domain/pool', function () {
Route::get('index', 'app\admin\controller\Cms\Domain\DomainPoolController/index');
Route::get('getEnabledDomains', 'app\admin\controller\Cms\Domain\DomainPoolController/getEnabledDomains');
Route::post('create', 'app\admin\controller\Cms\Domain\DomainPoolController/create');
Route::post('update', 'app\admin\controller\Cms\Domain\DomainPoolController/update');
Route::delete('delete/:id', 'app\admin\controller\Cms\Domain\DomainPoolController/delete');
Route::post('toggleStatus', 'app\admin\controller\Cms\Domain\DomainPoolController/toggleStatus');
});
// 租户域名绑定路由
Route::group('domain/tenant', function () {
Route::get('index', 'app\admin\controller\Cms\Domain\TenantDomainController/index');
Route::get('myDomains', 'app\admin\controller\Cms\Domain\TenantDomainController/myDomains');
Route::post('apply', 'app\admin\controller\Cms\Domain\TenantDomainController/apply');
Route::post('audit', 'app\admin\controller\Cms\Domain\TenantDomainController/audit');
Route::post('toggleStatus', 'app\admin\controller\Cms\Domain\TenantDomainController/toggleStatus');
Route::delete('delete/:id', 'app\admin\controller\Cms\Domain\TenantDomainController/delete');
});

View File

@ -2,7 +2,7 @@
use think\facade\Route; use think\facade\Route;
// 模板管理路由 // 模板管理路由
Route::get('theme', 'app\admin\controller\ThemeController@index'); Route::get('theme', 'app\admin\controller\Cms\Theme\ThemeController@index');
Route::post('theme/switch', 'app\admin\controller\ThemeController@switch'); Route::post('theme/switch', 'app\admin\controller\Cms\Theme\ThemeController@switch');
Route::get('theme/data', 'app\admin\controller\ThemeController@getData'); Route::get('theme/data', 'app\admin\controller\Cms\Theme\ThemeController@getData');
Route::post('theme/data', 'app\admin\controller\ThemeController@saveData'); Route::post('theme/data', 'app\admin\controller\Cms\Theme\ThemeController@saveData');

View File

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
namespace app\common\middleware;
use think\facade\Db;
use think\Request;
/**
* 域名解析中间件
* 通过访问域名自动识别租户
*/
class DomainParse
{
public function handle(Request $request, \Closure $next)
{
$host = $request->host(true); // 获取完整域名,不带端口
// 排除后台域名和平台官网域名
$adminDomains = ['admin.xxx.com']; // TODO: 配置后台域名
$platformDomains = ['www.xxx.com', 'xxx.com']; // TODO: 配置平台官网域名
if (in_array($host, $adminDomains) || in_array($host, $platformDomains)) {
return $next($request);
}
// 解析二级域名
$domainParts = explode('.', $host);
// 至少需要三级域名(如 sub.domain.com
if (count($domainParts) < 3) {
return $next($request);
}
$subDomain = $domainParts[0];
$mainDomain = implode('.', array_slice($domainParts, 1));
// 查询租户域名绑定记录
$tenantDomain = Db::name('mete_tenant_domain')
->where('full_domain', $host)
->where('status', 1) // 只有已生效的域名才能访问
->where('delete_time', null)
->find();
if ($tenantDomain) {
// 将租户ID写入请求对象供后续控制器使用
$request->tenantId = $tenantDomain['tenant_id'];
// 同时写入header方便前端获取
$request->header['X-Tenant-Id', $tenantDomain['tenant_id']);
}
return $next($request);
}
}

View File

@ -12,6 +12,8 @@ use app\model\System\SystemSiteSettings;
use app\service\ThemeService; use app\service\ThemeService;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\facade\Env; use think\facade\Env;
use think\facade\Request;
use app\model\Template\TemplateSiteConfig;
class Index extends BaseController class Index extends BaseController
{ {
@ -33,16 +35,34 @@ class Index extends BaseController
*/ */
public function init() public function init()
{ {
// 直接返回默认模板数据 // 获取租户ID从请求参数
$tid = Request::param('tid', 0, 'int');
// 从TemplateSiteConfig获取配置根据租户ID
$config = null;
if ($tid > 0) {
$config = TemplateSiteConfig::where('tid', $tid)
->where('key', 'current_theme')
->find();
}
$themeKey = $config['value'] ?? 'default';
// 模板路径:/themes/{theme_key}/优先使用index.php其次index.html
$themeBasePath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $themeKey;
if (is_file($themeBasePath . DIRECTORY_SEPARATOR . 'index.php')) {
$themePath = '/themes/' . $themeKey . '/index.php';
} else {
$themePath = '/themes/' . $themeKey . '/index.html';
}
return json([ return json([
'code' => 200, 'code' => 200,
'msg' => 'success', 'msg' => 'success',
'data' => [ 'data' => [
'theme_key' => 'default', 'theme_key' => $themeKey,
'theme_path' => '/themes/default/index.html', 'theme_path' => $themePath
'data' => [
'site_name' => '企业官网'
]
] ]
]); ]);
} }

View File

@ -1,5 +1,6 @@
<?php <?php
return [ return [
\app\common\middleware\AllowCrossDomain::class, \app\common\middleware\AllowCrossDomain::class,
\app\common\middleware\DomainParse::class,
\think\middleware\SessionInit::class, \think\middleware\SessionInit::class,
]; ];

View File

@ -0,0 +1,37 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app\model\System;
use think\Model;
use think\model\concern\SoftDelete;
/**
* 系统域名池模型
*/
class SystemDomainPool extends Model
{
// 数据库表名
protected $name = 'mete_system_domain_pool';
// 字段类型转换
protected $type = [
'id' => 'integer',
'main_domain' => 'string',
'status' => 'integer',
'create_time' => 'datetime',
'update_time' => 'datetime',
'delete_time' => 'datetime',
];
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace app\model\Template;
use think\Model;
use think\model\concern\SoftDelete;
class TemplateSiteConfig extends Model
{
use SoftDelete;
protected $name = 'mete_template_site_config';
protected $type = [
'id' => 'integer',
'tid' => 'integer',
'key' => 'string',
'value' => 'string',
'create_time' => 'datetime',
'update_time' => 'datetime',
'delete_time' => 'datetime',
];
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace app\model\Template;
use think\Model;
use think\model\concern\SoftDelete;
class TemplateThemeData extends Model
{
use SoftDelete;
protected $name = 'mete_template_theme_data';
protected $type = [
'id' => 'integer',
'theme_key' => 'string',
'field_key' => 'string',
'field_value' => 'string',
'create_time' => 'datetime',
'update_time' => 'datetime',
'delete_time' => 'datetime',
];
}

View File

@ -0,0 +1,36 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app\model\Tenant;
use think\Model;
/**
* 租户域名模型
*/
class TenantDomain extends Model
{
// 数据库表名
protected $name = 'mete_tenant_domain';
// 字段类型转换
protected $type = [
'id' => 'integer',
'tenant_id' => 'integer',
'sub_domain' => 'string',
'main_domain' => 'string',
'full_domain' => 'string',
'status' => 'integer',
'create_time' => 'datetime',
'update_time' => 'datetime',
'delete_time' => 'datetime',
];
}

View File

@ -67,7 +67,8 @@ class ThemeService
} }
$fullPath = $this->themesPath . DIRECTORY_SEPARATOR . $item; $fullPath = $this->themesPath . DIRECTORY_SEPARATOR . $item;
if (is_dir($fullPath) && is_file($fullPath . DIRECTORY_SEPARATOR . 'index.html')) { // 检查是否有 index.html 或 index.php
if (is_dir($fullPath) && (is_file($fullPath . DIRECTORY_SEPARATOR . 'index.html') || is_file($fullPath . DIRECTORY_SEPARATOR . 'index.php'))) {
$dirs[] = $item; $dirs[] = $item;
} }
} }
@ -114,14 +115,18 @@ class ThemeService
/** /**
* 获取当前激活的模板Key * 获取当前激活的模板Key
* @param int $tid 租户ID
* @return string * @return string
*/ */
public function getCurrentTheme(): string public function getCurrentTheme(int $tid = 0): string
{ {
try { try {
$where = [['key', '=', 'current_theme'], ['delete_time', '=', null]];
if ($tid > 0) {
$where[] = ['tid', '=', $tid];
}
$config = Db::name('mete_template_site_config') $config = Db::name('mete_template_site_config')
->where('key', 'current_theme') ->where($where)
->where('delete_time', null)
->find(); ->find();
return $config['value'] ?? 'default'; return $config['value'] ?? 'default';
} catch (\Exception $e) { } catch (\Exception $e) {
@ -131,10 +136,11 @@ class ThemeService
/** /**
* 切换当前模板 * 切换当前模板
* @param int $tid 租户ID
* @param string $themeKey * @param string $themeKey
* @return bool * @return bool
*/ */
public function switchTheme(string $themeKey): bool public function switchTheme(int $tid, string $themeKey): bool
{ {
// 验证模板是否存在 // 验证模板是否存在
$themes = $this->getThemeList(); $themes = $this->getThemeList();
@ -152,9 +158,12 @@ class ThemeService
try { try {
// 查找或创建配置记录 // 查找或创建配置记录
$where = [['key', '=', 'current_theme'], ['delete_time', '=', null]];
if ($tid > 0) {
$where[] = ['tid', '=', $tid];
}
$config = Db::name('mete_template_site_config') $config = Db::name('mete_template_site_config')
->where('key', 'current_theme') ->where($where)
->where('delete_time', null)
->find(); ->find();
$now = date('Y-m-d H:i:s'); $now = date('Y-m-d H:i:s');
@ -181,17 +190,21 @@ class ThemeService
/** /**
* 获取模板数据(用于前端渲染) * 获取模板数据(用于前端渲染)
* @param int $tid 租户ID
* @param string|null $themeKey * @param string|null $themeKey
* @return array * @return array
*/ */
public function getThemeData(?string $themeKey = null): array public function getThemeData(int $tid = 0, ?string $themeKey = null): array
{ {
$themeKey = $themeKey ?? $this->getCurrentTheme(); $themeKey = $themeKey ?? $this->getCurrentTheme($tid);
try { try {
$where = [['theme_key', '=', $themeKey], ['delete_time', '=', null]];
if ($tid > 0) {
$where[] = ['tid', '=', $tid];
}
$themeData = Db::name('mete_template_theme_data') $themeData = Db::name('mete_template_theme_data')
->where('theme_key', $themeKey) ->where($where)
->where('delete_time', null)
->select() ->select()
->toArray(); ->toArray();
@ -216,18 +229,25 @@ class ThemeService
/** /**
* 保存模板字段数据 * 保存模板字段数据
* @param int $tid 租户ID
* @param string $themeKey * @param string $themeKey
* @param string $fieldKey * @param string $fieldKey
* @param mixed $fieldValue * @param mixed $fieldValue
* @return bool * @return bool
*/ */
public function saveThemeField(string $themeKey, string $fieldKey, $fieldValue): bool public function saveThemeField(int $tid, string $themeKey, string $fieldKey, $fieldValue): bool
{ {
try { try {
$where = [
['theme_key', '=', $themeKey],
['field_key', '=', $fieldKey],
['delete_time', '=', null]
];
if ($tid > 0) {
$where[] = ['tid', '=', $tid];
}
$existing = Db::name('mete_template_theme_data') $existing = Db::name('mete_template_theme_data')
->where('theme_key', $themeKey) ->where($where)
->where('field_key', $fieldKey)
->where('delete_time', null)
->find(); ->find();
$value = is_array($fieldValue) ? json_encode($fieldValue, JSON_UNESCAPED_UNICODE) : $fieldValue; $value = is_array($fieldValue) ? json_encode($fieldValue, JSON_UNESCAPED_UNICODE) : $fieldValue;
@ -242,6 +262,7 @@ class ThemeService
]); ]);
} else { } else {
Db::name('mete_template_theme_data')->insert([ Db::name('mete_template_theme_data')->insert([
'tid' => $tid,
'theme_key' => $themeKey, 'theme_key' => $themeKey,
'field_key' => $fieldKey, 'field_key' => $fieldKey,
'field_value' => $value, 'field_value' => $value,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
.tns-outer{padding:0 !important}.tns-outer [hidden]{display:none !important}.tns-outer [aria-controls],.tns-outer [data-action]{cursor:pointer}.tns-slider{-webkit-transition:all 0s;-moz-transition:all 0s;transition:all 0s}.tns-slider>.tns-item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.tns-horizontal.tns-subpixel{white-space:nowrap}.tns-horizontal.tns-subpixel>.tns-item{display:inline-block;vertical-align:top;white-space:normal}.tns-horizontal.tns-no-subpixel:after{content:'';display:table;clear:both}.tns-horizontal.tns-no-subpixel>.tns-item{float:left}.tns-horizontal.tns-carousel.tns-no-subpixel>.tns-item{margin-right:-100%}.tns-no-calc{position:relative;left:0}.tns-gallery{position:relative;left:0;min-height:1px}.tns-gallery>.tns-item{position:absolute;left:-100%;-webkit-transition:transform 0s, opacity 0s;-moz-transition:transform 0s, opacity 0s;transition:transform 0s, opacity 0s}.tns-gallery>.tns-slide-active{position:relative;left:auto !important}.tns-gallery>.tns-moving{-webkit-transition:all 0.25s;-moz-transition:all 0.25s;transition:all 0.25s}.tns-autowidth{display:inline-block}.tns-lazy-img{-webkit-transition:opacity 0.6s;-moz-transition:opacity 0.6s;transition:opacity 0.6s;opacity:0.6}.tns-lazy-img.tns-complete{opacity:1}.tns-ah{-webkit-transition:height 0s;-moz-transition:height 0s;transition:height 0s}.tns-ovh{overflow:hidden}.tns-visually-hidden{position:absolute;left:-10000em}.tns-transparent{opacity:0;visibility:hidden}.tns-fadeIn{opacity:1;filter:alpha(opacity=100);z-index:0}.tns-normal,.tns-fadeOut{opacity:0;filter:alpha(opacity=0);z-index:-1}.tns-vpfix{white-space:nowrap}.tns-vpfix>div,.tns-vpfix>li{display:inline-block}.tns-t-subp2{margin:0 auto;width:310px;position:relative;height:10px;overflow:hidden}.tns-t-ct{width:2333.3333333%;width:-webkit-calc(100% * 70 / 3);width:-moz-calc(100% * 70 / 3);width:calc(100% * 70 / 3);position:absolute;right:0}.tns-t-ct:after{content:'';display:table;clear:both}.tns-t-ct>div{width:1.4285714%;width:-webkit-calc(100% / 70);width:-moz-calc(100% / 70);width:calc(100% / 70);height:10px;float:left}
/*# sourceMappingURL=sourcemaps/tiny-slider.css.map */

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 596 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1 @@
<svg fill="none" height="44" viewBox="0 0 45 44" width="45" xmlns="http://www.w3.org/2000/svg"><g fill="#0067f4"><path d="m28.9548 22.4531v-.8684c0-6.4427-2.106-12.74067-6.0912-18.20787-.2052-.27872-.5292-.44488-.8748-.44488s-.6696.16616-.8748.44488c-3.9852 5.4672-6.0912 11.76517-6.0912 18.20787v.8684c-4.9356 2.7068-5.65384 9.0423-5.68084 9.3264-.0324.3001.0702.6003.27.8254.2052.2251.49684.3538.79924.3538h23.139c.3078 0 .5994-.1287.7992-.3538.2052-.2251.3024-.5253.27-.8254-.0162-.2841-.729-6.6196-5.6646-9.3264zm-13.932 2.5835v5.7781h-3.3102c.3618-1.5008 1.2474-4.1004 3.3102-5.7781zm2.16-3.4519c0-5.4993 1.6578-10.8915 4.806-15.68331 3.1482 4.79181 4.806 10.18401 4.806 15.68331v9.23h-9.612zm11.772 9.23v-5.7781c2.052 1.6777 2.9484 4.2773 3.3102 5.7781z"/><path d="m23.112 15.0294h-2.7378c-.594 0-1.08.4824-1.08 1.072s.486 1.072 1.08 1.072h2.7378c.594 0 1.08-.4824 1.08-1.072s-.4806-1.072-1.08-1.072z"/><path d="m18.2088 35.3975c-.594 0-1.08.4824-1.08 1.072v6.0943c0 .5896.486 1.072 1.08 1.072s1.08-.4824 1.08-1.072v-6.0943c0-.5896-.486-1.072-1.08-1.072z"/><path d="m21.9888 35.3975c-.594 0-1.08.4824-1.08 1.072v6.0943c0 .5896.486 1.072 1.08 1.072s1.08-.4824 1.08-1.072v-6.0943c0-.5896-.486-1.072-1.08-1.072z"/><path d="m25.7688 35.3975c-.594 0-1.08.4824-1.08 1.072v6.0943c0 .5896.486 1.072 1.08 1.072s1.08-.4824 1.08-1.072v-6.0943c0-.5896-.4806-1.072-1.08-1.072z"/><path d="m6.4476 16.8733h-1.6038v-1.5919c0-.5896-.486-1.072-1.08-1.072s-1.08.4824-1.08 1.072v1.5919h-1.6038c-.594 0-1.08.4824-1.08 1.072s.486 1.072 1.08 1.072h1.6038v1.5919c0 .5896.486 1.072 1.08 1.072s1.08-.4824 1.08-1.072v-1.5919h1.6038c.594 0 1.08-.4824 1.08-1.072s-.4806-1.072-1.08-1.072z"/><path d="m28.3824 3.92888h.7182v.71288c0 .5896.486 1.072 1.08 1.072s1.08-.4824 1.08-1.072v-.71288h.7182c.594 0 1.08-.4824 1.08-1.072s-.486-1.072-1.08-1.072h-.7182v-.71288c0-.5896-.486-1.072-1.08-1.072s-1.08.4824-1.08 1.072v.71288h-.7182c-.594 0-1.08.4824-1.08 1.072s.4806 1.072 1.08 1.072z"/><path d="m43.1676 10.3073h-2.7432v-2.72291c0-.5896-.486-1.072-1.08-1.072s-1.08.4824-1.08 1.072v2.72291h-2.7432c-.594 0-1.08.4824-1.08 1.072s.486 1.072 1.08 1.072h2.7432v2.7229c0 .5896.486 1.072 1.08 1.072s1.08-.4824 1.08-1.072v-2.7229h2.7432c.594 0 1.08-.4824 1.08-1.072s-.486-1.072-1.08-1.072z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1 @@
<svg fill="none" height="767" viewBox="0 0 1440 767" width="1440" xmlns="http://www.w3.org/2000/svg"><path d="m-14.8936 273.223c3.6985-23.916 20.64073-43.806 39.6425-58.829 52.1994-41.35 125.4821-54.514 188.8431-33.939 63.362 20.576 126.106 43.663 143.978 107.78 6.113 21.881 8.527 44.758 16.167 66.152 20.043 56.063 78.466 96.02 138.04 94.405 76.273-2.058 128.14-59.891 191.368-93.277 45.844-24.204 114.163-1.515 139.233 56.119 22.523 51.749-14.13 106.529-25.956 156.132-12.114 50.842 7.818 101.153 49.232 133.123 41.746 32.257 105.13 48.452 156.846 35.797 50.03-12.235 84.13-49.846 122.07-81.861 49.16-41.483 127.43-43.319 187.69-35.443 28.79 3.761 58.22 9.823 86.53 3.407 49.23-11.15 57.18-52.412 57.67-95.776.68-60.09.02-120.202-1.11-180.27-2.24-118.233-6.42-236.444-6.42-354.72131h-1483.8014v281.20131z" fill="#ebf4ff"/><path d="m1524.87 305.304c-22.19 75.665-103.56 116.861-179.92 136.795-49.59 12.943-101.32 20.687-152.17 14.16s-100.97-28.518-134.41-67.325c-29.47-34.204-44.4-79.028-74.01-113.122-41.481-47.811-107.788-68.674-171.105-67.435s-124.552 22.102-183.13 46.151c-33.84 13.895-68.61 29.227-105.196 28.143-43.252-1.284-82.562-25.488-115.317-53.741-32.755-28.23-61.457-61.306-96.847-86.174-96.78-68.055-240.0465-60.0459-328.6549 18.341v-169.09706h1511.8599z" fill="#2f80ed" opacity=".3"/><path d="m623.282 521.593c2.635 9.624 7.264 18.938 13.088 27.169 23.587 33.363 62.144 64.094 105.174 47.412 32.777-12.699 57.183-48.872 70.869-79.891 10.343-23.43 11.561-49.514-2.103-72.059-23.299-38.452-72.375-43.276-109.958-24.713-25.004 12.345-50.428 31.77-68.212 53.342-11.914 14.491-13.398 32.08-8.858 48.74z" fill="#ebf4ff"/><g fill="#2f80ed"><path d="m1234.25 386.58c0-4.47-3.08-7.545-7.55-7.545 4.47 0 7.55-3.075 7.55-7.544 0 4.469 3.08 7.544 7.55 7.544-4.47 0-7.55 3.075-7.55 7.545z"/><path d="m1286.11 440.453c0-4.469-3.07-7.545-7.55-7.545 4.48 0 7.55-3.075 7.55-7.544 0 4.469 3.08 7.544 7.56 7.544-4.45 0-7.56 3.076-7.56 7.545z"/><path d="m1313.64 305.073c0-4.469-3.08-7.544-7.55-7.544 4.47 0 7.55-3.075 7.55-7.545 0 4.47 3.08 7.545 7.55 7.545-4.47 0-7.55 3.075-7.55 7.544z"/><path d="m1101.55 354.875c0-4.469-3.08-7.544-7.56-7.544 4.48 0 7.56-3.075 7.56-7.544 0 4.469 3.07 7.544 7.55 7.544-4.48 0-7.55 3.097-7.55 7.544z"/><path d="m1180.63 270.537c0-4.469-3.08-7.544-7.55-7.544 4.47 0 7.55-3.076 7.55-7.545 0 4.469 3.08 7.545 7.55 7.545-4.47 0-7.55 3.097-7.55 7.544z"/><path d="m1135.52 318.791c0-7.987-5.52-13.496-13.51-13.496 7.99 0 13.51-5.509 13.51-13.496 0 7.987 5.51 13.496 13.51 13.496-7.98 0-13.51 5.509-13.51 13.496z"/><path d="m1250.61 297.529c0-7.987-5.51-13.496-13.51-13.496 8 0 13.51-5.509 13.51-13.496 0 7.987 5.52 13.496 13.51 13.496-7.97 0-13.51 5.509-13.51 13.496z"/><path d="m1293.67 365.252c0-6.128-4.26-10.376-10.39-10.376 6.16 0 10.39-4.248 10.39-10.377 0 6.151 4.25 10.377 10.38 10.377-6.13 0-10.38 4.248-10.38 10.376z"/><path d="m1200.78 324.985c0-5.31-3.67-8.96-8.97-8.96 5.32 0 8.97-3.651 8.97-8.96 0 5.309 3.66 8.96 8.97 8.96-5.29-.022-8.97 3.65-8.97 8.96z"/><path d="m859.646 718.325c0-4.004 2.769-6.77 6.777-6.77-4.008 0-6.777-2.765-6.777-6.77 0 4.005-2.768 6.77-6.777 6.77 4.009 0 6.777 2.766 6.777 6.77z"/><path d="m813.05 766.711c0-4.004 2.768-6.77 6.777-6.77-4.009 0-6.777-2.765-6.777-6.77 0 4.005-2.768 6.77-6.777 6.77 4.009 0 6.777 2.766 6.777 6.77z"/><path d="m788.334 645.116c0-4.005 2.769-6.77 6.777-6.77-4.008 0-6.777-2.766-6.777-6.77 0 4.004-2.768 6.77-6.776 6.77 4.008 0 6.776 2.765 6.776 6.77z"/><path d="m978.861 689.852c0-4.005 2.769-6.771 6.777-6.771-4.008 0-6.777-2.765-6.777-6.77 0 4.005-2.768 6.77-6.776 6.77 4.008 0 6.776 2.766 6.776 6.771z"/><path d="m907.837 614.097c0-4.004 2.769-6.77 6.777-6.77-4.008 0-6.777-2.765-6.777-6.77 0 4.005-2.768 6.77-6.777 6.77 4.009 0 6.777 2.766 6.777 6.77z"/><path d="m948.344 657.438c0-7.168 4.96-12.124 12.136-12.124-7.176 0-12.136-4.956-12.136-12.124 0 7.168-4.961 12.124-12.137 12.124 7.176 0 12.137 4.956 12.137 12.124z"/><path d="m844.941 638.346c0-7.169 4.961-12.124 12.137-12.124-7.176 0-12.137-4.956-12.137-12.125 0 7.169-4.961 12.125-12.136 12.125 7.175 0 12.136 4.955 12.136 12.124z"/><path d="m806.273 699.188c0-5.509 3.809-9.315 9.324-9.315-5.515 0-9.324-3.805-9.324-9.314 0 5.509-3.809 9.314-9.346 9.314 5.537-.022 9.346 3.806 9.346 9.315z"/><path d="m889.699 662.992c0-4.757 3.3-8.054 8.062-8.054-4.762 0-8.062-3.296-8.062-8.053 0 4.757-3.299 8.053-8.061 8.053 4.784 0 8.061 3.297 8.061 8.054z"/></g></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1 @@
<svg fill="none" height="43" viewBox="0 0 173 43" width="173" xmlns="http://www.w3.org/2000/svg"><g fill="#2f80ed"><path d="m63.375 37.6-21.6-36c-.5-1.1-1.6-1.6-2.9-1.6-1.1 0-2.1.5-2.9 1.6l-9.3 16.3-4.5-7.2c-.5-1.1-1.6-1.6-2.9-1.6-1.1 0-2.1.5-2.9 1.6l-16 26.9c-.5 1.1-.5 2.4 0 3.5.8 1.1 1.9 1.6 3.2 1.6h57.1c1.3 0 2.4-.5 2.9-1.6.3-1.1.3-2.5-.2-3.5zm-56.8-.3 12.5-21.1 4.5 7.5c.5 1.1 1.6 1.6 2.9 1.6 1.1 0 2.4-.5 2.9-1.6l9.6-16.3 18 29.9z"/><path d="m79.339 14.558-2.646-4.94899h-.196l.49 4.94899v22.442h-3.822v-34.83899h2.156l16.415 22.88299 2.548 4.704h.245l-.539-4.704v-22.34399h3.822v34.83899h-2.156z"/><path d="m104.371 24.75c0-4.1487.914-7.3173 2.744-9.506 1.862-2.2213 4.524-3.332 7.987-3.332 1.829 0 3.413.3103 4.753.931 1.372.588 2.499 1.4537 3.381 2.597.882 1.1107 1.535 2.4663 1.96 4.067.424 1.568.637 3.3157.637 5.243 0 4.1487-.931 7.3337-2.793 9.555-1.83 2.1887-4.476 3.283-7.938 3.283-1.83 0-3.43-.294-4.802-.882-1.34-.6207-2.45-1.4863-3.332-2.597-.882-1.1433-1.536-2.499-1.96-4.067-.425-1.6007-.637-3.3647-.637-5.292zm4.067 0c0 1.2413.114 2.4337.343 3.577.261 1.1433.653 2.1397 1.176 2.989.522.8493 1.208 1.5353 2.058 2.058.849.5227 1.878.784 3.087.784 4.442.0327 6.664-3.1033 6.664-9.408 0-1.274-.131-2.4827-.392-3.626-.229-1.1433-.605-2.1397-1.127-2.989-.523-.8493-1.209-1.519-2.058-2.009-.85-.5227-1.879-.784-3.087-.784-4.443-.0327-6.664 3.1033-6.664 9.408z"/><path d="m138.495 26.857 1.372 4.655h.049l1.225-4.753 5.488-14.259h4.214l-10.437 25.039h-1.666l-10.633-25.039h4.508z"/><path d="m154.686 14.313c1.241-.7513 2.678-1.3067 4.312-1.666 1.666-.3593 3.397-.539 5.194-.539 1.698 0 3.054.2287 4.067.686 1.045.4573 1.829 1.0617 2.352 1.813.555.7187.914 1.519 1.078 2.401.196.882.294 1.764.294 2.646 0 1.96-.049 3.871-.147 5.733s-.147 3.626-.147 5.292c0 1.2087.049 2.352.147 3.43s.277 2.0743.539 2.989h-2.891l-1.029-3.43h-.245c-.294.4573-.67.9147-1.127 1.372-.425.4247-.948.8167-1.568 1.176-.621.3267-1.34.6043-2.156.833-.817.2287-1.748.343-2.793.343-1.046 0-2.026-.1633-2.94-.49-.882-.3267-1.65-.784-2.303-1.372-.654-.6207-1.176-1.3557-1.568-2.205-.36-.8493-.539-1.813-.539-2.891 0-1.4373.294-2.6297.882-3.577.588-.98 1.404-1.7477 2.45-2.303 1.078-.588 2.352-.9963 3.822-1.225 1.502-.2613 3.152-.392 4.949-.392h1.323c.457 0 .914.0327 1.372.098.098-.98.147-1.862.147-2.646 0-1.7967-.36-3.0543-1.078-3.773-.719-.7187-2.026-1.078-3.92-1.078-.556 0-1.16.049-1.813.147-.621.0653-1.274.1797-1.96.343-.654.1307-1.291.3103-1.911.539-.588.196-1.111.4247-1.568.686zm6.958 19.649c.914 0 1.731-.1143 2.45-.343.718-.2613 1.339-.5717 1.862-.931.522-.392.947-.8167 1.274-1.274.359-.4573.62-.8983.784-1.323v-4.067c-.458-.0327-.931-.049-1.421-.049-.458-.0327-.915-.049-1.372-.049-1.013 0-2.009.0653-2.989.196-.948.098-1.797.3103-2.548.637-.719.294-1.307.7187-1.764 1.274-.425.5227-.637 1.1923-.637 2.009 0 1.1433.408 2.0907 1.225 2.842.816.7187 1.862 1.078 3.136 1.078z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
function counterUp(t){"use strict";this.defaults={duration:3e3,prepend:"",append:"%",selector:".countup",start:0,end:100,intvalues:!1,interval:100};var e=this;this.upating=!1,this.intervalID=null,this.props={};for(var r in this.defaults)"undefined"!=typeof r&&(e.props[r]=e.defaults[r],t.hasOwnProperty(r)&&e.props.hasOwnProperty(r)&&(e.props[r]=t[r]));this.domelems=document.querySelectorAll(this.props.selector),this.elems=[];var n={};this.domelems.forEach(function(t){n.obj=t;var r=parseInt(t.getAttribute("cup-start"));isNaN(r)?n.start=e.props.start:n.start=r;var p=parseInt(t.getAttribute("cup-end"));isNaN(p)?n.end=e.props.end:n.end=p;var a=parseInt(t.getAttribute("cup-duration"));isNaN(a)?n.duration=e.props.duration:n.duration=a;var s=t.getAttribute("cup-prepend");null==s?n.prepend=e.props.prepend:n.prepend=s;var i=t.getAttribute("cup-append");null==i?n.append=e.props.append:n.append=i;var o=t.getAttribute("cup-intval");null==o?n.intvalues=e.props.intvalues:n.intvalues=o,n.step=(n.end-n.start)/(n.duration/e.props.interval),n.val=n.start,e.elems.push(n),n={}})}counterUp.prototype.start=function(){"use strict";var t=this;this.intervalID=setInterval(function(){t.updating||t.update()},t.props.interval)},counterUp.prototype.update=function(){"use strict";this.updating=!0;var t=!0;this.elems.forEach(function(e){e.val+=e.step,e.val<e.end?(1==e.intvalues?e.obj.innerHTML=e.prepend+Math.floor(e.val).toString()+e.append:e.obj.innerHTML=e.prepend+(Math.round(100*e.val)/100).toString()+e.append,t=!1):e.obj.innerHTML=e.prepend+e.end.toString()+e.append}),1==t&&clearInterval(this.intervalID),this.updating=!1};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,104 @@
(function() {
/* ====================
Preloader
======================= */
window.onload = function () {
window.setTimeout(fadeout, 300);
}
function fadeout() {
document.querySelector('.preloader').style.opacity = '0';
document.querySelector('.preloader').style.display = 'none';
}
// =========== sticky menu
window.onscroll = function () {
var header_navbar = document.querySelector(".hero-section-wrapper-5 .header");
var sticky = header_navbar.offsetTop;
if (window.pageYOffset > sticky) {
header_navbar.classList.add("sticky");
} else {
header_navbar.classList.remove("sticky");
}
// show or hide the back-top-top button
var backToTo = document.querySelector(".scroll-top");
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
backToTo.style.display = "flex";
} else {
backToTo.style.display = "none";
}
};
// header-6 toggler-icon
let navbarToggler6 = document.querySelector(".header-6 .navbar-toggler");
var navbarCollapse6 = document.querySelector(".header-6 .navbar-collapse");
document.querySelectorAll(".header-6 .page-scroll").forEach(e =>
e.addEventListener("click", () => {
navbarToggler6.classList.remove("active");
navbarCollapse6.classList.remove('show')
})
);
navbarToggler6.addEventListener('click', function() {
navbarToggler6.classList.toggle("active");
})
// section menu active
function onScroll(event) {
var sections = document.querySelectorAll('.page-scroll');
var scrollPos = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
for (var i = 0; i < sections.length; i++) {
var currLink = sections[i];
var val = currLink.getAttribute('href');
var refElement = document.querySelector(val);
var scrollTopMinus = scrollPos + 73;
if (refElement.offsetTop <= scrollTopMinus && (refElement.offsetTop + refElement.offsetHeight > scrollTopMinus)) {
document.querySelector('.page-scroll').classList.remove('active');
currLink.classList.add('active');
} else {
currLink.classList.remove('active');
}
}
};
window.document.addEventListener('scroll', onScroll);
// ===== pricing-style-4 slider
tns({
container: '.pricing-active',
autoplay: false,
mouseDrag: true,
gutter: 0,
nav: false,
controls: true,
controlsText: [
'<i class="lni lni-chevron-left prev"></i>',
'<i class="lni lni-chevron-right prev"></i>',
],
responsive: {
0: {
items: 1,
},
768: {
items: 2,
},
992: {
items: 1.2,
},
1200: {
items: 2,
}
}
});
// WOW active
new WOW().init();
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,13 +0,0 @@
{
"name": "默认模板",
"description": "标准企业官网模板,适用于各类企业展示",
"version": "1.0.0",
"author": "System",
"fields": {
"site_name": "网站名称",
"banner": "轮播图列表",
"news": "新闻列表",
"solutions": "解决方案",
"partners": "合作伙伴"
}
}

View File

@ -1,82 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title data-field="site_name">企业官网</title>
<link rel="stylesheet" href="./styles/main.css">
</head>
<body>
<!-- 头部 -->
<header class="header">
<div class="container">
<h1 data-field="site_name">企业官网</h1>
<nav class="nav">
<a href="/">首页</a>
<a href="/news">新闻资讯</a>
<a href="/solutions">解决方案</a>
<a href="/contact">联系我们</a>
</nav>
</div>
</header>
<!-- 轮播图 -->
<section class="banner">
<div class="banner-slides">
<div class="slide active" data-field="banner">
<img src="./images/banner1.jpg" alt="Banner 1">
<div class="banner-content">
<h2>欢迎来到我们的网站</h2>
<p>专业的企业数字化解决方案提供商</p>
</div>
</div>
</div>
</section>
<!-- 新闻资讯 -->
<section class="news section">
<div class="container">
<h2 class="section-title">新闻资讯</h2>
<div class="news-list" data-field="news">
<div class="news-item">
<h3>公司动态</h3>
<p>这里是新闻内容...</p>
</div>
</div>
</div>
</section>
<!-- 解决方案 -->
<section class="solutions section">
<div class="container">
<h2 class="section-title">解决方案</h2>
<div class="solutions-grid" data-field="solutions">
<div class="solution-card">
<h3>解决方案一</h3>
<p>详细描述...</p>
</div>
</div>
</div>
</section>
<!-- 合作伙伴 -->
<section class="partners section">
<div class="container">
<h2 class="section-title">合作伙伴</h2>
<div class="partners-grid" data-field="partners">
<div class="partner-logo">Partner Logo</div>
</div>
</div>
</section>
<!-- 底部 -->
<footer class="footer">
<div class="container">
<p>&copy; 2024 <span data-field="site_name">企业官网</span>. All rights reserved.</p>
</div>
</footer>
<!-- 数据注入脚本 -->
<script src="./js/theme-loader.js"></script>
</body>
</html>

View File

@ -0,0 +1,527 @@
<!DOCTYPE html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Nova - Bootstrap 5 Template</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Place favicon.ico in the root directory -->
<!-- ========================= CSS here ========================= -->
<link rel="stylesheet" href="assets/css/bootstrap-5.0.0-beta1.min.css" />
<link rel="stylesheet" href="assets/css/LineIcons.2.0.css"/>
<link rel="stylesheet" href="assets/css/tiny-slider.css"/>
<link rel="stylesheet" href="assets/css/animate.css"/>
<link rel="stylesheet" href="assets/css/lindy-uikit.css"/>
</head>
<body>
<!--[if lte IE 9]>
<p class="browserupgrade">
You are using an <strong>outdated</strong> browser. Please
<a href="https://browsehappy.com/">upgrade your browser</a> to improve
your experience and security.
</p>
<![endif]-->
<!-- ========================= preloader start ========================= -->
<div class="preloader">
<div class="loader">
<div class="spinner">
<div class="spinner-container">
<div class="spinner-rotator">
<div class="spinner-left">
<div class="spinner-circle"></div>
</div>
<div class="spinner-right">
<div class="spinner-circle"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ========================= preloader end ========================= -->
<!-- ========================= hero-section-wrapper-5 start ========================= -->
<section id="home" class="hero-section-wrapper-5">
<!-- ========================= header-6 start ========================= -->
<header class="header header-6">
<div class="navbar-area">
<div class="container">
<div class="row align-items-center">
<div class="col-lg-12">
<nav class="navbar navbar-expand-lg">
<a class="navbar-brand" href="index.html">
<img src="assets/img/logo/logo.svg" alt="Logo" />
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent6" aria-controls="navbarSupportedContent6" aria-expanded="false" aria-label="Toggle navigation">
<span class="toggler-icon"></span>
<span class="toggler-icon"></span>
<span class="toggler-icon"></span>
</button>
<div class="collapse navbar-collapse sub-menu-bar" id="navbarSupportedContent6">
<ul id="nav6" class="navbar-nav ms-auto">
<li class="nav-item">
<a class="page-scroll active" href="#home">Home</a>
</li>
<li class="nav-item">
<a class="page-scroll" href="#feature">Feature</a>
</li>
<li class="nav-item">
<a class="page-scroll" href="#about">About</a>
</li>
<li class="nav-item">
<a class="page-scroll" href="#pricing">Pricing</a>
</li>
<li class="nav-item">
<a class="page-scroll" href="#contact">Contact</a>
</li>
</ul>
</div>
<div class="header-action d-flex">
<a href="#0"> <i class="lni lni-cart"></i> </a>
<a href="#0"> <i class="lni lni-alarm"></i> </a>
</div>
<!-- navbar collapse -->
</nav>
<!-- navbar -->
</div>
</div>
<!-- row -->
</div>
<!-- container -->
</div>
<!-- navbar area -->
</header>
<!-- ========================= header-6 end ========================= -->
<!-- ========================= hero-5 start ========================= -->
<div class="hero-section hero-style-5 img-bg" style="background-image: url('assets/img/hero/hero-5/hero-bg.svg')">
<div class="container">
<div class="row">
<div class="col-lg-6">
<div class="hero-content-wrapper">
<h2 class="mb-30 wow fadeInUp" data-wow-delay=".2s">You're Using Free Lite Version</h2>
<p class="mb-30 wow fadeInUp" data-wow-delay=".4s">Please purchase full version of the template to get all sections and permission to use with commercial projects.</p>
<a href="#0" class="button button-lg radius-50 wow fadeInUp" data-wow-delay=".6s">Get Started <i class="lni lni-chevron-right"></i> </a>
</div>
</div>
<div class="col-lg-6 align-self-end">
<div class="hero-image wow fadeInUp" data-wow-delay=".5s">
<img src="assets/img/hero/hero-5/hero-img.svg" alt="">
</div>
</div>
</div>
</div>
</div>
<!-- ========================= hero-5 end ========================= -->
</section>
<!-- ========================= hero-section-wrapper-6 end ========================= -->
<!-- ========================= feature style-5 start ========================= -->
<section id="feature" class="feature-section feature-style-5">
<div class="container">
<div class="row justify-content-center">
<div class="col-xxl-5 col-xl-5 col-lg-7 col-md-8">
<div class="section-title text-center mb-60">
<h3 class="mb-15 wow fadeInUp" data-wow-delay=".2s">Specializing In</h3>
<p class="wow fadeInUp" data-wow-delay=".4s">Stop wasting time and money designing and managing a website that doesnt get results. Happiness guaranteed!</p>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-md-6">
<div class="single-feature wow fadeInUp" data-wow-delay=".2s">
<div class="icon">
<i class="lni lni-vector"></i>
<svg width="110" height="72" viewBox="0 0 110 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M110 54.7589C110 85.0014 85.3757 66.2583 55 66.2583C24.6243 66.2583 0 85.0014 0 54.7589C0 24.5164 24.6243 0 55 0C85.3757 0 110 24.5164 110 54.7589Z" fill="#EBF4FF"/>
</svg>
</div>
<div class="content">
<h5>Graphics Design</h5>
<p>Short description for the ones who look for something new.</p>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="single-feature wow fadeInUp" data-wow-delay=".4s">
<div class="icon">
<i class="lni lni-pallet"></i>
<svg width="110" height="72" viewBox="0 0 110 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M110 54.7589C110 85.0014 85.3757 66.2583 55 66.2583C24.6243 66.2583 0 85.0014 0 54.7589C0 24.5164 24.6243 0 55 0C85.3757 0 110 24.5164 110 54.7589Z" fill="#EBF4FF"/>
</svg>
</div>
<div class="content">
<h5>Print Design</h5>
<p>Short description for the ones who look for something new.</p>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="single-feature wow fadeInUp" data-wow-delay=".6s">
<div class="icon">
<i class="lni lni-stats-up"></i>
<svg width="110" height="72" viewBox="0 0 110 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M110 54.7589C110 85.0014 85.3757 66.2583 55 66.2583C24.6243 66.2583 0 85.0014 0 54.7589C0 24.5164 24.6243 0 55 0C85.3757 0 110 24.5164 110 54.7589Z" fill="#EBF4FF"/>
</svg>
</div>
<div class="content">
<h5>Business Analysis</h5>
<p>Short description for the ones who look for something new.</p>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="single-feature wow fadeInUp" data-wow-delay=".2s">
<div class="icon">
<i class="lni lni-code-alt"></i>
<svg width="110" height="72" viewBox="0 0 110 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M110 54.7589C110 85.0014 85.3757 66.2583 55 66.2583C24.6243 66.2583 0 85.0014 0 54.7589C0 24.5164 24.6243 0 55 0C85.3757 0 110 24.5164 110 54.7589Z" fill="#EBF4FF"/>
</svg>
</div>
<div class="content">
<h5>Web Development</h5>
<p>Short description for the ones who look for something new.</p>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="single-feature wow fadeInUp" data-wow-delay=".4s">
<div class="icon">
<i class="lni lni-lock"></i>
<svg width="110" height="72" viewBox="0 0 110 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M110 54.7589C110 85.0014 85.3757 66.2583 55 66.2583C24.6243 66.2583 0 85.0014 0 54.7589C0 24.5164 24.6243 0 55 0C85.3757 0 110 24.5164 110 54.7589Z" fill="#EBF4FF"/>
</svg>
</div>
<div class="content">
<h5>Best Security</h5>
<p>Short description for the ones who look for something new.</p>
</div>
</div>
</div>
<div class="col-lg-4 col-md-6">
<div class="single-feature wow fadeInUp" data-wow-delay=".6s">
<div class="icon">
<i class="lni lni-code"></i>
<svg width="110" height="72" viewBox="0 0 110 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M110 54.7589C110 85.0014 85.3757 66.2583 55 66.2583C24.6243 66.2583 0 85.0014 0 54.7589C0 24.5164 24.6243 0 55 0C85.3757 0 110 24.5164 110 54.7589Z" fill="#EBF4FF"/>
</svg>
</div>
<div class="content">
<h5>Web Design</h5>
<p>Short description for the ones who look for something new.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ========================= feature style-5 end ========================= -->
<!-- ========================= about style-4 start ========================= -->
<section id="about" class="about-section about-style-4">
<div class="container">
<div class="row align-items-center">
<div class="col-xl-5 col-lg-6">
<div class="about-content-wrapper">
<div class="section-title mb-30">
<h3 class="mb-25 wow fadeInUp" data-wow-delay=".2s">The future of designing starts here</h3>
<p class="wow fadeInUp" data-wow-delay=".3s">Stop wasting time and money designing and managing a website that doesnt get results. Happiness guaranteed,</p>
</div>
<ul>
<li class="wow fadeInUp" data-wow-delay=".35s">
<i class="lni lni-checkmark-circle"></i>
Stop wasting time and money designing and managing a website that doesnt get results.
</li>
<li class="wow fadeInUp" data-wow-delay=".4s">
<i class="lni lni-checkmark-circle"></i>
Stop wasting time and money designing and managing.
</li>
<li class="wow fadeInUp" data-wow-delay=".45s">
<i class="lni lni-checkmark-circle"></i>
Stop wasting time and money designing and managing a website that doesnt get results.
</li>
</ul>
<a href="#0" class="button button-lg radius-10 wow fadeInUp" data-wow-delay=".5s">Learn More</a>
</div>
</div>
<div class="col-xl-7 col-lg-6">
<div class="about-image text-lg-right wow fadeInUp" data-wow-delay=".5s">
<img src="assets/img/about/about-4/about-img.svg" alt="">
</div>
</div>
</div>
</div>
</section>
<!-- ========================= about style-4 end ========================= -->
<!-- ========================= pricing style-4 start ========================= -->
<section id="pricing" class="pricing-section pricing-style-4 bg-light">
<div class="container">
<div class="row align-items-center">
<div class="col-xl-5 col-lg-6">
<div class="section-title mb-60">
<h3 class="mb-15 wow fadeInUp" data-wow-delay=".2s">Pricing Plan</h3>
<p class="wow fadeInUp" data-wow-delay=".4s">Stop wasting time and money designing and managing a website that doesnt get results. Happiness guaranteed!Stop wasting time and money designing and managing a website that doesnt get results. Happiness guaranteed!</p>
</div>
</div>
<div class="col-xl-7 col-lg-6">
<div class="pricing-active-wrapper wow fadeInUp" data-wow-delay=".4s">
<div class="pricing-active">
<div class="single-pricing-wrapper">
<div class="single-pricing">
<h6>Basic Design</h6>
<h4>Web Design</h4>
<h3>$ 29.00</h3>
<ul>
<li>Carefully crafted components</li>
<li>Amazing page examples</li>
<li>Super friendly support team</li>
<li>Awesome Support</li>
</ul>
<a href="#0" class="button radius-30">Get Started</a>
</div>
</div>
<div class="single-pricing-wrapper">
<div class="single-pricing">
<h6>Standard Design</h6>
<h4>Web Development</h4>
<h3>$ 89.00</h3>
<ul>
<li>Carefully crafted components</li>
<li>Amazing page examples</li>
<li>Super friendly support team</li>
<li>Awesome Support</li>
</ul>
<a href="#0" class="button radius-30">Get Started</a>
</div>
</div>
<div class="single-pricing-wrapper">
<div class="single-pricing">
<h6>Pro Design</h6>
<h4>Design & Develop</h4>
<h3>$ 199.00</h3>
<ul>
<li>Carefully crafted components</li>
<li>Amazing page examples</li>
<li>Super friendly support team</li>
<li>Awesome Support</li>
</ul>
<a href="#0" class="button radius-30">Get Started</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ========================= pricing style-4 end ========================= -->
<!-- ========================= contact-style-3 start ========================= -->
<section id="contact" class="contact-section contact-style-3">
<div class="container">
<div class="row justify-content-center">
<div class="col-xxl-5 col-xl-5 col-lg-7 col-md-10">
<div class="section-title text-center mb-50">
<h3 class="mb-15">Get in touch</h3>
<p>Stop wasting time and money designing and managing a website that doesnt get results. Happiness guaranteed!</p>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<div class="contact-form-wrapper">
<form action="" method="">
<div class="row">
<div class="col-md-6">
<div class="single-input">
<input type="text" id="name" name="name" class="form-input" placeholder="Name">
<i class="lni lni-user"></i>
</div>
</div>
<div class="col-md-6">
<div class="single-input">
<input type="email" id="email" name="email" class="form-input" placeholder="Email">
<i class="lni lni-envelope"></i>
</div>
</div>
<div class="col-md-6">
<div class="single-input">
<input type="text" id="number" name="number" class="form-input" placeholder="Number">
<i class="lni lni-phone"></i>
</div>
</div>
<div class="col-md-6">
<div class="single-input">
<input type="text" id="subject" name="subject" class="form-input" placeholder="Subject">
<i class="lni lni-text-format"></i>
</div>
</div>
<div class="col-md-12">
<div class="single-input">
<textarea name="message" id="message" class="form-input" placeholder="Message" rows="6"></textarea>
<i class="lni lni-comments-alt"></i>
</div>
</div>
<div class="col-md-12">
<div class="form-button">
<button type="submit" class="button"> <i class="lni lni-telegram-original"></i> Submit</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="col-lg-4">
<div class="left-wrapper">
<div class="row">
<div class="col-lg-12 col-md-6">
<div class="single-item">
<div class="icon">
<i class="lni lni-phone"></i>
</div>
<div class="text">
<p>0045939863784</p>
<p>+004389478327</p>
</div>
</div>
</div>
<div class="col-lg-12 col-md-6">
<div class="single-item">
<div class="icon">
<i class="lni lni-envelope"></i>
</div>
<div class="text">
<p>yourmail@gmail.com</p>
<p>admin@yourwebsite.com</p>
</div>
</div>
</div>
<div class="col-lg-12 col-md-6">
<div class="single-item">
<div class="icon">
<i class="lni lni-map-marker"></i>
</div>
<div class="text">
<p>John's House, 13/5 Road, Sidny United State Of America</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ========================= contact-style-3 end ========================= -->
<!-- ========================= clients-logo start ========================= -->
<section class="clients-logo-section pt-100 pb-100">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="client-logo wow fadeInUp" data-wow-delay=".2s">
<img src="assets/img/clients/brands.svg" alt="" class="w-100">
</div>
</div>
</div>
</div>
</section>
<!-- ========================= clients-logo end ========================= -->
<!-- ========================= footer style-4 start ========================= -->
<footer class="footer footer-style-4">
<div class="container">
<div class="widget-wrapper">
<div class="row">
<div class="col-xl-3 col-lg-4 col-md-6">
<div class="footer-widget wow fadeInUp" data-wow-delay=".2s">
<div class="logo">
<a href="#0"> <img src="assets/img/logo/logo.svg" alt=""> </a>
</div>
<p class="desc">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Facilisis nulla placerat amet amet congue.</p>
<ul class="socials">
<li> <a href="#0"> <i class="lni lni-facebook-filled"></i> </a> </li>
<li> <a href="#0"> <i class="lni lni-twitter-filled"></i> </a> </li>
<li> <a href="#0"> <i class="lni lni-instagram-filled"></i> </a> </li>
<li> <a href="#0"> <i class="lni lni-linkedin-original"></i> </a> </li>
</ul>
</div>
</div>
<div class="col-xl-2 offset-xl-1 col-lg-2 col-md-6 col-sm-6">
<div class="footer-widget wow fadeInUp" data-wow-delay=".3s">
<h6>Quick Link</h6>
<ul class="links">
<li> <a href="#0">Home</a> </li>
<li> <a href="#0">About</a> </li>
<li> <a href="#0">Service</a> </li>
<li> <a href="#0">Testimonial</a> </li>
<li> <a href="#0">Contact</a> </li>
</ul>
</div>
</div>
<div class="col-xl-3 col-lg-3 col-md-6 col-sm-6">
<div class="footer-widget wow fadeInUp" data-wow-delay=".4s">
<h6>Services</h6>
<ul class="links">
<li> <a href="#0">Web Design</a> </li>
<li> <a href="#0">Web Development</a> </li>
<li> <a href="#0">Seo Optimization</a> </li>
<li> <a href="#0">Blog Writing</a> </li>
</ul>
</div>
</div>
<div class="col-xl-3 col-lg-3 col-md-6">
<div class="footer-widget wow fadeInUp" data-wow-delay=".5s">
<h6>Download App</h6>
<ul class="download-app">
<li>
<a href="#0">
<span class="icon"><i class="lni lni-apple"></i></span>
<span class="text">Download on the <b>App Store</b> </span>
</a>
</li>
<li>
<a href="#0">
<span class="icon"><i class="lni lni-play-store"></i></span>
<span class="text">GET IT ON <b>Play Store</b> </span>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="copyright-wrapper wow fadeInUp" data-wow-delay=".2s">
<p>Design and Developed by <a href="https://uideck.com" rel="nofollow" target="_blank">UIdeck</a> Built-with <a href="https://uideck.com" rel="nofollow" target="_blank">Lindy UI Kit</a>. Distributed by <a href="https://themewagon.com" target="_blank">ThemeWagon</a></p>
</div>
</div>
</footer>
<!-- ========================= footer style-4 end ========================= -->
<!-- ========================= scroll-top start ========================= -->
<a href="#" class="scroll-top"> <i class="lni lni-chevron-up"></i> </a>
<!-- ========================= scroll-top end ========================= -->
<!-- ========================= JS here ========================= -->
<script src="assets/js/bootstrap-5.0.0-beta1.min.js"></script>
<script src="assets/js/tiny-slider.js"></script>
<script src="assets/js/wow.min.js"></script>
<script src="assets/js/main.js"></script>
</body>
</html>

View File

@ -1,213 +0,0 @@
/**
* 模板数据注入脚本
* 功能监听 postMessage 事件当收到 SET_SITE_DATA
* 自动寻找带有 data-field 属性的 HTML 标签替换为对应的数据
*/
(function() {
'use strict';
// 日志开关
const DEBUG = false;
function log(...args) {
if (DEBUG) {
console.log('[ThemeLoader]', ...args);
}
}
/**
* 替换元素内容或属性
* @param {HTMLElement} element - 目标元素
* @param {string} field - 字段名
* @param {any} value - 数据值
*/
function applyDataToElement(element, field, value) {
if (value === undefined || value === null) {
log(`字段 ${field} 值为空,跳过`);
return;
}
// 如果是数组或对象,尝试解析
if (typeof value === 'string') {
try {
const parsed = JSON.parse(value);
if (parsed) {
value = parsed;
}
} catch (e) {
// 保持原值
}
}
// 处理数组类型(用于轮播图、列表等)
if (Array.isArray(value)) {
handleArrayField(element, field, value);
return;
}
// 处理对象类型
if (typeof value === 'object') {
handleObjectField(element, field, value);
return;
}
// 处理基础类型(字符串、数字)
// 1. 如果是 input/textarea/select设置为 value
const tagName = element.tagName.toLowerCase();
if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
element.value = value;
return;
}
// 2. 如果有 src 属性,设置为 src图片等
if (element.hasAttribute('src') && !element.hasAttribute('data-keep-src')) {
// 检查是否是占位符图片
const currentSrc = element.getAttribute('src');
if (!currentSrc || currentSrc.indexOf('placeholder') > -1) {
element.src = value;
}
return;
}
// 3. 否则设置为 innerText
element.innerText = value;
}
/**
* 处理数组类型的字段如轮播图列表
*/
function handleArrayField(container, field, dataList) {
// 查找模板元素(带有 data-template 属性的元素)
const templateElement = container.querySelector('[data-template]');
if (!templateElement) {
log(`字段 ${field} 未找到模板元素`);
return;
}
const template = templateElement.cloneNode(true);
template.removeAttribute('data-template');
template.style.display = '';
// 清空容器
container.innerHTML = '';
// 渲染每个数据项
dataList.forEach((item, index) => {
const itemElement = template.cloneNode(true);
applyDataToObject(itemElement, item, index);
container.appendChild(itemElement);
});
}
/**
* 处理对象类型的字段
*/
function handleObjectField(element, field, data) {
// 递归处理对象属性
applyDataToObject(element, data);
}
/**
* 将数据应用到元素及其子元素
*/
function applyDataToObject(element, data, index = 0) {
// 处理 data-field 属性
const fieldElements = element.querySelectorAll('[data-field]');
fieldElements.forEach(el => {
const field = el.getAttribute('data-field');
// 支持点号分隔的路径,如 "banner.0.image"
const value = getNestedValue(data, field);
if (value !== undefined) {
applyDataToElement(el, field, value);
}
});
// 也处理元素本身的 data-field
if (element.hasAttribute('data-field')) {
const field = element.getAttribute('data-field');
const value = getNestedValue(data, field);
if (value !== undefined) {
applyDataToElement(element, field, value);
}
}
}
/**
* 获取嵌套属性值
* @param {object} obj - 数据对象
* @param {string} path - 属性路径 "banner.0.image"
* @returns {any}
*/
function getNestedValue(obj, path) {
if (!path) return obj;
const keys = path.split('.');
let value = obj;
for (const key of keys) {
if (value === null || value === undefined) {
return undefined;
}
value = value[key];
}
return value;
}
/**
* 初始化数据注入
*/
function init() {
log('ThemeLoader 初始化');
// 监听来自父窗口的消息
window.addEventListener('message', function(event) {
log('收到消息:', event.data);
// 验证消息类型
if (!event.data || event.data.type !== 'SET_SITE_DATA') {
return;
}
const siteData = event.data.data;
if (!siteData) {
log('未收到有效数据');
return;
}
log('开始注入数据:', siteData);
// 查找所有带有 data-field 属性的元素
const elements = document.querySelectorAll('[data-field]');
elements.forEach(element => {
const field = element.getAttribute('data-field');
const value = siteData[field];
if (value !== undefined) {
applyDataToElement(element, field, value);
}
});
// 触发自定义事件,通知数据已加载
window.dispatchEvent(new CustomEvent('themeDataLoaded', {
detail: siteData
}));
log('数据注入完成');
});
// 发送就绪消息给父窗口
window.parent.postMessage({
type: 'THEME_READY'
}, '*');
}
// DOM 加载完成后初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -1,153 +0,0 @@
/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.section {
padding: 60px 0;
}
.section-title {
text-align: center;
font-size: 32px;
margin-bottom: 40px;
color: #333;
}
/* 头部 */
.header {
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
}
.header .container {
display: flex;
justify-content: space-between;
align-items: center;
height: 70px;
}
.header h1 {
font-size: 24px;
color: #1890ff;
}
.nav a {
margin-left: 30px;
text-decoration: none;
color: #333;
transition: color 0.3s;
}
.nav a:hover {
color: #1890ff;
}
/* 轮播图 */
.banner {
margin-top: 70px;
height: 500px;
overflow: hidden;
position: relative;
}
.banner-slides .slide {
display: none;
}
.banner-slides .slide.active {
display: block;
}
.banner-slides .slide img {
width: 100%;
height: 500px;
object-fit: cover;
}
.banner-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #fff;
}
.banner-content h2 {
font-size: 48px;
margin-bottom: 20px;
}
.banner-content p {
font-size: 20px;
}
/* 新闻 */
.news-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
}
.news-item {
background: #f5f5f5;
padding: 20px;
border-radius: 8px;
}
/* 解决方案 */
.solutions-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.solution-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 40px 20px;
border-radius: 8px;
text-align: center;
color: #fff;
}
/* 合作伙伴 */
.partners-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px;
}
.partner-logo {
background: #f5f5f5;
padding: 30px;
text-align: center;
border-radius: 8px;
}
/* 底部 */
.footer {
background: #333;
color: #fff;
padding: 30px 0;
text-align: center;
}

View File

@ -0,0 +1,398 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Zay Shop - About Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="assets/img/apple-icon.png">
<link rel="shortcut icon" type="image/x-icon" href="assets/img/favicon.ico">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/templatemo.css">
<link rel="stylesheet" href="assets/css/custom.css">
<!-- Load fonts style after rendering the layout styles -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;200;300;400;500;700;900&display=swap">
<link rel="stylesheet" href="assets/css/fontawesome.min.css">
<!--
TemplateMo 559 Zay Shop
https://templatemo.com/tm-559-zay-shop
-->
</head>
<body>
<!-- Start Top Nav -->
<nav class="navbar navbar-expand-lg bg-dark navbar-light d-none d-lg-block" id="templatemo_nav_top">
<div class="container text-light">
<div class="w-100 d-flex justify-content-between">
<div>
<i class="fa fa-envelope mx-2"></i>
<a class="navbar-sm-brand text-light text-decoration-none" href="mailto:info@company.com">info@company.com</a>
<i class="fa fa-phone mx-2"></i>
<a class="navbar-sm-brand text-light text-decoration-none" href="tel:010-020-0340">010-020-0340</a>
</div>
<div>
<a class="text-light" href="https://fb.com/templatemo" target="_blank" rel="sponsored"><i class="fab fa-facebook-f fa-sm fa-fw me-2"></i></a>
<a class="text-light" href="https://www.instagram.com/" target="_blank"><i class="fab fa-instagram fa-sm fa-fw me-2"></i></a>
<a class="text-light" href="https://twitter.com/" target="_blank"><i class="fab fa-twitter fa-sm fa-fw me-2"></i></a>
<a class="text-light" href="https://www.linkedin.com/" target="_blank"><i class="fab fa-linkedin fa-sm fa-fw"></i></a>
</div>
</div>
</div>
</nav>
<!-- Close Top Nav -->
<!-- Header -->
<nav class="navbar navbar-expand-lg navbar-light shadow">
<div class="container d-flex justify-content-between align-items-center">
<a class="navbar-brand text-success logo h1 align-self-center" href="index.html">
Zay
</a>
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" data-bs-target="#templatemo_main_nav" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="align-self-center collapse navbar-collapse flex-fill d-lg-flex justify-content-lg-between" id="templatemo_main_nav">
<div class="flex-fill">
<ul class="nav navbar-nav d-flex justify-content-between mx-lg-auto">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="about.html">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="shop.html">Shop</a>
</li>
<li class="nav-item">
<a class="nav-link" href="contact.html">Contact</a>
</li>
</ul>
</div>
<div class="navbar align-self-center d-flex">
<div class="d-lg-none flex-sm-fill mt-3 mb-4 col-7 col-sm-auto pr-3">
<div class="input-group">
<input type="text" class="form-control" id="inputMobileSearch" placeholder="Search ...">
<div class="input-group-text">
<i class="fa fa-fw fa-search"></i>
</div>
</div>
</div>
<a class="nav-icon d-none d-lg-inline" href="#" data-bs-toggle="modal" data-bs-target="#templatemo_search">
<i class="fa fa-fw fa-search text-dark mr-2"></i>
</a>
<a class="nav-icon position-relative text-decoration-none" href="#">
<i class="fa fa-fw fa-cart-arrow-down text-dark mr-1"></i>
<span class="position-absolute top-0 left-100 translate-middle badge rounded-pill bg-light text-dark">7</span>
</a>
<a class="nav-icon position-relative text-decoration-none" href="#">
<i class="fa fa-fw fa-user text-dark mr-3"></i>
<span class="position-absolute top-0 left-100 translate-middle badge rounded-pill bg-light text-dark">+99</span>
</a>
</div>
</div>
</div>
</nav>
<!-- Close Header -->
<!-- Modal -->
<div class="modal fade bg-white" id="templatemo_search" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="w-100 pt-1 mb-5 text-right">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="" method="get" class="modal-content modal-body border-0 p-0">
<div class="input-group mb-2">
<input type="text" class="form-control" id="inputModalSearch" name="q" placeholder="Search ...">
<button type="submit" class="input-group-text bg-success text-light">
<i class="fa fa-fw fa-search text-white"></i>
</button>
</div>
</form>
</div>
</div>
<section class="bg-success py-5">
<div class="container">
<div class="row align-items-center py-5">
<div class="col-md-8 text-white">
<h1>About Us</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
</div>
<div class="col-md-4">
<img src="assets/img/about-hero.svg" alt="About Hero">
</div>
</div>
</div>
</section>
<!-- Close Banner -->
<!-- Start Section -->
<section class="container py-5">
<div class="row text-center pt-5 pb-3">
<div class="col-lg-6 m-auto">
<h1 class="h1">Our Services</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
Lorem ipsum dolor sit amet.
</p>
</div>
</div>
<div class="row">
<div class="col-md-6 col-lg-3 pb-5">
<div class="h-100 py-5 services-icon-wap shadow">
<div class="h1 text-success text-center"><i class="fa fa-truck fa-lg"></i></div>
<h2 class="h5 mt-4 text-center">Delivery Services</h2>
</div>
</div>
<div class="col-md-6 col-lg-3 pb-5">
<div class="h-100 py-5 services-icon-wap shadow">
<div class="h1 text-success text-center"><i class="fas fa-exchange-alt"></i></div>
<h2 class="h5 mt-4 text-center">Shipping & Return</h2>
</div>
</div>
<div class="col-md-6 col-lg-3 pb-5">
<div class="h-100 py-5 services-icon-wap shadow">
<div class="h1 text-success text-center"><i class="fa fa-percent"></i></div>
<h2 class="h5 mt-4 text-center">Promotion</h2>
</div>
</div>
<div class="col-md-6 col-lg-3 pb-5">
<div class="h-100 py-5 services-icon-wap shadow">
<div class="h1 text-success text-center"><i class="fa fa-user"></i></div>
<h2 class="h5 mt-4 text-center">24 Hours Service</h2>
</div>
</div>
</div>
</section>
<!-- End Section -->
<!-- Start Brands -->
<section class="bg-light py-5">
<div class="container my-4">
<div class="row text-center py-3">
<div class="col-lg-6 m-auto">
<h1 class="h1">Our Brands</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
Lorem ipsum dolor sit amet.
</p>
</div>
<div class="col-lg-9 m-auto tempaltemo-carousel">
<div class="row d-flex flex-row">
<!--Controls-->
<div class="col-1 align-self-center">
<a class="h1" href="#templatemo-slide-brand" role="button" data-bs-slide="prev">
<i class="text-light fas fa-chevron-left"></i>
</a>
</div>
<!--End Controls-->
<!--Carousel Wrapper-->
<div class="col">
<div class="carousel slide carousel-multi-item pt-2 pt-md-0" id="templatemo-slide-brand" data-bs-ride="carousel">
<!--Slides-->
<div class="carousel-inner product-links-wap" role="listbox">
<!--First slide-->
<div class="carousel-item active">
<div class="row">
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_01.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_02.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_03.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_04.png" alt="Brand Logo"></a>
</div>
</div>
</div>
<!--End First slide-->
<!--Second slide-->
<div class="carousel-item">
<div class="row">
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_01.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_02.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_03.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_04.png" alt="Brand Logo"></a>
</div>
</div>
</div>
<!--End Second slide-->
<!--Third slide-->
<div class="carousel-item">
<div class="row">
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_01.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_02.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_03.png" alt="Brand Logo"></a>
</div>
<div class="col-3 p-md-5">
<a href="#"><img class="img-fluid brand-img" src="assets/img/brand_04.png" alt="Brand Logo"></a>
</div>
</div>
</div>
<!--End Third slide-->
</div>
<!--End Slides-->
</div>
</div>
<!--End Carousel Wrapper-->
<!--Controls-->
<div class="col-1 align-self-center">
<a class="h1" href="#templatemo-slide-brand" role="button" data-bs-slide="next">
<i class="text-light fas fa-chevron-right"></i>
</a>
</div>
<!--End Controls-->
</div>
</div>
</div>
</div>
</section>
<!--End Brands-->
<!-- Start Footer -->
<footer class="bg-dark" id="tempaltemo_footer">
<div class="container">
<div class="row">
<div class="col-md-4 pt-5">
<h2 class="h2 text-success border-bottom pb-3 border-light logo">Zay Shop</h2>
<ul class="list-unstyled text-light footer-link-list">
<li>
<i class="fas fa-map-marker-alt fa-fw"></i>
123 Consectetur at ligula 10660
</li>
<li>
<i class="fa fa-phone fa-fw"></i>
<a class="text-decoration-none" href="tel:010-020-0340">010-020-0340</a>
</li>
<li>
<i class="fa fa-envelope fa-fw"></i>
<a class="text-decoration-none" href="mailto:info@company.com">info@company.com</a>
</li>
</ul>
</div>
<div class="col-md-4 pt-5">
<h2 class="h2 text-light border-bottom pb-3 border-light">Products</h2>
<ul class="list-unstyled text-light footer-link-list">
<li><a class="text-decoration-none" href="#">Luxury</a></li>
<li><a class="text-decoration-none" href="#">Sport Wear</a></li>
<li><a class="text-decoration-none" href="#">Men's Shoes</a></li>
<li><a class="text-decoration-none" href="#">Women's Shoes</a></li>
<li><a class="text-decoration-none" href="#">Popular Dress</a></li>
<li><a class="text-decoration-none" href="#">Gym Accessories</a></li>
<li><a class="text-decoration-none" href="#">Sport Shoes</a></li>
</ul>
</div>
<div class="col-md-4 pt-5">
<h2 class="h2 text-light border-bottom pb-3 border-light">Further Info</h2>
<ul class="list-unstyled text-light footer-link-list">
<li><a class="text-decoration-none" href="#">Home</a></li>
<li><a class="text-decoration-none" href="#">About Us</a></li>
<li><a class="text-decoration-none" href="#">Shop Locations</a></li>
<li><a class="text-decoration-none" href="#">FAQs</a></li>
<li><a class="text-decoration-none" href="#">Contact</a></li>
</ul>
</div>
</div>
<div class="row text-light mb-4">
<div class="col-12 mb-3">
<div class="w-100 my-3 border-top border-light"></div>
</div>
<div class="col-auto me-auto">
<ul class="list-inline text-left footer-icons">
<li class="list-inline-item border border-light rounded-circle text-center">
<a rel="nofollow" class="text-light text-decoration-none" target="_blank" href="http://fb.com/templatemo"><i class="fab fa-facebook-f fa-lg fa-fw"></i></a>
</li>
<li class="list-inline-item border border-light rounded-circle text-center">
<a class="text-light text-decoration-none" target="_blank" href="https://www.instagram.com/"><i class="fab fa-instagram fa-lg fa-fw"></i></a>
</li>
<li class="list-inline-item border border-light rounded-circle text-center">
<a class="text-light text-decoration-none" target="_blank" href="https://twitter.com/"><i class="fab fa-twitter fa-lg fa-fw"></i></a>
</li>
<li class="list-inline-item border border-light rounded-circle text-center">
<a class="text-light text-decoration-none" target="_blank" href="https://www.linkedin.com/"><i class="fab fa-linkedin fa-lg fa-fw"></i></a>
</li>
</ul>
</div>
<div class="col-auto">
<label class="sr-only" for="subscribeEmail">Email address</label>
<div class="input-group mb-2">
<input type="text" class="form-control bg-dark border-light" id="subscribeEmail" placeholder="Email address">
<div class="input-group-text btn-success text-light">Subscribe</div>
</div>
</div>
</div>
</div>
<div class="w-100 bg-black py-3">
<div class="container">
<div class="row pt-2">
<div class="col-12">
<p class="text-left text-light">
Copyright &copy; 2021 Company Name
| Designed by <a rel="sponsored" href="https://templatemo.com/page/1" target="_blank">TemplateMo</a>
</p>
</div>
</div>
</div>
</div>
</footer>
<!-- End Footer -->
<!-- Start Script -->
<script src="assets/js/jquery-1.11.0.min.js"></script>
<script src="assets/js/jquery-migrate-1.2.1.min.js"></script>
<script src="assets/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/templatemo.js"></script>
<script src="assets/js/custom.js"></script>
<!-- End Script -->
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
/*
Custom Css
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,207 @@
@charset 'UTF-8';
/* Slider */
.slick-loading .slick-list
{
background: #fff url('../img/ajax-loader.gif') center center no-repeat;
}
/* Icons */
@font-face
{
font-family: 'slick';
font-weight: normal;
font-style: normal;
src: url('../webfonts/slick.eot');
src: url('../webfonts/slick.eot?#iefix') format('embedded-opentype'),
url('../webfonts/slick.woff') format('woff'),
url('../webfonts/slick.ttf') format('truetype'),
url('../webfonts/slick.svg#slick') format('svg');
}
/* Arrows */
.slick-prev,
.slick-next
{
font-size: 0;
line-height: 0;
position: absolute;
top: 50%;
display: block;
width: 20px;
height: 20px;
padding: 0;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
cursor: pointer;
color: transparent;
border: none;
outline: none;
background: transparent;
}
.slick-prev:hover,
.slick-prev:focus,
.slick-next:hover,
.slick-next:focus
{
color: transparent;
outline: none;
background: transparent;
}
.slick-prev:hover:before,
.slick-prev:focus:before,
.slick-next:hover:before,
.slick-next:focus:before
{
opacity: 1;
}
.slick-prev.slick-disabled:before,
.slick-next.slick-disabled:before
{
opacity: .25;
}
.slick-prev:before,
.slick-next:before
{
font-family: 'slick';
font-size: 20px;
line-height: 1;
opacity: .75;
color: white;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.slick-prev
{
left: -25px;
}
[dir='rtl'] .slick-prev
{
right: -25px;
left: auto;
}
.slick-prev:before
{
content: '←';
}
[dir='rtl'] .slick-prev:before
{
content: '→';
}
.slick-next
{
right: -25px;
}
[dir='rtl'] .slick-next
{
right: auto;
left: -25px;
}
.slick-next:before
{
content: '→';
}
[dir='rtl'] .slick-next:before
{
content: '←';
}
/* Dots */
.slick-dotted.slick-slider
{
margin-bottom: 30px;
}
.slick-dots
{
position: absolute;
bottom: -25px;
display: block;
width: 100%;
padding: 0;
margin: 0;
list-style: none;
text-align: center;
}
.slick-dots li
{
position: relative;
display: inline-block;
width: 20px;
height: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
}
.slick-dots li button
{
font-size: 0;
line-height: 0;
display: block;
width: 20px;
height: 20px;
padding: 5px;
cursor: pointer;
color: transparent;
border: 0;
outline: none;
background: transparent;
}
.slick-dots li button:hover,
.slick-dots li button:focus
{
outline: none;
}
.slick-dots li button:hover:before,
.slick-dots li button:focus:before
{
opacity: 1;
}
.slick-dots li button:before
{
font-family: 'slick';
font-size: 6px;
line-height: 20px;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
content: '•';
text-align: center;
opacity: .25;
color: black;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.slick-dots li.slick-active button:before
{
opacity: .75;
color: black;
}

View File

@ -0,0 +1 @@
@charset 'UTF-8';.slick-dots,.slick-next,.slick-prev{position:absolute;display:block;padding:0}.slick-dots li button:before,.slick-next:before,.slick-prev:before{font-family:slick;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-loading .slick-list{background:url(../img/ajax-loader.gif) center center no-repeat #fff}@font-face{font-family:slick;font-weight:400;font-style:normal;src:url(../webfonts/slick.eot);src:url(../webfonts/slick.eot?#iefix) format('embedded-opentype'),url(../webfonts/slick.woff) format('woff'),url(../webfonts/slick.ttf) format('truetype'),url(../webfonts/slick.svg#slick) format('svg')}.slick-next,.slick-prev{font-size:0;line-height:0;top:50%;width:20px;height:20px;-webkit-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%);cursor:pointer;color:transparent;border:none;outline:0;background:0 0}.slick-next:focus,.slick-next:hover,.slick-prev:focus,.slick-prev:hover{color:transparent;outline:0;background:0 0}.slick-next:focus:before,.slick-next:hover:before,.slick-prev:focus:before,.slick-prev:hover:before{opacity:1}.slick-next.slick-disabled:before,.slick-prev.slick-disabled:before{opacity:.25}.slick-next:before,.slick-prev:before{font-size:20px;line-height:1;opacity:.75;color:#fff}.slick-prev{left:-25px}[dir=rtl] .slick-prev{right:-25px;left:auto}.slick-prev:before{content:'←'}.slick-next:before,[dir=rtl] .slick-prev:before{content:'→'}.slick-next{right:-25px}[dir=rtl] .slick-next{right:auto;left:-25px}[dir=rtl] .slick-next:before{content:'←'}.slick-dotted.slick-slider{margin-bottom:30px}.slick-dots{bottom:-25px;width:100%;margin:0;list-style:none;text-align:center}.slick-dots li{position:relative;display:inline-block;width:20px;height:20px;margin:0 5px;padding:0;cursor:pointer}.slick-dots li button{font-size:0;line-height:0;display:block;width:20px;height:20px;padding:5px;cursor:pointer;color:transparent;border:0;outline:0;background:0 0}.slick-dots li button:focus,.slick-dots li button:hover{outline:0}.slick-dots li button:focus:before,.slick-dots li button:hover:before{opacity:1}.slick-dots li button:before{font-size:6px;line-height:20px;position:absolute;top:0;left:0;width:20px;height:20px;content:'•';text-align:center;opacity:.25;color:#000}.slick-dots li.slick-active button:before{opacity:.75;color:#000}

View File

@ -0,0 +1,2 @@
.slick-slider{position:relative;display:block;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.slick-list{position:relative;display:block;overflow:hidden;margin:0;padding:0}.slick-list:focus{outline:0}.slick-list.dragging{cursor:pointer;cursor:hand}.slick-slider .slick-list,.slick-slider .slick-track{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slick-track{position:relative;top:0;left:0;display:block;margin-left:auto;margin-right:auto}.slick-track:after,.slick-track:before{display:table;content:''}.slick-track:after{clear:both}.slick-loading .slick-track{visibility:hidden}.slick-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .slick-slide{float:right}.slick-slide img{display:block}.slick-slide.slick-loading img{display:none}.slick-slide.dragging img{pointer-events:none}.slick-initialized .slick-slide{display:block}.slick-loading .slick-slide{visibility:hidden}.slick-vertical .slick-slide{display:block;height:auto;border:1px solid transparent}.slick-arrow.slick-hidden{display:none}
/*# sourceMappingURL=slick.min.css.map */

View File

@ -0,0 +1,191 @@
/*
TemplateMo 559 Zay Shop
https://templatemo.com/tm-559-zay-shop
---------------------------------------------
Table of contents
------------------------------------------------
1. Typography
2. General
3. Nav
4. Hero Carousel
5. Accordion
6. Shop
7. Product
8. Carousel Hero
9. Carousel Brand
10. Services
11. Contact map
12. Footer
13. Small devices (landscape phones, 576px and up)
14. Medium devices (tablets, 768px and up)
15. Large devices (desktops, 992px and up)
16. Extra large devices (large desktops, 1200px and up)
--------------------------------------------- */
/* Typography */
body, ul, li, p, a, label, input, div {
font-family: 'Roboto', sans-serif;
font-size: 18px !important;
font-weight: 300 !important;
}
.h1 {
font-family: 'Roboto', sans-serif;
font-size: 48px !important;
font-weight: 200 !important;
}
.h2 {
font-family: 'Roboto', sans-serif;
font-size: 30px !important;
font-weight: 300;
}
.h3 {
font-family: 'Roboto', sans-serif;
font-size: 22px !important;
}
/* General */
.logo { font-weight: 500 !important;}
.text-warning { color: #ede861 !important;}
.text-muted { color: #bcbcbc !important;}
.text-success { color: #59ab6e !important;}
.text-light { color: #cfd6e1 !important;}
.bg-dark { background-color: #212934 !important;}
.bg-light { background-color: #e9eef5 !important;}
.bg-black { background-color: #1d242d !important;}
.bg-success { background-color: #59ab6e !important;}
.btn-success {
background-color: #59ab6e !important;
border-color: #56ae6c !important;
}
.pagination .page-link:hover {color: #000;}
.pagination .page-link:hover, .pagination .page-link.active {
background-color: #69bb7e;
color: #fff;
}
/* Nav */
#templatemo_nav_top { min-height: 40px;}
#templatemo_nav_top * { font-size: .9em !important;}
#templatemo_main_nav a { color: #212934;}
#templatemo_main_nav a:hover { color: #69bb7e;}
#templatemo_main_nav .navbar .nav-icon { margin-right: 20px;}
/* Hero Carousel */
#template-mo-zay-hero-carousel { background: #efefef !important;}
/* Accordion */
.templatemo-accordion a { color: #000;}
.templatemo-accordion a:hover { color: #333d4a;}
/* Shop */
.shop-top-menu a:hover { color: #69bb7e !important;}
/* Product */
.product-wap { box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.10);}
.product-wap .product-color-dot.color-dot-red { background:#f71515;}
.product-wap .product-color-dot.color-dot-blue { background:#6db4fe;}
.product-wap .product-color-dot.color-dot-black { background:#000000;}
.product-wap .product-color-dot.color-dot-light { background:#e0e0e0;}
.product-wap .product-color-dot.color-dot-green { background:#0bff7e;}
.card.product-wap .card .product-overlay {
background: rgba(0,0,0,.2);
visibility: hidden;
opacity: 0;
transition: .3s;
}
.card.product-wap:hover .card .product-overlay {
visibility: visible;
opacity: 1;
}
.card.product-wap a { color: #000;}
#carousel-related-product .slick-slide:focus { outline: none !important;}
#carousel-related-product .slick-dots li button:before {
font-size: 15px;
margin-top: 20px;
}
/* Brand */
.brand-img {
filter: grayscale(100%);
opacity: 0.5;
transition: .5s;
}
.brand-img:hover {
filter: grayscale(0%);
opacity: 1;
}
/* Carousel Hero */
#template-mo-zay-hero-carousel .carousel-indicators li {
margin-top: -50px;
background-color: #59ab6e;
}
#template-mo-zay-hero-carousel .carousel-control-next i,
#template-mo-zay-hero-carousel .carousel-control-prev i {
color: #59ab6e !important;
font-size: 2.8em !important;
}
/* Carousel Brand */
.tempaltemo-carousel .h1 {
font-size: .5em !important;
color: #000 !important;
}
/* Services */
.services-icon-wap {transition: .3s;}
.services-icon-wap:hover, .services-icon-wap:hover i {color: #fff;}
.services-icon-wap:hover {background: #69bb7e;}
/* Contact map */
.leaflet-control a, .leaflet-control { font-size: 10px !important;}
.form-control { border: 1px solid #e8e8e8;}
/* Footer */
#tempaltemo_footer a { color: #dcdde1;}
#tempaltemo_footer a:hover { color: #68bb7d;}
#tempaltemo_footer ul.footer-link-list li { padding-top: 10px;}
#tempaltemo_footer ul.footer-icons li {
width: 2.6em;
height: 2.6em;
line-height: 2.6em;
}
#tempaltemo_footer ul.footer-icons li:hover {
background-color: #cfd6e1;
transition: .5s;
}
#tempaltemo_footer ul.footer-icons li:hover i {
color: #212934;
transition: .5s;
}
#tempaltemo_footer .border-light { border-color: #2d343f !important;}
/*
// Extra small devices (portrait phones, less than 576px)
// No media query since this is the default in Bootstrap
*/
/* Small devices (landscape phones, 576px and up)*/
.product-wap .h3, .product-wap li, .product-wap i, .product-wap p {
font-size: 12px !important;
}
.product-wap .product-color-dot {
width: 6px;
height: 6px;
}
@media (min-width: 576px) {
.tempaltemo-carousel .h1 { font-size: 1em !important;}
}
/*// Medium devices (tablets, 768px and up)*/
@media (min-width: 768px) {
#templatemo_main_nav .navbar-nav {max-width: 450px;}
}
/* Large devices (desktops, 992px and up)*/
@media (min-width: 992px) {
#templatemo_main_nav .navbar-nav {max-width: 550px;}
#template-mo-zay-hero-carousel .carousel-item {min-height: 30rem !important;}
.product-wap .h3, .product-wap li, .product-wap i, .product-wap p {font-size: 18px !important;}
.product-wap .product-color-dot {
width: 12px;
height: 12px;
}
}
/* Extra large devices (large desktops, 1200px and up)*/
@media (min-width: 1200px) {}

View File

@ -0,0 +1 @@
.h1,.h2,.h3,a,body,div,input,label,li,p,ul{font-family:Roboto,sans-serif}a,body,div,input,label,li,p,ul{font-size:18px!important;font-weight:300!important}.h1{font-size:48px!important;font-weight:200!important}.h2{font-size:30px!important;font-weight:300}.h3{font-size:22px!important}.logo{font-weight:500!important}.text-warning{color:#ede861!important}.text-muted{color:#bcbcbc!important}.text-success{color:#59ab6e!important}.text-light{color:#cfd6e1!important}.bg-dark{background-color:#212934!important}.bg-light{background-color:#e9eef5!important}.bg-black{background-color:#1d242d!important}.bg-success,.btn-success{background-color:#59ab6e!important}.btn-success{border-color:#56ae6c!important}.pagination .page-link.active,.pagination .page-link:hover{background-color:#69bb7e;color:#fff}#templatemo_nav_top{min-height:40px}#templatemo_nav_top *{font-size:.9em!important}#templatemo_main_nav a{color:#212934}#templatemo_main_nav a:hover{color:#69bb7e}#templatemo_main_nav .navbar .nav-icon{margin-right:20px}#template-mo-zay-hero-carousel{background:#efefef!important}.templatemo-accordion a{color:#000}.templatemo-accordion a:hover{color:#333d4a}.shop-top-menu a:hover{color:#69bb7e!important}.product-wap{box-shadow:0 5px 10px 0 rgba(0,0,0,.1)}.product-wap .product-color-dot.color-dot-red{background:#f71515}.product-wap .product-color-dot.color-dot-blue{background:#6db4fe}.product-wap .product-color-dot.color-dot-black{background:#000}.product-wap .product-color-dot.color-dot-light{background:#e0e0e0}.product-wap .product-color-dot.color-dot-green{background:#0bff7e}.card.product-wap .card .product-overlay{background:rgba(0,0,0,.2);visibility:hidden;opacity:0;transition:.3s}.card.product-wap:hover .card .product-overlay{visibility:visible;opacity:1}.card.product-wap a{color:#000}#carousel-related-product .slick-slide:focus{outline:0!important}#carousel-related-product .slick-dots li button:before{font-size:15px;margin-top:20px}.brand-img{filter:grayscale(100%);opacity:.5;transition:.5s}.brand-img:hover{filter:grayscale(0);opacity:1}#template-mo-zay-hero-carousel .carousel-indicators li{margin-top:-50px;background-color:#59ab6e}#template-mo-zay-hero-carousel .carousel-control-next i,#template-mo-zay-hero-carousel .carousel-control-prev i{color:#59ab6e!important;font-size:2.8em!important}.tempaltemo-carousel .h1{font-size:.5em!important;color:#000!important}.services-icon-wap{transition:.3s}.services-icon-wap:hover,.services-icon-wap:hover i{color:#fff}.services-icon-wap:hover{background:#69bb7e}.leaflet-control,.leaflet-control a{font-size:10px!important}.form-control{border:1px solid #e8e8e8}#tempaltemo_footer a{color:#dcdde1}#tempaltemo_footer a:hover{color:#68bb7d}#tempaltemo_footer ul.footer-link-list li{padding-top:10px}#tempaltemo_footer ul.footer-icons li{width:2.6em;height:2.6em;line-height:2.6em}#tempaltemo_footer ul.footer-icons li:hover{background-color:#cfd6e1;transition:.5s}#tempaltemo_footer ul.footer-icons li:hover i{color:#212934;transition:.5s}#tempaltemo_footer .border-light{border-color:#2d343f!important}.product-wap .h3,.product-wap i,.product-wap li,.product-wap p{font-size:12px!important}.product-wap .product-color-dot{width:6px;height:6px}@media (min-width:576px){.tempaltemo-carousel .h1{font-size:1em!important}}@media (min-width:768px){#templatemo_main_nav .navbar-nav{max-width:450px}}@media (min-width:992px){#templatemo_main_nav .navbar-nav{max-width:550px}#template-mo-zay-hero-carousel .carousel-item{min-height:30rem!important}.product-wap .h3,.product-wap i,.product-wap li,.product-wap p{font-size:18px!important}.product-wap .product-color-dot{width:12px;height:12px}}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,57 @@
/*
TemplateMo 559 Zay Shop
https://templatemo.com/tm-559-zay-shop
*/
'use strict';
$(document).ready(function() {
// Accordion
var all_panels = $('.templatemo-accordion > li > ul').hide();
$('.templatemo-accordion > li > a').click(function() {
console.log('Hello world!');
var target = $(this).next();
if(!target.hasClass('active')){
all_panels.removeClass('active').slideUp();
target.addClass('active').slideDown();
}
return false;
});
// End accordion
// Product detail
$('.product-links-wap a').click(function(){
var this_src = $(this).children('img').attr('src');
$('#product-detail').attr('src',this_src);
return false;
});
$('#btn-minus').click(function(){
var val = $("#var-value").html();
val = (val=='1')?val:val-1;
$("#var-value").html(val);
$("#product-quanity").val(val);
return false;
});
$('#btn-plus').click(function(){
var val = $("#var-value").html();
val++;
$("#var-value").html(val);
$("#product-quanity").val(val);
return false;
});
$('.btn-size').click(function(){
var this_val = $(this).html();
$("#product-size").val(this_val);
$(".btn-size").removeClass('btn-secondary');
$(".btn-size").addClass('btn-success');
$(this).removeClass('btn-success');
$(this).addClass('btn-secondary');
return false;
});
// End roduct detail
});

View File

@ -0,0 +1 @@
"use strict";$(document).ready(function(){var t=$(".templatemo-accordion > li > ul").hide();$(".templatemo-accordion > li > a").click(function(){var a=$(this).next();return a.hasClass("active")||(t.removeClass("active").slideUp(),a.addClass("active").slideDown()),!1}),$(".product-links-wap a").click(function(){var t=$(this).children("img").attr("src");return $("#product-detail").attr("src",t),!1}),$("#btn-minus").click(function(){var t=$("#var-value").html();return t="1"==t?t:t-1,$("#var-value").html(t),$("#product-quanity").val(t),!1}),$("#btn-plus").click(function(){var t=$("#var-value").html();return t++,$("#var-value").html(t),$("#product-quanity").val(t),!1}),$(".btn-size").click(function(){var t=$(this).html();return $("#product-size").val(t),$(".btn-size").removeClass("btn-secondary"),$(".btn-size").addClass("btn-success"),$(this).removeClass("btn-success"),$(this).addClass("btn-secondary"),!1})});

Some files were not shown because too many files have changed in this diff Show More