feat: datasource

This commit is contained in:
junjun
2025-05-14 14:27:59 +08:00
parent a10058c770
commit 3be3b7e6f7
6 changed files with 115 additions and 67 deletions
+7 -2
View File
@@ -20,15 +20,20 @@ def check_status(session: SessionDep, ds: CoreDatasource):
return True
except Exception as e:
print("Fail:", e)
raise e
return False
finally:
conn.close()
return False
def create_ds(session: SessionDep, ds: CoreDatasource):
ds.create_time = datetime.datetime.now()
ds.status = "Success" # todo check status
status = check_status(session, ds)
ds.status = "Success" if status is True else "Fail"
record = CoreDatasource(**ds.model_dump())
# get tables and fields
if status:
pass
session.add(record)
session.commit()
return ds
+21 -4
View File
@@ -2,6 +2,7 @@ from sqlmodel import SQLModel, Field
from sqlalchemy import Column, Text, BigInteger, DateTime, Integer, Identity
from datetime import datetime
from pydantic import BaseModel
from typing import List
class CoreDatasource(SQLModel, table=True):
@@ -16,6 +17,22 @@ class CoreDatasource(SQLModel, table=True):
status: str = Field(max_length=64, nullable=True)
class TableSchema(BaseModel):
checked: str = True
table_name: str = ''
table_comment: str = ''
custom_comment: str = ''
table_fields: List = []
class FieldSchema(BaseModel):
checked: str = True
field_name: str = ''
field_type: str = ''
field_comment: str = ''
custom_comment: str = ''
class DatasourceConf(BaseModel):
host: str = ''
port: int = 0
@@ -28,18 +45,18 @@ class DatasourceConf(BaseModel):
class TableSchema:
def __init__(self, attr1, attr2):
self.tableName = attr1
self.tableRemark = attr2
self.tableComment = attr2
tableName: str
tableRemark: str
tableComment: str
class ColumnSchema:
def __init__(self, attr1, attr2, attr3):
self.fieldName = attr1
self.fieldType = attr2
self.fieldRemark = attr3
self.fieldComment = attr3
fieldName: str
fieldType: str
fieldRemark: str
fieldComment: str
+6 -21
View File
@@ -17,6 +17,7 @@ def get_uri(ds: CoreDatasource):
raise 'The datasource type not support.'
return db_url
def get_session(ds: CoreDatasource):
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration)))
db_url: str
@@ -55,21 +56,22 @@ def get_tables(ds: CoreDatasource):
session.close()
def get_fields(ds: CoreDatasource, table_name: str):
def get_fields(ds: CoreDatasource, table_name: str = None):
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration)))
session = get_session(ds)
result: Result[Any]
try:
if ds.type == "mysql":
sql = f"""SELECT
sql1 = f"""SELECT
COLUMN_NAME,
DATA_TYPE,
COLUMN_COMMENT
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = '{conf.database}' AND
TABLE_NAME = '{table_name}';"""
TABLE_SCHEMA = '{conf.database}'"""
sql2 = f""" AND TABLE_NAME = '{table_name}';""" if table_name is not None and table_name != "" else ";"
sql = sql1 + sql2
result = session.execute(text(sql))
res = result.fetchall()
@@ -99,20 +101,3 @@ def exec_sql(ds: CoreDatasource, sql: str):
if session is not None:
session.close()
def exec_sql(ds: CoreDatasource, sql: str):
ds = session.get(CoreDatasource, id)
session = get_session(ds)
result = session.execute(text(sql))
try:
columns = result.keys()._keys
res = result.fetchall()
result_list = [
{columns[i]: value for i, value in enumerate(tuple_item)}
for tuple_item in res
]
return {"fields": columns, "data": result_list}
finally:
if result is not None:
result.close()
if session is not None:
session.close()
+7
View File
@@ -38,6 +38,13 @@ const router = createRouter({
name: 'ds',
component: ds,
meta: { title: 'Data Connections', icon: 'ds' }
},
{
path: 'dsTable/:dsId/:dsName',
name: 'dsTable',
component: () => import('@/views/ds/TableList.vue'),
meta: { title: 'Data Connections', icon: 'ds' },
props: true
}
]
},
+69 -34
View File
@@ -1,5 +1,24 @@
<template>
<el-drawer
<div class="layout">
<el-row class="header">
<div class="title">
<el-button text :icon="ArrowLeft" @click="back()" />
{{ props.dsName }}
</div>
<el-button type="primary" @click="save()">
Save
</el-button>
</el-row>
<el-row class="data">
<el-table-v2
:columns="tableColumns"
:data="tableData"
:width="1000"
:height="800"
fixed
/>
</el-row>
<el-drawer
v-model="drawer"
direction="btt"
:destroy-on-close="true"
@@ -11,33 +30,23 @@
</template>
<template #default>
<el-row :gutter="20">
<el-col :span="12">
<el-table-v2
:columns="tableColumns"
:data="tableData"
:width="700"
:height="400"
fixed
/>
</el-col>
<el-col :span="12">
<el-table-v2
:columns="fieldColumns"
:data="fieldData"
:width="700"
:height="400"
fixed
/>
</el-col>
<el-table-v2
:columns="fieldColumns"
:data="fieldData"
:width="1000"
:height="800"
fixed
/>
</el-row>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="cancelClick">cancel</el-button>
<el-button type="primary" @click="confirmClick">confirm</el-button>
<el-button @click="cancelClick">Cancel</el-button>
<el-button type="primary" @click="confirmClick">Confirm</el-button>
</div>
</template>
</el-drawer>
</div>
</template>
<script lang="tsx" setup>
@@ -45,6 +54,13 @@ import { ref } from 'vue'
import { datasourceApi } from '@/api/datasource'
import { ElButton } from 'element-plus'
import { h } from 'vue'
import { onMounted } from 'vue'
import { ArrowLeft } from '@element-plus/icons-vue'
const props = defineProps({
dsId: { type: [Number], required: true },
dsName: { type: [String], required: true }
})
const drawer = ref<boolean>(false)
const tableColumns = ref<any>([
@@ -55,9 +71,9 @@ const tableColumns = ref<any>([
width: 150,
},
{
key:"tableRemark",
dataKey:"tableRemark",
title: 'Table Remark',
key:"tableComment",
dataKey:"tableComment",
title: 'Table Comment',
width: 300,
},
{
@@ -87,24 +103,25 @@ const fieldColumns = ref<any>([
width: 150,
},
{
key:"fieldRemark",
dataKey:"fieldRemark",
title: 'Field Remark',
key:"fieldComment",
dataKey:"fieldComment",
title: 'Field Comment',
width: 300,
}
])
const fieldData = ref<any>([])
const dsId = ref<Number>(0)
const open = (id: Number) => {
drawer.value = true
dsId.value = id
datasourceApi.getTables(id).then((res) => {
tableData.value = res
})
const back = () => {
history.back()
}
const save = () => {
}
const showFields = (tableName: string) =>{
drawer.value = true
datasourceApi.getFields(dsId.value, tableName).then((res) => {
fieldData.value = res
})
@@ -119,9 +136,27 @@ const confirmClick = () => {
cancelClick()
}
onMounted(() => {
dsId.value = props.dsId
datasourceApi.getTables(props.dsId).then((res) => {
tableData.value = res
})
})
defineExpose({ open })
</script>
<style lang="less" scoped>
.layout{
padding: 20px 40px;
.header{
padding: 20px 0;
display: flex;
justify-content: space-between;
}
.title{
display: flex;
align-items: center;
}
}
</style>
+5 -6
View File
@@ -35,7 +35,7 @@
</div>
<div class="connection-status" :class="`${getStatus(ds.status)}`">{{ ds.status }}</div>
<div class="connection-actions">
<el-button class="action-btn" circle @click="getTables(ds.id)" :icon="List" />
<el-button class="action-btn" circle @click="getTables(ds.id, ds.name)" :icon="List" />
<el-button type="primary" class="action-btn" circle @click="editDs(ds)" :icon="IconOpeEdit"/>
<el-button type="danger" class="action-btn" circle @click="deleteDs(ds)" :icon="IconOpeDelete"/>
</div>
@@ -43,7 +43,6 @@
</div>
</div>
<DsForm ref="dsForm" @refresh="refresh"/>
<TableList ref="tableList" />
</template>
<script lang="ts" setup>
import IconOpeAdd from '@/assets/svg/operate/ope-add.svg'
@@ -55,13 +54,13 @@ import DsForm from './form.vue'
import { datasourceApi } from '@/api/datasource'
import { datetimeFormat } from '@/utils/utils'
import { ElMessageBox } from 'element-plus'
import TableList from './TableList.vue'
import { useRouter } from 'vue-router'
const searchValue = ref<string>('')
const dsForm = ref()
const tableList = ref()
const dsList = ref<any>([])// show ds list
const allDsList = ref<any>([])// all ds list
const router = useRouter()
const getStatus = (status: string) => {
if (status === 'Success') {
@@ -118,7 +117,7 @@ const deleteDs = (item: any) => {
})
}
const getTables = (id: Number) => {
const getTables = (id: number, name: string) => {
// datasourceApi.getTables(id).then((res) => {
// console.log(res)
// })
@@ -130,7 +129,7 @@ const getTables = (id: Number) => {
// datasourceApi.execSql(id,'select id,name,table_name from core_dataset_table limit 10').then((res) => {
// console.log(res)
// })
tableList.value.open(id)
router.push(`/ds/dsTable/${id}/${name}`)
}
onMounted(() => {