1097 lines
35 KiB
Vue
1097 lines
35 KiB
Vue
<script lang="ts" setup>
|
||
import { cloneDeep, random } from 'lodash-es';
|
||
import type { VxeTablePropTypes } from 'vxe-table';
|
||
import { IconDragDotVertical } from '@arco-design/web-vue/es/icon';
|
||
import Sortable from 'sortablejs';
|
||
import XEUtils from 'xe-utils';
|
||
import { ref, reactive, nextTick, onMounted } from 'vue';
|
||
import { useRouter } from 'vue-router';
|
||
import { getInterfaceGetInterfaceById } from '@/api/InterfaceServices/interface';
|
||
|
||
import {
|
||
getParameterGetParameterList,
|
||
postParameterSave,
|
||
postParameterSaveSort,
|
||
} from '@/api/ParameterServices/parameter';
|
||
import { getGetMapList } from '@/api/InterfaceMappingServices/interfaceMap';
|
||
import { getDictionaryGetList } from '@/api/ApplicationServices/dictionary';
|
||
import { useRequest } from 'vue-hooks-plus';
|
||
|
||
import useModal from '@/components/ModalPro/useModal';
|
||
import { Modal, Message } from '@arco-design/web-vue';
|
||
|
||
import TableButtons from '@/components/TableButtons/index.vue';
|
||
import TablePro from '@/components/TablePro/index.vue';
|
||
import ModalPro from '@/components/ModalPro/index.vue';
|
||
import SelectPro from '@/components/SelectPro/index.vue';
|
||
import { useI18n } from 'vue-i18n';
|
||
import {
|
||
entrancePrarm,
|
||
exitPrarm,
|
||
mapentranceColumns,
|
||
} from '../models/tableColumns';
|
||
|
||
const $modal = Modal;
|
||
const $message = Message;
|
||
const { t } = useI18n();
|
||
|
||
defineOptions({
|
||
name: 'EntranceArgumentsMap',
|
||
});
|
||
|
||
const props = defineProps<IProps>();
|
||
|
||
const emit = defineEmits(['close']);
|
||
|
||
type IProps = {
|
||
interfaceMapId?: number;
|
||
id?: number;
|
||
serviceProviderId?: number;
|
||
addId?: number;
|
||
upStreamId?: number;
|
||
downStreamId?: number;
|
||
intId?: number;
|
||
saveFlag: boolean;
|
||
systemInterfaceName: string;
|
||
serviceProviderName: string;
|
||
interfaceName: string;
|
||
};
|
||
|
||
// const route = useRoute()
|
||
const router = useRouter();
|
||
// const active = ref(0)
|
||
const [register, registerMethods] = useModal();
|
||
const tableRef = ref();
|
||
const dialogVisible = ref(false);
|
||
const mapDisabled = ref(true);
|
||
const dialogTableRef = ref();
|
||
const tableProps = reactive({
|
||
tableConfig: {
|
||
columns: mapentranceColumns,
|
||
showToolbar: true,
|
||
height: 480,
|
||
},
|
||
api: getGetMapList,
|
||
searchInfo: {
|
||
isInPara: true,
|
||
id: Number(props.interfaceMapId) || props.id,
|
||
},
|
||
});
|
||
const dialogTableProps = reactive({
|
||
tableConfig: {
|
||
columns: [
|
||
{
|
||
field: 'asdsad',
|
||
title: '按住拖动',
|
||
className: 'sort',
|
||
width: 80,
|
||
slots: {
|
||
default: 'asdsad',
|
||
},
|
||
},
|
||
{
|
||
field: 'name',
|
||
title: '参数名',
|
||
treeNode: true,
|
||
editRender: { autofocus: '.arco-input__inner' },
|
||
slots: {
|
||
edit: 'name_edit',
|
||
},
|
||
},
|
||
{
|
||
field: 'cnName',
|
||
title: '参数名(中文)',
|
||
editRender: { autofocus: '.arco-input__inner' },
|
||
slots: {
|
||
edit: 'cnName_edit',
|
||
},
|
||
},
|
||
{
|
||
field: 'type',
|
||
title: '参数类型',
|
||
editRender: {},
|
||
slots: {
|
||
edit: 'type_edit',
|
||
default: 'type_default',
|
||
},
|
||
},
|
||
{
|
||
field: 'description',
|
||
title: '参数描述',
|
||
editRender: { autofocus: '.arco-input__inner' },
|
||
slots: {
|
||
edit: 'description_edit',
|
||
},
|
||
},
|
||
{
|
||
field: 'action',
|
||
title: '操作',
|
||
fixed: 'right',
|
||
align: 'center',
|
||
width: 180,
|
||
slots: {
|
||
default: 'action',
|
||
},
|
||
},
|
||
],
|
||
showToolbar: true,
|
||
editConfig: { trigger: 'click', mode: 'row' },
|
||
showIndex: false,
|
||
},
|
||
data: [] as any[],
|
||
});
|
||
const dialogTableRules = ref<VxeTablePropTypes.EditRules>({
|
||
name: [
|
||
{ required: true, content: '参数名不能为空', trigger: 'change' },
|
||
{
|
||
pattern: /^[^\u4E00-\u9FA5\s]+$/,
|
||
message: '禁止录入空格以及中文名称',
|
||
trigger: 'change',
|
||
},
|
||
],
|
||
cnName: [
|
||
// { required: true, content: '参数名(中文)不能为空', trigger: 'change' },
|
||
// {
|
||
// pattern: /[\u4E00-\u9FA5]/,
|
||
// message: '限制为中文',
|
||
// trigger: 'change',
|
||
// },
|
||
],
|
||
description: [
|
||
// { required: true, content: '参数描述不能为空', trigger: 'change' },
|
||
{
|
||
max: 200,
|
||
message: '请控制长度在200个字符之内',
|
||
trigger: 'change',
|
||
},
|
||
],
|
||
type: [{ required: true, content: '参数类型不能为空', trigger: 'change' }],
|
||
});
|
||
// 新增系统参数
|
||
function addParameter() {
|
||
parameterList.value = [];
|
||
getInterfaceGetSystemInterface();
|
||
dialogVisible.value = true;
|
||
nextTick(() => {
|
||
// 加载完成之后在绑定拖动事件
|
||
initTime = setTimeout(() => {
|
||
treeDrop();
|
||
}, 500);
|
||
});
|
||
}
|
||
// 请求弹窗表格里的下拉数据
|
||
const ParameterTypeList = ref<any[]>([]);
|
||
async function EnumValueInfoGetList() {
|
||
const { data: data1 } = await getDictionaryGetList({
|
||
type: 'ParameterType',
|
||
});
|
||
ParameterTypeList.value = data1;
|
||
}
|
||
EnumValueInfoGetList();
|
||
// 参数类型转换
|
||
function formatType(type: number) {
|
||
const typec = ParameterTypeList.value.filter((i) => i.key === type) || [];
|
||
return typec.length > 0 ? typec[0].value : '';
|
||
}
|
||
// 新增参数
|
||
async function addClick() {
|
||
const record = {
|
||
id: random(0, 2099999999),
|
||
pId: 0,
|
||
type: 8,
|
||
name: '',
|
||
};
|
||
const { row: newRow } = await dialogTableRef.value!.addRow(record);
|
||
await dialogTableRef.value?.editRowEvent(newRow);
|
||
}
|
||
// 参数表单新增按钮
|
||
async function addRow(currRow: any) {
|
||
const record = {
|
||
id: random(0, 2099999999),
|
||
pId: currRow.id,
|
||
type: 8,
|
||
name: '',
|
||
};
|
||
if (currRow.type === 9 || currRow.type === 8 || currRow.type === 11)
|
||
return $message.error('该参数类型不可新增下一级');
|
||
|
||
if (!currRow.name) return $message.error('参数名不能为空');
|
||
|
||
await dialogTableRef.value?.addRowsAt(record, -1);
|
||
await dialogTableRef.value?.setTreeExpand(currRow, true);
|
||
}
|
||
// 表单删除按钮
|
||
async function delRow(currRow: any) {
|
||
await dialogTableRef.value?.removeRow(currRow);
|
||
if (!currRow.children) currRow.type.disabled = false;
|
||
}
|
||
const formsTypeList_new = ref<any[]>([]);
|
||
const formsTypeList = ref<any[]>([]);
|
||
async function formsValueInfoGetList() {
|
||
const { data } = await getParameterGetParameterList({
|
||
isInPara: true,
|
||
id: Number(props.addId) || Number(props.upStreamId),
|
||
onlyLeafs: true,
|
||
});
|
||
formsTypeList_new.value = data;
|
||
formsTypeList.value = data;
|
||
}
|
||
formsValueInfoGetList();
|
||
// const parameterTypeList = ref()
|
||
// const parameterSetGetList = async () => {
|
||
// const { data } = await InterfaceMapGetSingleMapGET({
|
||
// mapId: Number(props.interfaceMapId) || Number(props.id),
|
||
// })
|
||
// parameterTypeList.value = data
|
||
// }
|
||
// parameterSetGetList()
|
||
type TypeAs = {
|
||
[key: string]: any;
|
||
};
|
||
|
||
async function getInterfaceGetSystemInterface() {
|
||
const id = Number(props.addId);
|
||
const { data } = (await getInterfaceGetInterfaceById({
|
||
id: id || Number(props.upStreamId),
|
||
})) as unknown as TypeAs;
|
||
dialogTableProps.data = data.inParameterList;
|
||
}
|
||
getInterfaceGetSystemInterface();
|
||
|
||
// onMounted(async () => {
|
||
// const id = Number(props.addId)
|
||
// const { data } = (await getInterfaceGetInterfaceById({
|
||
// id: id || Number(props.upStreamId),
|
||
// })) as unknown as TypeAs
|
||
// dialogTableProps.data = data.inParameterList
|
||
// })
|
||
// 给子节点新增删除标记
|
||
function childrenTotree(data: any[]) {
|
||
data.forEach((list) => {
|
||
if (list.children && list.children != null) childrenTotree(list.children);
|
||
|
||
list.optionType = 2;
|
||
});
|
||
}
|
||
|
||
/** 把表格新增或者修改的数据存下来 */
|
||
const parameterList = ref<any[]>([]);
|
||
// 因为拖动的时候会改变getActionRows的数据,所以需要提前保存
|
||
function getUpdataTableData() {
|
||
const inParameterListInstall = dialogTableRef.value
|
||
?.getActionRows()
|
||
.insertRecords.map((i: API.ParameterInput) => {
|
||
if (i.name === '') return $message.error('参数名不能为空');
|
||
|
||
return {
|
||
optionType: 1,
|
||
...i,
|
||
Id: undefined,
|
||
cnName: i.cnName === '' ? null : i.cnName,
|
||
};
|
||
});
|
||
// 删除
|
||
const inParameterListRemove = dialogTableRef.value
|
||
?.getActionRows()
|
||
.removeRecords.map((i: API.ParameterInput & { children?: any }) => {
|
||
if (i.children) childrenTotree(i.children);
|
||
|
||
return {
|
||
optionType: 2,
|
||
...i,
|
||
Id: undefined,
|
||
};
|
||
});
|
||
// 更改
|
||
const inParameterListUpdate = dialogTableRef.value
|
||
?.getActionRows()
|
||
.updateRecords.map((i: API.ParameterInput) => {
|
||
if (i.name === '') return $message.error('参数名不能为空');
|
||
|
||
return {
|
||
optionType: 3,
|
||
...i,
|
||
Id: undefined,
|
||
cnName: i.cnName === '' ? null : i.cnName,
|
||
};
|
||
});
|
||
parameterList.value = [
|
||
...inParameterListInstall,
|
||
...inParameterListRemove,
|
||
...inParameterListUpdate,
|
||
];
|
||
}
|
||
|
||
// 新增系统参数保存
|
||
async function serveForm() {
|
||
if (!parameterList.value.length) getUpdataTableData();
|
||
// treeData(parameterList)
|
||
console.log(parameterList.value, 'parameterList.value');
|
||
type CommonParameterInputType = API.ParameterInput & { id: number };
|
||
dialogTableRef.value?.validate().then(async (res: boolean) => {
|
||
if (res) {
|
||
(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 (backSortArr?.length) {
|
||
const index = backSortArr?.findIndex((i) => i.id === item.id);
|
||
console.log(item, 'index');
|
||
if (index > -1) backSortArr[index].optionType = item?.optionType;
|
||
}
|
||
});
|
||
fc.forEach((el: any) => {
|
||
el.Id = undefined;
|
||
el.children = undefined;
|
||
el._X_ROW_CHILD = undefined;
|
||
});
|
||
backSortArr.forEach((el: any) => {
|
||
el.Id = undefined;
|
||
el.children = undefined;
|
||
el._X_ROW_CHILD = undefined;
|
||
el.isRequired = !!el.isRequired;
|
||
});
|
||
fc = fc.map((item) => {
|
||
return {
|
||
...item,
|
||
sort: getRowSeq(item, dialogTableRef.value),
|
||
isRequired: !!item.isRequired,
|
||
};
|
||
});
|
||
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 as any).changeOkLoading(false);
|
||
$message.success('保存成功');
|
||
savePort(isIDReturn(props.id, fc).outParameterList);
|
||
dialogVisible.value = false;
|
||
clearTimeout(initTime);
|
||
if (sortable) sortable.destroy();
|
||
|
||
getInterfaceGetSystemInterface();
|
||
tableRef.value?.reload();
|
||
} else {
|
||
(registerMethods as any).changeOkLoading(false);
|
||
$message.error('保存失败');
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 保存序列
|
||
function savePort(sortArr: any[]) {
|
||
saveSortRun({
|
||
interfaceId: props.interfaceMapId
|
||
? Number(props.upStreamId)
|
||
: Number(props.addId),
|
||
parameterSortList: sortArr,
|
||
});
|
||
}
|
||
|
||
const { run: saveSortRun } = useRequest(postParameterSaveSort, {
|
||
manual: true,
|
||
});
|
||
|
||
/** 根据是否有id返回具体的参数 */
|
||
function isIDReturn(id: any, fc: any[]) {
|
||
if (id) {
|
||
return {
|
||
outParameterList: backSortArr.length ? backSortArr : fc.reverse(),
|
||
};
|
||
}
|
||
return {
|
||
outParameterList: fc.length ? fc.reverse() : backSortArr,
|
||
};
|
||
}
|
||
|
||
// 弹窗取消
|
||
function delClick() {
|
||
dialogVisible.value = false;
|
||
}
|
||
// const { setMapList } = useSystemMapStore()
|
||
|
||
// 删除当前标签页
|
||
// const tabsStore = useTabsStore()
|
||
// const { delVisitedRoute } = tabsStore
|
||
|
||
function close() {
|
||
emit('close');
|
||
}
|
||
|
||
// 入参保存
|
||
const loading = ref(false);
|
||
async function addMapClick() {
|
||
if (
|
||
tableRef.value
|
||
?.getTableData()
|
||
.tableData.some(
|
||
(node: any) => node.isRequired === true && !node.mapId && !node.fixedValue
|
||
)
|
||
)
|
||
return $message.error(
|
||
'服务商接口参数要求必填,请维护映射关系或者固定参数'
|
||
);
|
||
|
||
// const arr: Array<object> = []
|
||
tableRef.value?.getTableData().tableData.forEach((item: any) => {
|
||
const obj: Indexable = {};
|
||
obj.interfaceMapDetailId = item.interfaceMapDetailId;
|
||
obj.mappedParaId = item.mapId;
|
||
obj.alias = item.alias;
|
||
obj.fixedId = item.fixedId;
|
||
obj.fixedValue = item.fixedValue;
|
||
obj.description = item.description;
|
||
obj.isRequired = item.isRequired;
|
||
entrancePrarm.push(obj);
|
||
});
|
||
|
||
// const maps = arr.concat(entrancePrarm, exitPrarm)
|
||
loading.value = true;
|
||
// const { code } = await InterfaceMapSaveParameterMapsPOST({
|
||
// interfaceMapId: Number(props.id),
|
||
// // inParaIds: arr,
|
||
// mapDetails: maps,
|
||
// // outParaMapIds: null,
|
||
// }).finally(() => {
|
||
// loading.value = false
|
||
// })
|
||
// if (code === '200') {
|
||
$message.success('保存成功');
|
||
// emit('close')
|
||
entrancePrarm.length = 0;
|
||
exitPrarm.length = 0;
|
||
// $pub('reload-router-view', 'SystemInterface')
|
||
// const path = handleActivePath(route, true)
|
||
// // delVisitedRoute(
|
||
// // `/system-Interface/exit-arguments-map?id=${props.id}&intId=${props.intId}&addId=${props.addId}`
|
||
// // )
|
||
// delVisitedRoute(path)
|
||
|
||
// router.push({
|
||
// name: 'MapServiceProvider',
|
||
// query: {
|
||
// // interfaceId: props.id,
|
||
// // intId: props.intId,
|
||
// id: props.addId,
|
||
// addId: props.addId,
|
||
// },
|
||
// })
|
||
// } else {
|
||
// $baseMessage('success')
|
||
// }
|
||
// }
|
||
}
|
||
|
||
function formsChange(row: any) {
|
||
mapDisabled.value = false;
|
||
const a = formsTypeList.value.find((node: any) => node.id === row.mapId);
|
||
if (a) {
|
||
row.mapCnName = a.cnName;
|
||
row.mapAlias = a.alias;
|
||
row.mapDescription = a.description;
|
||
}
|
||
}
|
||
|
||
function visibleChange(val: boolean) {
|
||
if (!val) formsTypeList.value = formsTypeList_new.value;
|
||
}
|
||
|
||
function formsClear(row: any) {
|
||
// mapDisabled.value = false
|
||
row.mapCnName = '';
|
||
row.mapAlias = '';
|
||
row.mapDescription = '';
|
||
}
|
||
|
||
function filterMethod(val: string) {
|
||
formsTypeList.value = formsTypeList.value.filter((item) => {
|
||
return (
|
||
item.alias.toLowerCase().includes(val.toLowerCase()) ||
|
||
(item.cnName && item.cnName.includes(val.toLowerCase()))
|
||
);
|
||
});
|
||
}
|
||
|
||
const restaurants = ref<RestaurantItem[]>([]);
|
||
|
||
type RestaurantItem = {
|
||
value: string;
|
||
key: number;
|
||
};
|
||
|
||
function querySearch(queryString: string, cb: any) {
|
||
const results =
|
||
queryString?.length && queryString !== 'null'
|
||
? restaurants.value.filter(createFilter(queryString))
|
||
: restaurants.value;
|
||
// call callback function to return suggestions
|
||
console.log(results, 'results');
|
||
cb(results);
|
||
}
|
||
|
||
function createFilter(queryString: string) {
|
||
return (restaurant: RestaurantItem) => {
|
||
return (
|
||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||
);
|
||
};
|
||
}
|
||
|
||
// 点击跳转
|
||
function goRouter(id: number | undefined, address: string, type?: string) {
|
||
console.log(props);
|
||
router.replace({
|
||
name: address,
|
||
query: { id, type },
|
||
});
|
||
}
|
||
// 跳转newPort
|
||
function goNewPort(id: number, serviceProviderId: number, address: string) {
|
||
router.replace({
|
||
name: address,
|
||
query: { pid: id, id: serviceProviderId },
|
||
});
|
||
}
|
||
|
||
function loadAll() {
|
||
return [{ value: '$FromAccount', key: 1 }];
|
||
}
|
||
|
||
onMounted(() => {
|
||
restaurants.value = loadAll();
|
||
});
|
||
|
||
let sortable: any = null;
|
||
// 参数拖拽
|
||
// 返回参数排序
|
||
let backSortArr: any[] = [];
|
||
function restore(
|
||
wrapperElem: any,
|
||
targetTrElem: any,
|
||
alternativeTrElem: any
|
||
) {
|
||
const insertBefore = isDraggedDown(targetTrElem, alternativeTrElem);
|
||
if (insertBefore) wrapperElem.insertBefore(targetTrElem, alternativeTrElem);
|
||
else insertAfter(targetTrElem, alternativeTrElem);
|
||
}
|
||
|
||
function insertAfter(newElement: any, targetElement: any) {
|
||
const parent = targetElement.parentNode;
|
||
if (parent.lastChild === targetElement) {
|
||
// 如果最后的节点是目标元素,则直接新增。因为默认是最后
|
||
parent.appendChild(newElement);
|
||
} else {
|
||
// 如果不是,则插入在目标元素的下一个兄弟节点 的前面。也就是目标元素的后面
|
||
parent.insertBefore(newElement, targetElement.nextSibling);
|
||
}
|
||
}
|
||
|
||
function isDraggedDown(targetTrElem: any, alternativeTrElem: any) {
|
||
const targetTrElemId = targetTrElem.getAttribute('rowid');
|
||
const alternativeTrElemId = alternativeTrElem.getAttribute('rowid');
|
||
const treeArray = XEUtils.toTreeArray(dialogTableProps.data) as any[]; // 按先序遍历输出树节点(与表格中从上到下行的排列顺序一致)
|
||
return treeArray.some((value, index) => {
|
||
// 若targetTrElem拖拽前在alternativeTrElem之前(即向下拖拽),返回true
|
||
if (
|
||
value.id === targetTrElemId &&
|
||
XEUtils.findIndexOf(
|
||
treeArray,
|
||
(item) => item.id === alternativeTrElemId
|
||
) > index
|
||
)
|
||
return true;
|
||
return false;
|
||
});
|
||
}
|
||
function findPrevRowOrItsAncestorIndex(
|
||
row: any,
|
||
selfNode: any,
|
||
tableData: any
|
||
): any {
|
||
let prevRowIndex = -1;
|
||
selfNode?.items.some((value: any, index: number) => {
|
||
if (value.id === row.id) {
|
||
prevRowIndex = index;
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
if (prevRowIndex === -1) {
|
||
const parentRow = XEUtils.findTree(
|
||
tableData,
|
||
(r: any) => {
|
||
return Number(r.pId) === Number(row?.id);
|
||
},
|
||
{
|
||
children: 'children',
|
||
}
|
||
);
|
||
console.log(parentRow, 'parentRow');
|
||
return findPrevRowOrItsAncestorIndex(parentRow, selfNode, tableData);
|
||
}
|
||
return prevRowIndex;
|
||
}
|
||
|
||
function treeDrop() {
|
||
const xTable = dialogTableRef.value?.xGrid;
|
||
const xe = XEUtils;
|
||
sortable = Sortable.create(
|
||
dialogTableRef.value?.$el.querySelector(
|
||
'.body--wrapper>.vxe-table--body tbody'
|
||
) as HTMLElement,
|
||
{
|
||
handle: '.sort',
|
||
onStart: () => {
|
||
getUpdataTableData();
|
||
},
|
||
// eslint-disable-next-line complexity
|
||
onEnd: ({ item, oldIndex }: any) => {
|
||
const options = { children: 'children' };
|
||
const wrapperElem = item.parentNode; // 移动后所处位置的父节点,由于vxe-table最终生成的dom节点都是同级的,只是节点text的缩进不同,所以移动前和移动后的父节点总是相同的
|
||
const targetTrElem = item; // 移动的节点
|
||
const alternativeTrElem = wrapperElem.children[oldIndex]; // 节点移动后,代替它原来位置的节点
|
||
const prevTrElem = targetTrElem.previousElementSibling; // 前面的兄弟节点(移动后所处位置的兄弟节点,不是移动前的)
|
||
const nextTrElem = targetTrElem.nextElementSibling; // 后面的兄弟节点
|
||
// console.log(tableRef.value?.xGrid.getTableData().tableData, "1111");
|
||
// const tableTreeData = tableProps.data?.length
|
||
// ? (tableProps.data as any[])
|
||
// : (tableRef.value?.xGrid.getTableData().tableData as any[])
|
||
const tableTreeData = dialogTableRef.value?.xGrid.getTableData()
|
||
.tableData as any[];
|
||
console.log(tableTreeData, 'tableTreeData');
|
||
const targetRowNode = xTable?.getRowNode(targetTrElem);
|
||
const selfRow = targetRowNode?.item;
|
||
const selfNode: any = XEUtils.findTree(
|
||
tableTreeData,
|
||
(row) => row === selfRow,
|
||
options
|
||
);
|
||
const pidData = xTable?.getParentRow(selfRow);
|
||
console.log(pidData, '当前行的父级');
|
||
if (prevTrElem) {
|
||
const prevRowNode = xTable?.getRowNode(prevTrElem);
|
||
const prevRow = prevRowNode?.item;
|
||
let preTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = false;
|
||
|
||
const preNode: any = xe.findTree(
|
||
tableTreeData,
|
||
(row) => {
|
||
return row.id === Number(prevTrElem.getAttribute('rowid'));
|
||
},
|
||
options
|
||
);
|
||
const preRow: any = preNode?.item;
|
||
console.log(selfRow, 'selfRow');
|
||
console.log(preRow, 'preRow');
|
||
if (selfRow?.pId === preRow?.pId || selfRow?.pId === preRow?.id)
|
||
preTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = true; // 若nextTrElem拖拽前和拖拽行同级,则为case2的情况
|
||
|
||
if (preTrElemIsOnSameLevelWidthTargetTrElemBeforeMove === false) {
|
||
restore(wrapperElem, targetTrElem, alternativeTrElem);
|
||
xTable?.clearTreeExpand();
|
||
console.log(1111);
|
||
$message.error('仅支持同级拖动');
|
||
return;
|
||
}
|
||
|
||
if (xTable?.isTreeExpandByRow(prevRow)) {
|
||
// 如果拖拽后,preRow有子节点,且preRow是展开状态
|
||
// if (prevRow.children && prevRow.chil dren.length > 0) { // 通过children只能判断是否为父节点,不能判断是否是展开状态
|
||
// 移动到当前的子节点
|
||
if (selfRow?.pId !== prevRow?.id) {
|
||
// 如果拖拽后的额父节点和新的父节点不一致,不允许
|
||
console.log(1111);
|
||
restore(wrapperElem, targetTrElem, alternativeTrElem);
|
||
$message.error('仅支持同级拖动');
|
||
return;
|
||
}
|
||
selfNode.items.splice(selfNode.index, 1);
|
||
// console.log(selfNode.parent.children, 'selfNode.parent.children')
|
||
console.log(pidData, ' pidData');
|
||
console.log(tableTreeData, 'tableTreeData');
|
||
const ac = tableTreeData.find((i) => i.id === pidData.id);
|
||
selfNode.items.unshift(selfRow); // 在数组头部新增节点
|
||
ac.children = [];
|
||
selfNode.items.forEach((item: any) => {
|
||
ac.children.push(item);
|
||
});
|
||
console.log(selfNode.items, 'selfNode.itemsselfNode.items');
|
||
console.log(ac, 'acacacac');
|
||
} else {
|
||
// 拖拽后,和preRow是兄弟节点或和preRow的祖先节点是兄弟节点
|
||
// 移动到相邻节点
|
||
|
||
if (selfRow.pId !== prevRow.id) {
|
||
// 拖动的节点和它前面的节点在拖拽前不是同级节点
|
||
|
||
if (
|
||
xe.findTree(
|
||
selfRow[options.children],
|
||
(row) => prevRow === row,
|
||
options
|
||
)
|
||
) {
|
||
// 这里selfRow[options.children]是移动前的数据,不是移动后的
|
||
// 错误的移动
|
||
console.log(1111);
|
||
restore(wrapperElem, targetTrElem, alternativeTrElem);
|
||
$message.error('仅支持同级拖动');
|
||
return;
|
||
}
|
||
|
||
let nextTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = true;
|
||
console.log(nextTrElem, 'nextTrElem');
|
||
if (nextTrElem) {
|
||
const nextNode: any = xe.findTree(
|
||
tableTreeData,
|
||
(row) => {
|
||
return (
|
||
row.id === Number(nextTrElem.getAttribute('rowid'))
|
||
);
|
||
},
|
||
options
|
||
);
|
||
const nextRow: any = nextNode.item;
|
||
console.log(nextRow, 'nextRow');
|
||
console.log(selfRow, 'selfRow');
|
||
console.log(prevRow, 'prevRow');
|
||
if (selfRow.pId !== nextRow.pId)
|
||
nextTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = false; // 若nextTrElem拖拽前和拖拽行同级,则为case2的情况
|
||
|
||
if (prevRow.pId === selfRow.pId)
|
||
nextTrElemIsOnSameLevelWidthTargetTrElemBeforeMove = true;
|
||
}
|
||
|
||
if (
|
||
nextTrElemIsOnSameLevelWidthTargetTrElemBeforeMove === false
|
||
) {
|
||
restore(wrapperElem, targetTrElem, alternativeTrElem);
|
||
console.log(1111);
|
||
$message.error('仅支持同级拖动');
|
||
return;
|
||
}
|
||
}
|
||
|
||
const sliceRow = selfNode?.items.splice(selfNode.index, 1)[0];
|
||
console.log(sliceRow);
|
||
const prevRowIndex = findPrevRowOrItsAncestorIndex(
|
||
prevRow,
|
||
selfNode,
|
||
tableTreeData
|
||
); // case2的情况,prevRow不在selfNode.items中,需要递归寻找祖先节点在selfNode.items中的位置(或者获取nextNode的index,插到nextNode前面?nextNode可能也不是同一级节点)
|
||
console.log(prevRowIndex, 'prevRowIndex');
|
||
selfNode.items.splice(prevRowIndex + 1, 0, selfRow);
|
||
if (
|
||
isDraggedDown(targetTrElem, alternativeTrElem) &&
|
||
xTable?.isTreeExpandByRow(selfRow)
|
||
) {
|
||
// 如果是向下拖拽节点,且拖拽节点是展开状态的父节点,需要将其子节点dom元素移动位置,否则子节点不会随父节点移动(向上拖拽时没有这个问题,不知道为什么)
|
||
let lastInsertTrElem = targetTrElem;
|
||
while (oldIndex < wrapperElem.children.length) {
|
||
const trElem = wrapperElem.children[oldIndex];
|
||
const isSiblingNodes = selfNode.items.some(
|
||
(value: any) => value.id === trElem.getAttribute('rowid')
|
||
);
|
||
if (isSiblingNodes) {
|
||
// 如果当前节点是节点拖拽前的兄弟节点,说明子节点已经全部访问完了, 停止迭代
|
||
break;
|
||
}
|
||
insertAfter(trElem, lastInsertTrElem);
|
||
lastInsertTrElem = trElem;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// 移动到第一行
|
||
console.log(selfRow, 'selfRow');
|
||
if (selfRow.pId !== 0) {
|
||
// 移动后位于第一行,父节点就是000000,若原来的父节点不是000000,则改变了父节点,不允许
|
||
restore(wrapperElem, targetTrElem, alternativeTrElem);
|
||
console.log(1111);
|
||
$message.error('仅支持同级拖动');
|
||
return;
|
||
}
|
||
const sliceRow = selfNode?.items.splice(selfNode.index, 1)[0];
|
||
console.log(sliceRow, 'sliceRow');
|
||
tableTreeData.unshift(selfRow);
|
||
}
|
||
console.log(tableTreeData, 'tableTreeDatatableTreeData');
|
||
const newArr = tableTreeData?.filter((item) => !item.pId) || [];
|
||
// console.log(newArr, 'asdasddsa')
|
||
// console.log(flattenArray(newArr))
|
||
// backSortArr = flattenArray(newArr)
|
||
// 如果变动了树层级,需要刷新数据
|
||
dialogTableProps.data = [...flattenArray(newArr)];
|
||
setTimeout(() => {
|
||
backSortArr = (flattenArray(newArr).map((item: any) => {
|
||
return {
|
||
...item,
|
||
sort: getRowSeq(item, dialogTableRef.value),
|
||
};
|
||
}) as any[]);
|
||
|
||
console.log(backSortArr);
|
||
}, 300);
|
||
},
|
||
}
|
||
);
|
||
}
|
||
|
||
// 获取行号
|
||
function getRowSeq(row: any, ref: any) {
|
||
return ref.xGrid?.getRowSeq(row);
|
||
}
|
||
|
||
function flattenArray(arr: any[]): any[] {
|
||
return arr.reduce((acc, val) => {
|
||
if (Array.isArray(val.children) && val.children.length) {
|
||
// delete val.children
|
||
return acc.concat(val, flattenArray(val.children));
|
||
}
|
||
return acc.concat(val);
|
||
}, []);
|
||
}
|
||
|
||
let initTime: any;
|
||
|
||
interface Indexable {
|
||
[key: string]: any;
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="application-trb-transform">
|
||
<div class="bg-white">
|
||
<TablePro ref="tableRef" v-bind="tableProps">
|
||
<template #toolbar_buttons>
|
||
<div class="toolbar-buttons">
|
||
<div>
|
||
<a-button type="primary" @click="addParameter">
|
||
{{ t('新增系统参数') }}
|
||
</a-button>
|
||
</div>
|
||
<div class="flex">
|
||
<div class="text-style">
|
||
<span class="label">{{ t('系统接口') }}:</span>
|
||
<span
|
||
class="value cursor-pointer"
|
||
@click="goRouter(props.addId, 'CreateInterface2')"
|
||
>
|
||
{{ props?.systemInterfaceName }}
|
||
</span>
|
||
</div>
|
||
<div class="text-style">
|
||
<span class="label">{{ t('映射服务商') }}:</span>
|
||
<span
|
||
class="value cursor-pointer"
|
||
@click="
|
||
goRouter(
|
||
props.serviceProviderId,
|
||
'ServiceInterface',
|
||
'goRouter'
|
||
)
|
||
"
|
||
>
|
||
{{ props?.serviceProviderName }}
|
||
</span>
|
||
</div>
|
||
<div class="text-style">
|
||
<span class="label">{{ t('映射服务商接口') }}:</span>
|
||
<span
|
||
class="value cursor-pointer"
|
||
@click="
|
||
goNewPort(props.intId!, props.serviceProviderId!, 'NewPort')
|
||
"
|
||
>
|
||
{{ props?.interfaceName }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<template #isRequired_edit="{ row }">
|
||
<span :class="{ 'text-red-500': row.isRequired }">
|
||
{{ row.isRequired ? '是' : '否' }}
|
||
</span>
|
||
</template>
|
||
<template #fixed_edit="{ row }">
|
||
<a-auto-complete
|
||
v-model="row.fixedValue"
|
||
:data="restaurants"
|
||
:filter-option="
|
||
(inputValue, option) =>
|
||
option.value.toLowerCase().includes(inputValue.toLowerCase())
|
||
"
|
||
allow-clear
|
||
@select="(e) => (row.fixedValue = e)"
|
||
@change="
|
||
(e) => {
|
||
row.fixedValue = e;
|
||
}
|
||
"
|
||
/>
|
||
</template>
|
||
<template #mapAlias_edit="{ row }">
|
||
<SelectPro
|
||
v-model="row.mapId"
|
||
:options="{
|
||
spareData: formsTypeList,
|
||
labelKey: ['alias', 'cnName'],
|
||
valueKey: 'id',
|
||
noPage: true,
|
||
}"
|
||
@change="formsChange(row)"
|
||
@clear="formsClear(row)"
|
||
@dropdown-visible-change="visibleChange"
|
||
/>
|
||
</template>
|
||
</TablePro>
|
||
|
||
<div class="flex justify-end pb-16px">
|
||
<a-space>
|
||
<a-button @click="close"> 取消 </a-button>
|
||
<a-button type="primary" @click="addMapClick"> 确定 </a-button>
|
||
</a-space>
|
||
</div>
|
||
|
||
<ModalPro
|
||
v-model:visible="dialogVisible"
|
||
:width="900"
|
||
title="请求参数"
|
||
@cancel="delClick"
|
||
@ok="serveForm"
|
||
@register="register"
|
||
>
|
||
<TablePro
|
||
ref="dialogTableRef"
|
||
:table-config="dialogTableProps.tableConfig"
|
||
:data="dialogTableProps.data"
|
||
:edit-rules="dialogTableRules"
|
||
:row-config="{ isHover: true }"
|
||
:tree-config="{ transform: true, rowField: 'id', parentField: 'pId' }"
|
||
:mouse-config="{ area: false }"
|
||
:use-form="false"
|
||
keep-source
|
||
show-overflow
|
||
show-header-overflow
|
||
:height="350"
|
||
size="small"
|
||
>
|
||
<template #toolbar_buttons>
|
||
<TableButtons
|
||
:actions="[
|
||
{
|
||
label: t('新增参数'),
|
||
type: 'primary',
|
||
onClick: addClick,
|
||
},
|
||
]"
|
||
/>
|
||
</template>
|
||
<template #asdsad>
|
||
<div class="text-center">
|
||
<icon-drag-dot-vertical class="cursor-move" />
|
||
</div>
|
||
</template>
|
||
<template #name_edit="{ row }">
|
||
<a-input v-model="row.name" placeholder="请输入参数名" />
|
||
</template>
|
||
<template #cnName_edit="{ row }">
|
||
<a-input v-model="row.cnName" placeholder="请输入参数名(中文)" />
|
||
</template>
|
||
<template #type_default="{ row }">
|
||
<span>{{ formatType(row.type) }}</span>
|
||
</template>
|
||
<template #type_edit="{ row }">
|
||
<SelectPro
|
||
v-model="row.type"
|
||
:disabled="row.children?.length"
|
||
:options="{
|
||
spareData: ParameterTypeList,
|
||
labelKey: ['value'],
|
||
valueKey: 'key',
|
||
noPage: true,
|
||
}"
|
||
/>
|
||
</template>
|
||
<template #description_edit="{ row }">
|
||
<a-input v-model="row.description" placeholder="请输入参数描述" />
|
||
</template>
|
||
<template #action="{ row }">
|
||
<a-space>
|
||
<a-button type="text" status="primary" @click="addRow(row)">
|
||
{{ t('新增') }}
|
||
</a-button>
|
||
<a-button type="text" status="danger" @click="delRow(row)">
|
||
{{ t('删除') }}
|
||
</a-button>
|
||
</a-space>
|
||
</template>
|
||
</TablePro>
|
||
</ModalPro>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang="less">
|
||
.button-footer {
|
||
justify-content: center;
|
||
width: 100%;
|
||
padding-top: 20px;
|
||
}
|
||
|
||
.text-style {
|
||
display: flex;
|
||
margin-right: 15px;
|
||
|
||
.label {
|
||
margin: 7px 10px 0 0;
|
||
}
|
||
|
||
.value {
|
||
margin: 7px 15px 0 0;
|
||
font-weight: 600;
|
||
color: var(--color-primary);
|
||
text-decoration: underline;
|
||
}
|
||
}
|
||
|
||
.toolbar-buttons {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.main-box {
|
||
padding: 20px;
|
||
}
|
||
|
||
.span-style {
|
||
margin-top: 5px;
|
||
font-size: 17px;
|
||
font-weight: 900;
|
||
}
|
||
|
||
.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>
|