From bbeb267649a636c6d0d249beda7fd08ca5a69895 Mon Sep 17 00:00:00 2001
From: "2368302435@qq.com" <2368302435@qq.com>
Date: Thu, 29 Feb 2024 21:06:37 +0800
Subject: [PATCH] =?UTF-8?q?feat(CRUD):=E5=A4=9A=E6=95=B0=E6=8D=AE=E5=BA=93?=
=?UTF-8?q?=E8=BF=9E=E6=8E=A5=E9=85=8D=E7=BD=AE=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/admin/controller/crud/Crud.php | 98 ++++++--------
app/admin/library/crud/Helper.php | 68 ++++++----
.../crud/stubs/mixins/model/model.stub | 2 +-
.../migrations/20231229043002_version206.php | 6 +
web/src/api/backend/crud.ts | 18 +--
web/src/lang/backend/en/crud/crud.ts | 4 +
web/src/lang/backend/zh-cn/crud/crud.ts | 4 +
web/src/views/backend/crud/design.vue | 123 ++++++++++++------
web/src/views/backend/crud/index.ts | 6 +-
web/src/views/backend/crud/log.vue | 15 ++-
web/src/views/backend/crud/start.vue | 87 ++++++++-----
11 files changed, 259 insertions(+), 172 deletions(-)
diff --git a/app/admin/controller/crud/Crud.php b/app/admin/controller/crud/Crud.php
index 3d01542a..efdba33b 100644
--- a/app/admin/controller/crud/Crud.php
+++ b/app/admin/controller/crud/Crud.php
@@ -59,7 +59,7 @@ class Crud extends Backend
*/
protected array $dtStringToArray = ['checkbox', 'selects', 'remoteSelects', 'city', 'images', 'files'];
- protected array $noNeedPermission = ['logStart', 'getFileData', 'parseFieldData', 'generateCheck', 'databaseList'];
+ protected array $noNeedPermission = ['logStart', 'getFileData', 'parseFieldData', 'generateCheck'];
public function initialize(): void
{
@@ -89,11 +89,11 @@ class Crud extends Backend
]);
// 表名称
- $tableName = TableManager::tableName($table['name'], false);
+ $tableName = TableManager::tableName($table['name'], false, $table['databaseConnection']);
if ($type == 'create' || $table['rebuild'] == 'Yes') {
// 数据表存在则删除
- TableManager::phinxTable($tableName)->drop()->save();
+ TableManager::phinxTable($tableName, [], true, $table['databaseConnection'])->drop()->save();
}
// 处理表设计
@@ -127,6 +127,7 @@ class Crud extends Backend
$this->modelData['beforeInsertMixins'] = [];
$this->modelData['beforeInsert'] = '';
$this->modelData['afterInsert'] = '';
+ $this->modelData['connection'] = $table['databaseConnection'];
$this->modelData['name'] = $tableName;
$this->modelData['className'] = $modelFile['lastName'];
$this->modelData['namespace'] = $modelFile['namespace'];
@@ -205,7 +206,7 @@ class Crud extends Backend
// 关联表数据解析
if (in_array($field['designType'], ['remoteSelect', 'remoteSelects'])) {
- $this->parseJoinData($field);
+ $this->parseJoinData($field, $table);
}
// 模型方法
@@ -308,9 +309,15 @@ class Crud extends Backend
}
// 数据表是否有数据
- $adapter = TableManager::phinxAdapter();
- if ($adapter->hasTable($info['table']['name'])) {
- $info['table']['empty'] = Db::name($info['table']['name'])->limit(1)->select()->isEmpty();
+ $connection = TableManager::getConnection($info['table']['databaseConnection']);
+ $tableName = TableManager::tableName($info['table']['name'], false, $connection);
+ $adapter = TableManager::phinxAdapter(true, $connection);
+ if ($adapter->hasTable($tableName)) {
+ $info['table']['empty'] = Db::connect($connection)
+ ->name($tableName)
+ ->limit(1)
+ ->select()
+ ->isEmpty();
} else {
$info['table']['empty'] = true;
}
@@ -438,9 +445,13 @@ class Crud extends Backend
*/
public function checkCrudLog(): void
{
- $table = $this->request->get('table');
+ $table = $this->request->get('table');
+ $connection = $this->request->get('connection');
+ $connection = $connection ?: config('database.default');
+
$crudLog = Db::name('crud_log')
->where('table_name', $table)
+ ->where('connection', $connection)
->order('create_time desc')
->find();
$this->success('', [
@@ -455,27 +466,36 @@ class Crud extends Backend
public function parseFieldData(): void
{
AdminLog::setTitle(__('Parse field data'));
- $type = $this->request->post('type');
- $table = $this->request->post('table');
- $table = TableManager::tableName($table);
+ $type = $this->request->post('type');
+ $table = $this->request->post('table');
+ $connection = $this->request->post('connection');
+ $connection = TableManager::getConnection($connection);
+
+ $table = TableManager::tableName($table, true, $connection);
+ $connectionConfig = TableManager::getConnectionConfig($connection);
+
if ($type == 'db') {
$sql = 'SELECT * FROM `information_schema`.`tables` '
. 'WHERE TABLE_SCHEMA = ? AND table_name = ?';
- $tableInfo = Db::query($sql, [config('database.connections.mysql.database'), $table]);
+ $tableInfo = Db::connect($connection)->query($sql, [$connectionConfig['database'], $table]);
if (!$tableInfo) {
$this->error(__('Record not found'));
}
// 数据表是否有数据
- $adapter = TableManager::phinxAdapter(false);
+ $adapter = TableManager::phinxAdapter(false, $connection);
if ($adapter->hasTable($table)) {
- $empty = Db::table($table)->limit(1)->select()->isEmpty();
+ $empty = Db::connect($connection)
+ ->table($table)
+ ->limit(1)
+ ->select()
+ ->isEmpty();
} else {
$empty = true;
}
$this->success('', [
- 'columns' => Helper::parseTableColumns($table),
+ 'columns' => Helper::parseTableColumns($table, false, $connection),
'comment' => $tableInfo[0]['TABLE_COMMENT'] ?? '',
'empty' => $empty,
]);
@@ -490,6 +510,7 @@ class Crud extends Backend
{
$table = $this->request->post('table');
$controllerFile = $this->request->post('controllerFile', '');
+ $connection = $this->request->post('connection');
if (!$table) {
$this->error(__('Parameter error'));
@@ -505,8 +526,8 @@ class Crud extends Backend
$this->error($e->getMessage());
}
- $tableList = TableManager::getTableList();
- $tableExist = array_key_exists(TableManager::tableName($table), $tableList);
+ $tableList = TableManager::getTableList($connection);
+ $tableExist = array_key_exists(TableManager::tableName($table, true, $connection), $tableList);
$controllerExist = file_exists(root_path() . $controllerFile);
if ($controllerExist || $tableExist) {
@@ -518,55 +539,21 @@ class Crud extends Backend
$this->success();
}
- /**
- * 数据表列表
- * @throws Throwable
- */
- public function databaseList(): void
- {
- $tablePrefix = config('database.connections.mysql.prefix');
- $outExcludeTable = [
- // 功能表
- 'area',
- 'token',
- 'captcha',
- 'admin_group_access',
- 'config',
- 'admin_log',
- // 不建议生成crud的表
- 'user_money_log',
- 'user_score_log',
- ];
-
- $outTables = [];
- $tables = TableManager::getTableList();
- $pattern = '/^' . $tablePrefix . '/i';
- foreach ($tables as $table => $tableComment) {
- if (!preg_match($pattern, $table)) continue;
- $table = preg_replace($pattern, '', $table);
- if (!in_array($table, $outExcludeTable)) {
- $outTables[$table] = $tableComment;
- }
- }
- $this->success('', [
- 'dbs' => $outTables,
- ]);
- }
-
/**
* 关联表数据解析
* @param $field
+ * @param $table
* @throws Throwable
*/
- private function parseJoinData($field): void
+ private function parseJoinData($field, $table): void
{
$dictEn = [];
$dictZhCn = [];
if ($field['form']['relation-fields'] && $field['form']['remote-table']) {
- $columns = Helper::parseTableColumns($field['form']['remote-table'], true);
+ $columns = Helper::parseTableColumns($field['form']['remote-table'], true, $table['databaseConnection']);
$relationFields = explode(',', $field['form']['relation-fields']);
- $tableName = TableManager::tableName($field['form']['remote-table'], false);
+ $tableName = TableManager::tableName($field['form']['remote-table'], false, $table['databaseConnection']);
$rnPattern = '/(.*)(_ids|_id)$/';
if (preg_match($rnPattern, $field['name'])) {
$relationName = parse_name(preg_replace($rnPattern, '$1', $field['name']), 1, false);
@@ -586,6 +573,7 @@ class Crud extends Backend
$joinModelData['beforeInsertMixins'] = [];
$joinModelData['beforeInsert'] = '';
$joinModelData['afterInsert'] = '';
+ $joinModelData['connection'] = $table['databaseConnection'];
$joinModelData['name'] = $tableName;
$joinModelData['className'] = $joinModelFile['lastName'];
$joinModelData['namespace'] = $joinModelFile['namespace'];
diff --git a/app/admin/library/crud/Helper.php b/app/admin/library/crud/Helper.php
index 23a5871f..008dbeef 100644
--- a/app/admin/library/crud/Helper.php
+++ b/app/admin/library/crud/Helper.php
@@ -281,10 +281,13 @@ class Helper
]);
return $data['id'];
}
- $log = CrudLog::create([
+
+ $connection = $data['table']['databaseConnection'] ?: config('database.default');
+ $log = CrudLog::create([
'table_name' => $data['table']['name'],
'table' => $data['table'],
'fields' => $data['fields'],
+ 'connection' => $connection,
'status' => $data['status'],
]);
return $log->id;
@@ -424,16 +427,17 @@ class Helper
/**
* 表字段排序
- * @param string $tableName 表名
- * @param array $fields 字段数据
- * @param array $designChange 前端字段改变数据
+ * @param string $tableName 表名
+ * @param array $fields 字段数据
+ * @param array $designChange 前端字段改变数据
+ * @param ?string $connection 数据库连接标识
* @return void
* @throws Throwable
*/
- public static function updateFieldOrder(string $tableName, array $fields, array $designChange): void
+ public static function updateFieldOrder(string $tableName, array $fields, array $designChange, ?string $connection = null): void
{
if ($designChange) {
- $table = TableManager::phinxTable($tableName, [], false);
+ $table = TableManager::phinxTable($tableName, [], false, $connection);
foreach ($designChange as $item) {
if (!$item['sync']) continue;
@@ -469,10 +473,10 @@ class Helper
*/
public static function handleTableDesign(array $table, array $fields): array
{
- $name = TableManager::tableName($table['name']);
+ $name = TableManager::tableName($table['name'], true, $table['databaseConnection']);
$comment = $table['comment'] ?? '';
$designChange = $table['designChange'] ?? [];
- $adapter = TableManager::phinxAdapter(false);
+ $adapter = TableManager::phinxAdapter(false, $table['databaseConnection']);
$pk = self::searchArray($fields, function ($item) {
return $item['primaryKey'];
@@ -482,8 +486,8 @@ class Helper
if ($adapter->hasTable($name)) {
// 更新表
if ($designChange) {
- $table = TableManager::phinxTable($name, [], false);
- $table->changeComment($comment)->update();
+ $tableManager = TableManager::phinxTable($name, [], false, $table['databaseConnection']);
+ $tableManager->changeComment($comment)->update();
// 改名和删除操作优先
$priorityOpt = false;
@@ -491,23 +495,23 @@ class Helper
if (!$item['sync']) continue;
- if (in_array($item['type'], ['change-field-name', 'del-field']) && !$table->hasColumn($item['oldName'])) {
+ if (in_array($item['type'], ['change-field-name', 'del-field']) && !$tableManager->hasColumn($item['oldName'])) {
// 字段不存在
throw new BaException(__($item['type'] . ' fail not exist', [$item['oldName']]));
}
if ($item['type'] == 'change-field-name') {
$priorityOpt = true;
- $table->renameColumn($item['oldName'], $item['newName']);
+ $tableManager->renameColumn($item['oldName'], $item['newName']);
} elseif ($item['type'] == 'del-field') {
$priorityOpt = true;
- $table->removeColumn($item['oldName']);
+ $tableManager->removeColumn($item['oldName']);
}
}
// 保存需要优先执行的操作,避免先改名再改属性时找不到字段
if ($priorityOpt) {
- $table->update();
+ $tableManager->update();
}
// 修改字段属性和添加字段操作
@@ -517,7 +521,7 @@ class Helper
if ($item['type'] == 'change-field-attr') {
- if (!$table->hasColumn($item['oldName'])) {
+ if (!$tableManager->hasColumn($item['oldName'])) {
// 字段不存在
throw new BaException(__($item['type'] . ' fail not exist', [$item['oldName']]));
}
@@ -525,10 +529,10 @@ class Helper
$phinxFieldData = self::getPhinxFieldData(self::searchArray($fields, function ($field) use ($item) {
return $field['name'] == $item['oldName'];
}));
- $table->changeColumn($item['oldName'], $phinxFieldData['type'], $phinxFieldData['options']);
+ $tableManager->changeColumn($item['oldName'], $phinxFieldData['type'], $phinxFieldData['options']);
} elseif ($item['type'] == 'add-field') {
- if ($table->hasColumn($item['newName'])) {
+ if ($tableManager->hasColumn($item['newName'])) {
// 字段已经存在
throw new BaException(__($item['type'] . ' fail exist', [$item['newName']]));
}
@@ -536,28 +540,28 @@ class Helper
$phinxFieldData = self::getPhinxFieldData(self::searchArray($fields, function ($field) use ($item) {
return $field['name'] == $item['newName'];
}));
- $table->addColumn($item['newName'], $phinxFieldData['type'], $phinxFieldData['options']);
+ $tableManager->addColumn($item['newName'], $phinxFieldData['type'], $phinxFieldData['options']);
}
}
- $table->update();
+ $tableManager->update();
// 表更新结构完成再处理字段排序
- self::updateFieldOrder($name, $fields, $designChange);
+ self::updateFieldOrder($name, $fields, $designChange, $table['databaseConnection']);
}
} else {
// 创建表
- $table = TableManager::phinxTable($name, [
+ $tableManager = TableManager::phinxTable($name, [
'id' => false,
'comment' => $comment,
'row_format' => 'DYNAMIC',
'primary_key' => $pk,
'collation' => 'utf8mb4_unicode_ci',
- ], false);
+ ], false, $table['databaseConnection']);
foreach ($fields as $field) {
$phinxFieldData = self::getPhinxFieldData($field);
- $table->addColumn($field['name'], $phinxFieldData['type'], $phinxFieldData['options']);
+ $tableManager->addColumn($field['name'], $phinxFieldData['type'], $phinxFieldData['options']);
}
- $table->create();
+ $tableManager->create();
}
return [$pk];
@@ -732,15 +736,19 @@ class Helper
* 根据数据表解析字段数据
* @throws Throwable
*/
- public static function parseTableColumns(string $table, bool $analyseField = false): array
+ public static function parseTableColumns(string $table, bool $analyseField = false, ?string $connection = null): array
{
+ $connection = TableManager::getConnection($connection);
+ $connectionConfig = TableManager::getConnectionConfig($connection);
+
// 从数据库中获取表字段信息
$sql = 'SELECT * FROM `information_schema`.`columns` '
. 'WHERE TABLE_SCHEMA = ? AND table_name = ? '
. 'ORDER BY ORDINAL_POSITION';
$columns = [];
- $tableColumn = Db::query($sql, [config('database.connections.mysql.database'), TableManager::tableName($table)]);
+ $tableColumn = Db::connect($connection)->query($sql, [$connectionConfig['database'], TableManager::tableName($table, true, $connection)]);
+
foreach ($tableColumn as $item) {
$isNullAble = $item['IS_NULLABLE'] == 'YES';
if (str_contains($item['COLUMN_TYPE'], '(')) {
@@ -989,7 +997,13 @@ class Helper
public static function writeModelFile(string $tablePk, array $fieldsMap, array $modelData, array $modelFile): void
{
- $modelData['pk'] = $tablePk == 'id' ? '' : "\n" . self::tab() . "// 表主键\n" . self::tab() . 'protected $pk = ' . "'$tablePk';\n" . self::tab();
+ if ($modelData['connection'] && $modelData['connection'] != config('database.default')) {
+ $modelData['connection'] = "\n" . self::tab() . "// 数据库连接配置标识\n" . self::tab() . 'protected $connection = ' . "'{$modelData['connection']}';\n";
+ } else {
+ $modelData['connection'] = '';
+ }
+
+ $modelData['pk'] = $tablePk == 'id' ? '' : "\n" . self::tab() . "// 表主键\n" . self::tab() . 'protected $pk = ' . "'$tablePk';\n";
$modelData['autoWriteTimestamp'] = array_key_exists(self::$createTimeField, $fieldsMap) || array_key_exists(self::$updateTimeField, $fieldsMap) ? 'true' : 'false';
if ($modelData['autoWriteTimestamp'] == 'true') {
$modelData['createTime'] = array_key_exists(self::$createTimeField, $fieldsMap) ? '' : "\n" . self::tab() . "protected \$createTime = false;";
diff --git a/app/admin/library/crud/stubs/mixins/model/model.stub b/app/admin/library/crud/stubs/mixins/model/model.stub
index a164337f..cd77f11c 100644
--- a/app/admin/library/crud/stubs/mixins/model/model.stub
+++ b/app/admin/library/crud/stubs/mixins/model/model.stub
@@ -8,7 +8,7 @@ use think\Model;
* {%className%}
*/
class {%className%} extends Model
-{{%pk%}
+{{%connection%}{%pk%}
// 表名
protected $name = '{%name%}';
diff --git a/database/migrations/20231229043002_version206.php b/database/migrations/20231229043002_version206.php
index d170028e..e4c75a2d 100644
--- a/database/migrations/20231229043002_version206.php
+++ b/database/migrations/20231229043002_version206.php
@@ -26,5 +26,11 @@ class Version206 extends Migrator
$table = $this->table('config');
$table->insert($rows)->saveData();
}
+
+ $crudLog = $this->table('crud_log');
+ if (!$crudLog->hasColumn('connection')) {
+ $crudLog->addColumn('connection', 'string', ['limit' => 100, 'default' => '', 'comment' => '数据库连接配置标识', 'null' => false, 'after' => 'status']);
+ $crudLog->save();
+ }
}
}
diff --git a/web/src/api/backend/crud.ts b/web/src/api/backend/crud.ts
index ee84ca57..1911b4b8 100644
--- a/web/src/api/backend/crud.ts
+++ b/web/src/api/backend/crud.ts
@@ -15,13 +15,6 @@ export function generate(data: anyObj) {
)
}
-export function getDatabaseList() {
- return createAxios({
- url: url + 'databaseList',
- method: 'get',
- })
-}
-
export function getFileData(table: string, commonModel = 0) {
return createAxios({
url: url + 'getFileData',
@@ -46,15 +39,11 @@ export function generateCheck(data: anyObj) {
)
}
-export function parseFieldData(type: string, table = '', sql = '') {
+export function parseFieldData(data: anyObj) {
return createAxios({
url: url + 'parseFieldData',
method: 'post',
- data: {
- type: type,
- table: table,
- sql: sql,
- },
+ data: data,
})
}
@@ -78,12 +67,13 @@ export function postDel(id: number) {
})
}
-export function checkCrudLog(table: string) {
+export function checkCrudLog(table: string, connection: string) {
return createAxios({
url: url + 'checkCrudLog',
method: 'get',
params: {
table: table,
+ connection: connection,
},
})
}
diff --git a/web/src/lang/backend/en/crud/crud.ts b/web/src/lang/backend/en/crud/crud.ts
index 049f71fc..9720b7ef 100644
--- a/web/src/lang/backend/en/crud/crud.ts
+++ b/web/src/lang/backend/en/crud/crud.ts
@@ -71,6 +71,10 @@ export default {
'Generated Validator Location': 'Generated Validator Location',
'Common model': 'Common model',
'WEB end view directory': 'WEB end view directory',
+ 'Database connection': 'Database connection',
+ 'Database connection help': 'You can configure multiple database connections in config/database.php and select it here',
+ 'Check model class': "Check whether protected $connection = '{connection}'; is configured in the above data model class",
+ 'There is no connection attribute in model class': 'If no configuration is available, you can configure it manually',
'Advanced Configuration': 'Advanced Configuration',
'Common Fields': 'Common Fields',
'Base Fields': 'Base Fields',
diff --git a/web/src/lang/backend/zh-cn/crud/crud.ts b/web/src/lang/backend/zh-cn/crud/crud.ts
index e351ea64..c10024b7 100644
--- a/web/src/lang/backend/zh-cn/crud/crud.ts
+++ b/web/src/lang/backend/zh-cn/crud/crud.ts
@@ -69,6 +69,10 @@ export default {
'Generated Data Model Location': '生成的数据模型位置',
'Generated Validator Location': '生成的验证器位置',
'WEB end view directory': 'WEB端视图目录',
+ 'Database connection': '数据库连接配置标识',
+ 'Database connection help': '您可以在 config/database.php 内配置多个数据库连接,然后在此处选择它',
+ 'Check model class': "请检查以上数据模型类中是否已经配置 protected $connection = '{connection}';",
+ 'There is no connection attribute in model class': '未配置请手动配置。',
'Common model': '公共模型',
'Advanced Configuration': '高级配置',
'Common Fields': '常用字段',
diff --git a/web/src/views/backend/crud/design.vue b/web/src/views/backend/crud/design.vue
index 1907a9be..44dc8a5b 100644
--- a/web/src/views/backend/crud/design.vue
+++ b/web/src/views/backend/crud/design.vue
@@ -138,6 +138,20 @@
labelWidth: 140,
}"
/>
+