<script lang="ts" setup>
|
import { computed, nextTick, onMounted, reactive, ref, toRefs, unref } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { ScrollContainer } from '@jnpf/ui';
|
import { useModal } from '@jnpf/ui/modal';
|
import { buildBitUUID } from '@jnpf/utils';
|
|
import { usePreferences } from '@vben/preferences';
|
|
import { CheckOutlined } from '@ant-design/icons-vue';
|
import { useDebounceFn } from '@vueuse/core';
|
import { TreeSelect } from 'ant-design-vue';
|
import { cloneDeep } from 'lodash-es';
|
import Sortablejs from 'sortablejs';
|
import draggable from 'vuedraggable';
|
|
import { getPrintDevSelector } from '#/api/system/printDev';
|
import { getDataInterfaceInfo, getDataInterfaceRes } from '#/api/systemData/dataInterface';
|
import { getDictionaryDataSelector, getDictionaryTypeSelector } from '#/api/systemData/dictionary';
|
import columnTypeDark1 from '#/assets/images/generator/columnType1-dark.png';
|
import columnType1 from '#/assets/images/generator/columnType1.png';
|
import columnTypeDark2 from '#/assets/images/generator/columnType2-dark.png';
|
import columnType2 from '#/assets/images/generator/columnType2.png';
|
import columnTypeDark3 from '#/assets/images/generator/columnType3-dark.png';
|
import columnType3 from '#/assets/images/generator/columnType3.png';
|
import columnTypeDark4 from '#/assets/images/generator/columnType4-dark.png';
|
import columnType4 from '#/assets/images/generator/columnType4.png';
|
import columnTypeDark5 from '#/assets/images/generator/columnType5-dark.png';
|
import columnType5 from '#/assets/images/generator/columnType5.png';
|
import { InterfaceModal } from '#/components/CommonModal';
|
import { dyOptionsList } from '#/components/FormGenerator/src/helper/config';
|
import { SelectInterfaceBtn } from '#/components/Interface';
|
import { alignOptions, fixedOptions } from '#/utils/constants';
|
import { getParamList } from '#/utils/jnpf';
|
|
import {
|
defaultBtnEnableFunc,
|
defaultBtnsList,
|
defaultColumnBtnsList,
|
defaultColumnData,
|
defaultFuncsData,
|
getDefaultValue,
|
getSearchMultiple,
|
getSearchType,
|
getSysFieldList,
|
noColumnShowList,
|
noGroupList,
|
noSearchList,
|
noUploadList,
|
sourceTypeOptions,
|
} from '../helper/config';
|
import BtnEvent from './BtnEvent.vue';
|
import ComplexHeaderModal from './ComplexHeaderModal.vue';
|
import ConditionModal from './ConditionModal.vue';
|
import DefaultSortConfigModal from './DefaultSortConfigModal.vue';
|
import ExtraConfigModal from './ExtraConfigModal.vue';
|
import FormScript from './FormScript.vue';
|
import UpLoadTpl from './UpLoadTpl.vue';
|
|
interface State {
|
columnData: any;
|
groupFieldOptions: any[];
|
treeFieldOptions: any[];
|
tabRelationFieldOptions: any[];
|
columnOptions: any[];
|
searchOptions: any[];
|
defaultBtnsList: any[];
|
defaultColumnBtnsList: any[];
|
activeFunc: string;
|
activeBtn: string;
|
searchSelectedRowKeys: string[];
|
columnSelectedRowKeys: string[];
|
printTplOptions: any[];
|
allOptions: any[];
|
options: any[];
|
activeSearchRowIndex: number;
|
}
|
|
const props = defineProps(['conf', 'formInfo', 'viewFields', 'interfaceParam', 'interfaceHasPage']);
|
defineExpose({ getData });
|
const { createMessage } = useMessage();
|
const debounceOnSearch = useDebounceFn(onSearch, 300);
|
const treeDataSourceOptions = [
|
{ id: 'dictionary', fullName: '数据字典' },
|
{ id: 'api', fullName: '数据接口' },
|
{ id: 'organize', fullName: '组织数据' },
|
{ id: 'formField', fullName: '表单控件' },
|
];
|
const treeSyncTypeOptions = [
|
{ id: 0, fullName: '同步' },
|
{ id: 1, fullName: '异步' },
|
];
|
const childTableStyleOptions = [
|
{ id: 1, fullName: '分组展示' },
|
{ id: 2, fullName: '折叠展示' },
|
];
|
const pageSizeOptions = [
|
{ id: 20, fullName: '20条' },
|
{ id: 50, fullName: '50条' },
|
{ id: 80, fullName: '80条' },
|
{ id: 100, fullName: '100条' },
|
];
|
const treeSyncTemplateJsonColumns = [
|
{ width: 50, title: '序号', align: 'center', customRender: ({ index }) => index + 1 },
|
{ title: '参数名称', dataIndex: 'field', key: 'field', width: 135 },
|
{ title: '表单字段', dataIndex: 'relationField', key: 'relationField', width: 135 },
|
];
|
const columnColumns = [
|
{ title: '拖动', dataIndex: 'drag', key: 'drag', align: 'center', width: 50 },
|
{ title: '列名', dataIndex: 'label', key: 'label', width: 200 },
|
{ title: '字段', dataIndex: 'prop', key: 'prop' },
|
{ title: '排序', dataIndex: 'sortable', key: 'sortable', width: 60, align: 'center' },
|
{ title: '冻结', dataIndex: 'fixed', key: 'fixed', width: 150 },
|
{ title: '标题对齐', dataIndex: 'headerAlign', key: 'headerAlign', width: 150 },
|
{ title: '内容对齐', dataIndex: 'align', key: 'align', width: 150 },
|
{ title: '宽度', dataIndex: 'width', key: 'width', width: 150 },
|
];
|
const rightColumns = [{ title: '字段', dataIndex: 'fullName', key: 'fullName' }];
|
|
const webType = computed(() => props.formInfo?.webType);
|
const getTypeList = computed(() => {
|
const { isDark } = usePreferences();
|
const type1 = isDark.value ? columnTypeDark1 : columnType1;
|
const type2 = isDark.value ? columnTypeDark2 : columnType2;
|
const type3 = isDark.value ? columnTypeDark3 : columnType3;
|
const type4 = isDark.value ? columnTypeDark4 : columnType4;
|
const type5 = isDark.value ? columnTypeDark5 : columnType5;
|
let list = [
|
{ url: type1, value: 1, name: '普通表格' },
|
{ url: type2, value: 2, name: '左侧树+普通表格' },
|
{ url: type4, value: 4, name: '编辑表格' },
|
{ url: type3, value: 3, name: '分组表格' },
|
{ url: type5, value: 5, name: '树形表格' },
|
];
|
if (unref(webType) == 4) list = list.filter((o) => o.value == 1 || o.value == 3);
|
return list;
|
});
|
const searchColumns = computed(() => {
|
let list = [
|
{ title: '拖动', dataIndex: 'drag', key: 'drag', align: 'center', width: 50 },
|
{ title: '列名', dataIndex: 'label', key: 'label', width: 200 },
|
{ title: '字段', dataIndex: 'prop', key: 'prop' },
|
{ title: '输入类型', dataIndex: 'jnpfKey', key: 'jnpfKey', width: 200 },
|
{ title: '条件类型', dataIndex: 'searchType', key: 'searchType', width: 100 },
|
{ title: '默认值类型', dataIndex: 'sourceType', key: 'sourceType', width: 100 },
|
{ title: '默认值', dataIndex: 'value', key: 'value', width: 200 },
|
{ title: '关键词', dataIndex: 'isKeyword', key: 'isKeyword', width: 70, align: 'center' },
|
{ title: '是否多选', dataIndex: 'searchMultiple', key: 'searchMultiple', width: 80, align: 'center' },
|
{ title: '是否隐藏', dataIndex: 'noShow', key: 'noShow', width: 80, align: 'center' },
|
];
|
list = unref(webType) == 4 ? list.filter((o) => o.dataIndex != 'isKeyword') : list.filter((o) => o.dataIndex != 'jnpfKey');
|
return list;
|
});
|
const multipleList = ['select', 'roleSelect', 'userSelect', 'usersSelect', 'organizeSelect', 'posSelect', 'groupSelect'];
|
const canSetKeyword = ['input', 'textarea', 'autoComplete'];
|
const canSetAttrs = ['select', 'datePicker', 'timePicker', 'organizeSelect', 'userSelect', 'posSelect'];
|
const searchTypeOptions = [
|
{ id: 1, fullName: '等于查询' },
|
{ id: 2, fullName: '模糊查询' },
|
{ id: 3, fullName: '范围查询' },
|
];
|
const viewJnpfKeyOptions = [
|
{ id: 'input', fullName: '单行输入' },
|
{ id: 'inputNumber', fullName: '数字输入' },
|
{ id: 'select', fullName: '下拉选择' },
|
{ id: 'datePicker', fullName: '日期选择' },
|
{ id: 'timePicker', fullName: '时间选择' },
|
{ id: 'organizeSelect', fullName: '组织选择' },
|
{ id: 'roleSelect', fullName: '角色选择' },
|
{ id: 'posSelect', fullName: '岗位选择' },
|
{ id: 'groupSelect', fullName: '分组选择' },
|
{ id: 'userSelect', fullName: '用户选择' },
|
];
|
const showInputList = ['input', 'billRule'];
|
const showSelectList = ['checkbox', 'radio', 'select'];
|
|
const activeKey = ref('column');
|
const dicOptions = ref<any[]>([]);
|
const state = reactive<State>({
|
columnData: cloneDeep(defaultColumnData),
|
groupFieldOptions: [],
|
treeFieldOptions: [],
|
tabRelationFieldOptions: [],
|
columnOptions: [],
|
searchOptions: [],
|
defaultBtnsList: [],
|
defaultColumnBtnsList: [],
|
activeFunc: '',
|
activeBtn: '',
|
searchSelectedRowKeys: [],
|
columnSelectedRowKeys: [],
|
printTplOptions: [],
|
allOptions: [],
|
options: [],
|
activeSearchRowIndex: 0,
|
});
|
const { columnData, searchSelectedRowKeys, columnSelectedRowKeys, printTplOptions, options } = toRefs(state);
|
const [registerScriptModal, { openModal: openScriptModal }] = useModal();
|
const [registerUpLoadTplModal, { openModal: openUpLoadTplModal }] = useModal();
|
const [registerBtnEventModal, { openModal: openBtnEventModal }] = useModal();
|
const [registerConditionModal, { openModal: openConditionModal }] = useModal();
|
const [registerComplexHeaderModal, { openModal: openComplexHeaderModal }] = useModal();
|
const [registerDefaultSortConfigModal, { openModal: openDefaultSortConfigModal }] = useModal();
|
const [registerExtraConfigModal, { openModal: openExtraConfigModal }] = useModal();
|
|
const getDrawingList = computed(() => {
|
if (!props.formInfo || !props.formInfo.formData) return [];
|
const formData = props.formInfo?.formData && JSON.parse(props.formInfo.formData);
|
return formData.fields || [];
|
});
|
const getRuleBtnText = computed(() => (state.columnData?.ruleList?.conditionList?.length ? '编辑过滤条件' : '添加过滤条件'));
|
const formFieldsOptions = computed(() => {
|
const list: any[] = [];
|
const loop = (data, parent?) => {
|
if (!data) return;
|
if (data.__config__ && data.__config__.children && Array.isArray(data.__config__.children)) {
|
loop(data.__config__.children, data);
|
}
|
if (Array.isArray(data)) data.forEach((d) => loop(d, parent));
|
if (data.__config__ && data.__config__.jnpfKey) {
|
const visibility = !data.__config__.visibility || (Array.isArray(data.__config__.visibility) && data.__config__.visibility.includes('pc'));
|
if (data.__config__.layout === 'colFormItem' && data.__vModel__ && visibility) {
|
const isTableChild = parent && parent.__config__ && parent.__config__.jnpfKey === 'table';
|
list.push({
|
id: isTableChild ? `${parent.__vModel__}-${data.__vModel__}` : data.__vModel__,
|
fullName: isTableChild ? `${parent.__config__.label}-${data.__config__.label}` : data.__config__.label,
|
fullNameI18nCode: isTableChild ? [parent.__config__.labelI18nCode || '', data.__config__.labelI18nCode || ''] : [data.__config__.labelI18nCode || ''],
|
...data,
|
});
|
}
|
}
|
};
|
loop(unref(getDrawingList));
|
return list;
|
});
|
const viewFieldOptions = computed(() => {
|
if (!props.viewFields) return [];
|
return props.viewFields.map((o) => ({ id: o.defaultValue, fullName: o.field, __vModel__: o.defaultValue, __config__: { jnpfKey: 'input' } }));
|
});
|
const selectOptions = computed(() => {
|
let options = unref(formFieldsOptions).map((o) => ({ ...o, disabled: false }));
|
if (state.columnData.treeDataSource === 'formField') options = options.filter((o) => o.__config__.jnpfKey === 'organizeSelect');
|
return options;
|
});
|
const summaryFieldOptions = computed(() =>
|
state.groupFieldOptions.filter((o) => ['calculate', 'input', 'inputNumber'].includes(o.__config__.jnpfKey) && o.__vModel__ && !o.useMask),
|
);
|
const getSearchOptions = computed(() => {
|
if (state.columnData.type == 2 && state.columnData.treeRelation) return state.searchOptions.filter((o) => o.id !== state.columnData.treeRelation);
|
if ([1, 4].includes(state.columnData.type) && state.columnData.tabConfig.relationField && state.columnData.tabConfig.on) {
|
return state.searchOptions.filter((o) => o.id !== state.columnData.tabConfig.relationField);
|
}
|
return state.searchOptions;
|
});
|
const getIsKeywordDisabled = computed(() => state.columnData.searchList.filter((o) => o.isKeyword).length >= 3);
|
|
// 供父组件使用 获取表单JSON
|
function getData() {
|
if (!state.columnData.columnList.length) {
|
createMessage.warning('列表字段不允许为空');
|
return;
|
}
|
if (state.columnData.type == 2) {
|
if (state.columnData.treeDataSource === 'dictionary' && !state.columnData.treeDictionary) {
|
createMessage.warning('请选择数据字典');
|
return;
|
}
|
if (state.columnData.treeDataSource === 'api') {
|
if (!state.columnData.treePropsValue) {
|
createMessage.warning('请输入主键字段');
|
return;
|
}
|
if (!state.columnData.treePropsLabel) {
|
createMessage.warning('请输入回显字段');
|
return;
|
}
|
if (!state.columnData.treePropsChildren) {
|
createMessage.warning('请输入子级字段');
|
return;
|
}
|
}
|
if (!state.columnData.treeRelation) {
|
createMessage.warning('请选择关联字段');
|
return;
|
}
|
if (!state.columnData.treeSyncInterfaceId && state.columnData.treeSyncType == 1) {
|
createMessage.warning('请选择异步数据接口');
|
return;
|
}
|
}
|
if (state.columnData.type == 3 && !state.columnData.groupField) {
|
createMessage.warning('请选择分组字段');
|
return;
|
}
|
if (state.columnData.type == 5 && !state.columnData.parentField) {
|
createMessage.warning('请选择父级字段');
|
return;
|
}
|
if (
|
state.columnData.type !== 5 &&
|
state.columnData.btnsList.some((o) => o.value === 'upload' && o.show) &&
|
!state.columnData.uploaderTemplateJson?.selectKey
|
) {
|
createMessage.warning('请设置导入模板');
|
return;
|
}
|
if (state.columnData.type !== 5 && state.columnData.btnsList.some((o) => o.value === 'batchPrint' && o.show) && !state.columnData.printIds?.length) {
|
createMessage.warning('请选择打印模板');
|
return;
|
}
|
state.columnData.defaultColumnList = state.columnOptions.map((o) => ({
|
...o,
|
checked: state.columnData.columnList.some((i) => i.prop === o.prop),
|
}));
|
return state.columnData;
|
}
|
function getDictionaryType() {
|
getDictionaryTypeSelector().then((res) => {
|
dicOptions.value = res.data.list.filter((o) => o.children && o.children.length);
|
});
|
}
|
function getPrintTplList() {
|
getPrintDevSelector().then((res) => {
|
state.printTplOptions = res.data.list.filter((o) => o.children && o.children.length).map((o) => ({ ...o, hasChildren: true }));
|
});
|
}
|
function getBtnText(key) {
|
let text = '';
|
switch (key) {
|
case 'batchPrint': {
|
text = '批量打印';
|
break;
|
}
|
case 'batchRemove': {
|
text = '批量删除';
|
break;
|
}
|
case 'detail': {
|
text = '详情';
|
break;
|
}
|
case 'download': {
|
text = '导出';
|
break;
|
}
|
case 'edit': {
|
text = '编辑';
|
break;
|
}
|
case 'remove': {
|
text = '删除';
|
break;
|
}
|
case 'upload': {
|
text = '导入';
|
break;
|
}
|
default: {
|
text = '新增';
|
break;
|
}
|
}
|
return text;
|
}
|
function getFuncText(key) {
|
let text = '';
|
switch (key) {
|
case 'afterOnload': {
|
text = '表格事件';
|
break;
|
}
|
case 'cellStyle': {
|
text = '单元格样式';
|
break;
|
}
|
case 'rowStyle': {
|
text = '表格行样式';
|
break;
|
}
|
default: {
|
text = '';
|
break;
|
}
|
}
|
return text;
|
}
|
function toggleType(val) {
|
if (state.columnData.type == val) return;
|
state.columnData.type = val;
|
if (val == 2) updateSearchList(state.columnData.treeRelation);
|
if (val == 3 || val == 5) state.columnData.childTableStyle = 1;
|
if (val == 5) resetBtnsList();
|
}
|
function resetBtnsList() {
|
for (let i = 0; i < state.columnData.btnsList.length; i++) {
|
const item = state.columnData.btnsList[i];
|
if (item.value != 'add') {
|
item.show = false;
|
state.columnData.printIds = [];
|
state.columnData.uploaderTemplateJson = {};
|
}
|
}
|
}
|
function dataTypeChange(val) {
|
state.columnData.treePropsValue = 'id';
|
state.columnData.treePropsLabel = 'fullName';
|
state.columnData.treePropsChildren = 'children';
|
if (val === 'formField') state.columnData.treeRelation = '';
|
}
|
function onTreePropsUrlChange(val, row) {
|
if (!val) {
|
state.columnData.treePropsUrl = '';
|
state.columnData.treePropsName = '';
|
state.columnData.treeTemplateJson = [];
|
initFieldData();
|
return;
|
}
|
if (state.columnData.treePropsUrl === val) return;
|
state.columnData.treePropsUrl = val;
|
state.columnData.treePropsName = row.fullName;
|
state.columnData.treeTemplateJson = row.parameterJson ? JSON.parse(row.parameterJson).map((o) => ({ ...o, relationField: '', sourceType: 2 })) : [];
|
initFieldData();
|
}
|
function onTreeSyncInterfaceChange(val, row) {
|
if (!val) {
|
state.columnData.treeSyncInterfaceId = '';
|
state.columnData.treeSyncInterfaceName = '';
|
state.columnData.treeSyncTemplateJson = [];
|
return;
|
}
|
if (state.columnData.treeSyncInterfaceId === val) return;
|
state.columnData.treeSyncInterfaceId = val;
|
state.columnData.treeSyncInterfaceName = row.fullName;
|
state.columnData.treeSyncTemplateJson = row.templateJson ? row.templateJson.map((o) => ({ ...o, relationField: '', sourceType: 1 })) : [];
|
}
|
function addCustomBtn() {
|
const id = buildBitUUID();
|
state.columnData.customBtnsList.push({
|
show: true,
|
value: `btn_${id}`,
|
label: `按钮${id}`,
|
labelI18nCode: '',
|
event: {},
|
});
|
}
|
function editBtnEvent(item, index) {
|
state.activeBtn = index;
|
openBtnEventModal(true, {
|
showType: 'pc',
|
formFieldsOptions: unref(webType) == 4 ? state.columnOptions : unref(formFieldsOptions),
|
dataForm: item.event,
|
});
|
}
|
function updateBtnEvent(data) {
|
state.columnData.customBtnsList[state.activeBtn].event = data;
|
}
|
function editRuleList() {
|
if (!state.columnData.ruleList || !state.columnData.ruleList.matchLogic) state.columnData.ruleList = { matchLogic: 'and', conditionList: [] };
|
openConditionModal(true, {
|
...state.columnData.ruleList,
|
fieldOptions: unref(webType) == 4 ? state.columnOptions : unref(formFieldsOptions),
|
});
|
}
|
function handleComplexHeader() {
|
const columnOptions = state.columnData.columnList.filter((o) => o.fixed === 'none' && !o.id.includes('-'));
|
openComplexHeaderModal(true, { list: state.columnData.complexHeaderList, columnOptions });
|
}
|
function editDefaultSortConfig() {
|
openDefaultSortConfigModal(true, {
|
list: state.columnData.defaultSortConfig,
|
columnOptions: state.groupFieldOptions.filter((o) => !o.id.includes('_jnpf_')),
|
});
|
}
|
function onFixedChange() {
|
updateComplexHeader();
|
}
|
function updateRuleList(data) {
|
state.columnData.ruleList = data;
|
}
|
function updateComplexHeaderList(data) {
|
state.columnData.complexHeaderList = data;
|
}
|
function updateDefaultSortConfig(data) {
|
state.columnData.defaultSortConfig = data;
|
}
|
function updateComplexHeader() {
|
if (!state.columnData?.complexHeaderList?.length) return;
|
const columnOptions = state.columnData.columnList.filter((o) => o.fixed === 'none' && !o.id.includes('-'));
|
for (let i = 0; i < state.columnData.complexHeaderList.length; i++) {
|
const e = state.columnData.complexHeaderList[i];
|
e.childColumns = e.childColumns.filter((o) => columnOptions.some((item) => item.id == o));
|
}
|
}
|
// 更新合计字段
|
function updateSummaryField() {
|
state.columnData.summaryField = state.columnData.summaryField.filter((o) => unref(summaryFieldOptions).some((item) => item.id == o));
|
}
|
function editFunc(funcName) {
|
state.activeFunc = funcName;
|
if (!state.columnData.funcs[state.activeFunc]) state.columnData.funcs[state.activeFunc] = defaultFuncsData[state.activeFunc];
|
openScriptModal(true, { text: state.columnData.funcs[state.activeFunc], funcName });
|
}
|
function handleEnableRule(item, index) {
|
state.activeBtn = index;
|
if (!item?.event?.enableFunc) item.event = { enableFunc: defaultBtnEnableFunc };
|
openScriptModal(true, { text: item.event.enableFunc, funcName: 'btnEnableRule' });
|
}
|
function updateScript(data, funcName) {
|
if (funcName == 'btnEnableRule') {
|
state.columnData.columnBtnsList[state.activeBtn].event.enableFunc = data;
|
} else {
|
state.columnData.funcs[state.activeFunc] = data;
|
}
|
}
|
function editUpLoadTpl() {
|
const data = { selectKey: [], dataType: '1', ...state.columnData.uploaderTemplateJson, fieldsOptions: unref(formFieldsOptions) };
|
openUpLoadTplModal(true, data);
|
}
|
function updateUpLoadTpl(data) {
|
state.columnData.uploaderTemplateJson = data;
|
}
|
function openExtraConfig(record, index) {
|
state.activeSearchRowIndex = index;
|
openExtraConfigModal(true, { ...record });
|
}
|
function updateSearchRow(data) {
|
state.columnData.searchList[state.activeSearchRowIndex] = data;
|
}
|
function onJnpfKeyChange(val, record, i) {
|
record.__config__.jnpfKey = val;
|
const defaultItem: any = {
|
id: record.id,
|
fullName: record.fullName,
|
label: record.label,
|
prop: record.prop,
|
jnpfKey: record.jnpfKey,
|
sourceType: 2,
|
value: getDefaultValue(record),
|
searchType: getSearchType(record),
|
__vModel__: record.__vModel__,
|
searchMultiple: getSearchMultiple(val),
|
isKeyword: false,
|
__config__: {
|
label: record.label,
|
jnpfKey: val,
|
},
|
};
|
if (val === 'datePicker') defaultItem.format = 'yyyy-MM-dd';
|
if (val === 'timePicker') defaultItem.format = 'HH:mm:ss';
|
if (val === 'select') {
|
defaultItem.options = [];
|
defaultItem.props = { label: 'fullName', value: 'id' };
|
defaultItem.__config__ = {
|
...defaultItem.__config__,
|
dataType: 'static',
|
propsUrl: '',
|
propsName: '',
|
templateJson: [],
|
dictionaryType: '',
|
};
|
}
|
if (['organizeSelect', 'posSelect', 'userSelect'].includes(val)) {
|
defaultItem.selectRange = '1';
|
}
|
state.columnData.searchList[i] = cloneDeep(defaultItem);
|
}
|
function onSourceTypeChange(record) {
|
record.value = record.sourceType == 4 ? getSysFieldList(record.jnpfKey, record.__config__.isFromParam)[0]?.id : getDefaultValue(record);
|
}
|
function getSourceTypeOptions(jnpfKey) {
|
return ['datePicker', 'organizeSelect', 'posSelect', 'userSelect'].includes(jnpfKey) ? sourceTypeOptions : sourceTypeOptions.filter((o) => o.id != 4);
|
}
|
function setBtnValue(data, defaultData) {
|
for (let i = 0; i < defaultData.length; i++) {
|
inter: for (const datum of data) {
|
if (defaultData[i].value === datum.value) {
|
defaultData[i] = datum;
|
if (!Reflect.has(defaultData[i], 'show')) defaultData[i].show = true;
|
break inter;
|
}
|
}
|
}
|
return defaultData;
|
}
|
function setListValue(data, defaultData, type) {
|
data = data.filter((o) => defaultData.some((e) => o.prop == e.prop));
|
for (let i = 0; i < data.length; i++) {
|
inter: for (let ii = 0; ii < defaultData.length; ii++) {
|
if (data[i].prop === defaultData[ii].prop) {
|
defaultData[ii].label = data[i].label;
|
defaultData[ii].labelI18nCode = data[i].labelI18nCode;
|
if (type === 'column') {
|
defaultData[ii].fixed = data[i].fixed;
|
defaultData[ii].headerAlign = data[i].headerAlign;
|
defaultData[ii].align = data[i].align;
|
defaultData[ii].width = data[i].width;
|
defaultData[ii].sortable = data[i].sortable;
|
}
|
if (type === 'search') {
|
if (data[i].jnpfKey === defaultData[ii].jnpfKey) {
|
defaultData[ii].searchType = data[i].searchType;
|
defaultData[ii].searchMultiple = data[i].searchMultiple;
|
defaultData[ii].noShow = data[i].noShow;
|
defaultData[ii].sourceType = data[i].sourceType;
|
defaultData[ii].value = data[i].value;
|
}
|
defaultData[ii].isKeyword = data[i].isKeyword;
|
if (unref(webType) == 4) defaultData[ii] = data[i];
|
}
|
data[i] = defaultData[ii];
|
break inter;
|
}
|
}
|
}
|
state[`${type}SelectedRowKeys`] = data.map((o) => o.prop);
|
return data;
|
}
|
function updateListValue(selectedRowKeys, selectedRows, type) {
|
state[`${type}SelectedRowKeys`] = selectedRowKeys;
|
if (!selectedRowKeys.length) return (state.columnData[`${type}List`] = []);
|
state.columnData[`${type}List`] = state.columnData[`${type}List`].filter((o) => selectedRowKeys.some((e) => o.prop == e));
|
for (const selectedRow of selectedRows) {
|
if (!state.columnData[`${type}List`].some((o) => o.prop === selectedRow.prop)) {
|
state.columnData[`${type}List`].push(cloneDeep(selectedRow));
|
}
|
}
|
if (type == 'search') buildOptions(state.columnData.searchList);
|
}
|
function onSearchSelectChange(selectedRowKeys, selectedRows) {
|
updateListValue(selectedRowKeys, selectedRows, 'search');
|
}
|
function onColumnSelectChange(selectedRowKeys, selectedRows) {
|
updateListValue(selectedRowKeys, selectedRows, 'column');
|
updateComplexHeader();
|
}
|
function setDefaultUpLoadData() {
|
const selectKey = state.columnData.uploaderTemplateJson?.selectKey || [];
|
const newList: any[] = [];
|
for (const element of selectKey) {
|
if (unref(formFieldsOptions).some((item) => item.id == element)) newList.push(element);
|
}
|
for (let i = 0; i < unref(formFieldsOptions).length; i++) {
|
const e = unref(formFieldsOptions)[i];
|
const required = e.__config__.required;
|
const jnpfKey = e.__config__.jnpfKey;
|
if (!noUploadList.includes(jnpfKey) && required && !newList.includes(e.id)) newList.push(e.id);
|
}
|
state.columnData.uploaderTemplateJson.selectKey = newList;
|
}
|
function initSort() {
|
const searchTable: any = document.querySelector(`.search-table .ant-table-tbody`);
|
Sortablejs.create(searchTable, {
|
handle: '.drag-handler',
|
animation: 150,
|
easing: 'cubic-bezier(1, 0, 0, 1)',
|
onStart: () => {},
|
onEnd: ({ newIndex, oldIndex }: any) => {
|
const currRow = state.columnData.searchList.splice(oldIndex, 1)[0];
|
state.columnData.searchList.splice(newIndex, 0, currRow);
|
},
|
});
|
const columnTable: any = document.querySelector(`.column-table .ant-table-tbody`);
|
Sortablejs.create(columnTable, {
|
handle: '.drag-handler',
|
animation: 150,
|
easing: 'cubic-bezier(1, 0, 0, 1)',
|
onStart: () => {},
|
onEnd: ({ newIndex, oldIndex }: any) => {
|
const currRow = state.columnData.columnList.splice(oldIndex, 1)[0];
|
state.columnData.columnList.splice(newIndex, 0, currRow);
|
},
|
});
|
}
|
function init(list) {
|
list = list.map((o) => {
|
if (o.__config__ && dyOptionsList.includes(o.__config__.jnpfKey) && o.__config__.dataType !== 'static') o.options = [];
|
return o;
|
});
|
const columnOptions = list.filter((o) => !noColumnShowList.includes(o.__config__.jnpfKey) || o.isStorage);
|
let searchOptions = list.filter((o) => !noSearchList.includes(o.__config__.jnpfKey));
|
if (unref(webType) == 4) {
|
const interfaceParam = (props.interfaceParam || [])
|
.filter((o) => o.useSearch)
|
.map((o) => {
|
let jnpfKey = 'input';
|
if (o.dataType === 'int' || o.dataType === 'decimal') jnpfKey = 'inputNumber';
|
if (o.dataType === 'datetime') jnpfKey = 'datePicker';
|
return {
|
id: o.field,
|
fullName: o.fieldName || o.field,
|
__vModel__: o.field,
|
__config__: { isFromParam: true, jnpfKey },
|
};
|
});
|
if (props.interfaceHasPage) {
|
searchOptions = interfaceParam;
|
} else {
|
searchOptions = searchOptions.filter((o) => !interfaceParam.some((e) => e.id === o.id));
|
searchOptions = [...interfaceParam, ...searchOptions];
|
}
|
}
|
state.groupFieldOptions = list.filter((o) => !o.id.includes('-') && !noGroupList.includes(o.__config__.jnpfKey)).map((o) => ({ ...o, disabled: false }));
|
state.treeFieldOptions = list.filter((o) => !o.id.includes('-') && o.__config__.jnpfKey == 'treeSelect');
|
state.tabRelationFieldOptions = list.filter(
|
(o) => !o.id.includes('-') && ['radio', 'select'].includes(o.__config__.jnpfKey) && o.__config__.dataType != 'dynamic' && !o.multiple,
|
);
|
state.columnOptions = columnOptions.map((o) => ({
|
label: o.fullName,
|
labelI18nCode: o.__config__.labelI18nCode || '',
|
prop: o.id,
|
fixed: 'none',
|
headerAlign: 'left',
|
align: 'left',
|
jnpfKey: o.__config__.jnpfKey,
|
sortable: false,
|
width: null,
|
...o,
|
}));
|
state.searchOptions = searchOptions.map((o) => ({
|
label: o.fullName,
|
labelI18nCode: o.__config__.labelI18nCode || '',
|
prop: o.id,
|
jnpfKey: o.__config__.jnpfKey,
|
sourceType: 2,
|
value: getDefaultValue(o),
|
searchType: getSearchType(o),
|
searchMultiple: getSearchMultiple(o.__config__.jnpfKey),
|
isKeyword: false,
|
...o,
|
}));
|
state.columnData.columnOptions = columnOptions;
|
if (!state.columnOptions.length) state.columnData.columnList = [];
|
if (!state.searchOptions.length) state.columnData.searchList = [];
|
// 处理旧数据兼容问题
|
state.columnData.btnsList = setBtnValue(state.columnData.btnsList, cloneDeep(state.defaultBtnsList));
|
state.columnData.columnBtnsList = setBtnValue(state.columnData.columnBtnsList, cloneDeep(state.defaultColumnBtnsList));
|
nextTick(() => {
|
if (state.columnData.btnsList.some((o) => o.value === 'upload' && o.show)) setDefaultUpLoadData();
|
updateTreeRelationInfo();
|
state.columnData.searchList = setListValue(state.columnData.searchList, cloneDeep(state.searchOptions), 'search');
|
state.columnData.columnList = setListValue(state.columnData.columnList, cloneDeep(state.columnOptions), 'column');
|
initSort();
|
setTimeout(() => {
|
buildOptions(state.columnData.searchList);
|
initFieldData();
|
}, 300);
|
});
|
updateSummaryField();
|
}
|
function initFieldData() {
|
if (!state.columnData.treePropsUrl) return (state.allOptions = []);
|
getDataInterfaceInfo(state.columnData.treePropsUrl).then((res) => {
|
const data = res.data;
|
const list = data.fieldJson ? JSON.parse(data.fieldJson) : [];
|
state.allOptions = list.map((o) => ({ ...o, value: o.defaultValue }));
|
});
|
}
|
function onSearch(searchText: string) {
|
state.options = state.allOptions.filter((o) => o.value.toLowerCase().includes(searchText.toLowerCase()));
|
}
|
function onFocus(searchText) {
|
onSearch(searchText);
|
}
|
function onSearchMultipleChange(record, index) {
|
if (record.sourceType === 4) return;
|
state.columnData.searchList[index].value = getDefaultValue(record);
|
}
|
function buildOptions(componentList) {
|
if (unref(webType) == 4) return;
|
componentList.forEach((cur) => {
|
const config = cur.__config__;
|
if (dyOptionsList.includes(config.jnpfKey)) {
|
if (config.dataType === 'dictionary' && config.dictionaryType) {
|
cur.options = [];
|
getDictionaryDataSelector(config.dictionaryType).then((res) => {
|
cur.options = res.data.list;
|
});
|
}
|
if (config.dataType === 'dynamic' && config.propsUrl) {
|
cur.options = [];
|
const query = { paramList: getParamList(config.templateJson) };
|
getDataInterfaceRes(config.propsUrl, query).then((res) => {
|
cur.options = Array.isArray(res.data) ? res.data : [];
|
});
|
}
|
}
|
});
|
}
|
function updateTreeRelationInfo() {
|
if (!state.columnData.treeRelation) return;
|
for (let i = 0; i < unref(selectOptions).length; i++) {
|
const e = unref(selectOptions)[i];
|
if (e.id === state.columnData.treeRelation && e.__config__?.jnpfKey && e.__config__.jnpfKey === 'organizeSelect') {
|
state.columnData.treeRelationFieldSelectType = e.selectType;
|
state.columnData.treeRelationFieldAbleIds = e.ableIds;
|
break;
|
}
|
}
|
}
|
function onRelationChange(val, data) {
|
if (data.__config__?.jnpfKey && data.__config__.jnpfKey === 'organizeSelect') {
|
state.columnData.treeRelationFieldSelectType = data.selectType;
|
state.columnData.treeRelationFieldAbleIds = data.ableIds;
|
}
|
updateSearchList(val);
|
}
|
function updateSearchList(val) {
|
if (!val) return;
|
state.columnData.searchList = state.columnData.searchList.filter((o) => o.id !== val);
|
state.columnData.searchList = setListValue(state.columnData.searchList, cloneDeep(state.searchOptions), 'search');
|
}
|
function onTabOnChange(val) {
|
if (!val) state.columnData.tabConfig.relationField = '';
|
}
|
|
onMounted(() => {
|
getDictionaryType();
|
getPrintTplList();
|
if (typeof props.conf === 'object' && props.conf !== null) {
|
state.columnData = cloneDeep(Object.assign({}, defaultColumnData, props.conf));
|
}
|
if (unref(webType) == 4) {
|
state.defaultBtnsList = defaultBtnsList.filter((o) => o.value === 'download');
|
state.defaultColumnBtnsList = [];
|
init(unref(viewFieldOptions));
|
} else {
|
// 树形表格过滤按钮
|
state.defaultBtnsList = defaultBtnsList;
|
state.defaultColumnBtnsList = defaultColumnBtnsList;
|
init(unref(formFieldsOptions));
|
}
|
});
|
</script>
|
<template>
|
<div class="column-design-container">
|
<div class="main-board">
|
<jnpf-group-title content="查询字段" :bordered="false" />
|
<a-table :data-source="columnData.searchList" :columns="searchColumns" size="small" :pagination="false" row-key="id" class="search-table">
|
<template #bodyCell="{ column, record, index }">
|
<template v-if="column.key === 'drag'">
|
<i class="drag-handler icon-ym icon-ym-darg" title="点击拖动"></i>
|
</template>
|
<template v-if="column.key === 'label'">
|
<jnpf-i18n-input v-model:value="record.label" v-model:i18n="record.labelI18nCode" placeholder="请输入" allow-clear />
|
</template>
|
<template v-if="column.key === 'jnpfKey'">
|
<jnpf-select
|
v-model:value="record.jnpfKey"
|
:options="viewJnpfKeyOptions"
|
:disabled="record.__config__.isFromParam"
|
class="!w-[156px]"
|
@change="onJnpfKeyChange($event, record, index)" />
|
<template v-if="canSetAttrs.includes(record.jnpfKey) && !record.__config__.isFromParam">
|
<i class="icon-ym icon-ym-shezhi ml-[8px] cursor-pointer leading-[30px]" title="组件属性设置" @click="openExtraConfig(record, index)"></i>
|
</template>
|
</template>
|
<template v-if="column.key === 'searchType'">
|
<jnpf-select
|
v-model:value="record.searchType"
|
:options="searchTypeOptions"
|
:disabled="!['input', 'textarea'].includes(record.jnpfKey)"
|
v-if="!record.__config__.isFromParam" />
|
<span v-else></span>
|
</template>
|
<template v-if="column.key === 'sourceType'">
|
<jnpf-select
|
v-model:value="record.sourceType"
|
placeholder="请选择"
|
:options="getSourceTypeOptions(record.jnpfKey)"
|
class="!w-100px"
|
@change="onSourceTypeChange(record)" />
|
</template>
|
<template v-if="column.key === 'value'">
|
<template v-if="record.sourceType === 2">
|
<template v-if="showInputList.includes(record.jnpfKey)">
|
<a-input v-model:value="record.value" placeholder="请输入" allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'inputNumber'">
|
<jnpf-number-range v-model:value="record.value" :precision="record.precision" :disabled="record.disabled" />
|
</template>
|
<template v-if="['rate', 'slider'].includes(record.jnpfKey)">
|
<jnpf-number-range v-model:value="record.value" :precision="record.allowHalf ? 1 : 0" :disabled="record.disabled" />
|
</template>
|
<template v-if="showSelectList.includes(record.jnpfKey)">
|
<jnpf-select
|
v-model:value="record.value"
|
:options="record.options"
|
:field-names="record.props"
|
:multiple="record.searchMultiple"
|
show-search
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'datePicker'">
|
<jnpf-date-range v-model:value="record.value" :format="record.format" allow-clear v-if="!record.__config__.isFromParam" />
|
<jnpf-date-picker v-model:value="record.value" :format="record.format" allow-clear v-else class="!w-full" />
|
</template>
|
<template v-if="record.jnpfKey === 'timePicker'">
|
<jnpf-time-range v-model:value="record.value" :format="record.format" allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'roleSelect'">
|
<jnpf-role-select
|
v-model:value="record.value"
|
:select-type="record.selectType"
|
:able-ids="record.ableIds"
|
:multiple="record.searchMultiple"
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'groupSelect'">
|
<jnpf-group-select
|
v-model:value="record.value"
|
:select-type="record.selectType"
|
:able-ids="record.ableIds"
|
:multiple="record.searchMultiple"
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'areaSelect'">
|
<jnpf-area-select v-model:value="record.value" :level="record.level" :multiple="record.searchMultiple" :key="record.cellKey" allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'organizeSelect'">
|
<jnpf-organize-select
|
v-model:value="record.value"
|
:select-type="record.selectType"
|
:able-ids="record.ableIds"
|
:multiple="record.searchMultiple"
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'cascader'">
|
<jnpf-cascader
|
v-model:value="record.value"
|
placeholder="请选择"
|
:options="record.options"
|
:field-names="record.props"
|
:show-all-levels="record.showAllLevels"
|
:multiple="record.searchMultiple"
|
show-search
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'posSelect'">
|
<jnpf-pos-select
|
v-model:value="record.value"
|
:select-type="record.selectType"
|
:able-ids="record.ableIds"
|
:multiple="record.searchMultiple"
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'userSelect'">
|
<jnpf-user-select
|
v-model:value="record.value"
|
:select-type="record.selectType != 'all' && record.selectType != 'custom' ? 'all' : record.selectType"
|
:able-ids="record.ableIds"
|
:multiple="record.searchMultiple"
|
allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'usersSelect'">
|
<jnpf-users-select v-model:value="record.value" allow-clear />
|
</template>
|
<template v-if="record.jnpfKey === 'autoComplete'">
|
<jnpf-auto-complete
|
v-model:value="record.value"
|
:placeholder="record.placeholder"
|
:allow-clear="record.clearable"
|
:disabled="record.disabled"
|
:interface-id="record.interfaceId"
|
:relation-field="record.relationField"
|
:template-json="record.templateJson"
|
:total="record.total" />
|
</template>
|
</template>
|
<template v-if="record.sourceType === 4">
|
<jnpf-select v-model:value="record.value" placeholder="请选择" :options="getSysFieldList(record.jnpfKey, record.__config__.isFromParam)" />
|
</template>
|
</template>
|
<template v-if="column.key === 'isKeyword'">
|
<a-checkbox v-model:checked="record.isKeyword" :disabled="!canSetKeyword.includes(record.jnpfKey) || (getIsKeywordDisabled && !record.isKeyword)" />
|
</template>
|
<template v-if="column.key === 'searchMultiple'">
|
<a-checkbox
|
v-model:checked="record.searchMultiple"
|
:disabled="!multipleList.includes(record.jnpfKey)"
|
@change="onSearchMultipleChange(record, index)" />
|
</template>
|
<template v-if="column.key === 'noShow'">
|
<a-checkbox v-model:checked="record.noShow" />
|
</template>
|
</template>
|
</a-table>
|
<jnpf-group-title content="列表字段" :bordered="false" class="mt-[20px]" />
|
<a-table :data-source="columnData.columnList" :columns="columnColumns" size="small" :pagination="false" row-key="id" class="column-table">
|
<template #bodyCell="{ column, record }">
|
<template v-if="column.key === 'drag'">
|
<i class="drag-handler icon-ym icon-ym-darg" title="点击拖动"></i>
|
</template>
|
<template v-if="column.key === 'label'">
|
<jnpf-i18n-input v-model:value="record.label" v-model:i18n="record.labelI18nCode" placeholder="请输入" allow-clear />
|
</template>
|
<template v-if="column.key === 'sortable'">
|
<a-checkbox
|
v-model:checked="record.sortable"
|
:disabled="
|
record.id.indexOf('_jnpf_') > 0 || (record.__config__ && record.__config__.isSubTable) || noGroupList.includes(record.__config__.jnpfKey)
|
" />
|
</template>
|
<template v-if="column.key === 'fixed'">
|
<jnpf-select
|
v-model:value="record.fixed"
|
:options="fixedOptions"
|
:disabled="record.__config__ && record.__config__.isSubTable"
|
@change="onFixedChange" />
|
</template>
|
<template v-if="column.key === 'headerAlign'">
|
<jnpf-select v-model:value="record.headerAlign" :options="alignOptions" />
|
</template>
|
<template v-if="column.key === 'align'">
|
<jnpf-select v-model:value="record.align" :options="alignOptions" />
|
</template>
|
<template v-if="column.key === 'width'">
|
<a-input-number v-model:value="record.width" placeholder="请输入" :min="0" :precision="0" class="w-full" />
|
</template>
|
</template>
|
</a-table>
|
</div>
|
<div class="right-board">
|
<a-tabs v-model:active-key="activeKey" :tab-bar-gutter="11" class="average-tabs">
|
<a-tab-pane key="search" tab="查询字段" />
|
<a-tab-pane key="field" tab="列表字段" />
|
<a-tab-pane key="column" tab="列表属性" />
|
</a-tabs>
|
<div class="right-main">
|
<div class="h-full" v-show="activeKey === 'search'">
|
<a-table
|
:data-source="getSearchOptions"
|
:columns="rightColumns"
|
size="small"
|
:pagination="false"
|
:scroll="{ y: 'calc(100vh - 161px)' }"
|
row-key="id"
|
:row-selection="{ columnWidth: 50, selectedRowKeys: searchSelectedRowKeys, onChange: onSearchSelectChange }">
|
<template #headerCell>查询字段</template>
|
</a-table>
|
</div>
|
<div class="h-full" v-show="activeKey === 'field'">
|
<a-table
|
:data-source="state.columnOptions"
|
:columns="rightColumns"
|
size="small"
|
:pagination="false"
|
:scroll="{ y: 'calc(100vh - 161px)' }"
|
row-key="id"
|
:row-selection="{ columnWidth: 50, selectedRowKeys: columnSelectedRowKeys, onChange: onColumnSelectChange }">
|
<template #headerCell>列表字段</template>
|
</a-table>
|
</div>
|
<ScrollContainer v-show="activeKey === 'column'">
|
<a-form :colon="false" layout="vertical" class="right-board-form">
|
<div class="typeList">
|
<div class="item" :class="{ 'view-item': webType == 4 }" v-for="(item, index) in getTypeList" :key="index" @click="toggleType(item.value)">
|
<div class="item-img" :class="{ checked: columnData.type == item.value }">
|
<img :src="item.url" />
|
<div class="icon-checked" v-if="columnData.type == item.value">
|
<CheckOutlined />
|
</div>
|
</div>
|
<p class="item-name">{{ item.name }}</p>
|
</div>
|
</div>
|
<div v-if="columnData.type == 2">
|
<a-divider>左侧配置</a-divider>
|
<a-form-item>
|
<template #label>左侧查询<BasicHelp text="暂不支持异步的左侧查询" /></template>
|
<a-switch v-model:checked="columnData.hasTreeQuery" />
|
</a-form-item>
|
<a-form-item label="左侧标题">
|
<jnpf-i18n-input v-model:value="columnData.treeTitle" v-model:i18n="columnData.treeTitleI18nCode" placeholder="请输入" />
|
</a-form-item>
|
<a-form-item label="数据来源">
|
<jnpf-select
|
v-model:value="columnData.treeDataSource"
|
:options="treeDataSourceOptions"
|
show-search
|
placeholder="请选择"
|
@change="dataTypeChange" />
|
</a-form-item>
|
<div v-if="columnData.treeDataSource === 'dictionary'">
|
<a-form-item label="数据字典">
|
<jnpf-tree-select v-model:value="columnData.treeDictionary" :options="dicOptions" last-level allow-clear placeholder="请选择" />
|
</a-form-item>
|
<a-form-item label="主键字段">
|
<a-select v-model:value="columnData.treePropsValue" placeholder="请选择">
|
<a-select-option value="id">id</a-select-option>
|
<a-select-option value="enCode">enCode</a-select-option>
|
</a-select>
|
</a-form-item>
|
</div>
|
<div v-if="columnData.treeDataSource === 'api'">
|
<a-form-item label="数据接口">
|
<InterfaceModal :value="columnData.treePropsUrl" :title="columnData.treePropsName" popup-title="数据接口" @change="onTreePropsUrlChange" />
|
</a-form-item>
|
<a-form-item label="参数设置" v-if="columnData.treeTemplateJson?.length">
|
<SelectInterfaceBtn :template-json="columnData.treeTemplateJson" :show-system-form-id="false" :type="2" />
|
</a-form-item>
|
<a-form-item label="主键字段">
|
<a-auto-complete
|
v-model:value="columnData.treePropsValue"
|
placeholder="请输入"
|
:options="options"
|
@focus="onFocus(columnData.treePropsValue)"
|
@search="debounceOnSearch(columnData.treePropsValue)" />
|
</a-form-item>
|
<a-form-item label="回显字段">
|
<a-auto-complete
|
v-model:value="columnData.treePropsLabel"
|
placeholder="请输入"
|
:options="options"
|
@focus="onFocus(columnData.treePropsLabel)"
|
@search="debounceOnSearch(columnData.treePropsLabel)" />
|
</a-form-item>
|
<a-form-item label="子级字段">
|
<a-input v-model:value="columnData.treePropsChildren" placeholder="请输入" />
|
</a-form-item>
|
</div>
|
<a-form-item label="关联字段">
|
<jnpf-select
|
v-model:value="columnData.treeRelation"
|
:options="selectOptions"
|
placeholder="请选择"
|
:field-names="{ options: 'options1' }"
|
show-search
|
@change="onRelationChange" />
|
</a-form-item>
|
<div v-if="columnData.treeDataSource === 'api'">
|
<a-form-item label="数据加载">
|
<jnpf-radio v-model:value="columnData.treeSyncType" :options="treeSyncTypeOptions" />
|
</a-form-item>
|
<a-form-item v-if="columnData.treeSyncType == 1">
|
<template #label>数据接口<BasicHelp text="提供异步调用的数据接口" /></template>
|
<InterfaceModal
|
:value="columnData.treeSyncInterfaceId"
|
:title="columnData.treeSyncInterfaceName"
|
popup-title="数据接口"
|
@change="onTreeSyncInterfaceChange" />
|
</a-form-item>
|
<a-table
|
:data-source="columnData.treeSyncTemplateJson"
|
:columns="treeSyncTemplateJsonColumns"
|
size="small"
|
:pagination="false"
|
v-if="columnData.treeSyncTemplateJson.length && columnData.treeSyncType == 1">
|
<template #bodyCell="{ column, record }">
|
<template v-if="column.key === 'field'">
|
<span class="required-sign">{{ record.required ? '*' : '' }}</span>
|
{{ record.field }}{{ record.fieldName ? `(${record.fieldName})` : '' }}
|
</template>
|
<template v-if="column.key === 'relationField'">
|
<a-input v-model:value="record.relationField" placeholder="请输入" />
|
</template>
|
</template>
|
</a-table>
|
</div>
|
</div>
|
<a-divider>表格配置</a-divider>
|
<a-form-item label="数据过滤" v-if="webType != 4">
|
<a-button block @click="editRuleList">{{ getRuleBtnText }}</a-button>
|
</a-form-item>
|
<a-form-item label="复杂表头" v-if="columnData.type !== 3 && columnData.type !== 5">
|
<a-button block @click="handleComplexHeader">{{ state.columnData.complexHeaderList?.length ? '编辑复杂表头' : '复杂表头配置' }}</a-button>
|
</a-form-item>
|
<a-form-item label="分组字段" v-if="columnData.type == 3">
|
<jnpf-select
|
v-model:value="columnData.groupField"
|
:options="state.groupFieldOptions"
|
placeholder="请选择"
|
:field-names="{ options: 'options1' }"
|
show-search />
|
</a-form-item>
|
<a-form-item label="父级字段" v-if="columnData.type == 5">
|
<jnpf-select
|
v-model:value="columnData.parentField"
|
:options="state.treeFieldOptions"
|
placeholder="请选择"
|
:field-names="{ options: 'options1' }"
|
show-search />
|
</a-form-item>
|
<a-form-item label="默认排序">
|
<a-button block @click="editDefaultSortConfig">默认排序配置</a-button>
|
</a-form-item>
|
<a-form-item label="列宽拖拽">
|
<a-switch v-model:checked="columnData.resizable" />
|
</a-form-item>
|
<a-form-item label="高级查询" v-if="webType != 4">
|
<a-switch v-model:checked="columnData.hasSuperQuery" />
|
</a-form-item>
|
<a-form-item>
|
<template #label>溢出省略<BasicHelp :text="['启用:溢出省略号显示;', '禁用:显示全部信息,溢出换行显示']" /></template>
|
<a-switch v-model:checked="columnData.showOverflow" />
|
</a-form-item>
|
<a-form-item v-if="webType == 4">
|
<template #label>视图主键<BasicHelp text="视图主键用于当前选中的数据导出,设置的主键必须是唯一值才能确保数据正常导出" /></template>
|
<jnpf-select v-model:value="columnData.viewKey" :options="state.columnOptions" />
|
</a-form-item>
|
<div v-if="columnData.type !== 3 && columnData.type !== 5">
|
<a-form-item label="分页设置">
|
<a-switch v-model:checked="columnData.hasPage" :disabled="!!interfaceHasPage" />
|
</a-form-item>
|
<a-form-item label="分页条数" v-if="columnData.hasPage">
|
<jnpf-radio v-model:value="columnData.pageSize" :options="pageSizeOptions" option-type="button" button-style="solid" class="right-radio" />
|
</a-form-item>
|
<a-form-item label="合计配置">
|
<a-switch v-model:checked="columnData.showSummary" />
|
</a-form-item>
|
<a-form-item label="合计字段" v-if="columnData.showSummary">
|
<jnpf-select
|
v-model:value="columnData.summaryField"
|
:options="summaryFieldOptions"
|
placeholder="请选择"
|
:field-names="{ options: 'options1' }"
|
show-search
|
allow-clear
|
multiple />
|
</a-form-item>
|
</div>
|
<template v-if="webType != 4 && [1, 4].includes(columnData.type)">
|
<a-form-item label="标签面板">
|
<a-switch v-model:checked="columnData.tabConfig.on" @change="onTabOnChange" />
|
</a-form-item>
|
<template v-if="columnData?.tabConfig?.on">
|
<a-form-item label="筛选字段">
|
<jnpf-select
|
v-model:value="columnData.tabConfig.relationField"
|
:options="state.tabRelationFieldOptions"
|
:field-names="{ options: 'options1' }"
|
show-search
|
@change="onRelationChange" />
|
</a-form-item>
|
<a-form-item label="全部标签">
|
<a-switch v-model:checked="columnData.tabConfig.hasAllTab" />
|
</a-form-item>
|
</template>
|
</template>
|
<a-form-item label="子表样式" v-if="(columnData.type == 1 || columnData.type == 2) && webType != 4">
|
<jnpf-select v-model:value="columnData.childTableStyle" :options="childTableStyleOptions" placeholder="请选择" />
|
</a-form-item>
|
<a-divider>按钮配置</a-divider>
|
<div class="btnsList">
|
<template v-for="item in columnData.btnsList" :key="item.value">
|
<div v-if="columnData.type !== 5 || (columnData.type == 5 && item.value === 'add')" class="btnsList-cell">
|
<a-checkbox v-model:checked="item.show">{{ getBtnText(item.value) }}</a-checkbox>
|
<div class="flex-1 overflow-hidden">
|
<jnpf-i18n-input v-model:value="item.label" v-model:i18n="item.labelI18nCode" placeholder="按钮名称" />
|
<div class="btn-upload" v-if="item.value === 'upload' && item.show">
|
<a-button block @click="editUpLoadTpl">请设置导入模板</a-button>
|
</div>
|
<div class="btn-upload" v-if="item.value === 'batchPrint' && item.show">
|
<jnpf-tree-select
|
v-model:value="columnData.printIds"
|
placeholder="请选择"
|
multiple
|
:options="printTplOptions"
|
last-level
|
:show-checked-strategy="TreeSelect.SHOW_CHILD"
|
class="w-full" />
|
</div>
|
</div>
|
</div>
|
</template>
|
</div>
|
<div class="btnsList">
|
<div v-for="(item, index) in columnData.columnBtnsList" :key="item.value" class="btnsList-cell">
|
<a-checkbox v-model:checked="item.show">{{ getBtnText(item.value) }}</a-checkbox>
|
<jnpf-i18n-input v-model:value="item.label" v-model:i18n="item.labelI18nCode" placeholder="按钮名称">
|
<template #addonBefore>
|
<span class="cursor-pointer px-[11px]" @click="handleEnableRule(item, index)">启用规则<BasicHelp text="不支持代码生成" /></span>
|
</template>
|
</jnpf-i18n-input>
|
</div>
|
</div>
|
<div>
|
<p class="btn-cap">自定义按钮区<BasicHelp text="不支持代码生成" /></p>
|
<div class="custom-btns-list">
|
<draggable v-model="columnData.customBtnsList" :animation="300" group="selectItem" handle=".option-drag" item-key="value">
|
<template #item="{ element, index }">
|
<div class="custom-item">
|
<div class="custom-line-icon option-drag">
|
<i class="icon-ym icon-ym-darg"></i>
|
</div>
|
<p class="custom-line-value">{{ element.value }}</p>
|
<jnpf-i18n-input v-model:value="element.label" v-model:i18n="element.labelI18nCode" placeholder="按钮名称">
|
<template #addonBefore>
|
<span class="cursor-pointer" @click="editBtnEvent(element, index)">事件</span>
|
</template>
|
</jnpf-i18n-input>
|
<div class="close-btn custom-line-icon" @click="columnData.customBtnsList.splice(index, 1)">
|
<i class="icon-ym icon-ym-btn-clearn"></i>
|
</div>
|
</div>
|
</template>
|
</draggable>
|
<div class="add-btn">
|
<a-button type="link" pre-icon="icon-ym icon-ym-btn-add" @click="addCustomBtn">添加按钮</a-button>
|
</div>
|
</div>
|
</div>
|
<div v-if="webType != 4">
|
<a-divider>权限设置</a-divider>
|
<a-form-item label="按钮权限">
|
<a-switch v-model:checked="columnData.useBtnPermission" />
|
</a-form-item>
|
<a-form-item label="列表权限">
|
<a-switch v-model:checked="columnData.useColumnPermission" />
|
</a-form-item>
|
<a-form-item label="表单权限">
|
<a-switch v-model:checked="columnData.useFormPermission" />
|
</a-form-item>
|
<a-form-item label="数据权限">
|
<a-switch v-model:checked="columnData.useDataPermission" />
|
</a-form-item>
|
</div>
|
<a-divider>脚本事件<BasicHelp text="不支持代码生成" /></a-divider>
|
<a-form-item :label="getFuncText(key)" v-for="(_value, key) in columnData.funcs" :key="key">
|
<a-button block @click="editFunc(key)">脚本编写</a-button>
|
</a-form-item>
|
</a-form>
|
</ScrollContainer>
|
</div>
|
</div>
|
<FormScript @register="registerScriptModal" @confirm="updateScript" />
|
<UpLoadTpl @register="registerUpLoadTplModal" @confirm="updateUpLoadTpl" />
|
<BtnEvent @register="registerBtnEventModal" @confirm="updateBtnEvent" />
|
<ConditionModal @register="registerConditionModal" @confirm="updateRuleList" />
|
<ComplexHeaderModal @register="registerComplexHeaderModal" @confirm="updateComplexHeaderList" />
|
<DefaultSortConfigModal @register="registerDefaultSortConfigModal" @confirm="updateDefaultSortConfig" />
|
<ExtraConfigModal @register="registerExtraConfigModal" @confirm="updateSearchRow" />
|
</div>
|
</template>
|