更新前端代码

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

View File

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

View File

@ -41,7 +41,10 @@
};
},
},
beforeSubmit: {
type: Function as PropType<(data: any) => any>,
default: null,
},
});
const formRef = ref<null>(null);
@ -145,7 +148,13 @@
console.log(formValue, 'formValue');
// 清理表单数据,避免空字符串传递给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 { addApi, editApi, apiParams } = props;
@ -207,7 +216,11 @@
<div class="max-h-50vh">
<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>
</ModalPro>
</template>

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { VxeTablePropTypes } from 'vxe-table'
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 {
@ -292,7 +292,7 @@ type TypeAs = {
async function getInterfaceGetSystemInterface() {
const id = Number(props.addId)
const { data } = (await getInterfaceGetSystemInterfaceById({
const { data } = (await getInterfaceGetInterfaceById({
id: Number(props.upStreamId) || id,
})) as unknown as TypeAs
dialogTableProps.data = data.outParameterList
@ -300,7 +300,7 @@ async function getInterfaceGetSystemInterface() {
// onMounted(async () => {
// const id = Number(props.addId)
// const { data } = (await getInterfaceGetSystemInterfaceById({
// const { data } = (await getInterfaceGetInterfaceById({
// id: Number(props.upStreamId) || id,
// })) as unknown as TypeAs
// dialogTableProps.data = data.outParameterList

View File

@ -1,4 +1,5 @@
import { FormItemType } from '../../types';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
// 表单配置
export const formItems: FormItemType[] = [
@ -6,7 +7,7 @@ export const formItems: FormItemType[] = [
comp: 'a-input',
field: 'name',
label: '接口名',
span: 4,
span: 6,
compProps: {
placeholder: '请填写接口中文名称',
},
@ -15,7 +16,7 @@ export const formItems: FormItemType[] = [
comp: 'a-input',
field: 'code',
label: 'Code',
span: 4,
span: 6,
required: true,
compProps: {
placeholder: '请填写接口code',
@ -25,7 +26,7 @@ export const formItems: FormItemType[] = [
comp: 'SelectPro',
field: 'isReturnMessage',
label: '是否返回源报文',
span: 4,
span: 6,
compProps: {
placeholder: '是否返回源报文',
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',
field: 'category',
label: '接口分组',
span: 4,
span: 6,
compProps: {
placeholder: '请选择接口分组',
showHeader: false,
@ -61,7 +146,7 @@ export const formItems: FormItemType[] = [
comp: 'a-input',
field: 'description',
label: '接口描述',
span: 8,
span: 6,
compProps: {
placeholder: '请输入接口备注',
allowClear: true,

View File

@ -496,6 +496,14 @@ import InterfaceConfig from './interface-config.vue';
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 loadingSubmit = ref(false);
const interfaceDetailModalRef = ref<any>();
const interfaceConfigRef = ref<any>();
const detailRefreshKey = ref(0);
const selectedProvider = ref<any>();
function saveModelEnter() {
@ -873,15 +883,8 @@ import InterfaceConfig from './interface-config.vue';
function handleInterfaceDetailCancel() {
// 取消编辑,重新加载接口详情
if (selectedInterface.value && interfaceDetailModalRef.value) {
nextTick(() => {
interfaceDetailModalRef.value.init({
id: selectedInterface.value.id,
serviceProviderId: selectedProvider.value?.id,
serviceProviderName: selectedProvider.value?.name,
mode: 'edit'
});
});
if (selectedInterface.value) {
detailRefreshKey.value++;
}
}
// 点击跳转
@ -1213,14 +1216,6 @@ import InterfaceConfig from './interface-config.vue';
</div>
</a-button>
<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))">
<icon-delete />
删除
@ -1340,6 +1335,36 @@ import InterfaceConfig from './interface-config.vue';
/>
</div>
</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>
</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-actions { display: flex; gap: 4px; }
.pane-header-actions { margin-left: auto; display: flex; }
.pane-header :deep(.arco-input-wrapper) { height: 28px !important; }
.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; }

View File

@ -12,10 +12,8 @@
postParameterParse,
postParameterValidateParameter,
} from '@/api/ParameterServices/parameter';
import {
getInterfaceGetSystemInterfaceById,
postInterfaceSaveSystemInterface,
} from '@/api/InterfaceServices/systemInterface';
import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
import { postInterfaceSaveSystemInterface } from '@/api/InterfaceServices/systemInterface';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
import type { RouteLocationNormalizedLoaded, Router } from 'vue-router';
import { $baseMessage, $baseConfirm } from '@/utils';
@ -1335,7 +1333,7 @@
}
try {
const response = await getInterfaceGetSystemInterfaceById({
const response = await getInterfaceGetInterfaceById({
id,
});
@ -1488,11 +1486,12 @@
<div class="section">
<div class="section-content">
<FormPro
class="interface-form"
ref="refSearchForm"
v-model="tableForm"
:button-config="{ showBtn: false }"
:default-span="5"
:row-gutter="8"
:default-span="6"
:row-gutter="16"
:form-layout="'inline'"
:item-list="formItems"
:label-col-props="{
@ -1896,6 +1895,25 @@
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 {
background-color: var(--color-bg-2);
border-radius: 4px;

View File

@ -23,7 +23,7 @@
}
return response.json();
};
import { getInterfaceGetSystemInterfaceDropdownList } from '@/api/InterfaceServices/systemInterface';
import { getInterfaceGetInterfaceDropdownList } from '@/api/InterfaceServices/interface';
defineOptions({ name: 'AdhibitionList' });
@ -50,7 +50,7 @@
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() {
@ -72,25 +72,63 @@
// 获取接口数据
async function loadInterfaceData() {
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 = [];
data.forEach(group => {
if (group.interfaces && group.interfaces.length > 0) {
group.interfaces.forEach(interfaceItem => {
allInterfaces.push({
id: interfaceItem.id,
name: interfaceItem.name,
enabled: false, // 默认未启用
qps: 100 // 默认QPS
});
const allInterfaces: any[] = [];
groups.forEach((group: any) => {
// 支持两种数据结构:
// 1. 分组结构:{ id, groupName, interfaces: [...] }
// 2. 扁平结构:直接是接口数组
if (group.interfaces && Array.isArray(group.interfaces)) {
// 分组结构
group.interfaces.forEach((interfaceItem: any) => {
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;
if (allInterfaces.length === 0) {
console.warn('没有获取到接口数据,原始数据:', resp);
}
} catch (error) {
console.error('获取接口数据失败:', error);
$baseMessage('获取接口数据失败', 'error');
}
}
@ -112,6 +150,9 @@
// 设置选中的应用详情
selectedApp.value = appDetail;
// 每次点击应用时,刷新可用接口下拉(上游、serviceProviderId=0)
await loadInterfaceData();
// 填充编辑表单
editForm.value = {
name: appDetail.name || '',
@ -120,7 +161,7 @@
isOnline: appDetail.isOnline || false
};
// 加载该应用的接口配置
// 加载该应用的接口配置(基于最新接口下拉数据)
loadAppInterfaces(appDetail);
} catch (error) {
$baseMessage('获取应用详情失败', 'error');
@ -525,7 +566,10 @@
<h3>可用接口</h3>
</div>
<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>
<tr>
<th>序号</th>
@ -535,9 +579,9 @@
</tr>
</thead>
<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>{{ interfaceItem.name }}</td>
<td>{{ interfaceItem.name || '-' }}</td>
<td>
<a-switch
v-model="interfaceItem.enabled"

View File

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

View File

@ -11,10 +11,8 @@
postParameterParse,
postParameterValidateParameter,
} from '@/api/ParameterServices/parameter';
import {
getInterfaceGetServiceProviderInterfaceById,
postInterfaceSaveServiceProviderInterface,
} from '@/api/InterfaceServices/serviceProviderInterface';
import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
import { postInterfaceSaveServiceProviderInterface } from '@/api/InterfaceServices/serviceProviderInterface';
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
import { $baseMessage, $baseConfirm } from '@/utils';
import { useI18n } from 'vue-i18n';
@ -370,7 +368,7 @@
if (isEditMode.value && data.id) {
// 编辑模式,加载接口数据
const interfaceData = await getInterfaceGetServiceProviderInterfaceById({
const interfaceData = await getInterfaceGetInterfaceById({
id: data.id,
});
refSearchForm.value?.setFormValue(interfaceData);
@ -464,14 +462,24 @@
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 = {
...formData,
serviceProviderId: serviceProviderId.value,
inParameterList: tableForm.inParameterList,
outParameterList: tableForm.outParameterList,
formParameterList: formParameterList,
inParameterList: filteredInList,
outParameterList: filteredOutList,
formParameterList: filteredFormList,
};
// 规范化新增/编辑的标识字段
if (isEditMode.value) {
@ -638,8 +646,8 @@
try {
const content = tabs.value === 'Json' ? textareaJson.value : textareaXml.value;
const data = await postParameterParse({
content,
type: tabs.value === 'Json' ? 'json' : 'xml',
parameterParseType: tabs.value === 'Json' ? 1 : 2,
parameterContent: content,
});
dataList.value = data;
@ -662,8 +670,8 @@
try {
const content = tabs1.value === 'Json' ? textareaJson1.value : textareaXml1.value;
const data = await postParameterParse({
content,
type: tabs1.value === 'Json' ? 'json' : 'xml',
parameterParseType: tabs1.value === 'Json' ? 1 : 2,
parameterContent: content,
});
dataList1.value = data;

View File

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

View File

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

View File

@ -48,6 +48,7 @@
IconMore,
IconDelete,
} from '@arco-design/web-vue/es/icon';
import ReturnConfig from './comps/ReturnConfig.vue';
defineOptions({
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(() => {
getAppList();
loadServiceProviderList();
@ -1375,6 +1386,14 @@
<IconDelete style="margin-right: 8px;" />
删除
</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>
</a-dropdown>
</div>
@ -1454,6 +1473,7 @@
<FixedParameters ref="FixedParametersRef" />
<ParameterConfig v-if="parameterConfigFlagShow" ref="parameterConfigFlag" />
<AccountList ref="accountList" />
<ReturnConfig ref="ReturnConfigRef" />
</div>
</template>

View File

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

View File

@ -1,5 +1,5 @@
<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 { useUserStore } from '@/store';
import { $baseMessage } from '@/utils';
@ -19,6 +19,9 @@
import { getAppGetList } from '@/api/ApplicationServices/apps';
import PullScroll from './components/PullScroll.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 = {
show: boolean;
@ -48,6 +51,8 @@
const modalFormLeftRef = ref();
const modalFormRightRef = ref();
const refHeight = ref();
const [registerChainPullModal, { openModal: openChainPullModal, closeModal: closeChainPullModal }] = useModal() as any;
const selectedServiceProviderId = ref<number | undefined>();
const { contentHeight, calcContentHeight } = useContentHeight(
refHeight,
@ -93,14 +98,6 @@
field: 'enContent',
title: '轨迹内容英文',
},
{
field: 'trackStatusValue',
title: '拉取轨迹状态',
},
{
field: 'trackPlaceValue',
title: '轨迹发生地',
},
{
field: 'trackKeyword',
title: '拉取轨迹关键字',
@ -111,6 +108,10 @@
title: '拉取轨迹关键字(过滤)',
width: 200,
},
{
field: 'trackPlaceValue',
title: '兜底轨迹发生地',
},
{
field: 'action',
title: '操作',
@ -126,6 +127,162 @@
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(() => {
return {
formLayout: 'vertical',
@ -135,6 +292,28 @@
style: { marginBottom: '16px' }
},
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: '服务商',
field: 'serviceProviderId',
@ -165,197 +344,169 @@
],
},
{
label: '定时任务(分钟)',
field: 'pullInterval',
comp: 'AInput',
label: '每天拉取次数',
field: 'dailyPullTimes',
comp: 'AInputNumber',
compProps: {
placeholder: '请输入大于60的正整数',
maxlength: 10,
placeholder: '请输入1-12的数字',
style: { width: '100%', height: '40px' },
min: 1,
max: 12,
precision: 0,
},
span: 8,
rules: [
{
required: true,
pattern: /^([6-9]\d|[1-9]\d{2,})$/,
message: '请输入大于60的正整数',
type: 'number',
min: 1,
max: 12,
message: '请输入1到12之间的数字',
trigger: 'change',
},
],
},
{
label: '返参解析对象',
field: 'parseMethod',
label: '客户',
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',
compProps: {
placeholder: '请选择',
placeholder: '请选择服务器节点',
style: { width: '100%', height: '40px' },
options: [
{ label: '接口通返参', value: 1 },
{ label: '服务商返参', value: 2 },
{ label: '公共节点', value: '公共节点' },
{ label: '独立节点1', value: '独立节点1' },
{ label: '独立节点2', value: '独立节点2' },
{ label: '独立节点3', value: '独立节点3' },
],
},
span: 8,
rules: [
{
required: true,
message: '请选择返参解析对象',
},
],
},
{
label: '订单路径',
field: 'orderPath',
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: '应用',
label: '开始轨迹',
field: 'startTrackContentId',
comp: 'SelectPro',
rules: [
{
required: true,
message: '请选择应用',
},
],
compProps: {
placeholder: '请选择应用',
size: 'large',
api: getAppGetList,
labelKeys: ['appKey'],
idKey: 'appKey',
isPage: true,
immediate: true,
onChange: handleAppChange,
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到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 = {
label: `轨迹代码`,
label: `映射轨迹内容`,
field: 'trackContentId',
comp: 'SelectPro',
compProps: () => {
@ -378,7 +529,7 @@
disabled: !!editFormRightParams.id,
clearable: true,
immediate: true,
labelKey: 'content',
labelKeys: ['code', 'content'],
titleStrs: ['轨迹代码', '轨迹内容'],
idKey: 'id',
api: postGetList,
@ -405,7 +556,7 @@
isPage: true,
clearable: true,
immediate: true,
labelKey: 'content',
labelKeys: ['code', 'content'],
titleStrs: ['轨迹代码', '轨迹内容'],
idKey: 'id',
api: postGetList,
@ -422,18 +573,6 @@
],
};
const data: any[] = [
{
label: '拉取轨迹状态',
field: 'trackStatusValues',
comp: 'TagsAdd',
compProps: ({ formModel }: { formModel: any }) => {
return {
placeholder: '请输入参数名',
disabled: disabledFn(formModel, 'trackStatusValues'),
};
},
span: 24,
},
{
label: '拉取轨迹关键字',
field: 'trackKeywords',
@ -466,7 +605,7 @@
return {
options: trackLocationData.value?.filter((i) => i.value !== 1),
idKey: 'key',
labelKey: 'value',
labelKeys: ['value'],
};
},
span: 24,
@ -482,12 +621,11 @@
});
function disabledFn(formData: any, type: string) {
const { trackStatusValues, trackKeywords, trackKeywordReverses } = formData;
const { trackKeywords, trackKeywordReverses } = formData;
// 封装逻辑
const hasValue =
trackKeywords?.length > 0 ||
trackKeywordReverses?.length > 0 ||
trackStatusValues?.length > 0;
trackKeywordReverses?.length > 0;
switch (type) {
case 'trackKeywordReverses':
default:
@ -500,20 +638,13 @@
editFormParams.app = appKey;
}
// const disabledType = computed(()=>{
// const a = modalFormLeftRef.value?.getFormValue()
// console.log(a)
// return false
// })
// 单击行获取行数据 par: any
function cellClick(par: any) {
console.log(par);
// 点击行数据处理
}
// 点击新增 编辑打开左侧弹窗
function handleOpenModal(type: IDialogConfig['type'], row?: any) {
console.log('handleOpenModal called:', type, row);
const titleObj: { [x in IDialogConfig['type']]: string } = {
add: `新增`,
edit: `编辑`,
@ -527,8 +658,15 @@
title: titleObj[type],
formData: {
serviceProviderId: row?.serviceProviderId,
pullInterval: row?.pullInterval,
parseMethod: row?.parseMethod,
dailyPullTimes: row?.pullInterval ? Math.round(row.pullInterval / 60) : undefined,
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,
orderNoName: row?.orderNoName,
trackDetailsPath: row?.trackDetailsPath,
@ -541,7 +679,6 @@
trackIsoTimeName: row?.trackIsoTimeName,
trackUtcTimeName: row?.trackUtcTimeName,
podName: row?.podName,
trackExtraNames: row?.trackExtraNames,
},
});
} else {
@ -549,6 +686,9 @@
editFormParams.id = undefined;
unref(modalFormLeftRef)?.openModalFn({
title: titleObj[type],
formData: {
parseMethod: 1, // 默认值:标准返参
},
});
}
}
@ -589,7 +729,6 @@
// 删除数据
function handleDelData(id: number) {
console.log(id, 'id');
$baseConfirm({
content: `确认要删除该拉取吗?`,
title: `温馨提示`,
@ -604,7 +743,6 @@
// 删除右侧数据
function handleDelRightData(id: number) {
console.log(id, 'id');
$baseConfirm({
content: `确认要删除该拉取内容吗?`,
title: `温馨提示`,
@ -640,9 +778,27 @@
tableRef.value?.reload([]);
}
// 处理操作选择
function handleActionSelect(value: string, option: any) {
// 操作已在模板中直接处理,这里不需要额外逻辑
// 提交前转换数据:将dailyPullTimes转换为pullInterval
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(() => {
onFormSubmitClick();
getTrackLocationData();
@ -749,8 +928,37 @@
:info-api="getGetDetail"
:api-params="editFormParams"
:form-props="leftProps"
:before-submit="beforeSubmitLeft"
@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>
</template>
<template #right>
@ -767,18 +975,28 @@
<div class="h-full bg-#fff px-15px">
<TablePro ref="tableRef" v-bind="tableProps">
<template #toolbar_buttons>
<TableButtons
:actions="[
{
label: '新增',
type: 'primary',
disabled: !currentId || !currentId.id,
onClick: () => {
handleOpenRightModal('add');
<div class="flex items-center gap-8px">
<a-button
type="primary"
size="small"
:disabled="!currentId || !currentId.id"
@click="handleOpenChainPullModal"
>
串联拉取
</a-button>
<TableButtons
:actions="[
{
label: '新增',
type: 'primary',
disabled: !currentId || !currentId.id,
onClick: () => {
handleOpenRightModal('add');
},
},
},
]"
/>
]"
/>
</div>
</template>
<template #action="{ row }">
<div class="action-buttons">
@ -806,6 +1024,32 @@
</div>
</template>
</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>
</template>
@ -888,4 +1132,8 @@
color: #bfbfbf !important;
border-color: #d9d9d9 !important;
}
.chain-pull-modal-content {
padding: 16px 0;
}
</style>

View File

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