|
|
|
@ -51,13 +51,37 @@ |
|
|
|
<el-table-column prop="operation" header-align="center" align="left" min-width="160" label="操作" /> |
|
|
|
<el-table-column prop="username" header-align="center" align="center" width="120" label="操作人" /> |
|
|
|
<el-table-column prop="createDate" header-align="center" align="center" width="170" label="创建时间" /> |
|
|
|
<el-table-column prop="oldValue" header-align="center" align="center" width="370" label="修改前值" :show-overflow-tooltip="true"/> |
|
|
|
<el-table-column prop="newValue" header-align="center" align="center" width="370" label="修改后值" :show-overflow-tooltip="true"/> |
|
|
|
<el-table-column fixed="right" header-align="center" align="center" width="100" label="操作"> |
|
|
|
<template v-for="field in dynamicColumns"> |
|
|
|
<el-table-column |
|
|
|
:key="field + '_old'" |
|
|
|
:label="getFieldLabel(field) + '改动前'" |
|
|
|
header-align="center" |
|
|
|
align="left" |
|
|
|
min-width="180" |
|
|
|
:show-overflow-tooltip="true" |
|
|
|
> |
|
|
|
<template slot-scope="scope"> |
|
|
|
{{ flattenDisplayValue(getFieldRawValue(scope.row.parsedOldValue, field)) }} |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column |
|
|
|
:key="field + '_new'" |
|
|
|
:label="getFieldLabel(field) + '改动后'" |
|
|
|
header-align="center" |
|
|
|
align="left" |
|
|
|
min-width="180" |
|
|
|
:show-overflow-tooltip="true" |
|
|
|
> |
|
|
|
<template slot-scope="scope"> |
|
|
|
{{ flattenDisplayValue(getFieldRawValue(scope.row.parsedNewValue, field)) }} |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</template> |
|
|
|
<!-- <el-table-column fixed="right" header-align="center" align="center" width="100" label="操作"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<el-link style="cursor: pointer" @click="openDetail(scope.row)">详情</el-link> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</el-table-column> --> |
|
|
|
</el-table> |
|
|
|
|
|
|
|
<el-pagination |
|
|
|
@ -79,14 +103,11 @@ |
|
|
|
</el-descriptions> |
|
|
|
|
|
|
|
<div style="margin-top: 12px"> |
|
|
|
<el-tabs type="border-card"> |
|
|
|
<el-tab-pane label="修改前(oldValue)"> |
|
|
|
<pre class="json-pre">{{ prettyJson(detailRow.oldValue) }}</pre> |
|
|
|
</el-tab-pane> |
|
|
|
<el-tab-pane label="修改后(newValue)"> |
|
|
|
<pre class="json-pre">{{ prettyJson(detailRow.newValue) }}</pre> |
|
|
|
</el-tab-pane> |
|
|
|
</el-tabs> |
|
|
|
<el-table :data="detailDiffList" border size="mini" max-height="420"> |
|
|
|
<el-table-column prop="label" label="字段" min-width="220" /> |
|
|
|
<el-table-column prop="oldValue" label="修改前" min-width="220" /> |
|
|
|
<el-table-column prop="newValue" label="修改后" min-width="220" /> |
|
|
|
</el-table> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
</div> |
|
|
|
@ -116,6 +137,7 @@ export default { |
|
|
|
tableHeight: 500, |
|
|
|
detailVisible: false, |
|
|
|
detailRow: {}, |
|
|
|
dynamicColumns: [], |
|
|
|
} |
|
|
|
}, |
|
|
|
created() { |
|
|
|
@ -127,6 +149,85 @@ export default { |
|
|
|
}) |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
isIdField(key) { |
|
|
|
if (!key) return false |
|
|
|
return /(^id$|_id$|Id$)/.test(String(key)) |
|
|
|
}, |
|
|
|
parseJsonObject(val) { |
|
|
|
if (val === null || val === undefined || val === '') return {} |
|
|
|
if (typeof val === 'object') return val || {} |
|
|
|
try { |
|
|
|
const parsed = JSON.parse(String(val)) |
|
|
|
return parsed && typeof parsed === 'object' ? parsed : {} |
|
|
|
} catch (e) { |
|
|
|
return {} |
|
|
|
} |
|
|
|
}, |
|
|
|
getFieldLabelMap() { |
|
|
|
return { |
|
|
|
detailPlanStartDate: '计划开始时间', |
|
|
|
detailPlanEndDate: '计划结束时间', |
|
|
|
projectStartDate: '项目开始时间', |
|
|
|
planStartDate: '项目计划开始时间', |
|
|
|
planEndDate: '项目计划结束时间', |
|
|
|
daysNumber: '天数', |
|
|
|
} |
|
|
|
}, |
|
|
|
getMappedFieldKeys() { |
|
|
|
// 固定列顺序,避免不同数据导致列顺序变化影响阅读 |
|
|
|
return [ |
|
|
|
'detailPlanStartDate', |
|
|
|
'detailPlanEndDate', |
|
|
|
'projectStartDate', |
|
|
|
'planStartDate', |
|
|
|
'planEndDate', |
|
|
|
'daysNumber', |
|
|
|
] |
|
|
|
}, |
|
|
|
getFieldRawValue(parsedValue, fieldKey) { |
|
|
|
if (parsedValue === null || parsedValue === undefined || parsedValue === '') return undefined |
|
|
|
// 支持 parsedValue 是数组的情况(例如 key 在数组元素对象里) |
|
|
|
if (Array.isArray(parsedValue)) { |
|
|
|
const values = [] |
|
|
|
parsedValue.forEach((item) => { |
|
|
|
if (item && typeof item === 'object' && !Array.isArray(item) && Object.prototype.hasOwnProperty.call(item, fieldKey)) { |
|
|
|
values.push(item[fieldKey]) |
|
|
|
} |
|
|
|
}) |
|
|
|
return values.length ? values : undefined |
|
|
|
} |
|
|
|
if (typeof parsedValue === 'object') { |
|
|
|
return Object.prototype.hasOwnProperty.call(parsedValue, fieldKey) ? parsedValue[fieldKey] : undefined |
|
|
|
} |
|
|
|
return undefined |
|
|
|
}, |
|
|
|
buildDynamicColumns(list) { |
|
|
|
// 这里直接固定为你约定的字段集合,避免出现数组下标(0/1/2...)被当成“列名” |
|
|
|
this.dynamicColumns = this.getMappedFieldKeys() |
|
|
|
}, |
|
|
|
getFieldLabel(key) { |
|
|
|
const map = this.getFieldLabelMap() |
|
|
|
return map[key] || key |
|
|
|
}, |
|
|
|
flattenDisplayValue(val) { |
|
|
|
if (val === null || val === undefined || val === '') return '-' |
|
|
|
const values = [] |
|
|
|
const pushLeaf = (v) => { |
|
|
|
if (v === null || v === undefined || v === '') return |
|
|
|
if (Array.isArray(v)) { |
|
|
|
v.forEach((it) => pushLeaf(it)) |
|
|
|
return |
|
|
|
} |
|
|
|
if (typeof v === 'object') { |
|
|
|
Object.values(v).forEach((it) => pushLeaf(it)) |
|
|
|
return |
|
|
|
} |
|
|
|
values.push(String(v)) |
|
|
|
} |
|
|
|
pushLeaf(val) |
|
|
|
if (!values.length) return '-' |
|
|
|
return values.join(';') |
|
|
|
}, |
|
|
|
getDataList() { |
|
|
|
this.dataListLoading = true |
|
|
|
const params = { |
|
|
|
@ -137,10 +238,21 @@ export default { |
|
|
|
querySysBusinessLogPage(params) |
|
|
|
.then(({ data }) => { |
|
|
|
if (data && data.code === 0 && data.page) { |
|
|
|
this.dataList = data.page.list || [] |
|
|
|
const list = data.page.list || [] |
|
|
|
this.dataList = list.map((item) => { |
|
|
|
const parsedOldValue = this.parseJsonObject(item.oldValue) |
|
|
|
const parsedNewValue = this.parseJsonObject(item.newValue) |
|
|
|
return { |
|
|
|
...item, |
|
|
|
parsedOldValue, |
|
|
|
parsedNewValue, |
|
|
|
} |
|
|
|
}) |
|
|
|
this.buildDynamicColumns(this.dataList) |
|
|
|
this.totalPage = data.page.totalCount || 0 |
|
|
|
} else { |
|
|
|
this.dataList = [] |
|
|
|
this.dynamicColumns = [] |
|
|
|
this.totalPage = 0 |
|
|
|
} |
|
|
|
}) |
|
|
|
@ -166,21 +278,18 @@ export default { |
|
|
|
this.detailRow = JSON.parse(JSON.stringify(row || {})) |
|
|
|
this.detailVisible = true |
|
|
|
}, |
|
|
|
prettyJson(val) { |
|
|
|
if (val === null || val === undefined || val === '') return '' |
|
|
|
if (typeof val === 'object') { |
|
|
|
try { |
|
|
|
return JSON.stringify(val, null, 2) |
|
|
|
} catch (e) { |
|
|
|
return String(val) |
|
|
|
} |
|
|
|
} |
|
|
|
const str = String(val) |
|
|
|
try { |
|
|
|
return JSON.stringify(JSON.parse(str), null, 2) |
|
|
|
} catch (e) { |
|
|
|
return str |
|
|
|
} |
|
|
|
getDetailDiffList(row) { |
|
|
|
const oldObj = this.parseJsonObject(row.oldValue) |
|
|
|
const newObj = this.parseJsonObject(row.newValue) |
|
|
|
const mappedKeys = this.getMappedFieldKeys() |
|
|
|
return mappedKeys |
|
|
|
.filter((k) => !this.isIdField(k)) |
|
|
|
.map((key) => ({ |
|
|
|
key, |
|
|
|
label: this.getFieldLabel(key), |
|
|
|
oldValue: this.flattenDisplayValue(this.getFieldRawValue(oldObj, key)), |
|
|
|
newValue: this.flattenDisplayValue(this.getFieldRawValue(newObj, key)), |
|
|
|
})) |
|
|
|
}, |
|
|
|
getReviewedLabel(flag) { |
|
|
|
if (flag === 'Y') return '已审核' |
|
|
|
@ -192,18 +301,15 @@ export default { |
|
|
|
return 'status-yellow' |
|
|
|
}, |
|
|
|
}, |
|
|
|
computed: { |
|
|
|
detailDiffList() { |
|
|
|
return this.getDetailDiffList(this.detailRow || {}) |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped> |
|
|
|
.json-pre { |
|
|
|
white-space: pre-wrap; |
|
|
|
word-break: break-word; |
|
|
|
margin: 0; |
|
|
|
font-size: 12px; |
|
|
|
line-height: 18px; |
|
|
|
} |
|
|
|
|
|
|
|
.status-green { |
|
|
|
color: #67c23a; |
|
|
|
} |
|
|
|
|