diff --git a/app/admin/controller/Cms/Demand/DemandController.php b/app/admin/controller/Cms/Demand/DemandController.php new file mode 100644 index 0000000..a07bf19 --- /dev/null +++ b/app/admin/controller/Cms/Demand/DemandController.php @@ -0,0 +1,180 @@ +order('id', 'desc') + ->select(); + + if (!$demandList) { + return json([ + 'code' => 200, + 'msg' => 'success', + 'list' => [], + ]); + } + + return json([ + 'code' => 200, + 'msg' => 'success', + 'list' => $demandList, + ]); + } + + /** + * 增加需求 + * @return Json + */ + public function addDemand(): Json + { + try { + $data = Request::only(['title', 'desc', 'applicant', 'status']); + + // 验证数据 + if (empty($data['title']) || empty($data['desc'])) { + return json([ + 'code' => 400, + 'msg' => '标题和描述不能为空', + ]); + } + + // 创建需求 + $demand = Demand::create([ + 'title' => $data['title'], + 'desc' => $data['desc'], + 'applicant' => $data['applicant'] ?? '', + 'status' => $data['status'] ?? 'pending', + ]); + + return json([ + 'code' => 200, + 'msg' => '添加成功', + 'data' => $demand, + ]); + } catch (\Exception $e) { + return json([ + 'code' => 500, + 'msg' => '添加失败:' . $e->getMessage(), + ]); + } + } + + /** + * 编辑需求 + * @return Json + */ + public function editDemand(): Json + { + try { + $id = Request::param('id'); + $data = Request::only(['title', 'desc', 'applicant', 'status']); + + // 验证数据 + if (empty($id)) { + return json([ + 'code' => 400, + 'msg' => '需求ID不能为空', + ]); + } + + if (empty($data['title']) || empty($data['desc'])) { + return json([ + 'code' => 400, + 'msg' => '标题和描述不能为空', + ]); + } + + // 查找需求 + $demand = Demand::find($id); + if (!$demand) { + return json([ + 'code' => 404, + 'msg' => '需求不存在', + ]); + } + + // 更新需求 + $demand->save([ + 'title' => $data['title'], + 'desc' => $data['desc'], + 'applicant' => $data['applicant'] ?? '', + 'status' => $data['status'] ?? 'pending', + ]); + + return json([ + 'code' => 200, + 'msg' => '编辑成功', + 'data' => $demand, + ]); + } catch (\Exception $e) { + return json([ + 'code' => 500, + 'msg' => '编辑失败:' . $e->getMessage(), + ]); + } + } + + /** + * 删除需求 + * @return Json + */ + public function deleteDemand(): Json + { + try { + $id = Request::param('id'); + + // 验证数据 + if (empty($id)) { + return json([ + 'code' => 400, + 'msg' => '需求ID不能为空', + ]); + } + + // 查找需求 + $demand = Demand::find($id); + if (!$demand) { + return json([ + 'code' => 404, + 'msg' => '需求不存在', + ]); + } + + // 软删除 + $demand->delete(); + + return json([ + 'code' => 200, + 'msg' => '删除成功', + ]); + } catch (\Exception $e) { + return json([ + 'code' => 500, + 'msg' => '删除失败:' . $e->getMessage(), + ]); + } + } +} diff --git a/app/admin/controller/ThemeController.php b/app/admin/controller/ThemeController.php new file mode 100644 index 0000000..2328961 --- /dev/null +++ b/app/admin/controller/ThemeController.php @@ -0,0 +1,120 @@ +themeService = new ThemeService(); + } + + /** + * 获取模板列表(后台管理) + * @return \think\response\Json + */ + public function index() + { + $themes = $this->themeService->getThemeList(); + $currentTheme = $this->themeService->getCurrentTheme(); + + return json([ + 'code' => 200, + 'msg' => 'success', + 'data' => [ + 'list' => $themes, + 'currentTheme' => $currentTheme + ] + ]); + } + + /** + * 切换模板 + * @return \think\response\Json + */ + public function switch() + { + $themeKey = Request::post('theme_key', ''); + + if (empty($themeKey)) { + return json([ + 'code' => 400, + 'msg' => '模板标识不能为空' + ]); + } + + $result = $this->themeService->switchTheme($themeKey); + + if ($result) { + return json([ + 'code' => 200, + 'msg' => '切换成功' + ]); + } + + return json([ + 'code' => 400, + 'msg' => '切换失败,模板不存在' + ]); + } + + /** + * 获取模板字段数据 + * @return \think\response\Json + */ + public function getData() + { + $themeKey = Request::get('theme_key', ''); + + $themeData = $this->themeService->getThemeData($themeKey ?: null); + + return json([ + 'code' => 200, + 'msg' => 'success', + 'data' => $themeData + ]); + } + + /** + * 保存模板字段数据 + * @return \think\response\Json + */ + public function saveData() + { + $themeKey = Request::post('theme_key', ''); + $fieldKey = Request::post('field_key', ''); + $fieldValue = Request::post('field_value', ''); + + if (empty($themeKey) || empty($fieldKey)) { + return json([ + 'code' => 400, + 'msg' => '参数不完整' + ]); + } + + $result = $this->themeService->saveThemeField($themeKey, $fieldKey, $fieldValue); + + if ($result) { + return json([ + 'code' => 200, + 'msg' => '保存成功' + ]); + } + + return json([ + 'code' => 400, + 'msg' => '保存失败' + ]); + } +} diff --git a/app/admin/route/routes/demand.php b/app/admin/route/routes/demand.php new file mode 100644 index 0000000..b4bc1b1 --- /dev/null +++ b/app/admin/route/routes/demand.php @@ -0,0 +1,8 @@ +themeService = new ThemeService(); + } + public function index() { return view('index/index'); } + /** + * 前端初始化接口 - 返回当前模板和填充数据 + * @return \think\response\Json + */ + public function init() + { + // 直接返回默认模板数据 + return json([ + 'code' => 200, + 'msg' => 'success', + 'data' => [ + 'theme_key' => 'default', + 'theme_path' => '/themes/default/index.html', + 'data' => [ + 'site_name' => '企业官网' + ] + ] + ]); + } + /** * 获取日志列表 */ diff --git a/app/index/route/app.php b/app/index/route/app.php index d9e3f03..043f905 100644 --- a/app/index/route/app.php +++ b/app/index/route/app.php @@ -5,6 +5,9 @@ use think\facade\Route; Route::get('/', 'app\index\controller\Index@index'); Route::get('index/index', 'app\index\controller\Index@index'); +// --- 模板初始化接口 --- +Route::get('init', 'app\index\controller\Index@init'); + // --- 前端底部数据路由 --- Route::get('footerdata', 'app\index\controller\Index@getFooterData'); diff --git a/app/model/Cms/Demand.php b/app/model/Cms/Demand.php new file mode 100644 index 0000000..7a90997 --- /dev/null +++ b/app/model/Cms/Demand.php @@ -0,0 +1,44 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\Cms; + +use think\Model; +use think\model\concern\SoftDelete; + +/** + * 文章分类模型 + */ +class Demand extends Model +{ + // 启用软删除 + use SoftDelete; + + // 数据库表名 + protected $name = 'mete_demand'; + + // 字段类型转换 + protected $type = [ + 'id' => 'integer', + 'tid' => 'integer', + 'title' => 'string', + 'desc' => 'string', + 'applicant' => 'string', + 'phone' => 'string', + 'status' => 'integer', + 'create_time' => 'datetime', + 'update_time' => 'datetime', + 'delete_time' => 'datetime', + ]; + + +} + diff --git a/app/model/Cms/DemandCategory.php b/app/model/Cms/DemandCategory.php new file mode 100644 index 0000000..964c688 --- /dev/null +++ b/app/model/Cms/DemandCategory.php @@ -0,0 +1,43 @@ + +// +---------------------------------------------------------------------- + +namespace app\model\Cms; + +use think\Model; +use think\model\concern\SoftDelete; + +/** + * 文章分类模型 + */ +class DemandCategory extends Model +{ + // 启用软删除 + use SoftDelete; + + // 数据库表名 + protected $name = 'mete_demand_category'; + + // 字段类型转换 + protected $type = [ + 'id' => 'integer', + 'title' => 'string', + 'desc' => 'string', + 'applicant' => 'string', + 'phone' => 'string', + 'status' => 'integer', + 'create_time' => 'datetime', + 'update_time' => 'datetime', + 'delete_time' => 'datetime', + ]; + + +} + diff --git a/app/service/ThemeService.php b/app/service/ThemeService.php new file mode 100644 index 0000000..2776b19 --- /dev/null +++ b/app/service/ThemeService.php @@ -0,0 +1,258 @@ +themesPath = root_path() . 'public' . DIRECTORY_SEPARATOR . 'themes'; + } + + /** + * 获取所有可用模板列表 + * @return array + */ + public function getThemeList(): array + { + $themes = []; + $dirs = $this->scanThemeDirs(); + + foreach ($dirs as $dir) { + $config = $this->readThemeConfig($dir); + $preview = $this->getThemePreview($dir); + + $themes[] = [ + 'key' => $dir, + 'name' => $config['name'] ?? $dir, + 'description'=> $config['description'] ?? '', + 'version' => $config['version'] ?? '1.0.0', + 'author' => $config['author'] ?? '', + 'preview' => $preview, + 'path' => '/themes/' . $dir . '/index.html', + 'fields' => $config['fields'] ?? [], + ]; + } + + return $themes; + } + + /** + * 扫描模板目录 + * @return array + */ + private function scanThemeDirs(): array + { + $dirs = []; + + if (!is_dir($this->themesPath)) { + return $dirs; + } + + $items = scandir($this->themesPath); + foreach ($items as $item) { + if ($item === '.' || $item === '..') { + continue; + } + + $fullPath = $this->themesPath . DIRECTORY_SEPARATOR . $item; + if (is_dir($fullPath) && is_file($fullPath . DIRECTORY_SEPARATOR . 'index.html')) { + $dirs[] = $item; + } + } + + return $dirs; + } + + /** + * 读取模板配置文件 + * @param string $themeDir + * @return array + */ + private function readThemeConfig(string $themeDir): array + { + $configPath = $this->themesPath . DIRECTORY_SEPARATOR . $themeDir . DIRECTORY_SEPARATOR . 'config.json'; + + if (!is_file($configPath)) { + return []; + } + + $content = file_get_contents($configPath); + $config = json_decode($content, true); + + return $config ?? []; + } + + /** + * 获取模板预览图 + * @param string $themeDir + * @return string + */ + private function getThemePreview(string $themeDir): string + { + $previewPath = '/themes/' . $themeDir . '/preview.png'; + + // 如果 preview.png 不存在,使用默认占位图 + $fullPath = $this->themesPath . DIRECTORY_SEPARATOR . $themeDir . DIRECTORY_SEPARATOR . 'preview.png'; + if (!is_file($fullPath)) { + return 'https://picsum.photos/300/200?random=' . ord($themeDir[0]); + } + + return $previewPath; + } + + /** + * 获取当前激活的模板Key + * @return string + */ + public function getCurrentTheme(): string + { + try { + $config = Db::name('mete_template_site_config') + ->where('key', 'current_theme') + ->where('delete_time', null) + ->find(); + return $config['value'] ?? 'default'; + } catch (\Exception $e) { + return 'default'; + } + } + + /** + * 切换当前模板 + * @param string $themeKey + * @return bool + */ + public function switchTheme(string $themeKey): bool + { + // 验证模板是否存在 + $themes = $this->getThemeList(); + $exists = false; + foreach ($themes as $theme) { + if ($theme['key'] === $themeKey) { + $exists = true; + break; + } + } + + if (!$exists) { + return false; + } + + try { + // 查找或创建配置记录 + $config = Db::name('mete_template_site_config') + ->where('key', 'current_theme') + ->where('delete_time', null) + ->find(); + + $now = date('Y-m-d H:i:s'); + + if ($config) { + Db::name('mete_template_site_config')->where('id', $config['id'])->update([ + 'value' => $themeKey, + 'update_time' => $now + ]); + } else { + Db::name('mete_template_site_config')->insert([ + 'key' => 'current_theme', + 'value' => $themeKey, + 'create_time' => $now, + 'update_time' => $now + ]); + } + + return true; + } catch (\Exception $e) { + return false; + } + } + + /** + * 获取模板数据(用于前端渲染) + * @param string|null $themeKey + * @return array + */ + public function getThemeData(?string $themeKey = null): array + { + $themeKey = $themeKey ?? $this->getCurrentTheme(); + + try { + $themeData = Db::name('mete_template_theme_data') + ->where('theme_key', $themeKey) + ->where('delete_time', null) + ->select() + ->toArray(); + + $data = []; + foreach ($themeData as $item) { + $data[$item['field_key']] = $item['field_value']; + } + + return [ + 'theme_key' => $themeKey, + 'theme_path' => '/themes/' . $themeKey . '/index.html', + 'data' => $data + ]; + } catch (\Exception $e) { + return [ + 'theme_key' => $themeKey, + 'theme_path' => '/themes/' . $themeKey . '/index.html', + 'data' => [] + ]; + } + } + + /** + * 保存模板字段数据 + * @param string $themeKey + * @param string $fieldKey + * @param mixed $fieldValue + * @return bool + */ + public function saveThemeField(string $themeKey, string $fieldKey, $fieldValue): bool + { + try { + $existing = Db::name('mete_template_theme_data') + ->where('theme_key', $themeKey) + ->where('field_key', $fieldKey) + ->where('delete_time', null) + ->find(); + + $value = is_array($fieldValue) ? json_encode($fieldValue, JSON_UNESCAPED_UNICODE) : $fieldValue; + $now = date('Y-m-d H:i:s'); + + if ($existing) { + Db::name('mete_template_theme_data') + ->where('id', $existing['id']) + ->update([ + 'field_value' => $value, + 'update_time' => $now + ]); + } else { + Db::name('mete_template_theme_data')->insert([ + 'theme_key' => $themeKey, + 'field_key' => $fieldKey, + 'field_value' => $value, + 'create_time' => $now, + 'update_time' => $now + ]); + } + + return true; + } catch (\Exception $e) { + return false; + } + } +} diff --git a/public/themes/default/config.json b/public/themes/default/config.json new file mode 100644 index 0000000..b99497b --- /dev/null +++ b/public/themes/default/config.json @@ -0,0 +1,13 @@ +{ + "name": "默认模板", + "description": "标准企业官网模板,适用于各类企业展示", + "version": "1.0.0", + "author": "System", + "fields": { + "site_name": "网站名称", + "banner": "轮播图列表", + "news": "新闻列表", + "solutions": "解决方案", + "partners": "合作伙伴" + } +} diff --git a/public/themes/default/index.html b/public/themes/default/index.html new file mode 100644 index 0000000..00239f1 --- /dev/null +++ b/public/themes/default/index.html @@ -0,0 +1,82 @@ + + +
+ + +这里是新闻内容...
+详细描述...
+