feat(history): exclude sort order changes from edit history
Stop recording sort order changes in the backend edit log Filter out existing sort order changes from the frontend edit history panel
This commit is contained in:
@@ -344,6 +344,7 @@
|
||||
- `created_at`
|
||||
- 详情页展示最后编辑者、最后编辑时间和编辑历史面板。
|
||||
- 编辑历史中的用户信息只展示必要署名,不暴露邮箱、token、hash 或内部元数据。
|
||||
- 排序操作仍更新列表顺序、最后编辑者和最后编辑时间,但 `sort_order` / Sort order 字段变更不写入或展示在详情页编辑历史面板中。
|
||||
- 编辑署名、编辑历史署名、Life 作者和讨论作者可链接到对应公开 Profile。
|
||||
|
||||
## Wiki 图片上传
|
||||
|
||||
@@ -1142,7 +1142,6 @@ async function nextPokemonInternalId(
|
||||
async function reorderTableRows(
|
||||
client: DbClient,
|
||||
tableName: string,
|
||||
entityType: string,
|
||||
ids: number[],
|
||||
userId: number
|
||||
): Promise<void> {
|
||||
@@ -1171,9 +1170,6 @@ async function reorderTableRows(
|
||||
`,
|
||||
[nextSortOrder, userId, id]
|
||||
);
|
||||
const changes: EditChange[] = [];
|
||||
pushChange(changes, 'Sort order', String(previousSortOrder), String(nextSortOrder));
|
||||
await recordEditLog(client, entityType, id, 'update', userId, changes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2798,9 +2794,6 @@ export async function reorderDailyChecklistItems(payload: Record<string, unknown
|
||||
`,
|
||||
[nextSortOrder, userId, id]
|
||||
);
|
||||
const changes: EditChange[] = [];
|
||||
pushChange(changes, 'Sort order', String(previousSortOrder), String(nextSortOrder));
|
||||
await recordEditLog(client, 'daily-checklist-items', id, 'update', userId, changes);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5339,7 +5332,7 @@ export async function reorderConfig(type: ConfigType, payload: Record<string, un
|
||||
}
|
||||
|
||||
await withTransaction(async (client) => {
|
||||
await reorderTableRows(client, definition.table, type, ids, userId);
|
||||
await reorderTableRows(client, definition.table, ids, userId);
|
||||
});
|
||||
|
||||
return listConfig(type, locale);
|
||||
@@ -5440,7 +5433,7 @@ async function reorderContent(type: SortableContentType, payload: Record<string,
|
||||
}
|
||||
|
||||
await withTransaction(async (client) => {
|
||||
await reorderTableRows(client, definition.table, definition.entityType, ids, userId);
|
||||
await reorderTableRows(client, definition.table, ids, userId);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6618,7 +6611,7 @@ export async function createItem(payload: Record<string, unknown>, userId: numbe
|
||||
}
|
||||
|
||||
orderedIds.splice(targetIndex + (cleanPayload.insertAfterItemId !== null ? 1 : 0), 0, itemId);
|
||||
await reorderTableRows(client, 'items', 'items', orderedIds, userId);
|
||||
await reorderTableRows(client, 'items', orderedIds, userId);
|
||||
}
|
||||
|
||||
await recordEditLog(client, 'items', itemId, 'create', userId);
|
||||
@@ -7526,7 +7519,7 @@ export async function reorderDishCategories(payload: Record<string, unknown>, us
|
||||
throw validationError('server.validation.selectRecord');
|
||||
}
|
||||
await withTransaction(async (client) => {
|
||||
await reorderTableRows(client, 'dish_categories', 'dish-categories', ids, userId);
|
||||
await reorderTableRows(client, 'dish_categories', ids, userId);
|
||||
});
|
||||
return listDish(locale);
|
||||
}
|
||||
@@ -7537,7 +7530,7 @@ export async function reorderDishes(payload: Record<string, unknown>, userId: nu
|
||||
throw validationError('server.validation.selectRecord');
|
||||
}
|
||||
await withTransaction(async (client) => {
|
||||
await reorderTableRows(client, 'dishes', 'dishes', ids, userId);
|
||||
await reorderTableRows(client, 'dishes', ids, userId);
|
||||
});
|
||||
return listDish(locale);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import type { EditHistoryAction, EditHistoryEntry, EditInfo, UserSummary } from '../services/api';
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
entity: EditInfo;
|
||||
history: EditHistoryEntry[];
|
||||
}>();
|
||||
@@ -118,7 +118,11 @@ function changeValue(value: string): string {
|
||||
}
|
||||
|
||||
function visibleChanges(entry: EditHistoryEntry) {
|
||||
return entry.changes.filter((change) => change.label !== 'Display ID');
|
||||
return entry.changes.filter((change) => change.label !== 'Display ID' && change.label !== 'Sort order' && change.label !== '排序');
|
||||
}
|
||||
|
||||
function visibleHistoryEntries() {
|
||||
return props.history.filter((entry) => entry.action !== 'update' || visibleChanges(entry).length > 0);
|
||||
}
|
||||
|
||||
function historySummary(entry: EditHistoryEntry): string {
|
||||
@@ -148,29 +152,29 @@ function formatDateTime(value: string): string {
|
||||
<div>
|
||||
<dt>{{ t('history.createdBy') }}</dt>
|
||||
<dd>
|
||||
<RouterLink v-if="entity.createdBy" class="user-profile-link" :to="`/profile/${entity.createdBy.id}`">
|
||||
{{ entity.createdBy.displayName }}
|
||||
<RouterLink v-if="props.entity.createdBy" class="user-profile-link" :to="`/profile/${props.entity.createdBy.id}`">
|
||||
{{ props.entity.createdBy.displayName }}
|
||||
</RouterLink>
|
||||
<strong v-else>{{ displayName(entity.createdBy) }}</strong>
|
||||
<time :datetime="entity.createdAt">{{ formatDateTime(entity.createdAt) }}</time>
|
||||
<strong v-else>{{ displayName(props.entity.createdBy) }}</strong>
|
||||
<time :datetime="props.entity.createdAt">{{ formatDateTime(props.entity.createdAt) }}</time>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>{{ t('history.lastEdited') }}</dt>
|
||||
<dd>
|
||||
<RouterLink v-if="entity.updatedBy" class="user-profile-link" :to="`/profile/${entity.updatedBy.id}`">
|
||||
{{ entity.updatedBy.displayName }}
|
||||
<RouterLink v-if="props.entity.updatedBy" class="user-profile-link" :to="`/profile/${props.entity.updatedBy.id}`">
|
||||
{{ props.entity.updatedBy.displayName }}
|
||||
</RouterLink>
|
||||
<strong v-else>{{ displayName(entity.updatedBy) }}</strong>
|
||||
<time :datetime="entity.updatedAt">{{ formatDateTime(entity.updatedAt) }}</time>
|
||||
<strong v-else>{{ displayName(props.entity.updatedBy) }}</strong>
|
||||
<time :datetime="props.entity.updatedAt">{{ formatDateTime(props.entity.updatedAt) }}</time>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<section class="edit-history-list" aria-labelledby="edit-history-list-title">
|
||||
<h3 id="edit-history-list-title">{{ t('history.editHistory') }}</h3>
|
||||
<ol v-if="history.length" class="edit-timeline">
|
||||
<li v-for="entry in history" :key="`${entry.action}-${entry.createdAt}-${entry.user?.id ?? 'system'}`">
|
||||
<ol v-if="visibleHistoryEntries().length" class="edit-timeline">
|
||||
<li v-for="entry in visibleHistoryEntries()" :key="`${entry.action}-${entry.createdAt}-${entry.user?.id ?? 'system'}`">
|
||||
<span class="edit-timeline__avatar" aria-hidden="true">{{ actionMark(entry.action) }}</span>
|
||||
<div class="edit-timeline__body">
|
||||
<details class="edit-history-entry">
|
||||
|
||||
Reference in New Issue
Block a user