diff --git a/app/Controller/AbstractController.php b/app/Controller/AbstractController.php
index ca509f8..4ce7b3e 100644
--- a/app/Controller/AbstractController.php
+++ b/app/Controller/AbstractController.php
@@ -7,6 +7,7 @@ namespace App\Controller;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
+use Hyperf\View\RenderInterface;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
@@ -23,4 +24,7 @@ abstract class AbstractController
#[Inject]
protected EventDispatcherInterface $eventDispatcher;
+
+ #[Inject]
+ protected RenderInterface $render;
}
diff --git a/app/Controller/Admin/System.php b/app/Controller/Admin/System.php
index bfe7dfa..932c0a4 100644
--- a/app/Controller/Admin/System.php
+++ b/app/Controller/Admin/System.php
@@ -578,4 +578,56 @@ class System extends Base
}
return $this->toAjax(gtModel::syncTable($table_id));
}
+
+ #[GetMapping(path: "gen_table/show")]
+ #[Auth(auth: "gen_table:show")]
+ public function genTableShow()
+ {
+ $table_id = $this->request->input("id");
+ if (!$table_id) {
+ return $this->error("生成失败");
+ }
+ $table = gtModel::info($table_id);
+ if (empty($table)) {
+ return $this->error("生成失败");
+ }
+ // 表前缀
+ $prefix = config("databases.default.prefix");
+ // 表名
+ $table_name = str_replace($prefix, "", $table['table_name']);
+ $module_name = $table['module_name'];
+ $controller_name = $table['controller_name'];
+ // 搜搜字段
+ $query_fields = [];
+ $insert_fields = [];
+ $list_fields = [];
+ $required_fields = [];
+ $fields = $table['gen_table_columns'];
+ foreach ($fields as $column) {
+ if ($column['is_query']) {
+ $query_fields[] = $column;
+ }
+ if ($column['is_insert'] && !in_array($column['column_name'], ['create_time', 'update_time', 'deleted_at'])) {
+ $insert_fields[] = $column;
+ }
+ if ($column['is_edit'] && !in_array($column['column_name'], ['create_time', 'update_time', 'deleted_at'])) {
+ $edit_fields[] = $column;
+ }
+ if ($column['is_list']) {
+ $list_fields[] = $column;
+ }
+ if ($column['is_required'] && !in_array($column['column_name'], ['create_time', 'update_time', 'deleted_at'])) {
+ $required_fields[] = $column;
+ }
+ }
+ $data = [
+ 'model.php' => $this->render->getContents('templates/model.php.twig', compact("table_name", "fields", "controller_name", "query_fields", "list_fields")),
+ 'request.php' => $this->render->getContents('templates/request.php.twig', compact("controller_name", "insert_fields", "fields", "required_fields", "edit_fields")),
+ 'controller.php' => $this->render->getContents('templates/controller.php.twig', compact("controller_name", "module_name", "query_fields", "insert_fields", "edit_fields", "table_name")),
+ 'api.ts' => $this->render->getContents('templates/api.ts.twig', compact('table_name')),
+ 'index.vue' => $this->render->getContents('templates/index.vue.twig', compact('table_name', 'list_fields', 'query_fields')),
+ 'save.vue' => $this->render->getContents('templates/save.vue.twig', compact('table_name', 'insert_fields', 'required_fields'))
+ ];
+ return $this->success("模板信息", $data);
+ }
}
\ No newline at end of file
diff --git a/app/Model/GenTable.php b/app/Model/GenTable.php
index 3f68040..626c155 100644
--- a/app/Model/GenTable.php
+++ b/app/Model/GenTable.php
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Model;
-use App\Exception\ServiceException;
use App\Utils\Str;
use Hyperf\DbConnection\Db;
@@ -66,6 +65,7 @@ class GenTable extends Model
Db::rollBack();
return false;
}
+
// 字段管理
$columns = Db::select("SHOW FULL COLUMNS FROM `{$row->Name}`");
$i = 1;
diff --git a/composer.json b/composer.json
index 8468f87..c3fc680 100644
--- a/composer.json
+++ b/composer.json
@@ -32,8 +32,10 @@
"hyperf/rate-limit": "^3.1",
"hyperf/redis": "~3.1.0",
"hyperf/validation": "^3.1",
+ "hyperf/view": "^3.1",
"hyperf/websocket-server": "^3.1",
"phpoffice/phpspreadsheet": "^4.5",
+ "twig/twig": "^3.22",
"zoujingli/ip2region": "^3.0"
},
"require-dev": {
diff --git a/config/autoload/view.php b/config/autoload/view.php
new file mode 100644
index 0000000..135e3cd
--- /dev/null
+++ b/config/autoload/view.php
@@ -0,0 +1,14 @@
+ Hyperf\View\Engine\TwigEngine::class,
+ 'mode' => Mode::SYNC,
+ 'config' => [
+ 'view_path' => BASE_PATH . '/static/view/',
+ 'cache_path' => BASE_PATH . '/runtime/view/'
+ ]
+];
diff --git a/static/view/templates/api.ts.twig b/static/view/templates/api.ts.twig
new file mode 100644
index 0000000..6f4dd12
--- /dev/null
+++ b/static/view/templates/api.ts.twig
@@ -0,0 +1,24 @@
+import http from "@/utils/request"
+
+export default {
+ {{ table_name }}: {
+ list: async function (data = {}) {
+ return await http.get("{{ table_name }}/list", data);
+ },
+ info: async function (data = {}) {
+ return await http.get("{{ table_name }}/list", data);
+ },
+ add: async function (data = {}) {
+ return await http.post("{{ table_name }}/add", data);
+ },
+ edit: async function (data = {}) {
+ return await http.put("{{ table_name }}/edit", data);
+ },
+ del: async function (data = {}) {
+ return await http.delete("{{ table_name }}/del", data);
+ },
+ option: async function (data = {}) {
+ return await http.get("{{ table_name }}/option", data);
+ },
+ },
+}
diff --git a/static/view/templates/controller.php.twig b/static/view/templates/controller.php.twig
new file mode 100644
index 0000000..97f9279
--- /dev/null
+++ b/static/view/templates/controller.php.twig
@@ -0,0 +1,71 @@
+
+*/
+
+namespace {{ module_name }};
+
+use App\Annotation\Auth;
+use App\Model\{{ controller_name }} as {{ table_name | slice(0, 1) }}Model;
+use App\Request\{{ controller_name }} as {{ table_name | slice(0, 1) }}Request;
+use App\Utils\Param;
+use Hyperf\HttpServer\Annotation\Controller;
+use Hyperf\HttpServer\Annotation\DeleteMapping;
+use Hyperf\HttpServer\Annotation\GetMapping;
+use Hyperf\HttpServer\Annotation\PostMapping;
+use Hyperf\HttpServer\Annotation\PutMapping;
+
+#[Controller(prefix: "admin")]
+class {{ controller_name }} extends Base
+{
+ #[GetMapping(path: "{{ table_name }}/list")]
+ #[Auth(auth: "{{ table_name }}:list")]
+ public function {{ table_name }}List()
+ {
+ $param = Param::only([{% for field in query_fields %}"{{ field.column_name }}"{% if not loop.last %}, {% endif %}{% endfor %}]);
+ return $this->success({{ table_name | slice(0, 1) }}Model::list($param));
+ }
+
+ #[GetMapping(path: "{{ table_name }}/option")]
+ #[Auth(needAuth: false)]
+ public function {{ table_name }}Option()
+ {
+ return $this->success({{ table_name | slice(0, 1) }}Model::options());
+ }
+
+ #[GetMapping(path: "{{ table_name }}/info")]
+ #[Auth(auth: "{{ table_name }}:info")]
+ public function {{ table_name }}Info()
+ {
+ $id = $this->request->input("id");
+ return $this->success({{ table_name | slice(0, 1) }}Model::getById());
+ }
+
+ #[PostMapping(path: "{{ table_name }}/add")]
+ #[Auth(auth: "{{ table_name }}:add")]
+ public function {{ table_name }}Add()
+ {
+ $request = $this->container->get({{ table_name | slice(0, 1)}}Request::class);
+ $request->scene('add')->validateResolved();
+ $data = Param::only([{% for field in insert_fields %}"{{ field.column_name }}"{% if not loop.last %}, {% endif %}{% endfor %}]);
+ return $this->toAjax({{ table_name | slice(0, 1) }}Model::add($data));
+ }
+
+ #[PutMapping(path: "{{ table_name }}/edit")]
+ #[Auth(auth: "{{ table_name }}:edit")]
+ public function {{ table_name }}Edit()
+ {
+ $request = $this->container->get({{ table_name | slice(0, 1)}}Request::class);
+ $request->scene('edit')->validateResolved();
+ $data = Param::only([{% for field in edit_fields %}"{{ field.column_name }}"{% if not loop.last %}, {% endif %}{% endfor %}]);
+ return $this->toAjax({{ table_name | slice(0, 1) }}Model::edit($data));
+ }
+
+ #[DeleteMapping(path: "{{ table_name }}/del")]
+ #[Auth(auth: "{{ table_name }}:del")]
+ public function {{ table_name }}Del()
+ {
+ $ids = $this->request->input("ids");
+ return $this->toAjax({{ table_name | slice(0, 1) }}Model::del($ids));
+ }
+}
\ No newline at end of file
diff --git a/static/view/templates/index.vue.twig b/static/view/templates/index.vue.twig
new file mode 100644
index 0000000..c1ce8cc
--- /dev/null
+++ b/static/view/templates/index.vue.twig
@@ -0,0 +1,170 @@
+
+
+{% if query_fields|length > 2 %}
+
+{% for field in query_fields %}
+{% if loop.index > 2 %}
+{% if field.html_type == 'select' or field.html_type == 'radio' or field.html_type == 'checkbox' %}
+
+
+
+{% elseif field.html_type == 'date' %}
+
+{% elseif field.html_type == 'datetime' %}
+
+{% else %}
+
+{% endif %}
+{% endif %}
+{% endfor %}
+
+{% endif %}
+
+
+
+
+
+
+{% if query_fields|length > 2 %}
+{% for field in query_fields %}
+{% if loop.index <= 2 %}
+{% if field.html_type == 'select' or field.html_type == 'radio' or field.html_type == 'checkbox' %}
+
+
+
+{% elseif field.html_type == 'date' %}
+
+{% elseif field.html_type == 'datetime' %}
+
+{% else %}
+
+{% endif %}
+{% endif %}
+{% endfor %}
+{% else %}
+{% for field in query_fields %}
+{% if field.html_type == 'select' or field.html_type == 'radio' or field.html_type == 'checkbox' %}
+
+
+
+{% elseif field.html_type == 'date' %}
+
+{% elseif field.html_type == 'datetime' %}
+
+{% else %}
+
+{% endif %}
+{% endfor %}
+{% endif %}
+
+
+
+{% for field in list_fields %}
+
+{% endfor %}
+
+
+
+ 查看
+
+ 编辑
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
diff --git a/static/view/templates/model.php.twig b/static/view/templates/model.php.twig
new file mode 100644
index 0000000..ba107c3
--- /dev/null
+++ b/static/view/templates/model.php.twig
@@ -0,0 +1,78 @@
+ 'integer'{% set first = false %}{% endif %}{% endfor %}];
+
+ public static function list(array $param)
+ {
+ $model = self::query();
+{% for field in query_fields %}
+{% if field.query_type == 'eq' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', $param['{{ field.column_name }}']);
+ }
+{% elseif field.query_type == 'neq' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', "<>", $param['{{ field.column_name }}']);
+ }
+{% elseif field.query_type == 'gt' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', ">", $param['{{ field.column_name }}']);
+ }
+{% elseif field.query_type == 'lt' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', "<", $param['{{ field.column_name }}']);
+ }
+{% elseif field.query_type == 'gte' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', ">=", $param['{{ field.column_name }}']);
+ }
+{% elseif field.query_type == 'lte' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', "<=", $param['{{ field.column_name }}']);
+ }
+{% elseif field.query_type == 'like' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', "like", "%{$param['{{ field.column_name }}']}%");
+ }
+{% elseif field.query_type == 'between' %}
+ if (isset($param['{{ field.column_name }}']) && $param['{{ field.column_name }}'] != '') {
+ $model = $model->where('{{field.column_name}}', "between", $param['{{ field.column_name }}']);
+ }
+{% endif %}
+{% endfor %}
+ return $model->orderByDesc("{{ table_name }}_id")
+ ->select([{% for field in list_fields %}"{{ field.column_name }}"{% if not loop.last %}, {% endif %}{% endfor %}])
+ ->paginate((int)$param['limit']);
+ }
+
+ public static function options()
+ {
+ return self::select(["{{ table_name }}_id", "{{ table_name }}_name"])->get()->toArray();
+ }
+}
diff --git a/static/view/templates/request.php.twig b/static/view/templates/request.php.twig
new file mode 100644
index 0000000..33da3da
--- /dev/null
+++ b/static/view/templates/request.php.twig
@@ -0,0 +1,42 @@
+ [{% for field in insert_fields %}"{{ field.column_name }}"{% if not loop.last %}, {% endif %}{% endfor %}],
+ 'edit' => [{% for field in edit_fields %}"{{ field.column_name }}"{% if not loop.last %}, {% endif %}{% endfor %}],
+ ];
+
+ /**
+ * Determine if the user is authorized to make this request.
+ */
+ public function authorize(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Get the validation rules that apply to the request.
+ */
+ public function rules(): array
+ {
+ return [
+{% for field in fields %}
+ '{{ field.column_name }}' => 'required',
+{% endfor %}
+ ];
+ }
+
+ public function messages(): array
+ {
+ return [
+{% for field in edit_fields %}
+ '{{ field.column_name }}.required' => '{{ field.column_comment }}必传!',
+{% endfor %}
+ ];
+ }
+}
diff --git a/static/view/templates/save.vue.twig b/static/view/templates/save.vue.twig
new file mode 100644
index 0000000..b677318
--- /dev/null
+++ b/static/view/templates/save.vue.twig
@@ -0,0 +1,100 @@
+
+
+
+{% for field in insert_fields %}
+{% if field.html_type == 'select' %}
+
+
+
+
+
+{% elseif field.html_type == 'radio' %}
+
+
+
+
+
+{% elseif field.html_type == 'checkbox' %}
+
+
+
+
+
+{% elseif field.html_type == 'date' %}
+
+
+
+{% elseif field.html_type == 'datetime' %}
+
+
+
+{% elseif field.html_type == 'textarea' %}
+
+
+
+{% else %}
+
+
+
+{% endif %}
+{% endfor %}
+
+
+ 取 消
+ 保 存
+
+
+
+
+
diff --git a/watcher.php b/watcher.php
new file mode 100644
index 0000000..9f19cd0
--- /dev/null
+++ b/watcher.php
@@ -0,0 +1,16 @@
+ ScanFileDriver::class,
+ 'bin' => PHP_BINARY,
+ 'watch' => [
+ 'dir' => ['app', 'config'],
+ 'file' => ['.env'],
+ 'scan_interval' => 2000,
+ ],
+ 'ext' => ['.php', '.env'],
+];