UNPKG

@ithinkdt/core

Version:

iThinkDT Core

198 lines (177 loc) 5.39 kB
import { ref, computed, toValue, reactive, unref } from 'vue' import { $msg } from '../feedback' import { useI18n } from '../i18n' import { useForm } from './form' import { useModal } from './use-modal' import { pageInit } from './plugin' export function useFormModal({ save, form, cols = 24, defaultSpan = form?.defaultSpan || 24, model: _model = form?.model, formRef: _formRef = form?.ref, multiStep, items: _items = form?.items || form || [], type = 'dialog', title, actions, onClose, width = type === 'drawer' ? 477 : 488, submitText = '保 存', cancelText = '取 消', ...options }) { const { t } = useI18n() if (form) { console.warn(`[use-modal-form]: 'form' is deprecated`) } form = { multiStep, defaultSpan, model: _model, formRef: _formRef, items: _items, } const { model, items, formRef, reset, step, next, prev, hasNext } = useForm(form) const readonly = ref(false) const submiting = ref(false) let resolve, reject const submit = () => { if (!visible.value || submiting.value) return false submiting.value = true return formRef.value ?.validate() .catch((error) => { $msg.error(t('form.validate.error')) throw error }) .then(async () => { if (hasNext.value) { next() return } const req = await save?.(model) close() if (req && 'id' in req) { Object.assign(model, req) } resolve?.(model) return req }) .catch((error) => { console.debug('form: error on submit', error) }) .finally(() => { submiting.value = false }) } async function _close() { if (!visible.value || submiting.value) return false if (step.value !== 0) { prev() return } if ((await onClose?.()) === false) return false close() reject?.({ __alert_ignore: true, }) } if (!actions) { actions = ({ readonly }) => ['cancel', readonly ? undefined : 'submit'] } const btns = computed(() => { let btns = actions if (typeof btns === 'function') { btns = btns({ model, readonly: readonly.value, submiting: submiting.value, onSubmit: submit, onClose: _close, }) } return btns.map((act) => { if (!act) return if (act === 'submit') { return reactive({ type: 'primary', onClick: submit, loading: submiting, disabled: submiting, text: computed(() => (unref(multiStep) && hasNext.value ? '下一步' : toValue(submitText))), }) } if (act === 'cancel') { return reactive({ onClick: _close, disabled: submiting, text: computed(() => (unref(multiStep) && step.value ? '上一步' : toValue(cancelText))), }) } let click = act.onClick act.onClick = () => click?.({ ...model }) return reactive(act) }) }) const { modal: modalOps, form: formOps } = pageInit.handleFormModalOptions(options) const { show, close, visible } = useModal({ ...modalOps, type: type === 'dialog' ? 'modal' : type, width, onClose: _close, content: () => pageInit.renderFormModal({ ...formOps, type, cols, model, items, formRef, title: toValue(title), submiting: submiting.value, readonly: readonly.value, submitText, cancelText, btns: btns.value.filter((it) => !!it && it.text), onClose: _close, onSubmit: submit, onReset: reset, }), }) return { submiting, model, formRef, close, visible, open(init, readonly0) { if (init instanceof Event) { init = {} readonly0 = false } reset() readonly.value = !!readonly0 show() if (init instanceof Promise) { submiting.value = true Promise.resolve(init) .then((data) => { reset(data ?? {}) if (readonly.value) resolve(model) }) .finally(() => { submiting.value = false }) } else { reset(init ?? {}) } const p = new Promise((_resolve, _reject) => { resolve = _resolve reject = _reject }) return p }, } }