| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- <template>
- <Form
- ref="formEditor"
- :name="name"
- v-bind="finalOptions.formAdditionaProps"
- :model="model || {}"
- :rules="finalOptions.formRules"
- :disabled="finalOptions.disabled"
- :readonly="finalOptions.readonly"
- @submit="(e) => emit('submit', e)"
- @submitFailed="() => emit('finishFailed')"
- >
- <DynamicFormRoot
- :options="finalOptions"
- :model="model"
- :name="name"
- />
- </Form>
- </template>
- <script setup lang="ts">
- import { computed, onMounted, provide, ref, toRef, toRefs, type PropType } from 'vue';
- import Form, { type FormInstance } from '../form/Form.vue';
- import {
- type IDynamicFormOptions, type IDynamicFormItem, type IDynamicFormRef,
- type IDynamicFormObject, defaultDynamicFormOptions,
- type IDynamicFormMessageCenter,
- type IDynamicFormMessageCenterCallback,
- MESSAGE_RELOAD
- } from '.';
- import DynamicFormRoot from './nest/DynamicFormRoot.vue';
- const props = defineProps({
- /**
- * 动态表单选项
- */
- options: {
- type: Object as PropType<IDynamicFormOptions>,
- default: null
- },
- /**
- * 表单数据模型
- */
- model: {
- type: Object,
- default: null
- },
- /**
- * 表单名称, 设置到表单组件上。
- */
- name: {
- type: String,
- default: ''
- },
- /**
- * 全局参数。用于向每个表单项的参数中添加额外的参数,可以在回调中的 formGlobalParams 中访问。
- */
- globalParams: {
- type: Object as PropType<IDynamicFormObject>,
- default: null
- },
- });
- const emit = defineEmits(['ready', 'submit', 'finish', 'finishFailed']);
- const { options, model, name } = toRefs(props);
- const finalOptions = computed<IDynamicFormOptions>(() => ({
- ...defaultDynamicFormOptions,
- ...options.value,
- }));
- provide('rawModel', model);
- provide('globalParams', toRef(props, 'globalParams'));
- provide('finalOptions', finalOptions);
- const formEditor = ref<FormInstance>();
- const widgetsRefMap = ref(new Map<string,() => unknown>());
- const messageCenterMap = new Map<string, IDynamicFormMessageCenterCallback>();
-
- provide('widgetsRefMap', widgetsRefMap);
- provide('messageCenter', {
- addInstance: (name: string, fn: IDynamicFormMessageCenterCallback) => messageCenterMap.set(name, fn),
- removeInstance: (name: string) => messageCenterMap.delete(name),
- } as IDynamicFormMessageCenter);
- //获取组件引用
- function getFormItemControlRef(key: string) {
- return widgetsRefMap.value.get(key)?.();
- }
- //通过路径访问
- function accessFormModel(keyName: string, isSet: boolean, setValue: unknown) : unknown {
- const keys = keyName.split('.');
- let ret : unknown = undefined;
- let obj = model.value as Record<string, unknown>;
- let keyIndex = 0;
- let key = keys[keyIndex];
- while (obj) {
- const leftIndex = key.indexOf('[');
- if (leftIndex > 0 && key.endsWith(']')) {
- const arr = obj[key.substring(0, leftIndex)] as Record<string, unknown>[];
- const index = parseInt(key.substring(leftIndex + 1, key.length - 1))
- obj = arr[index];
- if (keyIndex >= keys.length - 1) {
- ret = obj;
- if (isSet) arr[index] = setValue as Record<string, unknown>;
- }
- } else {
- const newObj = obj[key] as Record<string, unknown>;
- if (keyIndex >= keys.length - 1) {
- ret = newObj;
- if (isSet)
- obj[key] = setValue as Record<string, unknown>;
- }
- obj = newObj;
- }
- if (keyIndex < keys.length - 1)
- key = keys[++keyIndex];
- else
- break;
- }
- return ret;
- }
- //发送通知消息
- function dispatchMessage(messageName: string, data?: unknown, receiveFilter?: RegExp) {
- for (const iterator of messageCenterMap) {
- if (!receiveFilter || receiveFilter.test(iterator[0]))
- iterator[1](messageName, data);
- }
- }
- //发送重新加载消息
- function dispatchReload() {
- dispatchMessage(MESSAGE_RELOAD);
- }
- //初始化默认值到模型
- function initDefaultValuesToModel() {
- function loopItems(key: string, parentKey: string, type: string, items: IDynamicFormItem[]) {
- let i = 0;
- for (const item of items) {
- let currentKey = key;
- switch (type) {
- case 'flat-simple':
- case 'flat-group':
- currentKey = (parentKey ? parentKey + '.' : '') + item.name;
- break;
- default:
- case 'object':
- case 'object-group':
- currentKey = (key ? key + '.' : '') + item.name;
- break
- case 'array':
- currentKey = (parentKey ? parentKey + '.' : '') + `[${i}]`;
- break;
- case 'array-object':
- currentKey = (parentKey ? parentKey + '.' : '') + `[${i}]` + item.name;
- break;
- }
- if (item.children) {
- loopItems(currentKey, key, item.type || '', item.children);
- }
- //console.log(currentKey);
- if (item.defaultValue !== undefined) {
- const oldValue = accessFormModel(currentKey, false, undefined);
- if (oldValue !== undefined && oldValue !== null)
- continue;
- accessFormModel(currentKey, true, typeof item.defaultValue === 'function' ? item.defaultValue() : item.defaultValue);
- }
- i++;
- }
- }
- loopItems('', '', '', finalOptions.value.formItems);
- }
- //获取当前表单中可见的所有字段名
- function getVisibleFormNames() {
- return Array.from(messageCenterMap.keys());
- }
- onMounted(() => {
- setTimeout(() => {
- emit('ready');
- }, 400);
- });
- const formRef : IDynamicFormRef = {
- initDefaultValuesToModel,
- getVisibleFormNames,
- getFormRef() {
- if (!formEditor.value)
- throw new Error('Form instance is not create.');
- return formEditor.value
- },
- getFormItemControlRef: getFormItemControlRef as any,
- submit() { return this.getFormRef().validate(); },
- validate() { return this.getFormRef().validate(); },
- setValueByPath: (path: string|string[], value: unknown) => {
- if (Array.isArray(path))
- path = path.join('.');
- return accessFormModel(path, true, value);
- },
- getValueByPath: (path: string|string[]) => {
- if (Array.isArray(path))
- path = path.join('.');
- return accessFormModel(path, false, undefined);
- },
- dispatchMessage,
- dispatchReload,
- };
- provide('formRef', formRef);
- provide('formName', name.value || 'unnamed');
- defineExpose(formRef);
- </script>
|