fix: 修复飞书数据源插件

This commit is contained in:
taojinlong
2025-02-19 19:44:17 +08:00
committed by taojinlong
parent 463a8cdca5
commit 7ceaf6d6b7
5 changed files with 203 additions and 169 deletions

View File

@@ -126,7 +126,7 @@ public class DataSourceManage {
}
}
@XpackInteract(value = "larkManageInteract", before = true)
@XpackInteract(value = "larkManage", replace = true)
public String getTenantAccessToken() {
return null;
}

View File

@@ -35,7 +35,7 @@ public class ApiUtils {
private static TypeReference<List<Map<String, Object>>> listForMapTypeReference = new TypeReference<List<Map<String, Object>>>() {
};
public static List<DatasetTableDTO> getTables(DatasourceRequest datasourceRequest) throws DEException {
public static List<DatasetTableDTO> getApiTables(DatasourceRequest datasourceRequest) throws DEException {
List<DatasetTableDTO> tableDescs = new ArrayList<>();
TypeReference<List<ApiDefinition>> listTypeReference = new TypeReference<List<ApiDefinition>>() {
};
@@ -71,7 +71,7 @@ public class ApiUtils {
}
public static Map<String, Object> fetchResultField(DatasourceRequest datasourceRequest) throws DEException {
public static Map<String, Object> fetchApiResultField(DatasourceRequest datasourceRequest) throws DEException {
Map<String, Object> result = new HashMap<>();
List<String[]> dataList = new ArrayList<>();
List<TableField> fieldList = new ArrayList<>();
@@ -152,7 +152,7 @@ public class ApiUtils {
return tableFields;
}
public static String checkStatus(DatasourceRequest datasourceRequest) throws Exception {
public static String checkAPIStatus(DatasourceRequest datasourceRequest) throws Exception {
TypeReference<List<ApiDefinition>> listTypeReference = new TypeReference<List<ApiDefinition>>() {
};
List<ApiDefinition> apiDefinitionList = JsonUtil.parseList(datasourceRequest.getDatasource().getConfiguration(), listTypeReference);

View File

@@ -15,6 +15,7 @@ import { fieldType } from '@/utils/attr'
import type { ApiConfiguration } from '@/views/visualized/data/datasource/form/option'
import { cancelMap } from '@/config/axios/service'
import { iconFieldMap } from '@/components/icon-group/field-list'
import { PluginComponent } from '@/components/plugin'
export interface Field {
name: string
@@ -29,6 +30,9 @@ export interface ApiItem {
status: string
name: string
type: string
appToken: string
tableId: string
viewId: string
deTableName?: string
url: string
copy: boolean
@@ -109,6 +113,7 @@ const columns = shallowRef([])
const valueList = shallowRef([])
const tableData = shallowRef([])
const apiItemBasicInfo = ref<FormInstance>()
const xpackApiItemBasicInfo = ref<FormInstance>()
const isSupportSetKey = ref(false)
const isNumber = (rule, value, callback) => {
if (!value) {
@@ -166,11 +171,29 @@ const rule = reactive<FormRules>({
const activeName = ref('table')
const editItem = ref(false)
const copyItem = ref(false)
const dsType = ref('API')
const jsName = ref('')
const isPlugin = ref(false)
const pluginDs = ref([])
const pluginIndex = ref('')
const copyDs = ref(false)
provide('api-active-name', activeName)
const initApiItem = (val: ApiItem, from, name, edit, supportSetKey) => {
const initApiItem = (
val: ApiItem,
from,
name,
edit,
supportSetKey,
pluginDsList,
indexPlugin,
isPluginDs
) => {
pluginDs.value = pluginDsList
pluginIndex.value = indexPlugin
isPlugin.value = isPluginDs
copyItem.value = val.copy
copyDs.value = from.copy
dsType.value = from.type
isSupportSetKey.value = supportSetKey
activeName.value = name
editItem.value = edit
@@ -179,6 +202,9 @@ const initApiItem = (val: ApiItem, from, name, edit, supportSetKey) => {
if (from.paramsConfiguration) {
paramsList = from.paramsConfiguration
}
if (isPlugin.value) {
jsName.value = getPluginStatic()
}
valueList.value = []
if (val.type !== 'params' && paramsList) {
for (let i = 0; i < paramsList.length; i++) {
@@ -189,7 +215,14 @@ const initApiItem = (val: ApiItem, from, name, edit, supportSetKey) => {
edit_api_item.value = true
active.value = 0
nextTick(() => {
apiItemBasicInfo.value.clearValidate()
if (isPlugin.value) {
xpackApiItemBasicInfo?.value?.invokeMethod({
methodName: 'clearForm',
args: []
})
} else {
apiItemBasicInfo.value.clearValidate()
}
})
}
@@ -200,7 +233,7 @@ const showApiData = () => {
const params = Base64.encode(JSON.stringify(paramsList))
loading.value = true
cancelMap['/datasource/checkApiDatasource']?.()
checkApiItem({ data: data, type: 'apiStructure', paramsList: params })
checkApiItem({ dsType: dsType.value, data: data, type: 'apiStructure', paramsList: params })
.then(response => {
originFieldItem.jsonFields = response.data.jsonFields
})
@@ -323,80 +356,101 @@ const before = () => {
active.value -= 1
}
const next = () => {
apiItemBasicInfo.value.validate(val => {
if (val) {
if (apiItem.useJsonPath && !apiItem.jsonPath) {
ElMessage.error(t('datasource.please_input_dataPath'))
console.log(apiItem)
if (isPlugin.value) {
} else {
apiItemBasicInfo.value.validate(val => {
if (!val) {
return
}
if (apiItem.type === 'params') {
for (let i = 0; i < paramsList.length; i++) {
if (
paramsList[i].name === apiItem.name &&
apiItem.serialNumber !== paramsList[i].serialNumber
) {
ElMessage.error(t('data_source.name_already_exists_de'))
return
}
}
} else {
for (let i = 0; i < apiItemList.length; i++) {
if (
apiItemList[i].name === apiItem.name &&
apiItem.serialNumber !== apiItemList[i].serialNumber
) {
ElMessage.error(t('datasource.has_repeat_name'))
return
}
}
})
}
if (apiItem.useJsonPath && !apiItem.jsonPath) {
ElMessage.error(t('datasource.please_input_dataPath'))
return
}
if (apiItem.type === 'params') {
for (let i = 0; i < paramsList.length; i++) {
if (
paramsList[i].name === apiItem.name &&
apiItem.serialNumber !== paramsList[i].serialNumber
) {
ElMessage.error(t('data_source.name_already_exists_de'))
return
}
cancelMap['/datasource/checkApiDatasource']?.()
const params = Base64.encode(JSON.stringify(paramsList))
disabledNext.value = true
formLoading.value = true
checkApiItem({ data: Base64.encode(JSON.stringify(apiItem)), paramsList: params })
.then(response => {
disabledNext.value = false
formLoading.value = false
apiItem.jsonFields = response.data.jsonFields
apiItem.fields = []
handleFiledChange(apiItem)
previewData()
active.value += 1
})
.catch(error => {
disabledNext.value = false
formLoading.value = false
console.warn(error?.message)
})
}
} else {
for (let i = 0; i < apiItemList.length; i++) {
if (
apiItemList[i].name === apiItem.name &&
apiItem.serialNumber !== apiItemList[i].serialNumber
) {
ElMessage.error(t('datasource.has_repeat_name'))
return
}
}
}
cancelMap['/datasource/checkApiDatasource']?.()
const params = Base64.encode(JSON.stringify(paramsList))
disabledNext.value = true
formLoading.value = true
checkApiItem({
dsType: dsType.value,
data: Base64.encode(JSON.stringify(apiItem)),
paramsList: params
})
.then(response => {
disabledNext.value = false
formLoading.value = false
apiItem.jsonFields = response.data.jsonFields
apiItem.fields = []
apiItem.name = response.data.name
handleFiledChange(apiItem)
previewData()
active.value += 1
})
.catch(error => {
disabledNext.value = false
formLoading.value = false
console.warn(error?.message)
})
}
const validate = () => {
apiItemBasicInfo.value.validate(val => {
if (val) {
if (apiItem.useJsonPath && !apiItem.jsonPath) {
ElMessage.error(t('datasource.please_input_dataPath'))
if (isPlugin.value) {
xpackApiItemBasicInfo?.value?.invokeMethod({
methodName: 'submitForm',
args: [apiItem]
})
} else {
apiItemBasicInfo.value.validate(val => {
if (!val) {
return
}
cancelMap['/datasource/checkApiDatasource']?.()
const params = Base64.encode(JSON.stringify(paramsList))
checkApiItem({ data: Base64.encode(JSON.stringify(apiItem)), paramsList: params })
.then(response => {
apiItem.jsonFields = response.data.jsonFields
apiItem.fields = []
handleFiledChange(apiItem)
previewData()
ElMessage.success(t('datasource.validate_success'))
})
.catch(() => {
ElMessage.error(t('data_source.verification_failed'))
})
}
})
}
if (apiItem.useJsonPath && !apiItem.jsonPath) {
ElMessage.error(t('datasource.please_input_dataPath'))
return
}
cancelMap['/datasource/checkApiDatasource']?.()
const params = Base64.encode(JSON.stringify(paramsList))
checkApiItem({
dsType: dsType.value,
data: Base64.encode(JSON.stringify(apiItem)),
paramsList: params
})
.then(response => {
apiItem.jsonFields = response.data.jsonFields
apiItem.fields = []
apiItem.name = response.data.name
handleFiledChange(apiItem)
previewData()
ElMessage.success(t('datasource.validate_success'))
})
.catch(() => {
ElMessage.error(t('data_source.verification_failed'))
})
}
const closeEditItem = () => {
cancelMap['/datasource/checkApiDatasource']?.()
@@ -537,6 +591,18 @@ const changeId = (val: string) => {
const activeColumnInfo = ref(true)
const activeDataPreview = ref(true)
const getPluginStatic = () => {
const arr = pluginDs.value.filter(ele => {
return ele.type === dsType.value
})
return pluginIndex.value
? pluginIndex.value
: arr && arr.length > 0
? arr[0].staticMap?.index
: null
}
const returnAPIItem = defineEmits(['returnItem'])
defineExpose({
@@ -584,7 +650,7 @@ defineExpose({
</el-steps>
</div>
<el-row v-show="active === 0">
<el-row v-show="active === 0 && dsType === 'API'">
<el-form
ref="apiItemBasicInfo"
:model="apiItem"
@@ -689,6 +755,52 @@ defineExpose({
</div>
</el-form>
</el-row>
<el-row v-show="active === 0 && dsType !== 'API'">
<plugin-component
:jsname="jsName"
:api-item="apiItem"
ref="xpackApiItemBasicInfo"
v-if="dsType !== 'API'"
>
</plugin-component>
<!-- <el-form-->
<!-- ref="xpackApiItemBasicInfo"-->
<!-- :model="apiItem"-->
<!-- label-position="top"-->
<!-- label-width="100px"-->
<!-- require-asterisk-position="right"-->
<!-- :rules="rule"-->
<!-- v-loading="formLoading"-->
<!-- >-->
<!-- <div class="title-form_primary base-info">-->
<!-- <span>{{ t('datasource.base_info') }}</span>-->
<!-- </div>-->
<!-- <el-form-item :label="t('common.name')">-->
<!-- <el-input v-model="apiItem.name" autocomplete="off" />-->
<!-- </el-form-item>-->
<!-- <el-form-item :label="t('datasource.app_token')" prop="appToken">-->
<!-- <el-input-->
<!-- v-model="apiItem.appToken"-->
<!-- :placeholder="t('datasource.input_app_token')"-->
<!-- autocomplete="off"-->
<!-- />-->
<!-- </el-form-item>-->
<!-- <el-form-item :label="t('datasource.table_id')" prop="tableId">-->
<!-- <el-input-->
<!-- v-model="apiItem.tableId"-->
<!-- :placeholder="t('datasource.input_table_id')"-->
<!-- autocomplete="off"-->
<!-- />-->
<!-- </el-form-item>-->
<!-- <el-form-item :label="t('datasource.view_id')" prop="viewId">-->
<!-- <el-input-->
<!-- v-model="apiItem.viewId"-->
<!-- :placeholder="t('datasource.input_view_id')"-->
<!-- autocomplete="off"-->
<!-- />-->
<!-- </el-form-item>-->
<!-- </el-form>-->
</el-row>
<el-row v-show="active === 1">
<el-form
style="width: 100%"

View File

@@ -431,7 +431,10 @@ const addApiItem = item => {
form.value,
activeName.value,
editItem,
isSupportSetKey.value
isSupportSetKey.value,
pluginDs.value,
pluginIndex.value,
isPlugin.value
)
})
}
@@ -850,7 +853,7 @@ defineExpose({
show-word-limit
/>
</el-form-item>
<template v-if="form.type === 'API'">
<template v-if="form.type.startsWith('API')">
<div class="title-form_primary flex-space table-info-mr" v-show="activeStep !== 2">
<el-tabs v-model="activeName" class="api-tabs">
<el-tab-pane :label="t('datasource.data_table')" name="table"></el-tab-pane>
@@ -872,7 +875,9 @@ defineExpose({
:description="t('datasource.no_data_table')"
img-type="noneWhite"
/>
<template v-if="form.type === 'API' && activeStep === 1 && activeName === 'table'">
<template
v-if="form.type.startsWith('API') && activeStep === 1 && activeName === 'table'"
>
<div class="api-card-content">
<div
v-for="(api, idx) in form.apiConfiguration"
@@ -1018,90 +1023,6 @@ defineExpose({
</div>
</div>
</template>
<template v-if="form.type !== 'API' && form.type.startsWith('API')">
<div class="title-form_primary flex-space table-info-mr" v-show="activeStep !== 2">
<el-tabs v-model="activeName" class="api-tabs">
<el-tab-pane :label="t('datasource.data_table')" name="table"></el-tab-pane>
</el-tabs>
<el-button type="primary" style="margin-left: auto" @click="() => addLarkItem(null)">
<template #icon>
<Icon name="icon_add_outlined"><icon_add_outlined class="svg-icon" /></Icon>
</template>
{{ t('common.add') }}
</el-button>
</div>
<empty-background
v-show="activeStep !== 2"
v-if="!form.apiConfiguration.length && activeName === 'table'"
:description="t('datasource.no_data_table')"
img-type="noneWhite"
/>
<template v-if="activeStep === 1 && activeName === 'table'">
<div class="api-card-content">
<div
v-for="(api, idx) in form.apiConfiguration"
:key="api.id"
class="api-card"
@click="addLarkItem(api)"
>
<el-row>
<el-col style="display: flex" :span="19">
<span class="name ellipsis">{{ api.name }}</span>
<span v-if="api.status === 'Error'" class="de-tag invalid">{{
t('datasource.invalid')
}}</span>
<span v-if="api.status === 'Success'" class="de-tag valid">{{
t('datasource.valid')
}}</span>
</el-col>
<el-col style="text-align: right" :span="5">
<el-icon class="de-copy-icon hover-icon" @click.stop="copyItem(api)">
<Icon name="de-copy"><deCopy class="svg-icon" /></Icon>
</el-icon>
<span @click.stop>
<el-popover
placement="top"
width="200"
:ref="setItemRef"
show-arrow
popper-class="api-table-delete"
trigger="click"
>
<template #reference>
<el-icon class="de-delete-icon hover-icon">
<Icon name="de-delete"><deDelete class="svg-icon" /></Icon>
</el-icon>
</template>
<template #default>
<el-icon class="de-copy-icon icon-warning">
<Icon name="icon_warning_filled"
><icon_warning_filled class="svg-icon"
/></Icon>
</el-icon>
<div class="tips">
{{ t('datasource.delete_this_item') }}
</div>
<div class="foot">
<el-button style="min-width: 48px" secondary @click="cancelItem(idx)">{{
t('common.cancel')
}}</el-button>
<el-button
style="min-width: 48px"
type="primary"
@click="deleteItem(api, idx)"
>{{ t('common.sure') }}</el-button
>
</div>
</template>
</el-popover>
</span>
</el-col>
</el-row>
</div>
</div>
</template>
</template>
<template v-if="notapiexcelconfig">
<el-form-item
:label="t('data_source.connection_method')"
@@ -1634,13 +1555,6 @@ defineExpose({
</template>
</el-dialog>
<api-http-request-draw @return-item="returnItem" ref="editApiItem"></api-http-request-draw>
<plugin-component
:jsname="getPluginStatic()"
ref="xpack"
@return-item="returnItem"
v-if="isPlugin && visible"
>
</plugin-component>
</div>
</div>
</template>

View File

@@ -85,6 +85,14 @@ const selectDsType = (type: string) => {
currentDsType.value = type
activeStep.value = 1
activeApiStep.value = 1
currentTypeList.value
.map(ele => ele.dbList)
.flat()
.some(ele => {
if (ele.type === currentDsType.value) {
isPlugin.value = ele['isPlugin']
}
})
nextTick(() => {
detail?.value?.initForm(type, pluginDs.value, pluginIndex.value, isPlugin.value) ||
xpack?.value?.invokeMethod({
@@ -108,8 +116,8 @@ const selectDsType = (type: string) => {
const handleDsNodeClick = data => {
if (!data.type) return
selectDsType(data.type)
isPlugin.value = data['isPlugin']
selectDsType(data.type)
}
const handleNodeClick = (data: Node) => {
currentType.value = data.type
@@ -355,7 +363,7 @@ const validateDS = () => {
} else {
request.configuration = Base64.encode(JSON.stringify(request.configuration))
}
if (isPlugin.value) {
if (isPlugin.value && !currentDsType.value.includes('API')) {
xpack?.value?.invokeMethod({
methodName: 'submitForm',
args: [{ eventName: 'validateDs', args: request }]
@@ -475,10 +483,10 @@ const saveDS = () => {
} else {
request.configuration = Base64.encode(JSON.stringify(request.configuration))
}
if (isPlugin.value) {
if (isPlugin.value && !currentDsType.value.includes('API')) {
xpack?.value?.invokeMethod({
methodName: 'submitForm',
args: [{ eventName: 'saveDs', args: request }]
args: [{ eventName: 'save Ds', args: request }]
})
} else {
const validate = detail?.value?.submitForm()