mirror of
				https://github.com/Tencent/tmagic-editor.git
				synced 2025-11-01 00:57:01 +08:00 
			
		
		
		
	feat(form): 支持表单差异对比
1、支持表单差异对比 2、支持在tab统计差异数量
This commit is contained in:
		
							parent
							
								
									c41af9d01d
								
							
						
					
					
						commit
						6610f30afd
					
				| @ -158,6 +158,9 @@ watch( | |||||||
|     services?.codeBlockService.refreshAllRelations(); |     services?.codeBlockService.refreshAllRelations(); | ||||||
|     refreshCodeList(); |     refreshCodeList(); | ||||||
|   }, |   }, | ||||||
|  |   { | ||||||
|  |     immediate: true, | ||||||
|  |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| watch( | watch( | ||||||
|  | |||||||
| @ -53,8 +53,7 @@ | |||||||
|       padding: 5px; |       padding: 5px; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .is-text, |     .is-text > i { | ||||||
|     i { |  | ||||||
|       color: $--font-color; |       color: $--font-color; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -15,6 +15,8 @@ | |||||||
|         :key="item[keyProp] ?? index" |         :key="item[keyProp] ?? index" | ||||||
|         :config="item" |         :config="item" | ||||||
|         :model="values" |         :model="values" | ||||||
|  |         :last-values="lastValuesProcessed" | ||||||
|  |         :is-compare="isCompare" | ||||||
|         :label-width="item.labelWidth || labelWidth" |         :label-width="item.labelWidth || labelWidth" | ||||||
|         :step-active="stepActive" |         :step-active="stepActive" | ||||||
|         :size="size" |         :size="size" | ||||||
| @ -26,8 +28,8 @@ | |||||||
| 
 | 
 | ||||||
| <script setup lang="ts" name="MForm"> | <script setup lang="ts" name="MForm"> | ||||||
| import { provide, reactive, ref, toRaw, watch, watchEffect } from 'vue'; | import { provide, reactive, ref, toRaw, watch, watchEffect } from 'vue'; | ||||||
|  | import { isEqual } from 'lodash-es'; | ||||||
| import cloneDeep from 'lodash-es/cloneDeep'; | import cloneDeep from 'lodash-es/cloneDeep'; | ||||||
| import isEqual from 'lodash-es/isEqual'; |  | ||||||
| 
 | 
 | ||||||
| import { TMagicForm } from '@tmagic/design'; | import { TMagicForm } from '@tmagic/design'; | ||||||
| 
 | 
 | ||||||
| @ -38,8 +40,14 @@ import type { FormConfig, FormState, FormValue, ValidateError } from './schema'; | |||||||
| 
 | 
 | ||||||
| const props = withDefaults( | const props = withDefaults( | ||||||
|   defineProps<{ |   defineProps<{ | ||||||
|  |     /** 表单配置 */ | ||||||
|     config: FormConfig; |     config: FormConfig; | ||||||
|  |     /** 表单值 */ | ||||||
|     initValues: Object; |     initValues: Object; | ||||||
|  |     /** 需对比的值(开启对比模式时传入) */ | ||||||
|  |     lastValues?: Object; | ||||||
|  |     /** 是否开启对比模式 */ | ||||||
|  |     isCompare?: boolean; | ||||||
|     parentValues?: Object; |     parentValues?: Object; | ||||||
|     labelWidth?: string; |     labelWidth?: string; | ||||||
|     disabled?: boolean; |     disabled?: boolean; | ||||||
| @ -54,6 +62,8 @@ const props = withDefaults( | |||||||
|   { |   { | ||||||
|     config: () => [], |     config: () => [], | ||||||
|     initValues: () => ({}), |     initValues: () => ({}), | ||||||
|  |     lastValues: () => ({}), | ||||||
|  |     isCompare: false, | ||||||
|     parentValues: () => ({}), |     parentValues: () => ({}), | ||||||
|     labelWidth: '200px', |     labelWidth: '200px', | ||||||
|     disabled: false, |     disabled: false, | ||||||
| @ -70,6 +80,7 @@ const emit = defineEmits(['change', 'field-input', 'field-change']); | |||||||
| const tMagicForm = ref<InstanceType<typeof TMagicForm>>(); | const tMagicForm = ref<InstanceType<typeof TMagicForm>>(); | ||||||
| const initialized = ref(false); | const initialized = ref(false); | ||||||
| const values = ref<FormValue>({}); | const values = ref<FormValue>({}); | ||||||
|  | const lastValuesProcessed = ref<FormValue>({}); | ||||||
| const fields = new Map<string, any>(); | const fields = new Map<string, any>(); | ||||||
| 
 | 
 | ||||||
| const requestFuc = getConfig('request') as Function; | const requestFuc = getConfig('request') as Function; | ||||||
| @ -79,8 +90,11 @@ const formState: FormState = reactive<FormState>({ | |||||||
|   popperClass: props.popperClass, |   popperClass: props.popperClass, | ||||||
|   config: props.config, |   config: props.config, | ||||||
|   initValues: props.initValues, |   initValues: props.initValues, | ||||||
|  |   isCompare: props.isCompare, | ||||||
|  |   lastValues: props.lastValues, | ||||||
|   parentValues: props.parentValues, |   parentValues: props.parentValues, | ||||||
|   values, |   values, | ||||||
|  |   lastValuesProcessed, | ||||||
|   $emit: emit as (event: string, ...args: any[]) => void, |   $emit: emit as (event: string, ...args: any[]) => void, | ||||||
|   fields, |   fields, | ||||||
|   setField: (prop: string, field: any) => fields.set(prop, field), |   setField: (prop: string, field: any) => fields.set(prop, field), | ||||||
| @ -98,6 +112,8 @@ const formState: FormState = reactive<FormState>({ | |||||||
| 
 | 
 | ||||||
| watchEffect(() => { | watchEffect(() => { | ||||||
|   formState.initValues = props.initValues; |   formState.initValues = props.initValues; | ||||||
|  |   formState.lastValues = props.lastValues; | ||||||
|  |   formState.isCompare = props.isCompare; | ||||||
|   formState.config = props.config; |   formState.config = props.config; | ||||||
|   formState.keyProp = props.keyProp; |   formState.keyProp = props.keyProp; | ||||||
|   formState.popperClass = props.popperClass; |   formState.popperClass = props.popperClass; | ||||||
| @ -118,8 +134,20 @@ watch( | |||||||
|       config: props.config, |       config: props.config, | ||||||
|     }).then((value) => { |     }).then((value) => { | ||||||
|       values.value = value; |       values.value = value; | ||||||
|       initialized.value = true; |       // 非对比模式,初始化完成 | ||||||
|  |       initialized.value = !props.isCompare; | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|  |     if (props.isCompare) { | ||||||
|  |       // 对比模式下初始化待对比的表单值 | ||||||
|  |       initValue(formState, { | ||||||
|  |         initValues: props.lastValues, | ||||||
|  |         config: props.config, | ||||||
|  |       }).then((value) => { | ||||||
|  |         lastValuesProcessed.value = value; | ||||||
|  |         initialized.value = true; | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|   }, |   }, | ||||||
|   { immediate: true }, |   { immediate: true }, | ||||||
| ); | ); | ||||||
| @ -130,6 +158,7 @@ const changeHandler = () => { | |||||||
| 
 | 
 | ||||||
| defineExpose({ | defineExpose({ | ||||||
|   values, |   values, | ||||||
|  |   lastValuesProcessed, | ||||||
|   formState, |   formState, | ||||||
|   initialized, |   initialized, | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,8 @@ | |||||||
|   <TMagicCol v-show="display && config.type !== 'hidden'" :span="span"> |   <TMagicCol v-show="display && config.type !== 'hidden'" :span="span"> | ||||||
|     <Container |     <Container | ||||||
|       :model="model" |       :model="model" | ||||||
|  |       :lastValues="lastValues" | ||||||
|  |       :is-compare="isCompare" | ||||||
|       :config="config" |       :config="config" | ||||||
|       :prop="prop" |       :prop="prop" | ||||||
|       :label-width="config.labelWidth || labelWidth" |       :label-width="config.labelWidth || labelWidth" | ||||||
| @ -9,6 +11,7 @@ | |||||||
|       :size="size" |       :size="size" | ||||||
|       :disabled="disabled" |       :disabled="disabled" | ||||||
|       @change="changeHandler" |       @change="changeHandler" | ||||||
|  |       @add-diff-count="onAddDiffCount" | ||||||
|     ></Container> |     ></Container> | ||||||
|   </TMagicCol> |   </TMagicCol> | ||||||
| </template> | </template> | ||||||
| @ -25,6 +28,8 @@ import Container from './Container.vue'; | |||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   model: any; |   model: any; | ||||||
|  |   lastValues?: any; | ||||||
|  |   isCompare?: boolean; | ||||||
|   config: ChildConfig; |   config: ChildConfig; | ||||||
|   labelWidth?: string; |   labelWidth?: string; | ||||||
|   expandMore?: boolean; |   expandMore?: boolean; | ||||||
| @ -34,9 +39,10 @@ const props = defineProps<{ | |||||||
|   disabled?: boolean; |   disabled?: boolean; | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| const display = computed(() => displayFunction(mForm, props.config.display, props)); | const display = computed(() => displayFunction(mForm, props.config.display, props)); | ||||||
| const changeHandler = () => emit('change', props.model); | const changeHandler = () => emit('change', props.model); | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -20,6 +20,8 @@ | |||||||
|       :size="size" |       :size="size" | ||||||
|       :is="tagName" |       :is="tagName" | ||||||
|       :model="model" |       :model="model" | ||||||
|  |       :last-values="lastValues" | ||||||
|  |       :is-compare="isCompare" | ||||||
|       :config="config" |       :config="config" | ||||||
|       :disabled="disabled" |       :disabled="disabled" | ||||||
|       :name="name" |       :name="name" | ||||||
| @ -28,15 +30,120 @@ | |||||||
|       :expand-more="expand" |       :expand-more="expand" | ||||||
|       :label-width="itemLabelWidth" |       :label-width="itemLabelWidth" | ||||||
|       @change="onChangeHandler" |       @change="onChangeHandler" | ||||||
|  |       @addDiffCount="onAddDiffCount" | ||||||
|     ></component> |     ></component> | ||||||
| 
 | 
 | ||||||
|     <template v-else-if="type && display"> |     <template v-else-if="type && display && !showDiff"> | ||||||
|       <TMagicFormItem |       <TMagicFormItem | ||||||
|         :style="config.tip ? 'flex: 1' : ''" |         :style="config.tip ? 'flex: 1' : ''" | ||||||
|         :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }" |         :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }" | ||||||
|         :prop="itemProp" |         :prop="itemProp" | ||||||
|         :label-width="itemLabelWidth" |         :label-width="itemLabelWidth" | ||||||
|         :rules="rule" |         :rules="rule" | ||||||
|  |       > | ||||||
|  |         <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template> | ||||||
|  |         <TMagicTooltip v-if="tooltip"> | ||||||
|  |           <component | ||||||
|  |             :key="key(config)" | ||||||
|  |             :size="size" | ||||||
|  |             :is="tagName" | ||||||
|  |             :model="model" | ||||||
|  |             :config="config" | ||||||
|  |             :name="name" | ||||||
|  |             :disabled="disabled" | ||||||
|  |             :prop="itemProp" | ||||||
|  |             @change="onChangeHandler" | ||||||
|  |             @addDiffCount="onAddDiffCount" | ||||||
|  |           ></component> | ||||||
|  |           <template #content> | ||||||
|  |             <div v-html="tooltip"></div> | ||||||
|  |           </template> | ||||||
|  |         </TMagicTooltip> | ||||||
|  | 
 | ||||||
|  |         <component | ||||||
|  |           v-else | ||||||
|  |           :key="key(config)" | ||||||
|  |           :size="size" | ||||||
|  |           :is="tagName" | ||||||
|  |           :model="model" | ||||||
|  |           :config="config" | ||||||
|  |           :name="name" | ||||||
|  |           :disabled="disabled" | ||||||
|  |           :prop="itemProp" | ||||||
|  |           @change="onChangeHandler" | ||||||
|  |           @addDiffCount="onAddDiffCount" | ||||||
|  |         ></component> | ||||||
|  | 
 | ||||||
|  |         <div v-if="extra" v-html="extra" class="m-form-tip"></div> | ||||||
|  |       </TMagicFormItem> | ||||||
|  | 
 | ||||||
|  |       <TMagicTooltip v-if="config.tip" placement="left"> | ||||||
|  |         <TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon> | ||||||
|  |         <template #content> | ||||||
|  |           <div v-html="config.tip"></div> | ||||||
|  |         </template> | ||||||
|  |       </TMagicTooltip> | ||||||
|  |     </template> | ||||||
|  | 
 | ||||||
|  |     <!-- 对比 --> | ||||||
|  |     <template v-else-if="type && display && showDiff"> | ||||||
|  |       <!-- 上次内容 --> | ||||||
|  |       <TMagicFormItem | ||||||
|  |         :style="config.tip ? 'flex: 1' : ''" | ||||||
|  |         :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }" | ||||||
|  |         :prop="itemProp" | ||||||
|  |         :label-width="itemLabelWidth" | ||||||
|  |         :rules="rule" | ||||||
|  |         style="background: #f7dadd" | ||||||
|  |       > | ||||||
|  |         <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template> | ||||||
|  |         <TMagicTooltip v-if="tooltip"> | ||||||
|  |           <component | ||||||
|  |             :key="key(config)" | ||||||
|  |             :size="size" | ||||||
|  |             :is="tagName" | ||||||
|  |             :model="lastValues" | ||||||
|  |             :config="config" | ||||||
|  |             :name="name" | ||||||
|  |             :disabled="disabled" | ||||||
|  |             :prop="itemProp" | ||||||
|  |             @change="onChangeHandler" | ||||||
|  |           ></component> | ||||||
|  |           <template #content> | ||||||
|  |             <div v-html="tooltip"></div> | ||||||
|  |           </template> | ||||||
|  |         </TMagicTooltip> | ||||||
|  | 
 | ||||||
|  |         <component | ||||||
|  |           v-else | ||||||
|  |           :key="key(config)" | ||||||
|  |           :size="size" | ||||||
|  |           :is="tagName" | ||||||
|  |           :model="lastValues" | ||||||
|  |           :config="config" | ||||||
|  |           :name="name" | ||||||
|  |           :disabled="disabled" | ||||||
|  |           :prop="itemProp" | ||||||
|  |           @change="onChangeHandler" | ||||||
|  |         ></component> | ||||||
|  | 
 | ||||||
|  |         <div v-if="extra" v-html="extra" class="m-form-tip"></div> | ||||||
|  |       </TMagicFormItem> | ||||||
|  | 
 | ||||||
|  |       <TMagicTooltip v-if="config.tip" placement="left"> | ||||||
|  |         <TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon> | ||||||
|  |         <template #content> | ||||||
|  |           <div v-html="config.tip"></div> | ||||||
|  |         </template> | ||||||
|  |       </TMagicTooltip> | ||||||
|  |       <!-- 当前内容 --> | ||||||
|  |       <TMagicFormItem | ||||||
|  |         :style="config.tip ? 'flex: 1' : ''" | ||||||
|  |         :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }" | ||||||
|  |         :prop="itemProp" | ||||||
|  |         :label-width="itemLabelWidth" | ||||||
|  |         :rules="rule" | ||||||
|  |         style="background: #def7da" | ||||||
|       > |       > | ||||||
|         <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template> |         <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template> | ||||||
|         <TMagicTooltip v-if="tooltip"> |         <TMagicTooltip v-if="tooltip"> | ||||||
| @ -86,6 +193,8 @@ | |||||||
|           v-for="item in items" |           v-for="item in items" | ||||||
|           :key="key(item)" |           :key="key(item)" | ||||||
|           :model="name || name === 0 ? model[name] : model" |           :model="name || name === 0 ? model[name] : model" | ||||||
|  |           :last-values="name || name === 0 ? lastValues[name] : lastValues" | ||||||
|  |           :is-compare="isCompare" | ||||||
|           :config="item" |           :config="item" | ||||||
|           :size="size" |           :size="size" | ||||||
|           :disabled="disabled" |           :disabled="disabled" | ||||||
| @ -94,6 +203,7 @@ | |||||||
|           :label-width="itemLabelWidth" |           :label-width="itemLabelWidth" | ||||||
|           :prop="itemProp" |           :prop="itemProp" | ||||||
|           @change="onChangeHandler" |           @change="onChangeHandler" | ||||||
|  |           @addDiffCount="onAddDiffCount" | ||||||
|         ></Container> |         ></Container> | ||||||
|       </template> |       </template> | ||||||
|     </template> |     </template> | ||||||
| @ -107,8 +217,9 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup lang="ts" name="MFormContainer"> | <script setup lang="ts" name="MFormContainer"> | ||||||
| import { computed, inject, ref, resolveComponent, watchEffect } from 'vue'; | import { computed, inject, ref, resolveComponent, watch, watchEffect } from 'vue'; | ||||||
| import { WarningFilled } from '@element-plus/icons-vue'; | import { WarningFilled } from '@element-plus/icons-vue'; | ||||||
|  | import { isEqual } from 'lodash-es'; | ||||||
| 
 | 
 | ||||||
| import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design'; | import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design'; | ||||||
| 
 | 
 | ||||||
| @ -117,7 +228,10 @@ import { display as displayFunction, filterFunction, getRules } from '../utils/f | |||||||
| 
 | 
 | ||||||
| const props = withDefaults( | const props = withDefaults( | ||||||
|   defineProps<{ |   defineProps<{ | ||||||
|  |     /** 表单值 */ | ||||||
|     model: FormValue; |     model: FormValue; | ||||||
|  |     /** 需对比的值(开启对比模式时传入) */ | ||||||
|  |     lastValues?: FormValue; | ||||||
|     config: ChildConfig; |     config: ChildConfig; | ||||||
|     prop?: string; |     prop?: string; | ||||||
|     disabled?: boolean; |     disabled?: boolean; | ||||||
| @ -125,15 +239,19 @@ const props = withDefaults( | |||||||
|     expandMore?: boolean; |     expandMore?: boolean; | ||||||
|     stepActive?: string | number; |     stepActive?: string | number; | ||||||
|     size?: string; |     size?: string; | ||||||
|  |     /** 是否开启对比模式 */ | ||||||
|  |     isCompare?: boolean; | ||||||
|   }>(), |   }>(), | ||||||
|   { |   { | ||||||
|     prop: '', |     prop: '', | ||||||
|     size: 'small', |     size: 'small', | ||||||
|     expandMore: false, |     expandMore: false, | ||||||
|  |     lastValues: () => ({}), | ||||||
|  |     isCompare: false, | ||||||
|   }, |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| 
 | 
 | ||||||
| @ -141,6 +259,14 @@ const expand = ref(false); | |||||||
| 
 | 
 | ||||||
| const name = computed(() => props.config.name || ''); | const name = computed(() => props.config.name || ''); | ||||||
| 
 | 
 | ||||||
|  | // 是否展示两个版本的对比内容 | ||||||
|  | const showDiff = computed(() => { | ||||||
|  |   if (!props.isCompare) return false; | ||||||
|  |   const curValue = name.value ? props.model[name.value] : props.model; | ||||||
|  |   const lastValue = name.value ? props.lastValues[name.value] : props.lastValues; | ||||||
|  |   return !isEqual(curValue, lastValue); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| const items = computed(() => (props.config as ContainerCommonConfig).items); | const items = computed(() => (props.config as ContainerCommonConfig).items); | ||||||
| 
 | 
 | ||||||
| const itemProp = computed(() => { | const itemProp = computed(() => { | ||||||
| @ -196,6 +322,21 @@ watchEffect(() => { | |||||||
|   expand.value = props.expandMore; |   expand.value = props.expandMore; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | // 监听是否展示对比内容,如果出现差异项则触发差异数计数事件 | ||||||
|  | watch( | ||||||
|  |   showDiff, | ||||||
|  |   (showDiff) => { | ||||||
|  |     if (type.value === 'hidden') return; | ||||||
|  |     if (items.value && !props.config.text && type.value && display.value) return; | ||||||
|  |     if (display.value && showDiff && type.value) { | ||||||
|  |       emit('addDiffCount'); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     immediate: true, | ||||||
|  |   }, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| const expandHandler = () => (expand.value = !expand.value); | const expandHandler = () => (expand.value = !expand.value); | ||||||
| 
 | 
 | ||||||
| const key = (config: any) => config[mForm?.keyProps]; | const key = (config: any) => config[mForm?.keyProps]; | ||||||
| @ -236,6 +377,9 @@ const trimHandler = (trim: any, value: FormValue | number | string) => { | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // 继续抛出给更高层级的组件 | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
|  | 
 | ||||||
| const onChangeHandler = async function (v: FormValue, key?: string) { | const onChangeHandler = async function (v: FormValue, key?: string) { | ||||||
|   const { filter, onChange, trim, name, dynamicKey } = props.config as any; |   const { filter, onChange, trim, name, dynamicKey } = props.config as any; | ||||||
|   let value: FormValue | number | string = v; |   let value: FormValue | number | string = v; | ||||||
|  | |||||||
| @ -24,6 +24,8 @@ | |||||||
|           v-for="(item, index) in config.items" |           v-for="(item, index) in config.items" | ||||||
|           :key="key(item, index)" |           :key="key(item, index)" | ||||||
|           :model="name ? model[name] : model" |           :model="name ? model[name] : model" | ||||||
|  |           :lastValues="name ? lastValues[name] : lastValues" | ||||||
|  |           :is-compare="isCompare" | ||||||
|           :rules="name ? rules[name] : []" |           :rules="name ? rules[name] : []" | ||||||
|           :config="item" |           :config="item" | ||||||
|           :prop="prop" |           :prop="prop" | ||||||
| @ -31,6 +33,7 @@ | |||||||
|           :labelWidth="lWidth" |           :labelWidth="lWidth" | ||||||
|           :size="size" |           :size="size" | ||||||
|           @change="change" |           @change="change" | ||||||
|  |           @add-diff-count="onAddDiffCount()" | ||||||
|         ></Container> |         ></Container> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
| @ -42,6 +45,8 @@ | |||||||
|         v-for="(item, index) in config.items" |         v-for="(item, index) in config.items" | ||||||
|         :key="key(item, index)" |         :key="key(item, index)" | ||||||
|         :model="name ? model[name] : model" |         :model="name ? model[name] : model" | ||||||
|  |         :lastValues="name ? lastValues[name] : lastValues" | ||||||
|  |         :is-compare="isCompare" | ||||||
|         :rules="name ? rules[name] : []" |         :rules="name ? rules[name] : []" | ||||||
|         :config="item" |         :config="item" | ||||||
|         :prop="prop" |         :prop="prop" | ||||||
| @ -49,6 +54,7 @@ | |||||||
|         :size="size" |         :size="size" | ||||||
|         :disabled="disabled" |         :disabled="disabled" | ||||||
|         @change="change" |         @change="change" | ||||||
|  |         @addDiffCount="onAddDiffCount()" | ||||||
|       ></Container> |       ></Container> | ||||||
|     </template> |     </template> | ||||||
|   </fieldset> |   </fieldset> | ||||||
| @ -69,6 +75,8 @@ const props = withDefaults( | |||||||
|     prop: string; |     prop: string; | ||||||
|     size?: string; |     size?: string; | ||||||
|     model: Record<string, any>; |     model: Record<string, any>; | ||||||
|  |     lastValues?: Record<string, any>; | ||||||
|  |     isCompare?: boolean; | ||||||
|     config: FieldsetConfig; |     config: FieldsetConfig; | ||||||
|     rules?: any; |     rules?: any; | ||||||
|     disabled?: boolean; |     disabled?: boolean; | ||||||
| @ -76,10 +84,12 @@ const props = withDefaults( | |||||||
|   { |   { | ||||||
|     rules: {}, |     rules: {}, | ||||||
|     prop: '', |     prop: '', | ||||||
|  |     lastValues: () => ({}), | ||||||
|  |     isCompare: false, | ||||||
|   }, |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| 
 | 
 | ||||||
| @ -113,4 +123,5 @@ if (props.config.checkbox && name.value) { | |||||||
|     }, |     }, | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -10,6 +10,8 @@ | |||||||
|       v-for="(item, index) in model[name]" |       v-for="(item, index) in model[name]" | ||||||
|       :key="index" |       :key="index" | ||||||
|       :model="item" |       :model="item" | ||||||
|  |       :lastValues="getLastValues(lastValues[name], index)" | ||||||
|  |       :is-compare="isCompare" | ||||||
|       :config="config" |       :config="config" | ||||||
|       :prop="prop" |       :prop="prop" | ||||||
|       :index="index" |       :index="index" | ||||||
| @ -20,6 +22,7 @@ | |||||||
|       @remove-item="removeHandler" |       @remove-item="removeHandler" | ||||||
|       @swap-item="swapHandler" |       @swap-item="swapHandler" | ||||||
|       @change="changeHandler" |       @change="changeHandler" | ||||||
|  |       @addDiffCount="onAddDiffCount()" | ||||||
|     ></MFieldsGroupListItem> |     ></MFieldsGroupListItem> | ||||||
| 
 | 
 | ||||||
|     <TMagicButton @click="addHandler" size="small" :disabled="disabled" v-if="addable">添加组</TMagicButton> |     <TMagicButton @click="addHandler" size="small" :disabled="disabled" v-if="addable">添加组</TMagicButton> | ||||||
| @ -41,6 +44,8 @@ import MFieldsGroupListItem from './GroupListItem.vue'; | |||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   model: any; |   model: any; | ||||||
|  |   lastValues?: any; | ||||||
|  |   isCompare?: boolean; | ||||||
|   config: GroupListConfig; |   config: GroupListConfig; | ||||||
|   name: string; |   name: string; | ||||||
|   labelWidth?: string; |   labelWidth?: string; | ||||||
| @ -49,7 +54,7 @@ const props = defineProps<{ | |||||||
|   disabled?: boolean; |   disabled?: boolean; | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| 
 | 
 | ||||||
| @ -123,4 +128,7 @@ const toggleMode = () => { | |||||||
|       text: null, |       text: null, | ||||||
|     }))) as any; |     }))) as any; | ||||||
| }; | }; | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
|  | 
 | ||||||
|  | const getLastValues = (item: any, index: number) => item?.[index] || {}; | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -32,11 +32,14 @@ | |||||||
|       v-if="expand" |       v-if="expand" | ||||||
|       :config="rowConfig" |       :config="rowConfig" | ||||||
|       :model="model" |       :model="model" | ||||||
|  |       :lastValues="lastValues" | ||||||
|  |       :is-compare="isCompare" | ||||||
|       :labelWidth="labelWidth" |       :labelWidth="labelWidth" | ||||||
|       :prop="`${prop}${prop ? '.' : ''}${String(index)}`" |       :prop="`${prop}${prop ? '.' : ''}${String(index)}`" | ||||||
|       :size="size" |       :size="size" | ||||||
|       :disabled="disabled" |       :disabled="disabled" | ||||||
|       @change="changeHandler" |       @change="changeHandler" | ||||||
|  |       @addDiffCount="onAddDiffCount()" | ||||||
|     ></Container> |     ></Container> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
| @ -54,6 +57,8 @@ import Container from './Container.vue'; | |||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   model: any; |   model: any; | ||||||
|  |   lastValues: any; | ||||||
|  |   isCompare?: boolean; | ||||||
|   groupModel: any[]; |   groupModel: any[]; | ||||||
|   config: GroupListConfig; |   config: GroupListConfig; | ||||||
|   labelWidth?: string; |   labelWidth?: string; | ||||||
| @ -63,7 +68,7 @@ const props = defineProps<{ | |||||||
|   disabled?: boolean; |   disabled?: boolean; | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['swap-item', 'remove-item', 'change']); | const emit = defineEmits(['swap-item', 'remove-item', 'change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| const expand = ref(false); | const expand = ref(false); | ||||||
| @ -122,4 +127,5 @@ const movable = () => { | |||||||
|   } |   } | ||||||
|   return movable; |   return movable; | ||||||
| }; | }; | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -23,11 +23,14 @@ | |||||||
|             :key="item[mForm?.keyProp || '__key'] ?? index" |             :key="item[mForm?.keyProp || '__key'] ?? index" | ||||||
|             :config="item" |             :config="item" | ||||||
|             :model="name ? model[name] : model" |             :model="name ? model[name] : model" | ||||||
|  |             :lastValues="name ? lastValues[name] : lastValues" | ||||||
|  |             :is-compare="isCompare" | ||||||
|             :prop="prop" |             :prop="prop" | ||||||
|             :size="size" |             :size="size" | ||||||
|             :disabled="disabled" |             :disabled="disabled" | ||||||
|             :label-width="config.labelWidth || labelWidth" |             :label-width="config.labelWidth || labelWidth" | ||||||
|             @change="changeHandler" |             @change="changeHandler" | ||||||
|  |             @addDiffCount="onAddDiffCount()" | ||||||
|           ></Container> |           ></Container> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
| @ -40,11 +43,14 @@ | |||||||
|           :key="item[mForm?.keyProp || '__key'] ?? index" |           :key="item[mForm?.keyProp || '__key'] ?? index" | ||||||
|           :config="item" |           :config="item" | ||||||
|           :model="name ? model[name] : model" |           :model="name ? model[name] : model" | ||||||
|  |           :lastValues="name ? lastValues[name] : lastValues" | ||||||
|  |           :is-compare="isCompare" | ||||||
|           :prop="prop" |           :prop="prop" | ||||||
|           :size="size" |           :size="size" | ||||||
|           :disabled="disabled" |           :disabled="disabled" | ||||||
|           :label-width="config.labelWidth || labelWidth" |           :label-width="config.labelWidth || labelWidth" | ||||||
|           @change="changeHandler" |           @change="changeHandler" | ||||||
|  |           @addDiffCount="onAddDiffCount()" | ||||||
|         ></Container> |         ></Container> | ||||||
|       </template> |       </template> | ||||||
|     </div> |     </div> | ||||||
| @ -64,6 +70,8 @@ import Container from './Container.vue'; | |||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   model: any; |   model: any; | ||||||
|  |   lastValues?: any; | ||||||
|  |   isCompare?: boolean; | ||||||
|   config: PanelConfig; |   config: PanelConfig; | ||||||
|   name: string; |   name: string; | ||||||
|   labelWidth?: string; |   labelWidth?: string; | ||||||
| @ -72,7 +80,7 @@ const props = defineProps<{ | |||||||
|   disabled?: boolean; |   disabled?: boolean; | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| 
 | 
 | ||||||
| @ -83,4 +91,5 @@ const items = computed(() => props.config.items); | |||||||
| const filter = (config: any) => filterFunction(mForm, config, props); | const filter = (config: any) => filterFunction(mForm, config, props); | ||||||
| 
 | 
 | ||||||
| const changeHandler = () => emit('change', props.model); | const changeHandler = () => emit('change', props.model); | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -8,10 +8,13 @@ | |||||||
|       :labelWidth="config.labelWidth || labelWidth" |       :labelWidth="config.labelWidth || labelWidth" | ||||||
|       :expandMore="expandMore" |       :expandMore="expandMore" | ||||||
|       :model="name ? model[name] : model" |       :model="name ? model[name] : model" | ||||||
|  |       :lastValues="name ? lastValues[name] : lastValues" | ||||||
|  |       :is-compare="isCompare" | ||||||
|       :prop="prop" |       :prop="prop" | ||||||
|       :size="size" |       :size="size" | ||||||
|       :disabled="disabled" |       :disabled="disabled" | ||||||
|       @change="changeHandler" |       @change="changeHandler" | ||||||
|  |       @add-diff-count="onAddDiffCount" | ||||||
|     /> |     /> | ||||||
|   </TMagicRow> |   </TMagicRow> | ||||||
| </template> | </template> | ||||||
| @ -27,6 +30,8 @@ import Col from './Col.vue'; | |||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = defineProps<{ | ||||||
|   model: any; |   model: any; | ||||||
|  |   lastValues?: any; | ||||||
|  |   isCompare?: boolean; | ||||||
|   config: RowConfig; |   config: RowConfig; | ||||||
|   name: string; |   name: string; | ||||||
|   labelWidth?: string; |   labelWidth?: string; | ||||||
| @ -36,9 +41,10 @@ const props = defineProps<{ | |||||||
|   disabled?: boolean; |   disabled?: boolean; | ||||||
| }>(); | }>(); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| 
 | 
 | ||||||
| const changeHandler = () => emit('change', props.name ? props.model[props.name] : props.model); | const changeHandler = () => emit('change', props.name ? props.model[props.name] : props.model); | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -18,11 +18,14 @@ | |||||||
|           :key="item[mForm?.keyProp || '__key']" |           :key="item[mForm?.keyProp || '__key']" | ||||||
|           :config="item" |           :config="item" | ||||||
|           :model="step.name ? model[step.name] : model" |           :model="step.name ? model[step.name] : model" | ||||||
|  |           :lastValues="step.name ? lastValues[step.name] : lastValues" | ||||||
|  |           :is-compare="isCompare" | ||||||
|           :prop="`${step.name}`" |           :prop="`${step.name}`" | ||||||
|           :size="size" |           :size="size" | ||||||
|           :disabled="disabled" |           :disabled="disabled" | ||||||
|           :label-width="config.labelWidth || labelWidth" |           :label-width="config.labelWidth || labelWidth" | ||||||
|           @change="changeHandler" |           @change="changeHandler" | ||||||
|  |           @addDiffCount="onAddDiffCount()" | ||||||
|         ></Container> |         ></Container> | ||||||
|       </template> |       </template> | ||||||
|     </template> |     </template> | ||||||
| @ -41,6 +44,8 @@ import Container from './Container.vue'; | |||||||
| const props = withDefaults( | const props = withDefaults( | ||||||
|   defineProps<{ |   defineProps<{ | ||||||
|     model: any; |     model: any; | ||||||
|  |     lastValues?: any; | ||||||
|  |     isCompare?: boolean; | ||||||
|     config: StepConfig; |     config: StepConfig; | ||||||
|     stepActive?: number; |     stepActive?: number; | ||||||
|     labelWidth?: string; |     labelWidth?: string; | ||||||
| @ -52,7 +57,7 @@ const props = withDefaults( | |||||||
|   }, |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| const active = ref(1); | const active = ref(1); | ||||||
| @ -69,4 +74,5 @@ const stepClick = (index: number) => { | |||||||
| const changeHandler = () => { | const changeHandler = () => { | ||||||
|   emit('change', props.model); |   emit('change', props.model); | ||||||
| }; | }; | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
|           style="width: 100%" |           style="width: 100%" | ||||||
|           :row-key="config.rowKey || 'id'" |           :row-key="config.rowKey || 'id'" | ||||||
|           :data="data" |           :data="data" | ||||||
|  |           :lastData="lastData" | ||||||
|           :border="config.border" |           :border="config.border" | ||||||
|           :max-height="config.maxHeight" |           :max-height="config.maxHeight" | ||||||
|           :default-expand-all="true" |           :default-expand-all="true" | ||||||
| @ -108,8 +109,11 @@ | |||||||
|                   :rules="column.rules" |                   :rules="column.rules" | ||||||
|                   :config="makeConfig(column, scope.row)" |                   :config="makeConfig(column, scope.row)" | ||||||
|                   :model="scope.row" |                   :model="scope.row" | ||||||
|  |                   :lastValues="lastData[scope.$index]" | ||||||
|  |                   :is-compare="isCompare" | ||||||
|                   :size="size" |                   :size="size" | ||||||
|                   @change="$emit('change', model[modelName])" |                   @change="$emit('change', model[modelName])" | ||||||
|  |                   @addDiffCount="onAddDiffCount()" | ||||||
|                 ></Container> |                 ></Container> | ||||||
|               </template> |               </template> | ||||||
|             </TMagicTableColumn> |             </TMagicTableColumn> | ||||||
| @ -196,6 +200,8 @@ import Container from './Container.vue'; | |||||||
| const props = withDefaults( | const props = withDefaults( | ||||||
|   defineProps<{ |   defineProps<{ | ||||||
|     model: any; |     model: any; | ||||||
|  |     lastValues?: any; | ||||||
|  |     isCompare?: boolean; | ||||||
|     config: TableConfig; |     config: TableConfig; | ||||||
|     name: string; |     name: string; | ||||||
|     prop?: string; |     prop?: string; | ||||||
| @ -213,10 +219,12 @@ const props = withDefaults( | |||||||
|     sortKey: '', |     sortKey: '', | ||||||
|     enableToggleMode: true, |     enableToggleMode: true, | ||||||
|     showIndex: true, |     showIndex: true, | ||||||
|  |     lastValues: () => ({}), | ||||||
|  |     isCompare: false, | ||||||
|   }, |   }, | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change', 'select']); | const emit = defineEmits(['change', 'select', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| let timer: any | null = null; | let timer: any | null = null; | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| @ -241,6 +249,15 @@ const data = computed(() => | |||||||
|     : props.model[modelName.value], |     : props.model[modelName.value], | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|  | const lastData = computed(() => | ||||||
|  |   props.config.pagination | ||||||
|  |     ? props.lastValues[modelName.value].filter( | ||||||
|  |         (item: any, index: number) => | ||||||
|  |           index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value, | ||||||
|  |       ) | ||||||
|  |     : props.lastValues[modelName.value] || {}, | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| const sortChange = ({ prop, order }: SortProp) => { | const sortChange = ({ prop, order }: SortProp) => { | ||||||
|   if (order === 'ascending') { |   if (order === 'ascending') { | ||||||
|     props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => a[prop] - b[prop]); |     props.model[modelName.value] = props.model[modelName.value].sort((a: any, b: any) => a[prop] - b[prop]); | ||||||
| @ -593,6 +610,8 @@ const getProp = (index: number) => { | |||||||
|   return `${prop.value}${prop.value ? '.' : ''}${index + 1 + pagecontext.value * pagesize.value - 1}`; |   return `${prop.value}${prop.value ? '.' : ''}${index + 1 + pagecontext.value * pagesize.value - 1}`; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | const onAddDiffCount = () => emit('addDiffCount'); | ||||||
|  | 
 | ||||||
| defineExpose({ | defineExpose({ | ||||||
|   toggleRowSelection, |   toggleRowSelection, | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -18,25 +18,26 @@ | |||||||
|         :label="filter(tab.title)" |         :label="filter(tab.title)" | ||||||
|         :lazy="tab.lazy || false" |         :lazy="tab.lazy || false" | ||||||
|       > |       > | ||||||
|  |         <template #label> | ||||||
|  |           <span class="custom-tabs-label"> | ||||||
|  |             {{ filter(tab.title) | ||||||
|  |             }}<el-badge :hidden="!diffCount[tabIndex]" :value="diffCount[tabIndex]" class="diff-count-badge"></el-badge> | ||||||
|  |           </span> | ||||||
|  |         </template> | ||||||
|         <Container |         <Container | ||||||
|           v-for="item in tabItems(tab)" |           v-for="item in tabItems(tab)" | ||||||
|           :key="item[mForm?.keyProp || '__key']" |           :key="item[mForm?.keyProp || '__key']" | ||||||
|           :config="item" |           :config="item" | ||||||
|           :disabled="disabled" |           :disabled="disabled" | ||||||
|           :model=" |           :model="getValues(model, tabIndex, tab)" | ||||||
|             config.dynamic |           :last-values="getValues(lastValues, tabIndex, tab)" | ||||||
|               ? (name ? model[name] : model)[tabIndex] |           :is-compare="isCompare" | ||||||
|               : tab.name |  | ||||||
|               ? (name ? model[name] : model)[tab.name] |  | ||||||
|               : name |  | ||||||
|               ? model[name] |  | ||||||
|               : model |  | ||||||
|           " |  | ||||||
|           :prop="config.dynamic ? `${prop}${prop ? '.' : ''}${String(tabIndex)}` : prop" |           :prop="config.dynamic ? `${prop}${prop ? '.' : ''}${String(tabIndex)}` : prop" | ||||||
|           :size="size" |           :size="size" | ||||||
|           :label-width="tab.labelWidth || labelWidth" |           :label-width="tab.labelWidth || labelWidth" | ||||||
|           :expand-more="expandMore" |           :expand-more="expandMore" | ||||||
|           @change="changeHandler" |           @change="changeHandler" | ||||||
|  |           @addDiffCount="onAddDiffCount(tabIndex)" | ||||||
|         ></Container> |         ></Container> | ||||||
|       </component> |       </component> | ||||||
|     </template> |     </template> | ||||||
| @ -54,6 +55,10 @@ import { display as displayFunc, filterFunction } from '../utils/form'; | |||||||
| 
 | 
 | ||||||
| import Container from './Container.vue'; | import Container from './Container.vue'; | ||||||
| 
 | 
 | ||||||
|  | type DiffCount = { | ||||||
|  |   [tabIndex: number]: number; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| const uiComponent = getConfig('components').tabPane; | const uiComponent = getConfig('components').tabPane; | ||||||
| 
 | 
 | ||||||
| const getActive = (mForm: FormState | undefined, props: any, activeTabName: string) => { | const getActive = (mForm: FormState | undefined, props: any, activeTabName: string) => { | ||||||
| @ -83,21 +88,30 @@ const tabClick = (mForm: FormState | undefined, tab: any, props: any) => { | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const props = defineProps<{ | const props = withDefaults( | ||||||
|   model: any; |   defineProps<{ | ||||||
|   config: TabConfig; |     model: any; | ||||||
|   name: string; |     lastValues?: any; | ||||||
|   size?: string; |     isCompare?: boolean; | ||||||
|   labelWidth?: string; |     config: TabConfig; | ||||||
|   prop?: string; |     name: string; | ||||||
|   expandMore?: boolean; |     size?: string; | ||||||
|   disabled?: boolean; |     labelWidth?: string; | ||||||
| }>(); |     prop?: string; | ||||||
|  |     expandMore?: boolean; | ||||||
|  |     disabled?: boolean; | ||||||
|  |   }>(), | ||||||
|  |   { | ||||||
|  |     lastValues: () => ({}), | ||||||
|  |     isCompare: false, | ||||||
|  |   }, | ||||||
|  | ); | ||||||
| 
 | 
 | ||||||
| const emit = defineEmits(['change']); | const emit = defineEmits(['change', 'addDiffCount']); | ||||||
| 
 | 
 | ||||||
| const mForm = inject<FormState | undefined>('mForm'); | const mForm = inject<FormState | undefined>('mForm'); | ||||||
| const activeTabName = ref(getActive(mForm, props, '')); | const activeTabName = ref(getActive(mForm, props, '')); | ||||||
|  | const diffCount = ref<DiffCount>({}); | ||||||
| 
 | 
 | ||||||
| const tabs = computed(() => { | const tabs = computed(() => { | ||||||
|   if (props.config.dynamic) { |   if (props.config.dynamic) { | ||||||
| @ -170,4 +184,27 @@ const changeHandler = () => { | |||||||
|     props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config }); |     props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config }); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | const getValues = (model: any, tabIndex: number, tab: any) => { | ||||||
|  |   const tabName = props.config.dynamic ? (model[props?.name] || model)[tabIndex] : tab.name; | ||||||
|  |   let propName = props.name; | ||||||
|  |   if (tabName) { | ||||||
|  |     propName = (model[props?.name] || model)[tab.name]; | ||||||
|  |   } | ||||||
|  |   if (propName) { | ||||||
|  |     return model[props.name]; | ||||||
|  |   } | ||||||
|  |   return model; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 在tabs组件中收集事件触发次数,即该tab下的差异数 | ||||||
|  | const onAddDiffCount = (tabIndex: number) => { | ||||||
|  |   if (!diffCount.value[tabIndex]) { | ||||||
|  |     diffCount.value[tabIndex] = 1; | ||||||
|  |   } else { | ||||||
|  |     diffCount.value[tabIndex] += 1; | ||||||
|  |   } | ||||||
|  |   // 继续抛出给更高层级的组件 | ||||||
|  |   emit('addDiffCount'); | ||||||
|  | }; | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -28,6 +28,8 @@ export type FormState = { | |||||||
|   config: FormConfig; |   config: FormConfig; | ||||||
|   popperClass?: string; |   popperClass?: string; | ||||||
|   initValues: FormValue; |   initValues: FormValue; | ||||||
|  |   lastValues: FormValue; | ||||||
|  |   isCompare: boolean; | ||||||
|   values: FormValue; |   values: FormValue; | ||||||
|   $emit: (event: string, ...args: any[]) => void; |   $emit: (event: string, ...args: any[]) => void; | ||||||
|   keyProp?: string; |   keyProp?: string; | ||||||
|  | |||||||
| @ -7,3 +7,4 @@ | |||||||
| @use "./panel.scss"; | @use "./panel.scss"; | ||||||
| @use "./table.scss"; | @use "./table.scss"; | ||||||
| @use "./select.scss"; | @use "./select.scss"; | ||||||
|  | @use "./tabs.scss"; | ||||||
|  | |||||||
| @ -23,3 +23,7 @@ | |||||||
| .magic-form-tab { | .magic-form-tab { | ||||||
|   margin-bottom: 10px; |   margin-bottom: 10px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .diff-count-badge { | ||||||
|  |   top: -10px; | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,9 +1,21 @@ | |||||||
| <template> | <template> | ||||||
|   <div style="width: 100%"> |   <div style="width: 100%; overflow-y: auto"> | ||||||
|     <nav-menu :data="menu"></nav-menu> |     <nav-menu :data="menu"></nav-menu> | ||||||
|  |     <div class="diff-form"> | ||||||
|  |       <div>开启表单对比功能</div> | ||||||
|  |       <m-form | ||||||
|  |         ref="form" | ||||||
|  |         :config="diffFormConfig" | ||||||
|  |         :is-compare="true" | ||||||
|  |         :init-values="currentVersion" | ||||||
|  |         :last-values="lastVersion" | ||||||
|  |         size="small" | ||||||
|  |         height="100%" | ||||||
|  |       ></m-form> | ||||||
|  |     </div> | ||||||
|  |     <div class="title">表单字段展示</div> | ||||||
|     <div class="form-content"> |     <div class="form-content"> | ||||||
|       <m-form ref="form" :config="config" :init-values="initValue" size="small" height="100%"></m-form> |       <m-form ref="form" :config="config" :init-values="initValue" size="small" height="100%"></m-form> | ||||||
| 
 |  | ||||||
|       <magic-code-editor class="code-editor-content" :init-values="config" @save="change"></magic-code-editor> |       <magic-code-editor class="code-editor-content" :init-values="config" @save="change"></magic-code-editor> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| @ -30,6 +42,58 @@ const resultVisible = ref(false); | |||||||
| const result = ref(''); | const result = ref(''); | ||||||
| const form = ref<InstanceType<typeof MForm>>(); | const form = ref<InstanceType<typeof MForm>>(); | ||||||
| 
 | 
 | ||||||
|  | const diffFormConfig = ref([ | ||||||
|  |   { | ||||||
|  |     type: 'tab', | ||||||
|  |     items: [ | ||||||
|  |       { | ||||||
|  |         title: 'tab1', | ||||||
|  |         labelWidth: '80px', | ||||||
|  |         items: [ | ||||||
|  |           { | ||||||
|  |             name: 'text1', | ||||||
|  |             text: '文本字段1', | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             name: 'text2', | ||||||
|  |             text: '文本字段2', | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             type: 'number', | ||||||
|  |             text: '计数器', | ||||||
|  |             name: 'number', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         title: 'tab2', | ||||||
|  |         labelWidth: '80px', | ||||||
|  |         items: [ | ||||||
|  |           { | ||||||
|  |             type: 'colorPicker', | ||||||
|  |             text: '取色器', | ||||||
|  |             name: 'colorPicker', | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |   }, | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
|  | const currentVersion = ref({ | ||||||
|  |   text1: '当前版本的文本内容', | ||||||
|  |   text2: '你好', | ||||||
|  |   number: 10, | ||||||
|  |   colorPicker: '#ffffff', | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const lastVersion = ref({ | ||||||
|  |   text1: '上一版本的文本内容', | ||||||
|  |   text2: '你好', | ||||||
|  |   number: 12, | ||||||
|  |   colorPicker: '#000000', | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| const config = ref([ | const config = ref([ | ||||||
|   { |   { | ||||||
|     text: '文本', |     text: '文本', | ||||||
| @ -358,9 +422,16 @@ function change(value: string) { | |||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
|  | .diff-form { | ||||||
|  |   width: 500px; | ||||||
|  |   margin: 20px 0 0 50px; | ||||||
|  | } | ||||||
|  | .title { | ||||||
|  |   margin: 20px 0 0 50px; | ||||||
|  | } | ||||||
| .form-content { | .form-content { | ||||||
|   display: flex; |   display: flex; | ||||||
|   height: calc(100% - 75px); |   height: 800px; | ||||||
| 
 | 
 | ||||||
|   .code-editor-content, |   .code-editor-content, | ||||||
|   .m-form { |   .m-form { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user