更新前端代码

This commit is contained in:
biybuy 2025-11-03 19:39:54 +08:00
parent a61503d606
commit 21c4c065d8
24 changed files with 1072 additions and 411 deletions

View File

@ -0,0 +1,8 @@
{
"hash": "756e9009",
"configHash": "5e7a16b4",
"lockfileHash": "134c49f5",
"browserHash": "c06415c9",
"optimized": {},
"chunks": {}
}

3
.vite/deps/package.json Normal file
View File

@ -0,0 +1,3 @@
{
"type": "module"
}

View File

@ -0,0 +1,17 @@
// @ts-ignore
/* eslint-disable */
// Backwards-compat shims for previously generated SystemInterface module
// Map old function names to the new ones generated in `./interface`
export {
// 获取接口明细(旧名:getInterfaceGetSystemInterfaceById)
getInterfaceGetInterfaceById as getInterfaceGetSystemInterfaceById,
// 获取接口下拉(旧名:getInterfaceGetSystemInterfaceDropdownList)
getInterfaceGetInterfaceDropdownList as getInterfaceGetSystemInterfaceDropdownList,
// 接口分页列表(旧名:postInterfaceSystemInterfacePaginatedList)
postInterfaceInterfacePaginatedList as postInterfaceSystemInterfacePaginatedList,
// 批量删除接口(旧名:postInterfaceBatchDeleteSystemInterfaceByIds)
postInterfaceBatchDeleteInterfaceByIds as postInterfaceBatchDeleteSystemInterfaceByIds,
// 保存接口(旧名:postInterfaceSaveSystemInterface)
postInterfaceSaveInterface as postInterfaceSaveSystemInterface,
} from './interface';

View File

@ -6,9 +6,11 @@ import * as interfaceCategory from './interfaceCategory';
import * as interfaceReturnConfig from './interfaceReturnConfig'; import * as interfaceReturnConfig from './interfaceReturnConfig';
import * as serviceProviderInterface from './serviceProviderInterface'; import * as serviceProviderInterface from './serviceProviderInterface';
import * as systemInterface from './systemInterface'; import * as systemInterface from './systemInterface';
import * as interfaceApi from './interface';
export default { export default {
interfaceCategory, interfaceCategory,
interfaceReturnConfig, interfaceReturnConfig,
serviceProviderInterface, serviceProviderInterface,
systemInterface, systemInterface,
interface: interfaceApi,
}; };

View File

@ -0,0 +1,108 @@
// @ts-ignore
/* eslint-disable */
import request from '@/utils/request';
/** 批量删除接口 POST /Interface/BatchDeleteInterfaceByIds */
export async function postInterfaceBatchDeleteInterfaceByIds(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.postInterfaceBatchDeleteInterfaceByIdsParams,
body: number[],
options?: { [key: string]: any }
) {
return request<boolean>(`api/Interface/BatchDeleteInterfaceByIds`, {
method: 'POST',
headers: {
'Content-Type': 'application/json-patch+json',
},
params: {
...params,
},
data: body,
...(options || {}),
});
}
/** 获取接口明细 GET /Interface/GetInterfaceById */
export async function getInterfaceGetInterfaceById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getInterfaceGetInterfaceByIdParams,
options?: { [key: string]: any }
) {
return request<API.InterfaceOutput>(`api/Interface/GetInterfaceById`, {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 获取接口下拉列表 GET /Interface/GetInterfaceDropdownList */
export async function getInterfaceGetInterfaceDropdownList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getInterfaceGetInterfaceDropdownListParams,
options?: { [key: string]: any }
) {
return request<API.InterfaceDropdownListItem[]>(
`api/Interface/GetInterfaceDropdownList`,
{
method: 'GET',
params: {
...params,
},
...(options || {}),
}
);
}
/** 接口树形列表 POST /Interface/GetInterfaceTreeListAsync */
export async function postInterfaceGetInterfaceTreeListAsync(
body: API.InterfaceTreeListInputObjectValue,
options?: { [key: string]: any }
) {
return request<API.InterfaceTreeListOutputValueObjectCategoryTreeNode[]>(
`api/Interface/GetInterfaceTreeListAsync`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json-patch+json',
},
data: body,
...(options || {}),
}
);
}
/** 接口分页列表 POST /Interface/InterfacePaginatedList */
export async function postInterfaceInterfacePaginatedList(
body: API.InterfacePaginatedInputObjectValue,
options?: { [key: string]: any }
) {
return request<API.InterfacePaginatedOutputValueObjectPagedResult>(
`api/Interface/InterfacePaginatedList`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json-patch+json',
},
data: body,
...(options || {}),
}
);
}
/** 保存接口 用OptionType来区分操作目的,1:新增,2:删除,3:修改
<br>tips:新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系 POST /Interface/SaveInterface */
export async function postInterfaceSaveInterface(
body: API.SaveInterfaceInput,
options?: { [key: string]: any }
) {
return request<number>(`api/Interface/SaveInterface`, {
method: 'POST',
headers: {
'Content-Type': 'application/json-patch+json',
},
data: body,
...(options || {}),
});
}

View File

@ -2,32 +2,33 @@
/* eslint-disable */ /* eslint-disable */
import request from '@/utils/request'; import request from '@/utils/request';
/** 批量删除服务商接口 POST /Interface/BatchDeleteServiceProviderInterfaceByIds */ /** 批量删除服务商接口(切换至通用删除接口) POST /Interface/BatchDeleteInterfaceByIds */
export async function postInterfaceBatchDeleteServiceProviderInterfaceByIds( export async function postInterfaceBatchDeleteServiceProviderInterfaceByIds(
body: number[], body: number[],
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<boolean>( return request<boolean>(
`api/Interface/BatchDeleteServiceProviderInterfaceByIds`, `api/Interface/BatchDeleteInterfaceByIds`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json-patch+json', 'Content-Type': 'application/json-patch+json',
}, },
params: { isUpstream: false },
data: body, data: body,
...(options || {}), ...(options || {}),
} }
); );
} }
/** 获取服务商接口明细 GET /Interface/GetServiceProviderInterfaceById */ /** 获取服务商接口明细(已切换至通用接口明细) GET /Interface/GetInterfaceById */
export async function getInterfaceGetServiceProviderInterfaceById( export async function getInterfaceGetServiceProviderInterfaceById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象) // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getInterfaceGetServiceProviderInterfaceByIdParams, params: API.getInterfaceGetServiceProviderInterfaceByIdParams,
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<API.ServiceProviderInterfaceOutput>( return request<any>(
`api/Interface/GetServiceProviderInterfaceById`, `api/Interface/GetInterfaceById`,
{ {
method: 'GET', method: 'GET',
params: { params: {
@ -73,36 +74,35 @@ export async function postInterfaceGetServiceProviderInterfaceTreeListAsync(
}); });
} }
/** 保存服务商接口 用OptionType来区分操作目的,1:新增,2:删除,3:修改 /** 保存服务商接口(已切换至通用保存接口) 用OptionType来区分操作目的,1:新增,2:删除,3:修改
<br>tips:新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系 POST /Interface/SaveServiceProviderInterface */ <br>tips:新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系 POST /Interface/SaveInterface */
export async function postInterfaceSaveServiceProviderInterface( export async function postInterfaceSaveServiceProviderInterface(
body: API.ServiceProviderInterfaceInput, body: API.ServiceProviderInterfaceInput,
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<number>(`api/Interface/SaveServiceProviderInterface`, { return request<any>(`api/Interface/SaveInterface`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json-patch+json', 'Content-Type': 'application/json-patch+json',
}, },
data: body, // 透传原有参数,并强制 isUpstream = false
data: { ...(body as any), isUpstream: false },
...(options || {}), ...(options || {}),
}); });
} }
/** 服务商接口分页列表 POST /Interface/ServiceProviderInterfacePaginatedList */ /** 服务商接口分页列表(已切换至通用接口列表) POST /Interface/InterfacePaginatedList */
export async function postInterfaceServiceProviderInterfacePaginatedList( export async function postInterfaceServiceProviderInterfacePaginatedList(
body: API.ServiceProviderInterfacePaginatedInputObjectValue, body: API.ServiceProviderInterfacePaginatedInputObjectValue,
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<API.ServiceProviderInterfacePaginatedOutputValueObjectPagedResult>( return request<any>(`api/Interface/InterfacePaginatedList`, {
`api/Interface/ServiceProviderInterfacePaginatedList`, method: 'POST',
{ headers: {
method: 'POST', 'Content-Type': 'application/json-patch+json',
headers: { },
'Content-Type': 'application/json-patch+json', // 透传原有查询条件,并强制 isUpstream = false
}, data: { ...(body as any), isUpstream: false },
data: body, ...(options || {}),
...(options || {}), });
}
);
} }

View File

@ -2,29 +2,30 @@
/* eslint-disable */ /* eslint-disable */
import request from '@/utils/request'; import request from '@/utils/request';
/** 批量删除系统接口 POST /Interface/BatchDeleteSystemInterfaceByIds */ /** 批量删除系统接口(切换至通用删除接口) POST /Interface/BatchDeleteInterfaceByIds */
export async function postInterfaceBatchDeleteSystemInterfaceByIds( export async function postInterfaceBatchDeleteSystemInterfaceByIds(
body: number[], body: number[],
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<boolean>(`api/Interface/BatchDeleteSystemInterfaceByIds`, { return request<boolean>(`api/Interface/BatchDeleteInterfaceByIds`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json-patch+json', 'Content-Type': 'application/json-patch+json',
}, },
params: { isUpstream: true },
data: body, data: body,
...(options || {}), ...(options || {}),
}); });
} }
/** 获取系统接口明细 GET /Interface/GetSystemInterfaceById */ /** 获取系统接口明细(已切换至通用接口明细) GET /Interface/GetInterfaceById */
export async function getInterfaceGetSystemInterfaceById( export async function getInterfaceGetSystemInterfaceById(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象) // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.getInterfaceGetSystemInterfaceByIdParams, params: API.getInterfaceGetSystemInterfaceByIdParams,
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<API.SystemInterfaceOutput>( return request<any>(
`api/Interface/GetSystemInterfaceById`, `api/Interface/GetInterfaceById`,
{ {
method: 'GET', method: 'GET',
params: { params: {
@ -66,36 +67,35 @@ export async function postInterfaceGetSystemInterfaceTreeListAsync(
); );
} }
/** 保存系统接口 用OptionType来区分操作目的,1:新增,2:删除,3:修改 /** 保存系统接口(已切换至通用保存接口) 用OptionType来区分操作目的,1:新增,2:删除,3:修改
<br>注意!新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系 POST /Interface/SaveSystemInterface */ <br>注意!新增时,参数id由调用者伪造,以表现层级关系,不能小于1,你必须真实的表达id和pid的关系 POST /Interface/SaveInterface */
export async function postInterfaceSaveSystemInterface( export async function postInterfaceSaveSystemInterface(
body: API.SystemInterfaceInput, body: API.SystemInterfaceInput,
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<any>(`api/Interface/SaveSystemInterface`, { return request<any>(`api/Interface/SaveInterface`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json-patch+json', 'Content-Type': 'application/json-patch+json',
}, },
data: body, // 透传原有参数,并强制 isUpstream = true
data: { ...(body as any), isUpstream: true },
...(options || {}), ...(options || {}),
}); });
} }
/** 系统接口分页列表 POST /Interface/SystemInterfacePaginatedList */ /** 系统接口分页列表(已切换至通用接口列表) POST /Interface/InterfacePaginatedList */
export async function postInterfaceSystemInterfacePaginatedList( export async function postInterfaceSystemInterfacePaginatedList(
body: API.SystemInterfacePaginatedInputObjectValue, body: API.SystemInterfacePaginatedInputObjectValue,
options?: { [key: string]: any } options?: { [key: string]: any }
) { ) {
return request<API.SystemInterfacePaginatedOutputValueObjectPagedResult>( return request<any>(`api/Interface/InterfacePaginatedList`, {
`api/Interface/SystemInterfacePaginatedList`, method: 'POST',
{ headers: {
method: 'POST', 'Content-Type': 'application/json-patch+json',
headers: { },
'Content-Type': 'application/json-patch+json', // 透传原有查询条件,并强制 isUpstream = true
}, data: { ...(body as any), isUpstream: true },
data: body, ...(options || {}),
...(options || {}), });
}
);
} }

View File

@ -41,7 +41,10 @@
}; };
}, },
}, },
beforeSubmit: {
type: Function as PropType<(data: any) => any>,
default: null,
},
}); });
const formRef = ref<null>(null); const formRef = ref<null>(null);
@ -145,7 +148,13 @@
console.log(formValue, 'formValue'); console.log(formValue, 'formValue');
// 清理表单数据,避免空字符串传递给API // 清理表单数据,避免空字符串传递给API
const cleanedFormValue = cleanFormData(formValue); let cleanedFormValue = cleanFormData(formValue);
// 如果有beforeSubmit钩子,执行数据转换
if (props.beforeSubmit && isFunction(props.beforeSubmit)) {
cleanedFormValue = props.beforeSubmit(cleanedFormValue) || cleanedFormValue;
}
const form = { ...formData.value, ...cleanedFormValue }; const form = { ...formData.value, ...cleanedFormValue };
const { addApi, editApi, apiParams } = props; const { addApi, editApi, apiParams } = props;
@ -207,7 +216,11 @@
<div class="max-h-50vh"> <div class="max-h-50vh">
<slot name="BasicMsgTop" /> <slot name="BasicMsgTop" />
<FormPro v-bind="formProps" ref="formRef" /> <FormPro v-bind="formProps" ref="formRef">
<template v-for="(_, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData" />
</template>
</FormPro>
</div> </div>
</ModalPro> </ModalPro>
</template> </template>

View File

@ -6,10 +6,8 @@
import { Message, Modal } from '@arco-design/web-vue'; import { Message, Modal } from '@arco-design/web-vue';
import { cloneDeep, random } from 'lodash'; import { cloneDeep, random } from 'lodash';
import FormPro from '@/components/FormPro/index.vue'; import FormPro from '@/components/FormPro/index.vue';
import { import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
getInterfaceGetServiceProviderInterfaceById, import { postInterfaceSaveServiceProviderInterface } from '@/api/InterfaceServices/serviceProviderInterface';
postInterfaceSaveServiceProviderInterface,
} from '@/api/InterfaceServices/serviceProviderInterface';
import type { import type {
InterfaceParameterOutputValueObject, InterfaceParameterOutputValueObject,
ServiceProviderInterfaceInput, ServiceProviderInterfaceInput,
@ -550,7 +548,7 @@
const getInterfaceDetail = async (id: number) => { const getInterfaceDetail = async (id: number) => {
try { try {
loading.value = true; loading.value = true;
const res = await getInterfaceGetServiceProviderInterfaceById({ id }); const res = await getInterfaceGetInterfaceById({ id });
if (res) { if (res) {
Object.assign(tableForm, { Object.assign(tableForm, {
interfaceName: res.name || '', interfaceName: res.name || '',

View File

@ -12,10 +12,8 @@ import {
postParameterParse, postParameterParse,
postParameterValidateParameter, postParameterValidateParameter,
} from '@/api/ParameterServices/parameter'; } from '@/api/ParameterServices/parameter';
import { import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
getInterfaceGetSystemInterfaceById, import { postInterfaceSaveSystemInterface } from '@/api/InterfaceServices/systemInterface';
postInterfaceSaveSystemInterface,
} from '@/api/InterfaceServices/systemInterface';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary'; import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
import { paramColumns } from './config/interface-config'; import { paramColumns } from './config/interface-config';
@ -204,7 +202,7 @@ const init = async () => {
flag.value = true; flag.value = true;
} }
const { data } = await getInterfaceGetSystemInterfaceById({ id }); const { data } = await getInterfaceGetInterfaceById({ id });
// Set form data // Set form data
Object.assign(formData, data); Object.assign(formData, data);

View File

@ -4,7 +4,9 @@
import { IconDragDotVertical } from '@arco-design/web-vue/es/icon'; import { IconDragDotVertical } from '@arco-design/web-vue/es/icon';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';
import XEUtils from 'xe-utils'; import XEUtils from 'xe-utils';
import { getInterfaceGetSystemInterfaceById } from '@/api/InterfaceServices/systemInterface'; import { ref, reactive, nextTick, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
import { import {
getParameterGetParameterList, getParameterGetParameterList,
@ -22,7 +24,7 @@
import TablePro from '@/components/TablePro/index.vue'; import TablePro from '@/components/TablePro/index.vue';
import ModalPro from '@/components/ModalPro/index.vue'; import ModalPro from '@/components/ModalPro/index.vue';
import SelectPro from '@/components/SelectPro/index.vue'; import SelectPro from '@/components/SelectPro/index.vue';
import { translateTitle as t } from '@/utils/i18n'; import { useI18n } from 'vue-i18n';
import { import {
entrancePrarm, entrancePrarm,
exitPrarm, exitPrarm,
@ -31,6 +33,7 @@
const $modal = Modal; const $modal = Modal;
const $message = Message; const $message = Message;
const { t } = useI18n();
defineOptions({ defineOptions({
name: 'EntranceArgumentsMap', name: 'EntranceArgumentsMap',
@ -135,7 +138,7 @@
editConfig: { trigger: 'click', mode: 'row' }, editConfig: { trigger: 'click', mode: 'row' },
showIndex: false, showIndex: false,
}, },
data: [], data: [] as any[],
}); });
const dialogTableRules = ref<VxeTablePropTypes.EditRules>({ const dialogTableRules = ref<VxeTablePropTypes.EditRules>({
name: [ name: [
@ -248,7 +251,7 @@
async function getInterfaceGetSystemInterface() { async function getInterfaceGetSystemInterface() {
const id = Number(props.addId); const id = Number(props.addId);
const { data } = (await getInterfaceGetSystemInterfaceById({ const { data } = (await getInterfaceGetInterfaceById({
id: id || Number(props.upStreamId), id: id || Number(props.upStreamId),
})) as unknown as TypeAs; })) as unknown as TypeAs;
dialogTableProps.data = data.inParameterList; dialogTableProps.data = data.inParameterList;
@ -257,7 +260,7 @@
// onMounted(async () => { // onMounted(async () => {
// const id = Number(props.addId) // const id = Number(props.addId)
// const { data } = (await getInterfaceGetSystemInterfaceById({ // const { data } = (await getInterfaceGetInterfaceById({
// id: id || Number(props.upStreamId), // id: id || Number(props.upStreamId),
// })) as unknown as TypeAs // })) as unknown as TypeAs
// dialogTableProps.data = data.inParameterList // dialogTableProps.data = data.inParameterList
@ -327,17 +330,17 @@
type CommonParameterInputType = API.ParameterInput & { id: number }; type CommonParameterInputType = API.ParameterInput & { id: number };
dialogTableRef.value?.validate().then(async (res: boolean) => { dialogTableRef.value?.validate().then(async (res: boolean) => {
if (res) { if (res) {
registerMethods.changeOkLoading(true); (registerMethods as any).changeOkLoading(true);
let fc = cloneDeep(dialogTableProps.data) as CommonParameterInputType[]; let fc = cloneDeep(dialogTableProps.data) as CommonParameterInputType[];
parameterList.value.forEach((item: any) => { parameterList.value.forEach((item: any) => {
const idx = fc.findIndex((i) => i.id === item.id); const idx = fc.findIndex((i) => i.id === item.id);
if (idx > -1) fc[idx] = item; if (idx > -1) fc[idx] = item;
else fc.push(item); else fc.push(item);
if (backSort.value?.length) { if (backSortArr?.length) {
const index = backSort.value?.findIndex((i) => i.id === item.id); const index = backSortArr?.findIndex((i) => i.id === item.id);
console.log(item, 'index'); console.log(item, 'index');
if (index > -1) backSort.value[index].optionType = item?.optionType; if (index > -1) backSortArr[index].optionType = item?.optionType;
} }
}); });
fc.forEach((el: any) => { fc.forEach((el: any) => {
@ -345,7 +348,7 @@
el.children = undefined; el.children = undefined;
el._X_ROW_CHILD = undefined; el._X_ROW_CHILD = undefined;
}); });
backSort.value.forEach((el: any) => { backSortArr.forEach((el: any) => {
el.Id = undefined; el.Id = undefined;
el.children = undefined; el.children = undefined;
el._X_ROW_CHILD = undefined; el._X_ROW_CHILD = undefined;
@ -358,15 +361,15 @@
isRequired: !!item.isRequired, isRequired: !!item.isRequired,
}; };
}); });
const { code } = await postParameterSave({ const { code } = (await postParameterSave({
isInPara: true, isInPara: true,
interfaceId: props.interfaceMapId interfaceId: props.interfaceMapId
? Number(props.upStreamId) ? Number(props.upStreamId)
: Number(props.addId), : Number(props.addId),
parameterList: isIDReturn(props.id, fc).outParameterList, parameterList: isIDReturn(props.id, fc).outParameterList,
}); })) as any;
if (code === '200') { if (code === '200') {
registerMethods.changeOkLoading(false); (registerMethods as any).changeOkLoading(false);
$message.success('保存成功'); $message.success('保存成功');
savePort(isIDReturn(props.id, fc).outParameterList); savePort(isIDReturn(props.id, fc).outParameterList);
dialogVisible.value = false; dialogVisible.value = false;
@ -376,7 +379,7 @@
getInterfaceGetSystemInterface(); getInterfaceGetSystemInterface();
tableRef.value?.reload(); tableRef.value?.reload();
} else { } else {
registerMethods.changeOkLoading(false); (registerMethods as any).changeOkLoading(false);
$message.error('保存失败'); $message.error('保存失败');
} }
} }
@ -401,11 +404,11 @@
function isIDReturn(id: any, fc: any[]) { function isIDReturn(id: any, fc: any[]) {
if (id) { if (id) {
return { return {
outParameterList: backSort.value.length ? backSort.value : fc.reverse(), outParameterList: backSortArr.length ? backSortArr : fc.reverse(),
}; };
} }
return { return {
outParameterList: fc.length ? fc.reverse() : backSort.value, outParameterList: fc.length ? fc.reverse() : backSortArr,
}; };
} }
@ -429,8 +432,8 @@
if ( if (
tableRef.value tableRef.value
?.getTableData() ?.getTableData()
.tableData.some( .tableData.some(
(node) => node.isRequired === true && !node.mapId && !node.fixedValue (node: any) => node.isRequired === true && !node.mapId && !node.fixedValue
) )
) )
return $message.error( return $message.error(
@ -438,7 +441,7 @@
); );
// const arr: Array<object> = [] // const arr: Array<object> = []
tableRef.value?.getTableData().tableData.forEach((item) => { tableRef.value?.getTableData().tableData.forEach((item: any) => {
const obj: Indexable = {}; const obj: Indexable = {};
obj.interfaceMapDetailId = item.interfaceMapDetailId; obj.interfaceMapDetailId = item.interfaceMapDetailId;
obj.mappedParaId = item.mapId; obj.mappedParaId = item.mapId;
@ -569,7 +572,7 @@
let sortable: any = null; let sortable: any = null;
// 参数拖拽 // 参数拖拽
// 返回参数排序 // 返回参数排序
const backSort = ref<any[]>([]); let backSortArr: any[] = [];
function restore( function restore(
wrapperElem: any, wrapperElem: any,
targetTrElem: any, targetTrElem: any,
@ -594,7 +597,7 @@
function isDraggedDown(targetTrElem: any, alternativeTrElem: any) { function isDraggedDown(targetTrElem: any, alternativeTrElem: any) {
const targetTrElemId = targetTrElem.getAttribute('rowid'); const targetTrElemId = targetTrElem.getAttribute('rowid');
const alternativeTrElemId = alternativeTrElem.getAttribute('rowid'); const alternativeTrElemId = alternativeTrElem.getAttribute('rowid');
const treeArray = XEUtils.toTreeArray(dialogTableProps.data); // 按先序遍历输出树节点(与表格中从上到下行的排列顺序一致) const treeArray = XEUtils.toTreeArray(dialogTableProps.data) as any[]; // 按先序遍历输出树节点(与表格中从上到下行的排列顺序一致)
return treeArray.some((value, index) => { return treeArray.some((value, index) => {
// 若targetTrElem拖拽前在alternativeTrElem之前(即向下拖拽),返回true // 若targetTrElem拖拽前在alternativeTrElem之前(即向下拖拽),返回true
if ( if (
@ -666,7 +669,7 @@
console.log(tableTreeData, 'tableTreeData'); console.log(tableTreeData, 'tableTreeData');
const targetRowNode = xTable?.getRowNode(targetTrElem); const targetRowNode = xTable?.getRowNode(targetTrElem);
const selfRow = targetRowNode?.item; const selfRow = targetRowNode?.item;
const selfNode = XEUtils.findTree( const selfNode: any = XEUtils.findTree(
tableTreeData, tableTreeData,
(row) => row === selfRow, (row) => row === selfRow,
options options
@ -678,14 +681,14 @@
const prevRow = prevRowNode?.item; const prevRow = prevRowNode?.item;
let preTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = false; let preTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = false;
const preNode = xe.findTree( const preNode: any = xe.findTree(
tableTreeData, tableTreeData,
(row) => { (row) => {
return row.id === Number(prevTrElem.getAttribute('rowid')); return row.id === Number(prevTrElem.getAttribute('rowid'));
}, },
options options
); );
const preRow = preNode?.item; const preRow: any = preNode?.item;
console.log(selfRow, 'selfRow'); console.log(selfRow, 'selfRow');
console.log(preRow, 'preRow'); console.log(preRow, 'preRow');
if (selfRow?.pId === preRow?.pId || selfRow?.pId === preRow?.id) if (selfRow?.pId === preRow?.pId || selfRow?.pId === preRow?.id)
@ -717,7 +720,7 @@
const ac = tableTreeData.find((i) => i.id === pidData.id); const ac = tableTreeData.find((i) => i.id === pidData.id);
selfNode.items.unshift(selfRow); // 在数组头部新增节点 selfNode.items.unshift(selfRow); // 在数组头部新增节点
ac.children = []; ac.children = [];
selfNode.items.forEach((item) => { selfNode.items.forEach((item: any) => {
ac.children.push(item); ac.children.push(item);
}); });
console.log(selfNode.items, 'selfNode.itemsselfNode.items'); console.log(selfNode.items, 'selfNode.itemsselfNode.items');
@ -747,7 +750,7 @@
let nextTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = true; let nextTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = true;
console.log(nextTrElem, 'nextTrElem'); console.log(nextTrElem, 'nextTrElem');
if (nextTrElem) { if (nextTrElem) {
const nextNode = xe.findTree( const nextNode: any = xe.findTree(
tableTreeData, tableTreeData,
(row) => { (row) => {
return ( return (
@ -756,7 +759,7 @@
}, },
options options
); );
const nextRow = nextNode.item; const nextRow: any = nextNode.item;
console.log(nextRow, 'nextRow'); console.log(nextRow, 'nextRow');
console.log(selfRow, 'selfRow'); console.log(selfRow, 'selfRow');
console.log(prevRow, 'prevRow'); console.log(prevRow, 'prevRow');
@ -795,7 +798,7 @@
while (oldIndex < wrapperElem.children.length) { while (oldIndex < wrapperElem.children.length) {
const trElem = wrapperElem.children[oldIndex]; const trElem = wrapperElem.children[oldIndex];
const isSiblingNodes = selfNode.items.some( const isSiblingNodes = selfNode.items.some(
(value) => value.id === trElem.getAttribute('rowid') (value: any) => value.id === trElem.getAttribute('rowid')
); );
if (isSiblingNodes) { if (isSiblingNodes) {
// 如果当前节点是节点拖拽前的兄弟节点,说明子节点已经全部访问完了, 停止迭代 // 如果当前节点是节点拖拽前的兄弟节点,说明子节点已经全部访问完了, 停止迭代
@ -824,18 +827,18 @@
const newArr = tableTreeData?.filter((item) => !item.pId) || []; const newArr = tableTreeData?.filter((item) => !item.pId) || [];
// console.log(newArr, 'asdasddsa') // console.log(newArr, 'asdasddsa')
// console.log(flattenArray(newArr)) // console.log(flattenArray(newArr))
// backSort.value = flattenArray(newArr) // backSortArr = flattenArray(newArr)
// 如果变动了树层级,需要刷新数据 // 如果变动了树层级,需要刷新数据
dialogTableProps.data = [...flattenArray(newArr)]; dialogTableProps.data = [...flattenArray(newArr)];
setTimeout(() => { setTimeout(() => {
backSort.value = flattenArray(newArr).map((item) => { backSortArr = (flattenArray(newArr).map((item: any) => {
return { return {
...item, ...item,
sort: getRowSeq(item, dialogTableRef.value), sort: getRowSeq(item, dialogTableRef.value),
}; };
}); }) as any[]);
console.log(backSort.value); console.log(backSortArr);
}, 300); }, 300);
}, },
} }
@ -1065,6 +1068,7 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
margin-bottom: 12px;
} }
.main-box { .main-box {
@ -1080,4 +1084,13 @@
.cursor-move { .cursor-move {
cursor: move; cursor: move;
} }
/* 提升上下行的垂直间距,避免行与行过于贴近 */
:deep(.vxe-table .vxe-body--row > td) {
padding-top: 8px !important;
padding-bottom: 8px !important;
}
:deep(.vxe-table .vxe-body--row) {
height: 44px !important;
}
</style> </style>

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { VxeTablePropTypes } from 'vxe-table' import type { VxeTablePropTypes } from 'vxe-table'
import type { TableProRef } from '@/components/TablePro/types' import type { TableProRef } from '@/components/TablePro/types'
import { getInterfaceGetSystemInterfaceById } from '@/api/InterfaceServices/systemInterface' import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface'
import { getGetMapList } from '@/api/InterfaceMappingServices/interfaceMap' import { getGetMapList } from '@/api/InterfaceMappingServices/interfaceMap'
import { import {
@ -292,7 +292,7 @@ type TypeAs = {
async function getInterfaceGetSystemInterface() { async function getInterfaceGetSystemInterface() {
const id = Number(props.addId) const id = Number(props.addId)
const { data } = (await getInterfaceGetSystemInterfaceById({ const { data } = (await getInterfaceGetInterfaceById({
id: Number(props.upStreamId) || id, id: Number(props.upStreamId) || id,
})) as unknown as TypeAs })) as unknown as TypeAs
dialogTableProps.data = data.outParameterList dialogTableProps.data = data.outParameterList
@ -300,7 +300,7 @@ async function getInterfaceGetSystemInterface() {
// onMounted(async () => { // onMounted(async () => {
// const id = Number(props.addId) // const id = Number(props.addId)
// const { data } = (await getInterfaceGetSystemInterfaceById({ // const { data } = (await getInterfaceGetInterfaceById({
// id: Number(props.upStreamId) || id, // id: Number(props.upStreamId) || id,
// })) as unknown as TypeAs // })) as unknown as TypeAs
// dialogTableProps.data = data.outParameterList // dialogTableProps.data = data.outParameterList

View File

@ -1,4 +1,5 @@
import { FormItemType } from '../../types'; import { FormItemType } from '../../types';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
// 表单配置 // 表单配置
export const formItems: FormItemType[] = [ export const formItems: FormItemType[] = [
@ -6,7 +7,7 @@ export const formItems: FormItemType[] = [
comp: 'a-input', comp: 'a-input',
field: 'name', field: 'name',
label: '接口名', label: '接口名',
span: 4, span: 6,
compProps: { compProps: {
placeholder: '请填写接口中文名称', placeholder: '请填写接口中文名称',
}, },
@ -15,7 +16,7 @@ export const formItems: FormItemType[] = [
comp: 'a-input', comp: 'a-input',
field: 'code', field: 'code',
label: 'Code', label: 'Code',
span: 4, span: 6,
required: true, required: true,
compProps: { compProps: {
placeholder: '请填写接口code', placeholder: '请填写接口code',
@ -25,7 +26,7 @@ export const formItems: FormItemType[] = [
comp: 'SelectPro', comp: 'SelectPro',
field: 'isReturnMessage', field: 'isReturnMessage',
label: '是否返回源报文', label: '是否返回源报文',
span: 4, span: 6,
compProps: { compProps: {
placeholder: '是否返回源报文', placeholder: '是否返回源报文',
showHeader: false, showHeader: false,
@ -38,11 +39,95 @@ export const formItems: FormItemType[] = [
], ],
}, },
}, },
{
comp: 'SelectPro',
field: 'requestProtocol',
label: '请求协议',
span: 6,
compProps: {
placeholder: '请选择请求协议',
api: getDictionaryGetList,
extra: { type: 'RequestProtocol' },
labelKeys: ['value'],
idKey: 'key',
isPage: false,
showHeader: false,
},
},
{
comp: 'SelectPro',
field: 'requestMethod',
label: '请求方式',
span: 6,
compProps: {
placeholder: '请选择请求方式',
api: getDictionaryGetList,
extra: { type: 'RequestMethod' },
labelKeys: ['value'],
idKey: 'key',
isPage: false,
showHeader: false,
},
},
{
comp: 'a-input',
field: 'requestAddress',
label: '请求地址',
span: 6,
compProps: {
placeholder: '例: http://xx/api/CreateOrder',
},
},
{
comp: 'SelectPro',
field: 'contentType',
label: 'Content-Type',
span: 6,
compProps: {
placeholder: '请选择Content-Type',
api: getDictionaryGetList,
extra: { type: 'ContentType' },
labelKeys: ['value'],
idKey: 'key',
isPage: false,
showHeader: false,
},
},
{
comp: 'SelectPro',
field: 'responseContentType',
label: 'Response-Content-Type',
span: 6,
compProps: {
placeholder: '请选择Response-Content-Type',
api: getDictionaryGetList,
extra: { type: 'ResponseContentType' },
labelKeys: ['value'],
idKey: 'key',
isPage: false,
showHeader: false,
},
},
{
comp: 'a-input-number',
field: 'qps',
label: 'QPS',
span: 6,
compProps: {
min: 0,
precision: 0,
controlsPosition: 'right',
valueOnClear: 0,
controls: false,
placeholder: 'QPS',
style: { width: '100%' },
},
},
{ {
comp: 'SelectPro', comp: 'SelectPro',
field: 'category', field: 'category',
label: '接口分组', label: '接口分组',
span: 4, span: 6,
compProps: { compProps: {
placeholder: '请选择接口分组', placeholder: '请选择接口分组',
showHeader: false, showHeader: false,
@ -61,7 +146,7 @@ export const formItems: FormItemType[] = [
comp: 'a-input', comp: 'a-input',
field: 'description', field: 'description',
label: '接口描述', label: '接口描述',
span: 8, span: 6,
compProps: { compProps: {
placeholder: '请输入接口备注', placeholder: '请输入接口备注',
allowClear: true, allowClear: true,

View File

@ -496,6 +496,14 @@ import InterfaceConfig from './interface-config.vue';
return; return;
} }
} }
// 如果切换到接口明细tab,检查是否选择了接口
if (tabName === 'detail') {
if (!selectedInterface.value) {
$baseMessage('请选择左侧接口', 'warning');
activeContentTab.value = 'mapping';
return;
}
}
} }
// 监听第一个映射的变化,如果改变了服务商,清空后续映射 // 监听第一个映射的变化,如果改变了服务商,清空后续映射
@ -809,6 +817,8 @@ import InterfaceConfig from './interface-config.vue';
const MapServiceProviderRef = ref<any>(); const MapServiceProviderRef = ref<any>();
const loadingSubmit = ref(false); const loadingSubmit = ref(false);
const interfaceDetailModalRef = ref<any>(); const interfaceDetailModalRef = ref<any>();
const interfaceConfigRef = ref<any>();
const detailRefreshKey = ref(0);
const selectedProvider = ref<any>(); const selectedProvider = ref<any>();
function saveModelEnter() { function saveModelEnter() {
@ -873,15 +883,8 @@ import InterfaceConfig from './interface-config.vue';
function handleInterfaceDetailCancel() { function handleInterfaceDetailCancel() {
// 取消编辑,重新加载接口详情 // 取消编辑,重新加载接口详情
if (selectedInterface.value && interfaceDetailModalRef.value) { if (selectedInterface.value) {
nextTick(() => { detailRefreshKey.value++;
interfaceDetailModalRef.value.init({
id: selectedInterface.value.id,
serviceProviderId: selectedProvider.value?.id,
serviceProviderName: selectedProvider.value?.name,
mode: 'edit'
});
});
} }
} }
// 点击跳转 // 点击跳转
@ -1213,14 +1216,6 @@ import InterfaceConfig from './interface-config.vue';
</div> </div>
</a-button> </a-button>
<template #content> <template #content>
<a-doption value="edit" :data="getNodeData(key)" @click="compileClick(getNodeData(key))">
<icon-edit />
修改
</a-doption>
<a-doption value="map" :data="getNodeData(key)" @click="newmapClick(getNodeData(key))">
<icon-plus />
映射
</a-doption>
<a-doption value="delete" :data="getNodeData(key)" @click="deleteInterfaceClick(getNodeData(key))"> <a-doption value="delete" :data="getNodeData(key)" @click="deleteInterfaceClick(getNodeData(key))">
<icon-delete /> <icon-delete />
删除 删除
@ -1340,6 +1335,36 @@ import InterfaceConfig from './interface-config.vue';
/> />
</div> </div>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="detail" title="接口明细" :disabled="!selectedInterface">
<div class="mapping-split">
<div class="mapping-split-content">
<div class="pane-body">
<div class="pane-header">
<div class="pane-header-actions">
<a-space :size="8">
<a-button size="small" @click="handleInterfaceDetailCancel">取消</a-button>
<a-button size="small" type="primary" @click="interfaceConfigRef?.submit?.()">确定</a-button>
</a-space>
</div>
</div>
<div class="mapping-content">
<div v-if="selectedInterface" class="h-full w-full">
<InterfaceConfig
:key="`${selectedInterface?.id}-${detailRefreshKey}`"
ref="interfaceConfigRef"
:modal-mode="true"
:modal-id="selectedInterface?.id"
@saved="() => { /* 保留在当前tab,按需刷新左侧树 */ }"
/>
</div>
<div v-else class="empty-state">
<a-empty description="请选择左侧接口查看接口明细" />
</div>
</div>
</div>
</div>
</div>
</a-tab-pane>
</a-tabs> </a-tabs>
</div> </div>
</div> </div>
@ -1887,6 +1912,7 @@ import InterfaceConfig from './interface-config.vue';
} }
.pane-header .search-box { display: flex; align-items: center; gap: 8px; } .pane-header .search-box { display: flex; align-items: center; gap: 8px; }
.pane-header .search-actions { display: flex; gap: 4px; } .pane-header .search-actions { display: flex; gap: 4px; }
.pane-header-actions { margin-left: auto; display: flex; }
.pane-header :deep(.arco-input-wrapper) { height: 28px !important; } .pane-header :deep(.arco-input-wrapper) { height: 28px !important; }
.pane-header-actions :deep(.arco-btn) { height: 28px !important; padding: 0 10px; } .pane-header-actions :deep(.arco-btn) { height: 28px !important; padding: 0 10px; }
.action-icon-btn { width: 28px; height: 28px !important; padding: 0; display: flex; align-items: center; justify-content: center; color: #8c8c8c; border: 1px solid transparent; border-radius: 4px; font-size: 16px; font-weight: bold; } .action-icon-btn { width: 28px; height: 28px !important; padding: 0; display: flex; align-items: center; justify-content: center; color: #8c8c8c; border: 1px solid transparent; border-radius: 4px; font-size: 16px; font-weight: bold; }

View File

@ -12,10 +12,8 @@
postParameterParse, postParameterParse,
postParameterValidateParameter, postParameterValidateParameter,
} from '@/api/ParameterServices/parameter'; } from '@/api/ParameterServices/parameter';
import { import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
getInterfaceGetSystemInterfaceById, import { postInterfaceSaveSystemInterface } from '@/api/InterfaceServices/systemInterface';
postInterfaceSaveSystemInterface,
} from '@/api/InterfaceServices/systemInterface';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary'; import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
import type { RouteLocationNormalizedLoaded, Router } from 'vue-router'; import type { RouteLocationNormalizedLoaded, Router } from 'vue-router';
import { $baseMessage, $baseConfirm } from '@/utils'; import { $baseMessage, $baseConfirm } from '@/utils';
@ -1335,7 +1333,7 @@
} }
try { try {
const response = await getInterfaceGetSystemInterfaceById({ const response = await getInterfaceGetInterfaceById({
id, id,
}); });
@ -1488,11 +1486,12 @@
<div class="section"> <div class="section">
<div class="section-content"> <div class="section-content">
<FormPro <FormPro
class="interface-form"
ref="refSearchForm" ref="refSearchForm"
v-model="tableForm" v-model="tableForm"
:button-config="{ showBtn: false }" :button-config="{ showBtn: false }"
:default-span="5" :default-span="6"
:row-gutter="8" :row-gutter="16"
:form-layout="'inline'" :form-layout="'inline'"
:item-list="formItems" :item-list="formItems"
:label-col-props="{ :label-col-props="{
@ -1896,6 +1895,25 @@
overflow: auto; overflow: auto;
} }
/* 表单视觉间距与一致性优化 */
:deep(.interface-form.arco-form-inline) {
column-gap: 16px;
row-gap: 12px;
}
:deep(.interface-form .arco-form-item) {
margin-right: 0 !important;
margin-bottom: 12px !important;
}
:deep(.interface-form .arco-input-wrapper),
:deep(.interface-form .arco-select-view),
:deep(.interface-form .arco-input-number),
:deep(.interface-form .arco-textarea-wrapper) {
height: 32px;
}
:deep(.interface-form .arco-textarea-wrapper) {
min-height: 32px;
}
.section { .section {
background-color: var(--color-bg-2); background-color: var(--color-bg-2);
border-radius: 4px; border-radius: 4px;

View File

@ -23,7 +23,7 @@
} }
return response.json(); return response.json();
}; };
import { getInterfaceGetSystemInterfaceDropdownList } from '@/api/InterfaceServices/systemInterface'; import { getInterfaceGetInterfaceDropdownList } from '@/api/InterfaceServices/interface';
defineOptions({ name: 'AdhibitionList' }); defineOptions({ name: 'AdhibitionList' });
@ -50,7 +50,7 @@
const ipWhitelistText = ref('192.168.0.1;192.168.0.3;192.168.0.2'); const ipWhitelistText = ref('192.168.0.1;192.168.0.3;192.168.0.2');
// 接口相关 // 接口相关
const interfaceList = ref([]); const interfaceList = ref<any[]>([]);
// 获取应用列表 // 获取应用列表
async function loadAppList() { async function loadAppList() {
@ -72,25 +72,63 @@
// 获取接口数据 // 获取接口数据
async function loadInterfaceData() { async function loadInterfaceData() {
try { try {
const data = await getInterfaceGetSystemInterfaceDropdownList(); const resp = await getInterfaceGetInterfaceDropdownList({ isUpstream: true, serviceProviderId: 0 } as any);
// 调试日志
console.log('接口返回数据:', resp);
// 兼容多种返回格式:直接数组、data包裹、或其他格式
let groups: any[] = [];
if (Array.isArray(resp)) {
groups = resp;
} else if (resp?.data && Array.isArray(resp.data)) {
groups = resp.data;
} else if (resp?.data?.data && Array.isArray(resp.data.data)) {
groups = resp.data.data;
} else if (resp?.items && Array.isArray(resp.items)) {
groups = resp.items;
} else {
console.warn('未知的数据格式:', resp);
groups = [];
}
// 将接口数据转换为列表格式 // 将接口数据转换为列表格式
const allInterfaces = []; const allInterfaces: any[] = [];
data.forEach(group => { groups.forEach((group: any) => {
if (group.interfaces && group.interfaces.length > 0) { // 支持两种数据结构:
group.interfaces.forEach(interfaceItem => { // 1. 分组结构:{ id, groupName, interfaces: [...] }
allInterfaces.push({ // 2. 扁平结构:直接是接口数组
id: interfaceItem.id, if (group.interfaces && Array.isArray(group.interfaces)) {
name: interfaceItem.name, // 分组结构
enabled: false, // 默认未启用 group.interfaces.forEach((interfaceItem: any) => {
qps: 100 // 默认QPS if (interfaceItem && interfaceItem.id) {
}); allInterfaces.push({
id: interfaceItem.id,
name: interfaceItem.name || interfaceItem.interfaceName || '',
enabled: false,
qps: 100
});
}
});
} else if (group.id && (group.name || group.interfaceName)) {
// 扁平结构:直接是接口项
allInterfaces.push({
id: group.id,
name: group.name || group.interfaceName || '',
enabled: false,
qps: 100
}); });
} }
}); });
console.log('处理后的接口列表:', allInterfaces);
interfaceList.value = allInterfaces; interfaceList.value = allInterfaces;
if (allInterfaces.length === 0) {
console.warn('没有获取到接口数据,原始数据:', resp);
}
} catch (error) { } catch (error) {
console.error('获取接口数据失败:', error);
$baseMessage('获取接口数据失败', 'error'); $baseMessage('获取接口数据失败', 'error');
} }
} }
@ -112,6 +150,9 @@
// 设置选中的应用详情 // 设置选中的应用详情
selectedApp.value = appDetail; selectedApp.value = appDetail;
// 每次点击应用时,刷新可用接口下拉(上游、serviceProviderId=0)
await loadInterfaceData();
// 填充编辑表单 // 填充编辑表单
editForm.value = { editForm.value = {
name: appDetail.name || '', name: appDetail.name || '',
@ -120,7 +161,7 @@
isOnline: appDetail.isOnline || false isOnline: appDetail.isOnline || false
}; };
// 加载该应用的接口配置 // 加载该应用的接口配置(基于最新接口下拉数据)
loadAppInterfaces(appDetail); loadAppInterfaces(appDetail);
} catch (error) { } catch (error) {
$baseMessage('获取应用详情失败', 'error'); $baseMessage('获取应用详情失败', 'error');
@ -525,7 +566,10 @@
<h3>可用接口</h3> <h3>可用接口</h3>
</div> </div>
<div class="interfaces-table"> <div class="interfaces-table">
<table class="interface-table"> <div v-if="interfaceList.length === 0" class="empty-state">
<p>暂无可用接口</p>
</div>
<table v-else class="interface-table">
<thead> <thead>
<tr> <tr>
<th>序号</th> <th>序号</th>
@ -535,9 +579,9 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(interfaceItem, index) in interfaceList" :key="interfaceItem.id"> <tr v-for="(interfaceItem, index) in interfaceList" :key="interfaceItem.id || index">
<td>{{ index + 1 }}</td> <td>{{ index + 1 }}</td>
<td>{{ interfaceItem.name }}</td> <td>{{ interfaceItem.name || '-' }}</td>
<td> <td>
<a-switch <a-switch
v-model="interfaceItem.enabled" v-model="interfaceItem.enabled"

View File

@ -8,7 +8,7 @@
postAppUpdate, postAppUpdate,
} from '@/api/ApplicationServices/apps'; } from '@/api/ApplicationServices/apps';
import { getInterfaceGetSystemInterfaceDropdownList } from '@/api/InterfaceServices/systemInterface'; import { getInterfaceGetInterfaceDropdownList } from '@/api/InterfaceServices/interface';
import { $baseMessage } from '@/utils'; import { $baseMessage } from '@/utils';
defineOptions({ defineOptions({
@ -122,7 +122,7 @@
const { contentHeight } = useContentHeight(cardBoxRef, true, 80); const { contentHeight } = useContentHeight(cardBoxRef, true, 80);
onMounted(async () => { onMounted(async () => {
const data = await getInterfaceGetSystemInterfaceDropdownList(); const data = await getInterfaceGetInterfaceDropdownList({ isUpstream: true, serviceProviderId: 0 } as any);
dataSource.value = data.map((item) => { dataSource.value = data.map((item) => {
return { return {
id: item.id, id: item.id,

View File

@ -11,10 +11,8 @@
postParameterParse, postParameterParse,
postParameterValidateParameter, postParameterValidateParameter,
} from '@/api/ParameterServices/parameter'; } from '@/api/ParameterServices/parameter';
import { import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
getInterfaceGetServiceProviderInterfaceById, import { postInterfaceSaveServiceProviderInterface } from '@/api/InterfaceServices/serviceProviderInterface';
postInterfaceSaveServiceProviderInterface,
} from '@/api/InterfaceServices/serviceProviderInterface';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary'; import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
import { $baseMessage, $baseConfirm } from '@/utils'; import { $baseMessage, $baseConfirm } from '@/utils';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@ -370,7 +368,7 @@
if (isEditMode.value && data.id) { if (isEditMode.value && data.id) {
// 编辑模式,加载接口数据 // 编辑模式,加载接口数据
const interfaceData = await getInterfaceGetServiceProviderInterfaceById({ const interfaceData = await getInterfaceGetInterfaceById({
id: data.id, id: data.id,
}); });
refSearchForm.value?.setFormValue(interfaceData); refSearchForm.value?.setFormValue(interfaceData);
@ -464,14 +462,24 @@
tableForm.outParameterList = normalizedOut; tableForm.outParameterList = normalizedOut;
// 获取二次请求参数数据 // 获取二次请求参数数据
const formParameterList = tableRef2.value?.getTableData() || []; const formParameterList = tableRef2.value?.getTableData().fullData || [];
// 参数过滤函数,name 和 value 都不能为空(更严格,避免只传 name)
function isValidParam(param: any) {
return param
&& param.name && String(param.name).trim() !== ''
&& param.value && String(param.value).trim() !== '';
}
const filteredInList = (tableForm.inParameterList || []).filter(isValidParam);
const filteredOutList = (tableForm.outParameterList || []).filter(isValidParam);
const filteredFormList = (formParameterList || []).filter(isValidParam);
const saveData: any = { const saveData: any = {
...formData, ...formData,
serviceProviderId: serviceProviderId.value, serviceProviderId: serviceProviderId.value,
inParameterList: tableForm.inParameterList, inParameterList: filteredInList,
outParameterList: tableForm.outParameterList, outParameterList: filteredOutList,
formParameterList: formParameterList, formParameterList: filteredFormList,
}; };
// 规范化新增/编辑的标识字段 // 规范化新增/编辑的标识字段
if (isEditMode.value) { if (isEditMode.value) {
@ -638,8 +646,8 @@
try { try {
const content = tabs.value === 'Json' ? textareaJson.value : textareaXml.value; const content = tabs.value === 'Json' ? textareaJson.value : textareaXml.value;
const data = await postParameterParse({ const data = await postParameterParse({
content, parameterParseType: tabs.value === 'Json' ? 1 : 2,
type: tabs.value === 'Json' ? 'json' : 'xml', parameterContent: content,
}); });
dataList.value = data; dataList.value = data;
@ -662,8 +670,8 @@
try { try {
const content = tabs1.value === 'Json' ? textareaJson1.value : textareaXml1.value; const content = tabs1.value === 'Json' ? textareaJson1.value : textareaXml1.value;
const data = await postParameterParse({ const data = await postParameterParse({
content, parameterParseType: tabs1.value === 'Json' ? 1 : 2,
type: tabs1.value === 'Json' ? 'json' : 'xml', parameterContent: content,
}); });
dataList1.value = data; dataList1.value = data;

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { getInterfaceGetServiceProviderInterfaceDropdownList } from '@/api/InterfaceServices/serviceProviderInterface'; import { getInterfaceGetInterfaceDropdownList } from '@/api/InterfaceServices/interface';
import { import {
getServiceProviderChangeAuthInterface, getServiceProviderChangeAuthInterface,
getServiceProviderGetAuthInfo, getServiceProviderGetAuthInfo,
@ -43,11 +43,12 @@
comp: 'SelectPro', comp: 'SelectPro',
span: 6, span: 6,
compProps: { compProps: {
api: getInterfaceGetServiceProviderInterfaceDropdownList, api: getInterfaceGetInterfaceDropdownList,
labelKeys: ['name'], labelKeys: ['name'],
idKey: 'code', idKey: 'code',
isPage: false, isPage: false,
extra: { extra: {
isUpstream: false,
serviceProviderId: props.serviceProviderId, serviceProviderId: props.serviceProviderId,
}, },
onSelectChange: async (e: any) => { onSelectChange: async (e: any) => {

View File

@ -179,12 +179,10 @@
const data = await getInterfaceReturnConfigGetList({ const data = await getInterfaceReturnConfigGetList({
interfaceId: id, interfaceId: id,
}); });
listData.value = data?.map((i: any) => { listData.value = data?.map((i: any) => ({
return { ...i,
...i, value: i.value == null ? '' : String(i.value),
value: Number(i.value), }));
};
});
unref(tableRef2)?.reloadData(listData.value); unref(tableRef2)?.reloadData(listData.value);
addId.value = id; addId.value = id;

View File

@ -48,6 +48,7 @@
IconMore, IconMore,
IconDelete, IconDelete,
} from '@arco-design/web-vue/es/icon'; } from '@arco-design/web-vue/es/icon';
import ReturnConfig from './comps/ReturnConfig.vue';
defineOptions({ defineOptions({
name: 'ServiceProvidersList', name: 'ServiceProvidersList',
@ -1159,6 +1160,16 @@
} }
} }
const ReturnConfigRef = ref();
function showReturnConfig(row) {
ReturnConfigRef.value?.init(row.id);
}
function showInterfaceFixedParameters(row) {
FixedParametersRef.value?.init(selectedProvider.value.id, row.id);
}
onMounted(() => { onMounted(() => {
getAppList(); getAppList();
loadServiceProviderList(); loadServiceProviderList();
@ -1375,6 +1386,14 @@
<IconDelete style="margin-right: 8px;" /> <IconDelete style="margin-right: 8px;" />
删除 删除
</a-doption> </a-doption>
<a-doption @click="showReturnConfig(item)">
<IconSettings style="margin-right: 8px;" />
返回参数配置
</a-doption>
<a-doption @click="showInterfaceFixedParameters(item)">
<IconSettings style="margin-right: 8px;" />
固定参数配置
</a-doption>
</template> </template>
</a-dropdown> </a-dropdown>
</div> </div>
@ -1454,6 +1473,7 @@
<FixedParameters ref="FixedParametersRef" /> <FixedParameters ref="FixedParametersRef" />
<ParameterConfig v-if="parameterConfigFlagShow" ref="parameterConfigFlag" /> <ParameterConfig v-if="parameterConfigFlagShow" ref="parameterConfigFlag" />
<AccountList ref="accountList" /> <AccountList ref="accountList" />
<ReturnConfig ref="ReturnConfigRef" />
</div> </div>
</template> </template>

View File

@ -10,10 +10,8 @@
import { IconDragArrow} from '@arco-design/web-vue/es/icon'; import { IconDragArrow} from '@arco-design/web-vue/es/icon';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary'; import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
import { import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
getInterfaceGetServiceProviderInterfaceById, import { postInterfaceSaveServiceProviderInterface } from '@/api/InterfaceServices/serviceProviderInterface';
postInterfaceSaveServiceProviderInterface,
} from '@/api/InterfaceServices/serviceProviderInterface';
import { import {
postParameterSaveSort, postParameterSaveSort,
@ -1643,7 +1641,7 @@
if (!route.query.pid) return; if (!route.query.pid) return;
const id = Number(route.query.pid); const id = Number(route.query.pid);
if (id) stateVisible.value = true; if (id) stateVisible.value = true;
const data = await getInterfaceGetServiceProviderInterfaceById({ const data = await getInterfaceGetInterfaceById({
id, id,
}); });

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { IconPlus, IconEdit, IconDelete } from '@arco-design/web-vue/es/icon'; import { IconEdit, IconDelete } from '@arco-design/web-vue/es/icon';
import { IconSearch } from '@arco-design/web-vue/es/icon'; import { IconSearch } from '@arco-design/web-vue/es/icon';
import { useUserStore } from '@/store'; import { useUserStore } from '@/store';
import { $baseMessage } from '@/utils'; import { $baseMessage } from '@/utils';
@ -19,6 +19,9 @@
import { getAppGetList } from '@/api/ApplicationServices/apps'; import { getAppGetList } from '@/api/ApplicationServices/apps';
import PullScroll from './components/PullScroll.vue'; import PullScroll from './components/PullScroll.vue';
import ModalForm from '@/components/ModalForm/index.vue'; import ModalForm from '@/components/ModalForm/index.vue';
import ModalPro from '@/components/ModalPro/index.vue';
import useModal from '@/components/ModalPro/useModal';
import SelectPro from '@/components/SelectPro/index.vue';
type IDialogConfig = { type IDialogConfig = {
show: boolean; show: boolean;
@ -48,6 +51,8 @@
const modalFormLeftRef = ref(); const modalFormLeftRef = ref();
const modalFormRightRef = ref(); const modalFormRightRef = ref();
const refHeight = ref(); const refHeight = ref();
const [registerChainPullModal, { openModal: openChainPullModal, closeModal: closeChainPullModal }] = useModal() as any;
const selectedServiceProviderId = ref<number | undefined>();
const { contentHeight, calcContentHeight } = useContentHeight( const { contentHeight, calcContentHeight } = useContentHeight(
refHeight, refHeight,
@ -93,14 +98,6 @@
field: 'enContent', field: 'enContent',
title: '轨迹内容英文', title: '轨迹内容英文',
}, },
{
field: 'trackStatusValue',
title: '拉取轨迹状态',
},
{
field: 'trackPlaceValue',
title: '轨迹发生地',
},
{ {
field: 'trackKeyword', field: 'trackKeyword',
title: '拉取轨迹关键字', title: '拉取轨迹关键字',
@ -111,6 +108,10 @@
title: '拉取轨迹关键字(过滤)', title: '拉取轨迹关键字(过滤)',
width: 200, width: 200,
}, },
{
field: 'trackPlaceValue',
title: '兜底轨迹发生地',
},
{ {
field: 'action', field: 'action',
title: '操作', title: '操作',
@ -126,6 +127,162 @@
api: postGetContentPage, api: postGetContentPage,
}); });
// 返参配置的字段列表
const returnParamFields = [
{
label: '返参取值对象',
field: 'parseMethod',
comp: 'ASelect',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请选择',
style: { width: '100%', height: '40px' },
options: [
{ label: '标准返参', value: 1 },
{ label: '自定义返参', value: 2 },
],
}),
span: 8,
rules: [
{
required: true,
message: '请选择返参解析对象',
},
],
},
{
label: '订单路径',
field: 'orderPath',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入路径',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '订单号参数名',
field: 'orderNoName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹详情路径',
field: 'trackDetailsPath',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入路径',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹状态参数名',
field: 'trackStatusName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹内容代码参数名',
field: 'trackContentCodeName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹内容参数名',
field: 'trackContentName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹发生地参数名',
field: 'trackPlaceName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹时间参数名',
field: 'trackTimeName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹时区参数名',
field: 'trackTimeZoneName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹ISO时间参数名',
field: 'trackIsoTimeName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入ISO时间参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: '轨迹UTC时间参数名',
field: 'trackUtcTimeName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
{
label: 'Pod名称参数名',
field: 'podName',
comp: 'AInput',
compProps: ({ formModel }: { formModel: any }) => ({
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
disabled: formModel?.parseMethod === 1,
}),
span: 8,
},
];
const leftProps = computed(() => { const leftProps = computed(() => {
return { return {
formLayout: 'vertical', formLayout: 'vertical',
@ -135,6 +292,28 @@
style: { marginBottom: '16px' } style: { marginBottom: '16px' }
}, },
itemList: [ itemList: [
{
field: 'appKey',
label: '应用',
comp: 'SelectPro',
rules: [
{
required: true,
message: '请选择应用',
},
],
compProps: {
placeholder: '请选择应用',
size: 'large',
api: getAppGetList,
labelKeys: ['appKey'],
idKey: 'appKey',
isPage: true,
immediate: true,
onChange: handleAppChange,
},
span: 8,
},
{ {
label: '服务商', label: '服务商',
field: 'serviceProviderId', field: 'serviceProviderId',
@ -165,197 +344,169 @@
], ],
}, },
{ {
label: '定时任务(分钟)', label: '每天拉取次数',
field: 'pullInterval', field: 'dailyPullTimes',
comp: 'AInput', comp: 'AInputNumber',
compProps: { compProps: {
placeholder: '请输入大于60的正整数', placeholder: '请输入1-12的数字',
maxlength: 10,
style: { width: '100%', height: '40px' }, style: { width: '100%', height: '40px' },
min: 1,
max: 12,
precision: 0,
}, },
span: 8, span: 8,
rules: [ rules: [
{ {
required: true, required: true,
pattern: /^([6-9]\d|[1-9]\d{2,})$/, type: 'number',
message: '请输入大于60的正整数', min: 1,
max: 12,
message: '请输入1到12之间的数字',
trigger: 'change', trigger: 'change',
}, },
], ],
}, },
{ {
label: '返参解析对象', label: '客户',
field: 'parseMethod', field: 'client',
comp: 'AInput',
compProps: {
placeholder: '请输入客户',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '渠道',
field: '渠道',
comp: 'AInput',
compProps: {
placeholder: '请输入渠道',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '产品',
field: '产品',
comp: 'AInput',
compProps: {
placeholder: '请输入产品',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '拉取优先级',
field: 'pullPriority',
comp: 'ASelect', comp: 'ASelect',
compProps: { compProps: {
placeholder: '请选择', placeholder: '请选择服务器节点',
style: { width: '100%', height: '40px' }, style: { width: '100%', height: '40px' },
options: [ options: [
{ label: '接口通返参', value: 1 }, { label: '公共节点', value: '公共节点' },
{ label: '服务商返参', value: 2 }, { label: '独立节点1', value: '独立节点1' },
{ label: '独立节点2', value: '独立节点2' },
{ label: '独立节点3', value: '独立节点3' },
], ],
}, },
span: 8, span: 8,
rules: [
{
required: true,
message: '请选择返参解析对象',
},
],
}, },
{ {
label: '订单路径', label: '开始轨迹',
field: 'orderPath', field: 'startTrackContentId',
comp: 'AInput',
compProps: {
placeholder: '请输入路径',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '订单号参数名',
field: 'orderNoName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹详情路径',
field: 'trackDetailsPath',
comp: 'AInput',
compProps: {
placeholder: '请输入路径',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹状态参数名',
field: 'trackStatusName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹内容代码参数名',
field: 'trackContentCodeName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹内容参数名',
field: 'trackContentName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹发生地参数名',
field: 'trackPlaceName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹时间参数名',
field: 'trackTimeName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹时区参数名',
field: 'trackTimeZoneName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹ISO时间参数名',
field: 'trackIsoTimeName',
comp: 'AInput',
compProps: {
placeholder: '请输入ISO时间参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹UTC时间参数名',
field: 'trackUtcTimeName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: 'Pod名称参数名',
field: 'podName',
comp: 'AInput',
compProps: {
placeholder: '请输入参数名',
style: { width: '100%', height: '40px' },
},
span: 8,
},
{
label: '轨迹额外参数名',
field: 'trackExtraNames',
comp: 'TagsAdd',
compProps: {
placeholder: '请输入参数名',
stringOutput: true,
style: { width: '100%', minHeight: '40px' },
},
span: 24,
},
{
field: 'appKey',
label: '应用',
comp: 'SelectPro', comp: 'SelectPro',
rules: [ compProps: () => {
{ return {
required: true, placeholder: '请选择开始轨迹',
message: '请选择应用', isPage: true,
}, clearable: true,
], immediate: true,
compProps: { labelKeys: ['code', 'content'],
placeholder: '请选择应用', titleStrs: ['轨迹代码', '轨迹内容'],
size: 'large', idKey: 'id',
api: getAppGetList, api: postGetList,
labelKeys: ['appKey'], searchKey: 'keywords',
idKey: 'appKey', extra: { appKey: userStore.appKey, pageSize: 100 },
isPage: true, style: { width: '100%', height: '40px' },
immediate: true, };
onChange: handleAppChange,
}, },
span: 8, span: 8,
}, },
{
label: '开始睡眠多久/小时',
field: 'continuePullDays',
comp: 'AInputNumber',
compProps: {
placeholder: '请输入1到48的整数',
style: { width: '100%', height: '40px' },
min: 1,
max: 14,
precision: 0,
},
span: 8,
rules: [
{
required: false,
type: 'number',
min: 1,
max: 48,
message: '请输入1到48之间的整数',
trigger: 'change',
},
],
},
{
label: '结束轨迹',
field: 'endTrackContentId',
comp: 'SelectPro',
compProps: () => {
return {
placeholder: '请选择结束轨迹',
isPage: true,
clearable: true,
immediate: true,
labelKeys: ['code', 'content'],
titleStrs: ['轨迹代码', '轨迹内容'],
idKey: 'id',
api: postGetList,
searchKey: 'keywords',
extra: { appKey: userStore.appKey, pageSize: 100 },
style: { width: '100%', height: '40px' },
};
},
span: 8,
},
{
label: '结束继续拉取多久/天',
field: 'continuePullDays',
comp: 'AInputNumber',
compProps: {
placeholder: '请输入1-14的整数',
style: { width: '100%', height: '40px' },
min: 1,
max: 14,
precision: 0,
},
span: 8,
rules: [
{
required: false,
type: 'number',
min: 1,
max: 14,
message: '请输入1到14之间的整数',
trigger: 'change',
},
],
},
{
field: 'returnParamConfig',
label: '',
comp: 'slot',
span: 24,
hideLabel: true,
},
], ],
}; };
}); });
@ -368,7 +519,7 @@
}; };
const install = { const install = {
label: `轨迹代码`, label: `映射轨迹内容`,
field: 'trackContentId', field: 'trackContentId',
comp: 'SelectPro', comp: 'SelectPro',
compProps: () => { compProps: () => {
@ -378,7 +529,7 @@
disabled: !!editFormRightParams.id, disabled: !!editFormRightParams.id,
clearable: true, clearable: true,
immediate: true, immediate: true,
labelKey: 'content', labelKeys: ['code', 'content'],
titleStrs: ['轨迹代码', '轨迹内容'], titleStrs: ['轨迹代码', '轨迹内容'],
idKey: 'id', idKey: 'id',
api: postGetList, api: postGetList,
@ -405,7 +556,7 @@
isPage: true, isPage: true,
clearable: true, clearable: true,
immediate: true, immediate: true,
labelKey: 'content', labelKeys: ['code', 'content'],
titleStrs: ['轨迹代码', '轨迹内容'], titleStrs: ['轨迹代码', '轨迹内容'],
idKey: 'id', idKey: 'id',
api: postGetList, api: postGetList,
@ -422,18 +573,6 @@
], ],
}; };
const data: any[] = [ const data: any[] = [
{
label: '拉取轨迹状态',
field: 'trackStatusValues',
comp: 'TagsAdd',
compProps: ({ formModel }: { formModel: any }) => {
return {
placeholder: '请输入参数名',
disabled: disabledFn(formModel, 'trackStatusValues'),
};
},
span: 24,
},
{ {
label: '拉取轨迹关键字', label: '拉取轨迹关键字',
field: 'trackKeywords', field: 'trackKeywords',
@ -466,7 +605,7 @@
return { return {
options: trackLocationData.value?.filter((i) => i.value !== 1), options: trackLocationData.value?.filter((i) => i.value !== 1),
idKey: 'key', idKey: 'key',
labelKey: 'value', labelKeys: ['value'],
}; };
}, },
span: 24, span: 24,
@ -482,12 +621,11 @@
}); });
function disabledFn(formData: any, type: string) { function disabledFn(formData: any, type: string) {
const { trackStatusValues, trackKeywords, trackKeywordReverses } = formData; const { trackKeywords, trackKeywordReverses } = formData;
// 封装逻辑 // 封装逻辑
const hasValue = const hasValue =
trackKeywords?.length > 0 || trackKeywords?.length > 0 ||
trackKeywordReverses?.length > 0 || trackKeywordReverses?.length > 0;
trackStatusValues?.length > 0;
switch (type) { switch (type) {
case 'trackKeywordReverses': case 'trackKeywordReverses':
default: default:
@ -500,20 +638,13 @@
editFormParams.app = appKey; editFormParams.app = appKey;
} }
// const disabledType = computed(()=>{
// const a = modalFormLeftRef.value?.getFormValue()
// console.log(a)
// return false
// })
// 单击行获取行数据 par: any // 单击行获取行数据 par: any
function cellClick(par: any) { function cellClick(par: any) {
console.log(par); // 点击行数据处理
} }
// 点击新增 编辑打开左侧弹窗 // 点击新增 编辑打开左侧弹窗
function handleOpenModal(type: IDialogConfig['type'], row?: any) { function handleOpenModal(type: IDialogConfig['type'], row?: any) {
console.log('handleOpenModal called:', type, row);
const titleObj: { [x in IDialogConfig['type']]: string } = { const titleObj: { [x in IDialogConfig['type']]: string } = {
add: `新增`, add: `新增`,
edit: `编辑`, edit: `编辑`,
@ -527,8 +658,15 @@
title: titleObj[type], title: titleObj[type],
formData: { formData: {
serviceProviderId: row?.serviceProviderId, serviceProviderId: row?.serviceProviderId,
pullInterval: row?.pullInterval, dailyPullTimes: row?.pullInterval ? Math.round(row.pullInterval / 60) : undefined,
parseMethod: row?.parseMethod, client: row?.client,
key1: row?.key1,
key2: row?.key2,
pullWeight: row?.pullWeight,
continuePullDays: row?.continuePullDays,
startTrackContentId: row?.startTrackContentId,
endTrackContentId: row?.endTrackContentId,
parseMethod: row?.parseMethod !== undefined && row?.parseMethod !== null ? row.parseMethod : 1, // 默认值:标准返参
orderPath: row?.orderPath, orderPath: row?.orderPath,
orderNoName: row?.orderNoName, orderNoName: row?.orderNoName,
trackDetailsPath: row?.trackDetailsPath, trackDetailsPath: row?.trackDetailsPath,
@ -541,7 +679,6 @@
trackIsoTimeName: row?.trackIsoTimeName, trackIsoTimeName: row?.trackIsoTimeName,
trackUtcTimeName: row?.trackUtcTimeName, trackUtcTimeName: row?.trackUtcTimeName,
podName: row?.podName, podName: row?.podName,
trackExtraNames: row?.trackExtraNames,
}, },
}); });
} else { } else {
@ -549,6 +686,9 @@
editFormParams.id = undefined; editFormParams.id = undefined;
unref(modalFormLeftRef)?.openModalFn({ unref(modalFormLeftRef)?.openModalFn({
title: titleObj[type], title: titleObj[type],
formData: {
parseMethod: 1, // 默认值:标准返参
},
}); });
} }
} }
@ -589,7 +729,6 @@
// 删除数据 // 删除数据
function handleDelData(id: number) { function handleDelData(id: number) {
console.log(id, 'id');
$baseConfirm({ $baseConfirm({
content: `确认要删除该拉取吗?`, content: `确认要删除该拉取吗?`,
title: `温馨提示`, title: `温馨提示`,
@ -604,7 +743,6 @@
// 删除右侧数据 // 删除右侧数据
function handleDelRightData(id: number) { function handleDelRightData(id: number) {
console.log(id, 'id');
$baseConfirm({ $baseConfirm({
content: `确认要删除该拉取内容吗?`, content: `确认要删除该拉取内容吗?`,
title: `温馨提示`, title: `温馨提示`,
@ -640,9 +778,27 @@
tableRef.value?.reload([]); tableRef.value?.reload([]);
} }
// 处理操作选择 // 提交前转换数据:将dailyPullTimes转换为pullInterval
function handleActionSelect(value: string, option: any) { function beforeSubmitLeft(formData: any) {
// 操作已在模板中直接处理,这里不需要额外逻辑 if (formData.dailyPullTimes !== undefined && formData.dailyPullTimes !== null) {
formData.pullInterval = formData.dailyPullTimes * 60;
}
// 移除dailyPullTimes字段,因为API只需要pullInterval
delete formData.dailyPullTimes;
return formData;
}
// 从API获取数据后,将pullInterval转换为dailyPullTimes用于显示
function onGetInfoLeft(data: any) {
if (data) {
if (data.pullInterval !== undefined && data.pullInterval !== null) {
data.dailyPullTimes = Math.round(data.pullInterval / 60);
}
// 如果parseMethod为空,设置默认值为1(标准返参)
if (data.parseMethod === undefined || data.parseMethod === null) {
data.parseMethod = 1;
}
}
} }
// 左侧弹窗保存 // 左侧弹窗保存
@ -674,6 +830,29 @@
}); });
} }
// 打开串联拉取弹窗
function handleOpenChainPullModal() {
selectedServiceProviderId.value = undefined;
openChainPullModal(true);
}
// 关闭串联拉取弹窗
function handleCloseChainPullModal() {
selectedServiceProviderId.value = undefined;
closeChainPullModal();
}
// 确认串联拉取
function handleConfirmChainPull() {
if (!selectedServiceProviderId.value) {
$baseMessage('请选择服务商', 'warning');
return;
}
// TODO: 这里可以添加串联拉取的具体逻辑
$baseMessage('串联拉取功能开发中', 'info');
handleCloseChainPullModal();
}
onMounted(() => { onMounted(() => {
onFormSubmitClick(); onFormSubmitClick();
getTrackLocationData(); getTrackLocationData();
@ -749,8 +928,37 @@
:info-api="getGetDetail" :info-api="getGetDetail"
:api-params="editFormParams" :api-params="editFormParams"
:form-props="leftProps" :form-props="leftProps"
:before-submit="beforeSubmitLeft"
@on-submit="onSubmitLeft" @on-submit="onSubmitLeft"
/> @on-getinfo="onGetInfoLeft"
>
<template #returnParamConfig="{ model, schema }">
<a-collapse :default-active-key="['1']" :bordered="false">
<a-collapse-item header="返参配置" name="1">
<a-row :gutter="20">
<a-col
v-for="field in returnParamFields"
:key="field.field"
:span="field.span || 8"
:style="{ marginBottom: '16px' }"
>
<a-form-item
:field="field.field"
:label="field.label"
:rules="field.rules"
>
<component
:is="field.comp"
v-model="model[field.field]"
v-bind="typeof field.compProps === 'function' ? field.compProps({ formModel: model, field: field.field }) : field.compProps"
/>
</a-form-item>
</a-col>
</a-row>
</a-collapse-item>
</a-collapse>
</template>
</ModalForm>
</div> </div>
</template> </template>
<template #right> <template #right>
@ -767,18 +975,28 @@
<div class="h-full bg-#fff px-15px"> <div class="h-full bg-#fff px-15px">
<TablePro ref="tableRef" v-bind="tableProps"> <TablePro ref="tableRef" v-bind="tableProps">
<template #toolbar_buttons> <template #toolbar_buttons>
<TableButtons <div class="flex items-center gap-8px">
:actions="[ <a-button
{ type="primary"
label: '新增', size="small"
type: 'primary', :disabled="!currentId || !currentId.id"
disabled: !currentId || !currentId.id, @click="handleOpenChainPullModal"
onClick: () => { >
handleOpenRightModal('add'); 串联拉取
</a-button>
<TableButtons
:actions="[
{
label: '新增',
type: 'primary',
disabled: !currentId || !currentId.id,
onClick: () => {
handleOpenRightModal('add');
},
}, },
}, ]"
]" />
/> </div>
</template> </template>
<template #action="{ row }"> <template #action="{ row }">
<div class="action-buttons"> <div class="action-buttons">
@ -806,6 +1024,32 @@
</div> </div>
</template> </template>
</BasicLayoutLeftRight> </BasicLayoutLeftRight>
<!-- 串联拉取弹窗 -->
<ModalPro
title="串联拉取"
:width="500"
@register="registerChainPullModal"
@ok="handleConfirmChainPull"
@cancel="handleCloseChainPullModal"
>
<div class="chain-pull-modal-content">
<a-form :model="{ serviceProviderId: selectedServiceProviderId }" layout="vertical">
<a-form-item label="服务商" required>
<SelectPro
v-model="selectedServiceProviderId"
:api="getServiceProviderGetServiceProviderDropdownList"
:extra="{ appKey: userStore.appKey }"
:label-keys="['name']"
id-key="id"
:is-page="false"
placeholder="请选择服务商"
style="width: 100%"
/>
</a-form-item>
</a-form>
</div>
</ModalPro>
</div> </div>
</template> </template>
@ -888,4 +1132,8 @@
color: #bfbfbf !important; color: #bfbfbf !important;
border-color: #d9d9d9 !important; border-color: #d9d9d9 !important;
} }
.chain-pull-modal-content {
padding: 16px 0;
}
</style> </style>

View File

@ -13,7 +13,9 @@
import { postGetList } from '@/api/TrajectoryContent/trackContent'; import { postGetList } from '@/api/TrajectoryContent/trackContent';
import { getGetList } from '@/api/ApplicationServicesProvider/dictionary'; import { getGetList } from '@/api/ApplicationServicesProvider/dictionary';
import { getAppGetList } from '@/api/ApplicationServices/apps'; import { getAppGetList } from '@/api/ApplicationServices/apps';
import { getServiceProviderGetServiceProviderDropdownList } from '@/api/ServiceProviderInterface/serviceProvider';
import PushScroll from './components/PushScroll.vue'; import PushScroll from './components/PushScroll.vue';
import ModalForm from '@/components/ModalForm/index.vue';
type IDialogConfig = { type IDialogConfig = {
show: boolean; show: boolean;
@ -75,7 +77,7 @@
}, },
{ {
field: 'sort', field: 'sort',
title: '排序', title: '推送顺序',
}, },
{ {
field: 'code', field: 'code',
@ -130,21 +132,74 @@
const leftFormProps = computed(() => { const leftFormProps = computed(() => {
return { return {
formLayout: 'vertical', formLayout: 'vertical',
defaultSpan: 12,
colProps: {
span: 12,
style: { marginBottom: '16px' }
},
itemList: [ itemList: [
{
label: '应用',
field: 'appKey',
comp: 'SelectPro',
rules: [
{
required: true,
message: '请选择应用',
},
],
compProps: {
placeholder: '请选择应用',
size: 'large',
api: getAppGetList,
labelKeys: ['appKey'],
idKey: 'appKey',
isPage: true,
immediate: true,
onChange: handleAppChange,
style: { width: '100%', height: '40px' },
},
span: 12,
},
{ {
label: `客户`, label: `客户`,
field: 'customer', field: 'customer',
comp: 'AInput', comp: 'AInput',
compProps: {
placeholder: '请输入客户',
style: { width: '100%', height: '40px' },
},
span: 12, span: 12,
rules: [{ required: true, message: '请选择客户' }], rules: [{ required: true, message: '请选择客户' }],
}, },
{ {
label: `服务商`, label: '服务商',
field: 'serviceProviderCode', field: 'serviceProviderId',
comp: 'AInput', comp: 'SelectPro',
compProps: () => {
return {
immediate: true,
clearable: true,
labelKeys: ['name'],
titleStrs: ['name'],
placeholder: '请选择服务商',
style: { width: '100%', height: '40px' },
idKey: 'id',
isPage: false,
api: getServiceProviderGetServiceProviderDropdownList,
extra: { appKey: userStore.appKey },
allowSearch: true,
allowCreate: false,
trigger: 'click',
};
},
span: 12, span: 12,
rules: [
{
required: true,
message: '请选择服务商',
},
],
}, },
{ {
label: `是否自动推送`, label: `是否自动推送`,
@ -155,6 +210,7 @@
placeholder: '请选择是否自动推送', placeholder: '请选择是否自动推送',
size: 'large', size: 'large',
defaultValue: true, defaultValue: true,
style: { width: '100%', height: '40px' },
options: [ options: [
{ label: '是', value: true }, { label: '是', value: true },
{ label: '否', value: false }, { label: '否', value: false },
@ -164,14 +220,15 @@
span: 12, span: 12,
}, },
{ {
label: `是否支持更新`, label: `是否支持重推`,
field: 'isCanUpdate', field: 'isCanUpdate',
comp: 'ASelect', comp: 'ASelect',
compProps: () => { compProps: () => {
return { return {
placeholder: '请选择是否支持更新', placeholder: '请选择是否支持重推',
size: 'large', size: 'large',
defaultValue: false, defaultValue: false,
style: { width: '100%', height: '40px' },
options: [ options: [
{ label: '是', value: true }, { label: '是', value: true },
{ label: '否', value: false }, { label: '否', value: false },
@ -189,6 +246,7 @@
placeholder: '请选择是否全量推送', placeholder: '请选择是否全量推送',
size: 'large', size: 'large',
defaultValue: false, defaultValue: false,
style: { width: '100%', height: '40px' },
options: [ options: [
{ label: '是', value: true }, { label: '是', value: true },
{ label: '否', value: false }, { label: '否', value: false },
@ -204,6 +262,7 @@
compProps: { compProps: {
idKey: 'value', idKey: 'value',
labelKeys: ['label'], labelKeys: ['label'],
style: { width: '100%', height: '40px' },
options: [ options: [
{ label: '时间戳', value: 1 }, { label: '时间戳', value: 1 },
{ label: '时间+时区', value: 2 }, { label: '时间+时区', value: 2 },
@ -217,6 +276,7 @@
comp: 'AInput', comp: 'AInput',
compProps: { compProps: {
placeholder: '时间格式: yyyy-MM-dd HH:mm:ss或yyyy/MM/dd HH:mm:ss', placeholder: '时间格式: yyyy-MM-dd HH:mm:ss或yyyy/MM/dd HH:mm:ss',
style: { width: '100%', height: '40px' },
}, },
span: 12, span: 12,
ifShow: ({ model }: { model: any }) => model?.dateTimeFormatType === 2, ifShow: ({ model }: { model: any }) => model?.dateTimeFormatType === 2,
@ -227,29 +287,24 @@
comp: 'AInput', comp: 'AInput',
compProps: { compProps: {
placeholder: '时区格式: GMT/UTC', placeholder: '时区格式: GMT/UTC',
style: { width: '100%', height: '40px' },
}, },
span: 12, span: 12,
ifShow: ({ model }: { model: any }) => model?.dateTimeFormatType === 2, ifShow: ({ model }: { model: any }) => model?.dateTimeFormatType === 2,
}, },
{ {
field: 'appKey', label: '推送优先级',
label: '应用', field: 'pushPriority',
comp: 'SelectPro', comp: 'ASelect',
rules: [
{
required: true,
message: '请选择应用',
},
],
compProps: { compProps: {
placeholder: '请选择应用', placeholder: '请选择服务器节点',
size: 'large', style: { width: '100%', height: '40px' },
api: getAppGetList, options: [
labelKeys: ['appKey'], { label: '公共节点', value: '公共节点' },
idKey: 'appKey', { label: '独立节点1', value: '独立节点1' },
isPage: true, { label: '独立节点2', value: '独立节点2' },
immediate: true, { label: '独立节点3', value: '独立节点3' },
onChange: handleAppChange, ],
}, },
span: 12, span: 12,
}, },