feat(editor): refine history diff defaults

This commit is contained in:
roymondchen 2026-06-26 17:08:39 +08:00
parent fd359e493f
commit f7afed66aa
5 changed files with 67 additions and 6 deletions

View File

@ -1,7 +1,7 @@
<template>
<div v-if="!buckets.length" class="m-editor-history-list-empty">暂无操作记录</div>
<template v-else>
<div class="m-editor-history-list-toolbar">
<div v-if="config.showClear !== false" class="m-editor-history-list-toolbar">
<span class="m-editor-history-list-clear" :title="`清空${config.title}的历史记录`" @click="$emit('clear')"
>清空</span
>
@ -38,7 +38,7 @@ defineOptions({
defineProps<{
/**
* 该类历史的整体渲染配置title / prefix / describe* / isStep* / showInitial / gotoEnabled
* 该类历史的整体渲染配置title / prefix / describe* / isStep* / showInitial / gotoEnabled / showClear
* 由父组件按业务类型注入并整体透传给 Bucket避免逐项透传多个 props
*/
config: HistoryBucketConfig<T>;

View File

@ -21,7 +21,7 @@
</TMagicRadioGroup>
<TMagicRadioGroup v-model="mode" size="small" class="m-editor-history-diff-dialog-mode">
<TMagicRadioButton value="before">与修改前对比</TMagicRadioButton>
<TMagicRadioButton value="before" :disabled="!hasValue">与修改前对比</TMagicRadioButton>
<TMagicRadioButton value="current" :disabled="!hasCurrent">与当前对比</TMagicRadioButton>
</TMagicRadioGroup>
</div>
@ -159,6 +159,15 @@ const dialogTitle = computed(() => (props.onConfirm ? '确认回滚' : '查看
const hasCurrent = computed(() => payload.value?.currentValue !== undefined && payload.value?.currentValue !== null);
/** 是否存在该步「修改后的值」:不存在(如仅删除)时「与修改前对比」无意义,置灰禁用。 */
const hasValue = computed(() => payload.value?.value !== undefined && payload.value?.value !== null);
/**
* 计算 open 时的初始对比模式
* 没有修改后的值但有当前值时与修改前对比不可用默认进入与当前对比否则默认与修改前对比
*/
const resolveInitialMode = (): DiffMode => (!hasValue.value && hasCurrent.value ? 'current' : 'before');
/** 左侧(旧/参照)值 */
const leftValue = computed<Record<string, any>>(() => {
if (!payload.value) return {};
@ -212,8 +221,9 @@ const targetText = computed(() => {
const open = (p: DiffDialogPayload) => {
payload.value = p;
// ""退
mode.value = 'before';
// payload hasValue / hasCurrent payload
//
mode.value = resolveInitialMode();
//
viewMode.value = 'form';
visible.value = true;

View File

@ -1353,6 +1353,8 @@ export interface HistoryBucketConfig<T extends BaseStepValue = BaseStepValue> ex
showInitial?: boolean;
/** 是否支持「跳转到该记录」(goto),默认 true。 */
gotoEnabled?: boolean;
/** 是否展示顶部「清空」按钮,默认 true。无需提供清空能力的自定义历史可传 false。 */
showClear?: boolean;
}
export interface UseHistoryRevertOptions {

View File

@ -16,7 +16,7 @@ const buildConfig = (): HistoryBucketConfig<any> => ({
describeStep: () => 'sub-desc',
});
const buildGroup = () => ({
const buildGroup = (): any => ({
applied: true,
opType: 'update' as const,
steps: [{ index: 0, applied: true, step: { mark: 's-0' } }],
@ -58,6 +58,18 @@ describe('BucketTab.vue', () => {
expect(wrapper.emitted('clear')).toBeTruthy();
});
test('config.showClear 为 false 时不渲染清空按钮', () => {
const wrapper = mount(BucketTab, {
props: {
config: { ...buildConfig(), showClear: false },
buckets: [{ id: 'ds_1', groups: [buildGroup()] }],
expanded: {},
},
});
expect(wrapper.find('.m-editor-history-list-toolbar').exists()).toBe(false);
expect(wrapper.find('.m-editor-history-list-clear').exists()).toBe(false);
});
test('透传 Bucket 子组件事件', async () => {
const wrapper = mount(BucketTab, {
props: {

View File

@ -166,6 +166,43 @@ describe('HistoryDiffDialog.vue', () => {
expect(currentRadio!.attributes('data-disabled')).toBe('true');
});
test('无「修改后的值」时「与修改前对比」按钮置灰', async () => {
const wrapper = factory();
(wrapper.vm as any).open(basePayload({ value: null }));
await nextTick();
const beforeRadio = wrapper.findAll('.fake-radio-btn').find((b) => b.attributes('data-value') === 'before');
expect(beforeRadio!.attributes('data-disabled')).toBe('true');
});
test('无「修改后的值」但有当前值时默认进入「与当前对比」', async () => {
const wrapper = factory();
(wrapper.vm as any).open(basePayload({ value: null }));
await nextTick();
const form = wrapper.findComponent({ name: 'CompareForm' });
// current 模式:左=该步修改后 value此处为空右=当前 currentValue
expect(form.props('value')).toEqual({ text: 'current' });
});
test('无「修改后的值」且无当前值时仍默认「与修改前对比」', async () => {
const wrapper = factory();
(wrapper.vm as any).open(basePayload({ value: null, currentValue: null }));
await nextTick();
const form = wrapper.findComponent({ name: 'CompareForm' });
expect(form.props('lastValue')).toEqual({ text: 'old' });
});
test('有「修改后的值」时「与修改前对比」按钮可用', async () => {
const wrapper = factory();
(wrapper.vm as any).open(basePayload());
await nextTick();
const beforeRadio = wrapper.findAll('.fake-radio-btn').find((b) => b.attributes('data-value') === 'before');
expect(beforeRadio!.attributes('data-disabled')).toBe('false');
});
test('targetText 按 category 生成前缀', async () => {
const wrapper = factory();
(wrapper.vm as any).open(basePayload({ category: 'data-source', targetLabel: '接口A' }));