init
This commit is contained in:
228
src/views/dts/executor/index.vue
Normal file
228
src/views/dts/executor/index.vue
Normal file
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column label="排序" width="50" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.order }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="名称" width="120" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">{{ scope.row.title }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="分组标识" width="200" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.appName }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="注册方式" width="110" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope"> {{ addressTypes.find(t => t.value === scope.row.addressType).label }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="在线机器" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">{{ scope.row.addressList }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="230" class-name="small-padding fixed-width">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" size="mini" @click="handleUpdate(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.current" :limit.sync="listQuery.size" @pagination="fetchData" />
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
|
||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="80px" style="width: 400px; margin-left:50px;">
|
||||
<el-form-item label="AppName" prop="appName">
|
||||
<el-input v-model="temp.appName" placeholder="AppName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" prop="title">
|
||||
<el-input v-model="temp.title" placeholder="请输入执行器名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="prop">
|
||||
<el-input v-model="temp.order" placeholder="执行器序号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="注册方式" prop="addressType">
|
||||
<el-radio-group v-model="temp.addressType">
|
||||
<el-radio :label="0">自动注册</el-radio>
|
||||
<el-radio :label="1">手动录入</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="机器地址" prop="addressList">
|
||||
<el-input v-model="temp.addressList" :disabled="dialogStatus!=='create'" placeholder="多个以逗号分隔" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as executor from '@/api/dts/datax-executor'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
|
||||
|
||||
export default {
|
||||
name: 'Executor',
|
||||
components: { Pagination },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
name: undefined,
|
||||
jobGroup: undefined
|
||||
},
|
||||
editJsonVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
textMap: {
|
||||
update: 'Edit',
|
||||
create: 'Create'
|
||||
},
|
||||
rules: {
|
||||
appName: [{ required: true, message: 'appName is required', trigger: 'blur' }],
|
||||
title: [{ required: true, message: 'title is required', trigger: 'blur' }],
|
||||
order: [{ required: true, message: 'title is required', trigger: 'blur' }],
|
||||
addressType: [{ required: true, message: 'title is required', trigger: 'change' }]
|
||||
},
|
||||
temp: {
|
||||
id: undefined,
|
||||
appName: undefined,
|
||||
title: undefined,
|
||||
order: undefined,
|
||||
addressType: undefined,
|
||||
addressList: undefined
|
||||
},
|
||||
addressTypes: [
|
||||
{ value: 0, label: '自动注册' },
|
||||
{ value: 1, label: '手动录入' }
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
executor.getList().then(response => {
|
||||
const { content } = response
|
||||
this.list = content
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
resetTemp() {
|
||||
this.temp = {
|
||||
id: undefined,
|
||||
appName: undefined,
|
||||
title: undefined,
|
||||
order: undefined,
|
||||
addressType: undefined,
|
||||
addressList: undefined
|
||||
}
|
||||
},
|
||||
handleCreate() {
|
||||
this.resetTemp()
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
createData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
executor.created(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.temp = Object.assign({}, row) // copy obj
|
||||
this.dialogStatus = 'update'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
updateData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
const tempData = Object.assign({}, this.temp)
|
||||
tempData.configJson = this.configJson
|
||||
executor.updated(tempData).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Update Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
executor.deleted(row.id).then(response => {
|
||||
this.fetchData()
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
// const index = this.list.indexOf(row)
|
||||
},
|
||||
handleFetchPv(id) {
|
||||
executor.fetch(id).then(response => {
|
||||
this.pluginData = response
|
||||
this.dialogPvVisible = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
426
src/views/dts/jdbc-datasource/index.vue
Normal file
426
src/views/dts/jdbc-datasource/index.vue
Normal file
@@ -0,0 +1,426 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input
|
||||
v-model="listQuery.datasourceName"
|
||||
clearable
|
||||
placeholder="数据源名称"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="handleFilter"
|
||||
/>
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
|
||||
添加
|
||||
</el-button>
|
||||
<!-- <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
|
||||
reviewer
|
||||
</el-checkbox> -->
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<!-- <el-table-column align="center" label="序号" width="95">
|
||||
<template slot-scope="scope">{{ scope.$index }}</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="数据源" width="120" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.datasource }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据源名称" width="150" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.datasourceName }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据源分组" width="120" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.datasourceGroup }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column label="用户名" width="150" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jdbcUsername ? scope.row.jdbcUsername:'-' }}</template>
|
||||
</el-table-column>-->
|
||||
<el-table-column label="jdbc连接串" width="300" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">{{ scope.row.jdbcUrl ? scope.row.jdbcUrl:'-' }}</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="jdbc驱动类" width="200" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">{{ scope.row.jdbcDriverClass ? scope.row.jdbcDriverClass:'-' }}</template>
|
||||
</el-table-column>-->
|
||||
<el-table-column label="ZK地址" width="200" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">{{ scope.row.zkAdress ? scope.row.zkAdress:'-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数据库名" width="200" align="center" :show-overflow-tooltip="true">-->
|
||||
<template slot-scope="scope">{{ scope.row.databaseName ? scope.row.databaseName:'-' }}</template>-->
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="备注" width="150" align="center">-->
|
||||
<!-- <template slot-scope="scope">{{ scope.row.comments }}</template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column label="操作" align="center" width="230" class-name="small-padding fixed-width">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" size="mini" @click="handleUpdate(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="listQuery.current"
|
||||
:limit.sync="listQuery.size"
|
||||
@pagination="fetchData"
|
||||
/>
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="800px">
|
||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="100px">
|
||||
<el-form-item label="数据源" prop="datasource">
|
||||
<el-select
|
||||
v-model="temp.datasource"
|
||||
placeholder="数据源"
|
||||
style="width: 200px"
|
||||
@change="selectDataSource(temp.datasource)"
|
||||
>
|
||||
<el-option v-for="item in dataSources" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据源名称" prop="datasourceName">
|
||||
<el-input v-model="temp.datasourceName" placeholder="数据源名称" style="width: 40%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据源分组" prop="datasourceGroup">
|
||||
<el-input v-model="temp.datasourceGroup" placeholder="数据源分组" style="width: 40%" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="jdbc" label="用户名">
|
||||
<el-input v-model="temp.jdbcUsername" placeholder="用户名" style="width: 40%" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="visible" v-show="jdbc" label="密码">
|
||||
<el-input v-model="temp.jdbcPassword" type="password" placeholder="密码" style="width: 40%">
|
||||
<i slot="suffix" title="显示密码" style="cursor:pointer" class="el-icon-view" @click="changePass('show')" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="jdbc" v-else label="密码">
|
||||
<el-input v-model="temp.jdbcPassword" type="text" placeholder="密码" style="width: 40%">
|
||||
<i slot="suffix" title="隐藏密码" style="cursor:pointer" class="el-icon-check" @click="changePass('hide')" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="jdbc" label="jdbc url" prop="jdbcUrl">
|
||||
<el-input
|
||||
v-model="temp.jdbcUrl"
|
||||
:autosize="{ minRows: 3, maxRows: 6}"
|
||||
type="textarea"
|
||||
placeholder="jdbc url"
|
||||
style="width: 60%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mongodb" label="地址" prop="jdbcUrl">
|
||||
<el-input
|
||||
v-model="temp.jdbcUrl"
|
||||
:autosize="{ minRows: 3, maxRows: 6}"
|
||||
type="textarea"
|
||||
placeholder="localhost:27017"
|
||||
style="width: 60%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="jdbc" label="jdbc驱动类" prop="jdbcDriverClass">
|
||||
<el-input v-model="temp.jdbcDriverClass" placeholder="jdbc驱动类" style="width: 60%" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="hbase" label="ZK地址" prop="zkAdress">
|
||||
<el-input v-model="temp.zkAdress" placeholder="localhost:2181" style="width: 60%" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="mongodb" label="数据库名称" prop="databaseName">
|
||||
<el-input v-model="temp.databaseName" placeholder="数据库名称" style="width: 60%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="注释">
|
||||
<el-input
|
||||
v-model="temp.comments"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
type="textarea"
|
||||
placeholder="Please input"
|
||||
style="width: 60%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
|
||||
确认
|
||||
</el-button>
|
||||
<el-button type="primary" @click="testDataSource()">
|
||||
测试连接
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog :visible.sync="dialogPluginVisible" title="Reading statistics">
|
||||
<el-table :data="pluginData" border fit highlight-current-row style="width: 100%">
|
||||
<el-table-column prop="key" label="Channel" />
|
||||
<el-table-column prop="pv" label="Pv" />
|
||||
</el-table>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as datasourceApi from '@/api/dts/datax-jdbcDatasource'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
import { parseTime } from '@/utils'
|
||||
import Pagination from '@/components/Pagination'
|
||||
|
||||
export default {
|
||||
name: 'JdbcDatasource',
|
||||
components: { Pagination },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
pluginTypeOptions: ['reader', 'writer'],
|
||||
dialogPluginVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
textMap: {
|
||||
update: 'Edit',
|
||||
create: 'Create'
|
||||
},
|
||||
rules: {
|
||||
datasourceName: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
jdbcUsername: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
jdbcPassword: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
jdbcUrl: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
jdbcDriverClass: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
datasource: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
zkAdress: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
databaseName: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
},
|
||||
temp: {
|
||||
id: undefined,
|
||||
datasourceName: '',
|
||||
datasourceGroup: 'Default',
|
||||
jdbcUsername: '',
|
||||
jdbcPassword: '',
|
||||
jdbcUrl: '',
|
||||
jdbcDriverClass: '',
|
||||
comments: '',
|
||||
datasource: '',
|
||||
zkAdress: '',
|
||||
databaseName: ''
|
||||
},
|
||||
visible: true,
|
||||
dataSources: [
|
||||
{ value: 'mysql', label: 'mysql' },
|
||||
{ value: 'oracle', label: 'oracle' },
|
||||
{ value: 'hana', label: 'hana' },
|
||||
{ value: 'postgresql', label: 'postgresql' },
|
||||
{ value: 'sqlserver', label: 'sqlserver' },
|
||||
{ value: 'hive', label: 'hive' },
|
||||
{ value: 'hbase', label: 'hbase' },
|
||||
{ value: 'mongodb', label: 'mongodb' },
|
||||
{ value: 'clickhouse', label: 'clickhouse' }
|
||||
],
|
||||
jdbc: true,
|
||||
hbase: false,
|
||||
mongodb: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
selectDataSource(datasource) {
|
||||
if (datasource === 'mysql') {
|
||||
this.temp.jdbcUrl = 'jdbc:mysql://{host}:{port}/{database}'
|
||||
this.temp.jdbcDriverClass = 'com.mysql.jdbc.Driver'
|
||||
} else if (datasource === 'hana') {
|
||||
this.temp.jdbcUrl = 'jdbc:sap://{host}:{port}/{instanceNumber}'
|
||||
this.temp.jdbcDriverClass = 'com.sap.db.jdbc.Driver'
|
||||
} else if (datasource === 'oracle') {
|
||||
this.temp.jdbcUrl = 'jdbc:oracle:thin:@//{host}:{port}/{serviceName}'
|
||||
this.temp.jdbcDriverClass = 'oracle.jdbc.OracleDriver'
|
||||
} else if (datasource === 'postgresql') {
|
||||
this.temp.jdbcUrl = 'jdbc:postgresql://{host}:{port}/{database}'
|
||||
this.temp.jdbcDriverClass = 'org.postgresql.Driver'
|
||||
} else if (datasource === 'sqlserver') {
|
||||
this.temp.jdbcUrl = 'jdbc:jtds:sqlserver://{host}:{port};DatabaseName={database}'
|
||||
this.temp.jdbcDriverClass = 'net.sourceforge.jtds.jdbc.Driver'
|
||||
} else if (datasource === 'clickhouse') {
|
||||
this.temp.jdbcUrl = 'jdbc:clickhouse://{host}:{port}/{database}'
|
||||
this.temp.jdbcDriverClass = 'ru.yandex.clickhouse.ClickHouseDriver'
|
||||
} else if (datasource === 'hive') {
|
||||
this.temp.jdbcUrl = 'jdbc:hive2://{host}:{port}/{database}'
|
||||
this.temp.jdbcDriverClass = 'org.apache.hive.jdbc.HiveDriver'
|
||||
this.hbase = this.mongodb = false
|
||||
this.jdbc = true
|
||||
}
|
||||
this.getShowStrategy(datasource)
|
||||
},
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
datasourceApi.list(this.listQuery).then(response => {
|
||||
const { data } = response
|
||||
const { total } = data.total
|
||||
this.total = total
|
||||
this.list = data.records
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
resetTemp() {
|
||||
this.temp = {
|
||||
id: undefined,
|
||||
datasourceName: '',
|
||||
datasourceGroup: 'Default',
|
||||
jdbcUsername: '',
|
||||
jdbcPassword: '',
|
||||
jdbcUrl: '',
|
||||
jdbcDriverClass: '',
|
||||
comments: ''
|
||||
}
|
||||
},
|
||||
handleCreate() {
|
||||
this.resetTemp()
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
createData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
datasourceApi.created(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
testDataSource() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
datasourceApi.test(this.temp).then(response => {
|
||||
if (response.data === false) {
|
||||
this.$notify({
|
||||
title: 'Fail',
|
||||
message: response.data.msg,
|
||||
type: 'fail',
|
||||
duration: 2000
|
||||
})
|
||||
} else {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Tested Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.getShowStrategy(row.datasource)
|
||||
this.temp = Object.assign({}, row) // copy obj
|
||||
this.dialogStatus = 'update'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
updateData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
const tempData = Object.assign({}, this.temp)
|
||||
datasourceApi.updated(tempData).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Update Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
getShowStrategy(datasource) {
|
||||
if (datasource === 'hbase') {
|
||||
this.jdbc = this.mongodb = false
|
||||
this.hbase = true
|
||||
} else if (datasource === 'mongodb') {
|
||||
this.jdbc = this.hbase = false
|
||||
this.mongodb = true
|
||||
this.temp.jdbcUrl = 'mongodb://[username:password@]host1[:port1][,...hostN[:portN]]][/[database][?options]]'
|
||||
} else {
|
||||
this.hbase = this.mongodb = false
|
||||
this.jdbc = true
|
||||
}
|
||||
},
|
||||
handleDelete(row) {
|
||||
console.log('删除')
|
||||
const idList = []
|
||||
idList.push(row.id)
|
||||
// 拼成 idList=xx
|
||||
// 多个比较麻烦,这里不处理
|
||||
datasourceApi.deleted({ idList: row.id }).then(response => {
|
||||
this.fetchData()
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
// const index = this.list.indexOf(row)
|
||||
},
|
||||
handleFetchPv(id) {
|
||||
datasourceApi.fetched(id).then(response => {
|
||||
this.pluginData = response
|
||||
this.dialogPvVisible = true
|
||||
})
|
||||
},
|
||||
formatJson(filterVal, jsonData) {
|
||||
return jsonData.map(v => filterVal.map(j => {
|
||||
if (j === 'timestamp') {
|
||||
return parseTime(v[j])
|
||||
} else {
|
||||
return v[j]
|
||||
}
|
||||
}))
|
||||
},
|
||||
changePass(value) {
|
||||
this.visible = !(value === 'show')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
758
src/views/dts/jobInfo/index.vue
Normal file
758
src/views/dts/jobInfo/index.vue
Normal file
@@ -0,0 +1,758 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input v-model="listQuery.jobDesc" placeholder="任务名称" style="width: 200px;" class="filter-item" />
|
||||
<el-select v-model="projectIds" multiple placeholder="所属项目" class="filter-item">
|
||||
<el-option v-for="item in jobProjectList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-select v-model="listQuery.glueType" placeholder="任务类型" style="width: 200px" class="filter-item">
|
||||
<el-option v-for="item in glueTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
|
||||
添加
|
||||
</el-button>
|
||||
<!-- <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
|
||||
reviewer
|
||||
</el-checkbox> -->
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
style="width: 100%"
|
||||
size="medium"
|
||||
>
|
||||
<el-table-column align="center" label="ID" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.id }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务名称" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jobDesc }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属项目" align="center" width="120">
|
||||
<template slot-scope="scope">{{ scope.row.projectName }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Cron" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.jobCron }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="路由策略" align="center" width="130">
|
||||
<template slot-scope="scope"> {{ routeStrategies.find(t => t.value === scope.row.executorRouteStrategy).label }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.triggerStatus"
|
||||
active-color="#00A854"
|
||||
active-text="启动"
|
||||
:active-value="1"
|
||||
inactive-color="#F04134"
|
||||
inactive-text="停止"
|
||||
:inactive-value="0"
|
||||
@change="changeSwitch(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="注册节点" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="500"
|
||||
@show="loadById(scope.row)"
|
||||
>
|
||||
<el-table :data="registerNode">
|
||||
<el-table-column width="150" property="title" label="执行器名称" />
|
||||
<el-table-column width="150" property="appName" label="分组标识" />
|
||||
<el-table-column width="150" property="registryList" label="机器地址" />
|
||||
</el-table>
|
||||
<el-button slot="reference" size="small">查看</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下次触发时间" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="300"
|
||||
@show="nextTriggerTime(scope.row)"
|
||||
>
|
||||
<h5 v-html="triggerNextTimes" />
|
||||
<el-button slot="reference" size="small">查看</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="执行状态" align="center" width="80">
|
||||
<template slot-scope="scope"> {{ statusList.find(t => t.value === scope.row.lastHandleCode).label }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" fixed="right">
|
||||
<template slot-scope="{row}">
|
||||
<!-- <el-dropdown type="primary" size="small"> -->
|
||||
<!-- 操作 -->
|
||||
<el-dropdown trigger="click">
|
||||
<span class="el-dropdown-link">
|
||||
操作<i class="el-icon-arrow-down el-icon--right" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="handlerExecute(row)">执行一次</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="handlerViewLog(row)">查询日志</el-dropdown-item>
|
||||
<el-dropdown-item divided @click.native="handlerUpdate(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="handlerDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.current" :limit.sync="listQuery.size" @pagination="fetchData" />
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="1000px" :before-close="handleClose">
|
||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="110px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行器" prop="jobGroup">
|
||||
<el-select v-model="temp.jobGroup" placeholder="请选择执行器">
|
||||
<el-option v-for="item in executorList" :key="item.id" :label="item.title" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务名称" prop="jobDesc">
|
||||
<el-input v-model="temp.jobDesc" size="medium" placeholder="请输入任务描述" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="路由策略" prop="executorRouteStrategy">
|
||||
<el-select v-model="temp.executorRouteStrategy" placeholder="请选择路由策略">
|
||||
<el-option v-for="item in routeStrategies" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-dialog
|
||||
title="提示"
|
||||
:visible.sync="showCronBox"
|
||||
width="60%"
|
||||
append-to-body
|
||||
>
|
||||
<cron v-model="temp.jobCron" />
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showCronBox = false;">关闭</el-button>
|
||||
<el-button type="primary" @click="showCronBox = false">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-form-item label="Cron" prop="jobCron">
|
||||
<el-input v-model="temp.jobCron" auto-complete="off" placeholder="请输入Cron表达式">
|
||||
<el-button v-if="!showCronBox" slot="append" icon="el-icon-turn-off" title="打开图形配置" @click="showCronBox = true" />
|
||||
<el-button v-else slot="append" icon="el-icon-open" title="关闭图形配置" @click="showCronBox = false" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="阻塞处理" prop="executorBlockStrategy">
|
||||
<el-select v-model="temp.executorBlockStrategy" placeholder="请选择阻塞处理策略">
|
||||
<el-option v-for="item in blockStrategies" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="报警邮件">
|
||||
<el-input v-model="temp.alarmEmail" placeholder="请输入报警邮件,多个用逗号分隔" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务类型" prop="glueType">
|
||||
<el-select v-model="temp.glueType" placeholder="任务脚本类型">
|
||||
<el-option v-for="item in glueTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="失败重试次数">
|
||||
<el-input-number v-model="temp.executorFailRetryCount" :min="0" :max="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属项目" prop="projectId">
|
||||
<el-select v-model="temp.projectId" placeholder="所属项目" class="filter-item">
|
||||
<el-option v-for="item in jobProjectList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="超时时间(分钟)">
|
||||
<el-input-number v-model="temp.executorTimeout" :min="0" :max="120" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="子任务">
|
||||
<el-select v-model="temp.childJobId" multiple placeholder="子任务" value-key="id">
|
||||
<el-option v-for="item in jobIdList" :key="item.id" :label="item.jobDesc" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" />
|
||||
</el-row>
|
||||
<el-row v-if="temp.glueType==='BEAN'" :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="辅助参数" prop="incrementType">
|
||||
<el-select v-model="temp.incrementType" placeholder="请选择参数类型" value="">
|
||||
<el-option v-for="item in incrementTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="temp.glueType==='BEAN' && temp.incrementType === 1" :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="增量主键开始ID" prop="incStartId">
|
||||
<el-input v-model="temp.incStartId" placeholder="首次增量使用" style="width: 56%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="ID增量参数" prop="replaceParam">
|
||||
<el-input v-model="temp.replaceParam" placeholder="-DstartId='%s' -DendId='%s'" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="reader数据源" prop="datasourceId">
|
||||
<el-select v-model="temp.datasourceId" placeholder="reader数据源" class="filter-item">
|
||||
<el-option v-for="item in dataSourceList" :key="item.id" :label="item.datasourceName" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item label="reader表" prop="readerTable">
|
||||
<el-input v-model="temp.readerTable" placeholder="读表的表名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-form-item label="主键" label-width="40px" prop="primaryKey">
|
||||
<el-input v-model="temp.primaryKey" placeholder="请填写主键字段名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="temp.glueType==='BEAN' && temp.incrementType === 2" :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="增量开始时间" prop="incStartTime">
|
||||
<el-date-picker
|
||||
v-model="temp.incStartTime"
|
||||
type="datetime"
|
||||
placeholder="首次增量使用"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
style="width: 57%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="增量时间字段" prop="replaceParam">
|
||||
<el-input v-model="temp.replaceParam" placeholder="-DlastTime='%s' -DcurrentTime='%s'" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="增量时间格式" prop="replaceParamType">
|
||||
<el-select v-model="temp.replaceParamType" placeholder="增量时间格式" @change="incStartTimeFormat">
|
||||
<el-option v-for="item in replaceFormatTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row v-if="temp.glueType==='BEAN' && temp.incrementType === 3" :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="分区字段" prop="partitionField">
|
||||
<el-input v-model="partitionField" placeholder="请输入分区字段" style="width: 56%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item label="分区时间">
|
||||
<el-select v-model="timeFormatType" placeholder="分区时间格式">
|
||||
<el-option v-for="item in timeFormatTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-input-number v-model="timeOffset" :min="-20" :max="0" style="width: 65%" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="temp.glueType==='BEAN'" :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="JVM启动参数">
|
||||
<el-input v-model="temp.jvmParam" placeholder="-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<json-editor v-if="temp.glueType==='BEAN'" ref="jsonEditor" v-model="jobJson" />
|
||||
<shell-editor v-if="temp.glueType==='GLUE_SHELL'" ref="shellEditor" v-model="glueSource" />
|
||||
<python-editor v-if="temp.glueType==='GLUE_PYTHON'" ref="pythonEditor" v-model="glueSource" />
|
||||
<powershell-editor v-if="temp.glueType==='GLUE_POWERSHELL'" ref="powershellEditor" v-model="glueSource" />
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as executor from '@/api/dts/datax-executor'
|
||||
import * as job from '@/api/dts/datax-job-info'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
import Cron from '@/components/Cron'
|
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
|
||||
import JsonEditor from '@/components/JsonEditor'
|
||||
import ShellEditor from '@/components/ShellEditor'
|
||||
import PythonEditor from '@/components/PythonEditor'
|
||||
import PowershellEditor from '@/components/PowershellEditor'
|
||||
import * as datasourceApi from '@/api/dts/datax-jdbcDatasource'
|
||||
import * as jobProjectApi from '@/api/dts/datax-job-project'
|
||||
import { isJSON } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
name: 'JobInfo',
|
||||
components: { Pagination, JsonEditor, ShellEditor, PythonEditor, PowershellEditor, Cron },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validateIncParam = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
callback(new Error('Increment parameters is required'))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
const validatePartitionParam = (rule, value, callback) => {
|
||||
if (!this.partitionField) {
|
||||
callback(new Error('Partition parameters is required'))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
projectIds: '',
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
jobGroup: 0,
|
||||
projectIds: '',
|
||||
triggerStatus: -1,
|
||||
jobDesc: '',
|
||||
glueType: ''
|
||||
},
|
||||
showCronBox: false,
|
||||
dialogPluginVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
textMap: {
|
||||
update: 'Edit',
|
||||
create: 'Create'
|
||||
},
|
||||
rules: {
|
||||
jobGroup: [{ required: true, message: 'jobGroup is required', trigger: 'change' }],
|
||||
executorRouteStrategy: [{ required: true, message: 'executorRouteStrategy is required', trigger: 'change' }],
|
||||
executorBlockStrategy: [{ required: true, message: 'executorBlockStrategy is required', trigger: 'change' }],
|
||||
glueType: [{ required: true, message: 'jobType is required', trigger: 'change' }],
|
||||
projectId: [{ required: true, message: 'projectId is required', trigger: 'change' }],
|
||||
jobDesc: [{ required: true, message: 'jobDesc is required', trigger: 'blur' }],
|
||||
jobProject: [{ required: true, message: 'jobProject is required', trigger: 'blur' }],
|
||||
jobCron: [{ required: true, message: 'jobCron is required', trigger: 'blur' }],
|
||||
incStartId: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
replaceParam: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
primaryKey: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
incStartTime: [{ trigger: 'change', validator: validateIncParam }],
|
||||
replaceParamType: [{ trigger: 'change', validator: validateIncParam }],
|
||||
partitionField: [{ trigger: 'blur', validator: validatePartitionParam }],
|
||||
datasourceId: [{ trigger: 'change', validator: validateIncParam }],
|
||||
readerTable: [{ trigger: 'blur', validator: validateIncParam }]
|
||||
},
|
||||
temp: {
|
||||
id: undefined,
|
||||
jobGroup: '',
|
||||
jobCron: '',
|
||||
jobDesc: '',
|
||||
executorRouteStrategy: '',
|
||||
executorBlockStrategy: '',
|
||||
childJobId: '',
|
||||
executorFailRetryCount: '',
|
||||
alarmEmail: '',
|
||||
executorTimeout: '',
|
||||
userId: 0,
|
||||
jobConfigId: '',
|
||||
executorHandler: '',
|
||||
glueType: '',
|
||||
glueSource: '',
|
||||
jobJson: '',
|
||||
executorParam: '',
|
||||
replaceParam: '',
|
||||
replaceParamType: 'Timestamp',
|
||||
jvmParam: '',
|
||||
incStartTime: '',
|
||||
partitionInfo: '',
|
||||
incrementType: 0,
|
||||
incStartId: '',
|
||||
primaryKey: '',
|
||||
projectId: '',
|
||||
datasourceId: '',
|
||||
readerTable: ''
|
||||
},
|
||||
resetTemp() {
|
||||
// this.temp = this.$options.data().temp
|
||||
this.jobJson = ''
|
||||
this.glueSource = ''
|
||||
this.timeOffset = 0
|
||||
this.timeFormatType = 'yyyy-MM-dd'
|
||||
this.partitionField = ''
|
||||
},
|
||||
executorList: '',
|
||||
jobIdList: '',
|
||||
jobProjectList: '',
|
||||
dataSourceList: '',
|
||||
blockStrategies: [
|
||||
{ value: 'SERIAL_EXECUTION', label: '单机串行' },
|
||||
{ value: 'DISCARD_LATER', label: '丢弃后续调度' },
|
||||
{ value: 'COVER_EARLY', label: '覆盖之前调度' }
|
||||
],
|
||||
routeStrategies: [
|
||||
{ value: 'FIRST', label: '第一个' },
|
||||
{ value: 'LAST', label: '最后一个' },
|
||||
{ value: 'ROUND', label: '轮询' },
|
||||
{ value: 'RANDOM', label: '随机' },
|
||||
{ value: 'CONSISTENT_HASH', label: '一致性HASH' },
|
||||
{ value: 'LEAST_FREQUENTLY_USED', label: '最不经常使用' },
|
||||
{ value: 'LEAST_RECENTLY_USED', label: '最近最久未使用' },
|
||||
{ value: 'FAILOVER', label: '故障转移' },
|
||||
{ value: 'BUSYOVER', label: '忙碌转移' }
|
||||
// { value: 'SHARDING_BROADCAST', label: '分片广播' }
|
||||
],
|
||||
glueTypes: [
|
||||
{ value: 'BEAN', label: 'FlinkX任务' },
|
||||
{ value: 'GLUE_SHELL', label: 'Shell任务' },
|
||||
{ value: 'GLUE_PYTHON', label: 'Python任务' },
|
||||
{ value: 'GLUE_POWERSHELL', label: 'PowerShell任务' }
|
||||
],
|
||||
incrementTypes: [
|
||||
{ value: 0, label: '无' },
|
||||
{ value: 1, label: '主键自增' },
|
||||
{ value: 2, label: '时间自增' },
|
||||
{ value: 3, label: 'HIVE分区' }
|
||||
],
|
||||
triggerNextTimes: '',
|
||||
registerNode: [],
|
||||
jobJson: '',
|
||||
glueSource: '',
|
||||
timeOffset: 0,
|
||||
timeFormatType: 'yyyy-MM-dd',
|
||||
partitionField: '',
|
||||
timeFormatTypes: [
|
||||
{ value: 'yyyy-MM-dd', label: 'yyyy-MM-dd' },
|
||||
{ value: 'yyyyMMdd', label: 'yyyyMMdd' },
|
||||
{ value: 'yyyy/MM/dd', label: 'yyyy/MM/dd' }
|
||||
],
|
||||
replaceFormatTypes: [
|
||||
{ value: 'yyyy/MM/dd', label: 'yyyy/MM/dd' },
|
||||
{ value: 'yyyy-MM-dd', label: 'yyyy-MM-dd' },
|
||||
{ value: 'HH:mm:ss', label: 'HH:mm:ss' },
|
||||
{ value: 'yyyy/MM/dd HH:mm:ss', label: 'yyyy/MM/dd HH:mm:ss' },
|
||||
{ value: 'yyyy-MM-dd HH:mm:ss', label: 'yyyy-MM-dd HH:mm:ss' },
|
||||
{ value: 'Timestamp', label: '时间戳' }
|
||||
],
|
||||
statusList: [
|
||||
{ value: 500, label: '失败' },
|
||||
{ value: 502, label: '失败(超时)' },
|
||||
{ value: 200, label: '成功' },
|
||||
{ value: 0, label: '无' }
|
||||
]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
this.getExecutor()
|
||||
this.getJobIdList()
|
||||
this.getJobProject()
|
||||
this.getDataSourceList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClose(done) {
|
||||
this.$confirm('确认关闭?')
|
||||
.then(_ => {
|
||||
done()
|
||||
})
|
||||
.catch(_ => {})
|
||||
},
|
||||
getExecutor() {
|
||||
job.getExecutorList().then(response => {
|
||||
const { content } = response
|
||||
this.executorList = content
|
||||
})
|
||||
},
|
||||
getJobIdList() {
|
||||
job.getJobIdList().then(response => {
|
||||
const { content } = response
|
||||
this.jobIdList = content
|
||||
})
|
||||
},
|
||||
getJobProject() {
|
||||
jobProjectApi.getJobProjectList().then(response => {
|
||||
this.jobProjectList = response.data
|
||||
})
|
||||
},
|
||||
getDataSourceList() {
|
||||
datasourceApi.getDataSourceList().then(response => {
|
||||
this.dataSourceList = response
|
||||
})
|
||||
},
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
if (this.projectIds) {
|
||||
this.listQuery.projectIds = this.projectIds.toString()
|
||||
}
|
||||
|
||||
job.getList(this.listQuery).then(response => {
|
||||
const { content } = response
|
||||
this.total = content.recordsTotal
|
||||
this.list = content.data
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
incStartTimeFormat(vData) {
|
||||
},
|
||||
handleCreate() {
|
||||
this.resetTemp()
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
createData() {
|
||||
if (this.temp.glueType === 'BEAN' && !isJSON(this.jobJson)) {
|
||||
this.$notify({
|
||||
title: 'Fail',
|
||||
message: 'json格式错误',
|
||||
type: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.temp.childJobId) {
|
||||
const auth = []
|
||||
for (const i in this.temp.childJobId) {
|
||||
auth.push(this.temp.childJobId[i].id)
|
||||
}
|
||||
this.temp.childJobId = auth.toString()
|
||||
}
|
||||
this.temp.jobJson = this.jobJson
|
||||
this.temp.glueSource = this.glueSource
|
||||
this.temp.executorHandler = this.temp.glueType === 'BEAN' ? 'executorJobHandler' : ''
|
||||
if (this.partitionField) this.temp.partitionInfo = this.partitionField + ',' + this.timeOffset + ',' + this.timeFormatType
|
||||
job.createJob(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerUpdate(row) {
|
||||
// this.resetTemp()
|
||||
this.temp = Object.assign({}, row) // copy obj
|
||||
if (this.temp.jobJson) this.jobJson = JSON.parse(this.temp.jobJson)
|
||||
this.glueSource = this.temp.glueSource
|
||||
const arrchildSet = []
|
||||
const arrJobIdList = []
|
||||
if (this.jobIdList) {
|
||||
for (const n in this.jobIdList) {
|
||||
if (this.jobIdList[n].id !== this.temp.id) {
|
||||
arrJobIdList.push(this.jobIdList[n])
|
||||
}
|
||||
}
|
||||
this.JobIdList = arrJobIdList
|
||||
}
|
||||
|
||||
if (this.temp.childJobId) {
|
||||
const arrString = this.temp.childJobId.split(',')
|
||||
for (const i in arrString) {
|
||||
for (const n in this.jobIdList) {
|
||||
if (this.jobIdList[n].id === parseInt(arrString[i])) {
|
||||
arrchildSet.push(this.jobIdList[n])
|
||||
}
|
||||
}
|
||||
}
|
||||
this.temp.childJobId = arrchildSet
|
||||
}
|
||||
if (this.temp.partitionInfo) {
|
||||
const partition = this.temp.partitionInfo.split(',')
|
||||
this.partitionField = partition[0]
|
||||
this.timeOffset = partition[1]
|
||||
this.timeFormatType = partition[2]
|
||||
}
|
||||
this.dialogStatus = 'update'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
updateData() {
|
||||
this.temp.jobJson = typeof (this.jobJson) !== 'string' ? JSON.stringify(this.jobJson) : this.jobJson
|
||||
if (this.temp.glueType === 'BEAN' && !isJSON(this.temp.jobJson)) {
|
||||
this.$notify({
|
||||
title: 'Fail',
|
||||
message: 'json格式错误',
|
||||
type: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.temp.childJobId) {
|
||||
const auth = []
|
||||
for (const i in this.temp.childJobId) {
|
||||
auth.push(this.temp.childJobId[i].id)
|
||||
}
|
||||
this.temp.childJobId = auth.toString()
|
||||
}
|
||||
this.temp.executorHandler = this.temp.glueType === 'BEAN' ? 'executorJobHandler' : ''
|
||||
this.temp.glueSource = this.glueSource
|
||||
if (this.partitionField) this.temp.partitionInfo = this.partitionField + ',' + this.timeOffset + ',' + this.timeFormatType
|
||||
job.updateJob(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Update Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerDelete(row) {
|
||||
this.$confirm('确定删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
job.removeJob(row.id).then(response => {
|
||||
this.fetchData()
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// const index = this.list.indexOf(row)
|
||||
},
|
||||
handlerExecute(row) {
|
||||
this.$confirm('确定执行吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const param = {}
|
||||
param.jobId = row.id
|
||||
param.executorParam = row.executorParam
|
||||
job.triggerJob(param).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Execute Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
// 查看日志
|
||||
handlerViewLog(row) {
|
||||
this.$router.push({ path: '/data/log', query: { jobId: row.id }})
|
||||
},
|
||||
handlerStart(row) {
|
||||
job.startJob(row.id).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Start Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
},
|
||||
handlerStop(row) {
|
||||
job.stopJob(row.id).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Start Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
},
|
||||
changeSwitch(row) {
|
||||
row.triggerStatus === 1 ? this.handlerStart(row) : this.handlerStop(row)
|
||||
},
|
||||
nextTriggerTime(row) {
|
||||
job.nextTriggerTime(row.jobCron).then(response => {
|
||||
const { content } = response
|
||||
this.triggerNextTimes = content.join('<br>')
|
||||
})
|
||||
},
|
||||
loadById(row) {
|
||||
executor.loadById(row.jobGroup).then(response => {
|
||||
this.registerNode = []
|
||||
const { content } = response
|
||||
this.registerNode.push(content)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
}
|
||||
.el-dropdown + .el-dropdown {
|
||||
margin-left: 15px;
|
||||
}
|
||||
</style>
|
||||
319
src/views/dts/jobLog/index.vue
Normal file
319
src/views/dts/jobLog/index.vue
Normal file
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input v-model="listQuery.jobId" placeholder="全部" style="width: 200px" />
|
||||
<el-select v-model="listQuery.jobGroup" placeholder="执行器">
|
||||
<el-option v-for="item in executorList" :key="item.id" :label="item.title" :value="item.id" />
|
||||
</el-select>
|
||||
<el-select v-model="listQuery.logStatus" placeholder="类型" style="width: 200px">
|
||||
<el-option v-for="item in logStatusList" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
style="margin-left: 10px;"
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click="handlerDelete"
|
||||
>
|
||||
清除
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column align="center" label="任务ID" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.jobId }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="任务描述">
|
||||
<template slot-scope="scope">{{ scope.row.jobDesc }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="调度时间" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.triggerTime }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="执行结果" align="center">
|
||||
<template slot-scope="scope"> <span :style="`color:${scope.row.handleCode==500?'red':''}`">{{ statusList.find(t => t.value === scope.row.handleCode).label }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="300">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" @click="handleViewJobLog(row)">日志查看</el-button>
|
||||
<el-button type="primary" @click="killRunningJob(row)">
|
||||
终止任务
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="listQuery.current"
|
||||
:limit.sync="listQuery.size"
|
||||
@pagination="fetchData"
|
||||
/>
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="600px">
|
||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="center" label-width="100px">
|
||||
<el-row>
|
||||
<el-col :span="14" :offset="5">
|
||||
<el-form-item label="执行器">
|
||||
<el-input size="medium" value="全部" :disabled="true" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="14" :offset="5">
|
||||
<el-form-item label="任务">
|
||||
<el-input size="medium" value="全部" :disabled="true" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="14" :offset="5">
|
||||
<el-form-item label="执行器">
|
||||
<el-select v-model="temp.deleteType" placeholder="请选择执行器" style="width: 230px">
|
||||
<el-option v-for="item in deleteTypeList" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="deleteLog">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog title="日志查看" :visible.sync="dialogVisible" width="95%">
|
||||
<div class="log-container">
|
||||
<pre :loading="logLoading" v-text="logContent" />
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">
|
||||
关闭
|
||||
</el-button>
|
||||
<el-button type="primary" @click="loadLog">
|
||||
刷新日志
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as log from '@/api/dts/datax-job-log'
|
||||
import * as job from '@/api/dts/datax-job-info'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
|
||||
|
||||
export default {
|
||||
name: 'JobLog',
|
||||
components: { Pagination },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
jobGroup: 0,
|
||||
jobId: '',
|
||||
logStatus: -1,
|
||||
filterTime: ''
|
||||
},
|
||||
dialogPluginVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
executorList: '',
|
||||
textMap: {
|
||||
create: 'Clear'
|
||||
},
|
||||
rules: {},
|
||||
temp: {
|
||||
deleteType: 1,
|
||||
jobGroup: 0,
|
||||
jobId: 0
|
||||
},
|
||||
statusList: [
|
||||
{ value: 500, label: '失败' },
|
||||
{ value: 502, label: '失败(超时)' },
|
||||
{ value: 200, label: '成功' },
|
||||
{ value: 0, label: '无' }
|
||||
],
|
||||
deleteTypeList: [
|
||||
{ value: 1, label: '清理一个月之前日志数据' },
|
||||
{ value: 2, label: '清理三个月之前日志数据' },
|
||||
{ value: 3, label: '清理六个月之前日志数据' },
|
||||
{ value: 4, label: '清理一年之前日志数据' },
|
||||
{ value: 5, label: '清理一千条以前日志数据' },
|
||||
{ value: 6, label: '清理一万条以前日志数据' },
|
||||
{ value: 7, label: '清理三万条以前日志数据' },
|
||||
{ value: 8, label: '清理十万条以前日志数据' },
|
||||
{ value: 9, label: '清理所有日志数据' }
|
||||
],
|
||||
logStatusList: [
|
||||
{ value: -1, label: '全部' },
|
||||
{ value: 1, label: '成功' },
|
||||
{ value: 2, label: '失败' },
|
||||
{ value: 3, label: '进行中' }
|
||||
],
|
||||
// 日志查询参数
|
||||
jobLogQuery: {
|
||||
executorAddress: '',
|
||||
triggerTime: '',
|
||||
id: '',
|
||||
fromLineNum: 1
|
||||
},
|
||||
// 日志内容
|
||||
logContent: '',
|
||||
// 显示日志
|
||||
logShow: false,
|
||||
// 日志显示加载中效果
|
||||
logLoading: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
this.getExecutor()
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
const param = Object.assign({}, this.listQuery)
|
||||
const urlJobId = this.$route.query.jobId
|
||||
if (urlJobId > 0 && !param.jobId) {
|
||||
param.jobId = urlJobId
|
||||
} else if (!urlJobId && !param.jobId) {
|
||||
param.jobId = 0
|
||||
}
|
||||
log.getList(param).then(response => {
|
||||
const { content } = response
|
||||
this.total = content.recordsTotal
|
||||
this.list = content.data
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
getExecutor() {
|
||||
job.getExecutorList().then(response => {
|
||||
const { content } = response
|
||||
this.executorList = content
|
||||
const defaultParam = { id: 0, title: '全部' }
|
||||
this.executorList.unshift(defaultParam)
|
||||
this.listQuery.jobGroup = this.executorList[0].id
|
||||
})
|
||||
},
|
||||
handlerDelete() {
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
deleteLog() {
|
||||
log.clearLog(this.temp.jobGroup, this.temp.jobId, this.temp.deleteType).then(response => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
// const index = this.list.indexOf(row)
|
||||
},
|
||||
// 查看日志
|
||||
handleViewJobLog(row) {
|
||||
// const str = location.href.split('#')[0]
|
||||
// window.open(`${str}#/ router的name `)
|
||||
this.dialogVisible = true
|
||||
|
||||
this.jobLogQuery.executorAddress = row.executorAddress
|
||||
this.jobLogQuery.id = row.id
|
||||
this.jobLogQuery.triggerTime = Date.parse(row.triggerTime)
|
||||
if (this.logShow === false) {
|
||||
this.logShow = true
|
||||
}
|
||||
// window.open(`#/data/log?executorAddress=${this.jobLogQuery.executorAddress}&triggerTime=${this.jobLogQuery.triggerTime}&id=${this.jobLogQuery.id}&fromLineNum=${this.jobLogQuery.fromLineNum}`)
|
||||
this.loadLog()
|
||||
},
|
||||
// 获取日志
|
||||
loadLog() {
|
||||
this.logLoading = true
|
||||
log.viewJobLog(this.jobLogQuery.executorAddress, this.jobLogQuery.triggerTime, this.jobLogQuery.id,
|
||||
this.jobLogQuery.fromLineNum).then(response => {
|
||||
// 判断是否是 '\n',如果是表示显示完成,不重新加载
|
||||
if (response.content.logContent === '\n') {
|
||||
// this.jobLogQuery.fromLineNum = response.toLineNum - 20;
|
||||
// 重新加载
|
||||
// setTimeout(() => {
|
||||
// this.loadLog()
|
||||
// }, 2000);
|
||||
} else {
|
||||
this.logContent = response.content.logContent
|
||||
}
|
||||
this.logLoading = false
|
||||
})
|
||||
},
|
||||
killRunningJob(row) {
|
||||
log.killJob(row).then(response => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Kill Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.log-container {
|
||||
margin-bottom: 20px;
|
||||
background: #f5f5f5;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
overflow: scroll;
|
||||
pre {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
margin: 0 0 10.5px;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
color: #334851;
|
||||
background-color: #f5f5f5;
|
||||
// border: 1px solid #ccd1d3;
|
||||
border-radius: 1px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
62
src/views/dts/jobLog/log.vue
Normal file
62
src/views/dts/jobLog/log.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="background-color: #304156; padding:10px 0; text-align:right;"><el-button type="primary" style="margin-right:20px;" @click="loadLog">刷新日志</el-button></div>
|
||||
<div class="log-container">
|
||||
<pre :loading="logLoading" v-text="logContent" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as log from '@/api/dts/datax-job-log'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
logContent: '',
|
||||
logLoading: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadLog()
|
||||
},
|
||||
methods: {
|
||||
loadLog() {
|
||||
this.logLoading = true
|
||||
|
||||
log.viewJobLog(this.$route.query.executorAddress, this.$route.query.triggerTime, this.$route.query.id, this.$route.query.fromLineNum).then(response => {
|
||||
// 判断是否是 '\n',如果是表示显示完成,不重新加载
|
||||
if (response.content.logContent === '\n') {
|
||||
// this.jobLogQuery.fromLineNum = response.toLineNum - 20;
|
||||
// 重新加载
|
||||
// setTimeout(() => {
|
||||
// this.loadLog()
|
||||
// }, 2000);
|
||||
} else {
|
||||
this.logContent = response.content.logContent
|
||||
}
|
||||
this.logLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.log-container {
|
||||
background: #f5f5f5;
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
margin:20px;
|
||||
border:1px solid #ddd;
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
padding: 10px;
|
||||
margin: 0 0 10.5px;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
color: #334851;
|
||||
background-color: #f5f5f5;
|
||||
// border: 1px solid #ccd1d3;
|
||||
border-radius: 1px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
227
src/views/dts/jobProject/index.vue
Normal file
227
src/views/dts/jobProject/index.vue
Normal file
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input
|
||||
v-model="listQuery.searchVal"
|
||||
clearable
|
||||
placeholder="项目名称"
|
||||
style="width: 200px;"
|
||||
class="filter-item"
|
||||
@keyup.enter.native="handleFilter"
|
||||
/>
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column align="center" label="序号" width="95">
|
||||
<template slot-scope="scope">{{ scope.$index+1 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目名称" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.name }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目描述" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.description }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属用户" width="200" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.userName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" width="200" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.createTime }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="230" class-name="small-padding fixed-width">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" size="mini" @click="handleUpdate(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button v-if="row.status!=='deleted'" size="mini" type="danger" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="listQuery.pageNo"
|
||||
:limit.sync="listQuery.pageSize"
|
||||
@pagination="fetchData"
|
||||
/>
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="800px">
|
||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="100px">
|
||||
<el-form-item label="项目名称" prop="name">
|
||||
<el-input v-model="temp.name" placeholder="项目名称" style="width: 40%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目描述" prop="description">
|
||||
<el-input v-model="temp.description" placeholder="项目描述" style="width: 40%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog :visible.sync="dialogPluginVisible" title="Reading statistics">
|
||||
<el-table :data="pluginData" border fit highlight-current-row style="width: 100%">
|
||||
<el-table-column prop="key" label="Channel" />
|
||||
<el-table-column prop="pv" label="Pv" />
|
||||
</el-table>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as jobProjectApi from '@/api/dts/datax-job-project'
|
||||
import waves from '@/directive/waves'
|
||||
import Pagination from '@/components/Pagination'
|
||||
|
||||
export default {
|
||||
name: 'JobProject',
|
||||
components: { Pagination },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchVal: ''
|
||||
},
|
||||
pluginTypeOptions: ['reader', 'writer'],
|
||||
dialogPluginVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
textMap: {
|
||||
update: 'Edit',
|
||||
create: 'Create'
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
description: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
},
|
||||
temp: {
|
||||
id: undefined,
|
||||
name: '',
|
||||
description: ''
|
||||
},
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
jobProjectApi.list(this.listQuery).then(response => {
|
||||
const { records, total } = response.data
|
||||
this.total = parseInt(total || 0)
|
||||
this.list = records
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
resetTemp() {
|
||||
this.temp = {
|
||||
id: undefined,
|
||||
name: '',
|
||||
description: ''
|
||||
}
|
||||
},
|
||||
handleCreate() {
|
||||
this.resetTemp()
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
createData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
jobProjectApi.created(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.temp = Object.assign({}, row) // copy obj
|
||||
this.dialogStatus = 'update'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
updateData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
const tempData = Object.assign({}, this.temp)
|
||||
jobProjectApi.updated(tempData).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Update Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
console.log('删除')
|
||||
const idList = []
|
||||
idList.push(row.id)
|
||||
jobProjectApi.deleted({ idList: row.id }).then(response => {
|
||||
this.fetchData()
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
529
src/views/dts/jobTemplate/index.vue
Normal file
529
src/views/dts/jobTemplate/index.vue
Normal file
@@ -0,0 +1,529 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input v-model="listQuery.jobDesc" placeholder="任务描述" style="width: 200px;" class="filter-item" />
|
||||
<el-select v-model="projectIds" multiple placeholder="所属项目" class="filter-item">
|
||||
<el-option v-for="item in jobProjectList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
|
||||
添加
|
||||
</el-button>
|
||||
<!-- <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
|
||||
reviewer
|
||||
</el-checkbox> -->
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column align="center" label="任务ID" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.id }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务描述" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jobDesc }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属项目" align="center" width="120">
|
||||
<template slot-scope="scope">{{ scope.row.projectName }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Cron" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.jobCron }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="路由策略" align="center">
|
||||
<template slot-scope="scope"> {{ routeStrategies.find(t => t.value === scope.row.executorRouteStrategy).label }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="修改用户" align="center" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.userName }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="注册节点" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="500"
|
||||
@show="loadById(scope.row)"
|
||||
>
|
||||
<el-table :data="registerNode">
|
||||
<el-table-column width="150" property="title" label="执行器名称" />
|
||||
<el-table-column width="150" property="appName" label="appName" />
|
||||
<el-table-column width="150" property="registryList" label="机器地址" />
|
||||
</el-table>
|
||||
<el-button slot="reference" size="small">查看</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下次触发时间" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
width="300"
|
||||
@show="nextTriggerTime(scope.row)"
|
||||
>
|
||||
<h5 v-html="triggerNextTimes" />
|
||||
<el-button slot="reference" size="small">查看</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-dropdown trigger="click">
|
||||
<span class="el-dropdown-link">
|
||||
操作<i class="el-icon-arrow-down el-icon--right" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item divided @click.native="handlerUpdate(row)">编辑</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="handlerDelete(row)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.current" :limit.sync="listQuery.size" @pagination="fetchData" />
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="1000px" :before-close="handleClose">
|
||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="110px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="执行器" prop="jobGroup">
|
||||
<el-select v-model="temp.jobGroup" placeholder="请选择执行器">
|
||||
<el-option v-for="item in executorList" :key="item.id" :label="item.title" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务描述" prop="jobDesc">
|
||||
<el-input v-model="temp.jobDesc" size="medium" placeholder="请输入任务描述" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="路由策略" prop="executorRouteStrategy">
|
||||
<el-select v-model="temp.executorRouteStrategy" placeholder="请选择路由策略">
|
||||
<el-option v-for="item in routeStrategies" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-dialog
|
||||
title="提示"
|
||||
:visible.sync="showCronBox"
|
||||
width="60%"
|
||||
append-to-body
|
||||
>
|
||||
<cron v-model="temp.jobCron" />
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showCronBox = false;">关闭</el-button>
|
||||
<el-button type="primary" @click="showCronBox = false">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-form-item label="Cron" prop="jobCron">
|
||||
<el-input v-model="temp.jobCron" auto-complete="off" placeholder="请输入Cron表达式">
|
||||
<el-button v-if="!showCronBox" slot="append" icon="el-icon-turn-off" title="打开图形配置" @click="showCronBox = true" />
|
||||
<el-button v-else slot="append" icon="el-icon-open" title="关闭图形配置" @click="showCronBox = false" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="阻塞处理" prop="executorBlockStrategy">
|
||||
<el-select v-model="temp.executorBlockStrategy" placeholder="请选择阻塞处理策略">
|
||||
<el-option v-for="item in blockStrategies" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="报警邮件">
|
||||
<el-input v-model="temp.alarmEmail" placeholder="请输入报警邮件,多个用逗号分隔" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="任务类型" prop="glueType">
|
||||
<el-select v-model="temp.glueType" placeholder="任务脚本类型">
|
||||
<el-option v-for="item in glueTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="失败重试次数">
|
||||
<el-input-number v-model="temp.executorFailRetryCount" :min="0" :max="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属项目" prop="projectId">
|
||||
<el-select v-model="temp.projectId" placeholder="所属项目" class="filter-item">
|
||||
<el-option v-for="item in jobProjectList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="超时时间(分钟)">
|
||||
<el-input-number v-model="temp.executorTimeout" :min="0" :max="120" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="子任务">
|
||||
<el-select v-model="temp.childJobId" multiple placeholder="子任务" value-key="id">
|
||||
<el-option v-for="item in jobIdList" :key="item.id" :label="item.jobDesc" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" />
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="JVM启动参数">
|
||||
<el-input
|
||||
v-model="temp.jvmParam"
|
||||
placeholder="-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as executor from '@/api/dts/datax-executor'
|
||||
import Cron from '@/components/Cron'
|
||||
import * as jobTemp from '@/api/dts/datax-job-template'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
|
||||
import * as datasourceApi from '@/api/dts/datax-jdbcDatasource'
|
||||
import * as jobProjectApi from '@/api/dts/datax-job-project'
|
||||
import * as job from '@/api/dts/datax-job-info'
|
||||
|
||||
export default {
|
||||
name: 'JobTemplate',
|
||||
components: { Pagination, Cron },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validateIncParam = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
callback(new Error('Increment parameters is required'))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
const validatePartitionParam = (rule, value, callback) => {
|
||||
if (!this.partitionField) {
|
||||
callback(new Error('Partition parameters is required'))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
projectIds: '',
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
jobGroup: 0,
|
||||
triggerStatus: -1,
|
||||
jobDesc: '',
|
||||
executorHandler: '',
|
||||
userId: 0,
|
||||
projectIds: ''
|
||||
},
|
||||
showCronBox: false,
|
||||
dialogPluginVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
textMap: {
|
||||
update: 'Edit',
|
||||
create: 'Create'
|
||||
},
|
||||
rules: {
|
||||
jobGroup: [{ required: true, message: 'jobGroup is required', trigger: 'change' }],
|
||||
executorRouteStrategy: [{ required: true, message: 'executorRouteStrategy is required', trigger: 'change' }],
|
||||
executorBlockStrategy: [{ required: true, message: 'executorBlockStrategy is required', trigger: 'change' }],
|
||||
jobDesc: [{ required: true, message: 'jobDesc is required', trigger: 'blur' }],
|
||||
jobProject: [{ required: true, message: 'jobProject is required', trigger: 'blur' }],
|
||||
jobCron: [{ required: true, message: 'jobCron is required', trigger: 'blur' }],
|
||||
incStartId: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
replaceParam: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
primaryKey: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
incStartTime: [{ trigger: 'change', validator: validateIncParam }],
|
||||
replaceParamType: [{ trigger: 'change', validator: validateIncParam }],
|
||||
partitionField: [{ trigger: 'blur', validator: validatePartitionParam }],
|
||||
datasourceId: [{ trigger: 'change', validator: validateIncParam }],
|
||||
readerTable: [{ trigger: 'blur', validator: validateIncParam }],
|
||||
projectId: [{ required: true, message: 'projectId is required', trigger: 'change' }]
|
||||
},
|
||||
temp: {
|
||||
id: undefined,
|
||||
jobGroup: '',
|
||||
jobCron: '',
|
||||
jobDesc: '',
|
||||
executorRouteStrategy: 'RANDOM',
|
||||
executorBlockStrategy: 'DISCARD_LATER',
|
||||
childJobId: '',
|
||||
executorFailRetryCount: '',
|
||||
alarmEmail: '',
|
||||
executorTimeout: '',
|
||||
userId: 0,
|
||||
jobConfigId: '',
|
||||
executorHandler: 'executorJobHandler',
|
||||
glueType: 'BEAN',
|
||||
executorParam: '',
|
||||
jvmParam: '',
|
||||
projectId: '',
|
||||
datasourceId: 0,
|
||||
readerTable: ''
|
||||
},
|
||||
resetTemp() {
|
||||
this.temp = this.$options.data().temp
|
||||
},
|
||||
executorList: '',
|
||||
jobIdList: '',
|
||||
jobProjectList: '',
|
||||
dataSourceList: '',
|
||||
blockStrategies: [
|
||||
{ value: 'SERIAL_EXECUTION', label: '单机串行' },
|
||||
{ value: 'DISCARD_LATER', label: '丢弃后续调度' },
|
||||
{ value: 'COVER_EARLY', label: '覆盖之前调度' }
|
||||
],
|
||||
routeStrategies: [
|
||||
{ value: 'FIRST', label: '第一个' },
|
||||
{ value: 'LAST', label: '最后一个' },
|
||||
{ value: 'ROUND', label: '轮询' },
|
||||
{ value: 'RANDOM', label: '随机' },
|
||||
{ value: 'CONSISTENT_HASH', label: '一致性HASH' },
|
||||
{ value: 'LEAST_FREQUENTLY_USED', label: '最不经常使用' },
|
||||
{ value: 'LEAST_RECENTLY_USED', label: '最近最久未使用' },
|
||||
{ value: 'FAILOVER', label: '故障转移' },
|
||||
{ value: 'BUSYOVER', label: '忙碌转移' }
|
||||
// { value: 'SHARDING_BROADCAST', label: '分片广播' }
|
||||
],
|
||||
glueTypes: [
|
||||
{ value: 'BEAN', label: 'FlinkX任务' }
|
||||
],
|
||||
triggerNextTimes: '',
|
||||
registerNode: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
this.getExecutor()
|
||||
this.getJobIdList()
|
||||
this.getJobProject()
|
||||
this.getDataSourceList()
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClose(done) {
|
||||
this.$confirm('确认关闭?')
|
||||
.then(_ => {
|
||||
done()
|
||||
})
|
||||
.catch(_ => {})
|
||||
},
|
||||
getExecutor() {
|
||||
jobTemp.getExecutorList().then(response => {
|
||||
const { content } = response
|
||||
this.executorList = content
|
||||
})
|
||||
},
|
||||
getJobIdList() {
|
||||
job.getJobIdList().then(response => {
|
||||
const { content } = response
|
||||
this.jobIdList = content
|
||||
})
|
||||
},
|
||||
getJobProject() {
|
||||
jobProjectApi.getJobProjectList().then(response => {
|
||||
this.jobProjectList = response.data
|
||||
})
|
||||
},
|
||||
getDataSourceList() {
|
||||
datasourceApi.getDataSourceList().then(response => {
|
||||
this.dataSourceList = response
|
||||
})
|
||||
},
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
if (this.projectIds) {
|
||||
this.listQuery.projectIds = this.projectIds.toString()
|
||||
}
|
||||
jobTemp.getList(this.listQuery).then(response => {
|
||||
const { content } = response
|
||||
this.total = content.recordsTotal
|
||||
this.list = content.data
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleCreate() {
|
||||
//this.resetTemp()
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.temp.jobGroup = this.executorList[0]['id']
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
createData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.temp.childJobId) {
|
||||
const childJobs = []
|
||||
for (const i in this.temp.childJobId) {
|
||||
childJobs.push(this.temp.childJobId[i].id)
|
||||
}
|
||||
this.temp.childJobId = childJobs.toString()
|
||||
}
|
||||
if (this.partitionField) this.temp.partitionInfo = this.partitionField + ',' + this.timeOffset + ',' + this.timeFormatType
|
||||
jobTemp.createJob(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerUpdate(row) {
|
||||
//this.resetTemp()
|
||||
this.temp = Object.assign({}, row) // copy obj
|
||||
this.dialogStatus = 'update'
|
||||
this.dialogFormVisible = true
|
||||
const arrchildSet = []
|
||||
const arrJobIdList = []
|
||||
if (this.JobIdList) {
|
||||
for (const n in this.JobIdList) {
|
||||
if (this.JobIdList[n].id !== this.temp.id) {
|
||||
arrJobIdList.push(this.JobIdList[n])
|
||||
}
|
||||
}
|
||||
this.JobIdList = arrJobIdList
|
||||
}
|
||||
|
||||
if (this.temp.childJobId) {
|
||||
const arrString = this.temp.childJobId.split(',')
|
||||
for (const i in arrString) {
|
||||
for (const n in this.jobIdList) {
|
||||
if (this.jobIdList[n].id === parseInt(arrString[i])) {
|
||||
arrchildSet.push(this.jobIdList[n])
|
||||
}
|
||||
}
|
||||
}
|
||||
this.temp.childJobId = arrchildSet
|
||||
}
|
||||
|
||||
if (this.temp.partitionInfo) {
|
||||
const partition = this.temp.partitionInfo.split(',')
|
||||
this.partitionField = partition[0]
|
||||
this.timeOffset = partition[1]
|
||||
this.timeFormatType = partition[2]
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
updateData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.temp.childJobId) {
|
||||
const childJobs = []
|
||||
for (const i in this.temp.childJobId) {
|
||||
childJobs.push(this.temp.childJobId[i].id)
|
||||
}
|
||||
this.temp.childJobId = childJobs.toString()
|
||||
}
|
||||
if (this.partitionField) this.temp.partitionInfo = this.partitionField + ',' + this.timeOffset + ',' + this.timeFormatType
|
||||
jobTemp.updateJob(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Update Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerDelete(row) {
|
||||
this.$confirm('确定删除吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
jobTemp.removeJob(row.id).then(response => {
|
||||
this.fetchData()
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// const index = this.list.indexOf(row)
|
||||
},
|
||||
nextTriggerTime(row) {
|
||||
jobTemp.nextTriggerTime(row.jobCron).then(response => {
|
||||
const { content } = response
|
||||
this.triggerNextTimes = content.join('<br>')
|
||||
})
|
||||
},
|
||||
loadById(row) {
|
||||
executor.loadById(row.jobGroup).then(response => {
|
||||
this.registerNode = []
|
||||
const { content } = response
|
||||
this.registerNode.push(content)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
}
|
||||
.el-dropdown + .el-dropdown {
|
||||
margin-left: 15px;
|
||||
}
|
||||
</style>
|
||||
9
src/views/dts/json-build-batch/busReader.js
Normal file
9
src/views/dts/json-build-batch/busReader.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// 公共的组件,来做为中间传达的工具
|
||||
import Vue from 'vue'
|
||||
export default new Vue({
|
||||
data() {
|
||||
return {
|
||||
dataSourceId: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
9
src/views/dts/json-build-batch/busWriter.js
Normal file
9
src/views/dts/json-build-batch/busWriter.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// 公共的组件,来做为中间传达的工具
|
||||
import Vue from 'vue'
|
||||
export default new Vue({
|
||||
data() {
|
||||
return {
|
||||
dataSourceId: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
76
src/views/dts/json-build-batch/components/tableMapper.vue
Normal file
76
src/views/dts/json-build-batch/components/tableMapper.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="left" label-width="80px" :model="readerForm">
|
||||
<el-form-item label="源端表">
|
||||
<el-checkbox
|
||||
v-model="readerForm.lcheckAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="lHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.ltables" @change="lHandleCheckedChange">
|
||||
<el-checkbox v-for="c in fromTablesList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标表">
|
||||
<el-checkbox
|
||||
v-model="readerForm.rcheckAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 20px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.rtables" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in toTablesList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TableMapper',
|
||||
data() {
|
||||
return {
|
||||
mapperJson: {},
|
||||
fromTablesList: [],
|
||||
toTablesList: [],
|
||||
readerForm: {
|
||||
ltables: [],
|
||||
rtables: [],
|
||||
lcheckAll: false,
|
||||
rcheckAll: false,
|
||||
isIndeterminate: true
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
lHandleCheckAllChange(val) {
|
||||
this.readerForm.ltables = val ? this.fromTablesList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.rtables = val ? this.toTablesList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
lHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.fromTablesList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.fromTablesList.length
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.toTablesList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.toTablesList.length
|
||||
},
|
||||
getLTables() {
|
||||
return this.readerForm.ltables
|
||||
},
|
||||
getRTables() {
|
||||
return this.readerForm.rtables
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
250
src/views/dts/json-build-batch/index.vue
Normal file
250
src/views/dts/json-build-batch/index.vue
Normal file
@@ -0,0 +1,250 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="build-container">
|
||||
<el-steps :active="active" finish-status="success">
|
||||
<el-step title="步骤 1" description="构建reader">1</el-step>
|
||||
<el-step title="步骤 2" description="构建writer">2</el-step>
|
||||
<el-step title="步骤 3" description="表映射">3</el-step>
|
||||
<el-step title="步骤 4" description="批量创建">4</el-step>
|
||||
</el-steps>
|
||||
|
||||
<div v-show="active===1" class="step1">
|
||||
<Reader ref="reader" />
|
||||
</div>
|
||||
<div v-show="active===2" class="step2">
|
||||
<Writer ref="writer" />
|
||||
</div>
|
||||
<div v-show="active===3" class="step3">
|
||||
<Mapper ref="mapper" />
|
||||
</div>
|
||||
<div v-show="active===4" class="step4">
|
||||
<el-button type="primary" @click="handleJobTemplateSelectDrawer">{{ jobTemplate ? jobTemplate : "1.选择模板" }}</el-button>
|
||||
<el-button type="primary" @click="createJob">2.批量创建任务</el-button>
|
||||
(步骤:选择模板->批量创建任务)
|
||||
<el-drawer
|
||||
ref="jobTemplateSelectDrawer"
|
||||
title="选择模板"
|
||||
:visible.sync="jobTemplateSelectDrawer"
|
||||
direction="rtl"
|
||||
size="50%"
|
||||
>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
destroy-on-close="true"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column align="center" label="任务ID" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.id }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务描述" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jobDesc }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属项目" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jobProject }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Cron" align="center">
|
||||
<template slot-scope="scope"><span>{{ scope.row.jobCron }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="路由策略" align="center">
|
||||
<template slot-scope="scope"> {{ routeStrategies.find(t => t.value === scope.row.executorRouteStrategy).label }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.current" :limit.sync="listQuery.size" @pagination="fetchData" />
|
||||
</el-drawer>
|
||||
<div style="margin-bottom: 20px;" />
|
||||
</div>
|
||||
|
||||
<el-button :disabled="active===1" style="margin-top: 12px;" @click="last">上一步</el-button>
|
||||
<el-button v-show="active!==4" type="primary" style="margin-top: 12px;margin-bottom: 12px;" @click="next">下一步</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as jobTemplate from '@/api/dts/datax-job-template'
|
||||
import * as job from '@/api/dts/datax-job-info'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import Reader from './reader'
|
||||
import Writer from './writer'
|
||||
import clip from '@/utils/clipboard'
|
||||
import Mapper from './mapper'
|
||||
|
||||
export default {
|
||||
name: 'JsonBuild',
|
||||
components: { Reader, Writer, Pagination, Mapper },
|
||||
data() {
|
||||
return {
|
||||
configJson: '',
|
||||
active: 1,
|
||||
jobTemplate: '',
|
||||
jobTemplateSelectDrawer: false,
|
||||
list: null,
|
||||
currentRow: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
jobGroup: 0,
|
||||
triggerStatus: -1,
|
||||
jobDesc: '',
|
||||
executorHandler: '',
|
||||
userId: 0
|
||||
},
|
||||
blockStrategies: [
|
||||
{ value: 'SERIAL_EXECUTION', label: '单机串行' },
|
||||
{ value: 'DISCARD_LATER', label: '丢弃后续调度' },
|
||||
{ value: 'COVER_EARLY', label: '覆盖之前调度' }
|
||||
],
|
||||
routeStrategies: [
|
||||
{ value: 'FIRST', label: '第一个' },
|
||||
{ value: 'LAST', label: '最后一个' },
|
||||
{ value: 'ROUND', label: '轮询' },
|
||||
{ value: 'RANDOM', label: '随机' },
|
||||
{ value: 'CONSISTENT_HASH', label: '一致性HASH' },
|
||||
{ value: 'LEAST_FREQUENTLY_USED', label: '最不经常使用' },
|
||||
{ value: 'LEAST_RECENTLY_USED', label: '最近最久未使用' },
|
||||
{ value: 'FAILOVER', label: '故障转移' },
|
||||
{ value: 'BUSYOVER', label: '忙碌转移' }
|
||||
// { value: 'SHARDING_BROADCAST', label: '分片广播' }
|
||||
],
|
||||
triggerNextTimes: '',
|
||||
registerNode: [],
|
||||
jobJson: '',
|
||||
temp: {
|
||||
id: undefined,
|
||||
jobGroup: '',
|
||||
jobCron: '',
|
||||
jobDesc: '',
|
||||
executorRouteStrategy: '',
|
||||
executorBlockStrategy: '',
|
||||
childJobId: '',
|
||||
executorFailRetryCount: '',
|
||||
alarmEmail: '',
|
||||
executorTimeout: '',
|
||||
userId: 0,
|
||||
jobConfigId: '',
|
||||
executorHandler: 'executorJobHandler',
|
||||
glueType: 'BEAN',
|
||||
jobJson: '',
|
||||
executorParam: '',
|
||||
replaceParam: '',
|
||||
jvmParam: '',
|
||||
incStartTime: '',
|
||||
templateId: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
const fromTableList = this.$refs.reader.getData().tables
|
||||
const toTableList = this.$refs.writer.getData().tables
|
||||
// const fromTableName = this.$refs.reader.getData().tableName
|
||||
// 第一步 reader 判断是否已选字段
|
||||
if (this.active === 1) {
|
||||
// 实现第一步骤读取的表和字段直接带到第二步骤
|
||||
// this.$refs.writer.sendTableNameAndColumns(fromTableName, fromColumnList)
|
||||
// 取子组件的数据
|
||||
// console.info(this.$refs.reader.getData())
|
||||
this.active++
|
||||
} else {
|
||||
// 将第一步和第二步得到的字段名字发送到第三步
|
||||
if (this.active === 2) {
|
||||
this.$refs.mapper.sendTables(fromTableList, toTableList)
|
||||
}
|
||||
if (this.active !== 4) {
|
||||
this.active++
|
||||
}
|
||||
}
|
||||
},
|
||||
last() {
|
||||
if (this.active > 1) {
|
||||
this.active--
|
||||
}
|
||||
},
|
||||
// Create job
|
||||
createJob() {
|
||||
const readerData = this.$refs.reader.getData()
|
||||
const writeData = this.$refs.writer.getData()
|
||||
const readerTables = this.$refs.mapper.getLTables()
|
||||
const writerTables = this.$refs.mapper.getRTables()
|
||||
const rdbmsReader = {
|
||||
readerSplitPk: readerData.splitPk
|
||||
}
|
||||
const rdbmsWriter = {}
|
||||
const obj = {
|
||||
readerDatasourceId: readerData.datasourceId,
|
||||
readerTables: readerTables,
|
||||
writerDatasourceId: writeData.datasourceId,
|
||||
writerTables: writerTables,
|
||||
rdbmsReader: rdbmsReader,
|
||||
rdbmsWriter: rdbmsWriter,
|
||||
templateId: this.temp.templateId
|
||||
}
|
||||
// 调api
|
||||
job.batchAddJob(obj).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
// 切回第一步
|
||||
this.active = 1
|
||||
})
|
||||
},
|
||||
handleCopy(text, event) {
|
||||
clip(this.configJson, event)
|
||||
this.$message({
|
||||
message: 'copy success',
|
||||
type: 'success'
|
||||
})
|
||||
},
|
||||
handleJobTemplateSelectDrawer() {
|
||||
this.jobTemplateSelectDrawer = !this.jobTemplateSelectDrawer
|
||||
if (this.jobTemplateSelectDrawer) {
|
||||
this.fetchData()
|
||||
this.getExecutor()
|
||||
}
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$refs.reader.getData()
|
||||
},
|
||||
getExecutor() {
|
||||
jobTemplate.getExecutorList().then(response => {
|
||||
const { content } = response
|
||||
this.executorList = content
|
||||
})
|
||||
},
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
jobTemplate.getList(this.listQuery).then(response => {
|
||||
const { content } = response
|
||||
this.total = content.recordsTotal
|
||||
this.list = content.data
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.temp = Object.assign({}, val)
|
||||
this.temp.id = undefined
|
||||
this.temp.jobDesc = this.getReaderData().tableName
|
||||
this.$refs.jobTemplateSelectDrawer.closeDrawer()
|
||||
this.jobTemplate = val.id + '(' + val.jobDesc + ')'
|
||||
this.temp.templateId = val.id
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
24
src/views/dts/json-build-batch/mapper.vue
Normal file
24
src/views/dts/json-build-batch/mapper.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<TableMapper ref="mapper" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import TableMapper from './components/tableMapper'
|
||||
export default {
|
||||
name: 'Mapper',
|
||||
components: { TableMapper },
|
||||
methods: {
|
||||
sendTables(fromTablesList, toTablesList) {
|
||||
this.$refs.mapper.fromTablesList = fromTablesList
|
||||
this.$refs.mapper.toTablesList = toTablesList
|
||||
},
|
||||
getLTables() {
|
||||
return this.$refs.mapper.getLTables()
|
||||
},
|
||||
getRTables() {
|
||||
return this.$refs.mapper.getRTables()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
27
src/views/dts/json-build-batch/reader.vue
Normal file
27
src/views/dts/json-build-batch/reader.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<TableReader ref="tablereader" @selectDataSource="showDataSource" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TableReader from './reader/tableReader'
|
||||
export default {
|
||||
name: 'Reader',
|
||||
components: { TableReader },
|
||||
data() {
|
||||
return {
|
||||
dataSource: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
return this.$refs.tablereader.getData()
|
||||
},
|
||||
showDataSource(data) {
|
||||
this.dataSource = data
|
||||
this.getData()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
170
src/views/dts/json-build-batch/reader/tableReader.vue
Normal file
170
src/views/dts/json-build-batch/reader/tableReader.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="right" label-width="120px" :model="readerForm" :rules="rules">
|
||||
<el-form-item label="数据库源:" prop="datasourceId">
|
||||
<el-select v-model="readerForm.datasourceId" filterable style="width: 300px" @change="rDsChange">
|
||||
<el-option
|
||||
v-for="item in rDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="dataSource==='postgresql' || dataSource==='oracle' ||dataSource==='sqlserver' ||dataSource==='hana'" label="Schema:">
|
||||
<el-select v-model="readerForm.tableSchema" filterable style="width: 300px" @change="schemaChange">
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="切分字段:">
|
||||
<el-input v-model="readerForm.splitPk" placeholder="切分主键" style="width: 13%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库表名:">
|
||||
<el-checkbox
|
||||
v-model="readerForm.checkAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选
|
||||
</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.tables" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in rTbList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busReader'
|
||||
|
||||
export default {
|
||||
name: 'TableReader',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200,
|
||||
ascs: 'datasource_name'
|
||||
},
|
||||
rDsList: [],
|
||||
rTbList: [],
|
||||
schemaList: [],
|
||||
loading: false,
|
||||
active: 1,
|
||||
customFields: '',
|
||||
customType: '',
|
||||
customValue: '',
|
||||
dataSource: '',
|
||||
readerForm: {
|
||||
datasourceId: undefined,
|
||||
tables: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
splitPk: '',
|
||||
tableSchema: ''
|
||||
},
|
||||
rules: {
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'readerForm.datasourceId': function(oldVal, newVal) {
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
this.getSchema()
|
||||
} else {
|
||||
this.getTables('reader')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs() {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response.data
|
||||
this.rDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'reader') {
|
||||
let obj = {}
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
tableSchema: this.readerForm.tableSchema
|
||||
}
|
||||
} else {
|
||||
obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
if (response) {
|
||||
this.rTbList = response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getSchema() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
dsQueryApi.getTableSchema(obj).then(response => {
|
||||
this.schemaList = response
|
||||
})
|
||||
},
|
||||
// schema 切换
|
||||
schemaChange(e) {
|
||||
this.readerForm.tableSchema = e
|
||||
// 获取可用表
|
||||
this.getTables('reader')
|
||||
},
|
||||
// reader 数据源切换
|
||||
rDsChange(e) {
|
||||
// 清空
|
||||
this.readerForm.tableName = ''
|
||||
this.readerForm.datasourceId = e
|
||||
this.rDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables('reader')
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.tables = val ? this.rTbList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.rTbList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.rTbList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.readerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.readerForm
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
38
src/views/dts/json-build-batch/writer.vue
Normal file
38
src/views/dts/json-build-batch/writer.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<TableWriter ref="tablewriter" @selectDataSource="showDataSource" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TableWriter from './writer/tableWriter'
|
||||
|
||||
export default {
|
||||
name: 'Writer',
|
||||
components: { TableWriter },
|
||||
data() {
|
||||
return {
|
||||
dataSource: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
return this.$refs.tablewriter.getData()
|
||||
},
|
||||
getTableName() {
|
||||
return this.$refs.tablewriter.getTableName()
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
showDataSource(data) {
|
||||
this.dataSource = data
|
||||
this.getData()
|
||||
},
|
||||
sendTableNameAndColumns(fromTableName, fromColumnList) {
|
||||
this.$refs.hivewriter.fromTableName = fromTableName
|
||||
this.$refs.hivewriter.fromColumnList = fromColumnList
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
181
src/views/dts/json-build-batch/writer/tableWriter.vue
Normal file
181
src/views/dts/json-build-batch/writer/tableWriter.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form label-position="right" label-width="150px" :model="writerForm" :rules="rules">
|
||||
<el-form-item label="数据库源:" prop="datasourceId">
|
||||
<el-select
|
||||
v-model="writerForm.datasourceId"
|
||||
filterable
|
||||
style="width: 300px;"
|
||||
@change="wDsChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="dataSource==='postgresql' || dataSource==='oracle' ||dataSource==='sqlserver' ||dataSource==='hana'" label="Schema:">
|
||||
<el-select v-model="writerForm.tableSchema" filterable style="width: 300px" @change="schemaChange">
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div style="margin: 5px 0;" />
|
||||
<el-form-item label="数据库表名:">
|
||||
<el-checkbox v-model="writerForm.checkAll" :indeterminate="writerForm.isIndeterminate" @change="wHandleCheckAllChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="writerForm.tables" @change="wHandleCheckedChange">
|
||||
<el-checkbox v-for="c in wTbList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busWriter'
|
||||
export default {
|
||||
name: 'TableWriter',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200,
|
||||
ascs: 'datasource_name'
|
||||
},
|
||||
wDsList: [],
|
||||
schemaList: [],
|
||||
fromTableName: '',
|
||||
wTbList: [],
|
||||
dataSource: '',
|
||||
createTableName: '',
|
||||
writerForm: {
|
||||
datasourceId: undefined,
|
||||
tables: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
tableSchema: ''
|
||||
},
|
||||
readerForm: this.getReaderData(),
|
||||
rules: {
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'writerForm.datasourceId': function(oldVal, newVal) {
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
this.getSchema()
|
||||
} else {
|
||||
this.getTables('writer')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs() {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response.data
|
||||
this.wDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'writer') {
|
||||
let obj = {}
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableSchema: this.writerForm.tableSchema
|
||||
}
|
||||
} else {
|
||||
obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.wTbList = response.data
|
||||
})
|
||||
}
|
||||
},
|
||||
getSchema() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
dsQueryApi.getTableSchema(obj).then(response => {
|
||||
this.schemaList = response
|
||||
})
|
||||
},
|
||||
// schema 切换
|
||||
schemaChange(e) {
|
||||
this.writerForm.tableSchema = e
|
||||
// 获取可用表
|
||||
this.getTables('writer')
|
||||
},
|
||||
wDsChange(e) {
|
||||
// 清空
|
||||
this.writerForm.tableName = ''
|
||||
this.writerForm.datasourceId = e
|
||||
this.wDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables()
|
||||
},
|
||||
wHandleCheckAllChange(val) {
|
||||
this.writerForm.tables = val ? this.wTbList : []
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
wHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.writerForm.checkAll = checkedCount === this.wTbList.length
|
||||
this.writerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.wTbList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.writerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.writerForm
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
getTableName() {
|
||||
return this.fromTableName
|
||||
},
|
||||
createTable() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableName: this.createTableName
|
||||
}
|
||||
dsQueryApi.createTable(obj).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Create Table Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}).catch(() => console.log('promise catch err'))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
9
src/views/dts/json-build/busReader.js
Normal file
9
src/views/dts/json-build/busReader.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// 公共的组件,来做为中间传达的工具
|
||||
import Vue from 'vue'
|
||||
export default new Vue({
|
||||
data() {
|
||||
return {
|
||||
dataSourceId: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
9
src/views/dts/json-build/busWriter.js
Normal file
9
src/views/dts/json-build/busWriter.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// 公共的组件,来做为中间传达的工具
|
||||
import Vue from 'vue'
|
||||
export default new Vue({
|
||||
data() {
|
||||
return {
|
||||
dataSourceId: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
76
src/views/dts/json-build/components/fieldMapper.vue
Normal file
76
src/views/dts/json-build/components/fieldMapper.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="left" label-width="80px" :model="readerForm">
|
||||
<el-form-item label="源端字段">
|
||||
<el-checkbox
|
||||
v-model="readerForm.lcheckAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="lHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.lcolumns" @change="lHandleCheckedChange">
|
||||
<el-checkbox v-for="c in fromColumnsList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标字段">
|
||||
<el-checkbox
|
||||
v-model="readerForm.rcheckAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 20px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.rcolumns" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in toColumnsList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FieldMapper',
|
||||
data() {
|
||||
return {
|
||||
mapperJson: {},
|
||||
fromColumnsList: [],
|
||||
toColumnsList: [],
|
||||
readerForm: {
|
||||
lcolumns: [],
|
||||
rcolumns: [],
|
||||
lcheckAll: false,
|
||||
rcheckAll: false,
|
||||
isIndeterminate: true
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
lHandleCheckAllChange(val) {
|
||||
this.readerForm.lcolumns = val ? this.fromColumnsList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.rcolumns = val ? this.toColumnsList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
lHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.fromColumnsList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.fromColumnsList.length
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.toColumnsList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.toColumnsList.length
|
||||
},
|
||||
getLColumns() {
|
||||
return this.readerForm.lcolumns
|
||||
},
|
||||
getRColumns() {
|
||||
return this.readerForm.rcolumns
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
299
src/views/dts/json-build/index.vue
Normal file
299
src/views/dts/json-build/index.vue
Normal file
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="build-container">
|
||||
<el-steps :active="active" finish-status="success">
|
||||
<el-step title="步骤 1" description="构建reader">1</el-step>
|
||||
<el-step title="步骤 2" description="构建writer">2</el-step>
|
||||
<el-step title="步骤 3" description="字段映射">3</el-step>
|
||||
<el-step title="步骤 4" description="构建">4</el-step>
|
||||
</el-steps>
|
||||
|
||||
<div v-show="active===1" class="step1">
|
||||
<Reader ref="reader" />
|
||||
</div>
|
||||
<div v-show="active===2" class="step2">
|
||||
<Writer ref="writer" />
|
||||
</div>
|
||||
<div v-show="active===3" class="step3">
|
||||
<Mapper ref="mapper" />
|
||||
</div>
|
||||
<div v-show="active===4" class="step4">
|
||||
<el-button type="primary" @click="buildJson">1.构建</el-button>
|
||||
<el-button type="primary" @click="handleJobTemplateSelectDrawer">{{ jobTemplate ? jobTemplate : "2.选择模板" }}</el-button>
|
||||
<el-button type="info" @click="handleCopy(inputData,$event)">复制json</el-button>
|
||||
(步骤:构建->选择模板->下一步)
|
||||
<el-drawer
|
||||
ref="jobTemplateSelectDrawer"
|
||||
title="选择模板"
|
||||
:visible.sync="jobTemplateSelectDrawer"
|
||||
direction="rtl"
|
||||
size="50%"
|
||||
>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
destroy-on-close="true"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<el-table-column align="center" label="任务ID" width="80">
|
||||
<template slot-scope="scope">{{ scope.row.id }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务描述" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.jobDesc }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="所属项目" align="center" width="120">
|
||||
<template slot-scope="scope">{{ scope.row.projectName }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Cron" align="center">
|
||||
<template slot-scope="scope"><span>{{ scope.row.jobCron }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="路由策略" align="center">
|
||||
<template slot-scope="scope"> {{ routeStrategies.find(t => t.value === scope.row.executorRouteStrategy).label }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total>0" :total="total" :page.sync="listQuery.current" :limit.sync="listQuery.size" @pagination="fetchData" />
|
||||
</el-drawer>
|
||||
<div style="margin-bottom: 20px;" />
|
||||
<json-editor v-show="active===4" ref="jsonEditor" v-model="configJson" />
|
||||
</div>
|
||||
|
||||
<el-button :disabled="active===1" style="margin-top: 12px;" @click="last">上一步</el-button>
|
||||
<el-button type="primary" style="margin-top: 12px;margin-bottom: 12px;" @click="next">下一步</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dataxJsonApi from '@/api/dts/datax-json'
|
||||
import * as jobTemplate from '@/api/dts/datax-job-template'
|
||||
import * as job from '@/api/dts/datax-job-info'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import JsonEditor from '@/components/JsonEditor'
|
||||
import Reader from './reader'
|
||||
import Writer from './writer'
|
||||
import clip from '@/utils/clipboard'
|
||||
import Mapper from './mapper'
|
||||
|
||||
export default {
|
||||
name: 'JsonBuild',
|
||||
components: { Reader, Writer, Pagination, JsonEditor, Mapper },
|
||||
data() {
|
||||
return {
|
||||
configJson: '',
|
||||
active: 1,
|
||||
jobTemplate: '',
|
||||
jobTemplateSelectDrawer: false,
|
||||
list: null,
|
||||
currentRow: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
jobGroup: 0,
|
||||
triggerStatus: -1,
|
||||
jobDesc: '',
|
||||
executorHandler: '',
|
||||
userId: 0
|
||||
},
|
||||
blockStrategies: [
|
||||
{ value: 'SERIAL_EXECUTION', label: '单机串行' },
|
||||
{ value: 'DISCARD_LATER', label: '丢弃后续调度' },
|
||||
{ value: 'COVER_EARLY', label: '覆盖之前调度' }
|
||||
],
|
||||
routeStrategies: [
|
||||
{ value: 'FIRST', label: '第一个' },
|
||||
{ value: 'LAST', label: '最后一个' },
|
||||
{ value: 'ROUND', label: '轮询' },
|
||||
{ value: 'RANDOM', label: '随机' },
|
||||
{ value: 'CONSISTENT_HASH', label: '一致性HASH' },
|
||||
{ value: 'LEAST_FREQUENTLY_USED', label: '最不经常使用' },
|
||||
{ value: 'LEAST_RECENTLY_USED', label: '最近最久未使用' },
|
||||
{ value: 'FAILOVER', label: '故障转移' },
|
||||
{ value: 'BUSYOVER', label: '忙碌转移' }
|
||||
// { value: 'SHARDING_BROADCAST', label: '分片广播' }
|
||||
],
|
||||
triggerNextTimes: '',
|
||||
registerNode: [],
|
||||
jobJson: '',
|
||||
temp: {
|
||||
id: undefined,
|
||||
jobGroup: '',
|
||||
jobCron: '',
|
||||
jobDesc: '',
|
||||
executorRouteStrategy: '',
|
||||
executorBlockStrategy: '',
|
||||
childJobId: '',
|
||||
executorFailRetryCount: '',
|
||||
alarmEmail: '',
|
||||
executorTimeout: '',
|
||||
userId: 0,
|
||||
jobConfigId: '',
|
||||
executorHandler: 'executorJobHandler',
|
||||
glueType: 'BEAN',
|
||||
jobJson: '',
|
||||
executorParam: '',
|
||||
replaceParam: '',
|
||||
jvmParam: '',
|
||||
incStartTime: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
const fromColumnList = this.$refs.reader.getData().columns
|
||||
const toColumnsList = this.$refs.writer.getData().columns
|
||||
// const fromTableName = this.$refs.reader.getData().tableName
|
||||
// 第一步 reader 判断是否已选字段
|
||||
if (this.active === 1) {
|
||||
// 实现第一步骤读取的表和字段直接带到第二步骤
|
||||
// this.$refs.writer.sendTableNameAndColumns(fromTableName, fromColumnList)
|
||||
// 取子组件的数据
|
||||
// console.info(this.$refs.reader.getData())
|
||||
this.active++
|
||||
} else {
|
||||
// 将第一步和第二步得到的字段名字发送到第三步
|
||||
if (this.active === 2) {
|
||||
this.$refs.mapper.sendColumns(fromColumnList, toColumnsList)
|
||||
}
|
||||
if (this.active === 4) {
|
||||
this.temp.jobJson = this.configJson
|
||||
job.createJob(this.temp).then(() => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
// 切回第一步
|
||||
this.active = 1
|
||||
})
|
||||
} else {
|
||||
this.active++
|
||||
}
|
||||
}
|
||||
},
|
||||
last() {
|
||||
if (this.active > 1) {
|
||||
this.active--
|
||||
}
|
||||
},
|
||||
// 构建json
|
||||
buildJson() {
|
||||
const readerData = this.$refs.reader.getData()
|
||||
const writeData = this.$refs.writer.getData()
|
||||
const readerColumns = this.$refs.mapper.getLColumns()
|
||||
const writerColumns = this.$refs.mapper.getRColumns()
|
||||
const hiveReader = {
|
||||
readerPath: readerData.path,
|
||||
readerDefaultFS: readerData.defaultFS,
|
||||
readerFileType: readerData.fileType,
|
||||
readerFieldDelimiter: readerData.fieldDelimiter,
|
||||
readerSkipHeader: readerData.skipHeader
|
||||
}
|
||||
const hiveWriter = {
|
||||
writerDefaultFS: writeData.defaultFS,
|
||||
writerFileType: writeData.fileType,
|
||||
writerPath: writeData.path,
|
||||
writerFileName: writeData.fileName,
|
||||
writeMode: writeData.writeMode,
|
||||
writeFieldDelimiter: writeData.fieldDelimiter
|
||||
}
|
||||
const hbaseReader = {
|
||||
readerMode: readerData.mode,
|
||||
readerMaxVersion: readerData.maxVersion,
|
||||
readerRange: readerData.range
|
||||
}
|
||||
const hbaseWriter = {
|
||||
writerMode: writeData.mode,
|
||||
writerRowkeyColumn: writeData.rowkeyColumn,
|
||||
writerVersionColumn: writeData.versionColumn,
|
||||
writeNullMode: writeData.nullMode
|
||||
}
|
||||
const mongoDBReader = {}
|
||||
const mongoDBWriter = {
|
||||
upsertInfo: writeData.upsertInfo
|
||||
}
|
||||
const rdbmsReader = {
|
||||
readerSplitPk: readerData.splitPk,
|
||||
whereParams: readerData.where,
|
||||
querySql: readerData.querySql
|
||||
}
|
||||
const rdbmsWriter = {
|
||||
preSql: writeData.preSql,
|
||||
postSql: writeData.postSql
|
||||
}
|
||||
const obj = {
|
||||
readerDatasourceId: readerData.datasourceId,
|
||||
readerTables: [readerData.tableName],
|
||||
readerColumns: readerColumns,
|
||||
writerDatasourceId: writeData.datasourceId,
|
||||
writerTables: [writeData.tableName],
|
||||
writerColumns: writerColumns,
|
||||
hiveReader: hiveReader,
|
||||
hiveWriter: hiveWriter,
|
||||
rdbmsReader: rdbmsReader,
|
||||
rdbmsWriter: rdbmsWriter,
|
||||
hbaseReader: hbaseReader,
|
||||
hbaseWriter: hbaseWriter,
|
||||
mongoDBReader: mongoDBReader,
|
||||
mongoDBWriter: mongoDBWriter
|
||||
}
|
||||
// 调api
|
||||
dataxJsonApi.buildJobJson(obj).then(response => {
|
||||
this.configJson = JSON.parse(response.data)
|
||||
})
|
||||
},
|
||||
handleCopy(text, event) {
|
||||
clip(this.configJson, event)
|
||||
this.$message({
|
||||
message: 'copy success',
|
||||
type: 'success'
|
||||
})
|
||||
},
|
||||
handleJobTemplateSelectDrawer() {
|
||||
this.jobTemplateSelectDrawer = !this.jobTemplateSelectDrawer
|
||||
if (this.jobTemplateSelectDrawer) {
|
||||
this.fetchData()
|
||||
this.getExecutor()
|
||||
}
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$refs.reader.getData()
|
||||
},
|
||||
getExecutor() {
|
||||
jobTemplate.getExecutorList().then(response => {
|
||||
const { content } = response
|
||||
this.executorList = content
|
||||
})
|
||||
},
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
jobTemplate.getList(this.listQuery).then(response => {
|
||||
const { content } = response
|
||||
this.total = content.recordsTotal
|
||||
this.list = content.data
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.temp = Object.assign({}, val)
|
||||
this.temp.id = undefined
|
||||
this.temp.jobDesc = this.getReaderData().tableName
|
||||
this.$refs.jobTemplateSelectDrawer.closeDrawer()
|
||||
this.jobTemplate = val.id + '(' + val.jobDesc + ')'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
24
src/views/dts/json-build/mapper.vue
Normal file
24
src/views/dts/json-build/mapper.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<FieldMapper ref="mapper" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import FieldMapper from './components/fieldMapper'
|
||||
export default {
|
||||
name: 'Mapper',
|
||||
components: { FieldMapper },
|
||||
methods: {
|
||||
sendColumns(fromColumnsList, toColumnsList) {
|
||||
this.$refs.mapper.fromColumnsList = fromColumnsList
|
||||
this.$refs.mapper.toColumnsList = toColumnsList
|
||||
},
|
||||
getLColumns() {
|
||||
return this.$refs.mapper.getLColumns()
|
||||
},
|
||||
getRColumns() {
|
||||
return this.$refs.mapper.getRColumns()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
41
src/views/dts/json-build/reader.vue
Normal file
41
src/views/dts/json-build/reader.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<RDBMSReader v-show="dataSource!=='hive' && dataSource!=='hbase' && dataSource!=='mongodb'" ref="rdbmsreader" @selectDataSource="showDataSource" />
|
||||
<HiveReader v-show="dataSource==='hive'" ref="hivereader" @selectDataSource="showDataSource" />
|
||||
<HBaseReader v-show="dataSource==='hbase'" ref="hbasereader" @selectDataSource="showDataSource" />
|
||||
<MongoDBReader v-show="dataSource==='mongodb'" ref="mongodbreader" @selectDataSource="showDataSource" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RDBMSReader from './reader/RDBMSReader'
|
||||
import HiveReader from './reader/HiveReader'
|
||||
import HBaseReader from './reader/HBaseReader'
|
||||
import MongoDBReader from './reader/MongoDBReader'
|
||||
export default {
|
||||
name: 'Reader',
|
||||
components: { RDBMSReader, HiveReader, HBaseReader, MongoDBReader },
|
||||
data() {
|
||||
return {
|
||||
dataSource: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
if (this.dataSource === 'hive') {
|
||||
return this.$refs.hivereader.getData()
|
||||
} else if (this.dataSource === 'hbase') {
|
||||
return this.$refs.hbasereader.getData()
|
||||
} else if (this.dataSource === 'mongodb') {
|
||||
return this.$refs.mongodbreader.getData()
|
||||
} else {
|
||||
return this.$refs.rdbmsreader.getData()
|
||||
}
|
||||
},
|
||||
showDataSource(data) {
|
||||
this.dataSource = data
|
||||
this.getData()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
203
src/views/dts/json-build/reader/HBaseReader.vue
Normal file
203
src/views/dts/json-build/reader/HBaseReader.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="left" label-width="105px" :model="readerForm" :rules="rules">
|
||||
<el-form-item label="数据源" prop="datasourceId">
|
||||
<el-select v-model="readerForm.datasourceId" filterable @change="rDsChange">
|
||||
<el-option
|
||||
v-for="item in rDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表" prop="tableName">
|
||||
<el-select v-model="readerForm.tableName" filterable @change="rTbChange">
|
||||
<el-option v-for="item in rTbList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="mode" prop="mode">
|
||||
<el-select v-model="readerForm.mode" placeholder="读取hbase的模式">
|
||||
<el-option v-for="item in modeTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="maxVersion">
|
||||
<el-input v-model="readerForm.maxVersion" placeholder="多版本模式下读取的版本数,取值只能为-1或者大于1的数字" style="width: 50%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="range">
|
||||
<el-input v-model="readerForm.range.startRowkey" placeholder="startRowkey指定开始rowkey" style="width: 50%" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input v-model="readerForm.range.endRowkey" placeholder="endRowkey指定结束rowkey" style="width: 50%" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="readerForm.range.isBinaryRowkey" placeholder="转换方式">
|
||||
<el-option v-for="item in binaryRowkeyTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段">
|
||||
<el-checkbox
|
||||
v-model="readerForm.checkAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.columns" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in rColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busReader'
|
||||
|
||||
export default {
|
||||
name: 'HBaseReader',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200
|
||||
},
|
||||
rDsList: [],
|
||||
rTbList: [],
|
||||
rColumnList: [],
|
||||
loading: false,
|
||||
active: 1,
|
||||
customFields: '',
|
||||
customType: '',
|
||||
customValue: '',
|
||||
dataSource: '',
|
||||
readerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
mode: '',
|
||||
maxVersion: '',
|
||||
range: {
|
||||
startRowkey: '',
|
||||
endRowkey: '',
|
||||
isBinaryRowkey: ''
|
||||
}
|
||||
},
|
||||
modeTypes: [
|
||||
{ value: 'normal', label: 'normal' },
|
||||
{ value: 'multiVersionFixedColumn', label: 'multiVersionFixedColumn' }
|
||||
],
|
||||
binaryRowkeyTypes: [
|
||||
{ value: 'true', label: '调用Bytes.toBytesBinary(rowkey)' },
|
||||
{ value: 'false', label: '调用Bytes.toBytes(rowkey)' }
|
||||
],
|
||||
rules: {
|
||||
mode: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'readerForm.datasourceId': function(oldVal, newVal) {
|
||||
this.getTables('hbaseReader')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs() {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response
|
||||
this.rDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'hbaseReader') {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.rTbList = response
|
||||
})
|
||||
}
|
||||
},
|
||||
// reader 数据源切换
|
||||
rDsChange(e) {
|
||||
// 清空
|
||||
this.readerForm.tableName = ''
|
||||
this.readerForm.datasourceId = e
|
||||
this.rDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables('reader')
|
||||
},
|
||||
getTableColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
tableName: this.readerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
getColumnsByQuerySql() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
querySql: this.readerForm.querySql
|
||||
}
|
||||
dsQueryApi.getColumnsByQuerySql(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns(type) {
|
||||
if (type === 'reader') {
|
||||
this.getTableColumns()
|
||||
}
|
||||
},
|
||||
// 表切换
|
||||
rTbChange(t) {
|
||||
this.readerForm.tableName = t
|
||||
this.rColumnList = []
|
||||
this.readerForm.columns = []
|
||||
this.getColumns('reader')
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.columns = val ? this.rColumnList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.rColumnList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.rColumnList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.readerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.readerForm
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
206
src/views/dts/json-build/reader/HiveReader.vue
Normal file
206
src/views/dts/json-build/reader/HiveReader.vue
Normal file
@@ -0,0 +1,206 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="left" label-width="105px" :model="readerForm" :rules="rules">
|
||||
<el-form-item label="数据源" prop="datasourceId">
|
||||
<el-select v-model="readerForm.datasourceId" filterable @change="rDsChange">
|
||||
<el-option
|
||||
v-for="item in rDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="表" prop="tableName">
|
||||
<el-select v-model="readerForm.tableName" filterable @change="rTbChange">
|
||||
<el-option v-for="item in rTbList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="path" prop="path">
|
||||
<el-input v-model="readerForm.path" :autosize="{ minRows: 2, maxRows: 20}" type="textarea" placeholder="要读取的文件路径,如果要读取多个文件,可以使用正则表达式'*'" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="defaultFS" prop="defaultFS">
|
||||
<el-input v-model="readerForm.defaultFS" placeholder="Hadoop hdfs文件系统namenode节点地址" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="fileType" prop="fileType">
|
||||
<el-select v-model="readerForm.fileType" placeholder="文件的类型">
|
||||
<el-option v-for="item in fileTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="fieldDelimiter" prop="fieldDelimiter">
|
||||
<el-input v-model="readerForm.fieldDelimiter" placeholder="读取的字段分隔符" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="skipHeader">
|
||||
<el-select v-model="readerForm.skipHeader" placeholder="是否跳过表头">
|
||||
<el-option v-for="item in skipHeaderTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段">
|
||||
<el-checkbox
|
||||
v-model="readerForm.checkAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.columns" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in rColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busReader'
|
||||
|
||||
export default {
|
||||
name: 'HiveReader',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200
|
||||
},
|
||||
rDsList: [],
|
||||
rTbList: [],
|
||||
rColumnList: [],
|
||||
loading: false,
|
||||
active: 1,
|
||||
customFields: '',
|
||||
customType: '',
|
||||
customValue: '',
|
||||
dataSource: '',
|
||||
readerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
path: '',
|
||||
defaultFS: '',
|
||||
fileType: '',
|
||||
fieldDelimiter: '',
|
||||
skipHeader: ''
|
||||
},
|
||||
rules: {
|
||||
path: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
defaultFS: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
fileType: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
},
|
||||
fileTypes: [
|
||||
{ value: 'text', label: 'text' },
|
||||
{ value: 'orc', label: 'orc' },
|
||||
{ value: 'rc', label: 'rc' },
|
||||
{ value: 'seq', label: 'seq' },
|
||||
{ value: 'csv', label: 'csv' }
|
||||
],
|
||||
skipHeaderTypes: [
|
||||
{ value: 'true', label: '读取跳过表头' },
|
||||
{ value: 'false', label: '读取包含表头' }
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'readerForm.datasourceId': function(oldVal, newVal) {
|
||||
this.getTables('hiveReader')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs(type) {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response
|
||||
this.rDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'hiveReader') {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.rTbList = response
|
||||
})
|
||||
}
|
||||
},
|
||||
// reader 数据源切换
|
||||
rDsChange(e) {
|
||||
// 清空
|
||||
this.readerForm.tableName = ''
|
||||
this.readerForm.datasourceId = e
|
||||
this.rDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables('reader')
|
||||
},
|
||||
getTableColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
tableName: this.readerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
getColumnsByQuerySql() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
querySql: this.readerForm.querySql
|
||||
}
|
||||
dsQueryApi.getColumnsByQuerySql(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns(type) {
|
||||
if (type === 'reader') {
|
||||
this.getTableColumns()
|
||||
}
|
||||
},
|
||||
// 表切换
|
||||
rTbChange(t) {
|
||||
this.readerForm.tableName = t
|
||||
this.rColumnList = []
|
||||
this.readerForm.columns = []
|
||||
this.getColumns('reader')
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.columns = val ? this.rColumnList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.rColumnList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.rColumnList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.readerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.readerForm
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
169
src/views/dts/json-build/reader/MongoDBReader.vue
Normal file
169
src/views/dts/json-build/reader/MongoDBReader.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="left" label-width="105px" :model="readerForm" :rules="rules">
|
||||
<el-form-item label="数据源" prop="datasourceId">
|
||||
<el-select v-model="readerForm.datasourceId" filterable @change="rDsChange">
|
||||
<el-option
|
||||
v-for="item in rDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="文档" prop="tableName">
|
||||
<el-select v-model="readerForm.tableName" filterable @change="rTbChange">
|
||||
<el-option v-for="item in rTbList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段">
|
||||
<el-checkbox
|
||||
v-model="readerForm.checkAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.columns" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in rColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busReader'
|
||||
|
||||
export default {
|
||||
name: 'MongoDBReader',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200
|
||||
},
|
||||
rDsList: [],
|
||||
rTbList: [],
|
||||
rColumnList: [],
|
||||
loading: false,
|
||||
active: 1,
|
||||
customFields: '',
|
||||
customType: '',
|
||||
customValue: '',
|
||||
dataSource: '',
|
||||
readerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true
|
||||
},
|
||||
rules: {
|
||||
mode: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'readerForm.datasourceId': function(oldVal, newVal) {
|
||||
this.getTables('mongodbReader')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs() {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response
|
||||
this.rDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'mongodbReader') {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.rTbList = response
|
||||
})
|
||||
}
|
||||
},
|
||||
// reader 数据源切换
|
||||
rDsChange(e) {
|
||||
// 清空
|
||||
this.readerForm.tableName = ''
|
||||
this.readerForm.datasourceId = e
|
||||
this.rDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables('reader')
|
||||
},
|
||||
getTableColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
tableName: this.readerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
getColumnsByQuerySql() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
querySql: this.readerForm.querySql
|
||||
}
|
||||
dsQueryApi.getColumnsByQuerySql(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns(type) {
|
||||
if (type === 'reader') {
|
||||
this.getTableColumns()
|
||||
}
|
||||
},
|
||||
// 表切换
|
||||
rTbChange(t) {
|
||||
this.readerForm.tableName = t
|
||||
this.rColumnList = []
|
||||
this.readerForm.columns = []
|
||||
this.getColumns('reader')
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.columns = val ? this.rColumnList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.rColumnList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.rColumnList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.readerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.readerForm
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
226
src/views/dts/json-build/reader/RDBMSReader.vue
Normal file
226
src/views/dts/json-build/reader/RDBMSReader.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form label-position="right" label-width="120px" :model="readerForm" :rules="rules">
|
||||
<el-form-item label="数据库源:" prop="datasourceId">
|
||||
<el-select v-model="readerForm.datasourceId" filterable style="width: 300px" @change="rDsChange">
|
||||
<el-option
|
||||
v-for="item in rDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="dataSource==='postgresql' || dataSource==='oracle' || dataSource==='sqlserver' || dataSource==='hana'" label="Schema:" prop="tableSchema">
|
||||
<el-select v-model="readerForm.tableSchema" allow-create default-first-option filterable style="width: 300px" @change="schemaChange">
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库表名:" prop="tableName">
|
||||
<el-select v-model="readerForm.tableName" allow-create default-first-option filterable style="width: 300px" @change="rTbChange">
|
||||
<el-option v-for="item in rTbList" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="SQL语句:">
|
||||
<el-input v-model="readerForm.querySql" :autosize="{ minRows: 3, maxRows: 20}" type="textarea" placeholder="sql查询,一般用于多表关联查询时才用" style="width: 42%" />
|
||||
<el-button type="primary" @click.prevent="getColumns('reader')">解析字段</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="切分字段:">
|
||||
<el-input v-model="readerForm.splitPk" placeholder="切分主键" style="width: 13%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="表所有字段:">
|
||||
<el-checkbox
|
||||
v-model="readerForm.checkAll"
|
||||
:indeterminate="readerForm.isIndeterminate"
|
||||
@change="rHandleCheckAllChange"
|
||||
>全选
|
||||
</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="readerForm.columns" @change="rHandleCheckedChange">
|
||||
<el-checkbox v-for="c in rColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="where条件:" prop="where">
|
||||
<el-input v-model="readerForm.where" placeholder="where条件,不需要再加where" type="textarea" style="width: 42%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busReader'
|
||||
|
||||
export default {
|
||||
name: 'RDBMSReader',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200,
|
||||
ascs: 'datasource_name'
|
||||
},
|
||||
rDsList: [],
|
||||
rTbList: [],
|
||||
schemaList: [],
|
||||
rColumnList: [],
|
||||
loading: false,
|
||||
active: 1,
|
||||
customFields: '',
|
||||
customType: '',
|
||||
customValue: '',
|
||||
dataSource: '',
|
||||
readerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
where: '',
|
||||
querySql: '',
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
splitPk: '',
|
||||
tableSchema: ''
|
||||
},
|
||||
rules: {
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
tableSchema: [{ required: true, message: 'this is required', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'readerForm.datasourceId': function(oldVal, newVal) {
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
this.getSchema()
|
||||
} else {
|
||||
this.getTables('rdbmsReader')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs(type) {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response.data
|
||||
this.rDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'rdbmsReader') {
|
||||
let obj = {}
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
tableSchema: this.readerForm.tableSchema
|
||||
}
|
||||
} else {
|
||||
obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
if (response) {
|
||||
this.rTbList = response.data
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getSchema() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId
|
||||
}
|
||||
dsQueryApi.getTableSchema(obj).then(response => {
|
||||
this.schemaList = response
|
||||
})
|
||||
},
|
||||
// schema 切换
|
||||
schemaChange(e) {
|
||||
this.readerForm.tableSchema = e
|
||||
// 获取可用表
|
||||
this.getTables('rdbmsReader')
|
||||
},
|
||||
// reader 数据源切换
|
||||
rDsChange(e) {
|
||||
// 清空
|
||||
this.readerForm.tableName = ''
|
||||
this.readerForm.datasourceId = e
|
||||
this.rDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
},
|
||||
getTableColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
tableName: this.readerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.rColumnList = response.data
|
||||
this.readerForm.columns = response.data
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
getColumnsByQuerySql() {
|
||||
const obj = {
|
||||
datasourceId: this.readerForm.datasourceId,
|
||||
querySql: this.readerForm.querySql
|
||||
}
|
||||
dsQueryApi.getColumnsByQuerySql(obj).then(response => {
|
||||
this.rColumnList = response
|
||||
this.readerForm.columns = response
|
||||
this.readerForm.checkAll = true
|
||||
this.readerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns(type) {
|
||||
if (type === 'reader') {
|
||||
if (this.readerForm.querySql !== '') {
|
||||
this.getColumnsByQuerySql()
|
||||
} else {
|
||||
this.getTableColumns()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 表切换
|
||||
rTbChange(t) {
|
||||
this.readerForm.tableName = t
|
||||
this.rColumnList = []
|
||||
this.readerForm.columns = []
|
||||
this.getColumns('reader')
|
||||
},
|
||||
rHandleCheckAllChange(val) {
|
||||
this.readerForm.columns = val ? this.rColumnList : []
|
||||
this.readerForm.isIndeterminate = false
|
||||
},
|
||||
rHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.readerForm.checkAll = checkedCount === this.rColumnList.length
|
||||
this.readerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.rColumnList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.readerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.readerForm
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
60
src/views/dts/json-build/writer.vue
Normal file
60
src/views/dts/json-build/writer.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<RDBMSWriter v-show="dataSource!=='hive' && dataSource!=='hbase' && dataSource!=='mongodb'" ref="rdbmswriter" @selectDataSource="showDataSource" />
|
||||
<HiveWriter v-show="dataSource==='hive'" ref="hivewriter" @selectDataSource="showDataSource" />
|
||||
<HBaseWriter v-show="dataSource==='hbase'" ref="hbasewriter" @selectDataSource="showDataSource" />
|
||||
<MongoDBWriter v-show="dataSource==='mongodb'" ref="mongodbwriter" @selectDataSource="showDataSource" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RDBMSWriter from './writer/RDBMSWriter'
|
||||
import HiveWriter from './writer/HiveWriter'
|
||||
import HBaseWriter from './writer/HBaseWriter'
|
||||
import MongoDBWriter from './writer/MongoDBWriter'
|
||||
export default {
|
||||
name: 'Writer',
|
||||
components: { RDBMSWriter, HiveWriter, HBaseWriter, MongoDBWriter },
|
||||
data() {
|
||||
return {
|
||||
dataSource: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
if (this.dataSource === 'hive') {
|
||||
return this.$refs.hivewriter.getData()
|
||||
} else if (this.dataSource === 'hbase') {
|
||||
return this.$refs.hbasewriter.getData()
|
||||
} else if (this.dataSource === 'mongodb') {
|
||||
return this.$refs.mongodbwriter.getData()
|
||||
} else {
|
||||
return this.$refs.rdbmswriter.getData()
|
||||
}
|
||||
},
|
||||
getTableName() {
|
||||
if (this.dataSource === 'hive') {
|
||||
return this.$refs.hivewriter.getTableName()
|
||||
} else if (this.dataSource === 'hbase') {
|
||||
return this.$refs.hbasewriter.getData()
|
||||
} else if (this.dataSource === 'mongodb') {
|
||||
return this.$refs.mongodbwriter.getData()
|
||||
} else {
|
||||
return this.$refs.rdbmswriter.getTableName()
|
||||
}
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
showDataSource(data) {
|
||||
this.dataSource = data
|
||||
this.getData()
|
||||
},
|
||||
sendTableNameAndColumns(fromTableName, fromColumnList) {
|
||||
this.$refs.hivewriter.fromTableName = fromTableName
|
||||
this.$refs.hivewriter.fromColumnList = fromColumnList
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
223
src/views/dts/json-build/writer/HBaseWriter.vue
Normal file
223
src/views/dts/json-build/writer/HBaseWriter.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form label-position="left" label-width="115px" :model="writerForm" :rules="rules">
|
||||
<el-form-item label="数据源" prop="datasourceId">
|
||||
<el-select
|
||||
v-model="writerForm.datasourceId"
|
||||
filterable
|
||||
@change="wDsChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="表" prop="fromTableName">
|
||||
<el-select
|
||||
v-model="fromTableName"
|
||||
:disabled="writerForm.ifCreateTable"
|
||||
filterable
|
||||
@change="wTbChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wTbList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="rowkeyColumn" prop="rowkeyColumn">
|
||||
<el-input v-model="writerForm.rowkeyColumn" :autosize="{ minRows: 5, maxRows: 20}" type="textarea" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="versionColumn">
|
||||
<el-input v-model="writerForm.versionColumn.index" placeholder="index指定对应reader端column的索引" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input v-model="writerForm.versionColumn.value" placeholder="value指定时间的值,long值" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="nullMode">
|
||||
<el-select v-model="writerForm.nullMode" placeholder="null值转换方式">
|
||||
<el-option v-for="item in nullModeTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段">
|
||||
<el-checkbox v-model="writerForm.checkAll" :indeterminate="writerForm.isIndeterminate" @change="wHandleCheckAllChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="writerForm.columns" @change="wHandleCheckedChange">
|
||||
<el-checkbox v-for="c in fromColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busWriter'
|
||||
export default {
|
||||
name: 'HBaseWriter',
|
||||
data() {
|
||||
const checkJson = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
callback(new Error('不能为空'))
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
var obj = JSON.parse(value)
|
||||
if (typeof obj !== 'object' || !obj) {
|
||||
callback(new Error('JSON格式错误'))
|
||||
}
|
||||
if (!(obj instanceof Array)) {
|
||||
callback(new Error('JSON必须为数组'))
|
||||
}
|
||||
} catch (e) {
|
||||
callback(new Error('JSON格式错误'))
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200
|
||||
},
|
||||
wDsList: [],
|
||||
fromTableName: '',
|
||||
fromColumnList: [],
|
||||
wTbList: [],
|
||||
dataSource: '',
|
||||
writerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
ifCreateTable: false,
|
||||
mode: 'normal',
|
||||
rowkeyColumn: '[{\n' +
|
||||
'\t"index": 0,\n' +
|
||||
'\t"type": "string"\n' +
|
||||
'}]',
|
||||
versionColumn: {
|
||||
index: '',
|
||||
value: ''
|
||||
},
|
||||
nullMode: ''
|
||||
},
|
||||
nullModeTypes: [
|
||||
{ value: 'skip', label: '不向hbase写这列' },
|
||||
{ value: 'empty', label: '写入new byte [0]' }
|
||||
],
|
||||
rules: {
|
||||
mode: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
fromTableName: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
rowkeyColumn: [{ required: true, trigger: 'blur', validator: checkJson }]
|
||||
},
|
||||
readerForm: this.getReaderData()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'writerForm.datasourceId': function(oldVal, newVal) {
|
||||
this.getTables('hbaseWriter')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs(type) {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response
|
||||
this.wDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'hbaseWriter') {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.wTbList = response
|
||||
})
|
||||
}
|
||||
},
|
||||
wDsChange(e) {
|
||||
// 清空
|
||||
this.writerForm.tableName = ''
|
||||
this.writerForm.datasourceId = e
|
||||
this.wDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables()
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableName: this.writerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.fromColumnList = response
|
||||
this.writerForm.columns = response
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 表切换
|
||||
wTbChange(t) {
|
||||
this.writerForm.tableName = t
|
||||
this.fromColumnList = []
|
||||
this.writerForm.columns = []
|
||||
this.getColumns('writer')
|
||||
},
|
||||
wHandleCheckAllChange(val) {
|
||||
this.writerForm.columns = val ? this.fromColumnList : []
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
wHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.writerForm.checkAll = checkedCount === this.fromColumnList.length
|
||||
this.writerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.fromColumnList.length
|
||||
},
|
||||
createTableCheckedChange(val) {
|
||||
this.writerForm.tableName = val ? this.readerForm.tableName : ''
|
||||
this.fromColumnList = this.readerForm.columns
|
||||
this.writerForm.columns = this.readerForm.columns
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.writerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.writerForm
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
getTableName() {
|
||||
return this.fromTableName
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
240
src/views/dts/json-build/writer/HiveWriter.vue
Normal file
240
src/views/dts/json-build/writer/HiveWriter.vue
Normal file
@@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form label-position="left" label-width="105px" :model="writerForm" :rules="rules">
|
||||
<el-form-item label="数据源" prop="datasourceId">
|
||||
<el-select
|
||||
v-model="writerForm.datasourceId"
|
||||
filterable
|
||||
@change="wDsChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="表" prop="fromTableName">
|
||||
<el-select
|
||||
v-model="fromTableName"
|
||||
:disabled="writerForm.ifCreateTable"
|
||||
filterable
|
||||
@change="wTbChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wTbList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--<el-col :span="6">
|
||||
<el-form-item>
|
||||
<el-button type="primary" :disabled="!this.fromTableName" @click="createTable()">一键生成目标表</el-button>
|
||||
</el-form-item>
|
||||
</el-col>-->
|
||||
</el-row>
|
||||
<el-form-item label="path" prop="path">
|
||||
<el-input v-model="writerForm.path" :autosize="{ minRows: 2, maxRows: 20}" type="textarea" placeholder="为与hive表关联,请填写hive表在hdfs上的存储路径" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="defaultFS" prop="defaultFS">
|
||||
<el-input v-model="writerForm.defaultFS" placeholder="Hadoop hdfs文件系统namenode节点地址" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="fileName" prop="fileName">
|
||||
<el-input v-model="writerForm.fileName" placeholder="HdfsWriter写入时的文件名" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="fileType" prop="fileType">
|
||||
<el-select v-model="writerForm.fileType" placeholder="文件的类型">
|
||||
<el-option v-for="item in fileTypes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="writeMode" prop="writeMode">
|
||||
<el-select v-model="writerForm.writeMode" placeholder="文件的类型">
|
||||
<el-option v-for="item in writeModes" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="fieldDelimiter" prop="fieldDelimiter">
|
||||
<el-input v-model="writerForm.fieldDelimiter" placeholder="与创建表的分隔符一致" style="width: 13%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="字段">
|
||||
<el-checkbox v-model="writerForm.checkAll" :indeterminate="writerForm.isIndeterminate" @change="wHandleCheckAllChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="writerForm.columns" @change="wHandleCheckedChange">
|
||||
<el-checkbox v-for="c in fromColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busWriter'
|
||||
export default {
|
||||
name: 'HiveWriter',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200
|
||||
},
|
||||
wDsList: [],
|
||||
fromTableName: '',
|
||||
fromColumnList: [],
|
||||
wTbList: [],
|
||||
dataSource: '',
|
||||
writerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
ifCreateTable: false,
|
||||
defaultFS: '',
|
||||
fileType: '',
|
||||
path: '',
|
||||
fileName: '',
|
||||
writeMode: '',
|
||||
fieldDelimiter: ''
|
||||
},
|
||||
rules: {
|
||||
path: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
defaultFS: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
fileName: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
fileType: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
writeMode: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
fieldDelimiter: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
fromTableName: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
},
|
||||
readerForm: this.getReaderData(),
|
||||
fileTypes: [
|
||||
{ value: 'text', label: 'text' },
|
||||
{ value: 'orc', label: 'orc' }
|
||||
],
|
||||
writeModes: [
|
||||
{ value: 'append', label: 'append 写入前不做任何处理' },
|
||||
{ value: 'nonConflict', label: 'nonConflict 目录下有fileName前缀的文件,直接报错' }
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'writerForm.datasourceId': function(oldVal, newVal) {
|
||||
this.getTables('hiveWriter')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs(type) {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response
|
||||
this.wDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'hiveWriter') {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.wTbList = response
|
||||
})
|
||||
}
|
||||
},
|
||||
wDsChange(e) {
|
||||
// 清空
|
||||
this.writerForm.tableName = ''
|
||||
this.writerForm.datasourceId = e
|
||||
this.wDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables()
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableName: this.writerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.fromColumnList = response
|
||||
this.writerForm.columns = response
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 表切换
|
||||
wTbChange(t) {
|
||||
this.writerForm.tableName = t
|
||||
this.fromColumnList = []
|
||||
this.writerForm.columns = []
|
||||
this.getColumns('writer')
|
||||
},
|
||||
wHandleCheckAllChange(val) {
|
||||
this.writerForm.columns = val ? this.fromColumnList : []
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
wHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.writerForm.checkAll = checkedCount === this.fromColumnList.length
|
||||
this.writerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.fromColumnList.length
|
||||
},
|
||||
createTableCheckedChange(val) {
|
||||
this.writerForm.tableName = val ? this.readerForm.tableName : ''
|
||||
this.fromColumnList = this.readerForm.columns
|
||||
this.writerForm.columns = this.readerForm.columns
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.writerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.writerForm
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
getTableName() {
|
||||
return this.fromTableName
|
||||
},
|
||||
createTable() {
|
||||
const tableName = this.fromTableName
|
||||
const datasourceId = this.writerForm.datasourceId
|
||||
const columns = this.fromColumnList
|
||||
const jsonString = {}
|
||||
jsonString['datasourceId'] = datasourceId
|
||||
jsonString['tableName'] = tableName
|
||||
jsonString['columns'] = columns
|
||||
console.info(jsonString)
|
||||
dsQueryApi.createTable(jsonString).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Create Table Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}).catch(() => console.log('promise catch err'))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
192
src/views/dts/json-build/writer/MongoDBWriter.vue
Normal file
192
src/views/dts/json-build/writer/MongoDBWriter.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form label-position="left" label-width="105px" :model="writerForm" :rules="rules">
|
||||
<el-form-item label="数据源" prop="datasourceId">
|
||||
<el-select
|
||||
v-model="writerForm.datasourceId"
|
||||
filterable
|
||||
@change="wDsChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="表" prop="fromTableName">
|
||||
<el-select
|
||||
v-model="fromTableName"
|
||||
:disabled="writerForm.ifCreateTable"
|
||||
filterable
|
||||
@change="wTbChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wTbList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="更新信息">
|
||||
<el-select v-model="writerForm.upsertInfo.isUpsert" placeholder="是否更新">
|
||||
<el-option v-for="item in upsertType" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input v-model="writerForm.upsertInfo.upsertKey" placeholder="更新的业务主键" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="字段">
|
||||
<el-checkbox v-model="writerForm.checkAll" :indeterminate="writerForm.isIndeterminate" @change="wHandleCheckAllChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="writerForm.columns" @change="wHandleCheckedChange">
|
||||
<el-checkbox v-for="c in fromColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busWriter'
|
||||
export default {
|
||||
name: 'MongoDBWriter',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200
|
||||
},
|
||||
wDsList: [],
|
||||
fromTableName: '',
|
||||
fromColumnList: [],
|
||||
wTbList: [],
|
||||
dataSource: '',
|
||||
writerForm: {
|
||||
datasourceId: undefined,
|
||||
columns: [],
|
||||
tableName: '',
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
ifCreateTable: false,
|
||||
upsertInfo: {
|
||||
isUpsert: '',
|
||||
upsertKey: ''
|
||||
}
|
||||
},
|
||||
upsertType: [
|
||||
{ value: true, label: '针对相同的upsertKey做更新' },
|
||||
{ value: false, label: '不做更新' }
|
||||
],
|
||||
rules: {
|
||||
mode: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'blur' }],
|
||||
fromTableName: [{ required: true, message: 'this is required', trigger: 'blur' }]
|
||||
},
|
||||
readerForm: this.getReaderData()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'writerForm.datasourceId': function(oldVal, newVal) {
|
||||
this.getTables('mongodbWriter')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs(type) {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response
|
||||
this.wDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'mongodbWriter') {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.wTbList = response
|
||||
})
|
||||
}
|
||||
},
|
||||
wDsChange(e) {
|
||||
// 清空
|
||||
this.writerForm.tableName = ''
|
||||
this.writerForm.datasourceId = e
|
||||
this.wDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
// 获取可用表
|
||||
this.getTables()
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableName: this.writerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.fromColumnList = response
|
||||
this.writerForm.columns = response
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 表切换
|
||||
wTbChange(t) {
|
||||
this.writerForm.tableName = t
|
||||
this.fromColumnList = []
|
||||
this.writerForm.columns = []
|
||||
this.getColumns('writer')
|
||||
},
|
||||
wHandleCheckAllChange(val) {
|
||||
this.writerForm.columns = val ? this.fromColumnList : []
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
wHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.writerForm.checkAll = checkedCount === this.fromColumnList.length
|
||||
this.writerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.fromColumnList.length
|
||||
},
|
||||
createTableCheckedChange(val) {
|
||||
this.writerForm.tableName = val ? this.readerForm.tableName : ''
|
||||
this.fromColumnList = this.readerForm.columns
|
||||
this.writerForm.columns = this.readerForm.columns
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.writerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.writerForm
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
getTableName() {
|
||||
return this.fromTableName
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
232
src/views/dts/json-build/writer/RDBMSWriter.vue
Normal file
232
src/views/dts/json-build/writer/RDBMSWriter.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form label-position="right" label-width="150px" :model="writerForm" :rules="rules">
|
||||
<el-form-item label="数据库源:" prop="datasourceId">
|
||||
<el-select
|
||||
v-model="writerForm.datasourceId"
|
||||
filterable
|
||||
style="width: 300px;"
|
||||
@change="wDsChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wDsList"
|
||||
:key="item.id"
|
||||
:label="item.datasourceName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="dataSource==='postgresql' || dataSource==='oracle' ||dataSource==='sqlserver' || dataSource==='hana'" label="Schema:" prop="tableSchema">
|
||||
<el-select v-model="writerForm.tableSchema" filterable style="width: 300px" @change="schemaChange">
|
||||
<el-option
|
||||
v-for="item in schemaList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库表名:" prop="tableName">
|
||||
<el-select
|
||||
v-model="fromTableName"
|
||||
allow-create
|
||||
default-first-option
|
||||
filterable
|
||||
:disabled="writerForm.ifCreateTable"
|
||||
style="width: 300px"
|
||||
@change="wTbChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in wTbList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-show="writerForm.ifCreateTable" v-model="writerForm.tableName" style="width: 200px;" :placeholder="readerForm.tableName" />
|
||||
<!--<el-input v-model="createTableName" style="width: 195px" />
|
||||
<el-button type="primary" @click="createTable">新增</el-button>-->
|
||||
</el-form-item>
|
||||
<div style="margin: 5px 0;" />
|
||||
<el-form-item label="字段:">
|
||||
<el-checkbox v-model="writerForm.checkAll" :indeterminate="writerForm.isIndeterminate" @change="wHandleCheckAllChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;" />
|
||||
<el-checkbox-group v-model="writerForm.columns" @change="wHandleCheckedChange">
|
||||
<el-checkbox v-for="c in fromColumnList" :key="c" :label="c">{{ c }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="前置sql语句:">
|
||||
<el-input v-model="writerForm.preSql" placeholder="前置sql在insert之前执行" type="textarea" style="width: 42%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="postSql">
|
||||
<el-input v-model="writerForm.postSql" placeholder="多个用;分隔" type="textarea" style="width: 42%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dsQueryApi from '@/api/dts/metadata-query'
|
||||
import { list as jdbcDsList } from '@/api/dts/datax-jdbcDatasource'
|
||||
import Bus from '../busWriter'
|
||||
export default {
|
||||
name: 'RDBMSWriter',
|
||||
data() {
|
||||
return {
|
||||
jdbcDsQuery: {
|
||||
current: 1,
|
||||
size: 200,
|
||||
ascs: 'datasource_name'
|
||||
},
|
||||
wDsList: [],
|
||||
schemaList: [],
|
||||
fromTableName: '',
|
||||
fromColumnList: [],
|
||||
wTbList: [],
|
||||
dataSource: '',
|
||||
createTableName: '',
|
||||
writerForm: {
|
||||
datasourceId: undefined,
|
||||
tableName: '',
|
||||
columns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: true,
|
||||
preSql: '',
|
||||
postSql: '',
|
||||
ifCreateTable: false,
|
||||
tableSchema: ''
|
||||
},
|
||||
readerForm: this.getReaderData(),
|
||||
rules: {
|
||||
datasourceId: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
tableName: [{ required: true, message: 'this is required', trigger: 'change' }],
|
||||
tableSchema: [{ required: true, message: 'this is required', trigger: 'change' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'writerForm.datasourceId': function(oldVal, newVal) {
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
this.getSchema()
|
||||
} else {
|
||||
this.getTables('rdbmsWriter')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getJdbcDs()
|
||||
},
|
||||
methods: {
|
||||
// 获取可用数据源
|
||||
getJdbcDs() {
|
||||
this.loading = true
|
||||
jdbcDsList(this.jdbcDsQuery).then(response => {
|
||||
const { records } = response.data
|
||||
this.wDsList = records
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取表名
|
||||
getTables(type) {
|
||||
if (type === 'rdbmsWriter') {
|
||||
let obj = {}
|
||||
if (this.dataSource === 'postgresql' || this.dataSource === 'oracle' || this.dataSource === 'sqlserver' || this.dataSource === 'hana') {
|
||||
obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableSchema: this.writerForm.tableSchema
|
||||
}
|
||||
} else {
|
||||
obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
}
|
||||
// 组装
|
||||
dsQueryApi.getTables(obj).then(response => {
|
||||
this.wTbList = response.data
|
||||
})
|
||||
}
|
||||
},
|
||||
getSchema() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId
|
||||
}
|
||||
dsQueryApi.getTableSchema(obj).then(response => {
|
||||
this.schemaList = response
|
||||
})
|
||||
},
|
||||
// schema 切换
|
||||
schemaChange(e) {
|
||||
this.writerForm.tableSchema = e
|
||||
// 获取可用表
|
||||
this.getTables('rdbmsWriter')
|
||||
},
|
||||
wDsChange(e) {
|
||||
// 清空
|
||||
this.writerForm.tableName = ''
|
||||
this.writerForm.datasourceId = e
|
||||
this.wDsList.find((item) => {
|
||||
if (item.id === e) {
|
||||
this.dataSource = item.datasource
|
||||
}
|
||||
})
|
||||
Bus.dataSourceId = e
|
||||
this.$emit('selectDataSource', this.dataSource)
|
||||
},
|
||||
// 获取表字段
|
||||
getColumns() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableName: this.writerForm.tableName
|
||||
}
|
||||
dsQueryApi.getColumns(obj).then(response => {
|
||||
this.fromColumnList = response.data
|
||||
this.writerForm.columns = response.data
|
||||
this.writerForm.checkAll = true
|
||||
this.writerForm.isIndeterminate = false
|
||||
})
|
||||
},
|
||||
// 表切换
|
||||
wTbChange(t) {
|
||||
this.writerForm.tableName = t
|
||||
this.fromColumnList = []
|
||||
this.writerForm.columns = []
|
||||
this.getColumns('writer')
|
||||
},
|
||||
wHandleCheckAllChange(val) {
|
||||
this.writerForm.columns = val ? this.fromColumnList : []
|
||||
this.writerForm.isIndeterminate = false
|
||||
},
|
||||
wHandleCheckedChange(value) {
|
||||
const checkedCount = value.length
|
||||
this.writerForm.checkAll = checkedCount === this.fromColumnList.length
|
||||
this.writerForm.isIndeterminate = checkedCount > 0 && checkedCount < this.fromColumnList.length
|
||||
},
|
||||
getData() {
|
||||
if (Bus.dataSourceId) {
|
||||
this.writerForm.datasourceId = Bus.dataSourceId
|
||||
}
|
||||
return this.writerForm
|
||||
},
|
||||
getReaderData() {
|
||||
return this.$parent.getReaderData()
|
||||
},
|
||||
getTableName() {
|
||||
return this.fromTableName
|
||||
},
|
||||
createTable() {
|
||||
const obj = {
|
||||
datasourceId: this.writerForm.datasourceId,
|
||||
tableName: this.createTableName
|
||||
}
|
||||
dsQueryApi.createTable(obj).then(response => {
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Create Table Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}).catch(() => console.log('promise catch err'))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
174
src/views/dts/registry/index.vue
Normal file
174
src/views/dts/registry/index.vue
Normal file
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input v-model="listQuery.registryKey" placeholder="执行器" style="width: 200px;" class="filter-item" />
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
Search
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-for="item in list" :key="item.id" class="container">
|
||||
<p><span class="fl">执行器:{{ item.registryKey }}</span><span class="fl"> 注册地址:{{ item.registryValue }}</span><span class="fr">更新时间:{{ item.updateTime }}</span></p>
|
||||
<div :class="item.id + ' fl'" style="width: 30%;height: 300px" />
|
||||
<div :class="item.id + ' fl'" style="width: 30%;height: 300px" />
|
||||
<div :class="item.id + ' fl' + ' loadAverage'" style="width: 30%;height: 300px ">
|
||||
<p class="title">平均负载</p>
|
||||
<p class="number">{{ item.loadAverage >= 0 ? item.loadAverage : 0 }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getList } from '@/api/dts/datax-registry'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
export default {
|
||||
name: 'Registry',
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
registryKey: undefined
|
||||
},
|
||||
dialogPluginVisible: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
this.list = []
|
||||
getList(this.listQuery).then(response => {
|
||||
const { data } = response
|
||||
const { total } = data.total
|
||||
this.total = total
|
||||
this.list = data.records
|
||||
this.listLoading = false
|
||||
|
||||
this.$nextTick(function() {
|
||||
if (this.list) {
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
this.initEcharts(this.list[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
initEcharts(data) {
|
||||
const myChart1 = this.$echarts.init(document.getElementsByClassName(data.id)[0])
|
||||
// 绘制图表
|
||||
var option1 = {
|
||||
title: {
|
||||
text: 'cpu使用率',
|
||||
subtext: '',
|
||||
x: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c}%'
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
restore: {},
|
||||
saveAsImage: {}
|
||||
},
|
||||
show: false
|
||||
},
|
||||
series: [{
|
||||
name: 'cpu使用率',
|
||||
type: 'gauge',
|
||||
max: 100,
|
||||
radius: '70%', // 半径
|
||||
startAngle: 215, // 起始位置
|
||||
endAngle: -35, // 终点位置
|
||||
detail: {
|
||||
formatter: '{value}%'
|
||||
},
|
||||
data: [{
|
||||
value: data.cpuUsage,
|
||||
name: ''
|
||||
}]
|
||||
}]
|
||||
}
|
||||
myChart1.setOption(option1)
|
||||
const myChart2 = this.$echarts.init(document.getElementsByClassName(data.id)[1])
|
||||
// 绘制图表
|
||||
var option2 = {
|
||||
title: {
|
||||
text: '内存使用率',
|
||||
subtext: '',
|
||||
x: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
formatter: '{a} <br/>{b} : {c}%'
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
restore: {},
|
||||
saveAsImage: {}
|
||||
},
|
||||
show: false
|
||||
},
|
||||
series: [{
|
||||
name: '内存使用率',
|
||||
type: 'gauge',
|
||||
max: 100,
|
||||
radius: '70%', // 半径
|
||||
startAngle: 215, // 起始位置
|
||||
endAngle: -35, // 终点位置
|
||||
detail: {
|
||||
formatter: '{value}%'
|
||||
},
|
||||
data: [{
|
||||
value: data.memoryUsage,
|
||||
name: ''
|
||||
}]
|
||||
}]
|
||||
}
|
||||
myChart2.setOption(option2)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scope>
|
||||
.container{
|
||||
overflow: hidden;
|
||||
p{
|
||||
font-size: 14px;color: #666;padding: 10px 0;
|
||||
.fl{
|
||||
float: left;
|
||||
}
|
||||
.fr{
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.loadAverage{
|
||||
p{
|
||||
text-align: center;
|
||||
}
|
||||
.title{
|
||||
font-size: 18px;font-weight: bold;color: #333;padding: 5px 0;margin: 0;
|
||||
}
|
||||
.number{
|
||||
font-size: 50px;color: #3d90d0
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
215
src/views/dts/resource/index.vue
Normal file
215
src/views/dts/resource/index.vue
Normal file
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="filter-container">
|
||||
<el-input v-model="listQuery.username" placeholder="资源名称" style="width: 200px;" class="filter-item" />
|
||||
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="fetchData">
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
class="filter-item"
|
||||
style="margin-left: 10px;"
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click="handleCreate"
|
||||
>
|
||||
添加
|
||||
</el-button>
|
||||
<!-- <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
|
||||
reviewer
|
||||
</el-checkbox> -->
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
element-loading-text="Loading"
|
||||
border
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column align="center" label="序号" width="95">
|
||||
<template slot-scope="scope">{{ scope.$index+1 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="资源名称" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.username }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="资源地址" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.username }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" size="mini" @click="handleUpdate(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button v-if="row.status!=='deleted'" size="mini" type="danger" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="listQuery.current"
|
||||
:limit.sync="listQuery.size"
|
||||
@pagination="fetchData"
|
||||
/>
|
||||
|
||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
|
||||
<el-form
|
||||
ref="dataForm"
|
||||
:rules="rules"
|
||||
:model="temp"
|
||||
label-position="right"
|
||||
label-width="100px"
|
||||
style="width: 400px; margin-left:50px;"
|
||||
>
|
||||
<el-form-item label="资源名称" prop="resourceName">
|
||||
<el-input v-model="temp.resourceName" placeholder="资源名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="资源地址" prop="resourcePath">
|
||||
<el-input v-model="temp.resourcePath" placeholder="资源地址" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as user from '@/api/dts/datax-user'
|
||||
import waves from '@/directive/waves' // waves directive
|
||||
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
|
||||
|
||||
export default {
|
||||
name: 'User',
|
||||
components: { Pagination },
|
||||
directives: { waves },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
published: 'success',
|
||||
draft: 'gray',
|
||||
deleted: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null,
|
||||
listLoading: true,
|
||||
total: 0,
|
||||
listQuery: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
username: undefined
|
||||
},
|
||||
roles: ['ROLE_USER', 'ROLE_ADMIN'],
|
||||
dialogPluginVisible: false,
|
||||
pluginData: [],
|
||||
dialogFormVisible: false,
|
||||
dialogStatus: '',
|
||||
textMap: {
|
||||
update: 'Edit',
|
||||
create: 'Create'
|
||||
},
|
||||
rules: {
|
||||
role: [{ required: true, message: 'role is required', trigger: 'change' }],
|
||||
username: [{ required: true, message: 'username is required', trigger: 'blur' }],
|
||||
password: [{ required: false, message: 'password is required', trigger: 'blur' }]
|
||||
},
|
||||
temp: {
|
||||
id: undefined,
|
||||
role: '',
|
||||
username: '',
|
||||
password: '',
|
||||
permission: ''
|
||||
},
|
||||
resetTemp() {
|
||||
this.temp = this.$options.data().temp
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
this.listLoading = true
|
||||
user.getList(this.listQuery).then(response => {
|
||||
const { content } = response
|
||||
this.total = content.recordsTotal
|
||||
this.list = content.data
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleCreate() {
|
||||
this.resetTemp()
|
||||
this.dialogStatus = 'create'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
createData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
user.createUser(this.temp).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Created Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.temp = Object.assign({}, row) // copy obj
|
||||
this.dialogStatus = 'update'
|
||||
this.dialogFormVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
})
|
||||
},
|
||||
updateData() {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (valid) {
|
||||
const tempData = Object.assign({}, this.temp)
|
||||
user.updateUser(tempData).then(() => {
|
||||
this.fetchData()
|
||||
this.dialogFormVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Update Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
user.deleteUser(row.id).then(response => {
|
||||
this.fetchData()
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
message: 'Delete Successfully',
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user