<script lang="ts" setup>
|
import type { TreeActionType } from '@jnpf/ui';
|
import type { ActionItem, SorterResult, TableActionType } from '@jnpf/ui/vxeTable';
|
|
import type { DynamicModelActionType, OpenDynamicModelOptions } from './helpers/dynamicModelActions';
|
import type { ListPrintColumn } from './helpers/listPrint';
|
|
import { computed, nextTick, onMounted, provide, reactive, ref, toRaw, toRefs, unref, watch } from 'vue';
|
import { useRoute } from 'vue-router';
|
|
import { useMessage, usePermission } from '@jnpf/hooks';
|
import { BasicLeftTree } from '@jnpf/ui';
|
import { BasicForm, useForm } from '@jnpf/ui/form';
|
import { useModal } from '@jnpf/ui/modal';
|
import { usePopup } from '@jnpf/ui/popup';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
import { downloadByUrl, getDateTimeUnit, getScriptFunc, getTimeUnit, thousandsFormat } from '@jnpf/utils';
|
|
import { getTabKey, useAccessStore, useUserStore } from '@vben/stores';
|
|
import { FilterOutlined } from '@ant-design/icons-vue';
|
import dayjs from 'dayjs';
|
import { cloneDeep, omit } from 'lodash-es';
|
import { Grid as VxeGrid } from 'vxe-table';
|
|
import {
|
batchDelete,
|
createModel,
|
exportModel,
|
getConfigData,
|
getModelInfo,
|
getModelList,
|
getViewList,
|
launchFlow,
|
updateModel,
|
} from '#/api/onlineDev/visualDev';
|
import { getGroupByCondition } from '#/api/permission/group';
|
import { getOrganizeSelector, getOrgByOrganizeCondition, getOrgSelectedList } from '#/api/permission/organize';
|
import { getPositionSelectedList } from '#/api/permission/position';
|
import { getRoleByCondition } from '#/api/permission/role';
|
import { getUserInfoList } from '#/api/permission/user';
|
import { getDataInterfaceRes } from '#/api/systemData/dataInterface';
|
import { checkInfo, create as createFlowForm, getCandidates, update as updateFlowForm } from '#/api/workFlow/task';
|
import { buildFormFieldMaskMap } from '#/components/ColumnDesign/src/helper/fieldConfigSync';
|
import { ExportModal, ImportModal, SuperQueryModal } from '#/components/CommonModal';
|
import { createSignedAuditRequestOnlineUtils } from '#/components/FormGenerator/src/helper/auditDisplay';
|
import { dyOptionsList, ocrList, overflowInvalidList, slotsList, systemComponentsList } from '#/components/FormGenerator/src/helper/config';
|
import { getFormDataOptionLabel } from '#/components/FormGenerator/src/helper/formDataOptions';
|
import { getSearchFormSchemas } from '#/components/FormGenerator/src/helper/transform';
|
import FlowListPopup from '#/components/GlobalFlowListModal/FlowListPopup.vue';
|
import GlobalListModal from '#/components/GlobalListModal/index.vue';
|
import PrintBrowse from '#/components/PrintDesign/printBrowse/index.vue';
|
import PrintSelect from '#/components/PrintDesign/printSelect/index.vue';
|
import { useFlowState } from '#/hooks/flow/useFlowStatus';
|
import { $t } from '#/locales';
|
import { useBaseStore } from '#/store';
|
import {
|
getLaunchFlowParamList,
|
getParamList,
|
isDraftFlowConfig,
|
normalizeOpenFlowEditConfig,
|
normalizeOpenFlowFormConfig,
|
onlineUtils,
|
resolveOpenFlowEditConfig,
|
resolveOpenFlowListConfig,
|
} from '#/utils/jnpf';
|
import FlowParser from '#/views/workFlow/components/FlowParser.vue';
|
import CandidateModal from '#/views/workFlow/components/modal/CandidateModal.vue';
|
import FreeModal from '#/views/workFlow/components/modal/FreeModal.vue';
|
|
import ChildTableColumn from './ChildTableColumn.vue';
|
import ListPrintModal from './components/ListPrintModal.vue';
|
import ViewList from './components/ViewList.vue';
|
import ViewSetting from './components/ViewSetting.vue';
|
import CustomForm from './CustomForm.vue';
|
import Detail from './detail/index.vue';
|
import Form from './Form.vue';
|
import { buildDynamicModelOpenData, parseTargetDynamicModelConfig, validateDynamicModelActionOptions } from './helpers/dynamicModelActions';
|
import { createRowClickSelectionHandler, getDynamicListSelectionConfig } from './helpers/rowSelection';
|
import { getColumnActionWidth, resolveColumnActionGroups } from './helpers/tableActions';
|
|
interface State {
|
config: any;
|
columnData: any;
|
formConf: any;
|
headerBtnsList: any[];
|
columnBtnsList: any[];
|
customHeaderBtnsList: any[];
|
customColumnBtnsList: any[];
|
columnOptions: any[];
|
treeFieldNames: any;
|
leftTreeData: any[];
|
leftTreeLoading: boolean;
|
isLeftTreeLazy: boolean;
|
treeActiveId: string;
|
treeActiveNodePath: any;
|
columns: any[];
|
allColumns: any[];
|
complexColumns: any[];
|
childColumnList: any[];
|
mergeList: any[];
|
exportList: any[];
|
cacheList: any[];
|
currRow: any;
|
workFlowFormData: any;
|
expandObj: any;
|
columnSettingList: any[];
|
searchSchemas: any[];
|
treeRelationObj: any;
|
treeQueryJson: any;
|
leftTreeActiveInfo: any;
|
customRow: any;
|
customCell: any;
|
tabActiveKey: any;
|
tabList: any[];
|
tabQueryJson: any;
|
externalParams: any;
|
userSuperQueryJson: string;
|
viewList: any[];
|
currentView: any;
|
rowStyle: any;
|
cellStyle: any;
|
}
|
|
const props = defineProps(['config', 'modelId', 'isPreview', 'isDataManage', 'menuId', 'externalParams', 'isOnlineUtilsOpen']);
|
const route = useRoute();
|
const currentTabKey = getTabKey(route);
|
const { hasBtnP } = usePermission();
|
const { createMessage, createConfirm } = useMessage();
|
const userStore = useUserStore();
|
const accessStore = useAccessStore();
|
const { permissionList } = accessStore;
|
const baseStore = useBaseStore();
|
const [registerFlowParser, { openPopup: openFlowParser }] = usePopup();
|
const [registerFlowListPopup, { openPopup: openFlowListPopup }] = usePopup();
|
const [registerExportModal, { openModal: openExportModal, closeModal: closeExportModal, setModalProps: setExportModalProps }] = useModal();
|
const [registerImportModal, { openModal: openImportModal }] = useModal();
|
const [registerSuperQueryModal, { openModal: openSuperQuery }] = useModal();
|
const [registerCandidate, { openModal: openCandidateModal, closeModal: closeCandidateModal }] = useModal();
|
const [registerPrintSelect, { openModal: openPrintSelect }] = useModal();
|
const [registerPrintBrowse, { openModal: openPrintBrowse }] = useModal();
|
const [registerListPrintModal, { openModal: openListPrintModal }] = useModal();
|
const viewEchoSlotList = new Set([
|
'checkbox',
|
'datePicker',
|
'groupSelect',
|
'organizeSelect',
|
'posSelect',
|
'radio',
|
'roleSelect',
|
'select',
|
'timePicker',
|
'userSelect',
|
'usersSelect',
|
]);
|
const [registerFree, { openModal: openFreeModal, closeModal: closeFreeModal }] = useModal();
|
const leftTreeRef = ref<Nullable<TreeActionType>>(null);
|
const formRef = ref<any>(null);
|
const customFormRef = ref<any>(null);
|
const tableRef = ref<Nullable<TableActionType>>(null);
|
const detailRef = ref<any>(null);
|
const listModalRef = ref<any>(null);
|
const searchInfo = reactive({
|
modelId: '',
|
menuId: '',
|
flowId: '',
|
onlineUtilsOpen: false,
|
queryJson: '',
|
superQueryJson: '',
|
interfacePageParam: {},
|
});
|
const state = reactive<State>({
|
config: {},
|
columnData: {},
|
formConf: {},
|
headerBtnsList: [],
|
columnBtnsList: [],
|
customHeaderBtnsList: [],
|
customColumnBtnsList: [],
|
columnOptions: [],
|
treeFieldNames: {
|
children: 'children',
|
title: 'fullName',
|
key: 'id',
|
isLeaf: 'isLeaf',
|
},
|
leftTreeData: [],
|
leftTreeLoading: false,
|
isLeftTreeLazy: false,
|
treeActiveId: '',
|
treeActiveNodePath: [],
|
columns: [],
|
allColumns: [],
|
complexColumns: [], // 复杂表头
|
childColumnList: [],
|
mergeList: [],
|
exportList: [],
|
cacheList: [],
|
currRow: {},
|
workFlowFormData: {},
|
expandObj: {},
|
columnSettingList: [],
|
searchSchemas: [],
|
treeRelationObj: null,
|
treeQueryJson: {},
|
leftTreeActiveInfo: {},
|
customRow: null,
|
customCell: null,
|
tabActiveKey: '',
|
tabList: [],
|
tabQueryJson: {},
|
externalParams: {},
|
userSuperQueryJson: '',
|
viewList: [],
|
currentView: {},
|
rowStyle: null,
|
cellStyle: null,
|
});
|
const { columnData, childColumnList, tabActiveKey, tabList, viewList, currentView, allColumns } = toRefs(state);
|
const { getFlowStatusContent, getFlowStatusColor } = useFlowState();
|
const [registerSearchForm, { updateSchema, resetFields, submit: searchFormSubmit }] = useForm({
|
baseColProps: { span: 6 },
|
showActionButtonGroup: true,
|
showAdvancedButton: true,
|
compact: true,
|
});
|
const [
|
registerTable,
|
{
|
reload,
|
setLoading,
|
insertTableDataRecord,
|
updateTableDataRecord,
|
deleteTableDataRecord,
|
getFetchParams,
|
getSelectRowKeys,
|
getSelectRows,
|
clearSelectedRowKeys,
|
deleteSelectRowByKey,
|
redoHeight,
|
setSelectedRows,
|
},
|
] = useVxeTable({
|
api: getModelList,
|
clickToRowSelect: false,
|
immediate: false,
|
tableSetting: { setting: false, redo: !props.isPreview },
|
afterFetch: (data) => {
|
// 行内编辑
|
if (state.columnData.type === 4) {
|
const list = data.map((o) => ({ ...o, rowEdit: false }));
|
state.cacheList = cloneDeep(list);
|
nextTick(() => {
|
if (state.columnData.funcs?.afterOnload) setTableLoadFunc();
|
});
|
return list;
|
}
|
let list = data.map((o) => ({ ...o, ...state.expandObj }));
|
state.cacheList = cloneDeep(list);
|
fillViewUserEchoText(list);
|
fillViewUserEchoText(state.cacheList);
|
// 分组表格
|
if (state.columnData.type === 3) {
|
list = list.map((o) => {
|
if (o.children?.length) {
|
o.children = o.children.map((e) => ({ ...e, ...state.expandObj }));
|
}
|
return o;
|
});
|
}
|
nextTick(() => {
|
if (state.columnData.funcs?.afterOnload) setTableLoadFunc();
|
});
|
return list;
|
},
|
});
|
|
provide('getLeftTreeActiveInfo', () => state.leftTreeActiveInfo);
|
provide('onlineUtils', getListOnlineUtils());
|
|
const getHasBatchBtn = computed(
|
() =>
|
state.columnData.type != 5 &&
|
(state.headerBtnsList.some((o) => ['batchPrint', 'batchRemove', 'download'].includes(o.value)) || state.customHeaderBtnsList.length),
|
);
|
const handleRowSelection = createRowClickSelectionHandler<Recordable, string>({
|
deselectRow: deleteSelectRowByKey,
|
getRowKey: () => unref(getRowKey),
|
getSelectedRowKeys: getSelectRowKeys,
|
isEnabled: () => !!unref(getHasBatchBtn),
|
selectRows: setSelectedRows,
|
});
|
// 导出、导入按钮固定渲染在工具栏最后
|
const getNormalHeaderBtnsList = computed(() => state.headerBtnsList.filter((o) => !['download', 'upload'].includes(o.value)));
|
const getTrailingHeaderBtnsList = computed(() => state.headerBtnsList.filter((o) => ['download', 'upload'].includes(o.value)));
|
const getLeftTreeBindValue = computed(() => {
|
const key = Date.now();
|
const data: any = {
|
title: state.columnData.treeTitleI18nCode ? $t(state.columnData.treeTitleI18nCode, state.columnData.treeTitle) : state.columnData.treeTitle,
|
showSearch: state.columnData.hasTreeQuery && state.columnData.treeSyncType == 0 && !state.isLeftTreeLazy,
|
fieldNames: state.treeFieldNames,
|
defaultExpandAll: state.columnData.treeSyncType == 0 && !state.isLeftTreeLazy,
|
treeData: state.leftTreeData,
|
loading: state.leftTreeLoading,
|
showReset: true,
|
key,
|
};
|
if (state.columnData.treeSyncType == 1 || state.isLeftTreeLazy) data.loadData = onLoadData;
|
return data;
|
});
|
const getPagination = computed(() => {
|
if ([3, 5].includes(state.columnData.type) || !state.columnData.hasPage) return false;
|
return { pageSize: state.columnData.pageSize };
|
});
|
const getChildTableStyle = computed(() => (state.columnData.type == 3 || state.columnData.type == 5 ? 1 : state.columnData.childTableStyle));
|
const getColumns = computed(() => {
|
const columns = unref(getChildTableStyle) == 2 || state.columnData.type == 4 ? state.columns : state.complexColumns;
|
return props.isDataManage || props.isPreview || props.isOnlineUtilsOpen ? columns : setListValue(state.currentView?.columnList, columns, 'prop');
|
});
|
const getSearchList = computed(() => {
|
const searchSchemas = cloneDeep(state.searchSchemas).map((o) => ({ ...o, show: true }));
|
const schemas =
|
props.isDataManage || props.isPreview || props.isOnlineUtilsOpen ? searchSchemas : setListValue(state.currentView?.searchList, searchSchemas, 'field');
|
getSearchOptions(schemas);
|
return schemas;
|
});
|
const getRowKey = computed(() => (state.config.webType == 4 && state.columnData.viewKey ? state.columnData.viewKey : 'id'));
|
const getTableBindValue = computed(() => {
|
// type,format 跟vxe-table 有冲突
|
const columns = unref(getColumns).map((o) => ({ ...omit(o, ['type', 'format']) }));
|
if (state.config.enableFlow) {
|
const boo = columns.some((o) => o.dataIndex === 'flowState');
|
if (!boo)
|
columns.push({
|
title: $t('component.table.status'),
|
dataIndex: 'flowState',
|
width: 100,
|
align: 'center',
|
fixed: columns.some((o) => o.fixed == 'right') ? 'right' : '',
|
slots: { default: 'flowState' },
|
});
|
}
|
const defaultSortConfig = (state.columnData.defaultSortConfig || []).map((o) => (o.sort === 'desc' ? '-' : '') + o.field);
|
const data: any = {
|
pagination: unref(getPagination),
|
searchInfo: unref(searchInfo),
|
defSort: { sidx: defaultSortConfig.join(',') },
|
sortConfig: { multiple: true },
|
sortFn: (sortInfo: SorterResult | SorterResult[]) => {
|
if (Array.isArray(sortInfo)) {
|
const sortList = sortInfo.map((o) => (o.order === 'desc' ? '-' : '') + o.field);
|
return { sidx: sortList.join(',') };
|
} else {
|
const { field, order } = sortInfo;
|
return field && order ? { sidx: (order === 'desc' ? '-' : '') + field } : {};
|
}
|
},
|
columns,
|
// 有子表且子表折叠展示
|
showExpandColumn: unref(getChildTableStyle) == 2 && [1, 2].includes(state.columnData.type) && !!state.childColumnList.length,
|
clearSelectOnPageChange: true,
|
showOverflow: false,
|
isTreeTable: [3, 5].includes(state.columnData.type),
|
border: (unref(getChildTableStyle) != 2 && !!state.childColumnList?.length) || !!state.columnData.complexHeaderList?.length,
|
showFooter: state.columnData.showSummary && [1, 2, 4].includes(state.columnData.type),
|
columnConfig: {
|
resizable: !!state.columnData.resizable,
|
},
|
rowKey: unref(getRowKey),
|
};
|
// 行内编辑且不带流程序号加插槽
|
if (state.columnData.type === 4 && !state.config.enableFlow) data.indexColumnProps = { slots: { default: 'editIndex' } };
|
// 有子表且子表分组展示
|
if (unref(getChildTableStyle) === 1 && state.childColumnList.length) data.spanMethod = spanMethod;
|
// 列表合计
|
if (state.columnData.showSummary) data.footerMethod = footerMethod;
|
// 批量
|
Object.assign(data, getDynamicListSelectionConfig(!!unref(getHasBatchBtn), data.isTreeTable));
|
// 计算按钮长度
|
if (state.columnBtnsList.length || state.customColumnBtnsList.length) {
|
const extraButtonCount = state.columnData.type == 4 && state.config.enableFlow ? 1 : 0;
|
const actionWidth = getColumnActionWidth(state.columnBtnsList.length, state.customColumnBtnsList.length, extraButtonCount);
|
data.actionColumn = {
|
width: actionWidth,
|
title: $t('component.table.action'),
|
dataIndex: 'action',
|
fixed: 'right',
|
};
|
}
|
// 行样式
|
if (state.rowStyle) data.rowStyle = state.rowStyle;
|
// 单元格样式
|
if (state.cellStyle) data.cellStyle = state.cellStyle;
|
return data;
|
});
|
const getSummaryColumn = computed(() => {
|
let defaultColumns = unref(getColumns);
|
// 处理列固定
|
if (state.columnSettingList?.length) {
|
for (const defaultColumn of defaultColumns) {
|
inner: for (let j = 0; j < state.columnSettingList.length; j++) {
|
if (defaultColumn.dataIndex === state.columnSettingList[j].dataIndex) {
|
defaultColumn.fixed = state.columnSettingList[j].fixed;
|
defaultColumn.visible = state.columnSettingList[j].visible;
|
break inner;
|
}
|
}
|
}
|
defaultColumns = defaultColumns.filter((o) => o.visible);
|
}
|
const columns: any[] = [];
|
for (const e of defaultColumns) {
|
if (e.jnpfKey === 'table' || e.jnpfKey === 'complexHeader') {
|
if (e.children?.length) columns.push(...e.children);
|
} else {
|
columns.push(e);
|
}
|
if (e.fixed && e.children?.length) {
|
for (let j = 0; j < e.children.length; j++) {
|
e.children[j].fixed = e.fixed;
|
}
|
}
|
}
|
const leftFixedList = columns.filter((o) => o.fixed === 'left');
|
const rightFixedList = columns.filter((o) => o.fixed === 'right');
|
const noFixedList = columns.filter((o) => o.fixed !== 'left' && o.fixed !== 'right');
|
return [...leftFixedList, ...noFixedList, ...rightFixedList];
|
});
|
// 列表合计
|
function footerMethod({ columns, data }) {
|
const isSummary = (key) => state.columnData.summaryField.includes(key);
|
const useThousands = (key) => unref(getSummaryColumn).some((o) => o.__vModel__ === key && o.thousands);
|
return [
|
columns.map((column, columnIndex) => {
|
if (columnIndex === 0) return '合计';
|
if (!data.length) return '';
|
let sumVal = data.reduce((sum, d) => sum + getCmpValOfRow(d, column.property), 0);
|
if (!isSummary(column.property)) sumVal = '';
|
sumVal = Number.isNaN(sumVal) ? '' : sumVal;
|
const realVal = sumVal && !Number.isInteger(sumVal) ? Number(sumVal).toFixed(2) : sumVal;
|
sumVal = useThousands(column.property) ? thousandsFormat(realVal) : realVal;
|
return sumVal;
|
}),
|
];
|
}
|
function getCmpValOfRow(row, key) {
|
const isSummary = (key) => state.columnData.summaryField.includes(key);
|
if (!state.columnData.summaryField.length || !isSummary(key)) return 0;
|
const target = row[key];
|
if (!target) return 0;
|
const data = Number.isNaN(target) ? 0 : Number(target);
|
return data;
|
}
|
function getTableActions(record, index): ActionItem[] {
|
const columnActions = state.columnBtnsList.map((o) => {
|
const item: ActionItem = {
|
label: o.labelI18nCode ? $t(o.labelI18nCode, o.label) : o.label,
|
onClick: columnBtnsHandle.bind(null, o, record, index),
|
};
|
if (o.value === 'remove') item.color = 'error';
|
if (state.config.enableFlow) {
|
if (o.value === 'edit') item.disabled = ![0, 8, 9].includes(record.flowState);
|
if (o.value === 'remove') item.disabled = ![0, 9].includes(record.flowState);
|
if (o.value === 'detail') item.disabled = !record.flowState;
|
} else {
|
if (o?.event?.enableFunc) {
|
const parameter = { row: record, rowIndex: index, onlineUtils: getListOnlineUtils() };
|
const func: any = getScriptFunc(o.event.enableFunc);
|
item.disabled = (func && !func(parameter)) || false;
|
}
|
}
|
return item;
|
});
|
const customActions = getCustomColumnActions(record, index);
|
if (record.rowEdit) {
|
const editBtnList: ActionItem[] = [
|
{ label: $t('common.saveText'), onClick: saveForRowEdit.bind(null, record, 0) },
|
{ label: $t('common.cancelText'), color: 'error', onClick: cancelRowEdit.bind(null, record, index) },
|
];
|
if (state.config.enableFlow) {
|
editBtnList.push({ label: $t('common.submitText'), onClick: submitForRowEdit.bind(null, record) });
|
}
|
return editBtnList;
|
}
|
return resolveColumnActionGroups(columnActions, customActions).inlineButtons;
|
}
|
function getCustomColumnActions(record, index): ActionItem[] {
|
return state.customColumnBtnsList.map((o) => {
|
const item: ActionItem = {
|
label: o.labelI18nCode ? $t(o.labelI18nCode, o.label) : o.label,
|
onClick: customBtnsHandle.bind(null, o, record, index),
|
};
|
if (o?.event?.enableFunc) {
|
const parameter = { row: record, rowIndex: index, onlineUtils: getListOnlineUtils() };
|
const func: any = getScriptFunc(o.event?.enableFunc);
|
item.disabled = (func && !func(parameter)) || false;
|
}
|
return item;
|
});
|
}
|
function getHeaderBtnVisible(item) {
|
if (!item?.event?.enableFunc) return true;
|
const parameter = { onlineUtils: getListOnlineUtils() };
|
const func: any = getScriptFunc(item.event.enableFunc);
|
return func ? !!func(parameter) : true;
|
}
|
function getDropDownActions(record, index): ActionItem[] {
|
return resolveColumnActionGroups([], getCustomColumnActions(record, index)).moreButtons;
|
}
|
function openFlowPopup() {
|
const data = {
|
id: '',
|
flowId: state.config.flowId,
|
opType: '-1',
|
showHeaderCancelBtn: true,
|
};
|
openFlowParser(true, data);
|
}
|
function collectTreeChildKeys(node: any): any[] {
|
if (!node) return [];
|
const data = node.dataRef || node;
|
const childrenKey = state.treeFieldNames.children || 'children';
|
const key = state.treeFieldNames.key || 'id';
|
const currKey = data[key] ?? node[key] ?? node.eventKey;
|
const result = currKey || currKey === 0 || currKey === false ? [currKey] : [];
|
const children = Array.isArray(data[childrenKey]) ? data[childrenKey] : Array.isArray(node.children) ? node.children : [];
|
for (const child of children) {
|
result.push(...collectTreeChildKeys(child));
|
}
|
return [...new Set(result)];
|
}
|
function handleLeftTreeSelect(id, _node, nodePath) {
|
if (props.isPreview) return;
|
if (state.treeActiveId == id) return;
|
state.treeActiveId = id;
|
state.treeActiveNodePath = nodePath;
|
let queryJson: any = {};
|
let leftTreeActiveInfo: any = {};
|
const isMultiple = state.treeRelationObj ? state.treeRelationObj.searchMultiple : false;
|
if (state.treeRelationObj?.jnpfKey && ['areaSelect', 'cascader'].includes(state.treeRelationObj.jnpfKey)) {
|
let currValue = [];
|
currValue = state.treeActiveNodePath.map((o) => o[state.treeFieldNames.key]);
|
queryJson = { [state.columnData.treeRelation]: isMultiple ? [currValue] : currValue };
|
leftTreeActiveInfo = { [state.columnData.treeRelation]: state.treeRelationObj.multiple ? [currValue] : currValue };
|
} else {
|
const treeActiveIds = state.columnData.treeIncludeChildren ? collectTreeChildKeys(_node) : [state.treeActiveId];
|
let queryValue: any = state.treeActiveId;
|
if (state.columnData.treeIncludeChildren || isMultiple) {
|
queryValue = treeActiveIds.length ? treeActiveIds : [state.treeActiveId];
|
}
|
queryJson = { [state.columnData.treeRelation]: queryValue };
|
leftTreeActiveInfo = { [state.columnData.treeRelation]: state.treeRelationObj.multiple ? [state.treeActiveId] : state.treeActiveId };
|
}
|
state.treeQueryJson = queryJson;
|
state.leftTreeActiveInfo = leftTreeActiveInfo;
|
unref(getSearchList)?.length ? resetFields() : handleSearchSubmit({});
|
}
|
// 清空左侧树的筛选,保留搜索表单已填的条件
|
function handleLeftTreeReset() {
|
if (props.isPreview) return;
|
if (!state.treeActiveId) return;
|
state.treeActiveId = '';
|
state.treeActiveNodePath = [];
|
state.treeQueryJson = {};
|
state.leftTreeActiveInfo = {};
|
unref(getSearchList)?.length ? searchFormSubmit() : handleSearchSubmit({});
|
}
|
// 行内编辑新增
|
function addHandleForRowEdit() {
|
const item = { rowEdit: true, id: 'jnpfAdd' };
|
const userInfo = userStore.getUserInfo;
|
const currDate = new Date();
|
for (let i = 0; i < state.columnData.columnList.length; i++) {
|
const e = state.columnData.columnList[i];
|
const config = e.__config__;
|
if (config.defaultCurrent) {
|
if (config.jnpfKey === 'datePicker') {
|
config.defaultValue = dayjs(currDate).startOf(getDateTimeUnit(e.format)).valueOf();
|
}
|
if (config.jnpfKey === 'timePicker') {
|
config.defaultValue = dayjs(currDate).format(e.format || 'HH:mm:ss');
|
}
|
if (config.jnpfKey === 'organizeSelect' && userInfo?.organizeIds?.length) {
|
config.defaultValue = e.multiple ? userInfo.organizeIds : userInfo.organizeId;
|
}
|
if (config.jnpfKey === 'userSelect' && userInfo?.userId) {
|
config.defaultValue = e.multiple ? [userInfo.userId] : userInfo.userId;
|
}
|
if (config.jnpfKey === 'usersSelect' && userInfo?.userId) {
|
config.defaultValue = [`${userInfo.userId}--user`];
|
}
|
if (config.jnpfKey === 'posSelect' && userInfo?.positionIds?.length) {
|
config.defaultValue = e.multiple ? userInfo.positionIds : userInfo.positionId;
|
}
|
if (config.jnpfKey === 'sign' && userInfo?.signImg) {
|
config.defaultValue = userInfo.signImg;
|
}
|
}
|
if (!config.isSubTable) item[e.__vModel__] = config.defaultValue;
|
}
|
insertTableDataRecord(cloneDeep(item), 0);
|
}
|
// 新增
|
function addHandle() {
|
// 行内编辑新增
|
if (state.columnData.type === 4) return addHandleForRowEdit();
|
// 带流程新增
|
if (state.config.enableFlow == 1) return openFlowPopup();
|
const data = {
|
id: '',
|
formConf: state.formConf,
|
modelId: props.modelId,
|
isPreview: props.isPreview,
|
isDataManage: props.isDataManage,
|
isOnlineUtilsOpen: props.isOnlineUtilsOpen,
|
useFormPermission: state.columnData.useFormPermission,
|
showMoreBtn: ![3, 5].includes(state.columnData.type),
|
menuId: searchInfo.menuId,
|
allList: state.cacheList,
|
};
|
formRef.value?.init(data);
|
}
|
function getButtonText(item) {
|
return item?.labelI18nCode ? $t(item.labelI18nCode, item.label) : item?.label || '';
|
}
|
function getListSignMetaData(item, rows: any[]) {
|
return {
|
biz_button: getButtonText(item),
|
biz_data: cloneDeep(rows),
|
biz_form_id: props.modelId || '',
|
biz_module: '',
|
biz_title: '',
|
is_biz_form: false,
|
is_review_button: false,
|
};
|
}
|
// 顶部按钮点击事件
|
function headBtnsHandle(item) {
|
const key = typeof item === 'string' ? item : item?.value;
|
// 新建
|
if (key === 'add') {
|
if (item?.event?.customBtn) return handleBuiltinBtnScript(item, [], 0);
|
return addHandle();
|
}
|
// 导出
|
if (key == 'download')
|
return openExportModal(true, {
|
columnList: state.exportList,
|
selectIds: getSelectRowKeys(),
|
showExportSelected: state.config.webType != 4 || state.columnData.viewKey,
|
});
|
// 导入
|
if (key == 'upload') return openImportModal(true, { modelId: props.modelId, menuId: searchInfo.menuId, flowId: state.config.flowId });
|
if (props.isPreview) return;
|
// 批量删除
|
if (key === 'batchRemove') handleBatchRemove(item);
|
// 批量打印
|
if (key === 'batchPrint') handleBatchPrint();
|
}
|
// 顶部自定义按钮点击事件
|
function headCustomBtnsHandle(item) {
|
if (props.isPreview) return;
|
const selectRows = getSelectRows();
|
if (!selectRows.length && item.event.dataRequired) return createMessage.error($t('common.selectDataTip'));
|
if (!item.event.biz_sign_enabled) return executeHeadCustomBtn(item, selectRows);
|
onlineUtils.sign({
|
isFaceToFace: false,
|
metaData: getListSignMetaData(item, selectRows),
|
onCancel: () => {},
|
onSubmit: (signData) => executeHeadCustomBtn(item, selectRows, signData, true),
|
});
|
}
|
function executeHeadCustomBtn(item, selectRows, signData?: any, hasBizSign = false) {
|
if (item.event.btnType == 2) handleScriptFunc(item, selectRows, 0, signData, hasBizSign);
|
if (item.event.btnType == 3) handleBatchInterface(item.event, selectRows);
|
if (item.event.btnType == 4) handleBatchLaunchFlow(item, selectRows);
|
}
|
// 导出
|
function handleDownload(data) {
|
if (props.isPreview) {
|
setExportModalProps({ confirmLoading: false });
|
createMessage.warning('功能预览不支持数据导出');
|
return;
|
}
|
const query = { ...getFetchParams(), ...data };
|
exportModel(props.modelId, query)
|
.then((res) => {
|
setExportModalProps({ confirmLoading: false });
|
if (!res.data.url) return;
|
downloadByUrl({ url: res.data.url });
|
closeExportModal();
|
})
|
.catch(() => {
|
setExportModalProps({ confirmLoading: false });
|
});
|
}
|
// 批量删除
|
function handleBatchRemove(item?, skipConfirm = false, signData?: any, hasBizSign = false) {
|
const ids = getSelectRowKeys();
|
const selectRows = getSelectRows();
|
if (!ids.length) return createMessage.error($t('common.selectDataTip'));
|
if (item?.event?.biz_sign_enabled && !skipConfirm) {
|
onlineUtils.sign({
|
isFaceToFace: false,
|
metaData: getListSignMetaData(item, selectRows),
|
onCancel: () => {},
|
onSubmit: (signData) => handleBatchRemove(item, true, signData, true),
|
});
|
return;
|
}
|
if (item?.event?.customBtn) return handleBuiltinBtnScript(item, getSelectRows(), 0, signData, hasBizSign);
|
const query = {
|
ids,
|
flowId: state.config.flowId || '',
|
...(hasBizSign ? { biz_sign: signData?.biz_sign } : {}),
|
};
|
const executeRemove = () => {
|
batchDelete(props.modelId, query).then((res) => {
|
createMessage.success(res.msg);
|
clearSelectedRowKeys();
|
reload();
|
});
|
};
|
if (skipConfirm) return executeRemove();
|
createConfirm({
|
iconType: 'warning',
|
title: $t('common.tipTitle'),
|
content: $t('common.batchDelTip'),
|
onOk: executeRemove,
|
});
|
}
|
// 批量打印
|
function handleBatchPrint() {
|
if (state.config.isPreview) return createMessage.warning('功能预览不支持打印');
|
if (!state.columnData.printIds?.length) return createMessage.error('未配置打印模板');
|
const ids = getSelectRowKeys();
|
if (!ids.length) return createMessage.error($t('common.selectDataTip'));
|
if (state.columnData.printIds?.length === 1) return handleShowBrowse(state.columnData.printIds[0]);
|
openPrintSelect(true, state.columnData.printIds);
|
}
|
function handleShowBrowse(id) {
|
const formInfo: any[] = (getSelectRows() || []).map((o) => {
|
const item: any = { formId: o.id };
|
if (state.config.enableFlow) item.flowTaskId = o.flowTaskId || o.id;
|
return item;
|
});
|
openPrintBrowse(true, { id, formInfo });
|
}
|
// 行按钮点击事件
|
function columnBtnsHandle(item, record, index?) {
|
const key = typeof item === 'string' ? item : item?.value;
|
if (key === 'edit') {
|
if (item?.event?.customBtn) return handleBuiltinBtnScript(item, record, index);
|
return updateHandle(record);
|
}
|
if (key === 'detail') {
|
if (item?.event?.customBtn) return handleBuiltinBtnScript(item, record, index);
|
return goDetail(record);
|
}
|
if (key == 'remove') {
|
if (item?.event?.biz_sign_enabled) {
|
onlineUtils.sign({
|
isFaceToFace: false,
|
metaData: getListSignMetaData(item, [record]),
|
onCancel: () => {},
|
onSubmit: (signData) => {
|
if (item?.event?.customBtn) return handleBuiltinBtnScript(item, record, index, signData, true);
|
handleDelete(record.id, true, signData?.biz_sign, true);
|
},
|
});
|
return;
|
}
|
if (item?.event?.customBtn) return handleBuiltinBtnScript(item, record, index);
|
handleDelete(record.id);
|
}
|
}
|
// 编辑
|
function updateHandle(record) {
|
// 行内编辑
|
if (state.columnData.type === 4) return editForRowEdit(record);
|
if (state.config.enableFlow == 1) {
|
const data = {
|
id: record.flowTaskId || record.id,
|
flowId: state.config.flowId,
|
opType: '-1',
|
};
|
openFlowParser(true, data);
|
} else {
|
const data = {
|
id: record.id,
|
formConf: state.formConf,
|
modelId: props.modelId,
|
isPreview: props.isPreview,
|
isDataManage: props.isDataManage,
|
isOnlineUtilsOpen: props.isOnlineUtilsOpen,
|
useFormPermission: state.columnData.useFormPermission,
|
showMoreBtn: ![3, 5].includes(state.columnData.type),
|
menuId: searchInfo.menuId,
|
allList: state.cacheList,
|
};
|
formRef.value?.init(data);
|
}
|
}
|
async function openTargetDynamicModel(action: DynamicModelActionType, options?: OpenDynamicModelOptions) {
|
try {
|
validateDynamicModelActionOptions(action, options);
|
const res = await getConfigData(options!.modelId);
|
const target = parseTargetDynamicModelConfig(res.data);
|
const data = buildDynamicModelOpenData(action, {
|
context: {
|
isDataManage: props.isDataManage,
|
isPreview: props.isPreview,
|
},
|
options: options!,
|
target,
|
});
|
|
if (action === 'detail') {
|
detailRef.value?.init(data);
|
return;
|
}
|
|
formRef.value?.init(data);
|
} catch (error: any) {
|
createMessage.warning(error?.message || '打开表单失败');
|
}
|
}
|
function openTargetAdd(options?: OpenDynamicModelOptions) {
|
return openTargetDynamicModel('add', options);
|
}
|
function openTargetEdit(options: OpenDynamicModelOptions) {
|
return openTargetDynamicModel('edit', options);
|
}
|
function openTargetDetail(options: OpenDynamicModelOptions) {
|
return openTargetDynamicModel('detail', options);
|
}
|
async function openTargetFlowDetail(configOrFlowId: any, taskIdArg?: number | string) {
|
const config = typeof configOrFlowId === 'object' ? { ...configOrFlowId } : { flowId: configOrFlowId, taskId: taskIdArg };
|
const flowId = config.flowId ?? config.flow_id;
|
const taskIdValue = isDraftFlowConfig(config)
|
? (config.id ?? config.f_id ?? config.taskId ?? config.flowTaskId)
|
: (config.taskId ?? config.flowTaskId ?? config.id ?? config.f_id);
|
if (!flowId) {
|
console.error('[onlineUtils.openFlowDetail] flowId is required');
|
return;
|
}
|
if (!taskIdValue) {
|
console.error('[onlineUtils.openFlowDetail] id is required');
|
return;
|
}
|
const data = {
|
...config,
|
flowId,
|
id: taskIdValue,
|
isFlow: config.isFlow ?? 0,
|
opType: config.opType ?? 0,
|
taskId: taskIdValue,
|
};
|
if (isDraftFlowConfig(data)) {
|
await openTargetFlowEdit(data);
|
return;
|
}
|
if (data.opType == 6) {
|
openFlowParser(true, data);
|
return;
|
}
|
try {
|
const res = await checkInfo(data.operatorId || data.id, data.opType);
|
data.opType = res.data.opType;
|
openFlowParser(true, { ...data, showHeaderCancelBtn: true });
|
} catch {}
|
}
|
function openTargetFlowForm(configOrFlowId: any, paramsArg?: Record<string, any>) {
|
const data = normalizeOpenFlowFormConfig(configOrFlowId, paramsArg);
|
if (!data) {
|
console.error('[onlineUtils.openFlowForm] flowId is required');
|
return;
|
}
|
openFlowParser(true, { ...data, showHeaderCancelBtn: true });
|
}
|
async function openTargetFlowList(configOrFlowId: any, paramsArg?: Record<string, any>) {
|
const config = typeof configOrFlowId === 'object' ? { ...configOrFlowId } : { flowId: configOrFlowId, params: paramsArg };
|
const flowId = config.flowId ?? config.flow_id;
|
if (!flowId) {
|
console.error('[onlineUtils.openFlowList] flowId is required');
|
return;
|
}
|
openFlowListPopup(true, await resolveOpenFlowListConfig(config));
|
}
|
async function openTargetFlowEdit(configOrFlowId: any, taskIdArg?: number | string) {
|
const data = normalizeOpenFlowEditConfig(
|
typeof configOrFlowId === 'object' && state.config.flowId ? { ...configOrFlowId, flowId: state.config.flowId } : configOrFlowId,
|
taskIdArg,
|
);
|
if (!data) {
|
console.error('[onlineUtils.openFlowEdit] flowId and id are required');
|
return;
|
}
|
openFlowParser(true, await resolveOpenFlowEditConfig(data));
|
}
|
function getOpenListParam(paramName: string) {
|
if (!paramName) return undefined;
|
if (Object.prototype.hasOwnProperty.call(state.externalParams, paramName)) return state.externalParams[paramName];
|
return onlineUtils.getParam(paramName);
|
}
|
function getListOnlineUtils() {
|
return {
|
...onlineUtils,
|
getParam: getOpenListParam,
|
openAdd: openTargetAdd,
|
openDetail: openTargetDetail,
|
openEdit: openTargetEdit,
|
openFlowEdit: openTargetFlowEdit,
|
openFlowForm: openTargetFlowForm,
|
openFlowDetail: openTargetFlowDetail,
|
openFlowList: openTargetFlowList,
|
openList: openTargetList,
|
printCurrentList: openCurrentListPrint,
|
requestFormData: (configOrRow?: any, idArg?: number | string) => {
|
const isConfig =
|
configOrRow &&
|
typeof configOrRow === 'object' &&
|
!Array.isArray(configOrRow) &&
|
['data', 'flow_id', 'flowId', 'menuId', 'modelId', 'onlineUtilsOpen', 'propsValue', 'row', 'rowKey', 'useDataChange'].some((key) =>
|
Object.prototype.hasOwnProperty.call(configOrRow, key),
|
);
|
const config =
|
configOrRow && typeof configOrRow === 'object' && !Array.isArray(configOrRow)
|
? isConfig
|
? { ...configOrRow }
|
: { row: configOrRow }
|
: { id: idArg ?? configOrRow };
|
return onlineUtils.requestFormData({
|
modelId: props.modelId,
|
menuId: searchInfo.menuId,
|
rowKey: unref(getRowKey),
|
...config,
|
});
|
},
|
refresh: reload,
|
};
|
}
|
|
interface RuntimeListPrintColumn extends ListPrintColumn {
|
source: any;
|
}
|
|
function getListPrintColumns() {
|
const columns: RuntimeListPrintColumn[] = [];
|
const loop = (list: any[] = []) => {
|
for (const item of list) {
|
if (item.visible === false) continue;
|
if (item.children?.length) {
|
loop(item.children);
|
continue;
|
}
|
const field = item.prop || item.dataIndex;
|
if (!field || ['action', 'expand'].includes(field)) continue;
|
const title = item.labelI18nCode ? $t(item.labelI18nCode, item.label) : item.label || item.title || item.fullName || field;
|
columns.push({ field, title, width: item.width, source: item });
|
}
|
};
|
loop(unref(getColumns));
|
return columns;
|
}
|
|
function openCurrentListPrint(options: any = {}) {
|
const runtimeColumns = getListPrintColumns();
|
openListPrintModal(true, {
|
columns: runtimeColumns.map(({ source: _source, ...column }) => column),
|
defaultPageSize: options.pageSize || state.columnData.pageSize || 20,
|
direction: options.direction || 'landscape',
|
paperType: options.paperType || 'A3',
|
title: options.title || state.config.fullName || String(route.meta?.title || '列表报表'),
|
fetchPage: async (currentPage: number, pageSize: number) => {
|
const params: any = {
|
...getFetchParams(),
|
currentPage,
|
menuId: searchInfo.menuId,
|
modelId: props.modelId,
|
pageSize,
|
};
|
const res = await getModelList(params);
|
const list = Array.isArray(res.data?.list) ? res.data.list : [];
|
await fillViewUserEchoText(list);
|
const displayList = list.map((row, index) => {
|
const displayRow: Record<string, any> = {};
|
for (const column of runtimeColumns) {
|
displayRow[column.field] = column.source.useContentFormat
|
? formatColumnContent(column.source, row, (currentPage - 1) * pageSize + index)
|
: getColumnDisplayText(column.source, row);
|
}
|
return displayRow;
|
});
|
return {
|
list: displayList,
|
total: Number(res.data?.pagination?.total) || list.length,
|
};
|
},
|
});
|
}
|
function parseRouteListQuery(value) {
|
const raw = Array.isArray(value) ? value[0] : value;
|
if (!raw || typeof raw !== 'string') return {};
|
const parseJson = (str) => {
|
try {
|
const data = JSON.parse(str);
|
return data && typeof data === 'object' && !Array.isArray(data) ? data : {};
|
} catch {
|
return null;
|
}
|
};
|
const data = parseJson(raw);
|
if (data) return data;
|
try {
|
return parseJson(decodeURIComponent(raw)) || {};
|
} catch {
|
return {};
|
}
|
}
|
function getRouteMetaQuery() {
|
const query = route.meta?.query;
|
return query && typeof query === 'object' && !Array.isArray(query) ? cloneDeep(query) : {};
|
}
|
function initExternalParams() {
|
state.externalParams =
|
props.externalParams && typeof props.externalParams === 'object'
|
? cloneDeep(props.externalParams)
|
: { ...getRouteMetaQuery(), ...parseRouteListQuery(route.query.jnpfListQuery) };
|
}
|
function hasExternalParamValue(value) {
|
if (Array.isArray(value)) return value.length > 0;
|
return value || value === 0 || value === false;
|
}
|
function resolveExternalParamValue(paramName) {
|
if (!paramName) return undefined;
|
if (Object.prototype.hasOwnProperty.call(state.externalParams, paramName)) return state.externalParams[paramName];
|
if (Object.prototype.hasOwnProperty.call(route.query, paramName)) {
|
const value = route.query[paramName];
|
return Array.isArray(value) ? value[0] : value;
|
}
|
return undefined;
|
}
|
function hasExternalParam(paramName) {
|
if (!paramName) return false;
|
return Object.prototype.hasOwnProperty.call(state.externalParams, paramName) || Object.prototype.hasOwnProperty.call(route.query, paramName);
|
}
|
function getViewInterfaceParams() {
|
const rawParams = state.config.interfaceParam;
|
if (!rawParams) return [];
|
try {
|
const params = Array.isArray(rawParams) ? rawParams : JSON.parse(rawParams);
|
return Array.isArray(params) ? cloneDeep(params) : [];
|
} catch {
|
return [];
|
}
|
}
|
function refreshViewInterfacePageParams() {
|
const params = getViewInterfaceParams();
|
const pageParams: Record<string, any> = {};
|
for (const param of params) {
|
if (param.sourceType !== 5) continue;
|
pageParams[param.relationField] = resolveExternalParamValue(param.relationField) ?? '';
|
}
|
searchInfo.interfacePageParam = pageParams;
|
}
|
function resolveExternalRuleQuery(ruleList) {
|
const query = cloneDeep(ruleList || {});
|
const conditionList = Array.isArray(query.conditionList) ? query.conditionList : [];
|
for (const condition of conditionList) {
|
const groups = Array.isArray(condition.groups) ? condition.groups : [];
|
for (const item of groups) {
|
if (item.fieldValueType !== 5) continue;
|
const paramName = item.fieldValue;
|
const value = resolveExternalParamValue(paramName);
|
item.hasExternalParam = hasExternalParam(paramName);
|
item.fieldValue_ = paramName;
|
item.fieldValue = hasExternalParamValue(value) ? value : undefined;
|
if (Array.isArray(item.fieldValue) && !['between', 'in', 'notIn'].includes(item.symbol)) item.fieldValue = item.fieldValue[0];
|
}
|
condition.groups = groups.filter(
|
(item) => item.fieldValueType !== 5 || (['notNull', 'null'].includes(item.symbol) ? item.hasExternalParam : hasExternalParamValue(item.fieldValue)),
|
);
|
}
|
query.conditionList = conditionList.filter((condition) => Array.isArray(condition.groups) && condition.groups.length);
|
return query;
|
}
|
function openTargetList(options: any = {}) {
|
if (!options?.path && !options?.menuId && !options?.modelId) {
|
console.error('[onlineUtils.openList] path, menuId or modelId is required');
|
return;
|
}
|
if (listModalRef.value?.open) {
|
listModalRef.value.open(options);
|
return;
|
}
|
onlineUtils.openList(options);
|
}
|
// 行内编辑
|
function editForRowEdit(record) {
|
record.rowEdit = true;
|
}
|
function cancelRowEdit(record, index) {
|
const id = !record.id || record.id === 'jnpfAdd' ? '' : record.id;
|
if (!id) return deleteTableDataRecord('jnpfAdd');
|
record.rowEdit = false;
|
const item = cloneDeep(state.cacheList[index]);
|
updateTableDataRecord(item.id, item);
|
}
|
// 行内编辑保存
|
function saveForRowEdit(record, status = 0, candidateData: any = null) {
|
if (props.isPreview) return createMessage.warning('功能预览不支持数据保存');
|
const id = !record.id || record.id === 'jnpfAdd' ? '' : record.id;
|
if (state.config.enableFlow == 1) {
|
let query = {
|
id: record.flowTaskId || id,
|
status: status || 0,
|
formData: record,
|
flowId: state.config.flowId,
|
flowUrgent: 1,
|
};
|
if (candidateData) query = { ...query, ...candidateData };
|
const formMethod = id ? updateFlowForm : createFlowForm;
|
formMethod(query).then((res) => {
|
createMessage.success(res.msg);
|
closeCandidateModal();
|
closeFreeModal();
|
reload({ page: 1 });
|
});
|
} else {
|
const query = { id, data: JSON.stringify(record), menuId: searchInfo.menuId };
|
const formMethod = id ? updateModel : createModel;
|
formMethod(props.modelId, query).then((res) => {
|
createMessage.success(res.msg);
|
reload({ page: 1 });
|
});
|
}
|
}
|
// 行内编辑提交审核
|
function submitForRowEdit(record) {
|
if (props.isPreview) return createMessage.warning('功能预览不支持数据保存');
|
state.currRow = record;
|
const id = !record.id || record.id === 'jnpfAdd' ? '' : record.id;
|
state.workFlowFormData = {
|
id: record.flowTaskId || id,
|
formData: record,
|
flowId: state.config.flowId,
|
};
|
getCandidates(0, state.workFlowFormData).then((res) => {
|
const candidateList = res?.data?.list.filter((o) => !o.isBranchFlow && o.isCandidates);
|
const branchList = res.data.list.filter((o) => o.isBranchFlow);
|
if (!candidateList.length && res.data.type == 3) {
|
createConfirm({
|
iconType: 'warning',
|
title: '提示',
|
content: '您确定要提交当前流程吗, 是否继续?',
|
onOk: () => {
|
saveForRowEdit(record, 1);
|
},
|
});
|
return;
|
}
|
// 自由流
|
if (res.data.type === 4) {
|
openFreeModal(true, {
|
formData: state.workFlowFormData,
|
oneSelfEndApproval: false,
|
});
|
return;
|
}
|
openCandidateModal(true, { branchList, candidateList, formData: state.workFlowFormData });
|
});
|
}
|
// 选择候选人
|
function submitCandidate(data) {
|
saveForRowEdit(state.currRow, 1, data);
|
}
|
function submitFree(data) {
|
saveForRowEdit(state.currRow, 1, data);
|
}
|
// 查看详情
|
function goDetail(record) {
|
if (state.config.enableFlow == 1) {
|
const data = {
|
id: record.flowTaskId || record.id,
|
flowId: state.config.flowId,
|
opType: 0,
|
};
|
openFlowParser(true, data);
|
} else {
|
const data = {
|
id: record.id,
|
formConf: state.formConf,
|
modelId: props.modelId,
|
menuId: searchInfo.menuId,
|
useFormPermission: state.columnData.useFormPermission,
|
isDataManage: props.isDataManage,
|
hideExtra: props.isDataManage,
|
};
|
detailRef.value?.init(data);
|
}
|
}
|
function normalizeDeleteIds(data?: any) {
|
const list = Array.isArray(data) ? data : data || data === 0 ? [data] : [];
|
return list.map((item) => (typeof item === 'object' ? item?.id || item?.[unref(getRowKey)] : item)).filter(Boolean);
|
}
|
function deleteRowsByIds(ids, bizSign?: any, hasBizSign = false) {
|
const query = {
|
ids,
|
flowId: state.config.flowId || '',
|
...(hasBizSign ? { biz_sign: bizSign } : {}),
|
};
|
return batchDelete(props.modelId, query).then((res) => {
|
createMessage.success(res.msg);
|
clearSelectedRowKeys();
|
reload();
|
});
|
}
|
function deleteRow(data) {
|
const ids = normalizeDeleteIds(data);
|
if (!ids.length) return;
|
return deleteRowsByIds([ids[0]]);
|
}
|
function batchDeleteRows(data?) {
|
const ids = normalizeDeleteIds(data);
|
const deleteIds = ids.length ? ids : getSelectRowKeys();
|
if (!deleteIds.length) return createMessage.error($t('common.selectDataTip'));
|
return deleteRowsByIds(deleteIds);
|
}
|
function handleDelete(id, skipConfirm = false, bizSign?: any, hasBizSign = false) {
|
if (skipConfirm) return deleteRowsByIds([id], bizSign, hasBizSign);
|
createConfirm({
|
iconType: 'warning',
|
title: $t('common.tipTitle'),
|
content: $t('common.delTip'),
|
onOk: () => {
|
deleteRowsByIds([id]);
|
},
|
});
|
}
|
// 行自定义按钮点击事件
|
function customBtnsHandle(item, record, index) {
|
if (!item.event.biz_sign_enabled) return executeCustomBtn(item, record, index);
|
onlineUtils.sign({
|
isFaceToFace: false,
|
metaData: getListSignMetaData(item, [record]),
|
onCancel: () => {},
|
onSubmit: (signData) => executeCustomBtn(item, record, index, signData, true),
|
});
|
}
|
function executeCustomBtn(item, record, index, signData?: any, hasBizSign = false) {
|
if (item.event.btnType == 1) handlePopup(item.event, record);
|
if (item.event.btnType == 2) handleScriptFunc(item, record, index, signData, hasBizSign);
|
if (item.event.btnType == 3) handleInterface(item.event, record);
|
if (item.event.btnType == 4) handleLaunchFlow(item, record);
|
}
|
function handlePopup(item, record) {
|
const data = {
|
...item,
|
recordModelId: props.modelId,
|
menuId: item.modelId,
|
record: toRaw(record),
|
isPreview: props.isPreview,
|
webType: state.config.webType,
|
rowKey: unref(getRowKey),
|
};
|
customFormRef.value?.init(data);
|
}
|
function getListCustomButtonSign(item, record, signData?: any, hasBizSign = false) {
|
return (callback: (data: any) => Promise<void> | void) => {
|
if (typeof callback !== 'function') return;
|
if (hasBizSign) return callback(signData);
|
return onlineUtils.sign({
|
isFaceToFace: false,
|
metaData: getListSignMetaData(item, Array.isArray(record) ? record : [record]),
|
onCancel: () => {},
|
onSubmit: callback,
|
});
|
};
|
}
|
function getListCustomButtonOnlineUtils(signData?: any, hasBizSign = false) {
|
const baseOnlineUtils = getListOnlineUtils();
|
if (!hasBizSign) return baseOnlineUtils;
|
return createSignedAuditRequestOnlineUtils(baseOnlineUtils, () => signData?.biz_sign);
|
}
|
function handleScriptFunc(item, record, index, signData?: any, hasBizSign = false) {
|
const parameter: any = {
|
data: record,
|
index,
|
refresh: reload,
|
onlineUtils: getListCustomButtonOnlineUtils(signData, hasBizSign),
|
deleteRow,
|
batchDeleteRows,
|
sign: getListCustomButtonSign(item, record, signData, hasBizSign),
|
};
|
if (hasBizSign) parameter.bizSign = signData?.biz_sign;
|
const func: any = getScriptFunc(item.event.func);
|
if (!func) return;
|
func(parameter);
|
}
|
function handleBuiltinBtnScript(item, record, index, signData?: any, hasBizSign = false) {
|
const parameter: any = {
|
data: record,
|
index,
|
refresh: reload,
|
onlineUtils: getListCustomButtonOnlineUtils(signData, hasBizSign),
|
addRow: addHandle,
|
editRow: (row = record) => updateHandle(row),
|
detailRow: (row = record) => goDetail(row),
|
deleteRow,
|
batchDeleteRows,
|
sign: getListCustomButtonSign(item, record, signData, hasBizSign),
|
};
|
if (hasBizSign) parameter.bizSign = signData?.biz_sign;
|
const func: any = getScriptFunc(item.event.func);
|
if (!func) return;
|
func(parameter);
|
}
|
function handleInterface(item, record) {
|
const handlerInterface = (data) => {
|
const query = { paramList: getParamList(item.templateJson, { ...data, id: record[unref(getRowKey)] }, unref(getRowKey)) || [] };
|
getDataInterfaceRes(item.interfaceId, query).then((res) => {
|
createMessage.success(res.msg);
|
if (item.isRefresh) reload();
|
});
|
};
|
const handlerData = () => {
|
getModelInfo(props.modelId, record[unref(getRowKey)]).then((res) => {
|
const dataForm = res.data || {};
|
if (!dataForm.data) return;
|
const data = { ...JSON.parse(dataForm.data), id: record[unref(getRowKey)] };
|
handlerInterface(data);
|
});
|
};
|
const handleFun = () => {
|
state.config.webType == '4' ? handlerInterface(record) : handlerData();
|
};
|
if (!item.useConfirm) return handleFun();
|
createConfirm({
|
iconType: 'warning',
|
title: $t('common.tipTitle'),
|
content: item.confirmTitle || '确认执行此操作?',
|
onOk: () => {
|
handleFun();
|
},
|
});
|
}
|
function handleBatchInterface(item, records) {
|
const getBatchParamList = (templateJson, data?) => {
|
if (!templateJson?.length) return [];
|
for (const e of templateJson) {
|
if (e.sourceType == 1 && data?.length) {
|
e.defaultValue = data.map((o) => (state.config.webType == '4' ? o[e.relationField] : o[`${e.relationField}_jnpfId`]));
|
}
|
if (e.sourceType == 4 && e.relationField == '@formId') e.defaultValue = data.map((o) => o.id);
|
}
|
return templateJson;
|
};
|
const handlerInterface = (data) => {
|
const query = { paramList: getBatchParamList(item.templateJson, data) || [] };
|
getDataInterfaceRes(item.interfaceId, query).then((res) => {
|
createMessage.success(res.msg);
|
if (item.isRefresh) reload();
|
});
|
};
|
if (!item.useConfirm) return handlerInterface(records);
|
createConfirm({
|
iconType: 'warning',
|
title: $t('common.tipTitle'),
|
content: item.confirmTitle || '确认执行此操作?',
|
onOk: () => {
|
handlerInterface(records);
|
},
|
});
|
}
|
function handleLaunchFlow(item, record) {
|
handleBatchLaunchFlow(item, [record]);
|
}
|
function handleBatchLaunchFlow(item, records) {
|
const launchFlowCfg = cloneDeep(item.event.launchFlow);
|
const dataList: any[] = [];
|
for (const record of records) {
|
dataList.push(getLaunchFlowParamList(launchFlowCfg.transferList, record, unref(getRowKey)));
|
}
|
const query = {
|
template: launchFlowCfg.flowId,
|
btnCode: item.value,
|
currentUser: launchFlowCfg.currentUser,
|
customUser: launchFlowCfg.customUser,
|
initiator: launchFlowCfg.initiator,
|
hasPermission: launchFlowCfg.hasPermission,
|
dataList,
|
};
|
launchFlow(props.modelId, query).then((res) => {
|
createMessage.success(res.msg);
|
});
|
}
|
async function init() {
|
state.config = {
|
modelId: props.modelId,
|
isPreview: props.isPreview,
|
...props.config,
|
};
|
searchInfo.modelId = props.modelId;
|
searchInfo.menuId = (props.menuId || route.meta.modelId) as string;
|
searchInfo.flowId = state.config.flowId || '';
|
searchInfo.onlineUtilsOpen = !!props.isOnlineUtilsOpen;
|
if (props.isPreview) searchInfo.menuId = '270579315303777093';
|
if (!state.config.columnData || (state.config.webType != '4' && !state.config.formData)) return;
|
initExternalParams();
|
refreshViewInterfacePageParams();
|
state.columnData = JSON.parse(state.config.columnData);
|
if (state.columnData.type === 3) {
|
state.columnData.columnList = state.columnData.columnList.filter((o) => o.prop != state.columnData.groupField);
|
}
|
state.formConf = state.config.formData ? JSON.parse(state.config.formData) : {};
|
const customBtnsList = state.columnData.customBtnsList || [];
|
const columnBtnsList = state.columnData.columnBtnsList || [];
|
getHeaderBtnsList(state.columnData.btnsList || []);
|
getColumnBtnsList(columnBtnsList, customBtnsList);
|
// 设置头部按钮样式为primary
|
state.headerBtnsList.forEach((btn) => {
|
// 为导出、批量删除、批量打印等按钮设置primary样式
|
if (['batchPrint', 'batchRemove', 'download'].includes(btn.value)) {
|
btn.type = 'primary';
|
}
|
});
|
// 设置自定义头部按钮样式为primary
|
state.customHeaderBtnsList.forEach((btn) => {
|
btn.type = 'primary';
|
});
|
state.columnOptions = state.columnData.columnOptions || [];
|
if (!unref(getPagination)) (searchInfo as any).pageSize = 1000000;
|
setLoading(true);
|
if (state.columnData.funcs.rowStyle) {
|
state.customRow = (record, index) => {
|
const data = { row: record, rowIndex: index };
|
const func: any = getScriptFunc(state.columnData.funcs.rowStyle);
|
const style: any = func ? func(data) : null;
|
if (!style) return {};
|
return { style };
|
};
|
}
|
if (state.columnData.funcs.cellStyle) {
|
state.customCell = (record, rowIndex, column) => {
|
const data = { row: record, rowIndex, column, columnIndex: column.key };
|
const func: any = getScriptFunc(state.columnData.funcs.cellStyle);
|
const style: any = func ? func(data) : null;
|
if (!style) return {};
|
return { style };
|
};
|
}
|
getSearchSchemas();
|
getColumnList();
|
!props.isDataManage && !props.isPreview && !props.isOnlineUtilsOpen && (await initViewList());
|
if (state.columnData.type == 4 || state.config.webType == '4') buildOptions();
|
if ([1, 4].includes(state.columnData.type)) getTabList();
|
if (state.columnData.funcs.rowStyle) state.rowStyle = getScriptFunc(state.columnData.funcs.rowStyle) || null;
|
if (state.columnData.funcs.cellStyle) state.cellStyle = getScriptFunc(state.columnData.funcs.cellStyle) || null;
|
if (props.isPreview) return setLoading(false);
|
if (state.columnData.type === 2) {
|
state.treeFieldNames.key = state.columnData.treePropsValue || 'id';
|
state.treeFieldNames.title = state.columnData.treePropsLabel || 'fullName';
|
state.treeFieldNames.children = state.columnData.treePropsChildren || 'children';
|
getTreeView();
|
} else {
|
nextTick(() => {
|
unref(getSearchList)?.length ? searchFormSubmit() : handleSearchSubmit({});
|
});
|
}
|
}
|
async function getTreeView() {
|
state.isLeftTreeLazy = false;
|
state.leftTreeLoading = true;
|
state.leftTreeActiveInfo = {};
|
state.treeQueryJson = {};
|
state.leftTreeData = [];
|
state.treeActiveId = '';
|
state.treeActiveNodePath = [];
|
let leftTreeData: any[] = [];
|
if (state.columnData.treeDataSource === 'dictionary') {
|
if (!state.columnData.treeDictionary) return (state.leftTreeLoading = false);
|
leftTreeData = await baseStore.getDicDataSelector(state.columnData.treeDictionary);
|
}
|
if (state.columnData.treeDataSource === 'organize') {
|
state.isLeftTreeLazy = true;
|
const res = await getOrganizeSelector();
|
leftTreeData = res.data.list;
|
}
|
if (state.columnData.treeDataSource === 'api') {
|
if (!state.columnData.treePropsUrl) return (state.leftTreeLoading = false);
|
const query = { paramList: getParamList(state.columnData.treeTemplateJson) || [] };
|
const res = await getDataInterfaceRes(state.columnData.treePropsUrl, query);
|
leftTreeData = Array.isArray(res.data) ? res.data : [];
|
}
|
if (state.columnData.treeDataSource === 'formField') {
|
const treeRelationObj: any = state.treeRelationObj;
|
const jnpfKey = treeRelationObj?.__config__?.jnpfKey || '';
|
if (state.columnData.treeRelation && jnpfKey === 'organizeSelect') {
|
if (treeRelationObj.selectType === 'all') {
|
state.isLeftTreeLazy = true;
|
const res = await getOrganizeSelector();
|
leftTreeData = res.data.list;
|
}
|
if (treeRelationObj.selectType === 'custom' && treeRelationObj.ableIds?.length) {
|
const res = await getOrgByOrganizeCondition(treeRelationObj.ableIds);
|
leftTreeData = res.data.list;
|
}
|
}
|
}
|
state.leftTreeData = leftTreeData;
|
state.leftTreeLoading = false;
|
nextTick(() => {
|
if (state.leftTreeData.length) leftTreeRef.value?.setExpandedKeys([state.leftTreeData[0].id]);
|
if (unref(getSearchList)?.length) {
|
searchFormSubmit();
|
} else {
|
refreshSuperQueryJson();
|
reload({ page: 1 });
|
}
|
});
|
}
|
// 获取标签面板数据、设置标签面板默认值
|
async function getTabList() {
|
state.tabList = [];
|
if (!state.columnData.tabConfig || !state.columnData.tabConfig.on || !state.columnData.tabConfig.relationField) return;
|
state.columnData.tabConfig?.hasAllTab && state.tabList.push({ fullName: '全部', id: '' });
|
const list: any[] = state.columnData.columnOptions.filter((o) => o.__vModel__ == state.columnData.tabConfig.relationField) || [];
|
if (list?.length) {
|
if (list[0].__config__.dataType == 'dictionary' && list[0].__config__.dictionaryType) {
|
const data = (await baseStore.getDicDataSelector(list[0].__config__.dictionaryType)) || [];
|
const options = list[0].props.value == 'enCode' ? data.map((o) => ({ ...o, id: o.enCode })) : data;
|
state.tabList = [...state.tabList, ...options];
|
} else {
|
state.tabList = [...state.tabList, ...list[0].options];
|
}
|
}
|
if (state.tabList?.length) {
|
state.tabActiveKey = state.tabList[0].id || '';
|
state.tabQueryJson = { [state.columnData.tabConfig.relationField]: state.tabList[0].id };
|
}
|
}
|
function onTabChange(val) {
|
if (props.isPreview) return;
|
state.tabQueryJson = { [state.columnData.tabConfig.relationField]: val };
|
unref(getSearchList)?.length ? resetFields() : handleSearchSubmit({});
|
}
|
function getHeaderBtnsList(btnsList) {
|
btnsList = btnsList.filter((o) => o.show || !Reflect.has(o, 'show'));
|
const resolveList = (list) => list.filter((item) => getHeaderBtnVisible(item));
|
if (props.isPreview || props.isDataManage || props.isOnlineUtilsOpen || !state.columnData.useBtnPermission)
|
return (state.headerBtnsList = resolveList(btnsList));
|
// 过滤权限
|
const btns: any[] = [];
|
for (const element of btnsList) {
|
if (hasBtnP(`btn_${element.value}`)) btns.push(element);
|
}
|
state.headerBtnsList = resolveList(btns);
|
}
|
function getColumnBtnsList(columnBtnsList, customBtnsList) {
|
columnBtnsList = columnBtnsList.filter((o) => o.show || !Reflect.has(o, 'show'));
|
let btns: any[] = [];
|
let customBtns: any[] = [];
|
if (props.isPreview || props.isDataManage || props.isOnlineUtilsOpen || !state.columnData.useBtnPermission) {
|
btns = columnBtnsList;
|
customBtns = customBtnsList;
|
} else {
|
// 过滤权限
|
const list = permissionList.find((o) => o.modelId === searchInfo.menuId);
|
const perBtnList = list && list.button ? list.button : [];
|
for (const element of columnBtnsList) {
|
inner: for (const element_ of perBtnList) {
|
if (`btn_${element.value}` === element_?.enCode) {
|
btns.push(element);
|
break inner;
|
}
|
}
|
}
|
for (const element of customBtnsList) {
|
inner: for (const element_ of perBtnList) {
|
if (element.value === element_?.enCode) {
|
customBtns.push(element);
|
break inner;
|
}
|
}
|
}
|
}
|
state.columnBtnsList = btns;
|
state.customHeaderBtnsList = customBtns.filter((o) => o.event?.position === 2 && getHeaderBtnVisible(o));
|
state.customColumnBtnsList = customBtns.filter((o) => o.event?.position !== 2);
|
if (state.columnData.type == 5) state.customHeaderBtnsList = [];
|
}
|
function getSearchSchemas() {
|
if (state.columnData.treeRelation) {
|
for (let i = 0; i < state.columnData.columnOptions.length; i++) {
|
const e = state.columnData.columnOptions[i];
|
if (e.id === state.columnData.treeRelation) {
|
state.treeRelationObj = { ...e, searchMultiple: false, jnpfKey: e.__config__.jnpfKey };
|
break;
|
}
|
}
|
}
|
const schemas = getSearchFormSchemas(state.columnData.searchList, state.config.enableFlow);
|
state.searchSchemas = schemas;
|
}
|
function getSearchOptions(schemas) {
|
schemas.forEach((cur) => {
|
const config = cur.__config__;
|
if (dyOptionsList.includes(config.jnpfKey)) {
|
if (config.dataType === 'dictionary' && config.dictionaryType) {
|
baseStore.getDicDataSelector(config.dictionaryType).then((res) => {
|
updateSchema([{ field: cur.field, componentProps: { options: res } }]);
|
});
|
}
|
if (config.dataType === 'dynamic' && config.propsUrl) {
|
const query = { paramList: config.templateJson || [] };
|
getDataInterfaceRes(config.propsUrl, query).then((res) => {
|
const data = Array.isArray(res.data) ? res.data : [];
|
updateSchema([{ field: cur.field, componentProps: { options: data } }]);
|
});
|
}
|
}
|
if ((Array.isArray(cur.value) && cur.value.length) || cur.value || cur.value === 0 || cur.value === false) cur.defaultValue = cur.value;
|
});
|
}
|
// 获取列
|
function getColumnList() {
|
let columnList: any[] = [];
|
if (props.isPreview || props.isDataManage || props.isOnlineUtilsOpen || !state.columnData.useColumnPermission) {
|
columnList = state.columnData.columnList;
|
} else {
|
// 过滤权限
|
const list = permissionList.find((o) => o.modelId === searchInfo.menuId);
|
const perColumnList = list && list.column ? list.column : [];
|
for (let i = 0; i < state.columnData.columnList.length; i++) {
|
inner: for (const element of perColumnList) {
|
if (state.columnData.columnList[i].prop === element.enCode) {
|
columnList.push(state.columnData.columnList[i]);
|
break inner;
|
}
|
}
|
}
|
}
|
// 列上的掩码配置是表单字段的旧快照,以当前表单字段为准
|
const maskMap = buildFormFieldMaskMap(state.formConf);
|
let columns = columnList
|
.filter((o) => !o.noShow)
|
.map((o) => {
|
const item: any = {
|
...o,
|
placeholder: state.columnData.type == 4 && o.placeholderI18nCode ? $t(o.placeholderI18nCode, o.placeholder) : o.placeholder,
|
title: o.labelI18nCode ? $t(o.labelI18nCode, o.label) : o.label,
|
dataIndex: o.prop,
|
align: o.align,
|
fixed: o.fixed == 'none' ? '' : o.fixed,
|
sortable: o.sortable,
|
width: o.width || '',
|
minWidth: o.width || 100,
|
};
|
const maskField = maskMap.get(o.prop);
|
if (maskField) {
|
item.useMask = maskField.useMask;
|
item.maskConfig = maskField.maskConfig || item.maskConfig;
|
}
|
if (item.useContentFormat) item.slots = { default: item.prop };
|
// 行内编辑和部分控件加插槽
|
if (
|
(state.columnData.type === 4 || slotsList.includes(item.jnpfKey) || (state.config.webType == '4' && viewEchoSlotList.has(item.jnpfKey))) &&
|
!item.dataIndex.includes('-')
|
) {
|
item.slots = { default: item.prop };
|
}
|
item.showOverflow = !!(state.columnData.showOverflow && !overflowInvalidList.includes(item.jnpfKey) && state.columnData.type !== 4);
|
return item;
|
});
|
state.allColumns = columns;
|
if (state.columnData.type !== 3 && state.columnData.type !== 5) columns = getComplexColumns(columns);
|
state.columns = columns.filter((o) => !o.prop.includes('-'));
|
if (state.columnData.type == 4) buildRowRelation();
|
getChildComplexColumns(columns);
|
}
|
function getComplexColumns(columns) {
|
let complexHeaderList: any[] = state.columnData.complexHeaderList || [];
|
if (!complexHeaderList.length) return columns;
|
const childColumns: any[] = [];
|
const firstChildColumns: string[] = [];
|
for (const e of complexHeaderList) {
|
e.label = e.fullName;
|
e.labelI18nCode = e.fullNameI18nCode;
|
e.title = e.fullNameI18nCode ? $t(e.fullNameI18nCode, e.fullName) : e.fullName;
|
e.dataIndex = e.id;
|
e.prop = e.id;
|
e.children = [];
|
e.jnpfKey = 'complexHeader';
|
if (e.childColumns?.length) {
|
childColumns.push(...e.childColumns);
|
for (let k = 0; k < e.childColumns.length; k++) {
|
const item = e.childColumns[k];
|
for (const o of columns) {
|
if (o.prop == item && o.fixed !== 'left' && o.fixed !== 'right') e.children.push({ ...omit(o, ['fixed']) });
|
}
|
}
|
}
|
if (e.children.length) firstChildColumns.push(e.children[0].prop);
|
}
|
complexHeaderList = complexHeaderList.filter((o) => o.children.length);
|
const list: any[] = [];
|
for (const e of columns) {
|
if (!childColumns.includes(e.prop) || e.fixed === 'left' || e.fixed === 'right') {
|
list.push(e);
|
} else {
|
if (firstChildColumns.includes(e.prop)) {
|
const item = complexHeaderList.find((o) => o.childColumns.includes(e.prop));
|
list.push(item);
|
}
|
}
|
}
|
return list;
|
}
|
function getChildComplexColumns(columnList) {
|
const list: any[] = [];
|
for (const e of columnList) {
|
if (e.prop.includes('-')) {
|
const prop = e.prop.split('-')[0];
|
let label = e.label.split('-')[0];
|
const childLabel = e.label.replace(`${label}-`, '');
|
if (e.fullNameI18nCode && Array.isArray(e.fullNameI18nCode) && e.fullNameI18nCode[0]) label = $t(e.fullNameI18nCode[0], label);
|
const newItem = {
|
align: 'center',
|
jnpfKey: 'table',
|
prop,
|
label,
|
title: label,
|
dataIndex: prop,
|
children: [],
|
customCell: state.customCell || null,
|
};
|
e.dataIndex = e.prop;
|
e.title = e.labelI18nCode ? $t(e.labelI18nCode, childLabel) : childLabel;
|
if (!Object.prototype.hasOwnProperty.call(state.expandObj, `${prop}Expand`)) state.expandObj[`${prop}Expand`] = false;
|
if (!list.some((o) => o.prop === prop)) list.push(newItem);
|
for (const element of list) {
|
if (element.prop === prop) {
|
const childItem =
|
!element.children.length && unref(getChildTableStyle) == 1
|
? { ...e, slots: { default: element.dataIndex }, showOverflow: false, className: 'child-table-box' }
|
: e;
|
element.children.push({ ...omit(childItem, ['fixed']) });
|
break;
|
}
|
}
|
} else {
|
list.push(e);
|
}
|
}
|
if (unref(getChildTableStyle) != 2) getMergeList(list);
|
getExportList(list);
|
state.complexColumns = list;
|
state.childColumnList = list.filter((o) => o.jnpfKey === 'table');
|
// 子表分组展示若没设置宽度,默认取100
|
for (let i = 0; i < state.childColumnList.length; i++) {
|
const e = state.childColumnList[i];
|
if (e.children?.length) {
|
e.children = e.children.map((o) => {
|
const item = { ...o };
|
if (unref(getChildTableStyle) == 2) {
|
item.field = o.__vModel__;
|
item.dataIndex = o.__vModel__;
|
if (state.columnData.type === 4 || slotsList.includes(item.jnpfKey)) {
|
item.slots = { default: item.dataIndex };
|
}
|
item.width = o.width || '';
|
item.minWidth = o.width || 100;
|
} else {
|
item.width = o.width || '';
|
item.minWidth = o.width || 100;
|
}
|
return item;
|
});
|
}
|
}
|
}
|
function getMergeList(list) {
|
list.forEach((item) => {
|
if (item.jnpfKey === 'table' && item.children?.length) {
|
item.children.forEach((child, index) => {
|
state.mergeList.push({
|
prop: child.prop,
|
rowspan: index == 0 ? 1 : 0,
|
colspan: index == 0 ? item.children.length : 0,
|
});
|
});
|
}
|
});
|
}
|
function spanMethod({ column }) {
|
for (let i = 0; i < state.mergeList.length; i++) {
|
if (column.property == state.mergeList[i].prop) {
|
return { rowspan: state.mergeList[i].rowspan, colspan: state.mergeList[i].colspan };
|
}
|
}
|
}
|
function getExportList(list) {
|
const exportList: any[] = [];
|
for (const element of list) {
|
if (element.jnpfKey === 'table') {
|
if (state.columnData.type != 4) exportList.push(...element.children);
|
} else if (element.jnpfKey === 'complexHeader') {
|
exportList.push(...element.children);
|
} else {
|
exportList.push(element);
|
}
|
}
|
state.exportList = exportList;
|
}
|
function setTableLoadFunc() {
|
const parameter = { data: state.cacheList, tableRef: tableRef.value, onlineUtils: getListOnlineUtils() };
|
const func: any = getScriptFunc(state.columnData.funcs.afterOnload);
|
if (!func) return;
|
func(parameter);
|
}
|
function toggleExpand(row, field) {
|
row[field] = !row[field];
|
}
|
// 关联表单查看详情
|
function toDetail(modelId, id, propsValue) {
|
if (!id) return;
|
getConfigData(modelId).then((res) => {
|
if (!res.data || !res.data.formData) return;
|
const formConf = JSON.parse(res.data.formData);
|
formConf.popupType = 'general';
|
formConf.customBtns = [];
|
formConf.hasPrintBtn = false;
|
const data = { id, formConf, modelId, propsValue };
|
detailRef.value?.init(data);
|
});
|
}
|
function handleColumnChange(data) {
|
state.columnSettingList = data;
|
}
|
// 左侧树异步加载
|
function onLoadData(node) {
|
return new Promise((resolve: (value?: unknown) => void) => {
|
if (state.columnData.treeDataSource === 'api') {
|
if (!state.columnData.treeSyncInterfaceId) return resolve();
|
if (state.columnData.treeSyncTemplateJson?.length) {
|
for (let i = 0; i < state.columnData.treeSyncTemplateJson.length; i++) {
|
const e = state.columnData.treeSyncTemplateJson[i];
|
e.defaultValue = node[e.relationField] || '';
|
}
|
}
|
const query = { paramList: getParamList(state.columnData.treeSyncTemplateJson) || [] };
|
getDataInterfaceRes(state.columnData.treeSyncInterfaceId, query).then((res) => {
|
const data = Array.isArray(res.data) ? res.data : [];
|
leftTreeRef.value?.updateNodeByKey(node.eventKey, { children: data, isLeaf: !data.length });
|
resolve();
|
});
|
} else {
|
getOrganizeSelector({ parentId: node.id }).then((res) => {
|
const list = res.data.list;
|
leftTreeRef.value?.updateNodeByKey(node.eventKey, { children: list, isLeaf: !list.length });
|
resolve();
|
});
|
}
|
});
|
}
|
// 高级查询
|
function handleSuperQuery(superQueryJson) {
|
if (props.isPreview) return;
|
state.userSuperQueryJson = superQueryJson;
|
refreshSuperQueryJson();
|
reload({ page: 1 });
|
}
|
function getSuperQueryFieldOptions() {
|
return (state.columnData.columnList || []).filter((column) => !column.noShow && !column.superQueryNoShow);
|
}
|
function parseSuperQueryJson(value) {
|
if (!value) return null;
|
try {
|
return JSON.parse(value);
|
} catch {
|
return null;
|
}
|
}
|
function getParamConditionList(ruleList) {
|
return Array.isArray(ruleList?.paramConditionList) ? ruleList.paramConditionList : [];
|
}
|
function getParamConditionFieldKey(item) {
|
return item?.id || item?.field || item?.__vModel__ || '';
|
}
|
function mergeParamConditionList(primaryList, fallbackList) {
|
const usedKeys = new Set<string>();
|
const mergedList: any[] = [];
|
for (const condition of primaryList) {
|
const groups = Array.isArray(condition.groups) ? condition.groups : [];
|
groups.forEach((item) => {
|
const key = getParamConditionFieldKey(item);
|
if (key) usedKeys.add(key);
|
});
|
if (groups.length) mergedList.push(condition);
|
}
|
for (const condition of fallbackList) {
|
const groups = Array.isArray(condition.groups) ? condition.groups.filter((item) => !usedKeys.has(getParamConditionFieldKey(item))) : [];
|
groups.forEach((item) => {
|
const key = getParamConditionFieldKey(item);
|
if (key) usedKeys.add(key);
|
});
|
if (groups.length) mergedList.push({ ...condition, groups });
|
}
|
return mergedList;
|
}
|
function getActiveExternalRuleList() {
|
const appRuleList = state.columnData.ruleListApp;
|
const pcRuleList = state.columnData.ruleList;
|
if (state.config.enableFlow) {
|
return {
|
matchLogic: appRuleList?.matchLogic || pcRuleList?.matchLogic || 'and',
|
paramConditionList: mergeParamConditionList(getParamConditionList(appRuleList), getParamConditionList(pcRuleList)),
|
};
|
}
|
return state.config.webType == '4' ? appRuleList : pcRuleList;
|
}
|
function getResolvedSuperQueryJson() {
|
const ruleList = getActiveExternalRuleList();
|
const resolvedRuleList = resolveExternalRuleQuery({
|
matchLogic: ruleList?.matchLogic || 'and',
|
conditionList: ruleList?.paramConditionList || [],
|
});
|
const paramList = Array.isArray(resolvedRuleList.conditionList) ? resolvedRuleList.conditionList : [];
|
const superQuery = parseSuperQueryJson(state.userSuperQueryJson);
|
const userConditionList = Array.isArray(superQuery?.conditionList) ? superQuery.conditionList : [];
|
const conditionList = [...paramList, ...userConditionList];
|
const matchLogic = paramList.length && userConditionList.length ? 'and' : superQuery?.matchLogic || ruleList?.matchLogic || 'and';
|
return conditionList.length ? JSON.stringify({ matchLogic, conditionList }) : '';
|
}
|
function refreshSuperQueryJson() {
|
searchInfo.superQueryJson = getResolvedSuperQueryJson();
|
}
|
function showLoadingBeforeReload() {
|
setLoading(true);
|
}
|
function handleSearchSubmit(data) {
|
if (props.isPreview) return;
|
clearSelectedRowKeys();
|
let obj = {};
|
for (const [key, value] of Object.entries(data)) {
|
if (value || value === 0 || value === false) {
|
if (Array.isArray(value)) {
|
if (value.length) obj[key] = value;
|
} else {
|
obj[key] = value;
|
}
|
}
|
}
|
obj = { ...obj, ...state.treeQueryJson, ...state.tabQueryJson };
|
searchInfo.queryJson = JSON.stringify(obj) === '{}' ? '' : JSON.stringify(obj);
|
refreshSuperQueryJson();
|
showLoadingBeforeReload();
|
reload({ page: 1 });
|
}
|
function handleSearchReset() {
|
searchFormSubmit();
|
}
|
function handleRowForm(record) {
|
let fields: any[] = [];
|
for (let i = 0; i < unref(getColumns).length; i++) {
|
const e = unref(getColumns)[i];
|
if (e.children?.length) {
|
for (let j = 0; j < e.children.length; j++) {
|
const o = e.children[j];
|
o.__config__.span = 24;
|
o.__config__.label = o.label;
|
fields.push(toRaw(o));
|
}
|
} else {
|
e.__config__.span = 24;
|
e.__config__.label = e.label;
|
fields.push(toRaw(e));
|
}
|
}
|
fields = fields.map((o) => {
|
if (o.__config__?.templateJson && o.__config__?.templateJson.length) {
|
o.__config__.templateJson = o.__config__.templateJson.map((o) => ({ ...o, relationField: '' }));
|
}
|
if (o.templateJson && o.templateJson.length) {
|
o.templateJson = o.templateJson.map((o) => ({ ...o, relationField: '' }));
|
}
|
return o;
|
});
|
const formConf = { ...state.formConf, fields, popupType: 'general' };
|
const data = {
|
id: record.id,
|
formConf,
|
modelId: props.modelId,
|
isPreview: props.isPreview,
|
isDataManage: props.isDataManage,
|
isOnlineUtilsOpen: props.isOnlineUtilsOpen,
|
useFormPermission: state.columnData.useFormPermission,
|
showMoreBtn: false,
|
menuId: searchInfo.menuId,
|
allList: state.cacheList,
|
formData: record,
|
};
|
formRef.value?.init(data);
|
}
|
// 行内编辑获取选项
|
function buildOptions() {
|
const loop = (list) => {
|
for (const cur of list) {
|
if (cur.children?.length) loop(cur.children);
|
const config = cur.__config__;
|
if (!config) continue;
|
if (dyOptionsList.includes(config.jnpfKey)) {
|
const index = state.allColumns.findIndex((o) => o.id === cur.id);
|
if (config.dataType === 'dictionary' && config.dictionaryType) {
|
cur.options = [];
|
if (index !== -1) state.allColumns[index].options = [];
|
baseStore.getDicDataSelector(config.dictionaryType).then((res) => {
|
cur.options = res;
|
if (index !== -1) state.allColumns[index].options = res;
|
});
|
}
|
if (config.dataType === 'dynamic' && config.propsUrl) {
|
cur.options = [];
|
if (index !== -1) state.allColumns[index].options = [];
|
const query = { paramList: config.templateJson || [] };
|
getDataInterfaceRes(config.propsUrl, query).then((res) => {
|
cur.options = Array.isArray(res.data) ? res.data : [];
|
if (index !== -1) state.allColumns[index].options = cur.options;
|
});
|
}
|
}
|
}
|
};
|
loop(state.columns);
|
}
|
async function fillViewUserEchoText(list) {
|
if (state.config.webType != '4' || !list?.length) return;
|
const echoColumns = state.allColumns.filter((o) =>
|
['groupSelect', 'organizeSelect', 'posSelect', 'roleSelect', 'userSelect', 'usersSelect'].includes(o.jnpfKey),
|
);
|
if (!echoColumns.length) return;
|
const rows: any[] = [];
|
const loopRows = (data = []) => {
|
for (const item of data) {
|
rows.push(item);
|
if (item.children?.length) loopRows(item.children);
|
}
|
};
|
loopRows(list);
|
const idsMap = {
|
groupSelect: new Set<string>(),
|
organizeSelect: new Set<string>(),
|
posSelect: new Set<string>(),
|
roleSelect: new Set<string>(),
|
userSelect: new Set<string>(),
|
usersSelect: new Set<string>(),
|
};
|
for (const row of rows) {
|
for (const column of echoColumns) {
|
if (row[`${column.prop}_name`]) continue;
|
const valueList = getViewEchoValueList(row[column.prop], column.multiple || column.jnpfKey === 'usersSelect');
|
valueList.forEach((id) => {
|
if (id && !String(id).startsWith('@') && !String(id).includes('--')) idsMap[column.jnpfKey].add(String(id));
|
});
|
}
|
}
|
const requestList = [
|
{ api: getUserInfoList, ids: [...idsMap.userSelect, ...idsMap.usersSelect], keys: ['userSelect', 'usersSelect'], labelKey: 'fullName' },
|
{ api: getOrgSelectedList, ids: [...idsMap.organizeSelect], keys: ['organizeSelect'], labelKey: 'orgNameTree' },
|
{ api: getPositionSelectedList, ids: [...idsMap.posSelect], keys: ['posSelect'], labelKey: 'orgNameTree' },
|
{ api: getRoleByCondition, ids: [...idsMap.roleSelect], keys: ['roleSelect'], labelKey: 'fullName' },
|
{ api: getGroupByCondition, ids: [...idsMap.groupSelect], keys: ['groupSelect'], labelKey: 'fullName' },
|
].filter((o) => o.ids.length);
|
if (!requestList.length) return;
|
const resList = await Promise.all(requestList.map((item) => item.api(item.ids).then((res) => ({ ...item, list: res.data.list || [] }))));
|
const textMap = new Map<string, Map<string, string>>();
|
for (const resItem of resList) {
|
const itemMap = new Map(resItem.list.map((item) => [String(item.id), item[resItem.labelKey] || item.fullName || item.orgNameTree]));
|
resItem.keys.forEach((key) => textMap.set(key, itemMap));
|
}
|
for (const row of rows) {
|
for (const column of echoColumns) {
|
if (row[`${column.prop}_name`]) continue;
|
const valueList = getViewEchoValueList(row[column.prop], column.multiple || column.jnpfKey === 'usersSelect');
|
const itemMap = textMap.get(column.jnpfKey);
|
const text = valueList.map((id) => itemMap?.get(String(id)) || id).join(',');
|
if (text) row[`${column.prop}_name`] = text;
|
}
|
}
|
}
|
function normalizeDateFormat(format = 'yyyy-MM-dd') {
|
return format.replaceAll('yyyy', 'YYYY').replaceAll('dd', 'DD');
|
}
|
function getViewEchoValueList(value, multiple) {
|
if (Array.isArray(value)) return value;
|
if (value === null || value === undefined || value === '') return [];
|
if (typeof value === 'string') {
|
try {
|
const list = JSON.parse(value);
|
if (Array.isArray(list)) return list;
|
} catch {}
|
if (multiple && value.includes(',')) return value.split(',');
|
}
|
return [value];
|
}
|
function getViewEchoOptionText(column, value) {
|
const valueList = getViewEchoValueList(value, column.multiple || column.jnpfKey === 'checkbox');
|
const fieldNames = column.props || {};
|
const valueKey = fieldNames.value || 'id';
|
const labelKey = fieldNames.label || 'fullName';
|
const options: any[] = [];
|
const loop = (list = []) => {
|
for (const item of list) {
|
options.push(item);
|
if (item.children?.length) loop(item.children);
|
}
|
};
|
loop(column.options || []);
|
return valueList
|
.map((valueItem) => {
|
const option = options.find((item) => String(item[valueKey]) === String(valueItem));
|
return option ? option[labelKey] : valueItem;
|
})
|
.filter((item) => item !== null && item !== undefined && item !== '')
|
.join(',');
|
}
|
function getViewEchoText(column, record) {
|
if (column.__config__?.dataType === 'formData') {
|
const value = getFormDataOptionLabel(column, record, record[column.prop]);
|
return Array.isArray(value) ? value.join(',') : value;
|
}
|
const nameValue = record[`${column.prop}_name`];
|
const value = nameValue !== null && nameValue !== undefined && nameValue !== '' ? nameValue : record[column.prop];
|
if (value === null || value === undefined || value === '') return '';
|
if (['checkbox', 'radio', 'select'].includes(column.jnpfKey)) return getViewEchoOptionText(column, value);
|
if (column.jnpfKey === 'datePicker') {
|
const dateValue = typeof value === 'number' || /^\d+$/.test(String(value)) ? Number(value) : value;
|
const date = dayjs(dateValue);
|
return date.isValid() ? date.format(normalizeDateFormat(column.format)) : value;
|
}
|
if (column.jnpfKey === 'timePicker') return value;
|
return Array.isArray(value) ? value.join(',') : value;
|
}
|
function getColumnDisplayText(column, record) {
|
if (viewEchoSlotList.has(column.jnpfKey)) return getViewEchoText(column, record);
|
const nameValue = record[`${column.prop}_name`];
|
const value = nameValue || record[column.prop];
|
if (value === null || value === undefined) return '';
|
return Array.isArray(value) ? value.join(',') : value;
|
}
|
function formatColumnContent(column, record, rowIndex) {
|
const data = getColumnDisplayText(column, record);
|
const func: any = getScriptFunc(column.contentFormat);
|
if (!func) return data;
|
try {
|
const result = func({ data, row: record, rowIndex, onlineUtils: getListOnlineUtils() });
|
return result === undefined ? data : result;
|
} catch {
|
return data;
|
}
|
}
|
function buildRowRelation() {
|
const loop = (list) => {
|
for (const cur of list) {
|
if (cur.children?.length) loop(cur.children);
|
const config = cur?.__config__;
|
if (!config) continue;
|
if (config.jnpfKey === 'datePicker') {
|
if (config.startTimeRule) {
|
if (config.startTimeType == 1) cur.startTime = config.startTimeValue;
|
if (config.startTimeType == 3) cur.startTime = Date.now();
|
if (config.startTimeType == 4 || config.startTimeType == 5) {
|
const type = getTimeUnit(config.startTimeTarget);
|
const method = config.startTimeType == 4 ? 'subtract' : 'add';
|
const startTime = dayjs()[method](config.startTimeValue, type);
|
let realStartTime = startTime.startOf('day').valueOf();
|
if (config.startTimeTarget == 4) realStartTime = startTime.startOf('minute').valueOf();
|
if (config.startTimeTarget == 5) realStartTime = startTime.startOf('second').valueOf();
|
if (config.startTimeTarget == 6) realStartTime = startTime.valueOf();
|
cur.startTime = realStartTime;
|
}
|
}
|
if (config.endTimeRule) {
|
if (config.endTimeType == 1) cur.endTime = config.endTimeValue;
|
if (config.endTimeType == 3) cur.endTime = Date.now();
|
if (config.endTimeType == 4 || config.endTimeType == 5) {
|
const type = getTimeUnit(config.endTimeTarget);
|
const method = config.endTimeType == 4 ? 'subtract' : 'add';
|
const endTime = dayjs()[method](config.endTimeValue, type);
|
let realEndTime = endTime.endOf('day').valueOf();
|
if (config.endTimeTarget == 4) realEndTime = endTime.endOf('minute').valueOf();
|
if (config.endTimeTarget == 5) realEndTime = endTime.endOf('second').valueOf();
|
if (config.endTimeTarget == 6) realEndTime = endTime.valueOf();
|
cur.endTime = realEndTime;
|
}
|
}
|
}
|
if (config.jnpfKey === 'timePicker') {
|
if (config.startTimeRule) {
|
if (config.startTimeType == 1) cur.startTime = config.startTimeValue || null;
|
if (config.startTimeType == 3) cur.startTime = dayjs().format(cur.format);
|
if (config.startTimeType == 4 || config.startTimeType == 5) {
|
const type = getTimeUnit(config.startTimeTarget + 3);
|
const method = config.startTimeType == 4 ? 'subtract' : 'add';
|
const startTime = dayjs()[method](config.startTimeValue, type).format(cur.format);
|
cur.startTime = startTime;
|
}
|
}
|
if (config.endTimeRule) {
|
if (config.endTimeType == 1) cur.endTime = config.endTimeValue || null;
|
if (config.endTimeType == 3) cur.endTime = dayjs().format(cur.format);
|
if (config.endTimeType == 4 || config.endTimeType == 5) {
|
const type = getTimeUnit(config.endTimeTarget + 3);
|
const method = config.endTimeType == 4 ? 'subtract' : 'add';
|
const endTime = dayjs()[method](config.endTimeValue, type).format(cur.format);
|
cur.endTime = endTime;
|
}
|
}
|
}
|
}
|
};
|
loop(state.columns);
|
}
|
async function initViewList(currentId = '') {
|
const query = {
|
menuId: searchInfo.menuId,
|
};
|
await getViewList(query).then((res) => {
|
const columns: any[] = unref(getChildTableStyle) == 2 || state.columnData.type == 4 ? state.columns : state.complexColumns;
|
const searchList: any[] = state.searchSchemas.map((o) => ({ label: o.label, id: o.field, show: o.show }));
|
const columnList: any[] = columns.map((o) => ({ label: o.label, id: o.prop, show: true, fixed: o.fixed || 'none', labelI18nCode: o.labelI18nCode }));
|
state.viewList = (res.data || []).map((o) => {
|
if (o.type == 0) return { ...o, searchList, columnList };
|
return { ...o, searchList: o.searchList ? JSON.parse(o.searchList) : [], columnList: o.columnList ? JSON.parse(o.columnList) : [] };
|
});
|
state.currentView = currentId
|
? state.viewList.find((o) => o.id === currentId) || state.viewList[0]
|
: state.viewList.find((o) => o.status === 1) || state.viewList[0];
|
});
|
}
|
function handleViewClick(item) {
|
state.currentView = item;
|
}
|
function setListValue(data: any[] = [], defaultData: any[] = [], key) {
|
const list: any[] = [];
|
for (const datum of data) {
|
for (const defaultDatum of defaultData) {
|
if (datum.show && datum.id == defaultDatum[key]) list.push(defaultDatum);
|
}
|
}
|
return list;
|
}
|
function handleColumnResizableChange({ resizeColumn, resizeWidth }) {
|
if (!resizeColumn.field || !resizeColumn.field.includes('-')) return;
|
const tableVModel = resizeColumn.field.split('-')[0];
|
setTimeout(() => {
|
for (let i = 0; i < state.childColumnList.length; i++) {
|
const element = state.childColumnList[i];
|
if (element.prop == tableVModel) {
|
for (let j = 0; j < element.children.length; j++) {
|
const item = element.children[j];
|
if (item.prop == resizeColumn.field) {
|
item.width = resizeWidth;
|
return;
|
}
|
}
|
}
|
}
|
}, 0);
|
}
|
|
onMounted(() => {
|
init();
|
});
|
watch(
|
() => route.query,
|
() => {
|
if (props.isPreview || !state.config?.modelId || getTabKey(route) !== currentTabKey) return;
|
initExternalParams();
|
refreshViewInterfacePageParams();
|
getHeaderBtnsList(state.columnData.btnsList || []);
|
getColumnBtnsList(state.columnData.columnBtnsList || [], state.columnData.customBtnsList || []);
|
unref(getSearchList)?.length ? searchFormSubmit() : handleSearchSubmit({});
|
},
|
);
|
</script>
|
|
<template>
|
<div class="jnpf-content-wrapper">
|
<div class="jnpf-content-wrapper-left" v-if="columnData.type === 2">
|
<BasicLeftTree v-bind="getLeftTreeBindValue" ref="leftTreeRef" @reload="getTreeView()" @reset="handleLeftTreeReset" @select="handleLeftTreeSelect" />
|
</div>
|
<div class="jnpf-content-wrapper-center">
|
<div class="jnpf-content-wrapper-search-box" v-if="getSearchList?.length">
|
<BasicForm
|
@register="registerSearchForm"
|
:schemas="getSearchList"
|
@advanced-change="redoHeight"
|
@submit="handleSearchSubmit"
|
@reset="handleSearchReset"
|
class="search-form" />
|
</div>
|
<div class="jnpf-content-wrapper-content jnpf-content-wrapper-list">
|
<a-tabs
|
v-model:active-key="tabActiveKey"
|
class="jnpf-content-wrapper-tabs"
|
destroy-inactive-tab-pane
|
@change="onTabChange"
|
v-if="[1, 4].includes(columnData.type) && tabList.length">
|
<a-tab-pane v-for="item in tabList" :key="item.id" :tab="item.fullName" />
|
</a-tabs>
|
<BasicVxeTable
|
@register="registerTable"
|
v-bind="getTableBindValue"
|
ref="tableRef"
|
@cell-click="handleRowSelection"
|
@columns-change="handleColumnChange"
|
@column-resizable-change="handleColumnResizableChange">
|
<template #tableTitle>
|
<!-- <a-button
|
v-for="item in state.headerBtnsList"
|
:key="item.value"
|
:type="item.value === 'add' ? 'primary' : 'link'"
|
:pre-icon="item.icon"
|
@click="headBtnsHandle(item)">
|
{{ item.labelI18nCode ? $t(item.labelI18nCode, item.label) : item.label }}
|
</a-button>
|
<a-button
|
v-for="item in state.customHeaderBtnsList"
|
:key="item.value"
|
type="link"
|
:pre-icon="item.event?.btnIcon"
|
@click="headCustomBtnsHandle(item)">
|
{{ item.labelI18nCode ? $t(item.labelI18nCode, item.label) : item.label }}
|
</a-button> -->
|
<a-button
|
v-for="item in getNormalHeaderBtnsList"
|
:key="item.value"
|
:type="item.type || (item.value === 'add' ? 'primary' : 'link')"
|
:pre-icon="item.icon"
|
@click="headBtnsHandle(item)">
|
{{ item.labelI18nCode ? $t(item.labelI18nCode, item.label) : item.label }}
|
</a-button>
|
<a-button
|
v-for="item in state.customHeaderBtnsList"
|
:key="item.value"
|
:type="item.type || 'link'"
|
:pre-icon="item.event?.btnIcon"
|
@click="headCustomBtnsHandle(item)">
|
{{ item.labelI18nCode ? $t(item.labelI18nCode, item.label) : item.label }}
|
</a-button>
|
<a-button
|
v-for="item in getTrailingHeaderBtnsList"
|
:key="item.value"
|
:type="item.type || (item.value === 'add' ? 'primary' : 'link')"
|
:pre-icon="item.icon"
|
@click="headBtnsHandle(item)">
|
{{ item.labelI18nCode ? $t(item.labelI18nCode, item.label) : item.label }}
|
</a-button>
|
</template>
|
<template #toolbar v-if="columnData.hasSuperQuery && config.webType != '4'">
|
<a-tooltip placement="top">
|
<template #title>
|
<span>{{ $t('common.superQuery') }}</span>
|
</template>
|
<FilterOutlined @click="openSuperQuery(true, { columnOptions: getSuperQueryFieldOptions(), showPlan: !isDataManage })" />
|
</a-tooltip>
|
</template>
|
<template #toolbarAfter v-if="!isDataManage && !props.isPreview && !props.isOnlineUtilsOpen">
|
<ViewList :menu-id="searchInfo.menuId" :view-list="viewList" @item-click="handleViewClick" @reload="initViewList" />
|
<ViewSetting :menu-id="searchInfo.menuId" :view-list="viewList" :current-view="currentView" @reload="initViewList" />
|
</template>
|
<template #expandedRowRender="{ record }" v-if="[1, 2].includes(columnData.type) && getChildTableStyle === 2 && childColumnList.length">
|
<a-tabs size="small">
|
<a-tab-pane v-for="(child, cIndex) in childColumnList" :tab="child.label" :label="child.label" :key="cIndex">
|
<VxeGrid size="small" :data="record[child.prop]" :columns="child.children" :show-overflow="!!columnData.showOverflow" :min-height="0">
|
<template #[column.dataIndex]="{ row: childRecord }" v-for="column in child.children" :key="column.dataIndex">
|
<template v-if="column.jnpfKey === 'relationForm'">
|
<p class="link-text" @click="toDetail(column.modelId, childRecord[`${column.dataIndex}_id`], column.propsValue)">
|
{{ childRecord[column.dataIndex] }}
|
</p>
|
</template>
|
<template v-if="column.jnpfKey === 'inputNumber'">
|
<jnpf-input-number
|
v-model:value="childRecord[column.dataIndex]"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
disabled
|
detailed />
|
</template>
|
<template v-if="column.jnpfKey === 'calculate'">
|
<jnpf-calculate
|
v-model:value="childRecord[column.dataIndex]"
|
:is-storage="column.isStorage"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
:round-type="column.roundType"
|
:type="column.type"
|
:date-cal-config="column.dateCalConfig"
|
detailed />
|
</template>
|
<template v-if="column.jnpfKey === 'sign'">
|
<jnpf-sign v-model:value="childRecord[column.dataIndex]" detailed />
|
</template>
|
<template v-if="column.jnpfKey === 'signature'">
|
<jnpf-signature v-model:value="childRecord[column.dataIndex]" detailed />
|
</template>
|
<template v-if="column.jnpfKey === 'rate'">
|
<jnpf-rate v-model:value="childRecord[column.dataIndex]" :count="column.count" :allow-half="column.allowHalf" disabled />
|
</template>
|
<template v-if="column.jnpfKey === 'slider'">
|
<jnpf-slider v-model:value="childRecord[column.dataIndex]" :min="column.min" :max="column.max" :step="column.step" disabled />
|
</template>
|
<template v-if="column.jnpfKey === 'uploadImg'">
|
<jnpf-upload-img v-model:value="childRecord[column.dataIndex]" disabled detailed simple v-if="childRecord[column.dataIndex]?.length" />
|
</template>
|
<template v-if="column.jnpfKey === 'uploadFile'">
|
<jnpf-upload-file v-model:value="childRecord[column.dataIndex]" disabled detailed simple v-if="childRecord[column.dataIndex]?.length" />
|
</template>
|
<template v-if="column.jnpfKey === 'input'">
|
<jnpf-input
|
v-model:value="childRecord[column.dataIndex]"
|
:use-mask="column.useMask"
|
:mask-config="column.maskConfig"
|
:show-overflow="columnData.showOverflow"
|
detailed />
|
</template>
|
</template>
|
</VxeGrid>
|
</a-tab-pane>
|
</a-tabs>
|
</template>
|
<!-- 行内编辑且不带流程序号加插槽 -->
|
<template #editIndex="{ record, index }">
|
<div class="edit-row-action">
|
<span class="edit-row-index">{{ index + 1 }}</span>
|
<i class="ym-custom ym-custom-arrow-expand" @click="handleRowForm(record)"></i>
|
</div>
|
</template>
|
<template #[column.prop]="{ record, index }" v-for="column in allColumns" :key="column.prop">
|
<template v-if="column.useContentFormat && !record.rowEdit">
|
{{ formatColumnContent(column, record, index) }}
|
</template>
|
<template v-else-if="columnData.type === 4">
|
<template v-if="record.rowEdit">
|
<template v-if="column.jnpfKey === 'inputNumber'">
|
<jnpf-input-number
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:min="column.min"
|
:max="column.max"
|
:step="column.step"
|
:controls="column.controls"
|
:addon-before="column.addonBefore"
|
:addon-after="column.addonAfter"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
:disabled="column.disabled"
|
:key="`editInputNumber${column.prop}`" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'calculate'">
|
<jnpf-calculate
|
v-model:value="record[column.prop]"
|
:is-storage="column.isStorage"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
:round-type="column.roundType"
|
:type="column.type"
|
:date-cal-config="column.dateCalConfig"
|
detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'rate'">
|
<jnpf-rate v-model:value="record[column.prop]" :count="column.count" :allow-half="column.allowHalf" :disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'slider'">
|
<jnpf-slider v-model:value="record[column.prop]" :min="column.min" :max="column.max" :step="column.step" :disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'uploadImg'">
|
<jnpf-upload-img
|
v-model:value="record[column.prop]"
|
:file-size="column.fileSize"
|
:size-unit="column.sizeUnit"
|
:button-text="column.buttonText"
|
:limit="column.limit"
|
:path-type="column.pathType"
|
:sort-rule="column.sortRule"
|
:time-format="column.timeFormat"
|
:folder="column.folder"
|
:tip-text="column.tipText"
|
:show-type="column.showType"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'uploadFile'">
|
<jnpf-upload-file
|
v-model:value="record[column.prop]"
|
:accept="column.accept"
|
:file-size="column.fileSize"
|
:size-unit="column.sizeUnit"
|
:button-text="column.buttonText"
|
:limit="column.limit"
|
:path-type="column.pathType"
|
:sort-rule="column.sortRule"
|
:time-format="column.timeFormat"
|
:folder="column.folder"
|
:tip-text="column.tipText"
|
:show-type="column.showType"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'switch'">
|
<jnpf-switch v-model:value="record[column.prop]" :disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'timePicker'">
|
<jnpf-time-picker
|
v-model:value="record[column.prop]"
|
:format="column.format"
|
:start-time="column.startTime"
|
:end-time="column.endTime"
|
:placeholder="column.placeholder"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'datePicker'">
|
<jnpf-date-picker
|
v-model:value="record[column.prop]"
|
:format="column.format"
|
:start-time="column.startTime"
|
:end-time="column.endTime"
|
:allow-clear="column.clearable"
|
:placeholder="column.placeholder"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'organizeSelect'">
|
<jnpf-organize-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:select-type="column.selectType"
|
:able-ids="column.ableIds" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'roleSelect'">
|
<jnpf-role-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:select-type="column.selectType"
|
:able-ids="column.ableIds" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'groupSelect'">
|
<jnpf-group-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:select-type="column.selectType"
|
:able-ids="column.ableIds" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'posSelect'">
|
<jnpf-pos-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:select-type="column.selectType"
|
:able-ids="column.ableIds" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'userSelect'">
|
<jnpf-user-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:select-type="['all', 'custom'].includes(column.selectType) ? column.selectType : 'all'"
|
:able-ids="column.ableIds" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'usersSelect'">
|
<jnpf-users-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'areaSelect'">
|
<jnpf-area-select
|
v-model:value="record[column.prop]"
|
:level="column.level"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="['select', 'radio', 'checkbox'].includes(column.jnpfKey)">
|
<jnpf-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple || column.jnpfKey === 'checkbox'"
|
:allow-clear="column.clearable || ['radio', 'checkbox'].includes(column.jnpfKey)"
|
:show-search="column.filterable"
|
:disabled="column.disabled"
|
:options="column.options"
|
:field-names="column.props" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'cascader'">
|
<jnpf-cascader
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:show-search="column.filterable"
|
:disabled="column.disabled"
|
:options="column.options"
|
:field-names="column.props"
|
:show-all-levels="column.showAllLevels" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'treeSelect'">
|
<jnpf-tree-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:show-search="column.filterable"
|
:disabled="column.disabled"
|
:options="column.options"
|
:field-names="column.props" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'relationForm'">
|
<JnpfRelationForm
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:model-id="column.modelId"
|
:column-options="column.columnOptions"
|
:relation-field="column.relationField"
|
:has-page="column.hasPage"
|
:page-size="column.pageSize"
|
:popup-type="column.popupType"
|
:popup-title="column.popupTitle"
|
:popup-width="column.popupWidth"
|
:props-value="column.propsValue"
|
:query-type="column.queryType" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'popupSelect' || column.jnpfKey === 'popupTableSelect'">
|
<jnpf-popup-select
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:multiple="column.multiple"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:interface-id="column.interfaceId"
|
:template-json="column.templateJson"
|
:column-options="column.columnOptions"
|
:props-value="column.propsValue"
|
:relation-field="column.relationField"
|
:has-page="column.hasPage"
|
:page-size="column.pageSize"
|
:popup-type="column.popupType"
|
:popup-title="column.popupTitle"
|
:popup-width="column.popupWidth" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'autoComplete'">
|
<jnpf-auto-complete
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:interface-id="column.interfaceId"
|
:relation-field="column.relationField"
|
:template-json="column.templateJson"
|
:total="column.total" />
|
</template>
|
<template v-else-if="['input', 'textarea'].includes(column.jnpfKey)">
|
<jnpf-input
|
v-model:value="record[column.prop]"
|
:placeholder="column.placeholder"
|
:allow-clear="column.clearable"
|
:disabled="column.disabled"
|
:readonly="column.readonly"
|
:prefix-icon="column.prefixIcon"
|
:suffix-icon="column.suffixIcon"
|
:addon-before="column.addonBefore"
|
:addon-after="column.addonAfter"
|
:maxlength="column.maxlength"
|
:show-count="column.showCount"
|
:show-password="column.showPassword" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'location'">
|
<jnpf-location
|
v-model:value="record[column.prop]"
|
:auto-location="column.autoLocation"
|
:enable-location-scope="column.enableLocationScope"
|
:adjustment-scope="column.adjustmentScope"
|
:enable-desktop-location="column.enableDesktopLocation"
|
:location-scope="column.locationScope"
|
:clearable="column.clearable"
|
:disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'sign'">
|
<jnpf-sign v-model:value="record[column.prop]" :is-invoke="column.isInvoke" :disabled="column.disabled" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'signature'">
|
<jnpf-signature v-model:value="record[column.prop]" :able-ids="column.ableIds" :disabled="column.disabled" />
|
</template>
|
<template v-else-if="systemComponentsList.includes(column.jnpfKey)">
|
{{ record[`${column.prop}_name`] || record[column.prop] }}
|
</template>
|
<template v-else-if="ocrList.includes(column.jnpfKey)">
|
<jnpf-ocr v-model:value="record[column.prop]" :disabled="column.disabled" />
|
</template>
|
<template v-else>
|
{{ record[column.prop] }}
|
</template>
|
</template>
|
<template v-else>
|
<template v-if="column.jnpfKey === 'inputNumber'">
|
<jnpf-input-number
|
v-model:value="record[`${column.prop}_name`]"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
disabled
|
detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'calculate'">
|
<jnpf-calculate
|
v-model:value="record[`${column.prop}_name`]"
|
:is-storage="column.isStorage"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
:round-type="column.roundType"
|
:type="column.type"
|
:date-cal-config="column.dateCalConfig"
|
detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'sign'">
|
<jnpf-sign v-model:value="record[`${column.prop}_name`]" detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'signature'">
|
<jnpf-signature v-model:value="record[`${column.prop}_name`]" detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'rate'">
|
<jnpf-rate v-model:value="record[`${column.prop}_name`]" :count="column.count" :allow-half="column.allowHalf" disabled />
|
</template>
|
<template v-else-if="column.jnpfKey === 'slider'">
|
<jnpf-slider v-model:value="record[`${column.prop}_name`]" :min="column.min" :max="column.max" :step="column.step" disabled />
|
</template>
|
<template v-else-if="column.jnpfKey === 'uploadImg'">
|
<jnpf-upload-img v-model:value="record[`${column.prop}_name`]" disabled detailed simple v-if="record[column.prop]?.length" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'uploadFile'">
|
<jnpf-upload-file v-model:value="record[`${column.prop}_name`]" disabled detailed simple v-if="record[column.prop]?.length" />
|
</template>
|
<template v-else-if="ocrList.includes(column.jnpfKey)">
|
<jnpf-ocr v-model:value="record[column.prop]" disabled v-if="record[column.prop]" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'input'">
|
<jnpf-input
|
v-model:value="record[`${column.prop}_name`]"
|
:use-mask="column.useMask"
|
:mask-config="column.maskConfig"
|
:show-overflow="columnData.showOverflow"
|
detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'relationForm'">
|
<p class="link-text" @click="toDetail(column.modelId, record[`${column.prop}_id`], column.propsValue)">
|
{{ record[`${column.prop}_name`] || record[column.prop] }}
|
</p>
|
</template>
|
<template v-else>
|
{{ record[`${column.prop}_name`] || record[column.prop] }}
|
</template>
|
</template>
|
</template>
|
<template v-else>
|
<template v-if="!record.top">
|
<template v-if="column.jnpfKey === 'inputNumber'">
|
<jnpf-input-number v-model:value="record[column.prop]" :precision="column.precision" :thousands="column.thousands" disabled detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'calculate'">
|
<jnpf-calculate
|
v-model:value="record[column.prop]"
|
:is-storage="column.isStorage"
|
:precision="column.precision"
|
:thousands="column.thousands"
|
:type="column.type"
|
:date-cal-config="column.dateCalConfig"
|
:round-type="column.roundType"
|
detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'sign'">
|
<jnpf-sign v-model:value="record[column.prop]" detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'signature'">
|
<jnpf-signature v-model:value="record[column.prop]" detailed />
|
</template>
|
<template v-else-if="column.jnpfKey === 'rate'">
|
<jnpf-rate v-model:value="record[column.prop]" :count="column.count" :allow-half="column.allowHalf" disabled />
|
</template>
|
<template v-else-if="column.jnpfKey === 'slider'">
|
<jnpf-slider v-model:value="record[column.prop]" :min="column.min" :max="column.max" :step="column.step" disabled />
|
</template>
|
<template v-else-if="column.jnpfKey === 'uploadImg'">
|
<jnpf-upload-img v-model:value="record[column.prop]" disabled detailed simple v-if="record[column.prop]?.length" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'uploadFile'">
|
<jnpf-upload-file v-model:value="record[column.prop]" disabled detailed simple v-if="record[column.prop]?.length" />
|
</template>
|
<template v-else-if="ocrList.includes(column.jnpfKey)">
|
<jnpf-ocr v-model:value="record[column.prop]" disabled v-if="record[column.prop]" />
|
</template>
|
<template v-else-if="column.jnpfKey === 'input'">
|
<jnpf-input
|
v-model:value="record[column.prop]"
|
:use-mask="column.useMask"
|
:mask-config="column.maskConfig"
|
:show-overflow="columnData.showOverflow"
|
detailed />
|
</template>
|
<template v-else-if="viewEchoSlotList.has(column.jnpfKey)">
|
{{ getViewEchoText(column, record) }}
|
</template>
|
<template v-else-if="column.jnpfKey === 'relationForm'">
|
<p class="link-text" @click="toDetail(column.modelId, record[`${column.prop}_id`], column.propsValue)">
|
{{ record[column.prop] || record[column.prop] }}
|
</p>
|
</template>
|
<template v-else-if="systemComponentsList.includes(column.jnpfKey)">
|
{{ record[`${column.prop}_name`] || record[column.prop] }}
|
</template>
|
<template v-else>
|
{{ record[column.prop] }}
|
</template>
|
</template>
|
<template v-else>{{ record[column.prop] }}</template>
|
</template>
|
</template>
|
<template #[item.dataIndex]="{ record }" v-for="(item, index) in childColumnList" :key="item.dataIndex">
|
<ChildTableColumn
|
:data="record[item.prop]"
|
:head="item.children"
|
:form-data="record"
|
@toggle-expand="toggleExpand(record, `${item.prop}Expand`)"
|
@to-detail="toDetail"
|
:expand="record[`${item.prop}Expand`]"
|
:show-overflow="columnData.showOverflow"
|
:key="index" />
|
</template>
|
<template #flowState="{ record }">
|
<JnpfTextTag
|
:content="getFlowStatusContent(record.flowState)"
|
:color="getFlowStatusColor(record.flowState)"
|
v-if="config.enableFlow == 1 && (!record.top || columnData.type == 5)" />
|
</template>
|
<template #action="{ record, index }">
|
<TableAction
|
:actions="getTableActions(record, index)"
|
:drop-down-actions="getDropDownActions(record, index)"
|
v-if="!record.top || columnData.type == 5" />
|
</template>
|
</BasicVxeTable>
|
</div>
|
</div>
|
<Form ref="formRef" @reload="reload" />
|
<Detail ref="detailRef" />
|
<GlobalListModal ref="listModalRef" :listen-global="false" />
|
<CandidateModal @register="registerCandidate" @confirm="submitCandidate" />
|
<FlowParser @register="registerFlowParser" @reload="reload" />
|
<FlowListPopup @register="registerFlowListPopup" />
|
<ExportModal @register="registerExportModal" @download="handleDownload" />
|
<ImportModal @register="registerImportModal" @reload="reload" />
|
<SuperQueryModal @register="registerSuperQueryModal" @super-query="handleSuperQuery" />
|
<CustomForm ref="customFormRef" @reload="reload" />
|
<PrintSelect @register="registerPrintSelect" @change="handleShowBrowse" />
|
<PrintBrowse @register="registerPrintBrowse" />
|
<ListPrintModal @register="registerListPrintModal" />
|
<FreeModal @register="registerFree" @confirm="submitFree" />
|
</div>
|
</template>
|