<script lang="ts" setup>
|
import type { TreeActionType } from '@jnpf/ui';
|
import type { BasicColumn } from '@jnpf/ui/vxeTable';
|
|
import { computed, reactive, ref, unref, watch } from 'vue';
|
|
import { BasicLeftTree } from '@jnpf/ui';
|
import { ModalClose } from '@jnpf/ui/modal';
|
import { BasicVxeTable, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import { Modal as AModal, Form } from 'ant-design-vue';
|
import { pick } from 'lodash-es';
|
import { Grid as VxeGrid } from 'vxe-table';
|
|
import { getDataInterfaceSelectorList } from '#/api/systemData/dataInterface';
|
import { $t } from '#/locales';
|
import { useBaseStore } from '#/store';
|
|
defineOptions({ inheritAttrs: false });
|
const props = defineProps({
|
value: { default: '' },
|
title: { type: String, default: '' },
|
popupTitle: { type: String, default: '数据接口' },
|
dataType: { type: String, default: '' },
|
disabled: { type: Boolean, default: false },
|
allowClear: { type: Boolean, default: true },
|
size: { type: String, default: 'default' },
|
/**
|
* sourceType
|
* 1 - 过滤掉:鉴权、真分页、SQL的增加、修改、删除类型
|
* 2 - 过滤掉:鉴权、SQL的增加、修改、删除类型
|
* 3 - 过滤掉:鉴权、真分页、SQL的查询类型
|
*/
|
sourceType: { type: Number, default: 1 },
|
});
|
const emit = defineEmits(['update:value', 'change']);
|
const formItemContext = Form.useInjectFormItemContext();
|
const baseStore = useBaseStore();
|
const innerValue = ref(undefined);
|
const visible = ref(false);
|
const options = ref<any[]>([]);
|
|
const columns: BasicColumn[] = [
|
{ title: '名称', dataIndex: 'fullName', minWidth: 100 },
|
{ title: '编码', dataIndex: 'enCode', width: 150 },
|
{ title: '类型', dataIndex: 'type', width: 100 },
|
];
|
const templateColumns: BasicColumn[] = [
|
{ title: $t('component.table.index'), type: 'seq', width: 50, align: 'center' },
|
{ title: '参数名称', dataIndex: 'field', key: 'field', minWidth: 100, slots: { default: 'field' } },
|
{ title: '参数类型', dataIndex: 'dataType', key: 'dataType', width: 150, slots: { default: 'dataType' } },
|
{ title: '默认值', dataIndex: 'defaultValue', key: 'defaultValue', width: 100 },
|
];
|
const typeOptions: any[] = [
|
{ fullName: '字符串', id: 'varchar' },
|
{ fullName: '整型', id: 'int' },
|
{ fullName: '日期时间', id: 'datetime' },
|
{ fullName: '浮点', id: 'decimal' },
|
{ fullName: '长整型', id: 'bigint' },
|
{ fullName: '文本', id: 'text' },
|
];
|
const searchInfo = reactive({
|
category: '',
|
sourceType: props.sourceType,
|
});
|
const leftTreeRef = ref<Nullable<TreeActionType>>(null);
|
const treeLoading = ref(false);
|
const treeData = ref<any[]>([]);
|
const [registerTable, { getForm, getSelectRows, setSelectedRowKeys, getSelectRowKeys }] = useVxeTable({
|
api: getDataInterfaceSelectorList,
|
columns,
|
immediate: false,
|
useSearchForm: true,
|
showExpandColumn: true,
|
formConfig: {
|
baseColProps: { span: 8 },
|
schemas: [
|
{
|
field: 'keyword',
|
label: $t('common.keyword'),
|
component: 'Input',
|
componentProps: {
|
placeholder: $t('common.enterKeyword'),
|
submitOnPressEnter: true,
|
},
|
},
|
{
|
field: 'type',
|
label: '类型',
|
component: 'Select',
|
componentProps: {
|
options: [
|
{ id: '2', fullName: '静态数据' },
|
{ id: '1', fullName: 'SQL操作' },
|
{ id: '3', fullName: 'API操作' },
|
],
|
},
|
},
|
],
|
},
|
tableSetting: { size: false, setting: false },
|
rowSelection: { type: 'radio' },
|
afterFetch: (data) => {
|
const list = data.map((o) => {
|
let templateJson = o.parameterJson ? JSON.parse(o.parameterJson) : [];
|
if (!templateJson) templateJson = [];
|
return {
|
...o,
|
templateJson,
|
};
|
});
|
setTimeout(() => {
|
setSelectedRowKeys(innerValue.value ? [innerValue.value] : []);
|
}, 100);
|
return list;
|
},
|
});
|
|
const getSelectBindValue = computed(() => {
|
return {
|
...pick(props, ['disabled', 'size', 'allowClear']),
|
fieldNames: { label: 'fullName', value: 'id' },
|
placeholder: '请选择',
|
open: false,
|
showSearch: false,
|
showArrow: true,
|
};
|
});
|
|
watch(
|
() => props.value,
|
(val) => {
|
setValue(val);
|
},
|
{ immediate: true },
|
);
|
watch(
|
() => props.title,
|
() => {
|
setValue(props.value);
|
},
|
);
|
|
function getTypeText(type) {
|
const item = typeOptions.find((o) => o.id == type);
|
return item && item.fullName ? item.fullName : '';
|
}
|
function setValue(value) {
|
innerValue.value = value || undefined;
|
options.value = [{ id: innerValue.value, fullName: props.title }];
|
}
|
function onChange() {
|
options.value = [];
|
emit('change', '', {});
|
}
|
async function openSelectModal() {
|
if (props.disabled) return;
|
visible.value = true;
|
treeLoading.value = true;
|
treeData.value = (await baseStore.getDictionaryData('DataInterfaceType')) as any[];
|
if (!treeData.value.length) return (treeLoading.value = false);
|
searchInfo.category = treeData.value[0].id;
|
const leftTree = unref(leftTreeRef);
|
leftTree?.setSelectedKeys([searchInfo.category]);
|
treeLoading.value = false;
|
getForm().resetFields();
|
}
|
function handleTreeSelect(id) {
|
if (!id || searchInfo.category === id) return;
|
searchInfo.category = id;
|
searchInfo.sourceType = props.sourceType;
|
getForm().resetFields();
|
}
|
function handleCancel() {
|
visible.value = false;
|
}
|
function handleSubmit() {
|
if (!getSelectRowKeys().length && !getSelectRows().length) return;
|
if (!getSelectRows().length) {
|
emit('update:value', innerValue.value);
|
emit('change', innerValue.value, options.value[0]);
|
formItemContext.onFieldChange();
|
handleCancel();
|
return;
|
}
|
const selectRow: any = getSelectRows()[0];
|
options.value = getSelectRows();
|
innerValue.value = selectRow.id;
|
emit('update:value', selectRow.id);
|
emit('change', selectRow.id, selectRow);
|
formItemContext.onFieldChange();
|
handleCancel();
|
}
|
</script>
|
|
<template>
|
<div class="common-container">
|
<a-select v-model:value="innerValue" v-bind="getSelectBindValue" :options="options" @change="onChange" @click="openSelectModal" />
|
<AModal
|
v-model:open="visible"
|
:title="popupTitle"
|
:width="1000"
|
class="common-container-modal"
|
@ok="handleSubmit"
|
@cancel="handleCancel"
|
:mask-closable="false"
|
destroy-on-close>
|
<template #closeIcon>
|
<ModalClose :can-fullscreen="false" @cancel="handleCancel" />
|
</template>
|
<div class="jnpf-content-wrapper">
|
<div class="jnpf-content-wrapper-left">
|
<BasicLeftTree ref="leftTreeRef" :show-search="false" :tree-data="treeData" :loading="treeLoading" @select="handleTreeSelect" />
|
</div>
|
<div class="jnpf-content-wrapper-center">
|
<div class="jnpf-content-wrapper-content">
|
<BasicVxeTable @register="registerTable" :search-info="searchInfo" class="jnpf-sub-table">
|
<template #expandedRowRender="{ record }">
|
<VxeGrid :data="record.templateJson" :columns="templateColumns" :min-height="0">
|
<template #field="{ row: childRecord }">
|
<span class="required-sign">{{ childRecord.required ? '*' : '' }}</span>
|
{{ childRecord.field }}{{ childRecord.fieldName ? `(${childRecord.fieldName})` : '' }}
|
</template>
|
<template #dataType="{ row: childRecord }">
|
{{ getTypeText(childRecord.dataType) }}
|
</template>
|
</VxeGrid>
|
</template>
|
</BasicVxeTable>
|
</div>
|
</div>
|
</div>
|
</AModal>
|
</div>
|
</template>
|