@tmagic/editor 1.8.0-beta.2 → 1.8.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +9 -0
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +32 -28
- package/dist/es/editorProps.js +2 -0
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +2 -5
- package/dist/es/hooks/use-stage.js +2 -1
- package/dist/es/index.js +3 -1
- package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +2 -5
- package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +33 -14
- package/dist/es/layouts/history-list/BucketTab.js +5 -0
- package/dist/es/layouts/history-list/{CodeBlockTab.vue_vue_type_script_setup_true_lang.js → BucketTab.vue_vue_type_script_setup_true_lang.js} +27 -16
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +71 -53
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +78 -28
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +136 -66
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +15 -9
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +12 -6
- package/dist/es/layouts/history-list/composables.js +20 -2
- package/dist/es/services/history.js +5 -2
- package/dist/es/style.css +44 -12
- package/dist/style.css +44 -12
- package/dist/tmagic-editor.umd.cjs +479 -326
- package/package.json +7 -7
- package/src/Editor.vue +8 -0
- package/src/components/CompareForm.vue +32 -19
- package/src/editorProps.ts +7 -0
- package/src/fields/CodeLink.vue +2 -5
- package/src/hooks/use-stage.ts +1 -0
- package/src/index.ts +2 -0
- package/src/layouts/CodeEditor.vue +2 -5
- package/src/layouts/history-list/Bucket.vue +53 -28
- package/src/layouts/history-list/BucketTab.vue +77 -0
- package/src/layouts/history-list/GroupRow.vue +95 -60
- package/src/layouts/history-list/HistoryDiffDialog.vue +51 -32
- package/src/layouts/history-list/HistoryListPanel.vue +161 -52
- package/src/layouts/history-list/InitialRow.vue +17 -6
- package/src/layouts/history-list/PageTab.vue +20 -6
- package/src/layouts/history-list/composables.ts +32 -1
- package/src/services/history.ts +3 -0
- package/src/theme/history-list-panel.scss +52 -13
- package/src/type.ts +90 -0
- package/types/index.d.ts +295 -135
- package/dist/es/layouts/history-list/CodeBlockTab.js +0 -5
- package/dist/es/layouts/history-list/DataSourceTab.js +0 -5
- package/dist/es/layouts/history-list/DataSourceTab.vue_vue_type_script_setup_true_lang.js +0 -62
- package/src/layouts/history-list/CodeBlockTab.vue +0 -61
- package/src/layouts/history-list/DataSourceTab.vue +0 -61
|
@@ -12,15 +12,11 @@
|
|
|
12
12
|
<span class="m-editor-history-list-item-index" :title="headIndexTitle">{{ headIndexLabel }}</span>
|
|
13
13
|
<span class="m-editor-history-list-item-op" :class="`op-${opType}`">{{ opLabel(opType) }}</span>
|
|
14
14
|
<span class="m-editor-history-list-item-desc">{{ desc }}</span>
|
|
15
|
-
|
|
16
|
-
<span
|
|
17
|
-
|
|
18
|
-
class="m-editor-history-list-item-diff"
|
|
19
|
-
title="查看修改差异"
|
|
20
|
-
@click.stop="onDiffClick(subSteps[0].index)"
|
|
21
|
-
>查看差异</span
|
|
22
|
-
>
|
|
15
|
+
|
|
16
|
+
<span v-if="time" class="m-editor-history-list-item-time" :title="timeTitle || time">{{ time }}</span>
|
|
17
|
+
|
|
23
18
|
<span v-if="merged" class="m-editor-history-list-item-merge">合并 {{ stepCount }} 步</span>
|
|
19
|
+
|
|
24
20
|
<span
|
|
25
21
|
v-if="!merged && headRevertable"
|
|
26
22
|
class="m-editor-history-list-item-revert"
|
|
@@ -28,6 +24,20 @@
|
|
|
28
24
|
@click.stop="onRevertClick(subSteps[0].index)"
|
|
29
25
|
>回滚</span
|
|
30
26
|
>
|
|
27
|
+
<span
|
|
28
|
+
v-if="!merged && gotoEnabled && !isCurrent && subSteps.length"
|
|
29
|
+
class="m-editor-history-list-item-goto"
|
|
30
|
+
title="回到该记录"
|
|
31
|
+
@click.stop="onGotoClick(subSteps[0].index)"
|
|
32
|
+
>回到</span
|
|
33
|
+
>
|
|
34
|
+
<span
|
|
35
|
+
v-if="!merged && headDiffable"
|
|
36
|
+
class="m-editor-history-list-item-diff"
|
|
37
|
+
title="查看修改差异"
|
|
38
|
+
@click.stop="onDiffClick(subSteps[0].index)"
|
|
39
|
+
>查看差异</span
|
|
40
|
+
>
|
|
31
41
|
<span v-if="merged" class="m-editor-history-list-group-toggle" :class="{ 'is-expanded': expanded }">▾</span>
|
|
32
42
|
</div>
|
|
33
43
|
|
|
@@ -35,20 +45,12 @@
|
|
|
35
45
|
<li
|
|
36
46
|
v-for="s in subStepsDisplay"
|
|
37
47
|
:key="s.index"
|
|
38
|
-
:class="{ 'is-undone': !s.applied, 'is-current': s.isCurrent
|
|
39
|
-
:title="s
|
|
40
|
-
@click="onSubStepClick(s)"
|
|
48
|
+
:class="{ 'is-undone': !s.applied, 'is-current': s.isCurrent }"
|
|
49
|
+
:title="subStepTitle(s)"
|
|
41
50
|
>
|
|
42
51
|
<span class="m-editor-history-list-item-index">#{{ s.index + 1 }}</span>
|
|
43
52
|
<span class="m-editor-history-list-substep-desc">{{ s.desc }}</span>
|
|
44
|
-
<span v-if="s.
|
|
45
|
-
<span
|
|
46
|
-
v-if="s.diffable"
|
|
47
|
-
class="m-editor-history-list-item-diff"
|
|
48
|
-
title="查看修改差异"
|
|
49
|
-
@click.stop="onDiffClick(s.index)"
|
|
50
|
-
>查看差异</span
|
|
51
|
-
>
|
|
53
|
+
<span v-if="s.time" class="m-editor-history-list-item-time" :title="s.timeTitle || s.time">{{ s.time }}</span>
|
|
52
54
|
<span
|
|
53
55
|
v-if="s.revertable"
|
|
54
56
|
class="m-editor-history-list-item-revert"
|
|
@@ -56,6 +58,20 @@
|
|
|
56
58
|
@click.stop="onRevertClick(s.index)"
|
|
57
59
|
>回滚</span
|
|
58
60
|
>
|
|
61
|
+
<span
|
|
62
|
+
v-if="gotoEnabled && !s.isCurrent"
|
|
63
|
+
class="m-editor-history-list-item-goto"
|
|
64
|
+
title="回到该记录"
|
|
65
|
+
@click.stop="onGotoClick(s.index)"
|
|
66
|
+
>回到</span
|
|
67
|
+
>
|
|
68
|
+
<span
|
|
69
|
+
v-if="s.diffable"
|
|
70
|
+
class="m-editor-history-list-item-diff"
|
|
71
|
+
title="查看修改差异"
|
|
72
|
+
@click.stop="onDiffClick(s.index)"
|
|
73
|
+
>查看差异</span
|
|
74
|
+
>
|
|
59
75
|
</li>
|
|
60
76
|
</ul>
|
|
61
77
|
</li>
|
|
@@ -72,34 +88,54 @@ defineOptions({
|
|
|
72
88
|
name: 'MEditorHistoryListGroupRow',
|
|
73
89
|
});
|
|
74
90
|
|
|
75
|
-
const props =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/** 是否为合并组(即组内 step 数大于 1,由多次连续操作合并而来)。决定是否展示合并标记与可展开的子步列表。 */
|
|
81
|
-
merged: boolean;
|
|
82
|
-
/** 操作类型:`add` / `remove` / `update`,用于决定操作徽标的颜色和文案。 */
|
|
83
|
-
opType: HistoryOpType;
|
|
84
|
-
/** 组的整体描述文案,由上层根据 step / group 计算后传入,例如 "修改 button · style.color"。 */
|
|
85
|
-
desc: string;
|
|
86
|
-
/** 组内的 step 总数,仅在 merged 为 true 时显示为 "合并 N 步"。 */
|
|
87
|
-
stepCount: number;
|
|
88
|
-
/** 子步列表,用于在展开状态下逐条展示每个 step 的索引、应用状态与描述文案。 */
|
|
89
|
-
subSteps: {
|
|
90
|
-
index: number;
|
|
91
|
+
const props = withDefaults(
|
|
92
|
+
defineProps<{
|
|
93
|
+
/** 唯一标识当前组的 key,作为 toggle 事件的 payload 回传给上层。形如 `pg-${首步 index}` / `ds-${id}-${首步 index}` / `cb-${id}-${首步 index}`,以稳定的 step 索引标识分组。 */
|
|
94
|
+
groupKey: string;
|
|
95
|
+
/** 该组当前是否处于已应用状态(false 表示已被 undo 撤销,UI 会显示为灰态)。 */
|
|
91
96
|
applied: boolean;
|
|
97
|
+
/** 是否为合并组(即组内 step 数大于 1,由多次连续操作合并而来)。决定是否展示合并标记与可展开的子步列表。 */
|
|
98
|
+
merged: boolean;
|
|
99
|
+
/** 操作类型:`add` / `remove` / `update`,用于决定操作徽标的颜色和文案。 */
|
|
100
|
+
opType: HistoryOpType;
|
|
101
|
+
/** 组的整体描述文案,由上层根据 step / group 计算后传入,例如 "修改 button · style.color"。 */
|
|
92
102
|
desc: string;
|
|
103
|
+
/** 组头部展示的时间文案(一般为组内最近一步的时间),为空时不渲染。 */
|
|
104
|
+
time?: string;
|
|
105
|
+
/** 组头部时间的 title 悬浮提示(完整时间),缺省时回退为 time。 */
|
|
106
|
+
timeTitle?: string;
|
|
107
|
+
/** 组内的 step 总数,仅在 merged 为 true 时显示为 "合并 N 步"。 */
|
|
108
|
+
stepCount: number;
|
|
109
|
+
/** 子步列表,用于在展开状态下逐条展示每个 step 的索引、应用状态与描述文案。 */
|
|
110
|
+
subSteps: {
|
|
111
|
+
index: number;
|
|
112
|
+
applied: boolean;
|
|
113
|
+
desc: string;
|
|
114
|
+
isCurrent?: boolean;
|
|
115
|
+
diffable?: boolean;
|
|
116
|
+
/** 是否可对该子步执行「回滚」(已应用 + 业务侧确认支持反向)。父级根据 step 与 applied 决定。 */
|
|
117
|
+
revertable?: boolean;
|
|
118
|
+
/** 该子步的时间文案,为空时不渲染。 */
|
|
119
|
+
time?: string;
|
|
120
|
+
/** 该子步时间的 title 悬浮提示(完整时间),缺省时回退为 time。 */
|
|
121
|
+
timeTitle?: string;
|
|
122
|
+
}[];
|
|
123
|
+
/** 当前组是否处于展开状态。仅在 merged 为 true 时生效,控制子步列表是否渲染。 */
|
|
124
|
+
expanded: boolean;
|
|
125
|
+
/** 是否为当前所在的分组(包含栈中最近一次已应用步骤的那一组),UI 高亮展示。 */
|
|
93
126
|
isCurrent?: boolean;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
127
|
+
/**
|
|
128
|
+
* 是否支持「跳转到该记录」(goto)。默认 true。
|
|
129
|
+
* 为 false 时:单步组头部与子步条目都不再可点击跳转、也不会触发 goto 事件,
|
|
130
|
+
* 仅保留合并组头部的展开 / 收起能力,以及查看差异、回滚等其它入口。
|
|
131
|
+
*/
|
|
132
|
+
gotoEnabled?: boolean;
|
|
133
|
+
}>(),
|
|
134
|
+
{
|
|
135
|
+
isCurrent: false,
|
|
136
|
+
gotoEnabled: true,
|
|
137
|
+
},
|
|
138
|
+
);
|
|
103
139
|
|
|
104
140
|
const emit = defineEmits<{
|
|
105
141
|
/**
|
|
@@ -129,36 +165,35 @@ const emit = defineEmits<{
|
|
|
129
165
|
(_e: 'revert-step', _index: number): void;
|
|
130
166
|
}>();
|
|
131
167
|
|
|
132
|
-
/**
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
168
|
+
/**
|
|
169
|
+
* 仅合并组头部可点击(切换展开 / 收起);
|
|
170
|
+
* 单步组的跳转改由头部的「回退」按钮触发,整行不再可点击。
|
|
171
|
+
*/
|
|
172
|
+
const isHeadClickable = computed(() => props.merged);
|
|
137
173
|
|
|
138
174
|
const headTitle = computed(() => {
|
|
139
175
|
if (props.merged) return props.expanded ? '点击收起子步' : '点击展开子步';
|
|
140
176
|
if (props.isCurrent) return '当前所在记录';
|
|
141
|
-
return '
|
|
177
|
+
return '';
|
|
142
178
|
});
|
|
143
179
|
|
|
144
180
|
/**
|
|
145
|
-
*
|
|
146
|
-
* - 合并组:仅切换展开 / 收起,不触发 goto;
|
|
147
|
-
* - 单步组:跳转到该唯一步骤;当前组忽略点击。
|
|
181
|
+
* 头部点击行为:仅合并组切换展开 / 收起;单步组不再响应整行点击。
|
|
148
182
|
*/
|
|
149
183
|
const onHeadClick = () => {
|
|
150
184
|
if (props.merged) {
|
|
151
185
|
emit('toggle', props.groupKey);
|
|
152
|
-
return;
|
|
153
186
|
}
|
|
154
|
-
if (props.isCurrent) return;
|
|
155
|
-
if (!props.subSteps.length) return;
|
|
156
|
-
emit('goto', props.subSteps[0].index);
|
|
157
187
|
};
|
|
158
188
|
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
161
|
-
emit('goto',
|
|
189
|
+
const onGotoClick = (index: number) => {
|
|
190
|
+
if (!props.gotoEnabled) return;
|
|
191
|
+
emit('goto', index);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const subStepTitle = (s: { isCurrent?: boolean }) => {
|
|
195
|
+
if (s.isCurrent) return '当前所在记录';
|
|
196
|
+
return '';
|
|
162
197
|
};
|
|
163
198
|
|
|
164
199
|
/** 单步组头部是否展示"查看差异"入口:要求该唯一子步本身可对比。 */
|
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
<TMagicDialog
|
|
4
4
|
v-model="visible"
|
|
5
5
|
class="m-editor-history-diff-dialog"
|
|
6
|
-
title="
|
|
7
|
-
width="900px"
|
|
6
|
+
:title="dialogTitle"
|
|
8
7
|
top="5vh"
|
|
9
8
|
destroy-on-close
|
|
10
9
|
append-to-body
|
|
10
|
+
:width="width"
|
|
11
|
+
@close="onClose"
|
|
11
12
|
>
|
|
12
13
|
<div v-if="payload" class="m-editor-history-diff-dialog-body">
|
|
14
|
+
<div v-if="onConfirm" class="m-editor-history-diff-dialog-notice">仅回滚有差异的字段</div>
|
|
15
|
+
|
|
13
16
|
<div class="m-editor-history-diff-dialog-header">
|
|
14
17
|
<span class="m-editor-history-diff-dialog-target">{{ targetText }}</span>
|
|
15
18
|
<div class="m-editor-history-diff-dialog-controls">
|
|
@@ -42,6 +45,8 @@
|
|
|
42
45
|
:value="rightValue"
|
|
43
46
|
:last-value="leftValue"
|
|
44
47
|
:extend-state="extendState"
|
|
48
|
+
:load-config="loadConfig"
|
|
49
|
+
:self-diff-field-types="selfDiffFieldTypes"
|
|
45
50
|
height="70vh"
|
|
46
51
|
/>
|
|
47
52
|
|
|
@@ -58,7 +63,11 @@
|
|
|
58
63
|
</div>
|
|
59
64
|
|
|
60
65
|
<template #footer>
|
|
61
|
-
<
|
|
66
|
+
<template v-if="onConfirm">
|
|
67
|
+
<TMagicButton size="small" @click="visible = false">取消</TMagicButton>
|
|
68
|
+
<TMagicButton size="small" type="primary" @click="onConfirmClick">确定回滚</TMagicButton>
|
|
69
|
+
</template>
|
|
70
|
+
<TMagicButton v-else size="small" @click="visible = false">关闭</TMagicButton>
|
|
62
71
|
</template>
|
|
63
72
|
</TMagicDialog>
|
|
64
73
|
</Teleport>
|
|
@@ -71,41 +80,37 @@ import { isEqual } from 'lodash-es';
|
|
|
71
80
|
import { TMagicButton, TMagicDialog, TMagicRadioButton, TMagicRadioGroup, TMagicTag } from '@tmagic/design';
|
|
72
81
|
import type { FormState } from '@tmagic/form';
|
|
73
82
|
|
|
74
|
-
import CompareForm
|
|
83
|
+
import CompareForm from '@editor/components/CompareForm.vue';
|
|
75
84
|
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
|
85
|
+
import type { CompareCategory, CompareFormLoadConfig, DiffDialogPayload } from '@editor/type';
|
|
76
86
|
|
|
77
87
|
defineOptions({
|
|
78
88
|
name: 'MEditorHistoryDiffDialog',
|
|
79
89
|
});
|
|
80
90
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
/** 用于标题展示的目标名称 */
|
|
105
|
-
targetLabel?: string;
|
|
106
|
-
/** 用于标题展示的目标 id */
|
|
107
|
-
id?: string | number;
|
|
108
|
-
}
|
|
91
|
+
const props = withDefaults(
|
|
92
|
+
defineProps<{
|
|
93
|
+
/**
|
|
94
|
+
* 来自 Editor 顶层的 `extendFormState`,用于扩展 MForm.formState。
|
|
95
|
+
* 透传给 CompareForm,从而让差异对比时表单 item 中依赖业务上下文的
|
|
96
|
+
* `display` / `disabled` 等 filterFunction 正常工作。
|
|
97
|
+
*/
|
|
98
|
+
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
99
|
+
/**
|
|
100
|
+
* 自定义 FormConfig 加载逻辑,透传给 CompareForm。传入后将接管内置的按 `category`
|
|
101
|
+
* 取配置逻辑,可通过 `ctx.defaultLoadConfig()` 复用默认结果再做二次加工。
|
|
102
|
+
*/
|
|
103
|
+
loadConfig?: CompareFormLoadConfig;
|
|
104
|
+
width?: string;
|
|
105
|
+
onConfirm?: () => void;
|
|
106
|
+
selfDiffFieldTypes?: string[];
|
|
107
|
+
}>(),
|
|
108
|
+
{
|
|
109
|
+
width: '900px',
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const emit = defineEmits(['close']);
|
|
109
114
|
|
|
110
115
|
/**
|
|
111
116
|
* 差异对比模式:
|
|
@@ -146,6 +151,8 @@ const codeDiffOptions = {
|
|
|
146
151
|
},
|
|
147
152
|
};
|
|
148
153
|
|
|
154
|
+
const dialogTitle = computed(() => (props.onConfirm ? '确认回滚' : '查看修改差异'));
|
|
155
|
+
|
|
149
156
|
const hasCurrent = computed(() => payload.value?.currentValue !== undefined && payload.value?.currentValue !== null);
|
|
150
157
|
|
|
151
158
|
/** 左侧(旧/参照)值 */
|
|
@@ -171,6 +178,14 @@ const isSameAsCurrent = computed(() => {
|
|
|
171
178
|
return isEqual(payload.value.value, payload.value.currentValue);
|
|
172
179
|
});
|
|
173
180
|
|
|
181
|
+
const onConfirmClick = () => {
|
|
182
|
+
const cb = props.onConfirm;
|
|
183
|
+
|
|
184
|
+
cb?.();
|
|
185
|
+
|
|
186
|
+
visible.value = false;
|
|
187
|
+
};
|
|
188
|
+
|
|
174
189
|
const targetText = computed(() => {
|
|
175
190
|
if (!payload.value) return '';
|
|
176
191
|
const categoryText: Record<CompareCategory, string> = {
|
|
@@ -205,6 +220,10 @@ watch(visible, (v) => {
|
|
|
205
220
|
}
|
|
206
221
|
});
|
|
207
222
|
|
|
223
|
+
const onClose = () => {
|
|
224
|
+
emit('close');
|
|
225
|
+
};
|
|
226
|
+
|
|
208
227
|
defineExpose({
|
|
209
228
|
open,
|
|
210
229
|
close,
|