diff --git a/app/admin/controller/v1/SiteConfig.php b/app/admin/controller/v1/SiteConfig.php new file mode 100644 index 00000000..957d246a --- /dev/null +++ b/app/admin/controller/v1/SiteConfig.php @@ -0,0 +1,163 @@ +language(request()->lang_id) + ->enabled() + ->order(['sort' => 'asc', 'id' => 'desc']) + ->select() + ->toArray(); + if (empty($groups)) { + return error('配置分组不存在'); + } + + // 根据分组获取配置项 + $configs = SysConfigModel::field([ + 'id', + 'group_id', + 'title', + 'name', + 'value', + 'extra', + 'type', + 'remark' + ]) + ->groupId(array_column($groups, 'id')) + ->order(['sort' => 'asc', 'id' => 'desc']) + ->select() + ->each(function($item) { + // 修改字段为null的输出为空字符串 + $keys = array_keys($item->toArray()); + foreach ($keys as $key) { + if (is_null($item[$key])) { + $item[$key] = ''; + } + } + return $item; + }) + ->toArray(); + if (empty($configs)) { + return error('配置项不存在'); + } + + // 处理附加配置项及联动项 + $config_name_map = []; + foreach ($configs as $config) { + unset($config['group_id']); + $config_name_map[$config['name']] = $config; + } + $configs = $this->handleExtra($configs, $config_name_map); + + // 组合数据 + $config_group_map = []; + foreach ($configs as $config) { + $group_id = $config['group_id']; + unset($config['group_id']); + $config_group_map[$group_id][] = $config; + } + + // 组合分组和配置项 + foreach ($groups as &$group) { + $group['configs'] = $config_group_map[$group['id']] ?? []; + } + unset($group); + + return success('获取成功', $groups); + } + // 处理配置联动项数据 + private function handleExtra($data, $map) + { + $ret = []; + $need_delete_names = []; + foreach ($data as $val) { + if (!empty($val['extra'])) { + $extra = explode(PHP_EOL, $val['extra']); + foreach ($extra as $v) { + if (preg_match('/^([^:]+):(.+)\[(.+)\]$/i', $v, $match)) { + $item = [ + 'name' => $match[2], + 'value' => $match[1] + ]; + if (isset($match[3])) { + $children = []; + $names = explode(',', $match[3]); + foreach ($names as $name) { + $name = trim(trim($name), "'"); + $need_delete_names[] = $name; + if (!empty($map[$name])) { + $children[] = $map[$name]; + } + } + // 处理子级 + if (!empty($children)) { + $item['children'] = $this->handleExtra($children, $map); + } + } + unset($val['extra']); + if (!isset($val['extras'])) { + $val['extras'] = []; + } + $val['extras'][] = $item; + } + } + } + $ret[] = $val; + } + // 删除多余的配置项 + foreach ($ret as $k => $it) { + if (in_array($it['name'], $need_delete_names)) { + unset($ret[$k]); + } + } + return $ret; + } + + // 更新配置 + public function update() + { + $put = request()->put(); + + if (empty($put)) { + return error('参数错误'); + } + + $validate = validate([ + 'id' => 'require|integer', + 'value' => 'max:255' + ]) + ->message([ + 'id.require' => '配置项ID不能为空', + 'id.integer' => '配置项ID必须是整数', + 'value.max' => '配置值不能超过255个字符' + ]); + foreach ($put as $val) { + if (!$validate->check($val)) { + return error($validate->getError()); + } + } + + $configs = (new SysConfigModel)->saveAll($put); + if ($configs->isEmpty()) { + return error('操作失败'); + } + + return success('操作成功'); + } +} diff --git a/app/admin/controller/v1/SysConfig.php b/app/admin/controller/v1/SysConfig.php new file mode 100644 index 00000000..b9aa352a --- /dev/null +++ b/app/admin/controller/v1/SysConfig.php @@ -0,0 +1,173 @@ +language(request()->lang_id) + ->enabled() + ->order(['sort' => 'asc', 'id' => 'desc']) + ->select(); + + return success('获取成功', $groups); + } + + // 获取配置类型 + public function types() + { + $types = SysConfigTypeModel::field([ + 'name', + 'value' + ]) + ->order(['sort' => 'asc']) + ->select(); + + return success('获取成功', $types); + } + + // 配置项分页 + public function index() + { + $param = request()->param([ + 'title', + 'page/d' => 1, + 'size/d' => 10 + ]); + + $configs = SysConfigModel::field([ + 'id', + 'group_id', + 'title', + 'name', + 'type', + 'sort' + ]) + ->with([ + 'group' => function($query) { + $query->field(['id', 'name' => 'group_name']); + }, + 'type' => function($query) { + $query->field(['name' => 'type_name', 'value']); + } + ]) + ->withSearch(['title'], ['title' => $param['title']??null]) + ->order(['sort' => 'asc', 'id' => 'desc']) + ->paginate([ + 'list_rows' => $param['size'], + 'page' => $param['page'] + ]) + ->bindAttr('group', ['group_name']) + ->bindAttr('type', ['type_name']) + ->hidden(['group_id', 'group', 'type']); + + return success('获取成功', $configs); + } + + // 配置项详情 + public function read() + { + $id = request()->param('id'); + + $config = SysConfigModel::withoutField([ + 'created_at', + 'updated_at', + 'deleted_at' + ]) + ->bypy($id) + ->find(); + if (empty($config)) { + return error('配置项不存在'); + } + + return success('获取成功', $config); + } + + // 配置项新增 + public function save() + { + $post = request()->post([ + 'group_id', + 'title', + 'name', + 'value', + 'extra', + 'type' => 'text', + 'sort', + 'remark' + ]); + + $validate = new SysConfigValidate; + if (!$validate->scene('add')->check($post)) { + return error($validate->getError()); + } + + $config = SysConfigModel::create($post); + if ($config->isEmpty()) { + return error('操作失败'); + } + return success('操作成功'); + } + + // 配置项更新 + public function update() + { + $id = request()->param('id'); + $put = request()->put([ + 'group_id', + 'title', + 'name', + 'value', + 'extra', + 'type' => 'text', + 'sort', + 'remark' + ]); + + $validate = new SysConfigValidate; + if (!$validate->check(array_merge($put, ['id' => $id]))) { + return error($validate->getError()); + } + + $config = SysConfigModel::bypk($id)->find(); + if (empty($config)) { + return error('请确认要操作对象是否存在'); + } + + if (!$config->save($put)) { + return error('操作失败'); + } + return success('操作成功'); + } + + // 配置项删除 + public function delete() + { + $id = request()->param('id'); + + $config = SysConfigModel::bypk($id)->find(); + if (empty($config)) { + return error('请确认要操作对象是否存在'); + } + + if (!$config->delete()) { + return error('操作失败'); + } + return success('操作成功'); + } +} diff --git a/app/admin/model/v1/SysConfigGroupModel.php b/app/admin/model/v1/SysConfigGroupModel.php new file mode 100644 index 00000000..d9c89786 --- /dev/null +++ b/app/admin/model/v1/SysConfigGroupModel.php @@ -0,0 +1,31 @@ +where('language_id', '=', $value); + } + + // 获取启用的配置分组 + public function scopeEnabled($query) + { + $query->where('status', '=', 1); + } +} diff --git a/app/admin/model/v1/SysConfigModel.php b/app/admin/model/v1/SysConfigModel.php new file mode 100644 index 00000000..427100c0 --- /dev/null +++ b/app/admin/model/v1/SysConfigModel.php @@ -0,0 +1,50 @@ +belongsTo('SysConfigGroupModel', 'group_id', 'id'); + } + + // 关联类型 + public function type() + { + return $this->belongsTo('SysConfigTypeModel', 'type', 'value'); + } + + // 按title搜索 + public function searchTitleAttr($query, $value, $data) + { + if (empty($value)) { + return; + } + $query->where('title', 'like', "%{$value}%"); + } + + // 按group_id查询 + public function scopeGroupId($query, $value) + { + if (is_array($value)) { + $query->where('group_id', 'in', $value); + return; + } + $query->where('group_id', '=', $value); + } +} diff --git a/app/admin/model/v1/SysConfigTypeModel.php b/app/admin/model/v1/SysConfigTypeModel.php new file mode 100644 index 00000000..24b0905b --- /dev/null +++ b/app/admin/model/v1/SysConfigTypeModel.php @@ -0,0 +1,15 @@ +prefix('v1.'); Route::miss(function() { diff --git a/app/admin/validate/v1/SysConfigValidate.php b/app/admin/validate/v1/SysConfigValidate.php new file mode 100644 index 00000000..8ed95d18 --- /dev/null +++ b/app/admin/validate/v1/SysConfigValidate.php @@ -0,0 +1,56 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => 'require|integer', + 'group_id' => 'require|integer', + 'title' => 'require|max:64', + 'name' => 'require|unique:sys_config|max:64', + 'value' => 'max:255', + 'extra' => 'max:255', + 'type' => 'max:64', + 'sort' => 'integer', + 'remark' => 'max:255' + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'id.require' => 'ID不能为空', + 'id.integer' => 'ID必须是整数', + 'group_id.require' => '分组ID不能为空', + 'group_id.integer' => '分组ID必须是整数', + 'title.require' => '标题不能为空', + 'title.max' => '标题最多不能超过64个字符', + 'name.require' => '标识不能为空', + 'name.unique' => '标识已存在', + 'name.max' => '名称最多不能超过64个字符', + 'value.max' => '值最多不能超过255个字符', + 'extra.max' => '额外信息最多不能超过255个字符', + 'type.max' => '类型最多不能超过64个字符', + 'sort.integer' => '排序必须是整数', + 'remark.max' => '备注最多不能超过255个字符', + ]; + + // 新增场景 + public function sceneAdd() + { + return $this->remove('id', 'require|integer'); + } +} diff --git a/app/common/model/SysConfigBaseModel.php b/app/common/model/SysConfigBaseModel.php new file mode 100644 index 00000000..e6cb6c07 --- /dev/null +++ b/app/common/model/SysConfigBaseModel.php @@ -0,0 +1,33 @@ + 'int', + 'group_id' => 'int', + 'title' => 'string', + 'name' => 'string', + 'value' => 'string', + 'extra' => 'string', + 'type' => 'string', + 'sort' => 'int', + 'remark' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; +} diff --git a/app/common/model/SysConfigGroupBaseModel.php b/app/common/model/SysConfigGroupBaseModel.php new file mode 100644 index 00000000..b72a71d4 --- /dev/null +++ b/app/common/model/SysConfigGroupBaseModel.php @@ -0,0 +1,29 @@ + 'int', + 'language_id' => 'int', + 'name' => 'string', + 'sort' => 'int', + 'status' => 'int', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; +} diff --git a/app/common/model/SysConfigTypeBaseModel.php b/app/common/model/SysConfigTypeBaseModel.php new file mode 100644 index 00000000..897214ce --- /dev/null +++ b/app/common/model/SysConfigTypeBaseModel.php @@ -0,0 +1,24 @@ + 'string', + 'value' => 'string', + 'sort' => 'int', + 'remark' => 'string' + ]; +} diff --git a/database/migrations/20241230064542_create_sys_config.php b/database/migrations/20241230064542_create_sys_config.php index b9aa7017..9b510ca0 100644 --- a/database/migrations/20241230064542_create_sys_config.php +++ b/database/migrations/20241230064542_create_sys_config.php @@ -31,13 +31,14 @@ class CreateSysConfig extends Migrator $table->addColumn('group_id', 'integer', ['limit' => 11, 'null' => false, 'comment' => '分组ID']) ->addColumn('title', 'string', ['limit' => 64, 'null' => false, 'comment' => '配置标题']) ->addColumn('name', 'string', ['limit' => 64, 'null' => false, 'comment' => '配置名称']) - ->addColumn('value', 'string', ['limit' => 255, 'null' => false, 'comment' => '配置值']) + ->addColumn('value', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '配置值']) ->addColumn('extra', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '配置额外信息']) ->addColumn('type', 'string', ['limit' => 64, 'null' => false, 'comment' => '配置类型: text, textarea, number, select, checkbox, radio, date, time, datetime']) ->addColumn('sort', 'integer', ['limit' => 11, 'null' => false, 'default' => 0, 'comment' => '排序']) ->addColumn('remark', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '备注']) ->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP', 'comment' => '创建时间']) ->addColumn('updated_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', 'comment' => '更新时间']) + ->addIndex(['name'], ['unique' => true, 'name' => 'unique_idx_name']) ->create(); } } diff --git a/database/migrations/20250307070304_create_sys_config_type.php b/database/migrations/20250307070304_create_sys_config_type.php new file mode 100644 index 00000000..bfc05471 --- /dev/null +++ b/database/migrations/20250307070304_create_sys_config_type.php @@ -0,0 +1,37 @@ +table('sys_config_type', ['id' => false, 'engine' => 'InnoDB', 'comment' => '系统配置类型表']); + $table->addColumn('name', 'string', ['limit' => 64, 'null' => false, 'comment' => '类型名']) + ->addColumn('value', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '类型值']) + ->addColumn('sort', 'integer', ['limit' => 11, 'null' => false, 'default' => 0, 'comment' => '排序']) + ->addColumn('remark', 'string', ['limit' => 255, 'null' => true, 'default' => null, 'comment' => '备注']) + ->create(); + } +}