mirror of
https://gitee.com/wonderful-code/buildadmin
synced 2024-11-21 22:55:36 +00:00
feat(CRUD):多数据库连接配置支持
This commit is contained in:
parent
c95fc126d0
commit
bbeb267649
@ -59,7 +59,7 @@ class Crud extends Backend
|
|||||||
*/
|
*/
|
||||||
protected array $dtStringToArray = ['checkbox', 'selects', 'remoteSelects', 'city', 'images', 'files'];
|
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
|
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') {
|
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['beforeInsertMixins'] = [];
|
||||||
$this->modelData['beforeInsert'] = '';
|
$this->modelData['beforeInsert'] = '';
|
||||||
$this->modelData['afterInsert'] = '';
|
$this->modelData['afterInsert'] = '';
|
||||||
|
$this->modelData['connection'] = $table['databaseConnection'];
|
||||||
$this->modelData['name'] = $tableName;
|
$this->modelData['name'] = $tableName;
|
||||||
$this->modelData['className'] = $modelFile['lastName'];
|
$this->modelData['className'] = $modelFile['lastName'];
|
||||||
$this->modelData['namespace'] = $modelFile['namespace'];
|
$this->modelData['namespace'] = $modelFile['namespace'];
|
||||||
@ -205,7 +206,7 @@ class Crud extends Backend
|
|||||||
|
|
||||||
// 关联表数据解析
|
// 关联表数据解析
|
||||||
if (in_array($field['designType'], ['remoteSelect', 'remoteSelects'])) {
|
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();
|
$connection = TableManager::getConnection($info['table']['databaseConnection']);
|
||||||
if ($adapter->hasTable($info['table']['name'])) {
|
$tableName = TableManager::tableName($info['table']['name'], false, $connection);
|
||||||
$info['table']['empty'] = Db::name($info['table']['name'])->limit(1)->select()->isEmpty();
|
$adapter = TableManager::phinxAdapter(true, $connection);
|
||||||
|
if ($adapter->hasTable($tableName)) {
|
||||||
|
$info['table']['empty'] = Db::connect($connection)
|
||||||
|
->name($tableName)
|
||||||
|
->limit(1)
|
||||||
|
->select()
|
||||||
|
->isEmpty();
|
||||||
} else {
|
} else {
|
||||||
$info['table']['empty'] = true;
|
$info['table']['empty'] = true;
|
||||||
}
|
}
|
||||||
@ -438,9 +445,13 @@ class Crud extends Backend
|
|||||||
*/
|
*/
|
||||||
public function checkCrudLog(): void
|
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')
|
$crudLog = Db::name('crud_log')
|
||||||
->where('table_name', $table)
|
->where('table_name', $table)
|
||||||
|
->where('connection', $connection)
|
||||||
->order('create_time desc')
|
->order('create_time desc')
|
||||||
->find();
|
->find();
|
||||||
$this->success('', [
|
$this->success('', [
|
||||||
@ -455,27 +466,36 @@ class Crud extends Backend
|
|||||||
public function parseFieldData(): void
|
public function parseFieldData(): void
|
||||||
{
|
{
|
||||||
AdminLog::setTitle(__('Parse field data'));
|
AdminLog::setTitle(__('Parse field data'));
|
||||||
$type = $this->request->post('type');
|
$type = $this->request->post('type');
|
||||||
$table = $this->request->post('table');
|
$table = $this->request->post('table');
|
||||||
$table = TableManager::tableName($table);
|
$connection = $this->request->post('connection');
|
||||||
|
$connection = TableManager::getConnection($connection);
|
||||||
|
|
||||||
|
$table = TableManager::tableName($table, true, $connection);
|
||||||
|
$connectionConfig = TableManager::getConnectionConfig($connection);
|
||||||
|
|
||||||
if ($type == 'db') {
|
if ($type == 'db') {
|
||||||
$sql = 'SELECT * FROM `information_schema`.`tables` '
|
$sql = 'SELECT * FROM `information_schema`.`tables` '
|
||||||
. 'WHERE TABLE_SCHEMA = ? AND table_name = ?';
|
. '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) {
|
if (!$tableInfo) {
|
||||||
$this->error(__('Record not found'));
|
$this->error(__('Record not found'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数据表是否有数据
|
// 数据表是否有数据
|
||||||
$adapter = TableManager::phinxAdapter(false);
|
$adapter = TableManager::phinxAdapter(false, $connection);
|
||||||
if ($adapter->hasTable($table)) {
|
if ($adapter->hasTable($table)) {
|
||||||
$empty = Db::table($table)->limit(1)->select()->isEmpty();
|
$empty = Db::connect($connection)
|
||||||
|
->table($table)
|
||||||
|
->limit(1)
|
||||||
|
->select()
|
||||||
|
->isEmpty();
|
||||||
} else {
|
} else {
|
||||||
$empty = true;
|
$empty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->success('', [
|
$this->success('', [
|
||||||
'columns' => Helper::parseTableColumns($table),
|
'columns' => Helper::parseTableColumns($table, false, $connection),
|
||||||
'comment' => $tableInfo[0]['TABLE_COMMENT'] ?? '',
|
'comment' => $tableInfo[0]['TABLE_COMMENT'] ?? '',
|
||||||
'empty' => $empty,
|
'empty' => $empty,
|
||||||
]);
|
]);
|
||||||
@ -490,6 +510,7 @@ class Crud extends Backend
|
|||||||
{
|
{
|
||||||
$table = $this->request->post('table');
|
$table = $this->request->post('table');
|
||||||
$controllerFile = $this->request->post('controllerFile', '');
|
$controllerFile = $this->request->post('controllerFile', '');
|
||||||
|
$connection = $this->request->post('connection');
|
||||||
|
|
||||||
if (!$table) {
|
if (!$table) {
|
||||||
$this->error(__('Parameter error'));
|
$this->error(__('Parameter error'));
|
||||||
@ -505,8 +526,8 @@ class Crud extends Backend
|
|||||||
$this->error($e->getMessage());
|
$this->error($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$tableList = TableManager::getTableList();
|
$tableList = TableManager::getTableList($connection);
|
||||||
$tableExist = array_key_exists(TableManager::tableName($table), $tableList);
|
$tableExist = array_key_exists(TableManager::tableName($table, true, $connection), $tableList);
|
||||||
$controllerExist = file_exists(root_path() . $controllerFile);
|
$controllerExist = file_exists(root_path() . $controllerFile);
|
||||||
|
|
||||||
if ($controllerExist || $tableExist) {
|
if ($controllerExist || $tableExist) {
|
||||||
@ -518,55 +539,21 @@ class Crud extends Backend
|
|||||||
$this->success();
|
$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 $field
|
||||||
|
* @param $table
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
private function parseJoinData($field): void
|
private function parseJoinData($field, $table): void
|
||||||
{
|
{
|
||||||
$dictEn = [];
|
$dictEn = [];
|
||||||
$dictZhCn = [];
|
$dictZhCn = [];
|
||||||
|
|
||||||
if ($field['form']['relation-fields'] && $field['form']['remote-table']) {
|
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']);
|
$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)$/';
|
$rnPattern = '/(.*)(_ids|_id)$/';
|
||||||
if (preg_match($rnPattern, $field['name'])) {
|
if (preg_match($rnPattern, $field['name'])) {
|
||||||
$relationName = parse_name(preg_replace($rnPattern, '$1', $field['name']), 1, false);
|
$relationName = parse_name(preg_replace($rnPattern, '$1', $field['name']), 1, false);
|
||||||
@ -586,6 +573,7 @@ class Crud extends Backend
|
|||||||
$joinModelData['beforeInsertMixins'] = [];
|
$joinModelData['beforeInsertMixins'] = [];
|
||||||
$joinModelData['beforeInsert'] = '';
|
$joinModelData['beforeInsert'] = '';
|
||||||
$joinModelData['afterInsert'] = '';
|
$joinModelData['afterInsert'] = '';
|
||||||
|
$joinModelData['connection'] = $table['databaseConnection'];
|
||||||
$joinModelData['name'] = $tableName;
|
$joinModelData['name'] = $tableName;
|
||||||
$joinModelData['className'] = $joinModelFile['lastName'];
|
$joinModelData['className'] = $joinModelFile['lastName'];
|
||||||
$joinModelData['namespace'] = $joinModelFile['namespace'];
|
$joinModelData['namespace'] = $joinModelFile['namespace'];
|
||||||
|
@ -281,10 +281,13 @@ class Helper
|
|||||||
]);
|
]);
|
||||||
return $data['id'];
|
return $data['id'];
|
||||||
}
|
}
|
||||||
$log = CrudLog::create([
|
|
||||||
|
$connection = $data['table']['databaseConnection'] ?: config('database.default');
|
||||||
|
$log = CrudLog::create([
|
||||||
'table_name' => $data['table']['name'],
|
'table_name' => $data['table']['name'],
|
||||||
'table' => $data['table'],
|
'table' => $data['table'],
|
||||||
'fields' => $data['fields'],
|
'fields' => $data['fields'],
|
||||||
|
'connection' => $connection,
|
||||||
'status' => $data['status'],
|
'status' => $data['status'],
|
||||||
]);
|
]);
|
||||||
return $log->id;
|
return $log->id;
|
||||||
@ -424,16 +427,17 @@ class Helper
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 表字段排序
|
* 表字段排序
|
||||||
* @param string $tableName 表名
|
* @param string $tableName 表名
|
||||||
* @param array $fields 字段数据
|
* @param array $fields 字段数据
|
||||||
* @param array $designChange 前端字段改变数据
|
* @param array $designChange 前端字段改变数据
|
||||||
|
* @param ?string $connection 数据库连接标识
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Throwable
|
* @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) {
|
if ($designChange) {
|
||||||
$table = TableManager::phinxTable($tableName, [], false);
|
$table = TableManager::phinxTable($tableName, [], false, $connection);
|
||||||
foreach ($designChange as $item) {
|
foreach ($designChange as $item) {
|
||||||
if (!$item['sync']) continue;
|
if (!$item['sync']) continue;
|
||||||
|
|
||||||
@ -469,10 +473,10 @@ class Helper
|
|||||||
*/
|
*/
|
||||||
public static function handleTableDesign(array $table, array $fields): array
|
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'] ?? '';
|
$comment = $table['comment'] ?? '';
|
||||||
$designChange = $table['designChange'] ?? [];
|
$designChange = $table['designChange'] ?? [];
|
||||||
$adapter = TableManager::phinxAdapter(false);
|
$adapter = TableManager::phinxAdapter(false, $table['databaseConnection']);
|
||||||
|
|
||||||
$pk = self::searchArray($fields, function ($item) {
|
$pk = self::searchArray($fields, function ($item) {
|
||||||
return $item['primaryKey'];
|
return $item['primaryKey'];
|
||||||
@ -482,8 +486,8 @@ class Helper
|
|||||||
if ($adapter->hasTable($name)) {
|
if ($adapter->hasTable($name)) {
|
||||||
// 更新表
|
// 更新表
|
||||||
if ($designChange) {
|
if ($designChange) {
|
||||||
$table = TableManager::phinxTable($name, [], false);
|
$tableManager = TableManager::phinxTable($name, [], false, $table['databaseConnection']);
|
||||||
$table->changeComment($comment)->update();
|
$tableManager->changeComment($comment)->update();
|
||||||
|
|
||||||
// 改名和删除操作优先
|
// 改名和删除操作优先
|
||||||
$priorityOpt = false;
|
$priorityOpt = false;
|
||||||
@ -491,23 +495,23 @@ class Helper
|
|||||||
|
|
||||||
if (!$item['sync']) continue;
|
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']]));
|
throw new BaException(__($item['type'] . ' fail not exist', [$item['oldName']]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($item['type'] == 'change-field-name') {
|
if ($item['type'] == 'change-field-name') {
|
||||||
$priorityOpt = true;
|
$priorityOpt = true;
|
||||||
$table->renameColumn($item['oldName'], $item['newName']);
|
$tableManager->renameColumn($item['oldName'], $item['newName']);
|
||||||
} elseif ($item['type'] == 'del-field') {
|
} elseif ($item['type'] == 'del-field') {
|
||||||
$priorityOpt = true;
|
$priorityOpt = true;
|
||||||
$table->removeColumn($item['oldName']);
|
$tableManager->removeColumn($item['oldName']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存需要优先执行的操作,避免先改名再改属性时找不到字段
|
// 保存需要优先执行的操作,避免先改名再改属性时找不到字段
|
||||||
if ($priorityOpt) {
|
if ($priorityOpt) {
|
||||||
$table->update();
|
$tableManager->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改字段属性和添加字段操作
|
// 修改字段属性和添加字段操作
|
||||||
@ -517,7 +521,7 @@ class Helper
|
|||||||
|
|
||||||
if ($item['type'] == 'change-field-attr') {
|
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']]));
|
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) {
|
$phinxFieldData = self::getPhinxFieldData(self::searchArray($fields, function ($field) use ($item) {
|
||||||
return $field['name'] == $item['oldName'];
|
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') {
|
} elseif ($item['type'] == 'add-field') {
|
||||||
|
|
||||||
if ($table->hasColumn($item['newName'])) {
|
if ($tableManager->hasColumn($item['newName'])) {
|
||||||
// 字段已经存在
|
// 字段已经存在
|
||||||
throw new BaException(__($item['type'] . ' fail exist', [$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) {
|
$phinxFieldData = self::getPhinxFieldData(self::searchArray($fields, function ($field) use ($item) {
|
||||||
return $field['name'] == $item['newName'];
|
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 {
|
} else {
|
||||||
// 创建表
|
// 创建表
|
||||||
$table = TableManager::phinxTable($name, [
|
$tableManager = TableManager::phinxTable($name, [
|
||||||
'id' => false,
|
'id' => false,
|
||||||
'comment' => $comment,
|
'comment' => $comment,
|
||||||
'row_format' => 'DYNAMIC',
|
'row_format' => 'DYNAMIC',
|
||||||
'primary_key' => $pk,
|
'primary_key' => $pk,
|
||||||
'collation' => 'utf8mb4_unicode_ci',
|
'collation' => 'utf8mb4_unicode_ci',
|
||||||
], false);
|
], false, $table['databaseConnection']);
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
$phinxFieldData = self::getPhinxFieldData($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];
|
return [$pk];
|
||||||
@ -732,15 +736,19 @@ class Helper
|
|||||||
* 根据数据表解析字段数据
|
* 根据数据表解析字段数据
|
||||||
* @throws Throwable
|
* @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` '
|
$sql = 'SELECT * FROM `information_schema`.`columns` '
|
||||||
. 'WHERE TABLE_SCHEMA = ? AND table_name = ? '
|
. 'WHERE TABLE_SCHEMA = ? AND table_name = ? '
|
||||||
. 'ORDER BY ORDINAL_POSITION';
|
. 'ORDER BY ORDINAL_POSITION';
|
||||||
|
|
||||||
$columns = [];
|
$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) {
|
foreach ($tableColumn as $item) {
|
||||||
$isNullAble = $item['IS_NULLABLE'] == 'YES';
|
$isNullAble = $item['IS_NULLABLE'] == 'YES';
|
||||||
if (str_contains($item['COLUMN_TYPE'], '(')) {
|
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
|
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';
|
$modelData['autoWriteTimestamp'] = array_key_exists(self::$createTimeField, $fieldsMap) || array_key_exists(self::$updateTimeField, $fieldsMap) ? 'true' : 'false';
|
||||||
if ($modelData['autoWriteTimestamp'] == 'true') {
|
if ($modelData['autoWriteTimestamp'] == 'true') {
|
||||||
$modelData['createTime'] = array_key_exists(self::$createTimeField, $fieldsMap) ? '' : "\n" . self::tab() . "protected \$createTime = false;";
|
$modelData['createTime'] = array_key_exists(self::$createTimeField, $fieldsMap) ? '' : "\n" . self::tab() . "protected \$createTime = false;";
|
||||||
|
@ -8,7 +8,7 @@ use think\Model;
|
|||||||
* {%className%}
|
* {%className%}
|
||||||
*/
|
*/
|
||||||
class {%className%} extends Model
|
class {%className%} extends Model
|
||||||
{{%pk%}
|
{{%connection%}{%pk%}
|
||||||
// 表名
|
// 表名
|
||||||
protected $name = '{%name%}';
|
protected $name = '{%name%}';
|
||||||
|
|
||||||
|
@ -26,5 +26,11 @@ class Version206 extends Migrator
|
|||||||
$table = $this->table('config');
|
$table = $this->table('config');
|
||||||
$table->insert($rows)->saveData();
|
$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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
export function getFileData(table: string, commonModel = 0) {
|
||||||
return createAxios({
|
return createAxios({
|
||||||
url: url + 'getFileData',
|
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({
|
return createAxios({
|
||||||
url: url + 'parseFieldData',
|
url: url + 'parseFieldData',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: {
|
data: data,
|
||||||
type: type,
|
|
||||||
table: table,
|
|
||||||
sql: sql,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,12 +67,13 @@ export function postDel(id: number) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkCrudLog(table: string) {
|
export function checkCrudLog(table: string, connection: string) {
|
||||||
return createAxios({
|
return createAxios({
|
||||||
url: url + 'checkCrudLog',
|
url: url + 'checkCrudLog',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
table: table,
|
table: table,
|
||||||
|
connection: connection,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,10 @@ export default {
|
|||||||
'Generated Validator Location': 'Generated Validator Location',
|
'Generated Validator Location': 'Generated Validator Location',
|
||||||
'Common model': 'Common model',
|
'Common model': 'Common model',
|
||||||
'WEB end view directory': 'WEB end view directory',
|
'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',
|
'Advanced Configuration': 'Advanced Configuration',
|
||||||
'Common Fields': 'Common Fields',
|
'Common Fields': 'Common Fields',
|
||||||
'Base Fields': 'Base Fields',
|
'Base Fields': 'Base Fields',
|
||||||
|
@ -69,6 +69,10 @@ export default {
|
|||||||
'Generated Data Model Location': '生成的数据模型位置',
|
'Generated Data Model Location': '生成的数据模型位置',
|
||||||
'Generated Validator Location': '生成的验证器位置',
|
'Generated Validator Location': '生成的验证器位置',
|
||||||
'WEB end view directory': 'WEB端视图目录',
|
'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': '公共模型',
|
'Common model': '公共模型',
|
||||||
'Advanced Configuration': '高级配置',
|
'Advanced Configuration': '高级配置',
|
||||||
'Common Fields': '常用字段',
|
'Common Fields': '常用字段',
|
||||||
|
@ -138,6 +138,20 @@
|
|||||||
labelWidth: 140,
|
labelWidth: 140,
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
<FormItem
|
||||||
|
:label="t('crud.crud.Database connection')"
|
||||||
|
v-model="state.table.databaseConnection"
|
||||||
|
type="remoteSelect"
|
||||||
|
:attr="{
|
||||||
|
labelWidth: 140,
|
||||||
|
blockHelp: t('crud.crud.Database connection help'),
|
||||||
|
}"
|
||||||
|
:input-attr="{
|
||||||
|
pk: 'key',
|
||||||
|
field: 'key',
|
||||||
|
'remote-url': getDatabaseConnectionListUrl,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
@ -418,15 +432,31 @@
|
|||||||
v-if="state.remoteSelectPre.index != -1 && state.fields[state.remoteSelectPre.index]"
|
v-if="state.remoteSelectPre.index != -1 && state.fields[state.remoteSelectPre.index]"
|
||||||
>
|
>
|
||||||
<FormItem
|
<FormItem
|
||||||
prop="table"
|
|
||||||
type="select"
|
|
||||||
:label="t('crud.crud.Associated Data Table')"
|
:label="t('crud.crud.Associated Data Table')"
|
||||||
v-model="state.remoteSelectPre.form.table"
|
v-model="state.remoteSelectPre.form.table"
|
||||||
:key="JSON.stringify(state.remoteSelectPre.dbList)"
|
type="remoteSelect"
|
||||||
:data="{
|
:key="state.table.databaseConnection"
|
||||||
content: state.remoteSelectPre.dbList,
|
:input-attr="{
|
||||||
|
pk: 'table',
|
||||||
|
field: 'comment',
|
||||||
|
params: {
|
||||||
|
connection: state.table.databaseConnection,
|
||||||
|
samePrefix: 1,
|
||||||
|
excludeTable: [
|
||||||
|
'area',
|
||||||
|
'token',
|
||||||
|
'captcha',
|
||||||
|
'admin_group_access',
|
||||||
|
'config',
|
||||||
|
'admin_log',
|
||||||
|
'user_money_log',
|
||||||
|
'user_score_log',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'remote-url': getTableListUrl,
|
||||||
|
onChange: onJoinTableChange,
|
||||||
}"
|
}"
|
||||||
:input-attr="{ onChange: onJoinTableChange }"
|
prop="table"
|
||||||
/>
|
/>
|
||||||
<div v-loading="state.loading.remoteSelect">
|
<div v-loading="state.loading.remoteSelect">
|
||||||
<FormItem
|
<FormItem
|
||||||
@ -494,6 +524,16 @@
|
|||||||
),
|
),
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
<el-form-item
|
||||||
|
v-if="state.table.databaseConnection && state.remoteSelectPre.form.modelFile"
|
||||||
|
:label="t('crud.crud.Database connection')"
|
||||||
|
>
|
||||||
|
<el-text size="large" type="danger">{{ state.table.databaseConnection }}</el-text>
|
||||||
|
<div class="block-help">
|
||||||
|
<div>{{ t('crud.crud.Check model class', { connection: state.table.databaseConnection }) }}</div>
|
||||||
|
<div>{{ t('crud.crud.There is no connection attribute in model class') }}</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="t('Reminder')">
|
<el-form-item :label="t('Reminder')">
|
||||||
<div class="block-help">
|
<div class="block-help">
|
||||||
{{ t('crud.crud.Design remote select tips') }}
|
{{ t('crud.crud.Design remote select tips') }}
|
||||||
@ -604,8 +644,8 @@ import { useTemplateRefsList } from '@vueuse/core'
|
|||||||
import { changeStep, state as crudState, getTableAttr, fieldItem, designTypes, tableFieldsKey } from '/@/views/backend/crud/index'
|
import { changeStep, state as crudState, getTableAttr, fieldItem, designTypes, tableFieldsKey } from '/@/views/backend/crud/index'
|
||||||
import { ElNotification, ElMessageBox, ElMessage } from 'element-plus'
|
import { ElNotification, ElMessageBox, ElMessage } from 'element-plus'
|
||||||
import type { FormItemRule, FormInstance, TimelineItemProps, MessageHandler } from 'element-plus'
|
import type { FormItemRule, FormInstance, TimelineItemProps, MessageHandler } from 'element-plus'
|
||||||
import { getDatabaseList, getFileData, generateCheck, generate, parseFieldData, postLogStart } from '/@/api/backend/crud'
|
import { getFileData, generateCheck, generate, parseFieldData, postLogStart } from '/@/api/backend/crud'
|
||||||
import { getTableFieldList } from '/@/api/common'
|
import { getTableFieldList, getTableListUrl, getDatabaseConnectionListUrl } from '/@/api/common'
|
||||||
import { buildValidatorData, regularVarName } from '/@/utils/validate'
|
import { buildValidatorData, regularVarName } from '/@/utils/validate'
|
||||||
import { getArrayKey } from '/@/utils/common'
|
import { getArrayKey } from '/@/utils/common'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
@ -635,6 +675,7 @@ const state: {
|
|||||||
controllerFile: string
|
controllerFile: string
|
||||||
validateFile: string
|
validateFile: string
|
||||||
webViewsDir: string
|
webViewsDir: string
|
||||||
|
databaseConnection: string
|
||||||
designChange: TableDesignChange[]
|
designChange: TableDesignChange[]
|
||||||
rebuild: string
|
rebuild: string
|
||||||
}
|
}
|
||||||
@ -644,7 +685,6 @@ const state: {
|
|||||||
remoteSelectPre: {
|
remoteSelectPre: {
|
||||||
show: boolean
|
show: boolean
|
||||||
index: number
|
index: number
|
||||||
dbList: anyObj
|
|
||||||
fieldList: anyObj
|
fieldList: anyObj
|
||||||
modelFileList: anyObj
|
modelFileList: anyObj
|
||||||
controllerFileList: anyObj
|
controllerFileList: anyObj
|
||||||
@ -692,6 +732,7 @@ const state: {
|
|||||||
controllerFile: '',
|
controllerFile: '',
|
||||||
validateFile: '',
|
validateFile: '',
|
||||||
webViewsDir: '',
|
webViewsDir: '',
|
||||||
|
databaseConnection: '',
|
||||||
designChange: [],
|
designChange: [],
|
||||||
rebuild: 'No',
|
rebuild: 'No',
|
||||||
},
|
},
|
||||||
@ -701,7 +742,6 @@ const state: {
|
|||||||
remoteSelectPre: {
|
remoteSelectPre: {
|
||||||
show: false,
|
show: false,
|
||||||
index: -1,
|
index: -1,
|
||||||
dbList: [],
|
|
||||||
fieldList: [],
|
fieldList: [],
|
||||||
modelFileList: [],
|
modelFileList: [],
|
||||||
controllerFileList: [],
|
controllerFileList: [],
|
||||||
@ -884,34 +924,30 @@ const showRemoteSelectPre = (index: number, hideDelField = false) => {
|
|||||||
state.remoteSelectPre.loading = true
|
state.remoteSelectPre.loading = true
|
||||||
state.remoteSelectPre.index = index
|
state.remoteSelectPre.index = index
|
||||||
state.remoteSelectPre.hideDelField = hideDelField
|
state.remoteSelectPre.hideDelField = hideDelField
|
||||||
getDatabaseList()
|
|
||||||
.then((res) => {
|
if (state.fields[index] && state.fields[index].form['remote-table'].value) {
|
||||||
state.remoteSelectPre.dbList = res.data.dbs
|
state.remoteSelectPre.form.table = state.fields[index].form['remote-table'].value
|
||||||
if (state.fields[index] && state.fields[index].form['remote-table'].value) {
|
state.remoteSelectPre.form.pk = state.fields[index].form['remote-pk'].value
|
||||||
state.remoteSelectPre.form.table = state.fields[index].form['remote-table'].value
|
state.remoteSelectPre.form.label = state.fields[index].form['remote-field'].value
|
||||||
state.remoteSelectPre.form.pk = state.fields[index].form['remote-pk'].value
|
state.remoteSelectPre.form.controllerFile = state.fields[index].form['remote-controller'].value
|
||||||
state.remoteSelectPre.form.label = state.fields[index].form['remote-field'].value
|
state.remoteSelectPre.form.modelFile = state.fields[index].form['remote-model'].value
|
||||||
state.remoteSelectPre.form.controllerFile = state.fields[index].form['remote-controller'].value
|
state.remoteSelectPre.form.joinField = state.fields[index].form['relation-fields'].value.split(',')
|
||||||
state.remoteSelectPre.form.modelFile = state.fields[index].form['remote-model'].value
|
getTableFieldList(state.fields[index].form['remote-table'].value).then((res) => {
|
||||||
state.remoteSelectPre.form.joinField = state.fields[index].form['relation-fields'].value.split(',')
|
const fieldSelect: anyObj = {}
|
||||||
getTableFieldList(state.fields[index].form['remote-table'].value).then((res) => {
|
for (const key in res.data.fieldList) {
|
||||||
const fieldSelect: anyObj = {}
|
fieldSelect[key] = (key ? key + ' - ' : '') + res.data.fieldList[key]
|
||||||
for (const key in res.data.fieldList) {
|
|
||||||
fieldSelect[key] = (key ? key + ' - ' : '') + res.data.fieldList[key]
|
|
||||||
}
|
|
||||||
state.remoteSelectPre.fieldList = fieldSelect
|
|
||||||
})
|
|
||||||
if (isEmpty(state.remoteSelectPre.modelFileList) || isEmpty(state.remoteSelectPre.controllerFileList)) {
|
|
||||||
getFileData(state.fields[index].form['remote-table'].value).then((res) => {
|
|
||||||
state.remoteSelectPre.modelFileList = res.data.modelFileList
|
|
||||||
state.remoteSelectPre.controllerFileList = res.data.controllerFileList
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
state.remoteSelectPre.fieldList = fieldSelect
|
||||||
})
|
})
|
||||||
.finally(() => {
|
if (isEmpty(state.remoteSelectPre.modelFileList) || isEmpty(state.remoteSelectPre.controllerFileList)) {
|
||||||
state.remoteSelectPre.loading = false
|
getFileData(state.fields[index].form['remote-table'].value).then((res) => {
|
||||||
})
|
state.remoteSelectPre.modelFileList = res.data.modelFileList
|
||||||
|
state.remoteSelectPre.controllerFileList = res.data.controllerFileList
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.remoteSelectPre.loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const onEditField = (index: number, field: FieldItem) => {
|
const onEditField = (index: number, field: FieldItem) => {
|
||||||
@ -987,6 +1023,7 @@ const onGenerate = () => {
|
|||||||
state.loading.generate = true
|
state.loading.generate = true
|
||||||
generateCheck({
|
generateCheck({
|
||||||
table: state.table.name,
|
table: state.table.name,
|
||||||
|
connection: state.table.databaseConnection,
|
||||||
controllerFile: state.table.controllerFile,
|
controllerFile: state.table.controllerFile,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -1112,7 +1149,12 @@ const loadData = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 从数据表或sql开始
|
// 从数据表或sql开始
|
||||||
parseFieldData(crudState.type, crudState.startData.db, crudState.startData.sql)
|
parseFieldData({
|
||||||
|
type: crudState.type,
|
||||||
|
table: crudState.startData.table,
|
||||||
|
sql: crudState.startData.sql,
|
||||||
|
connection: crudState.startData.databaseConnection,
|
||||||
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
let fields = []
|
let fields = []
|
||||||
for (const key in res.data.columns) {
|
for (const key in res.data.columns) {
|
||||||
@ -1134,12 +1176,13 @@ const loadData = () => {
|
|||||||
}
|
}
|
||||||
state.fields = fields
|
state.fields = fields
|
||||||
state.table.comment = res.data.comment
|
state.table.comment = res.data.comment
|
||||||
|
state.table.databaseConnection = crudState.startData.databaseConnection
|
||||||
if (res.data.empty) {
|
if (res.data.empty) {
|
||||||
state.table.rebuild = 'Yes'
|
state.table.rebuild = 'Yes'
|
||||||
}
|
}
|
||||||
if (crudState.type == 'db' && crudState.startData.db) {
|
if (crudState.type == 'db' && crudState.startData.table) {
|
||||||
state.table.name = crudState.startData.db
|
state.table.name = crudState.startData.table
|
||||||
onTableChange(crudState.startData.db)
|
onTableChange(crudState.startData.table)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
@ -27,17 +27,19 @@ export const state: {
|
|||||||
step: 'Start' | 'Design'
|
step: 'Start' | 'Design'
|
||||||
type: string
|
type: string
|
||||||
startData: {
|
startData: {
|
||||||
db: string
|
|
||||||
sql: string
|
sql: string
|
||||||
|
table: string
|
||||||
logId: string
|
logId: string
|
||||||
|
databaseConnection: string
|
||||||
}
|
}
|
||||||
} = reactive({
|
} = reactive({
|
||||||
step: 'Start',
|
step: 'Start',
|
||||||
type: '',
|
type: '',
|
||||||
startData: {
|
startData: {
|
||||||
db: '',
|
|
||||||
sql: '',
|
sql: '',
|
||||||
|
table: '',
|
||||||
logId: '',
|
logId: '',
|
||||||
|
databaseConnection: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -13,7 +13,15 @@
|
|||||||
:buttons="['refresh', 'quickSearch', 'columnDisplay']"
|
:buttons="['refresh', 'quickSearch', 'columnDisplay']"
|
||||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('crud.log.quick Search Fields') })"
|
:quick-search-placeholder="t('Quick search placeholder', { fields: t('crud.log.quick Search Fields') })"
|
||||||
/>
|
/>
|
||||||
<Table ref="tableRef" />
|
<Table ref="tableRef">
|
||||||
|
<template #tableName>
|
||||||
|
<el-table-column :show-overflow-tooltip="true" prop="table_name" align="center" :label="t('crud.log.table_name')">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ (scope.row.table.databaseConnection ? scope.row.table.databaseConnection + '.' : '') + scope.row.table.name }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -105,11 +113,10 @@ const baTable = new baTableClass(
|
|||||||
{ label: t('crud.log.id'), prop: 'id', align: 'center', width: 70, operator: '=', operatorPlaceholder: t('Id'), sortable: 'custom' },
|
{ label: t('crud.log.id'), prop: 'id', align: 'center', width: 70, operator: '=', operatorPlaceholder: t('Id'), sortable: 'custom' },
|
||||||
{
|
{
|
||||||
label: t('crud.log.table_name'),
|
label: t('crud.log.table_name'),
|
||||||
prop: 'table_name',
|
|
||||||
align: 'center',
|
|
||||||
operatorPlaceholder: t('Fuzzy query'),
|
operatorPlaceholder: t('Fuzzy query'),
|
||||||
operator: 'LIKE',
|
operator: 'LIKE',
|
||||||
sortable: false,
|
render: 'slot',
|
||||||
|
slotName: 'tableName',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('crud.log.status'),
|
label: t('crud.log.status'),
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
class="ba-operate-dialog select-db-dialog"
|
class="ba-operate-dialog select-table-dialog"
|
||||||
v-model="state.dialog.visible"
|
v-model="state.dialog.visible"
|
||||||
:title="state.dialog.type == 'sql' ? t('crud.crud.Please enter SQL') : t('crud.crud.Please select a data table')"
|
:title="state.dialog.type == 'sql' ? t('crud.crud.Please enter SQL') : t('crud.crud.Please select a data table')"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
@ -67,7 +67,7 @@
|
|||||||
<el-form
|
<el-form
|
||||||
:label-width="140"
|
:label-width="140"
|
||||||
@keyup.enter="onSubmit()"
|
@keyup.enter="onSubmit()"
|
||||||
class="select-db-form"
|
class="select-table-form"
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
:model="crudState.startData"
|
:model="crudState.startData"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
@ -87,22 +87,51 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else-if="state.dialog.type == 'db'">
|
<template v-else-if="state.dialog.type == 'db'">
|
||||||
<FormItem
|
<FormItem
|
||||||
:label="t('crud.crud.data sheet')"
|
:label="t('crud.crud.Database connection')"
|
||||||
class="select-db"
|
v-model="crudState.startData.databaseConnection"
|
||||||
v-model="crudState.startData.db"
|
type="remoteSelect"
|
||||||
type="select"
|
|
||||||
:key="JSON.stringify(state.dialog.dbList)"
|
|
||||||
:placeholder="t('crud.crud.Please select a data table')"
|
|
||||||
:data="{
|
|
||||||
content: state.dialog.dbList,
|
|
||||||
}"
|
|
||||||
:attr="{
|
:attr="{
|
||||||
|
labelWidth: 140,
|
||||||
|
blockHelp: t('crud.crud.Database connection help'),
|
||||||
|
}"
|
||||||
|
:input-attr="{
|
||||||
|
pk: 'key',
|
||||||
|
field: 'key',
|
||||||
|
'remote-url': getDatabaseConnectionListUrl,
|
||||||
|
onChange: onDatabaseChange,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<FormItem
|
||||||
|
:label="t('crud.crud.data sheet')"
|
||||||
|
v-model="crudState.startData.table"
|
||||||
|
type="remoteSelect"
|
||||||
|
:key="crudState.startData.databaseConnection"
|
||||||
|
:placeholder="t('crud.crud.Please select a data table')"
|
||||||
|
:attr="{
|
||||||
|
labelWidth: 140,
|
||||||
blockHelp: t('crud.crud.data sheet help'),
|
blockHelp: t('crud.crud.data sheet help'),
|
||||||
}"
|
}"
|
||||||
:input-attr="{
|
:input-attr="{
|
||||||
onChange: onDbStartChange,
|
pk: 'table',
|
||||||
|
field: 'comment',
|
||||||
|
params: {
|
||||||
|
connection: crudState.startData.databaseConnection,
|
||||||
|
samePrefix: 1,
|
||||||
|
excludeTable: [
|
||||||
|
'area',
|
||||||
|
'token',
|
||||||
|
'captcha',
|
||||||
|
'admin_group_access',
|
||||||
|
'config',
|
||||||
|
'admin_log',
|
||||||
|
'user_money_log',
|
||||||
|
'user_score_log',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'remote-url': getTableListUrl,
|
||||||
|
onChange: onTableStartChange,
|
||||||
}"
|
}"
|
||||||
prop="db"
|
prop="table"
|
||||||
/>
|
/>
|
||||||
<el-alert
|
<el-alert
|
||||||
v-if="state.successRecord"
|
v-if="state.successRecord"
|
||||||
@ -132,7 +161,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { getDatabaseList, checkCrudLog } from '/@/api/backend/crud'
|
import { checkCrudLog } from '/@/api/backend/crud'
|
||||||
import FormItem from '/@/components/formItem/index.vue'
|
import FormItem from '/@/components/formItem/index.vue'
|
||||||
import { changeStep, state as crudState } from '/@/views/backend/crud/index'
|
import { changeStep, state as crudState } from '/@/views/backend/crud/index'
|
||||||
import { ElNotification } from 'element-plus'
|
import { ElNotification } from 'element-plus'
|
||||||
@ -140,6 +169,7 @@ import type { FormInstance, FormItemRule } from 'element-plus'
|
|||||||
import { buildValidatorData } from '/@/utils/validate'
|
import { buildValidatorData } from '/@/utils/validate'
|
||||||
import CrudLog from '/@/views/backend/crud/log.vue'
|
import CrudLog from '/@/views/backend/crud/log.vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { getDatabaseConnectionListUrl, getTableListUrl } from '/@/api/common'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const sqlInputRef = ref()
|
const sqlInputRef = ref()
|
||||||
@ -148,7 +178,6 @@ const state = reactive({
|
|||||||
dialog: {
|
dialog: {
|
||||||
type: '',
|
type: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
dbList: [],
|
|
||||||
},
|
},
|
||||||
showLog: false,
|
showLog: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -164,15 +193,12 @@ const onShowDialog = (type: string) => {
|
|||||||
}, 200)
|
}, 200)
|
||||||
} else if (type == 'db') {
|
} else if (type == 'db') {
|
||||||
state.successRecord = 0
|
state.successRecord = 0
|
||||||
crudState.startData.db = ''
|
crudState.startData.table = ''
|
||||||
getDatabaseList().then((res) => {
|
|
||||||
state.dialog.dbList = res.data.dbs
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||||
db: [buildValidatorData({ name: 'required', message: t('crud.crud.Please select a data table') })],
|
table: [buildValidatorData({ name: 'required', message: t('crud.crud.Please select a data table') })],
|
||||||
})
|
})
|
||||||
|
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
@ -191,11 +217,16 @@ const onSubmit = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDbStartChange = () => {
|
const onDatabaseChange = () => {
|
||||||
if (crudState.startData.db) {
|
state.successRecord = 0
|
||||||
|
crudState.startData.table = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTableStartChange = () => {
|
||||||
|
if (crudState.startData.table) {
|
||||||
// 检查是否有CRUD记录
|
// 检查是否有CRUD记录
|
||||||
state.loading = true
|
state.loading = true
|
||||||
checkCrudLog(crudState.startData.db)
|
checkCrudLog(crudState.startData.table, crudState.startData.databaseConnection)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
state.successRecord = res.data.id
|
state.successRecord = res.data.id
|
||||||
})
|
})
|
||||||
@ -218,16 +249,17 @@ const isDev = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
:deep(.select-db-dialog) .el-dialog__body {
|
:deep(.select-table-dialog) .el-dialog__body {
|
||||||
height: unset;
|
height: unset;
|
||||||
.select-db-form {
|
.select-table-form {
|
||||||
width: 88%;
|
width: 88%;
|
||||||
|
padding: 40px 0;
|
||||||
}
|
}
|
||||||
.success-record-alert {
|
.success-record-alert {
|
||||||
width: calc(100% - 140px);
|
width: calc(100% - 140px);
|
||||||
margin-left: 140px;
|
margin-left: 140px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
margin-top: -30px;
|
margin-top: -10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.crud-title {
|
.crud-title {
|
||||||
@ -264,9 +296,6 @@ const isDev = () => {
|
|||||||
.sql-input {
|
.sql-input {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
.select-db {
|
|
||||||
margin: 40px 0;
|
|
||||||
}
|
|
||||||
.crud-tips {
|
.crud-tips {
|
||||||
margin-top: 60px;
|
margin-top: 60px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
Loading…
Reference in New Issue
Block a user