mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-12-02 12:07:37 +08:00
[Core] [Source] [Metadata] Refactor metadata (#746)
This commit is contained in:
commit
398928c521
@ -0,0 +1,23 @@
|
||||
package io.edurt.datacap.common.utils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CodeUtils
|
||||
{
|
||||
private CodeUtils() {}
|
||||
|
||||
/**
|
||||
* Generate code
|
||||
*
|
||||
* @param dash if dash is true, the code will be generated with dash
|
||||
* @return code
|
||||
*/
|
||||
public static String generateCode(boolean dash)
|
||||
{
|
||||
String code = UUID.randomUUID().toString();
|
||||
if (dash) {
|
||||
return code;
|
||||
}
|
||||
return code.replace("-", "");
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ public class ReflectionUtils
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
log.warn("Has field exception", e);
|
||||
log.debug("Has field exception", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,9 @@ public class ColumnController
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@PostMapping(value = "table/{id}")
|
||||
public CommonResponse<List<ColumnEntity>> fetchByTable(@PathVariable Long id)
|
||||
@PostMapping(value = "table/{code}")
|
||||
public CommonResponse<List<ColumnEntity>> fetchByTable(@PathVariable String code)
|
||||
{
|
||||
return this.service.getAllByTable(id);
|
||||
return this.service.getAllByTable(code);
|
||||
}
|
||||
}
|
||||
|
@ -32,16 +32,16 @@ public class TableController
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@PostMapping(value = "database/{id}")
|
||||
public CommonResponse<List<TableEntity>> fetchByDatabase(@PathVariable Long id)
|
||||
@PostMapping(value = "database/{code}")
|
||||
public CommonResponse<List<TableEntity>> fetchByDatabase(@PathVariable String code)
|
||||
{
|
||||
return this.service.getAllByDatabase(id);
|
||||
return this.service.getAllByDatabase(code);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "{id}", method = {RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
|
||||
public CommonResponse<Object> fetchDataById(@PathVariable Long id, @RequestBody TableFilter configure)
|
||||
@RequestMapping(value = "{code}", method = {RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
|
||||
public CommonResponse<Object> fetchDataById(@PathVariable String code, @RequestBody TableFilter configure)
|
||||
{
|
||||
return this.service.fetchDataById(id, configure);
|
||||
return this.service.fetchData(code, configure);
|
||||
}
|
||||
|
||||
@PostMapping(value = "export/{id}")
|
||||
@ -62,9 +62,9 @@ public class TableController
|
||||
return this.service.createTable(id, configure);
|
||||
}
|
||||
|
||||
@PostMapping(value = "manageColumn/{id}")
|
||||
public CommonResponse<Object> manageColumn(@PathVariable Long id, @RequestBody TableBody configure)
|
||||
@PostMapping(value = "manageColumn/{code}")
|
||||
public CommonResponse<Object> manageColumn(@PathVariable String code, @RequestBody TableBody configure)
|
||||
{
|
||||
return this.service.manageColumn(id, configure);
|
||||
return this.service.manageColumn(code, configure);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package io.edurt.datacap.service.service;
|
||||
|
||||
import io.edurt.datacap.common.enums.ServiceState;
|
||||
import io.edurt.datacap.common.response.CommonResponse;
|
||||
import io.edurt.datacap.common.utils.CodeUtils;
|
||||
import io.edurt.datacap.common.utils.NullAwareBeanUtils;
|
||||
import io.edurt.datacap.common.utils.ReflectionUtils;
|
||||
import io.edurt.datacap.service.SelfException;
|
||||
@ -12,6 +13,7 @@ import io.edurt.datacap.service.entity.PageEntity;
|
||||
import io.edurt.datacap.service.entity.UserEntity;
|
||||
import io.edurt.datacap.service.repository.BaseRepository;
|
||||
import io.edurt.datacap.service.security.UserDetailsService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public interface BaseService<T extends BaseEntity>
|
||||
@ -36,6 +38,9 @@ public interface BaseService<T extends BaseEntity>
|
||||
if (ReflectionUtils.hasField(configure, "user")) {
|
||||
ReflectionUtils.setFieldValue(configure, "user", UserDetailsService.getUser());
|
||||
}
|
||||
if (StringUtils.isEmpty(configure.getCode())) {
|
||||
configure.setCode(CodeUtils.generateCode(false));
|
||||
}
|
||||
return CommonResponse.success(repository.save(configure));
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ public interface ColumnService
|
||||
/**
|
||||
* Retrieves all the column entities associated with a specific table.
|
||||
*
|
||||
* @param id the ID of the table
|
||||
* @param code the code of the table
|
||||
* @return a common response containing a list of column entities
|
||||
*/
|
||||
CommonResponse<List<ColumnEntity>> getAllByTable(Long id);
|
||||
CommonResponse<List<ColumnEntity>> getAllByTable(String code);
|
||||
}
|
||||
|
@ -14,19 +14,19 @@ public interface TableService
|
||||
/**
|
||||
* Retrieves all records from the specified database.
|
||||
*
|
||||
* @param id the ID of the database
|
||||
* @param code the code of the database
|
||||
* @return a common response containing a list of table entities
|
||||
*/
|
||||
CommonResponse<List<TableEntity>> getAllByDatabase(Long id);
|
||||
CommonResponse<List<TableEntity>> getAllByDatabase(String code);
|
||||
|
||||
/**
|
||||
* Retrieves data from the database based on the provided ID and table filter.
|
||||
*
|
||||
* @param id the ID of the data to retrieve
|
||||
* @param code the code of the data to retrieve
|
||||
* @param configure the table filter to apply to the data retrieval
|
||||
* @return a common response object containing the retrieved data
|
||||
*/
|
||||
CommonResponse<Object> fetchDataById(Long id, TableFilter configure);
|
||||
CommonResponse<Object> fetchData(String code, TableFilter configure);
|
||||
|
||||
/**
|
||||
* Generates a function comment for the given function body in a markdown code block with the correct language syntax.
|
||||
@ -41,5 +41,5 @@ public interface TableService
|
||||
|
||||
CommonResponse<Object> createTable(Long databaseId, TableBody configure);
|
||||
|
||||
CommonResponse<Object> manageColumn(Long tableId, TableBody configure);
|
||||
CommonResponse<Object> manageColumn(String code, TableBody configure);
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package io.edurt.datacap.service.service.impl;
|
||||
|
||||
import io.edurt.datacap.common.response.CommonResponse;
|
||||
import io.edurt.datacap.service.entity.ColumnEntity;
|
||||
import io.edurt.datacap.service.entity.TableEntity;
|
||||
import io.edurt.datacap.service.repository.metadata.ColumnRepository;
|
||||
import io.edurt.datacap.service.repository.metadata.TableRepository;
|
||||
import io.edurt.datacap.service.service.ColumnService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -13,19 +13,20 @@ import java.util.List;
|
||||
public class ColumnServiceImpl
|
||||
implements ColumnService
|
||||
{
|
||||
private final TableRepository tableRepository;
|
||||
private final ColumnRepository repository;
|
||||
|
||||
public ColumnServiceImpl(ColumnRepository repository)
|
||||
public ColumnServiceImpl(TableRepository tableRepository, ColumnRepository repository)
|
||||
{
|
||||
this.tableRepository = tableRepository;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<List<ColumnEntity>> getAllByTable(Long id)
|
||||
public CommonResponse<List<ColumnEntity>> getAllByTable(String code)
|
||||
{
|
||||
TableEntity table = TableEntity.builder()
|
||||
.id(id)
|
||||
.build();
|
||||
return CommonResponse.success(this.repository.findAllByTable(table));
|
||||
return tableRepository.findByCode(code)
|
||||
.map(value -> CommonResponse.success(repository.findAllByTable(value)))
|
||||
.orElseGet(() -> CommonResponse.failure(String.format("Table [ %s ] not found", code)));
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import io.edurt.datacap.common.enums.NodeType;
|
||||
import io.edurt.datacap.common.enums.ServiceState;
|
||||
import io.edurt.datacap.common.enums.Type;
|
||||
import io.edurt.datacap.common.response.CommonResponse;
|
||||
import io.edurt.datacap.common.utils.CodeUtils;
|
||||
import io.edurt.datacap.common.utils.JsonUtils;
|
||||
import io.edurt.datacap.executor.common.RunState;
|
||||
import io.edurt.datacap.service.adapter.PageRequestAdapter;
|
||||
@ -378,10 +379,13 @@ public class SourceServiceImpl
|
||||
@Override
|
||||
public CommonResponse<SourceEntity> syncMetadata(Long id)
|
||||
{
|
||||
return this.sourceRepository.findById(id).map(entity -> {
|
||||
Executors.newSingleThreadExecutor().submit(() -> startSyncMetadata(entity, null));
|
||||
return CommonResponse.success(entity);
|
||||
}).orElseGet(() -> CommonResponse.failure(String.format("Source [ %s ] not found", id)));
|
||||
return this.sourceRepository.findById(id)
|
||||
.map(entity -> {
|
||||
Executors.newSingleThreadExecutor()
|
||||
.submit(() -> startSyncMetadata(entity, null));
|
||||
return CommonResponse.success(entity);
|
||||
})
|
||||
.orElseGet(() -> CommonResponse.failure(String.format("Source [ %s ] not found", id)));
|
||||
}
|
||||
|
||||
private void startSyncMetadata(SourceEntity entity, ScheduledEntity scheduled)
|
||||
@ -544,19 +548,25 @@ public class SourceServiceImpl
|
||||
}
|
||||
else {
|
||||
List<DatabaseEntity> origin = databaseHandler.findAllBySource(entity);
|
||||
List<DatabaseEntity> entities = response.getColumns().stream().map(item -> {
|
||||
DatabaseEntity database = DatabaseEntity.builder().name(getNodeText(item, NodeType.SCHEMA)).catalog(getNodeText(item, NodeType.CATALOG)).description(String.format("[ %s ] of [ %s ]", getNodeText(item, NodeType.SCHEMA), getNodeText(item, NodeType.CATALOG))).source(entity).build();
|
||||
Optional<DatabaseEntity> optionalDatabase = origin.stream().filter(node -> node.getName().equals(database.getName())).findAny();
|
||||
if (optionalDatabase.isPresent()) {
|
||||
database.setId(optionalDatabase.get().getId());
|
||||
database.setCreateTime(optionalDatabase.get().getCreateTime());
|
||||
databaseUpdatedCount.addAndGet(1);
|
||||
}
|
||||
else {
|
||||
databaseAddedCount.addAndGet(1);
|
||||
}
|
||||
return database;
|
||||
}).collect(Collectors.toList());
|
||||
List<DatabaseEntity> entities = response.getColumns()
|
||||
.stream()
|
||||
.map(item -> {
|
||||
DatabaseEntity database = DatabaseEntity.builder().name(getNodeText(item, NodeType.SCHEMA)).catalog(getNodeText(item, NodeType.CATALOG)).description(String.format("[ %s ] of [ %s ]", getNodeText(item, NodeType.SCHEMA), getNodeText(item, NodeType.CATALOG))).source(entity).build();
|
||||
Optional<DatabaseEntity> optionalDatabase = origin.stream().filter(node -> node.getName().equals(database.getName())).findAny();
|
||||
if (optionalDatabase.isPresent()) {
|
||||
database.setId(optionalDatabase.get().getId());
|
||||
database.setCreateTime(optionalDatabase.get().getCreateTime());
|
||||
if (StringUtils.isEmpty(database.getCode())) {
|
||||
database.setCode(CodeUtils.generateCode(false));
|
||||
}
|
||||
databaseUpdatedCount.addAndGet(1);
|
||||
}
|
||||
else {
|
||||
databaseAddedCount.addAndGet(1);
|
||||
}
|
||||
return database;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
// Write the new data retrieved to the database
|
||||
log.info("Added database size [ {} ] to source [ {} ]", entities.size(), entity.getName());
|
||||
databaseHandler.saveAll(entities);
|
||||
@ -566,7 +576,9 @@ public class SourceServiceImpl
|
||||
databaseTableCache.put(key, this.tableHandler.findSimpleAllByDatabase(item));
|
||||
});
|
||||
// Delete invalid data that no longer exists
|
||||
List<DatabaseEntity> deleteEntities = origin.stream().filter(node -> entities.stream().noneMatch(item -> node.getName().equals(item.getName()))).collect(Collectors.toList());
|
||||
List<DatabaseEntity> deleteEntities = origin.stream()
|
||||
.filter(node -> entities.stream().noneMatch(item -> node.getName().equals(item.getName())))
|
||||
.collect(Collectors.toList());
|
||||
log.info("Removed database size [ {} ] from source [ {} ]", deleteEntities.size(), entity.getName());
|
||||
databaseHandler.deleteAll(deleteEntities);
|
||||
databaseRemovedCount.addAndGet(deleteEntities.size());
|
||||
@ -605,12 +617,34 @@ public class SourceServiceImpl
|
||||
log.error("The source [ {} ] protocol [ {} ] sync metadata tables [ {} ] failed", entity.getName(), entity.getProtocol(), response.getMessage());
|
||||
}
|
||||
else {
|
||||
List<TableEntity> entities = response.getColumns().stream().map(item -> {
|
||||
String key = String.format("%s_%s", getNodeText(item, NodeType.CATALOG), getNodeText(item, NodeType.SCHEMA));
|
||||
DatabaseEntity database = databaseCache.get(key);
|
||||
String name = getNodeText(item, NodeType.TABLE);
|
||||
return TableEntity.builder().name(name).description(String.format("Table [ %s ] of database [ %s ] ", name, getNodeText(item, NodeType.SCHEMA))).type(getNodeText(item, NodeType.TYPE)).engine(getNodeText(item, NodeType.ENGINE)).format(getNodeText(item, NodeType.FORMAT)).inCreateTime(getNodeText(item, NodeType.CREATE_TIME)).inUpdateTime(getNodeText(item, NodeType.UPDATE_TIME)).collation(getNodeText(item, NodeType.COLLATION)).rows(getNodeText(item, NodeType.ROWS)).comment(getNodeText(item, NodeType.COMMENT)).avgRowLength(getNodeText(item, NodeType.AVG_ROW)).dataLength(getNodeText(item, NodeType.DATA)).indexLength(getNodeText(item, NodeType.INDEX)).autoIncrement(getNodeText(item, NodeType.AUTO_INCREMENT)).database(database).build();
|
||||
}).collect(Collectors.toList());
|
||||
List<TableEntity> entities = response.getColumns()
|
||||
.stream()
|
||||
.map(item -> {
|
||||
String key = String.format("%s_%s", getNodeText(item, NodeType.CATALOG), getNodeText(item, NodeType.SCHEMA));
|
||||
DatabaseEntity database = databaseCache.get(key);
|
||||
String name = getNodeText(item, NodeType.TABLE);
|
||||
TableEntity configure = TableEntity.builder()
|
||||
.name(name)
|
||||
.description(String.format("Table [ %s ] of database [ %s ] ", name, getNodeText(item, NodeType.SCHEMA)))
|
||||
.type(getNodeText(item, NodeType.TYPE)).engine(getNodeText(item, NodeType.ENGINE))
|
||||
.format(getNodeText(item, NodeType.FORMAT))
|
||||
.inCreateTime(getNodeText(item, NodeType.CREATE_TIME))
|
||||
.inUpdateTime(getNodeText(item, NodeType.UPDATE_TIME))
|
||||
.collation(getNodeText(item, NodeType.COLLATION))
|
||||
.rows(getNodeText(item, NodeType.ROWS))
|
||||
.comment(getNodeText(item, NodeType.COMMENT))
|
||||
.avgRowLength(getNodeText(item, NodeType.AVG_ROW))
|
||||
.dataLength(getNodeText(item, NodeType.DATA))
|
||||
.indexLength(getNodeText(item, NodeType.INDEX))
|
||||
.autoIncrement(getNodeText(item, NodeType.AUTO_INCREMENT))
|
||||
.database(database)
|
||||
.build();
|
||||
if (StringUtils.isEmpty(configure.getCode())) {
|
||||
configure.setCode(CodeUtils.generateCode(false));
|
||||
}
|
||||
return configure;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, List<TableEntity>> groupEntities = entities.stream().collect(Collectors.groupingBy(item -> String.format("%s_%s", item.getDatabase().getCatalog(), item.getDatabase().getName())));
|
||||
|
||||
@ -674,13 +708,34 @@ public class SourceServiceImpl
|
||||
log.error("The source [ {} ] protocol [ {} ] sync metadata columns [ {} ] failed", entity.getName(), entity.getProtocol(), response.getMessage());
|
||||
}
|
||||
else {
|
||||
List<ColumnEntity> entities = response.getColumns().stream().map(item -> {
|
||||
String key = String.format("%s_%s", getNodeText(item, NodeType.CATALOG), getNodeText(item, NodeType.SCHEMA));
|
||||
TableEntity table = tableCache.get(key);
|
||||
String name = getNodeText(item, NodeType.COLUMN);
|
||||
ColumnEntity column = ColumnEntity.builder().name(name).description(String.format("Table [ %s ] of column [ %s ] ", table.getName(), name)).type(getNodeText(item, NodeType.COLUMN_TYPE)).comment(getNodeText(item, NodeType.COMMENT)).defaultValue(getNodeText(item, NodeType.DEFAULT)).position(getNodeText(item, NodeType.POSITION)).maximumLength(getNodeText(item, NodeType.MAXIMUM_LENGTH)).collation(getNodeText(item, NodeType.COLLATION)).isKey(getNodeText(item, NodeType.KEY)).privileges(getNodeText(item, NodeType.FORMAT)).dataType(getNodeText(item, NodeType.DATA_TYPE)).extra(getNodeText(item, NodeType.EXTRA)).isNullable(getNodeText(item, NodeType.NULLABLE)).table(table).build();
|
||||
return column;
|
||||
}).collect(Collectors.toList());
|
||||
List<ColumnEntity> entities = response.getColumns()
|
||||
.stream()
|
||||
.map(item -> {
|
||||
String key = String.format("%s_%s", getNodeText(item, NodeType.CATALOG), getNodeText(item, NodeType.SCHEMA));
|
||||
TableEntity table = tableCache.get(key);
|
||||
String name = getNodeText(item, NodeType.COLUMN);
|
||||
ColumnEntity configure = ColumnEntity.builder()
|
||||
.name(name)
|
||||
.description(String.format("Table [ %s ] of column [ %s ] ", table.getName(), name))
|
||||
.type(getNodeText(item, NodeType.COLUMN_TYPE))
|
||||
.comment(getNodeText(item, NodeType.COMMENT))
|
||||
.defaultValue(getNodeText(item, NodeType.DEFAULT))
|
||||
.position(getNodeText(item, NodeType.POSITION))
|
||||
.maximumLength(getNodeText(item, NodeType.MAXIMUM_LENGTH))
|
||||
.collation(getNodeText(item, NodeType.COLLATION))
|
||||
.isKey(getNodeText(item, NodeType.KEY))
|
||||
.privileges(getNodeText(item, NodeType.FORMAT))
|
||||
.dataType(getNodeText(item, NodeType.DATA_TYPE))
|
||||
.extra(getNodeText(item, NodeType.EXTRA))
|
||||
.isNullable(getNodeText(item, NodeType.NULLABLE))
|
||||
.table(table)
|
||||
.build();
|
||||
if (StringUtils.isEmpty(configure.getCode())) {
|
||||
configure.setCode(CodeUtils.generateCode(false));
|
||||
}
|
||||
return configure;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, List<ColumnEntity>> groupEntities = entities.stream().collect(Collectors.groupingBy(item -> String.format("%s_%s", item.getTable().getDatabase().getName(), item.getTable().getName())));
|
||||
|
||||
|
@ -86,54 +86,51 @@ public class TableServiceImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<List<TableEntity>> getAllByDatabase(Long id)
|
||||
public CommonResponse<List<TableEntity>> getAllByDatabase(String code)
|
||||
{
|
||||
DatabaseEntity database = DatabaseEntity.builder()
|
||||
.id(id)
|
||||
.build();
|
||||
return CommonResponse.success(this.repository.findAllByDatabase(database));
|
||||
return databaseRepository.findByCode(code)
|
||||
.map(value -> CommonResponse.success(this.repository.findAllByDatabase(value)))
|
||||
.orElseGet(() -> CommonResponse.failure(String.format("Database [ %s ] not found", code)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Object> fetchDataById(Long id, TableFilter configure)
|
||||
public CommonResponse<Object> fetchData(String code, TableFilter configure)
|
||||
{
|
||||
TableEntity table = this.repository.findById(id)
|
||||
.orElse(null);
|
||||
if (table == null) {
|
||||
return CommonResponse.failure(String.format("Table [ %s ] not found", id));
|
||||
}
|
||||
|
||||
SourceEntity source = table.getDatabase().getSource();
|
||||
Optional<Plugin> pluginOptional = PluginUtils.getPluginByNameAndType(this.injector, source.getType(), source.getProtocol());
|
||||
if (!pluginOptional.isPresent()) {
|
||||
return CommonResponse.failure(ServiceState.PLUGIN_NOT_FOUND);
|
||||
}
|
||||
Plugin plugin = pluginOptional.get();
|
||||
if (configure.getType().equals(SqlType.SELECT)) {
|
||||
return this.fetchSelect(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.INSERT)) {
|
||||
return this.fetchInsert(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.UPDATE)) {
|
||||
return this.fetchUpdate(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.DELETE)) {
|
||||
return this.fetchDelete(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.ALTER)) {
|
||||
return this.fetchAlter(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.SHOW)) {
|
||||
return this.fetchShowCreateTable(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.TRUNCATE)) {
|
||||
return this.fetchTruncateTable(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.DROP)) {
|
||||
return this.fetchDropTable(plugin, table, source, configure);
|
||||
}
|
||||
return CommonResponse.failure(String.format("Not implemented yet [ %s ]", configure.getType()));
|
||||
return repository.findByCode(code)
|
||||
.map(table -> {
|
||||
SourceEntity source = table.getDatabase().getSource();
|
||||
Optional<Plugin> pluginOptional = PluginUtils.getPluginByNameAndType(this.injector, source.getType(), source.getProtocol());
|
||||
if (!pluginOptional.isPresent()) {
|
||||
return CommonResponse.failure(ServiceState.PLUGIN_NOT_FOUND);
|
||||
}
|
||||
Plugin plugin = pluginOptional.get();
|
||||
if (configure.getType().equals(SqlType.SELECT)) {
|
||||
return this.fetchSelect(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.INSERT)) {
|
||||
return this.fetchInsert(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.UPDATE)) {
|
||||
return this.fetchUpdate(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.DELETE)) {
|
||||
return this.fetchDelete(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.ALTER)) {
|
||||
return this.fetchAlter(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.SHOW)) {
|
||||
return this.fetchShowCreateTable(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.TRUNCATE)) {
|
||||
return this.fetchTruncateTable(plugin, table, source, configure);
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.DROP)) {
|
||||
return this.fetchDropTable(plugin, table, source, configure);
|
||||
}
|
||||
return CommonResponse.failure(String.format("Not implemented yet [ %s ]", configure.getType()));
|
||||
})
|
||||
.orElse(CommonResponse.failure(String.format("Table [ %s ] not found", code)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -259,59 +256,57 @@ public class TableServiceImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Object> manageColumn(Long tableId, TableBody configure)
|
||||
public CommonResponse<Object> manageColumn(String code, TableBody configure)
|
||||
{
|
||||
Optional<TableEntity> optionalTable = this.repository.findById(tableId);
|
||||
if (!optionalTable.isPresent()) {
|
||||
return CommonResponse.failure(String.format("Table [ %s ] not found", tableId));
|
||||
}
|
||||
|
||||
TableEntity table = optionalTable.get();
|
||||
SourceEntity source = table.getDatabase().getSource();
|
||||
Plugin plugin = PluginUtils.getPluginByNameAndType(this.injector, source.getType(), source.getProtocol()).get();
|
||||
AtomicReference<String> atomicReference = new AtomicReference<>(null);
|
||||
if (configure.getType().equals(SqlType.CREATE)) {
|
||||
ColumnBuilder.Companion.BEGIN();
|
||||
ColumnBuilder.Companion.CREATE_COLUMN(String.format("`%s`.`%s`", table.getDatabase().getName(), table.getName()));
|
||||
ColumnBuilder.Companion.COLUMNS(configure.getColumns().stream().map(Column::toColumnVar).collect(Collectors.toList()));
|
||||
atomicReference.set(ColumnBuilder.Companion.SQL());
|
||||
log.info("Create column sql \n {} \n on table [ {} ]", atomicReference.get(), table.getName());
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.DROP)) {
|
||||
columnRepository.findById(configure.getColumnId())
|
||||
.ifPresent(column -> {
|
||||
return repository.findByCode(code)
|
||||
.map(table -> {
|
||||
SourceEntity source = table.getDatabase().getSource();
|
||||
Plugin plugin = PluginUtils.getPluginByNameAndType(this.injector, source.getType(), source.getProtocol()).get();
|
||||
AtomicReference<String> atomicReference = new AtomicReference<>(null);
|
||||
if (configure.getType().equals(SqlType.CREATE)) {
|
||||
ColumnBuilder.Companion.BEGIN();
|
||||
ColumnBuilder.Companion.DROP_COLUMN(String.format("`%s`.`%s`", table.getDatabase().getName(), table.getName()));
|
||||
ColumnBuilder.Companion.COLUMNS(Lists.newArrayList(column.getName()));
|
||||
ColumnBuilder.Companion.CREATE_COLUMN(String.format("`%s`.`%s`", table.getDatabase().getName(), table.getName()));
|
||||
ColumnBuilder.Companion.COLUMNS(configure.getColumns().stream().map(Column::toColumnVar).collect(Collectors.toList()));
|
||||
atomicReference.set(ColumnBuilder.Companion.SQL());
|
||||
});
|
||||
log.info("Drop column sql \n {} \n on table [ {} ]", atomicReference.get(), table.getName());
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.MODIFY)) {
|
||||
ColumnBuilder.Companion.BEGIN();
|
||||
ColumnBuilder.Companion.MODIFY_COLUMN(String.format("`%s`.`%s`", table.getDatabase().getName(), table.getName()));
|
||||
ColumnBuilder.Companion.COLUMNS(configure.getColumns().stream().map(Column::toColumnVar).collect(Collectors.toList()));
|
||||
atomicReference.set(ColumnBuilder.Companion.SQL());
|
||||
log.info("Modify column sql \n {} \n on table [ {} ]", atomicReference.get(), table.getName());
|
||||
}
|
||||
Response response;
|
||||
if (configure.isPreview()) {
|
||||
response = Response.builder()
|
||||
.isSuccessful(true)
|
||||
.isConnected(true)
|
||||
.headers(Lists.newArrayList())
|
||||
.columns(Lists.newArrayList())
|
||||
.types(Lists.newArrayList())
|
||||
.content(atomicReference.get())
|
||||
.build();
|
||||
}
|
||||
else {
|
||||
plugin.connect(source.toConfigure());
|
||||
response = plugin.execute(atomicReference.get());
|
||||
response.setContent(atomicReference.get());
|
||||
plugin.destroy();
|
||||
}
|
||||
return CommonResponse.success(response);
|
||||
log.info("Create column sql \n {} \n on table [ {} ]", atomicReference.get(), table.getName());
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.DROP)) {
|
||||
columnRepository.findById(configure.getColumnId())
|
||||
.ifPresent(column -> {
|
||||
ColumnBuilder.Companion.BEGIN();
|
||||
ColumnBuilder.Companion.DROP_COLUMN(String.format("`%s`.`%s`", table.getDatabase().getName(), table.getName()));
|
||||
ColumnBuilder.Companion.COLUMNS(Lists.newArrayList(column.getName()));
|
||||
atomicReference.set(ColumnBuilder.Companion.SQL());
|
||||
});
|
||||
log.info("Drop column sql \n {} \n on table [ {} ]", atomicReference.get(), table.getName());
|
||||
}
|
||||
else if (configure.getType().equals(SqlType.MODIFY)) {
|
||||
ColumnBuilder.Companion.BEGIN();
|
||||
ColumnBuilder.Companion.MODIFY_COLUMN(String.format("`%s`.`%s`", table.getDatabase().getName(), table.getName()));
|
||||
ColumnBuilder.Companion.COLUMNS(configure.getColumns().stream().map(Column::toColumnVar).collect(Collectors.toList()));
|
||||
atomicReference.set(ColumnBuilder.Companion.SQL());
|
||||
log.info("Modify column sql \n {} \n on table [ {} ]", atomicReference.get(), table.getName());
|
||||
}
|
||||
Response response;
|
||||
if (configure.isPreview()) {
|
||||
response = Response.builder()
|
||||
.isSuccessful(true)
|
||||
.isConnected(true)
|
||||
.headers(Lists.newArrayList())
|
||||
.columns(Lists.newArrayList())
|
||||
.types(Lists.newArrayList())
|
||||
.content(atomicReference.get())
|
||||
.build();
|
||||
}
|
||||
else {
|
||||
plugin.connect(source.toConfigure());
|
||||
response = plugin.execute(atomicReference.get());
|
||||
response.setContent(atomicReference.get());
|
||||
plugin.destroy();
|
||||
}
|
||||
return CommonResponse.success(response);
|
||||
})
|
||||
.orElse(CommonResponse.failure(String.format("Table [ %s ] not found", code)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@ export interface StructureModel
|
||||
database?: null | any
|
||||
databaseId?: string
|
||||
table?: null
|
||||
tableId?: null
|
||||
tableId?: string
|
||||
applyId?: null | number
|
||||
type?: null
|
||||
dataType?: null
|
||||
@ -20,6 +20,7 @@ export interface StructureModel
|
||||
origin?: any
|
||||
selected?: boolean
|
||||
contextmenu?: true
|
||||
code?: string
|
||||
children?: StructureModel[]
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ export interface TableModel
|
||||
autoIncrement?: string
|
||||
database?: DatabaseModel
|
||||
columns?: Array<ColumnModel>
|
||||
code?: string
|
||||
}
|
||||
|
||||
export class TableRequest
|
||||
|
@ -1,6 +1,7 @@
|
||||
import LayoutContainer from '@/views/layouts/common/LayoutContainer.vue'
|
||||
import ProfileContainer from '@/views/layouts/profile/LayoutContainer.vue'
|
||||
import { TokenUtils } from '@/utils/token'
|
||||
import MetadataContainer from '@/views/layouts/metadata/MetadataContainer.vue'
|
||||
|
||||
/**
|
||||
* Create a default router
|
||||
@ -215,12 +216,67 @@ const createAdminRouter = (router: any) => {
|
||||
component: () => import('@/views/pages/admin/source/SourceHome.vue')
|
||||
},
|
||||
{
|
||||
path: 'source/manager/:code',
|
||||
path: 'source/:source',
|
||||
component: MetadataContainer,
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceManager.vue')
|
||||
children: [
|
||||
{
|
||||
path: 'd/:database/',
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceDatabase.vue')
|
||||
},
|
||||
{
|
||||
path: 'd/:database/t/info/:table',
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false,
|
||||
type: 'info'
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceTableInfo.vue')
|
||||
},
|
||||
{
|
||||
path: 'd/:database/t/structure/:table',
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false,
|
||||
type: 'structure'
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceTableStructure.vue')
|
||||
},
|
||||
{
|
||||
path: 'd/:database/t/data/:table',
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false,
|
||||
type: 'data'
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceTableData.vue')
|
||||
},
|
||||
{
|
||||
path: 'd/:database/t/statement/:table',
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false,
|
||||
type: 'statement'
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceTableStatement.vue')
|
||||
},
|
||||
{
|
||||
path: 'd/:database/t/erDiagram/:table',
|
||||
meta: {
|
||||
title: 'common.source',
|
||||
isRoot: false,
|
||||
type: 'erDiagram'
|
||||
},
|
||||
component: () => import('@/views/pages/admin/source/SourceTableErDiagram.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'history',
|
||||
|
@ -15,12 +15,12 @@ class ColumnService
|
||||
/**
|
||||
* Fetches all items from a table based on the provided ID.
|
||||
*
|
||||
* @param {number} id - The ID of the table.
|
||||
* @param {number} code - The code of the table.
|
||||
* @return {Promise<ResponseModel>} A Promise that resolves with the response from the API.
|
||||
*/
|
||||
getAllByTable(id: number): Promise<ResponseModel>
|
||||
getAllByTable(code: string): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpUtils().post(`${DEFAULT_PATH}/table/${id}`)
|
||||
return new HttpUtils().post(`${DEFAULT_PATH}/table/${code}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,39 +16,39 @@ class TableService
|
||||
/**
|
||||
* Retrieves all data from the database by the specified ID.
|
||||
*
|
||||
* @param {number} id - The ID of the database.
|
||||
* @param {number} code - The code of the database.
|
||||
* @return {Promise<ResponseModel>} A promise that resolves to a ResponseModel object.
|
||||
*/
|
||||
getAllByDatabase(id: number): Promise<ResponseModel>
|
||||
getAllByDatabase(code: string): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/database/${ id }`)
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/database/${ code }`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves data for a specific ID using the provided table filter configuration.
|
||||
*
|
||||
* @param {number} id - The ID of the data to retrieve.
|
||||
* @param {number} code - The code of the data to retrieve.
|
||||
* @param {TableFilter} configure - The table filter configuration.
|
||||
* @return {Promise<ResponseModel>} - A promise that resolves to the response model.
|
||||
*/
|
||||
getData(id: number, configure: TableFilter): Promise<ResponseModel>
|
||||
getData(code: string, configure: TableFilter): Promise<ResponseModel>
|
||||
{
|
||||
if (!configure) {
|
||||
configure = <TableFilter>{}
|
||||
}
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/${ id }`, configure)
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/${ code }`, configure)
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of the entire function.
|
||||
*
|
||||
* @param {number} id - The identifier of the data.
|
||||
* @param {string} code - The identifier of the data.
|
||||
* @param {any} configure - The configuration object.
|
||||
* @return {Promise<ResponseModel>} A promise that resolves to the response model.
|
||||
*/
|
||||
putData(id: number, configure: TableFilter): Promise<ResponseModel>
|
||||
putData(code: string, configure: TableFilter): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpUtils().put(`${ DEFAULT_PATH }/${ id }`, configure)
|
||||
return new HttpUtils().put(`${ DEFAULT_PATH }/${ code }`, configure)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,9 +68,9 @@ class TableService
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/createTable/${ databaseId }`, configure)
|
||||
}
|
||||
|
||||
manageColumn(tableId: number, configure: any): Promise<ResponseModel>
|
||||
manageColumn(code: string, configure: any): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/manageColumn/${ tableId }`, configure)
|
||||
return new HttpUtils().post(`${ DEFAULT_PATH }/manageColumn/${ code }`, configure)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,8 @@ export default defineComponent({
|
||||
Tree
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
code: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data()
|
||||
@ -37,109 +37,120 @@ export default defineComponent({
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
watch(() => this.id, () => this.handlerInitialize())
|
||||
watch(() => this.code, () => this.handlerInitialize())
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
this.dataTreeArray = []
|
||||
this.loading = true
|
||||
DatabaseService.getAllBySource(this.id as string)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: { name: null; catalog: null; id: null }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
catalog: item.catalog,
|
||||
applyId: item.id,
|
||||
level: StructureEnum.DATABASE,
|
||||
loading: false,
|
||||
children: [] as StructureModel[],
|
||||
render: (h: any, {data}: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'database',
|
||||
style: {marginRight: '6px'}
|
||||
}),
|
||||
h('span', data.title)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
this.dataTreeArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
DatabaseService.getAllBySource(this.code as string)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data
|
||||
.forEach((item: { name: null; catalog: null; code: undefined }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
catalog: item.catalog,
|
||||
code: item.code,
|
||||
level: StructureEnum.DATABASE,
|
||||
loading: false,
|
||||
children: [] as StructureModel[],
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'database',
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
h('span', data.title)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
this.dataTreeArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
},
|
||||
handlerLoadChildData(item: StructureModel, callback: any)
|
||||
{
|
||||
const dataChildArray = [] as StructureModel[]
|
||||
if (item.level === StructureEnum.DATABASE) {
|
||||
TableService.getAllByDatabase(item.applyId as number)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: { name: null; title: null; catalog: null; id: null; type: null; engine: null; database: { name: null }; }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.database.name,
|
||||
catalog: item.catalog,
|
||||
applyId: item.id,
|
||||
level: StructureEnum.TABLE,
|
||||
type: item.type,
|
||||
engine: item.engine,
|
||||
loading: false,
|
||||
children: [] as StructureModel[],
|
||||
render: (h: any, {data}: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'table',
|
||||
style: {marginRight: '6px'}
|
||||
}),
|
||||
h('span', data.title)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
dataChildArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => callback(dataChildArray))
|
||||
TableService.getAllByDatabase(item.code as string)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data
|
||||
.forEach((item: { name: null; title: null; catalog: null; code: undefined; type: null; engine: null; database: { name: null }; }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.database.name,
|
||||
catalog: item.catalog,
|
||||
code: item.code,
|
||||
level: StructureEnum.TABLE,
|
||||
type: item.type,
|
||||
engine: item.engine,
|
||||
loading: false,
|
||||
children: [] as StructureModel[],
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'table',
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
h('span', data.title)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
dataChildArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => callback(dataChildArray))
|
||||
}
|
||||
else if (item.level === StructureEnum.TABLE) {
|
||||
ColumnService.getAllByTable(item.applyId as number)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: { name: null; title: null; catalog: null; id: null; type: null; engine: null; table: { name: null, database: { name: null } }; }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.table.database.name,
|
||||
table: item.table.name,
|
||||
catalog: item.catalog,
|
||||
applyId: item.id,
|
||||
level: StructureEnum.COLUMN,
|
||||
type: item.type,
|
||||
engine: item.engine,
|
||||
render: (h: any, {data}: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'columns',
|
||||
style: {marginRight: '6px'}
|
||||
}),
|
||||
h('span', data.title)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
dataChildArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => callback(dataChildArray))
|
||||
ColumnService.getAllByTable(item.code as string)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data
|
||||
.forEach((item: {
|
||||
name: null;
|
||||
title: null;
|
||||
catalog: null;
|
||||
code: undefined;
|
||||
type: null;
|
||||
engine: null;
|
||||
table: { name: null, database: { name: null } };
|
||||
}) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.table.database.name,
|
||||
table: item.table.name,
|
||||
catalog: item.catalog,
|
||||
code: item.code,
|
||||
level: StructureEnum.COLUMN,
|
||||
type: item.type,
|
||||
engine: item.engine,
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'columns',
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
h('span', data.title)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
dataChildArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => callback(dataChildArray))
|
||||
}
|
||||
else {
|
||||
callback(dataChildArray)
|
||||
@ -151,7 +162,7 @@ export default defineComponent({
|
||||
let text: string = target.title as string
|
||||
switch (target.level) {
|
||||
case StructureEnum.TABLE:
|
||||
text = target.database + '.' + text;
|
||||
text = target.database + '.' + text
|
||||
break
|
||||
case StructureEnum.COLUMN:
|
||||
text = target.database + '.' + target.table + '.' + text
|
||||
@ -160,5 +171,5 @@ export default defineComponent({
|
||||
ObjectUtils.copy(text)
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="w-full h-full">
|
||||
<div class="hidden space-y-6 w-full md:block">
|
||||
<div class="flex flex-col space-y-8 lg:flex-row lg:space-x-6 lg:space-y-0">
|
||||
<aside class="-mx-4 w-[200px]">
|
||||
<MetadataSidebar/>
|
||||
</aside>
|
||||
<div class="flex-1">
|
||||
<MetadataContent/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import MetadataSidebar from '@/views/layouts/metadata/components/MetadataSidebar.vue'
|
||||
import MetadataContent from '@/views/layouts/metadata/components/MetadataContent.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MetadataContainer',
|
||||
components: {
|
||||
MetadataContent,
|
||||
MetadataSidebar
|
||||
}
|
||||
})
|
||||
</script>
|
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<Tabs v-model="selectTab as string" :default-value="selectTab as string" class="w-full">
|
||||
<Card :title-class="'p-0'" :body-class="'p-0'">
|
||||
<template #title>
|
||||
<TabsList>
|
||||
<TabsTrigger value="info" class="cursor-pointer" @click="handlerChange">
|
||||
<div class="flex space-x-2">
|
||||
<Info :size="18"/>
|
||||
<span>{{ $t('source.common.info') }}</span>
|
||||
</div>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="structure" class="cursor-pointer" @click="handlerChange">
|
||||
<div class="flex space-x-2">
|
||||
<LayoutPanelTop :size="18"/>
|
||||
<span>{{ $t('source.common.structure') }}</span>
|
||||
</div>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="data" class="cursor-pointer" @click="handlerChange">
|
||||
<div class="flex space-x-2">
|
||||
<Table :size="18"/>
|
||||
<span>{{ $t('source.common.tableData') }}</span>
|
||||
</div>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="statement" class="cursor-pointer" @click="handlerChange">
|
||||
<div class="flex space-x-2">
|
||||
<SatelliteDish :size="18"/>
|
||||
<span>{{ $t('source.common.statement') }}</span>
|
||||
</div>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="erDiagram" class="cursor-pointer" @click="handlerChange">
|
||||
<div class="flex space-x-2">
|
||||
<Wind :size="18"/>
|
||||
<span>{{ $t('source.common.erDiagram') }}</span>
|
||||
</div>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</template>
|
||||
<TabsContent :value="selectTab as string">
|
||||
<div class="h-[695px] overflow-x-auto overflow-y-auto">
|
||||
<RouterView/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Card>
|
||||
</Tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import Card from '@/views/ui/card'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { Info, LayoutPanelTop, SatelliteDish, Table, Wind } from 'lucide-vue-next'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MetadataContent',
|
||||
components: {
|
||||
Tabs, TabsContent, TabsList, TabsTrigger,
|
||||
Card,
|
||||
Info, LayoutPanelTop, Table, SatelliteDish, Wind
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
selectTab: null as string | null,
|
||||
originalSource: null as string | null,
|
||||
originalDatabase: null as string | null,
|
||||
originalTable: null as string | null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
this.watchChange()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
const source = this.$route.params?.source as string
|
||||
const database = this.$route.params?.database as string
|
||||
const table = this.$route.params?.table as string
|
||||
const type = this.$route.meta.type as string
|
||||
this.originalSource = source
|
||||
this.originalDatabase = database
|
||||
this.originalTable = table
|
||||
this.selectTab = type
|
||||
},
|
||||
handlerChange()
|
||||
{
|
||||
this.$router.push(`/admin/source/${ this.originalSource }/d/${ this.originalDatabase }/t/${ this.selectTab }/${ this.originalTable }`)
|
||||
},
|
||||
watchChange()
|
||||
{
|
||||
watch(
|
||||
() => this.$route?.params.table,
|
||||
() => this.handlerInitialize()
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
@ -0,0 +1,451 @@
|
||||
<template>
|
||||
<Card :title-class="'p-0'" :body-class="'p-0'">
|
||||
<template #title>
|
||||
<Select v-model="selectDatabase" :default-value="originalDatabase ? originalDatabase : selectDatabase" @update:modelValue="handlerChangeDatabase">
|
||||
<SelectTrigger class="border-0 w-[200px]">
|
||||
<SelectValue :placeholder="$t('source.tip.selectDatabase')"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent class="w-full">
|
||||
<SelectGroup class="w-full">
|
||||
<SelectItem v-for="item in databaseArray" :value="item.code as any" :key="item.title as string" class="cursor-pointer">
|
||||
{{ item.title }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
<div class="h-[700px] overflow-x-auto overflow-y-auto">
|
||||
<CircularLoading v-if="loading" :show="loading"/>
|
||||
<div v-else>
|
||||
<Tree :data="dataTreeArray" :empty-text="$t('source.tip.selectDatabase')" :load-data="handlerLoadChildData" @on-select-change="handlerSelectNode"
|
||||
@on-contextmenu="handlerContextMenu">
|
||||
<template #contextMenu>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<span id="contextMenu"></span>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="-mt-3">
|
||||
<DropdownMenuLabel>{{ $t('common.action') }}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator/>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger class="cursor-pointer">{{ $t('source.common.menuNew') }}</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerCreateTable(true)">
|
||||
<Table :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.menuNewTable') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem class="cursor-pointer" @click="handlerCreateColumn(true)">
|
||||
<Columns :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.newColumn') }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuGroup v-if="dataInfo?.level === StructureEnum.TABLE">
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger class="cursor-pointer">{{ $t('source.common.menuExport') }}</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerExportData(true)">
|
||||
<ArrowUpFromLine :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.exportData') }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator/>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerTruncateTable(true)">
|
||||
<Trash :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.truncateTable') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerDropTable(true)">
|
||||
<Delete :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.dropTable') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.COLUMN" class="cursor-pointer" @click="handlerChangeColumn(true)">
|
||||
<Pencil :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.changeColumn') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.COLUMN" class="cursor-pointer" @click="handlerDropColumn(true)">
|
||||
<Delete :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.dropColumn') }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
</Tree>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<TableCreate v-if="tableCreateVisible" :isVisible="tableCreateVisible" :info="dataInfo" @close="handlerCreateTable(false)"/>
|
||||
<TableExport v-if="tableExportVisible" :isVisible="tableExportVisible" :info="dataInfo" @close="handlerExportData(false)"/>
|
||||
<TableTruncate v-if="tableTruncateVisible" :isVisible="tableTruncateVisible" :info="dataInfo" @close="handlerTruncateTable(false)"/>
|
||||
<TableDrop v-if="tableDropVisible" :isVisible="tableDropVisible" :info="dataInfo" @close="handlerDropTable(false)"/>
|
||||
<ColumnCreate v-if="columnCreateVisible" :isVisible="columnCreateVisible" :info="dataInfo" @close="handlerCreateColumn(false)"/>
|
||||
<ColumnChange v-if="columnChangeVisible" :isVisible="columnChangeVisible" :info="dataInfo" @close="handlerChangeColumn(false)"/>
|
||||
<ColumnDrop v-if="columnDropVisible" :isVisible="columnDropVisible" :info="dataInfo" @close="handlerDropColumn(false)"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, resolveComponent } from 'vue'
|
||||
import { ArrowUpFromLine, Columns, Delete, Pencil, Table, Trash } from 'lucide-vue-next'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import DatabaseService from '@/services/database.ts'
|
||||
import { StructureEnum, StructureModel } from '@/model/structure.ts'
|
||||
import { Tree } from 'view-ui-plus'
|
||||
import '@/views/components/tree/style.css'
|
||||
import Card from '@/views/ui/card'
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||
import TableService from '@/services/table.ts'
|
||||
import ColumnService from '@/services/column.ts'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import ColumnCreate from '@/views/pages/admin/source/components/ColumnCreate.vue'
|
||||
import ColumnDrop from '@/views/pages/admin/source/components/ColumnDrop.vue'
|
||||
import TableExport from '@/views/pages/admin/source/components/TableExport.vue'
|
||||
import ColumnChange from '@/views/pages/admin/source/components/ColumnChange.vue'
|
||||
import TableTruncate from '@/views/pages/admin/source/components/TableTruncate.vue'
|
||||
import TableDrop from '@/views/pages/admin/source/components/TableDrop.vue'
|
||||
import TableCreate from '@/views/pages/admin/source/components/TableCreate.vue'
|
||||
import { ToastUtils } from '@/utils/toast.ts'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MetadataSidebar',
|
||||
components: {
|
||||
TableCreate, TableDrop, TableTruncate, ColumnChange, TableExport, ColumnDrop, ColumnCreate,
|
||||
Card,
|
||||
Tree,
|
||||
CircularLoading,
|
||||
Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue,
|
||||
Columns, Pencil, ArrowUpFromLine, Delete, Trash, Table,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger
|
||||
},
|
||||
computed: {
|
||||
StructureEnum()
|
||||
{
|
||||
return StructureEnum
|
||||
}
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
selectDatabase: undefined,
|
||||
originalSource: null as string | null,
|
||||
originalDatabase: null as string | null,
|
||||
originalTable: null as string | null,
|
||||
selectNode: null as StructureModel | null,
|
||||
databaseArray: Array<StructureModel>(),
|
||||
dataTreeArray: Array<StructureModel>(),
|
||||
dataInfo: null as StructureModel | null,
|
||||
tableCreateVisible: false,
|
||||
tableExportVisible: false,
|
||||
tableTruncateVisible: false,
|
||||
tableDropVisible: false,
|
||||
columnCreateVisible: false,
|
||||
columnChangeVisible: false,
|
||||
columnDropVisible: false
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
const source = this.$route.params?.source as string
|
||||
const database = this.$route.params?.database as string
|
||||
if (source) {
|
||||
this.originalSource = source
|
||||
this.loading = true
|
||||
DatabaseService.getAllBySource(source)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data
|
||||
.forEach((item: { name: null; catalog: null; code: undefined }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
catalog: item.catalog,
|
||||
code: item.code
|
||||
}
|
||||
this.databaseArray.push(structure)
|
||||
})
|
||||
if (database) {
|
||||
this.originalDatabase = database
|
||||
this.selectDatabase = database as any
|
||||
this.handlerChangeDatabase()
|
||||
}
|
||||
}
|
||||
else {
|
||||
ToastUtils.error(response.message)
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
}
|
||||
},
|
||||
handlerChangeDatabase()
|
||||
{
|
||||
this.loading = true
|
||||
this.dataTreeArray = []
|
||||
TableService.getAllByDatabase(this.selectDatabase as any)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data
|
||||
.forEach((item: {
|
||||
name: null;
|
||||
title: null;
|
||||
catalog: null;
|
||||
code: undefined;
|
||||
type: null;
|
||||
engine: null;
|
||||
comment: null;
|
||||
database: { name: null, id: string };
|
||||
}) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.database.name,
|
||||
databaseId: item.database.id,
|
||||
catalog: item.catalog,
|
||||
code: item.code,
|
||||
type: item.type,
|
||||
level: StructureEnum.TABLE,
|
||||
engine: item.engine,
|
||||
comment: item.comment,
|
||||
origin: item,
|
||||
loading: false,
|
||||
contextmenu: true,
|
||||
children: [] as StructureModel[],
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'table',
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
this.resolveTableComponent(h, data)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
this.dataTreeArray.push(structure)
|
||||
})
|
||||
}
|
||||
else {
|
||||
ToastUtils.error(response.message)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false
|
||||
const table = this.$route.params?.table as string
|
||||
if (table) {
|
||||
const node = this.dataTreeArray.find(item => item.code === table)
|
||||
if (node) {
|
||||
node.selected = true
|
||||
this.handlerSelectNode([node])
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.$router.push(`/admin/source/${ this.originalSource }/d/${ this.selectDatabase }`)
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerSelectNode(node: Array<StructureModel>)
|
||||
{
|
||||
if (node.length === 0 && this.selectNode) {
|
||||
// Prevent selection clearing after repeated clicks
|
||||
this.selectNode.selected = true
|
||||
return
|
||||
}
|
||||
const currentNode = node[0]
|
||||
if (currentNode.level === StructureEnum.COLUMN) {
|
||||
if (this.selectNode) {
|
||||
this.selectNode.selected = true
|
||||
}
|
||||
currentNode.selected = false
|
||||
return
|
||||
}
|
||||
this.selectNode = currentNode
|
||||
const type = this.$route.meta.type as string
|
||||
this.$router.push(`/admin/source/${ this.originalSource }/d/${ this.selectDatabase }/t/${ type ? type : 'info' }/${ currentNode.code }`)
|
||||
},
|
||||
handlerLoadChildData(item: StructureModel, callback: any)
|
||||
{
|
||||
const dataChildArray = [] as StructureModel[]
|
||||
if (item.level === StructureEnum.COLUMN) {
|
||||
callback(dataChildArray)
|
||||
return
|
||||
}
|
||||
ColumnService.getAllByTable(item.code as string)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: {
|
||||
name: null;
|
||||
title: null;
|
||||
catalog: null;
|
||||
code: undefined;
|
||||
type: null;
|
||||
dataType: null;
|
||||
extra: null;
|
||||
engine: null;
|
||||
isKey: null;
|
||||
defaultValue: null;
|
||||
table: { name: null, code: undefined, database: { name: null, id: string } };
|
||||
}) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.table.database.name,
|
||||
databaseId: item.table.database.id,
|
||||
table: item.table.name,
|
||||
tableId: item.table.code,
|
||||
catalog: item.catalog,
|
||||
code: item.code,
|
||||
level: StructureEnum.COLUMN,
|
||||
type: item.type,
|
||||
extra: item.extra,
|
||||
dataType: item.dataType,
|
||||
engine: item.engine,
|
||||
isKey: item.isKey,
|
||||
defaultValue: item.defaultValue,
|
||||
contextmenu: true,
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: this.getColumnIcon(data.isKey as unknown as string),
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
h('span', data.title),
|
||||
h('span', {
|
||||
style: {
|
||||
marginLeft: '6px',
|
||||
color: '#c5c8ce'
|
||||
}
|
||||
},
|
||||
this.getColumnTitle(data.type as unknown as string,
|
||||
data.extra as unknown as string,
|
||||
data.isKey as unknown as string,
|
||||
data.defaultValue as unknown as string))
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
dataChildArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => callback(dataChildArray))
|
||||
},
|
||||
handlerContextMenu(node: StructureModel)
|
||||
{
|
||||
console.log(node)
|
||||
this.dataInfo = node
|
||||
// Simulate right-click to trigger right-click menu
|
||||
const element = document.getElementById('contextMenu') as HTMLElement
|
||||
if (element) {
|
||||
element.click()
|
||||
}
|
||||
},
|
||||
handlerCreateTable(opened: boolean)
|
||||
{
|
||||
this.tableCreateVisible = opened
|
||||
},
|
||||
handlerCreateColumn(opened: boolean)
|
||||
{
|
||||
this.columnCreateVisible = opened
|
||||
},
|
||||
handlerExportData(opened: boolean)
|
||||
{
|
||||
this.tableExportVisible = opened
|
||||
},
|
||||
handlerTruncateTable(opened: boolean)
|
||||
{
|
||||
this.tableTruncateVisible = opened
|
||||
},
|
||||
handlerDropTable(opened: boolean)
|
||||
{
|
||||
this.tableDropVisible = opened
|
||||
},
|
||||
handlerChangeColumn(opened: boolean)
|
||||
{
|
||||
this.columnChangeVisible = opened
|
||||
},
|
||||
handlerDropColumn(opened: boolean)
|
||||
{
|
||||
this.columnDropVisible = opened
|
||||
},
|
||||
getColumnIcon(type: string)
|
||||
{
|
||||
if (type === 'PRI') {
|
||||
return 'key'
|
||||
}
|
||||
else if (type === 'MUL') {
|
||||
return 'repeat'
|
||||
}
|
||||
else if (type === 'UNI') {
|
||||
return 'circle'
|
||||
}
|
||||
else {
|
||||
return 'columns'
|
||||
}
|
||||
},
|
||||
getColumnTitle(dataType: string, extra: string, isKey: string, defaultValue: string)
|
||||
{
|
||||
let title = dataType
|
||||
if (isKey === 'PRI') {
|
||||
if (extra) {
|
||||
title = `${ title } (${ extra.replace('_', ' ') })`
|
||||
}
|
||||
else {
|
||||
title = `${ title }`
|
||||
}
|
||||
}
|
||||
if (defaultValue && defaultValue !== 'null') {
|
||||
title = `${ title } = ${ defaultValue }`
|
||||
}
|
||||
return title
|
||||
},
|
||||
resolveTableComponent(h: any, data: StructureModel)
|
||||
{
|
||||
if (data.comment) {
|
||||
return h(resolveComponent('Tooltip'), {
|
||||
content: data.comment,
|
||||
placement: 'bottom-start',
|
||||
delay: 1000
|
||||
},
|
||||
h('span', data.title))
|
||||
}
|
||||
else {
|
||||
return h('span', data.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
@ -5,7 +5,7 @@
|
||||
<Card>
|
||||
<CardHeader class="p-0">
|
||||
<SourceSelect :value="selectSource.full as string" @changeValue="handlerChangeValue($event)"/>
|
||||
<DataStructureLazyTree v-if="selectSource.id" :id="selectSource.id as string"/>
|
||||
<DataStructureLazyTree v-if="selectSource.code" :code="selectSource.code as string"/>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</aside>
|
||||
|
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<Card :body-class="'p-8'" :hidden-title="true">
|
||||
<Alert :description="$t('source.tip.notSelectedNode')"/>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import Card from '@/views/ui/card'
|
||||
import Alert from '@/views/ui/alert'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SourceDatabase',
|
||||
components: {
|
||||
Card,
|
||||
Alert
|
||||
}
|
||||
})
|
||||
</script>
|
@ -42,7 +42,7 @@
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem :disabled="(loginUserId !== row.user.id) || !row.available" class="cursor-pointer">
|
||||
<RouterLink :to="`/admin/source/manager/${row?.code}`" target="_blank" class="flex items-center">
|
||||
<RouterLink :to="`/admin/source/${row?.code}`" target="_blank" class="flex items-center">
|
||||
<Cog class="mr-2 h-4 w-4"/>
|
||||
<span>{{ $t('source.common.manager') }}</span>
|
||||
</RouterLink>
|
||||
|
@ -1,498 +0,0 @@
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<CircularLoading v-if="loading" :show="loading"/>
|
||||
<div v-else class="hidden space-y-6 pb-16 w-full md:block">
|
||||
<div class="flex flex-col space-y-8 lg:flex-row lg:space-x-6 lg:space-y-0">
|
||||
<aside class="-mx-4 w-[200px]">
|
||||
<Card :title-class="'p-0'" :body-class="'p-0'">
|
||||
<template #title>
|
||||
<Select v-model="applyValue.database" @update:modelValue="handlerChangeDatabase">
|
||||
<SelectTrigger class="border-0 w-[200px]">
|
||||
<SelectValue :placeholder="$t('source.tip.selectDatabase')"/>
|
||||
</SelectTrigger>
|
||||
<SelectContent class="w-full">
|
||||
<SelectGroup class="w-full">
|
||||
<SelectItem v-for="item in databaseArray" :value="item.applyId as any" :key="item.title as string" class="cursor-pointer">
|
||||
{{ item.title }}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
<div class="h-[500px] overflow-x-auto overflow-y-auto">
|
||||
<CircularLoading v-if="dataTreeLoading" :show="dataTreeLoading"/>
|
||||
<div v-else>
|
||||
<Tree :data="dataTreeArray" :empty-text="$t('source.tip.selectDatabase')" :load-data="handlerLoadChildData" @on-select-change="handlerSelectNode"
|
||||
@on-contextmenu="handlerContextMenu">
|
||||
<template #contextMenu>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<span id="contextMenu"></span>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="-mt-3">
|
||||
<DropdownMenuLabel>{{ $t('common.action') }}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator/>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger class="cursor-pointer">{{ $t('source.common.menuNew') }}</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerCreateTable(true)">
|
||||
<Table :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.menuNewTable') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem class="cursor-pointer" @click="handlerCreateColumn(true)">
|
||||
<Columns :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.newColumn') }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuGroup v-if="dataInfo?.level === StructureEnum.TABLE">
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger class="cursor-pointer">{{ $t('source.common.menuExport') }}</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerExportData(true)">
|
||||
<ArrowUpFromLine :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.exportData') }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator/>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerTruncateTable(true)">
|
||||
<Trash :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.truncateTable') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.TABLE" class="cursor-pointer" @click="handlerDropTable(true)">
|
||||
<Delete :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.dropTable') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.COLUMN" class="cursor-pointer" @click="handlerChangeColumn(true)">
|
||||
<Pencil :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.changeColumn') }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem v-if="dataInfo?.level === StructureEnum.COLUMN" class="cursor-pointer" @click="handlerDropColumn(true)">
|
||||
<Delete :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.dropColumn') }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</template>
|
||||
</Tree>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</aside>
|
||||
<div class="flex-1">
|
||||
<Card v-if="!applyValue.node" :body-class="'p-8'" :hidden-title="true">
|
||||
<Alert :description="$t('source.tip.notSelectedNode')"/>
|
||||
</Card>
|
||||
<Tabs v-else v-model="applyValue.tabType" :default-value="applyValue.tabType" class="w-full">
|
||||
<Card :title-class="'p-0'" :body-class="'p-0'">
|
||||
<template #title>
|
||||
<TabsList>
|
||||
<TabsTrigger value="info" class="cursor-pointer">
|
||||
<Info :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.info') }}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="structure" class="cursor-pointer">
|
||||
<LayoutPanelTop :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.structure') }}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="data" class="cursor-pointer">
|
||||
<Table :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.tableData') }}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="statement" class="cursor-pointer">
|
||||
<SatelliteDish :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.statement') }}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="erDiagram" class="cursor-pointer">
|
||||
<Wind :size="18" class="mr-2"/>
|
||||
{{ $t('source.common.erDiagram') }}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</template>
|
||||
<TabsContent value="info" class="p-3">
|
||||
<TableInfo v-if="applyValue.node" :info="applyValue.node"/>
|
||||
</TabsContent>
|
||||
<TabsContent value="structure">
|
||||
<TableStructure v-if="applyValue.node" :info="applyValue.node"/>
|
||||
</TabsContent>
|
||||
<TabsContent value="data" class="mt-0">
|
||||
<TableData v-if="applyValue.node" :info="applyValue.node"/>
|
||||
</TabsContent>
|
||||
<TabsContent value="statement">
|
||||
<TableStatement v-if="applyValue.node" :info="applyValue.node"/>
|
||||
</TabsContent>
|
||||
<TabsContent value="erDiagram">
|
||||
<TableErDiagram v-if="applyValue.node" :info="applyValue.node"/>
|
||||
</TabsContent>
|
||||
</Card>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ColumnCreate v-if="columnCreateVisible" :isVisible="columnCreateVisible" :info="dataInfo" @close="handlerCreateColumn(false)"/>
|
||||
<ColumnChange v-if="columnChangeVisible" :isVisible="columnChangeVisible" :info="dataInfo" @close="handlerChangeColumn(false)"/>
|
||||
<ColumnDrop v-if="columnDropVisible" :isVisible="columnDropVisible" :info="dataInfo" @close="handlerDropColumn(false)"/>
|
||||
<TableCreate v-if="tableCreateVisible" :isVisible="tableCreateVisible" :info="dataInfo" @close="handlerCreateTable(false)"/>
|
||||
<TableExport v-if="tableExportVisible" :isVisible="tableExportVisible" :info="dataInfo" @close="handlerExportData(false)"/>
|
||||
<TableTruncate v-if="tableTruncateVisible" :isVisible="tableTruncateVisible" :info="dataInfo" @close="handlerTruncateTable(false)"/>
|
||||
<TableDrop v-if="tableDropVisible" :isVisible="tableDropVisible" :info="dataInfo" @close="handlerDropTable(false)"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, resolveComponent } from 'vue'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import { StructureEnum, StructureModel } from '@/model/structure'
|
||||
import { useRouter } from 'vue-router'
|
||||
import DatabaseService from '@/services/database'
|
||||
import Card from '@/views/ui/card'
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||
import TableService from '@/services/table'
|
||||
import { Tree } from 'view-ui-plus'
|
||||
import '@/views/components/tree/style.css'
|
||||
import ColumnService from '@/services/column'
|
||||
import Alert from '@/views/ui/alert'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { ArrowUpFromLine, Columns, Delete, Info, LayoutPanelTop, Pencil, SatelliteDish, Table, Trash, Wind } from 'lucide-vue-next'
|
||||
import TableInfo from '@/views/pages/admin/source/components/TableInfo.vue'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { toNumber } from 'lodash'
|
||||
import TableCreate from '@/views/pages/admin/source/components/TableCreate.vue'
|
||||
import ColumnCreate from '@/views/pages/admin/source/components/ColumnCreate.vue'
|
||||
import TableExport from '@/views/pages/admin/source/components/TableExport.vue'
|
||||
import TableTruncate from '@/views/pages/admin/source/components/TableTruncate.vue'
|
||||
import TableDrop from '@/views/pages/admin/source/components/TableDrop.vue'
|
||||
import TableStructure from '@/views/pages/admin/source/components/TableStructure.vue'
|
||||
import ColumnChange from '@/views/pages/admin/source/components/ColumnChange.vue'
|
||||
import ColumnDrop from '@/views/pages/admin/source/components/ColumnDrop.vue'
|
||||
import TableData from '@/views/pages/admin/source/components/TableData.vue'
|
||||
import TableStatement from '@/views/pages/admin/source/components/TableStatement.vue'
|
||||
import TableErDiagram from '@/views/pages/admin/source/components/TableErDiagram.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SourceManager',
|
||||
components: {
|
||||
TableErDiagram,
|
||||
TableStatement,
|
||||
TableData,
|
||||
ColumnDrop,
|
||||
ColumnChange,
|
||||
TableStructure,
|
||||
TableDrop,
|
||||
TableTruncate,
|
||||
TableExport,
|
||||
ColumnCreate,
|
||||
TableCreate,
|
||||
TableInfo,
|
||||
Alert,
|
||||
Card,
|
||||
CircularLoading,
|
||||
Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue,
|
||||
Tree,
|
||||
Tabs, TabsContent, TabsList, TabsTrigger,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
Info, Table, Columns, ArrowUpFromLine, Trash, Delete, LayoutPanelTop, Pencil, SatelliteDish, Wind
|
||||
},
|
||||
computed: {
|
||||
StructureEnum()
|
||||
{
|
||||
return StructureEnum
|
||||
}
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
databaseArray: Array<StructureModel>(),
|
||||
applyValue: {
|
||||
database: undefined,
|
||||
node: null as StructureModel | null,
|
||||
tabType: 'info'
|
||||
},
|
||||
dataTreeLoading: false,
|
||||
dataTreeArray: Array<StructureModel>(),
|
||||
dataInfo: null as StructureModel | null,
|
||||
tableCreateVisible: false,
|
||||
tableExportVisible: false,
|
||||
tableTruncateVisible: false,
|
||||
tableDropVisible: false,
|
||||
columnCreateVisible: false,
|
||||
columnChangeVisible: false,
|
||||
columnDropVisible: false
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
this.loading = true
|
||||
const router = useRouter()
|
||||
const code = router.currentRoute?.value?.params['code'] as string
|
||||
DatabaseService.getAllBySource(code)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: { name: null; catalog: null; id: null }) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
catalog: item.catalog,
|
||||
applyId: item.id
|
||||
}
|
||||
this.databaseArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
},
|
||||
handlerChangeDatabase()
|
||||
{
|
||||
this.dataTreeLoading = true
|
||||
this.dataTreeArray = []
|
||||
TableService.getAllByDatabase(toNumber(this.applyValue.database))
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: {
|
||||
name: null;
|
||||
title: null;
|
||||
catalog: null;
|
||||
id: null;
|
||||
type: null;
|
||||
engine: null;
|
||||
comment: null;
|
||||
database: { name: null, id: string };
|
||||
}) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.database.name,
|
||||
databaseId: item.database.id,
|
||||
catalog: item.catalog,
|
||||
applyId: item.id,
|
||||
type: item.type,
|
||||
level: StructureEnum.TABLE,
|
||||
engine: item.engine,
|
||||
comment: item.comment,
|
||||
origin: item,
|
||||
loading: false,
|
||||
contextmenu: true,
|
||||
children: [] as StructureModel[],
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: 'table',
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
this.resolveTableComponent(h, data)
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
this.dataTreeArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => this.dataTreeLoading = false)
|
||||
},
|
||||
handlerSelectNode(node: Array<StructureModel>)
|
||||
{
|
||||
if (node.length === 0 && this.applyValue.node) {
|
||||
// Prevent selection clearing after repeated clicks
|
||||
this.applyValue.node.selected = true
|
||||
return
|
||||
}
|
||||
const currentNode = node[0]
|
||||
if (currentNode.level === StructureEnum.COLUMN) {
|
||||
if (this.applyValue.node) {
|
||||
this.applyValue.node.selected = true
|
||||
}
|
||||
currentNode.selected = false
|
||||
return
|
||||
}
|
||||
this.applyValue.node = currentNode
|
||||
},
|
||||
handlerLoadChildData(item: StructureModel, callback: any)
|
||||
{
|
||||
const dataChildArray = [] as StructureModel[]
|
||||
if (item.level === StructureEnum.COLUMN) {
|
||||
callback(dataChildArray)
|
||||
return
|
||||
}
|
||||
ColumnService.getAllByTable(item.applyId as number)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
response.data.forEach((item: {
|
||||
name: null;
|
||||
title: null;
|
||||
catalog: null;
|
||||
id: null;
|
||||
type: null;
|
||||
dataType: null;
|
||||
extra: null;
|
||||
engine: null;
|
||||
isKey: null;
|
||||
defaultValue: null;
|
||||
table: { name: null, id: null, database: { name: null, id: string } };
|
||||
}) => {
|
||||
const structure: StructureModel = {
|
||||
title: item.name,
|
||||
database: item.table.database.name,
|
||||
databaseId: item.table.database.id,
|
||||
table: item.table.name,
|
||||
tableId: item.table.id,
|
||||
catalog: item.catalog,
|
||||
applyId: item.id,
|
||||
level: StructureEnum.COLUMN,
|
||||
type: item.type,
|
||||
extra: item.extra,
|
||||
dataType: item.dataType,
|
||||
engine: item.engine,
|
||||
isKey: item.isKey,
|
||||
defaultValue: item.defaultValue,
|
||||
contextmenu: true,
|
||||
render: (h: any, { data }: { data: StructureModel }) => {
|
||||
return h('div', [
|
||||
h('span', [
|
||||
h(resolveComponent('FontAwesomeIcon'), {
|
||||
icon: this.getColumnIcon(data.isKey as unknown as string),
|
||||
style: { marginRight: '6px' }
|
||||
}),
|
||||
h('span', data.title),
|
||||
h('span', {
|
||||
style: {
|
||||
marginLeft: '6px',
|
||||
color: '#c5c8ce'
|
||||
}
|
||||
},
|
||||
this.getColumnTitle(data.type as unknown as string,
|
||||
data.extra as unknown as string,
|
||||
data.isKey as unknown as string,
|
||||
data.defaultValue as unknown as string))
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
dataChildArray.push(structure)
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => callback(dataChildArray))
|
||||
},
|
||||
handlerContextMenu(node: StructureModel)
|
||||
{
|
||||
this.dataInfo = node
|
||||
// Simulate right-click to trigger right-click menu
|
||||
const element = document.getElementById('contextMenu') as HTMLElement
|
||||
if (element) {
|
||||
element.click()
|
||||
}
|
||||
},
|
||||
handlerCreateTable(opened: boolean)
|
||||
{
|
||||
this.tableCreateVisible = opened
|
||||
},
|
||||
handlerCreateColumn(opened: boolean)
|
||||
{
|
||||
this.columnCreateVisible = opened
|
||||
},
|
||||
handlerExportData(opened: boolean)
|
||||
{
|
||||
this.tableExportVisible = opened
|
||||
},
|
||||
handlerTruncateTable(opened: boolean)
|
||||
{
|
||||
this.tableTruncateVisible = opened
|
||||
},
|
||||
handlerDropTable(opened: boolean)
|
||||
{
|
||||
this.tableDropVisible = opened
|
||||
},
|
||||
handlerChangeColumn(opened: boolean)
|
||||
{
|
||||
this.columnChangeVisible = opened
|
||||
},
|
||||
handlerDropColumn(opened: boolean)
|
||||
{
|
||||
this.columnDropVisible = opened
|
||||
},
|
||||
getColumnIcon(type: string)
|
||||
{
|
||||
if (type === 'PRI') {
|
||||
return 'key'
|
||||
}
|
||||
else if (type === 'MUL') {
|
||||
return 'repeat'
|
||||
}
|
||||
else if (type === 'UNI') {
|
||||
return 'circle'
|
||||
}
|
||||
else {
|
||||
return 'columns'
|
||||
}
|
||||
},
|
||||
getColumnTitle(dataType: string, extra: string, isKey: string, defaultValue: string)
|
||||
{
|
||||
let title = dataType
|
||||
if (isKey === 'PRI') {
|
||||
if (extra) {
|
||||
title = `${ title } (${ extra.replace('_', ' ') })`
|
||||
}
|
||||
else {
|
||||
title = `${ title }`
|
||||
}
|
||||
}
|
||||
if (defaultValue && defaultValue !== 'null') {
|
||||
title = `${ title } = ${ defaultValue }`
|
||||
}
|
||||
return title
|
||||
},
|
||||
resolveTableComponent(h: any, data: StructureModel)
|
||||
{
|
||||
if (data.comment) {
|
||||
return h(resolveComponent('Tooltip'), {
|
||||
content: data.comment,
|
||||
placement: 'bottom-start',
|
||||
delay: 1000
|
||||
},
|
||||
h('span', data.title))
|
||||
}
|
||||
else {
|
||||
return h('span', data.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
@ -109,14 +109,14 @@
|
||||
</div>
|
||||
</template>
|
||||
<CircularLoading v-if="refererLoading" :show="refererLoading"/>
|
||||
<AgGridVue class="ag-theme-datacap" style="width: 100%; min-height: 460px; height: 460px;" :gridOptions="gridOptions" :columnDefs="configure.headers"
|
||||
<AgGridVue class="ag-theme-datacap h-[650px]" :gridOptions="gridOptions" :columnDefs="configure.headers"
|
||||
:rowData="configure.datasets" :tooltipShowDelay="100" :sortingOrder="['desc', 'asc', null]" :rowSelection="'multiple'" @grid-ready="handlerGridReady"
|
||||
@sortChanged="handlerSortChanged" @cellValueChanged="handlerCellValueChanged" @selectionChanged="handlerSelectionChanged" @columnVisible="handlerColumnVisible"
|
||||
@columnMoved="handlerColumnMoved"/>
|
||||
</Card>
|
||||
<TableCellInfo v-if="dataCellChanged.pending && info" :isVisible="dataCellChanged.pending" :columns="dataCellChanged.columns" :tableId="info.applyId as number"
|
||||
:type="dataCellChanged.type" @close="handlerCellChangedPreview(false)"/>
|
||||
<TableRowDelete v-if="dataSelectedChanged.pending && info" :isVisible="dataSelectedChanged.pending" :tableId="info.applyId as number" :columns="dataSelectedChanged.columns"
|
||||
<TableCellInfo v-if="dataCellChanged.pending" :isVisible="dataCellChanged.pending" :columns="dataCellChanged.columns" :type="dataCellChanged.type"
|
||||
@close="handlerCellChangedPreview(false)"/>
|
||||
<TableRowDelete v-if="dataSelectedChanged.pending" :isVisible="dataSelectedChanged.pending" :columns="dataSelectedChanged.columns"
|
||||
@close="handlerSelectedChangedPreview(false)"/>
|
||||
<TableColumn v-if="visibleColumn.show" :isVisible="visibleColumn.show" :columns="visibleColumn.columns" @close="handlerVisibleColumn($event, false)"
|
||||
@change="handlerVisibleColumn($event, false)"/>
|
||||
@ -128,7 +128,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { StructureModel } from '@/model/structure'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { AgGridVue } from 'ag-grid-vue3'
|
||||
@ -136,12 +135,12 @@ import 'ag-grid-community/styles/ag-grid.css'
|
||||
import '@/views/components/grid/ag-theme-datacap.css'
|
||||
import { ColumnApi, ColumnState, GridApi } from 'ag-grid-community'
|
||||
import Card from '@/views/ui/card'
|
||||
import { PaginationEnum, PaginationModel } from '@/model/pagination'
|
||||
import { PaginationEnum, PaginationModel } from '@/model/pagination.ts'
|
||||
import { createColumnDefs, createDataEditorOptions } from '@/views/pages/admin/source/components/TableUtils.ts'
|
||||
import { OrderFilter, SqlColumn, SqlType, TableFilter } from '@/model/table'
|
||||
import TableService from '@/services/table'
|
||||
import { cloneDeep, toNumber } from 'lodash'
|
||||
import { ToastUtils } from '@/utils/toast'
|
||||
import { OrderFilter, SqlColumn, SqlType, TableFilter } from '@/model/table.ts'
|
||||
import TableService from '@/services/table.ts'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { ToastUtils } from '@/utils/toast.ts'
|
||||
import Button from '@/views/ui/button'
|
||||
import Tooltip from '@/views/ui/tooltip'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||
@ -154,7 +153,7 @@ import TableColumn from '@/views/pages/admin/source/components/TableColumn.vue'
|
||||
import TableRowFilter from '@/views/pages/admin/source/components/TableRowFilter.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TableData',
|
||||
name: 'SourceTableData',
|
||||
components: {
|
||||
TableRowFilter,
|
||||
TableColumn,
|
||||
@ -170,16 +169,11 @@ export default defineComponent({
|
||||
Popover, PopoverContent, PopoverTrigger,
|
||||
ArrowLeftToLine, ArrowLeft, ArrowRight, ArrowRightToLine, Cog, Plus, RectangleEllipsis, Copy, Minus, Eye, RefreshCw, Columns, Filter
|
||||
},
|
||||
props: {
|
||||
info: {
|
||||
type: Object as () => StructureModel | null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.i18n = useI18n()
|
||||
this.handlerInitialize()
|
||||
this.watchId()
|
||||
this.watchChange()
|
||||
},
|
||||
data()
|
||||
{
|
||||
@ -242,9 +236,10 @@ export default defineComponent({
|
||||
}
|
||||
this.configure.pagination = pagination
|
||||
}
|
||||
if (this.info) {
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.loading = true
|
||||
TableService.getData(toNumber(this.info.applyId), this.configure)
|
||||
TableService.getData(code, this.configure)
|
||||
.then(response => {
|
||||
if (response.status && response.data) {
|
||||
this.configure.headers = createColumnDefs(response.data.headers, response.data.types)
|
||||
@ -272,9 +267,10 @@ export default defineComponent({
|
||||
{
|
||||
this.configure.datasets = []
|
||||
this.gridOptions.overlayNoRowsTemplate = '<span></span>'
|
||||
if (this.info) {
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.refererLoading = true
|
||||
TableService.getData(toNumber(this.info.applyId), configure)
|
||||
TableService.getData(code, configure)
|
||||
.then(response => {
|
||||
if (response.status && response.data) {
|
||||
this.configure.headers = createColumnDefs(response.data.headers, response.data.types)
|
||||
@ -466,10 +462,10 @@ export default defineComponent({
|
||||
{
|
||||
this.newRows = []
|
||||
},
|
||||
watchId()
|
||||
watchChange()
|
||||
{
|
||||
watch(
|
||||
() => this.info,
|
||||
() => this.$route?.params.table,
|
||||
() => {
|
||||
this.configure.pagination = null as unknown as PaginationModel
|
||||
this.handlerInitialize()
|
@ -8,26 +8,14 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import ColumnService from '@/services/column'
|
||||
import { StructureModel } from '@/model/structure.ts'
|
||||
import { toNumber } from 'lodash'
|
||||
import ColumnService from '@/services/column.ts'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import ErDiagram from '@/views/components/diagram/ErDiagram.vue'
|
||||
import { ErDiagramOptions } from '@/views/components/diagram/ErDiagramOptions'
|
||||
import { ErDiagramOptions } from '@/views/components/diagram/ErDiagramOptions.ts'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TableErDiagram',
|
||||
name: 'SourceTableErDiagram',
|
||||
components: { ErDiagram, CircularLoading },
|
||||
props: {
|
||||
info: {
|
||||
type: Object as () => StructureModel | null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
this.watchId()
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
@ -35,29 +23,34 @@ export default defineComponent({
|
||||
options: null as unknown as ErDiagramOptions
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
this.watchChange()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
this.loading = true
|
||||
if (this.info) {
|
||||
ColumnService.getAllByTable(toNumber(this.info.applyId))
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.loading = true
|
||||
ColumnService.getAllByTable(code)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
if (response.status && response.data?.length > 0) {
|
||||
const table = response.data[0]
|
||||
this.options = new ErDiagramOptions()
|
||||
this.options.table = { id: toNumber(this.info?.applyId), name: this.info?.title as string }
|
||||
this.options.table = { id: table.id, name: table.name }
|
||||
this.options.columns = response.data
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
}
|
||||
},
|
||||
watchId()
|
||||
watchChange()
|
||||
{
|
||||
watch(
|
||||
() => this.info,
|
||||
() => {
|
||||
this.handlerInitialize()
|
||||
}
|
||||
() => this.$route?.params.table,
|
||||
() => this.handlerInitialize()
|
||||
)
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="pl-3 pr-3">
|
||||
<CircularLoading v-if="loading" :show="loading"/>
|
||||
<div v-else-if="dataInfo">
|
||||
<div class="grid w-full grid-cols-3 gap-6 pt-2">
|
||||
@ -93,7 +93,7 @@
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<Label for="autoIncrement">{{ $t('source.common.resetTo') }}</Label>
|
||||
<Input v-model="dataInfo.autoIncrement" id="autoIncrement" type="number" :default-value="dataInfo.autoIncrement"/>
|
||||
<Button :loading="loading" @click="handlerApply">
|
||||
<Button size="sm" :loading="submitting" :disabled="submitting" @click="handlerApply">
|
||||
{{ $t('common.apply') }}
|
||||
</Button>
|
||||
</div>
|
||||
@ -127,11 +127,9 @@ import { Label } from '@/components/ui/label'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { ToastUtils } from '@/utils/toast'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { StructureModel } from '@/model/structure'
|
||||
import { cloneDeep, toNumber } from 'lodash'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TableInfo',
|
||||
name: 'SourceTableInfo',
|
||||
components: {
|
||||
Textarea,
|
||||
Input,
|
||||
@ -144,39 +142,46 @@ export default defineComponent({
|
||||
Database, Table, Clock, CalendarHeart, ArrowUpDown, TableCellsMerge, RemoveFormatting, ArrowUp10, Search, Cog,
|
||||
Popover, PopoverContent, PopoverTrigger
|
||||
},
|
||||
props: {
|
||||
info: {
|
||||
type: Object as () => StructureModel | null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
this.watchId()
|
||||
this.watchChange()
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
submitting: false,
|
||||
dataInfo: null as TableModel | null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
if (this.info) {
|
||||
this.dataInfo = cloneDeep(this.info.origin)
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.loading = true
|
||||
TableService.getByCode(code)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
this.dataInfo = response.data
|
||||
}
|
||||
else {
|
||||
ToastUtils.error(response.message)
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
}
|
||||
},
|
||||
handlerApply()
|
||||
{
|
||||
if (this.dataInfo) {
|
||||
this.loading = true
|
||||
this.submitting = true
|
||||
const configure: TableFilter = {
|
||||
type: SqlType.ALTER,
|
||||
value: this.dataInfo.autoIncrement
|
||||
}
|
||||
TableService.getData(toNumber(this.dataInfo.id), configure)
|
||||
TableService.getData(this.dataInfo.code as string, configure)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
ToastUtils.success(this.$t('source.tip.resetAutoIncrementSuccess').replace('$VALUE', this.dataInfo?.autoIncrement as string))
|
||||
@ -186,16 +191,14 @@ export default defineComponent({
|
||||
ToastUtils.error(response.message)
|
||||
}
|
||||
})
|
||||
.finally(() => this.loading = false)
|
||||
.finally(() => this.submitting = false)
|
||||
}
|
||||
},
|
||||
watchId()
|
||||
watchChange()
|
||||
{
|
||||
watch(
|
||||
() => this.info,
|
||||
() => {
|
||||
this.handlerInitialize()
|
||||
}
|
||||
() => this.$route?.params.table,
|
||||
() => this.handlerInitialize()
|
||||
)
|
||||
}
|
||||
}
|
@ -5,24 +5,17 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { StructureModel } from '@/model/structure'
|
||||
import { toNumber } from 'lodash'
|
||||
import { SqlType, TableFilter, TableFilterRequest } from '@/model/table'
|
||||
import { SqlType, TableFilter, TableFilterRequest } from '@/model/table.ts'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import AceEditor from '@/views/components/editor/AceEditor.vue'
|
||||
import TableService from '@/services/table'
|
||||
import TableService from '@/services/table.ts'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TableStatement',
|
||||
name: 'SourceTableStatement',
|
||||
components: {
|
||||
AceEditor,
|
||||
CircularLoading
|
||||
},
|
||||
props: {
|
||||
info: {
|
||||
type: Object as () => StructureModel | null
|
||||
}
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
@ -34,16 +27,17 @@ export default defineComponent({
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
this.watchId()
|
||||
this.watchChange()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
if (this.info) {
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.formState = TableFilterRequest.of()
|
||||
this.formState.type = SqlType.SHOW
|
||||
this.loading = true
|
||||
TableService.getData(toNumber(this.info.applyId), this.formState)
|
||||
TableService.getData(code, this.formState)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
const content = response.data?.columns[0]
|
||||
@ -58,13 +52,11 @@ export default defineComponent({
|
||||
.finally(() => this.loading = false)
|
||||
}
|
||||
},
|
||||
watchId()
|
||||
watchChange()
|
||||
{
|
||||
watch(
|
||||
() => this.info,
|
||||
() => {
|
||||
this.handlerInitialize()
|
||||
}
|
||||
() => this.$route?.params.table,
|
||||
() => this.handlerInitialize()
|
||||
)
|
||||
}
|
||||
}
|
@ -1,34 +1,28 @@
|
||||
<template>
|
||||
<TableCommon :loading="loading" :columns="headers" :data="data">
|
||||
<template #isNullable="{row}">
|
||||
<Switch :value="row.isNullable" disabled="disabled"/>
|
||||
</template>
|
||||
</TableCommon>
|
||||
<div class="h-full">
|
||||
<TableCommon :loading="loading" :columns="headers" :data="data">
|
||||
<template #isNullable="{row}">
|
||||
<Switch :value="row.isNullable" disabled="disabled"/>
|
||||
</template>
|
||||
</TableCommon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch } from 'vue'
|
||||
import { StructureModel } from '@/model/structure'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { createHeaders } from '@/views/pages/admin/source/components/TableUtils'
|
||||
import { createHeaders } from '@/views/pages/admin/source/components/TableUtils.ts'
|
||||
import TableCommon from '@/views/components/table/TableCommon.vue'
|
||||
import ColumnService from '@/services/column'
|
||||
import { cloneDeep, toNumber } from 'lodash'
|
||||
import { TableModel } from '@/model/table'
|
||||
import { ColumnModel } from '@/model/column'
|
||||
import ColumnService from '@/services/column.ts'
|
||||
import { ColumnModel } from '@/model/column.ts'
|
||||
import Switch from '@/views/ui/switch'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TableStructure',
|
||||
name: 'SourceTableStructure',
|
||||
components: {
|
||||
TableCommon,
|
||||
Switch
|
||||
},
|
||||
props: {
|
||||
info: {
|
||||
type: Object as () => StructureModel | null
|
||||
}
|
||||
},
|
||||
setup()
|
||||
{
|
||||
const headers = createHeaders(useI18n())
|
||||
@ -41,22 +35,21 @@ export default defineComponent({
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
dataInfo: null as TableModel | null,
|
||||
data: Array<ColumnModel>
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
this.watchId()
|
||||
this.watchChange()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
if (this.info) {
|
||||
this.dataInfo = cloneDeep(this.info.origin)
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.loading = true
|
||||
ColumnService.getAllByTable(toNumber(this.dataInfo?.id))
|
||||
ColumnService.getAllByTable(code)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
this.data = response.data
|
||||
@ -65,10 +58,10 @@ export default defineComponent({
|
||||
.finally(() => this.loading = false)
|
||||
}
|
||||
},
|
||||
watchId()
|
||||
watchChange()
|
||||
{
|
||||
watch(
|
||||
() => this.info,
|
||||
() => this.$route?.params.table,
|
||||
() => {
|
||||
this.handlerInitialize()
|
||||
}
|
@ -103,7 +103,6 @@ import { Minus, Plus } from 'lucide-vue-next'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import Switch from '@/views/ui/switch'
|
||||
import { ToastUtils } from '@/utils/toast'
|
||||
import { toNumber } from 'lodash'
|
||||
import TableService from '@/services/table'
|
||||
import ColumnService from '@/services/column'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
@ -160,7 +159,7 @@ export default defineComponent({
|
||||
{
|
||||
if (this.info) {
|
||||
this.loading = true
|
||||
ColumnService.getById(toNumber(this.info.applyId))
|
||||
ColumnService.getByCode(this.info.code as string)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
const data = response.data
|
||||
@ -187,11 +186,14 @@ export default defineComponent({
|
||||
{
|
||||
if (this.info) {
|
||||
this.submitting = true
|
||||
TableService.manageColumn(toNumber(this.info.tableId), this.formState)
|
||||
TableService.manageColumn(this.info.code as string, this.formState)
|
||||
.then(response => {
|
||||
if (response.data) {
|
||||
if (response.data.isSuccessful) {
|
||||
const columns = this.formState?.columns?.map(item => item.name).join(', ') as string
|
||||
const columns = this.formState
|
||||
?.columns
|
||||
?.map(item => item.name)
|
||||
.join(', ') as string
|
||||
ToastUtils.success(this.$t('source.tip.changeColumnSuccess').replace('$VALUE', columns))
|
||||
this.handlerCancel()
|
||||
}
|
||||
|
@ -110,7 +110,6 @@ import { Minus, Plus } from 'lucide-vue-next'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import Switch from '@/views/ui/switch'
|
||||
import { ToastUtils } from '@/utils/toast'
|
||||
import { toNumber } from 'lodash'
|
||||
import TableService from '@/services/table'
|
||||
|
||||
export default defineComponent({
|
||||
@ -163,7 +162,7 @@ export default defineComponent({
|
||||
{
|
||||
if (this.info) {
|
||||
this.loading = true
|
||||
TableService.manageColumn(toNumber(this.info.applyId), this.formState)
|
||||
TableService.manageColumn(this.info.code as string, this.formState)
|
||||
.then(response => {
|
||||
if (response.data) {
|
||||
if (response.data.isSuccessful) {
|
||||
|
@ -99,7 +99,7 @@ export default defineComponent({
|
||||
this.submitting = true
|
||||
}
|
||||
this.formState.preview = preview
|
||||
TableService.getData(toNumber(this.info.tableId), this.formState)
|
||||
TableService.getData(this.info.tableId as string, this.formState)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
if (preview) {
|
||||
|
@ -19,7 +19,6 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { SqlColumn, SqlType, TableFilter, TableFilterRequest } from '@/model/table'
|
||||
import TableService from '@/services/table'
|
||||
import { toNumber } from 'lodash'
|
||||
import { ToastUtils } from '@/utils/toast'
|
||||
import Dialog from '@/views/ui/dialog'
|
||||
import Button from '@/views/ui/button'
|
||||
@ -38,9 +37,6 @@ export default defineComponent({
|
||||
isVisible: {
|
||||
type: Boolean
|
||||
},
|
||||
tableId: {
|
||||
type: Number
|
||||
},
|
||||
columns: {
|
||||
type: Array<SqlColumn>
|
||||
},
|
||||
@ -60,19 +56,24 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
submitting: false,
|
||||
contentDML: null as string | null,
|
||||
configure: null as unknown as TableFilter
|
||||
configure: null as unknown as TableFilter,
|
||||
code: null as string | null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.code = code
|
||||
}
|
||||
this.handlerInitialize()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
@ -86,7 +87,7 @@ export default defineComponent({
|
||||
}
|
||||
this.configure.type = this.type
|
||||
this.configure.preview = true
|
||||
TableService.putData(toNumber(this.tableId), this.configure)
|
||||
TableService.putData(this.code as string, this.configure)
|
||||
.then(response => {
|
||||
if (response.status && response.data && response.data.isSuccessful) {
|
||||
this.contentDML = response.data.content
|
||||
@ -101,7 +102,7 @@ export default defineComponent({
|
||||
{
|
||||
this.submitting = false
|
||||
this.configure.preview = false
|
||||
TableService.putData(toNumber(this.tableId), this.configure)
|
||||
TableService.putData(this.code as string, this.configure)
|
||||
.then(response => {
|
||||
if (response.status && response.data && response.data.isSuccessful) {
|
||||
ToastUtils.success(this.$t('source.tip.updateSuccess'))
|
||||
|
@ -35,7 +35,6 @@ import { SqlType, TableFilter, TableFilterRequest } from '@/model/table'
|
||||
import Button from '@/views/ui/button'
|
||||
import Alert from '@/views/ui/alert'
|
||||
import Divider from '@/views/ui/divider'
|
||||
import { toNumber } from 'lodash'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import AceEditor from '@/views/components/editor/AceEditor.vue'
|
||||
|
||||
@ -98,7 +97,7 @@ export default defineComponent({
|
||||
this.submitting = true
|
||||
}
|
||||
this.formState.preview = preview
|
||||
TableService.getData(toNumber(this.info.applyId), this.formState)
|
||||
TableService.getData(this.info.code as string, this.formState)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
if (preview) {
|
||||
|
@ -23,7 +23,6 @@ import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import TableService from '@/services/table'
|
||||
import { SqlColumn, SqlType, TableFilter, TableFilterRequest } from '@/model/table'
|
||||
import { ToastUtils } from '@/utils/toast'
|
||||
import { toNumber } from 'lodash'
|
||||
import Button from '@/views/ui/button'
|
||||
|
||||
export default defineComponent({
|
||||
@ -38,9 +37,6 @@ export default defineComponent({
|
||||
isVisible: {
|
||||
type: Boolean
|
||||
},
|
||||
tableId: {
|
||||
type: Number
|
||||
},
|
||||
columns: {
|
||||
type: Array<SqlColumn>
|
||||
}
|
||||
@ -57,19 +53,24 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
submitting: false,
|
||||
contentDML: null as string | null,
|
||||
configure: null as unknown as TableFilter
|
||||
configure: null as unknown as TableFilter,
|
||||
code: null as string | null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
const code = this.$route?.params.table as string
|
||||
if (code) {
|
||||
this.code = code
|
||||
}
|
||||
this.handlerInitialize()
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
@ -80,7 +81,7 @@ export default defineComponent({
|
||||
this.configure.columns = originalColumns
|
||||
this.configure.type = SqlType.DELETE
|
||||
this.configure.preview = true
|
||||
TableService.putData(toNumber(this.tableId), this.configure)
|
||||
TableService.putData(this.code as string, this.configure)
|
||||
.then(response => {
|
||||
if (response.status && response.data && response.data.isSuccessful) {
|
||||
this.contentDML = response.data.content
|
||||
@ -95,7 +96,7 @@ export default defineComponent({
|
||||
{
|
||||
this.submitting = false
|
||||
this.configure.preview = false
|
||||
TableService.putData(toNumber(this.tableId), this.configure)
|
||||
TableService.putData(this.code as string, this.configure)
|
||||
.then(response => {
|
||||
if (response.status && response.data && response.data.isSuccessful) {
|
||||
ToastUtils.success(this.$t('source.tip.deleteSuccess'))
|
||||
|
@ -35,7 +35,6 @@ import { SqlType, TableFilter, TableFilterRequest } from '@/model/table'
|
||||
import Button from '@/views/ui/button'
|
||||
import Alert from '@/views/ui/alert'
|
||||
import Divider from '@/views/ui/divider'
|
||||
import { toNumber } from 'lodash'
|
||||
import CircularLoading from '@/views/components/loading/CircularLoading.vue'
|
||||
import AceEditor from '@/views/components/editor/AceEditor.vue'
|
||||
|
||||
@ -98,7 +97,7 @@ export default defineComponent({
|
||||
this.submitting = true
|
||||
}
|
||||
this.formState.preview = preview
|
||||
TableService.getData(toNumber(this.info.applyId), this.formState)
|
||||
TableService.getData(this.info.code as string, this.formState)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
if (preview) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
<CardContent :class="`${bodyClass}`">
|
||||
<slot/>
|
||||
</CardContent>
|
||||
<CardFooter v-if="$slots.footer" :class="`border-t ${footerClass}`">
|
||||
<CardFooter v-if="$slots.footer">
|
||||
<slot name="footer"/>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
@ -39,9 +39,6 @@ export default defineComponent({
|
||||
bodyClass: {
|
||||
type: String
|
||||
},
|
||||
footerClass: {
|
||||
type: String
|
||||
},
|
||||
hiddenTitle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
Loading…
Reference in New Issue
Block a user