<script lang="ts" setup>
|
import { computed, inject, nextTick, reactive, ref, toRefs, unref } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicDrawer, useDrawer } from '@jnpf/ui/drawer';
|
import { BasicModal, useModal } from '@jnpf/ui/modal';
|
import { BasicPopup, usePopup } from '@jnpf/ui/popup';
|
import { createAsyncComponent, getDateTimeUnit } from '@jnpf/utils';
|
|
import { useAccessStore, useUserStore } from '@vben/stores';
|
|
import dayjs from 'dayjs';
|
import { cloneDeep } from 'lodash-es';
|
|
import { createModel, getModelInfo, updateModel } from '#/api/onlineDev/visualDev';
|
import FormExtraPanel from '#/components/FormExtraPanel/index.vue';
|
import { $t } from '#/locales';
|
import { useGeneratorStore } from '#/store';
|
|
interface State {
|
formConf: any;
|
defaultFormConf: any;
|
formData: any;
|
config: any;
|
loading: boolean;
|
prevBtnLoading: boolean;
|
nextBtnLoading: boolean;
|
key: number;
|
dataForm: any;
|
formOperates: any[];
|
title: string;
|
continueText: string;
|
allList: any[];
|
currIndex: number;
|
isContinue: boolean;
|
submitType: number;
|
showContinueBtn: boolean;
|
}
|
|
const emit = defineEmits(['reload']);
|
const getLeftTreeActiveInfo: (() => any) | null = inject('getLeftTreeActiveInfo', null);
|
const userStore = useUserStore();
|
const accessStore = useAccessStore();
|
const { permissionList } = accessStore;
|
const generatorStore = useGeneratorStore();
|
const { createMessage } = useMessage();
|
const [registerPopup, { openPopup, setPopupProps }] = usePopup();
|
const [registerModal, { openModal, setModalProps }] = useModal();
|
const [registerDrawer, { openDrawer, setDrawerProps }] = useDrawer();
|
const parserRef = ref<any>(null);
|
const state = reactive<State>({
|
formConf: {},
|
defaultFormConf: {},
|
formData: {},
|
config: {},
|
loading: true,
|
prevBtnLoading: false,
|
nextBtnLoading: false,
|
key: Date.now(),
|
dataForm: {
|
id: '',
|
data: '',
|
},
|
formOperates: [],
|
title: '',
|
continueText: '',
|
allList: [],
|
currIndex: 0,
|
isContinue: false,
|
submitType: 0,
|
showContinueBtn: true,
|
});
|
const { title, formConf, key, loading, continueText, showContinueBtn, submitType } = toRefs(state);
|
const Parser = createAsyncComponent(() => import('#/components/FormGenerator/src/components/Parser.vue'));
|
|
const getPrevDisabled = computed(() => state.currIndex === 0);
|
const getNextDisabled = computed(() => state.currIndex === state.allList.length - 1);
|
const getShowMoreBtn = computed(() => state.config.id && state.config.showMoreBtn && state.formConf.hasConfirmAndAddBtn);
|
const getOkText = computed(() => {
|
const text = state.formConf.confirmButtonTextI18nCode
|
? $t(state.formConf.confirmButtonTextI18nCode, state.formConf.confirmButtonText)
|
: state.formConf.confirmButtonText;
|
return text || $t('common.okText');
|
});
|
const getCancelText = computed(() => {
|
const text = state.formConf.cancelButtonTextI18nCode
|
? $t(state.formConf.cancelButtonTextI18nCode, state.formConf.cancelButtonText)
|
: state.formConf.cancelButtonText;
|
return text || $t('common.cancelText');
|
});
|
const getFormExtraBind = computed(() => ({ showLog: state.formConf.dataLog, modelId: state.config.modelId, formDataId: state.config.id }));
|
|
defineExpose({ init });
|
|
function fillFormData(form, data, isAdd) {
|
const userInfo = userStore.getUserInfo;
|
const currDate = new Date();
|
const loop = (list, parent?) => {
|
for (const item of list) {
|
if (item.__vModel__) {
|
const val = Object.prototype.hasOwnProperty.call(data, item.__vModel__) ? data[item.__vModel__] : item.__config__.defaultValue;
|
if (!item.__config__.isSubTable) item.__config__.defaultValue = val;
|
if ((isAdd || item.__config__.isSubTable) && item.__config__.defaultCurrent) {
|
if (item.__config__.jnpfKey === 'datePicker') {
|
item.__config__.defaultValue = dayjs(currDate).startOf(getDateTimeUnit(item.format)).valueOf();
|
}
|
if (item.__config__.jnpfKey === 'timePicker') {
|
item.__config__.defaultValue = dayjs(currDate).format(item.format || 'HH:mm:ss');
|
}
|
if (item.__config__.jnpfKey === 'organizeSelect' && userInfo?.organizeIds?.length) {
|
item.__config__.defaultValue = item.multiple ? userInfo.organizeIds : userInfo.organizeId;
|
}
|
if (item.__config__.jnpfKey === 'userSelect' && userInfo?.userId) {
|
item.__config__.defaultValue = item.multiple ? [userInfo.userId] : userInfo.userId;
|
}
|
if (item.__config__.jnpfKey === 'usersSelect' && userInfo?.userId) {
|
item.__config__.defaultValue = [`${userInfo?.userId}--user`];
|
}
|
if (item.__config__.jnpfKey === 'posSelect' && userInfo?.positionIds?.length) {
|
item.__config__.defaultValue = item.multiple ? userInfo.positionIds : userInfo.positionId;
|
}
|
if (item.__config__.jnpfKey === 'sign' && userInfo?.signImg) {
|
item.__config__.defaultValue = userInfo.signImg;
|
}
|
}
|
if (isAdd && !item.__config__.isSubTable && Object.prototype.hasOwnProperty.call(data, item.__vModel__))
|
item.__config__.defaultValue = data[item.__vModel__];
|
if (!state.config.isPreview && !state.config.isDataManage && state.config.useFormPermission) {
|
const id = item.__config__.isSubTable && parent?.__vModel__ ? `${parent.__vModel__}-${item.__vModel__}` : item.__vModel__;
|
let noShow = true;
|
if (state.formOperates && state.formOperates.length) {
|
noShow = !state.formOperates.some((o) => o.enCode === id);
|
}
|
noShow = item.__config__.noShow ? item.__config__.noShow : noShow;
|
item.__config__.noShow = noShow;
|
}
|
}
|
if (item.__config__ && item.__config__.children && Array.isArray(item.__config__.children)) {
|
loop(item.__config__.children, item);
|
}
|
}
|
};
|
loop(form.fields);
|
form.formData = data;
|
}
|
function init(data) {
|
state.loading = true;
|
state.submitType = 0;
|
state.isContinue = false;
|
state.prevBtnLoading = false;
|
state.nextBtnLoading = false;
|
state.title = !data.id || data.id === 'jnpfAdd' ? $t('common.add2Text') : $t('common.editText');
|
state.continueText = data.id ? $t('common.continueText') : $t('common.continueAndAddText');
|
state.config = data;
|
state.defaultFormConf = cloneDeep(data.formConf);
|
state.formConf = cloneDeep(state.defaultFormConf);
|
state.showContinueBtn = !data.formData && state.formConf.hasConfirmAndAddBtn;
|
state.dataForm.id = !data.id || data.id === 'jnpfAdd' ? '' : data.id;
|
getFormOperates();
|
openForm();
|
state.allList = data.allList;
|
state.currIndex = state.allList.length && data.id ? state.allList.findIndex((item) => item.id === data.id) : 0;
|
nextTick(() => {
|
if (!data.formData) return setTimeout(initData, 0);
|
// 行内编辑
|
setTimeout(() => {
|
state.formData = { ...data.formData, id: state.dataForm.id };
|
setFormValue();
|
}, 0);
|
});
|
}
|
function initData() {
|
changeLoading(true);
|
state.loading = true;
|
if (state.config.id) {
|
const extra = { modelId: state.config.modelId, id: state.config.id, type: 2 };
|
generatorStore.setDynamicModelExtra(extra);
|
getInfo(state.config.id);
|
} else {
|
generatorStore.setDynamicModelExtra({});
|
state.formData = {};
|
setFormValue(true);
|
}
|
}
|
function getInfo(id) {
|
getModelInfo(state.config.modelId, id, state.config.menuId).then((res) => {
|
state.dataForm = res.data || {};
|
if (!state.dataForm.data) return;
|
state.formData = { ...JSON.parse(state.dataForm.data), id: state.dataForm.id };
|
setFormValue();
|
});
|
}
|
function setFormValue(isAdd = false) {
|
if (isAdd && getLeftTreeActiveInfo) state.formData = { ...getLeftTreeActiveInfo() };
|
state.formConf = cloneDeep(state.defaultFormConf);
|
fillFormData(state.formConf, state.formData, isAdd);
|
nextTick(() => {
|
state.key = Date.now();
|
state.loading = false;
|
state.prevBtnLoading = false;
|
state.nextBtnLoading = false;
|
changeLoading(false);
|
});
|
}
|
function getFormOperates() {
|
if (state.config.isPreview || state.config.isDataManage || !state.config.useFormPermission) return;
|
const modelId = state.config.menuId;
|
const list = permissionList.find((o) => o.modelId === modelId);
|
state.formOperates = list && list.form ? list.form : [];
|
}
|
function submitForm(data, callback) {
|
if (!data) return;
|
setFormProps({ confirmLoading: true });
|
const formData = { ...state.formData, ...data };
|
state.dataForm.data = JSON.stringify(formData);
|
const formMethod = state.dataForm.id ? updateModel : createModel;
|
formMethod(state.config.modelId, { ...state.dataForm, menuId: state.config.menuId })
|
.then((res) => {
|
createMessage.success(res.msg);
|
if (callback && typeof callback === 'function') callback();
|
setFormProps({ confirmLoading: false });
|
if (state.submitType == 1) {
|
initData();
|
state.isContinue = true;
|
} else {
|
setFormProps({ open: false });
|
emit('reload');
|
}
|
})
|
.catch(() => {
|
setFormProps({ confirmLoading: false });
|
});
|
}
|
function handleReset() {
|
getParser().handleReset();
|
}
|
function handleSubmit() {
|
if (state.config.isPreview) return createMessage.warning('功能预览不支持数据保存');
|
getParser().handleSubmit();
|
}
|
function handlePrev() {
|
state.currIndex--;
|
// state.prevBtnLoading = true;
|
handleGetNewInfo();
|
}
|
function handleNext() {
|
state.currIndex++;
|
// state.nextBtnLoading = true;
|
handleGetNewInfo();
|
}
|
function handleGetNewInfo() {
|
changeLoading(true);
|
state.loading = true;
|
handleReset();
|
state.config.id = state.allList[state.currIndex].id;
|
getInfo(state.config.id);
|
}
|
function getParser() {
|
const parser = unref(parserRef);
|
if (!parser) throw new Error('parser is null!');
|
return parser;
|
}
|
function openForm() {
|
if (state.formConf.popupType === 'fullScreen') return openPopup();
|
if (state.formConf.popupType === 'drawer') return openDrawer();
|
openModal();
|
}
|
function setFormProps(data) {
|
if (state.formConf.popupType === 'fullScreen') return setPopupProps(data);
|
if (state.formConf.popupType === 'drawer') return setDrawerProps(data);
|
setModalProps(data);
|
}
|
function changeLoading(loading) {
|
setFormProps({ loading });
|
}
|
async function onClose() {
|
if (state.isContinue) emit('reload');
|
return true;
|
}
|
</script>
|
<template>
|
<BasicPopup
|
v-bind="$attrs"
|
@register="registerPopup"
|
show-ok-btn
|
:ok-text="getOkText"
|
:cancel-text="getCancelText"
|
destroy-on-close
|
@ok="handleSubmit"
|
:close-func="onClose"
|
class="full-popup">
|
<template #title>
|
<a-space :size="10">
|
<div class="text-[16px] font-medium">{{ title }}</div>
|
<a-space-compact size="small" block v-if="getShowMoreBtn">
|
<a-tooltip :title="$t('common.prevRecord')">
|
<a-button size="small" :loading="state.prevBtnLoading" :disabled="getPrevDisabled" @click="handlePrev">
|
<i class="icon-ym icon-ym-caret-left text-[10px]"></i>
|
</a-button>
|
</a-tooltip>
|
<a-tooltip :title="$t('common.nextRecord')">
|
<a-button size="small" :loading="state.nextBtnLoading" :disabled="getNextDisabled" @click="handleNext">
|
<i class="icon-ym icon-ym-caret-right text-[10px]"></i>
|
</a-button>
|
</a-tooltip>
|
</a-space-compact>
|
</a-space>
|
</template>
|
<template #insertToolbar>
|
<JnpfCheckboxSingle v-model:value="submitType" :label="continueText" v-if="showContinueBtn" />
|
</template>
|
<div class="jnpf-common-form-wrapper">
|
<div class="jnpf-common-form-wrapper__main p-[10px]" :style="{ margin: '0 auto', width: formConf.fullScreenWidth || '100%' }">
|
<Parser ref="parserRef" :form-conf="formConf" @submit="submitForm" :key="key" v-if="!loading" />
|
</div>
|
<FormExtraPanel v-bind="getFormExtraBind" v-if="state.dataForm.id && formConf.dataLog && !loading" :key="key" />
|
</div>
|
</BasicPopup>
|
<BasicModal
|
v-bind="$attrs"
|
@register="registerModal"
|
:width="formConf.generalWidth"
|
:min-height="100"
|
:ok-text="getOkText"
|
:cancel-text="getCancelText"
|
@ok="handleSubmit"
|
:close-func="onClose">
|
<template #title>
|
<a-space :size="10">
|
<div class="text-[16px] font-medium">{{ title }}</div>
|
<a-space-compact size="small" block v-if="getShowMoreBtn">
|
<a-tooltip :title="$t('common.prevRecord')">
|
<a-button size="small" :loading="state.prevBtnLoading" :disabled="getPrevDisabled" @click="handlePrev">
|
<i class="icon-ym icon-ym-caret-left text-[10px]"></i>
|
</a-button>
|
</a-tooltip>
|
<a-tooltip :title="$t('common.nextRecord')">
|
<a-button size="small" :loading="state.nextBtnLoading" :disabled="getNextDisabled" @click="handleNext">
|
<i class="icon-ym icon-ym-caret-right text-[10px]"></i>
|
</a-button>
|
</a-tooltip>
|
</a-space-compact>
|
</a-space>
|
</template>
|
<template #insertFooter>
|
<div class="float-left mt-[5px]" v-if="showContinueBtn">
|
<JnpfCheckboxSingle v-model:value="submitType" :label="continueText" />
|
</div>
|
</template>
|
<Parser ref="parserRef" :form-conf="formConf" @submit="submitForm" :key="key" v-if="!loading" />
|
</BasicModal>
|
<BasicDrawer
|
v-bind="$attrs"
|
@register="registerDrawer"
|
:width="formConf.drawerWidth"
|
show-footer
|
:ok-text="getOkText"
|
:cancel-text="getCancelText"
|
@ok="handleSubmit"
|
:close-func="onClose">
|
<template #title>
|
<div class="flex items-center justify-between">
|
<div class="text-[16px] font-medium">{{ title }}</div>
|
<a-space-compact size="small" v-if="getShowMoreBtn">
|
<a-tooltip :title="$t('common.prevRecord')">
|
<a-button size="small" :loading="state.prevBtnLoading" :disabled="getPrevDisabled" @click="handlePrev">
|
<i class="icon-ym icon-ym-caret-left text-[10px]"></i>
|
</a-button>
|
</a-tooltip>
|
<a-tooltip :title="$t('common.nextRecord')">
|
<a-button size="small" :loading="state.nextBtnLoading" :disabled="getNextDisabled" @click="handleNext">
|
<i class="icon-ym icon-ym-caret-right text-[10px]"></i>
|
</a-button>
|
</a-tooltip>
|
</a-space-compact>
|
</div>
|
</template>
|
<template #insertFooter>
|
<div class="float-left mt-[5px]" v-if="showContinueBtn">
|
<JnpfCheckboxSingle v-model:value="submitType" :label="continueText" />
|
</div>
|
</template>
|
<div class="p-[10px]">
|
<Parser ref="parserRef" :form-conf="formConf" @submit="submitForm" :key="key" v-if="!loading" />
|
</div>
|
</BasicDrawer>
|
</template>
|