<script lang="ts" setup>
|
import type { AuditFieldDiff } from './auditDiff';
|
|
import { computed } from 'vue';
|
|
import { createImgPreview } from '@jnpf/ui';
|
import { useModal } from '@jnpf/ui/modal';
|
|
import { Empty } from 'ant-design-vue';
|
|
import { getAuthMediaUrl } from '#/utils/jnpf';
|
|
import { formatAuditDiffValue, getSafeAuditDiffFieldLabel, hasAuditDiffValue, isSensitiveAuditDiff } from './auditDiff';
|
import AuditDiffTable from './AuditDiffTable.vue';
|
import ChildLogModal from './modal/ChildLogModal.vue';
|
|
const props = withDefaults(
|
defineProps<{
|
diffs: AuditFieldDiff[];
|
emptyText?: string;
|
hideTechnicalFieldNames?: boolean;
|
layout?: 'list' | 'table';
|
maskSensitive?: boolean;
|
parseError?: boolean;
|
showTotal?: boolean;
|
}>(),
|
{
|
emptyText: '该操作没有字段级变更明细',
|
hideTechnicalFieldNames: false,
|
layout: 'list',
|
maskSensitive: false,
|
parseError: false,
|
showTotal: true,
|
},
|
);
|
|
const [registerChildLogModal, { openModal: openChildLogModal }] = useModal();
|
const businessDiffs = computed(() => props.diffs.filter((diff) => !diff.technical));
|
const technicalDiffs = computed(() => props.diffs.filter((diff) => diff.technical));
|
|
function getFieldLabel(diff: AuditFieldDiff, index: number) {
|
if (props.hideTechnicalFieldNames) return getSafeAuditDiffFieldLabel(diff, index);
|
return diff.fieldName || diff.field || '未命名字段';
|
}
|
|
function previewMedia(value: unknown) {
|
if (!hasAuditDiffValue(value)) return;
|
const mediaPath = formatAuditDiffValue(value);
|
if (!mediaPath) return;
|
createImgPreview({ imageList: [getAuthMediaUrl(mediaPath)] });
|
}
|
|
function viewChildDiff(diff: AuditFieldDiff) {
|
openChildLogModal(true, { ...diff, maskSensitive: props.maskSensitive });
|
}
|
</script>
|
|
<template>
|
<div class="audit-diff-list">
|
<a-alert v-if="parseError" type="warning" show-icon message="字段明细解析失败" description="事件概览和技术信息仍可正常查看。" />
|
<Empty v-else-if="!diffs.length" :description="emptyText" :image="undefined" />
|
<template v-else>
|
<div class="audit-diff-total" v-if="showTotal">
|
共 <strong>{{ diffs.length }}</strong> 处字段变更
|
</div>
|
<template v-if="layout === 'table'">
|
<AuditDiffTable
|
v-if="businessDiffs.length"
|
:diffs="businessDiffs"
|
:hide-technical-field-names="hideTechnicalFieldNames"
|
:mask-sensitive="maskSensitive"
|
@view-child="viewChildDiff" />
|
<a-collapse v-if="technicalDiffs.length" class="audit-diff-technical" ghost expand-icon-position="end">
|
<a-collapse-panel key="technical" :header="`技术字段变更(${technicalDiffs.length})`">
|
<AuditDiffTable
|
:diffs="technicalDiffs"
|
:hide-technical-field-names="hideTechnicalFieldNames"
|
:mask-sensitive="maskSensitive"
|
@view-child="viewChildDiff" />
|
</a-collapse-panel>
|
</a-collapse>
|
</template>
|
<template v-else>
|
<div class="audit-diff-item" v-for="(diff, index) in diffs" :key="`${diff.field || 'field'}-${index}`">
|
<div class="audit-diff-label" :title="getFieldLabel(diff, index)">{{ getFieldLabel(diff, index) }}</div>
|
<div class="audit-diff-value">
|
<span class="audit-diff-masked" v-if="diff.nameModified">已修改</span>
|
<span class="audit-diff-masked" v-else-if="maskSensitive && isSensitiveAuditDiff(diff)">敏感信息已隐藏</span>
|
<a-button v-else-if="diff.jnpfKey === 'table'" type="link" size="small" @click="viewChildDiff(diff)">查看子表变更</a-button>
|
<template v-else-if="diff.jnpfKey === 'sign'">
|
<a-button v-if="hasAuditDiffValue(diff.oldData)" type="link" size="small" class="audit-diff-old-link" @click="previewMedia(diff.oldData)">
|
旧签名
|
</a-button>
|
<span class="audit-diff-arrow" v-if="hasAuditDiffValue(diff.oldData) && hasAuditDiffValue(diff.newData)">修改为</span>
|
<a-button v-if="hasAuditDiffValue(diff.newData)" type="link" size="small" @click="previewMedia(diff.newData)">新签名</a-button>
|
</template>
|
<template v-else-if="diff.jnpfKey === 'signature'">
|
<a-button v-if="hasAuditDiffValue(diff.oldData)" type="link" size="small" class="audit-diff-old-link" @click="previewMedia(diff.oldData)">
|
旧签章
|
</a-button>
|
<span class="audit-diff-arrow" v-if="hasAuditDiffValue(diff.oldData) && hasAuditDiffValue(diff.newData)">修改为</span>
|
<a-button v-if="hasAuditDiffValue(diff.newData)" type="link" size="small" @click="previewMedia(diff.newData)">新签章</a-button>
|
</template>
|
<template v-else>
|
<span class="audit-diff-old" v-if="hasAuditDiffValue(diff.oldData)">{{ formatAuditDiffValue(diff.oldData) }}</span>
|
<span class="audit-diff-arrow" v-if="hasAuditDiffValue(diff.oldData) && hasAuditDiffValue(diff.newData)">修改为</span>
|
<span class="audit-diff-new" v-if="hasAuditDiffValue(diff.newData)">{{ formatAuditDiffValue(diff.newData) }}</span>
|
<span class="audit-diff-empty" v-if="!hasAuditDiffValue(diff.oldData) && !hasAuditDiffValue(diff.newData)">无可展示值</span>
|
</template>
|
</div>
|
</div>
|
</template>
|
</template>
|
<ChildLogModal @register="registerChildLogModal" />
|
</div>
|
</template>
|
|
<style lang="scss" scoped>
|
.audit-diff-list {
|
min-width: 0;
|
}
|
|
.audit-diff-total {
|
padding: 0 0 10px;
|
color: var(--text-color-secondary);
|
|
strong {
|
color: var(--primary-color);
|
}
|
}
|
|
.audit-diff-technical {
|
margin-top: 12px;
|
border-top: 1px solid var(--border-color-base1);
|
|
:deep(.ant-collapse-header) {
|
padding-inline: 0;
|
font-weight: 500;
|
}
|
|
:deep(.ant-collapse-content-box) {
|
padding-inline: 0;
|
}
|
}
|
|
.audit-diff-item {
|
display: grid;
|
grid-template-columns: minmax(110px, 180px) minmax(0, 1fr);
|
gap: 12px;
|
padding: 12px 0;
|
border-bottom: 1px solid var(--border-color-base1);
|
}
|
|
.audit-diff-label {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
font-weight: 500;
|
white-space: nowrap;
|
}
|
|
.audit-diff-value {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 6px;
|
align-items: flex-start;
|
min-width: 0;
|
overflow-wrap: anywhere;
|
|
:deep(.ant-btn-link) {
|
height: auto;
|
padding: 0;
|
}
|
}
|
|
.audit-diff-old,
|
.audit-diff-new {
|
display: inline-block;
|
max-width: 100%;
|
padding: 2px 8px;
|
overflow: auto;
|
white-space: pre-wrap;
|
border-radius: 4px;
|
}
|
|
.audit-diff-old {
|
text-decoration: line-through;
|
background: var(--error-color-hover);
|
}
|
|
.audit-diff-new {
|
background: var(--success-color-hover);
|
}
|
|
.audit-diff-old-link {
|
text-decoration: line-through;
|
}
|
|
.audit-diff-arrow,
|
.audit-diff-empty {
|
color: var(--text-color-secondary);
|
}
|
|
.audit-diff-masked {
|
color: var(--warning-color);
|
}
|
|
@media (max-width: 640px) {
|
.audit-diff-item {
|
grid-template-columns: minmax(0, 1fr);
|
gap: 6px;
|
}
|
|
.audit-diff-label {
|
white-space: normal;
|
}
|
}
|
</style>
|