lvkun 2 жил өмнө
parent
commit
b85215776c

+ 4 - 4
config/proxy.ts

@@ -10,18 +10,18 @@ module.exports = {
       changeOrigin: true,
       pathRewrite: { '^/user': '' }
     },
-    '/cvs': {
+    '/cvss': {
       target: 'http://124.222.113.37:8080',
       changeOrigin: true,
-      pathRewrite: { '^/cvs': '' }
+      pathRewrite: { '^/cvss': '' }
     },
     '/iot': {
       target: 'http://124.222.113.37:8888',
       changeOrigin: true,
       pathRewrite: { '^/iot': '' }
     },
-    '/dataSource': {
-      target: 'http://124.222.113.37:8888',
+    '/datacenter': {
+      target: 'http://152.136.36.115:7777',
       changeOrigin: true,
       pathRewrite: { '^/datacenter': '' }
     }

+ 12 - 0
src/api/datacenter/dataLake.ts

@@ -0,0 +1,12 @@
+import request from '@/service/request'
+
+/**
+ * 查询数据源
+ * */
+export function execSql (params: {dataSourceId: string, querySql: string}) {
+  return request<any>({
+    url: '/dataView/sql',
+    method: 'POST',
+    params
+  })
+}

+ 5 - 5
src/api/datacenter/dataSource.ts

@@ -4,7 +4,7 @@ import request from '@/service/request'
  * 查询数据源
  * */
 export function getDataSourcePage (params) {
-  return request<SCHEDULE.SOURCE.Detail[]>({
+  return request<DC.SOURCE.Detail[]>({
     url: '/dataSource/page',
     method: 'GET',
     params
@@ -14,7 +14,7 @@ export function getDataSourcePage (params) {
 /**
  * 新增数据源
  * */
-export function addDataSource (data: SCHEDULE.SOURCE.Detail) {
+export function addDataSource (data: DC.SOURCE.Detail) {
   return request({
     url: '/dataSource',
     method: 'POST',
@@ -25,7 +25,7 @@ export function addDataSource (data: SCHEDULE.SOURCE.Detail) {
 /**
  * 修改数据源
  * */
-export function updateDataSource (data: SCHEDULE.SOURCE.Detail) {
+export function updateDataSource (data: DC.SOURCE.Detail) {
   return request({
     url: '/dataSource',
     method: 'POST',
@@ -34,7 +34,7 @@ export function updateDataSource (data: SCHEDULE.SOURCE.Detail) {
 }
 
 export function getDataSourceById (id: string) {
-  return request<SCHEDULE.SOURCE.Detail>({
+  return request<DC.SOURCE.Detail>({
     method: 'GET'
   })
 }
@@ -42,7 +42,7 @@ export function getDataSourceById (id: string) {
 /**
  * 数据源连接参数 -连接测试 【用在新建还未保存】
  * */
-export function dataSourceConnect (data: SCHEDULE.SOURCE.Detail) {
+export function dataSourceConnect (data: DC.SOURCE.Detail) {
   return request<Boolean>({
     url: '/dataSource/connect',
     method: 'POST',

+ 23 - 0
src/api/datacenter/meteTool.ts

@@ -0,0 +1,23 @@
+import request from '@/service/request'
+
+/**
+ * 查看数据源有哪些表
+ * */
+export function getTable (params: {dataSourceId: string}) {
+  return request<string[]>({
+    url: '/metadata/table',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 查看数据源有哪些表
+ * */
+export function getTableColumns (params: {dataSourceId: string, tableName: string}) {
+  return request<DC.TableColumns[]>({
+    url: '/metadata/tableColumns',
+    method: 'GET',
+    params
+  })
+}

+ 6 - 4
src/components/MicroComponents/index.tsx

@@ -146,6 +146,8 @@ export const InputTsx = defineComponent({
   },
   emits: ['update:value', 'submit'],
   setup (props, ctx) {
+    console.log('props.modelValue:', props.modelValue)
+
     const editing = ref<boolean>(false)
 
     const onInput = (value: string) => ctx.emit('update:value', value)
@@ -156,10 +158,11 @@ export const InputTsx = defineComponent({
     }
 
     return () => (
-      <>
+      <span>
         {
+
           props.mode === 'normal'
-            ? <Input style={{ minWidth: '170px' }} placeholder={props.placeholder} value={props.modelValue} onChange={(e) => onInput(e.target.value!)} />
+            ? <Input style={{ minWidth: '170px' }} placeholder={props.placeholder} onChange={(e) => onInput(e.target.value!)} />
             : <>
               <Space>
                 {
@@ -178,11 +181,10 @@ export const InputTsx = defineComponent({
               </Space>
                   : null
               }
-
           </>
         }
 
-      </>
+      </span>
 
     )
   }

+ 1 - 1
src/components/RealView/index.less

@@ -29,7 +29,7 @@
     width: 100%;
     height: 100%;
     padding: 18px;
-    padding-bottom: 138px;
+    padding-bottom: 168px;
     overflow: hidden;
     overflow-y: auto;
   }

+ 12 - 8
src/components/RealView/index.tsx

@@ -62,14 +62,18 @@ const RealView = defineComponent({
 
               {/* footer */}
               {
-                footer.value
-                  ? <Row class='footer' >
-                  <Space>
-                    <Button onClick={() => cancel()}>取消</Button>
-                    <Button type='primary' onClick={() => ok()}>确定</Button>
-                  </Space>
-                </Row>
-                  : null
+                ctx.slots.footer
+                  ? <Row class='footer'>
+                    { ctx.slots.footer?.() }
+                  </Row>
+                  : footer.value
+                    ? <Row class='footer' >
+                        <Space>
+                          <Button onClick={() => cancel()}>取消</Button>
+                          <Button type='primary' onClick={() => ok()}>确定</Button>
+                        </Space>
+                      </Row>
+                    : null
               }
 
             </div>

+ 4 - 4
src/controller/datacenter/dataSource.ts

@@ -4,16 +4,16 @@ import { message } from 'ant-design-vue'
 export class DataSourceController {
   static dataSourceType = ['MYSQL', 'PGSQL', 'DM', 'ORACLE', 'DORIS']
 
-  static async page (params: COMMON.API.QueryParams & {label: string, dataSourceType: SCHEDULE.SOURCE.DataSourceType}) {
+  static async page (params: COMMON.API.QueryParams & {label: string, dataSourceType: DC.SOURCE.DataSourceType}) {
     return await getDataSourcePage(params)
   }
 
-  static async add (data: SCHEDULE.SOURCE.Detail) {
+  static async add (data: DC.SOURCE.Detail) {
     await addDataSource(data)
     message.success('新增成功')
   }
 
-  static async update (data: SCHEDULE.SOURCE.Detail) {
+  static async update (data: DC.SOURCE.Detail) {
     await updateDataSource(data)
     message.success('修改成功')
   }
@@ -27,7 +27,7 @@ export class DataSourceController {
     return getDataSourceById(id)
   }
 
-  static async connect (data: SCHEDULE.SOURCE.Detail) {
+  static async connect (data: DC.SOURCE.Detail) {
     await dataSourceConnect(data)
     message.success('连接成功')
   }

+ 7 - 0
src/controller/datacenter/dataTool.ts

@@ -0,0 +1,7 @@
+import { execSql } from '@/api/datacenter/dataLake'
+
+export class DataToolController {
+  static async exec (params: {dataSourceId: string, querySql: string}) {
+    return await execSql(params)
+  }
+}

+ 12 - 0
src/controller/datacenter/meteTool.ts

@@ -0,0 +1,12 @@
+import { getTable, getTableColumns } from '@/api/datacenter/meteTool'
+
+export class MeteToolController {
+  static async table (params: {dataSourceId: string}) {
+    return await getTable(params)
+  }
+
+  static async tableColumns (params: {dataSourceId: string, tableName: string}) {
+    const { code, data } = await getTableColumns(params)
+    return code === 200 ? data : []
+  }
+}

+ 2 - 0
src/controller/index.ts

@@ -24,3 +24,5 @@ export { FeatureController } from './cvs/featureController'
 export { NodesController } from './cvs/nodesController'
 
 export { AiboxController } from './cvs/aiboxController'
+
+export { DataToolController } from './datacenter/dataTool'

+ 1 - 1
src/hooks/effect.ts

@@ -55,7 +55,7 @@ export const usePort = (title: string) => {
   if (title === '物联网') {
     setBaseUrl('/iot')
   } else if (title === '视联网') {
-    setBaseUrl('/cvs')
+    setBaseUrl('/cvss')
   } else if (title === '用户群组') {
     setBaseUrl('/user')
   } else if (title === '数据中台') {

+ 11 - 3
src/pages/datacenter/dataLake/dataTool/index.vue

@@ -10,11 +10,11 @@
       <a-card  style="height: 100%;"  >
         <div>
         <a-space>
-          <a-button small type="link" :icon="h(RightCircleOutlined)" >执行</a-button>
+          <a-button small type="link" :icon="h(RightCircleOutlined)"  @click="exec">执行</a-button>
         </a-space>
         </div>
         <div style="margin-top: 20px;border: 1px solid #c9c9c9;" >
-          <code-mirror-tsx  style="width: 100%;" body-type="sql" :number-of-rows="20" />
+          <code-mirror-tsx  ref="codeMirrorDom" style="width: 100%;" body-type="sql" :number-of-rows="20" />
         </div>
         <div class="execute-info" >
           <div class="title" >执行信息</div>
@@ -29,8 +29,16 @@
 </template>
 <script lang='ts' setup >
 import { CodeMirrorTsx } from '@/components/CodeMirror/index'
-import { h } from 'vue'
+import { h, ref } from 'vue'
 import { RightCircleOutlined } from '@ant-design/icons-vue'
+import { DataToolController } from '@/controller/datacenter/dataTool'
+
+const codeMirrorDom = ref()
+
+const exec = async () => {
+  await DataToolController.exec({ querySql: codeMirrorDom.value.getValue(), dataSourceId: '' })
+}
+
 </script>
 <style lang='less' scoped >
 

+ 134 - 18
src/pages/datacenter/dataSource/manage/index.vue

@@ -1,17 +1,16 @@
 <template>
 <a-card title="数据源管理" >
-
-  <!--     :server="DataSourceController.page" -->
   <table-pro
-
+    :service="DataSourceController.page"
+    :serverParams="serverParams"
     :columns="columns"
     ref="tableProDom"
     @add="openModal"
   >
     <template #search >
       <a-space>
-        <InputTsx v-model:value="serverParams.label"  ></InputTsx>
-        <a-select style="width: 170px;" >
+        <InputTsx v-model:value="serverParams.label" placeholder="请输入数据源名称"  ></InputTsx>
+        <a-select style="width: 170px;" v-model:value="serverParams.dataSourceType"  >
           <a-select-option
             v-for="item in DataSourceController.dataSourceType"
             :key="item"
@@ -25,6 +24,20 @@
     </template>
     <template #render="{column, record}" >
       <template v-if="column.key === 'action'" >
+        <a-space>
+          <a>详情</a>
+          <a @click="pushMeteTool(record)" >管理源数据</a>
+          <a>修改</a>
+          <a-popconfirm
+            title="确定要删除这个数据源吗?"
+            ok-text="Yes"
+            cancel-text="No"
+            @confirm="delSource(record)"
+          >
+          <a>删除</a>
+          </a-popconfirm>
+
+        </a-space>
       </template>
     </template>
   </table-pro>
@@ -35,9 +48,85 @@
   @cancel="visible = false"
   tab-key="base"
   :tabs-list="[{ key: 'base', tab: '基础信息' },]"
-  @ok="submit"
 >
-
+  <a-form  style="width: 100%;" :labelCol="{span: 2}" :wrapperCol="{span: 14}">
+    <a-card title="基本信息" >
+      <a-form-item label="设备名称" v-bind="validateInfos.label"  >
+        <InputTsx allowClear placeholder="请输入设备名称" mode="normal" v-model:value="sourceState.label" />
+      </a-form-item>
+      <a-form-item label="设备描述" v-bind="validateInfos.description"  >
+        <InputTsx allowClear placeholder="请输入设备描述" v-model:value="sourceState.description" />
+      </a-form-item>
+    </a-card>
+
+    <a-card title="数据源" style="margin-top: 20px;" >
+      <a-form-item label="数据源类型"  >
+        <a-radio-group v-model:value="sourceState.dataSourceConnectParam.dataSourceType" button-style="solid">
+         <a-radio-button
+          v-for="item in DataSourceController.dataSourceType"
+          :key="item"
+          :value="item"
+        >
+          {{item}}
+        </a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item label="用户名" v-bind="validateInfos.username"  >
+        <InputTsx allowClear placeholder="请输入用户名" v-model:value="sourceState.dataSourceConnectParam.username" />
+      </a-form-item>
+      <a-form-item label="密码" v-bind="validateInfos.password"  >
+        <InputTsx allowClear placeholder="请输入密码" v-model:value="sourceState.dataSourceConnectParam.password" />
+      </a-form-item>
+      <a-form-item label="连接地址" v-bind="validateInfos.password"  >
+        <InputTsx allowClear placeholder="请输入连接地址" v-model:value="sourceState.dataSourceConnectParam.address" />
+      </a-form-item>
+      <a-form-item label="端口号" v-bind="validateInfos.portf"  >
+        <InputTsx allowClear placeholder="请输入端口号" v-model:value="sourceState.dataSourceConnectParam.port" />
+      </a-form-item>
+      <a-form-item label="数据库" v-bind="validateInfos.database"  >
+        <InputTsx allowClear placeholder="请输入数据库" v-model:value="sourceState.dataSourceConnectParam.database" />
+      </a-form-item>
+      <a-form-item label="连接类型"  >
+        <a-radio-group v-model:value="sourceState.dataSourceConnectParam.connectType" button-style="solid">
+         <a-radio-button value="ORACLE_SERVICE_NAME" > ORACLE_SERVICE_NAME</a-radio-button>
+         <a-radio-button value="ORACLE_SID" >  ORACLE_SID</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item label="驱动名称" v-bind="validateInfos.database"  >
+        <InputTsx allowClear placeholder="请输入驱动名称" v-model:value="sourceState.dataSourceConnectParam.driverClassName" />
+      </a-form-item>
+      <a-form-item label="校验sql" v-bind="validateInfos.database"  >
+        <InputTsx allowClear placeholder="请输入校验sql" v-model:value="sourceState.dataSourceConnectParam.validateQuery" />
+      </a-form-item>
+
+      <a-form-item label="连接数" v-bind="validateInfos.database"  >
+        <a-space>
+          最小空闲:<a-input-number id="inputNumber" v-model:value="sourceState.dataSourceConnectParam.minimumIdle" :min="1"  />
+          最大连接:<a-input-number id="inputNumber" v-model:value="sourceState.dataSourceConnectParam.maximumPoolSize" :min="1"  />
+        </a-space>
+      </a-form-item>
+
+      <a-form-item label="其他参数" v-bind="validateInfos.database"  >
+        <a-row :gutter="[8, 8]">
+          <a-col  :span="24" v-for="(item, index) in otherParameters" :key="index" >
+            <a-space>
+              <InputTsx allowClear placeholder="key" v-model:value="item.key" />
+              <InputTsx allowClear placeholder="value" v-model:value="item.value" />
+              <a-button type="dashed" danger @click="otherParameters.splice(index, 1)">删除</a-button>
+            </a-space>
+          </a-col>
+        </a-row>
+        <a-button style="margin-top: 20px;" type="primary"  @click="addOtherParameters" >新增</a-button>
+      </a-form-item>
+    </a-card>
+  </a-form>
+  <template #footer >
+    <a-space>
+      <a-button>取消</a-button>
+      <a-button @click="testConnect" >测试</a-button>
+      <a-button type="primary"  @click="submit" >确定</a-button>
+    </a-space>
+  </template>
 </RealView>
 </template>
 <script lang='ts' setup >
@@ -46,6 +135,7 @@ import { reactive, ref } from 'vue'
 import { InputTsx } from '@/components/MicroComponents'
 import { RealView } from '@/components/RealView/index'
 import { Form } from 'ant-design-vue'
+import { useRouter } from 'vue-router'
 
 const columns = [
   {
@@ -72,7 +162,8 @@ const useForm = Form.useForm
 const tableProDom = ref()
 
 const serverParams = ref({
-  label: ''
+  label: '',
+  dataSourceType: ''
 })
 
 const state = reactive({
@@ -81,6 +172,8 @@ const state = reactive({
 
 const oracleConnectTypes = ['ORACLE_SERVICE_NAME', 'ORACLE_SID']
 
+const otherParameters = ref<{key: string, value: string}[]>([])
+
 const sourceState = reactive({
   label: '',
   description: '',
@@ -90,16 +183,19 @@ const sourceState = reactive({
     password: '',
     address: '',
     port: '',
-    database: '',
+    database: 'ORACLE',
     driverClassName: '',
     validateQuery: '',
     minimumIdle: 5,
     maximumPoolSize: 50,
-    connectType: 'ORACLE_SERVICE_NAME' // ORACLE_SID
+    connectType: 'ORACLE_SERVICE_NAME', // ORACLE_SID
+    otherParameters: {
+
+    }
   }
 })
 
-const visible = ref<boolean>(true)
+const visible = ref<boolean>(false)
 
 const search = () => {
   tableProDom.value.reload()
@@ -113,16 +209,36 @@ const { resetFields, validate, validateInfos } = useForm(sourceState, {
   label: [{ required: true, message: '请填写数据源名称' }],
   description: [{ required: true, message: '请填写数据源描述' }],
   username: [{ required: true, message: '请填写用户名' }],
-  password: [{ required: true, message: '请填写用户名' }],
-  address: [{ required: true, message: '请填写用户名' }],
-  port: [{ required: true, message: '请填写用户名' }],
-  database: [{ required: true, message: '请填写用户名' }],
-  driverClassName: [{ required: true, message: '请填写用户名' }],
-  validateQuery: [{ required: true, message: '请填写用户名' }]
+  password: [{ required: true, message: '请填写密码' }],
+  address: [{ required: true, message: '请填写连接地址' }],
+  port: [{ required: true, message: '请填写端口号' }],
+  database: [{ required: true, message: '请填写数据库' }],
+  driverClassName: [{ required: true, message: '请填写驱动名称' }],
+  validateQuery: [{ required: true, message: '请填写验证SQL' }]
 })
 
-const submit = () => {
+const addOtherParameters = () => {
+  otherParameters.value.push({ key: '', value: '' })
+}
+
+const pushMeteTool = (record: DC.SOURCE.Detail) => {
+  useRouter().push({ path: '/dataSource/metaTool', query: { id: record.id } })
+}
+
+const testConnect = async () => {
+  await DataSourceController.connect(sourceState)
+}
+
+const delSource = async (record: DC.SOURCE.Detail) => {
+  await DataSourceController.del(record.id!)
+  search()
+}
 
+const submit = async () => {
+  validate().then(async () => {
+    await DataSourceController.add(sourceState)
+    visible.value = false
+  }).catch(() => {})
 }
 
 </script>

+ 126 - 0
src/pages/datacenter/dataSource/metaTool/index.vue

@@ -1,8 +1,134 @@
 <template>
 <a-card title="元数据管理" >
+
+  <a-row :gutter="[8, 8]" justify="space-between" >
+    <a-col :span="4" >
+      <div class="slider" >
+        <div class="title" >
+          目录  <ReloadIconTsx :reload="getTable" />
+        </div>
+        <a-spin :spinning="spinning">
+          <div class="table" >
+            <div
+              class="table-item"
+              @click="selectTable(item)"
+              v-for="item in tableList"
+              :key="item"
+            >
+              <span>{{item}} </span><CheckOutlined v-if="item === tableName" style="color: green;font-size: 22px;"  />
+            </div>
+          </div>
+        </a-spin>
+      </div>
+    </a-col>
+    <a-col :span="19" style="border: 1px solid hsla(0,0%,58%,.3);" >
+      <div class="table-title">
+        表名  <ReloadIconTsx :reload="getTableColumns" />
+      </div>
+      <a-spin :spinning="spinningTableColumns" >
+        <a-row :gutter="[8, 8]" style="padding: 16px;">
+          <a-col :span="6" v-for="item in tableColumns" :key="item.columnName" >
+              <span style="cursor: pointer;" >
+                <a-tooltip>
+                  <template #title> <div>名称: {{item.columnName}}</div><div>类型: {{item.columnType}}</div> <div>备注: {{item.columnRemark}}</div><div>大小: {{item.columnSize}}</div></template>
+                  <a-space> <TableOutlined />{{item.columnName}} </a-space>
+                </a-tooltip>
+              </span>
+          </a-col>
+        </a-row>
+      </a-spin>
+    </a-col>
+  </a-row>
+
 </a-card>
 </template>
 <script lang='ts' setup >
+import { ReloadIconTsx } from '@/components/MicroComponents'
+import { MeteToolController } from '@/controller/datacenter/meteTool'
+import { CheckOutlined, TableOutlined } from '@ant-design/icons-vue'
+import { onMounted, ref } from 'vue'
+import { useRoute } from 'vue-router'
+
+const dataSourceId = useRoute().query.id as string
+
+const tableName = ref('')
+
+const tableList = ref<string[]>(['sql-lize', 'xxx'])
+
+const tableColumns = ref<DC.TableColumns[]>([])
+
+const spinning = ref<boolean>(false)
+
+const spinningTableColumns = ref<boolean>(false)
+
+const selectTable = (name: string) => {
+  tableName.value = name
+  getTableColumns()
+}
+
+const getTableColumns = async () => {
+  spinningTableColumns.value = true
+  tableColumns.value = await MeteToolController.tableColumns({ dataSourceId, tableName: tableName.value })
+  spinningTableColumns.value = false
+}
+
+const getTable = async () => {
+  spinning.value = true
+  const { data } = await MeteToolController.table({ dataSourceId })
+  spinning.value = false
+  tableList.value = data
+}
+
+onMounted(() => {
+  getTable()
+})
+
 </script>
 <style lang='less' scoped >
+
+.slider {
+  width: 300px;
+  height: 600px;
+  border: 1px solid hsla(0,0%,58%,.3);
+  .title {
+    width: 100%;
+    height: 40px;
+    border-bottom: 1px solid hsla(0,0%,58%,.3);
+    font-size: 20px;
+    display: flex;
+    align-items: center;
+    padding: 0 16px;
+    box-sizing: border-box;
+    justify-content: space-between;
+  }
+  .table {
+    width: 100%;
+    .table-item {
+      width: 100%;
+      height: 30px;
+      padding: 0 16px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      border-bottom: 1px solid hsla(0,0%,58%,.3);
+      cursor: pointer;
+    }
+    .active {
+      // background-color: #88beeb;
+    }
+  }
+}
+
+.table-title {
+    width: 100%;
+    height: 40px;
+    border-bottom: 1px solid hsla(0,0%,58%,.3);
+    font-size: 20px;
+    display: flex;
+    align-items: center;
+    padding: 0 16px;
+    box-sizing: border-box;
+    justify-content: space-between;
+}
+
 </style>

+ 8 - 1
src/type/schedule.d.ts → src/type/dc.d.ts

@@ -1,5 +1,5 @@
 
-declare namespace SCHEDULE {
+declare namespace DC {
   namespace API {
     interface Detail {
       serviceName: string,
@@ -75,4 +75,11 @@ declare namespace SCHEDULE {
       }
 
   }
+
+  interface TableColumns {
+    columnName: string
+    columnType: string
+    columnRemark: string
+    columnSize: string
+  }
 }