diff --git a/app/admin/controller/Cms/Services/ServicesController.php b/app/admin/controller/Cms/Services/ServicesController.php new file mode 100644 index 0000000..0f5cf84 --- /dev/null +++ b/app/admin/controller/Cms/Services/ServicesController.php @@ -0,0 +1,251 @@ +request->param('page', 1); + $limit = (int)$this->request->param('limit', 10); + $keyword = $this->request->param('keyword', ''); + $status = $this->request->param('status', ''); + + $query = Services::where('delete_time', null) + ->where('tid', $this->getTenantId()); + + // 关键词搜索 + if (!empty($keyword)) { + $query->where('name', 'like', '%' . $keyword . '%'); + } + + // 状态筛选 + if ($status !== '') { + $query->where('status', (int)$status); + } + + $total = $query->count(); + $list = $query->order('sort', 'asc') + ->order('id', 'desc') + ->page($page, $limit) + ->select() + ->toArray(); + + return json([ + 'code' => 200, + 'msg' => 'success', + 'data' => [ + 'list' => $list, + 'total' => $total + ] + ]); + } catch (\Exception $e) { + return json([ + 'code' => 500, + 'msg' => '获取失败:' . $e->getMessage(), + 'data' => [] + ]); + } + } + + /** + * 添加特色服务 + * @return Json + */ + public function add(): Json + { + try { + $data = $this->request->param(); + + // 验证参数 + $this->validate($data, [ + 'name|服务名称' => 'require|max:100', + 'url|服务地址' => 'require|url|max:255', + 'sort|排序' => 'integer', + 'status|状态' => 'in:0,1' + ]); + + $service = new Services(); + $service->tid = $this->getTenantId(); + $service->title = $data['title']; + $service->url = $data['url']; + $service->thumb = $data['thumb'] ?? ''; + $service->desc = $data['desc'] ?? ''; + $service->sort = $data['sort'] ?? 0; + $service->status = $data['status'] ?? 1; + $service->create_time = date('Y-m-d H:i:s'); + $service->save(); + + $this->logSuccess('特色服务', '添加服务', ['id' => $service->id]); + + return json([ + 'code' => 200, + 'msg' => '添加成功', + 'data' => $service->toArray() + ]); + } catch (ValidateException $e) { + return json([ + 'code' => 400, + 'msg' => $e->getError() + ]); + } catch (\Exception $e) { + $this->logFail('特色服务', '添加服务', $e->getMessage()); + return json([ + 'code' => 500, + 'msg' => '添加失败:' . $e->getMessage() + ]); + } + } + + /** + * 更新特色服务 + * @param int $id + * @return Json + */ + public function update(int $id): Json + { + try { + $data = $this->request->param(); + + $service = Services::where('id', $id) + ->where('tid', $this->getTenantId()) + ->where('delete_time', null) + ->find(); + + if (!$service) { + return json([ + 'code' => 404, + 'msg' => '服务不存在' + ]); + } + + // 验证参数 + if (isset($data['name'])) { + $this->validate($data, [ + 'name|服务名称' => 'require|max:100' + ]); + } + if (isset($data['url'])) { + $this->validate($data, [ + 'url|服务地址' => 'require|url|max:255' + ]); + } + + if (isset($data['title'])) $service->title = $data['title']; + if (isset($data['url'])) $service->url = $data['url']; + if (isset($data['thumb'])) $service->thumb = $data['thumb']; + if (isset($data['desc'])) $service->desc = $data['desc']; + if (isset($data['sort'])) $service->sort = $data['sort']; + if (isset($data['status'])) $service->status = $data['status']; + $service->update_time = date('Y-m-d H:i:s'); + $service->save(); + + $this->logSuccess('特色服务', '更新服务', ['id' => $id]); + + return json([ + 'code' => 200, + 'msg' => '更新成功', + 'data' => $service->toArray() + ]); + } catch (ValidateException $e) { + return json([ + 'code' => 400, + 'msg' => $e->getError() + ]); + } catch (\Exception $e) { + $this->logFail('特色服务', '更新服务', $e->getMessage()); + return json([ + 'code' => 500, + 'msg' => '更新失败:' . $e->getMessage() + ]); + } + } + + /** + * 删除特色服务 + * @param int $id + * @return Json + */ + public function delete(int $id): Json + { + try { + $service = Services::where('id', $id) + ->where('tid', $this->getTenantId()) + ->where('delete_time', null) + ->find(); + + if (!$service) { + return json([ + 'code' => 404, + 'msg' => '服务不存在' + ]); + } + + $service->delete(); + + $this->logSuccess('特色服务', '删除服务', ['id' => $id]); + + return json([ + 'code' => 200, + 'msg' => '删除成功' + ]); + } catch (\Exception $e) { + $this->logFail('特色服务', '删除服务', $e->getMessage()); + return json([ + 'code' => 500, + 'msg' => '删除失败:' . $e->getMessage() + ]); + } + } + + /** + * 批量删除特色服务 + * @return Json + */ + public function batchDelete(): Json + { + try { + $ids = $this->request->param('ids', []); + + if (empty($ids)) { + return json([ + 'code' => 400, + 'msg' => '请选择要删除的服务' + ]); + } + + Services::whereIn('id', $ids) + ->where('tid', $this->getTenantId()) + ->where('delete_time', null) + ->update(['delete_time' => date('Y-m-d H:i:s')]); + + $this->logSuccess('特色服务', '批量删除服务', ['ids' => $ids]); + + return json([ + 'code' => 200, + 'msg' => '批量删除成功' + ]); + } catch (\Exception $e) { + $this->logFail('特色服务', '批量删除服务', $e->getMessage()); + return json([ + 'code' => 500, + 'msg' => '批量删除失败:' . $e->getMessage() + ]); + } + } +} diff --git a/app/admin/route/routes/services.php b/app/admin/route/routes/services.php new file mode 100644 index 0000000..4276de9 --- /dev/null +++ b/app/admin/route/routes/services.php @@ -0,0 +1,8 @@ +header('Referer'); - if ($referer) { - $host = parse_url($referer, PHP_URL_HOST); - } else { - // 否则使用当前访问域名 - $host = $request->host(true); - } // 查询域名对应的租户ID $tenantDomain = Db::name('mete_tenant_domain') - ->where('full_domain', $host) + ->where('full_domain', $baseUrl) ->where('status', 1) ->whereNull('delete_time') ->find(); diff --git a/app/index/controller/Article/NewsCenterController.php b/app/index/controller/Article/NewsCenterController.php index 5826fe5..91f8352 100644 --- a/app/index/controller/Article/NewsCenterController.php +++ b/app/index/controller/Article/NewsCenterController.php @@ -24,7 +24,12 @@ class NewsCenterController extends BaseController */ public function getCenterNews(): Json { - // 从 BaseController 获取当前租户ID + $baseUrl = $this->request->get('baseUrl', ''); + + if (!empty($baseUrl)) { + $this->tenantId = BaseController::getTenantIdByDomain($baseUrl); + } + $tid = $this->getTenantId(); if (empty($tid)) { diff --git a/app/index/controller/BannerController.php b/app/index/controller/BannerController.php index 01ce7e3..e750ae4 100644 --- a/app/index/controller/BannerController.php +++ b/app/index/controller/BannerController.php @@ -17,9 +17,14 @@ class BannerController extends BaseController * 获取 Banner 列表 * @return Json */ - public function getBanners(): Json + public function getBanners() { - // 从 BaseController 获取当前租户ID + $baseUrl = $this->request->get('baseUrl', ''); + + if (!empty($baseUrl)) { + $this->tenantId = BaseController::getTenantIdByDomain($baseUrl); + } + $tid = $this->getTenantId(); if (empty($tid)) { diff --git a/app/index/controller/Index.php b/app/index/controller/Index.php index da279d2..d6f7dd4 100644 --- a/app/index/controller/Index.php +++ b/app/index/controller/Index.php @@ -15,6 +15,7 @@ use think\facade\Env; use think\facade\Request; use app\model\Cms\TemplateSiteConfig; use app\model\Cms\Friendlink; +use app\model\Tenant\Tenant; class Index extends BaseController { @@ -444,9 +445,15 @@ class Index extends BaseController */ public function getHomeData() { + $baseUrl = Request::param('baseUrl', ''); + + if (empty($baseUrl)) { + return json(['code' => 400, 'msg' => '缺少 baseUrl 参数']); + } + try { // 1. 通过域名获取租户ID - $tid = BaseController::getTenantIdByDomain(); + $tid = BaseController::getTenantIdByDomain($baseUrl); if (empty($tid)) { return json([ @@ -470,12 +477,20 @@ class Index extends BaseController ->select() ->toArray(); + // 获取联系方式 + $contact = Tenant::where('id', $tid) + ->where('status', 1) + ->where('delete_time', null) + ->field('contact_phone,contact_email,address,worktime') + ->find(); + // 4. 合并返回 return json([ 'code' => 200, 'msg' => 'success', 'data' => [ 'normal' => $normalInfos ?: (object) [], + 'contact' => $contact ?: (object) [], 'links' => $friendlinkList ] ]); diff --git a/app/model/Cms/Services.php b/app/model/Cms/Services.php new file mode 100644 index 0000000..ef1a5d5 --- /dev/null +++ b/app/model/Cms/Services.php @@ -0,0 +1,43 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\Cms; + +use think\Model; +use think\model\concern\SoftDelete; + +/** + * 特色服务模型 + */ +class Services extends Model +{ + // 启用软删除 + use SoftDelete; + + // 数据库表名 + protected $name = 'mete_apps_cms_services'; + + // 字段类型转换 + protected $type = [ + 'id' => 'integer', + 'tid' => 'integer', + 'title' => 'string', + 'desc' => 'string', + 'thumb' => 'string', + 'url' => 'string', + 'sort' => 'integer', + 'create_time' => 'datetime', + 'update_time' => 'datetime', + 'delete_time' => 'datetime', + ]; + + +} diff --git a/public/themes/default/index.php b/public/themes/default/index.php index 06a7af3..c8e1e43 100644 --- a/public/themes/default/index.php +++ b/public/themes/default/index.php @@ -15,10 +15,10 @@ $app = new App(__DIR__ . '/../../../'); $app->initialize(); // 获取当前域名 -$host = $_SERVER['HTTP_HOST'] ?? ''; +$baseUrl = $_SERVER['HTTP_HOST']; // 查询域名对应的租户ID -$tenantDomain = TenantDomain::where('full_domain', $host) +$tenantDomain = TenantDomain::where('full_domain', $baseUrl) ->where('status', 1) ->whereNull('delete_time') ->find(); @@ -40,7 +40,7 @@ if ($tid > 0) { if (!empty($banner['image'])) { if (!preg_match('/^https?:\/\//', $banner['image'])) { $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $banner['image'] = $scheme . '://' . $host . + $banner['image'] = $scheme . '://' . $baseUrl . (strpos($banner['image'], '/') === 0 ? '' : '/') . $banner['image']; } } @@ -71,12 +71,12 @@ if ($tid > 0) { // 处理图片路径 if (!empty($article['image']) && !preg_match('/^https?:\/\//', $article['image'])) { $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $article['image'] = $scheme . '://' . $host . + $article['image'] = $scheme . '://' . $baseUrl . (strpos($article['image'], '/') === 0 ? '' : '/') . $article['image']; } if (!empty($article['thumb']) && !preg_match('/^https?:\/\//', $article['thumb'])) { $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $article['thumb'] = $scheme . '://' . $host . + $article['thumb'] = $scheme . '://' . $baseUrl . (strpos($article['thumb'], '/') === 0 ? '' : '/') . $article['thumb']; } } @@ -117,17 +117,17 @@ if ($tid > 0) { // 处理图片路径 if (!empty($companyInfo['logo']) && !preg_match('/^https?:\/\//', $companyInfo['logo'])) { $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $companyInfo['logo'] = $scheme . '://' . $host . + $companyInfo['logo'] = $scheme . '://' . $baseUrl . (strpos($companyInfo['logo'], '/') === 0 ? '' : '/') . $companyInfo['logo']; } if (!empty($companyInfo['logow']) && !preg_match('/^https?:\/\//', $companyInfo['logow'])) { $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $companyInfo['logow'] = $scheme . '://' . $host . + $companyInfo['logow'] = $scheme . '://' . $baseUrl . (strpos($companyInfo['logow'], '/') === 0 ? '' : '/') . $companyInfo['logow']; } if (!empty($companyInfo['ico']) && !preg_match('/^https?:\/\//', $companyInfo['ico'])) { $scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $companyInfo['ico'] = $scheme . '://' . $host . + $companyInfo['ico'] = $scheme . '://' . $baseUrl . (strpos($companyInfo['ico'], '/') === 0 ? '' : '/') . $companyInfo['ico']; } @@ -615,7 +615,7 @@ function stripHtml($html) const bannerContainer = document.getElementById('banner-container'); if (!bannerContainer) return; - fetch(API_BASE_URL + '/getBanners') + fetch(API_BASE_URL + '/getBanners?baseUrl=' + window.location.hostname) .then(res => res.json()) .then(result => { if (result.code !== 200 || !result.list || result.list.length === 0) { @@ -710,7 +710,7 @@ function stripHtml($html) const container = document.getElementById('friendlink-container'); if (!container) return; - fetch(API_BASE_URL + '/homeData') + fetch(API_BASE_URL + '/homeData?baseUrl=' + window.location.hostname) .then(res => res.json()) .then(result => { if (result.code !== 200 || !result.data || !result.data.links || result.data.links.length === 0) { diff --git a/public/themes/template3/assets/css/main.css b/public/themes/template3/assets/css/main.css index 8806c74..246aae9 100644 --- a/public/themes/template3/assets/css/main.css +++ b/public/themes/template3/assets/css/main.css @@ -767,9 +767,84 @@ section, } .hero h1 { - margin: 0; - font-size: 3rem; - font-weight: 700; + font-size: 52px; + font-weight: 800; + line-height: 1.2; + margin-bottom: 20px; +} + +.hero-desc { + font-size: 18px; + line-height: 1.6; + color: rgba(255, 255, 255, 0.9); + margin-bottom: 30px; + max-width: 600px; +} + +.hero-bg-img { + position: absolute !important; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: 1; +} + +.hero-container { + position: relative; + z-index: 2; +} + +.hero-content { + position: relative; + z-index: 3; +} + +.hero-image { + position: relative; + z-index: 3; +} + +.hero-image img { + position: relative !important; + width: 100%; + height: auto; + border-radius: 10px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); +} + +.hero-nav { + margin-top: 30px; + display: flex; + align-items: center; + gap: 15px; +} + +.hero-prev, +.hero-next { + width: 40px; + height: 40px; + border: 2px solid rgba(255, 255, 255, 0.5); + background: rgba(0, 0, 0, 0.3); + color: #fff; + border-radius: 50%; + cursor: pointer; + font-size: 18px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s; +} + +.hero-prev:hover, +.hero-next:hover { + background: #fff; + color: #333; +} + +.hero-indicator { + color: rgba(255, 255, 255, 0.8); + font-size: 14px; } .hero blockquote { @@ -1156,7 +1231,7 @@ section, .recent-posts .post-box .post-title { color: var(--heading-color); - font-size: 18px; + font-size: 17px; font-weight: 700; margin: 15px 0 0 0; position: relative; diff --git a/public/themes/template3/assets/css/style.css b/public/themes/template3/assets/css/style.css new file mode 100644 index 0000000..2ba6b48 --- /dev/null +++ b/public/themes/template3/assets/css/style.css @@ -0,0 +1,32 @@ +.post-title { + height: 40px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-word; +} + +.post-img { + width: 330px; + height: 160px; + object-fit: cover; +} + +.recent-posts { + background-color: #f9f9f9 !important; +} +.feature-box { + display: flex; + flex-direction: column; + align-items: center; +} +.feature-box img { + width: 150px; + object-fit: cover; +} +.feature-box img:hover { + transform: scale(1.1); + transition: all 0.3s ease-in-out; +} \ No newline at end of file diff --git a/public/themes/template3/footer.php b/public/themes/template3/footer.php index 7aa8869..6f00106 100644 --- a/public/themes/template3/footer.php +++ b/public/themes/template3/footer.php @@ -1,9 +1,21 @@ - + +
+ + + @@ -18,4 +30,4 @@