mirror of
https://github.com/PanJiaChen/vue-element-admin.git
synced 2025-08-10 12:01:57 +08:00
Add Change Log option in field (#822)
* Add Change Log option in field * support mobile * minimal changes * sort logs * fix style Co-authored-by: elsiosanchez <elsiossanches@gmail.com>
This commit is contained in:
parent
dc5d3df181
commit
b406b8a3fc
@ -24,11 +24,11 @@
|
|||||||
<el-scrollbar :wrap-class="classIsMobilePanel">
|
<el-scrollbar :wrap-class="classIsMobilePanel">
|
||||||
<el-timeline>
|
<el-timeline>
|
||||||
<el-timeline-item
|
<el-timeline-item
|
||||||
v-for="(listLogs, key) in gettersListRecordLogs"
|
v-for="(listLogs, key) in gettersListRecordLogs.sort(sortSequence)"
|
||||||
:key="key"
|
:key="listLogs.logId"
|
||||||
|
:type="listLogs.type"
|
||||||
:timestamp="translateDate(listLogs.logDate)"
|
:timestamp="translateDate(listLogs.logDate)"
|
||||||
placement="top"
|
placement="top"
|
||||||
color="#008fd3"
|
|
||||||
>
|
>
|
||||||
<el-card shadow="hover" class="clearfix">
|
<el-card shadow="hover" class="clearfix">
|
||||||
<div>
|
<div>
|
||||||
@ -108,7 +108,25 @@ export default {
|
|||||||
return 'panel'
|
return 'panel'
|
||||||
},
|
},
|
||||||
gettersListRecordLogs() {
|
gettersListRecordLogs() {
|
||||||
return this.$store.getters.getRecordLogs.entityLogs
|
const log = this.$store.getters.getRecordLogs.entityLogs
|
||||||
|
if (log) {
|
||||||
|
return log.map(element => {
|
||||||
|
let type
|
||||||
|
if (!this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
|
||||||
|
type = 'success'
|
||||||
|
} else if (this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && !this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
|
||||||
|
type = 'danger'
|
||||||
|
} else {
|
||||||
|
type = 'primary'
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...element,
|
||||||
|
columnName: element.changeLogsList[0].columnName,
|
||||||
|
type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []
|
||||||
},
|
},
|
||||||
getIsChangeLog() {
|
getIsChangeLog() {
|
||||||
if (this.isEmptyValue(this.gettersListRecordLogs)) {
|
if (this.isEmptyValue(this.gettersListRecordLogs)) {
|
||||||
@ -118,6 +136,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
sortSequence(itemA, itemB) {
|
||||||
|
return new Date().setTime(new Date(itemB.logDate).getTime()) - new Date().setTime(new Date(itemA.logDate).getTime())
|
||||||
|
},
|
||||||
showkey(key, index) {
|
showkey(key, index) {
|
||||||
if (key === this.currentKey && index === this.typeAction) {
|
if (key === this.currentKey && index === this.typeAction) {
|
||||||
this.currentKey = 1000
|
this.currentKey = 1000
|
||||||
@ -141,6 +162,6 @@ export default {
|
|||||||
height: 57vh;
|
height: 57vh;
|
||||||
}
|
}
|
||||||
.panel {
|
.panel {
|
||||||
height: 100vh;
|
height: 75vh;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -0,0 +1,176 @@
|
|||||||
|
<!--
|
||||||
|
ADempiere-Vue (Frontend) for ADempiere ERP & CRM Smart Business Solution
|
||||||
|
Copyright (C) 2017-Present E.R.P. Consultores y Asociados, C.A.
|
||||||
|
Contributor(s): Elsio Sanchez elsiosanches@gmail.com www.erpya.com
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https:www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span>
|
||||||
|
{{ $t('field.logsField') }}
|
||||||
|
<b> {{ fieldAttributes.name }} </b>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-scrollbar v-if="!isEmptyValue(listLogsField)" :wrap-class="classIsMobilePanel">
|
||||||
|
<el-timeline>
|
||||||
|
<el-timeline-item
|
||||||
|
v-for="(listLogs) in listLogsField.sort(sortSequence)"
|
||||||
|
:key="listLogs.logId"
|
||||||
|
:type="listLogs.type"
|
||||||
|
:timestamp="translateDate(listLogs.logDate)"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<el-card shadow="hover" class="clearfix">
|
||||||
|
<div>
|
||||||
|
{{ listLogs.userName }}
|
||||||
|
</div>
|
||||||
|
<!-- <el-collapse-transition> -->
|
||||||
|
<div>
|
||||||
|
<span v-for="(list, index) in listLogs.changeLogsList" :key="index">
|
||||||
|
<p v-if="list.columnName === 'DocStatus'">
|
||||||
|
<b> {{ list.displayColumnName }} :</b>
|
||||||
|
<strike>
|
||||||
|
<el-tag :type="tagStatus(list.oldValue)">
|
||||||
|
{{ list.oldDisplayValue }}
|
||||||
|
</el-tag>
|
||||||
|
</strike>
|
||||||
|
<el-tag :type="tagStatus(list.newValue)">
|
||||||
|
{{ list.newDisplayValue }}
|
||||||
|
</el-tag>
|
||||||
|
</p>
|
||||||
|
<p v-else>
|
||||||
|
<b> {{ list.displayColumnName }} :</b>
|
||||||
|
<strike>
|
||||||
|
<el-link type="danger">
|
||||||
|
{{ list.oldDisplayValue }}
|
||||||
|
</el-link>
|
||||||
|
</strike>
|
||||||
|
<el-link type="success">
|
||||||
|
{{ list.newDisplayValue }}
|
||||||
|
</el-link>
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- </el-collapse-transition> -->
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FieldChangeLogs',
|
||||||
|
props: {
|
||||||
|
fieldAttributes: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
recordUuid: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoading: false,
|
||||||
|
currentKey: 0,
|
||||||
|
typeAction: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
language() {
|
||||||
|
return this.$store.getters.language
|
||||||
|
},
|
||||||
|
listLogsField() {
|
||||||
|
const log = this.$store.getters.getRecordLogs.entityLogs
|
||||||
|
if (log) {
|
||||||
|
const logsField = log.map(element => {
|
||||||
|
let type
|
||||||
|
if (!this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
|
||||||
|
type = 'success'
|
||||||
|
} else if (this.isEmptyValue(element.changeLogsList[0].newDisplayValue) && !this.isEmptyValue(element.changeLogsList[0].oldDisplayValue)) {
|
||||||
|
type = 'danger'
|
||||||
|
} else {
|
||||||
|
type = 'primary'
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...element,
|
||||||
|
columnName: element.changeLogsList[0].columnName,
|
||||||
|
type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return logsField.filter(field => field.columnName === this.fieldAttributes.columnName)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
isMobile() {
|
||||||
|
return this.$store.state.app.device === 'mobile'
|
||||||
|
},
|
||||||
|
classIsMobilePanel() {
|
||||||
|
if (this.isMobile) {
|
||||||
|
return 'panel-mobile'
|
||||||
|
}
|
||||||
|
return 'scroll-child'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sortSequence(itemA, itemB) {
|
||||||
|
return new Date().setTime(new Date(itemB.logDate).getTime()) - new Date().setTime(new Date(itemA.logDate).getTime())
|
||||||
|
},
|
||||||
|
translateDate(value) {
|
||||||
|
return this.$d(new Date(value), 'long', this.language)
|
||||||
|
},
|
||||||
|
showkey(key, index) {
|
||||||
|
if (key === this.currentKey && index === this.typeAction) {
|
||||||
|
this.currentKey = 1000
|
||||||
|
} else {
|
||||||
|
this.currentKey = key
|
||||||
|
this.typeAction = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.custom-tittle-popover {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="scss">
|
||||||
|
/**
|
||||||
|
* Separation between elements (item) of the form
|
||||||
|
*/
|
||||||
|
.el-form-item {
|
||||||
|
margin-bottom: 10px !important;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reduce the spacing between the form element and its label
|
||||||
|
*/
|
||||||
|
.el-form--label-top .el-form-item__label {
|
||||||
|
padding-bottom: 0px !important;
|
||||||
|
}
|
||||||
|
.panel-mobile {
|
||||||
|
height: 80vh;
|
||||||
|
}
|
||||||
|
</style>
|
@ -74,7 +74,7 @@
|
|||||||
/>
|
/>
|
||||||
<el-button slot="reference" type="text" style="color: #606266;">
|
<el-button slot="reference" type="text" style="color: #606266;">
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
|
<div v-if="!option.svg" style="margin-right: 5%;padding-top: 3%;">
|
||||||
<i :class="option.icon" style="font-weight: bolder;" />
|
<i :class="option.icon" style="font-weight: bolder;" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="margin-right: 5%">
|
<div v-else style="margin-right: 5%">
|
||||||
@ -91,7 +91,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<div v-if="isMobile" class="contents">
|
<div v-if="isMobile" class="contents">
|
||||||
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
|
<div v-if="!option.svg" style="margin-right: 5%;padding-top: 3%;">
|
||||||
<i :class="option.icon" style="font-weight: bolder;" />
|
<i :class="option.icon" style="font-weight: bolder;" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="margin-right: 5%">
|
<div v-else style="margin-right: 5%">
|
||||||
@ -142,10 +142,13 @@
|
|||||||
/>
|
/>
|
||||||
<el-button slot="reference" type="text" style="color: #606266;">
|
<el-button slot="reference" type="text" style="color: #606266;">
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
|
<div
|
||||||
|
v-if="!option.svg"
|
||||||
|
style="margin-right: 5%;padding-top: 3%;"
|
||||||
|
>
|
||||||
<i :class="option.icon" style="font-weight: bolder;" />
|
<i :class="option.icon" style="font-weight: bolder;" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="margin-right: 5%; padding-left: 8%;">
|
<div v-else style="margin-right: 5%;; padding-left: 2%;">
|
||||||
<svg-icon :icon-class="option.icon" style="margin-right: 5px;" />
|
<svg-icon :icon-class="option.icon" style="margin-right: 5px;" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -159,7 +162,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<div v-if="false" class="contents">
|
<div v-if="false" class="contents">
|
||||||
<div v-if="option.name !== $t('language')" style="margin-right: 5%;padding-top: 3%;">
|
<div v-if="!option.svg" style="margin-right: 5%;padding-top: 3%;">
|
||||||
<i :class="option.icon" style="font-weight: bolder;" />
|
<i :class="option.icon" style="font-weight: bolder;" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="margin-right: 5%">
|
<div v-else style="margin-right: 5%">
|
||||||
@ -297,6 +300,9 @@ export default {
|
|||||||
case this.$t('field.preference'):
|
case this.$t('field.preference'):
|
||||||
component = () => import('@/components/ADempiere/Field/contextMenuField/preference/index')
|
component = () => import('@/components/ADempiere/Field/contextMenuField/preference/index')
|
||||||
break
|
break
|
||||||
|
case this.$t('field.logsField'):
|
||||||
|
component = () => import('@/components/ADempiere/Field/contextMenuField/changeLogs/index')
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return component
|
return component
|
||||||
},
|
},
|
||||||
@ -554,18 +560,21 @@ export default {
|
|||||||
name: this.$t('field.info'),
|
name: this.$t('field.info'),
|
||||||
enabled: true,
|
enabled: true,
|
||||||
fieldAttributes: this.fieldAttributes,
|
fieldAttributes: this.fieldAttributes,
|
||||||
|
svg: false,
|
||||||
icon: 'el-icon-info'
|
icon: 'el-icon-info'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: this.$t('table.ProcessActivity.zoomIn'),
|
name: this.$t('table.ProcessActivity.zoomIn'),
|
||||||
enabled: this.isContextInfo,
|
enabled: this.isContextInfo,
|
||||||
fieldAttributes: this.fieldAttributes,
|
fieldAttributes: this.fieldAttributes,
|
||||||
|
svg: false,
|
||||||
icon: 'el-icon-files'
|
icon: 'el-icon-files'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: this.$t('language'),
|
name: this.$t('language'),
|
||||||
enabled: this.field.isTranslatedField,
|
enabled: this.field.isTranslatedField,
|
||||||
fieldAttributes: this.fieldAttributes,
|
fieldAttributes: this.fieldAttributes,
|
||||||
|
svg: true,
|
||||||
icon: 'language'
|
icon: 'language'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -574,6 +583,7 @@ export default {
|
|||||||
fieldAttributes: this.fieldAttributes,
|
fieldAttributes: this.fieldAttributes,
|
||||||
recordDataFields: this.recordDataFields,
|
recordDataFields: this.recordDataFields,
|
||||||
valueField: this.valueField,
|
valueField: this.valueField,
|
||||||
|
svg: false,
|
||||||
icon: 'el-icon-s-operation'
|
icon: 'el-icon-s-operation'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -581,7 +591,16 @@ export default {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
fieldAttributes: this.fieldAttributes,
|
fieldAttributes: this.fieldAttributes,
|
||||||
valueField: this.valueField,
|
valueField: this.valueField,
|
||||||
|
svg: false,
|
||||||
icon: 'el-icon-notebook-2'
|
icon: 'el-icon-notebook-2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: this.$t('field.logsField'),
|
||||||
|
enabled: true,
|
||||||
|
fieldAttributes: this.fieldAttributes,
|
||||||
|
valueField: this.valueField,
|
||||||
|
svg: true,
|
||||||
|
icon: 'tree-table'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -330,6 +330,7 @@ export default {
|
|||||||
info: 'Information',
|
info: 'Information',
|
||||||
calculator: 'Calculator',
|
calculator: 'Calculator',
|
||||||
preference: 'Preference',
|
preference: 'Preference',
|
||||||
|
logsField: 'Field Change Log',
|
||||||
codeTranslation: 'Translation Of ',
|
codeTranslation: 'Translation Of ',
|
||||||
container: {
|
container: {
|
||||||
help: 'Help',
|
help: 'Help',
|
||||||
|
@ -307,6 +307,7 @@ export default {
|
|||||||
calculator: 'Calculadora',
|
calculator: 'Calculadora',
|
||||||
preference: 'Preferencia',
|
preference: 'Preferencia',
|
||||||
codeTranslation: 'Traduccion de ',
|
codeTranslation: 'Traduccion de ',
|
||||||
|
logsField: 'Bitácora de Cambios',
|
||||||
container: {
|
container: {
|
||||||
help: 'Ayuda',
|
help: 'Ayuda',
|
||||||
description: 'Descripción'
|
description: 'Descripción'
|
||||||
|
@ -3,6 +3,7 @@ import {
|
|||||||
requestListWorkflowsLogs,
|
requestListWorkflowsLogs,
|
||||||
requestListWorkflows
|
requestListWorkflows
|
||||||
} from '@/api/ADempiere/window'
|
} from '@/api/ADempiere/window'
|
||||||
|
import { isEmptyValue } from '@/utils/ADempiere'
|
||||||
|
|
||||||
const initStateContainerInfo = {
|
const initStateContainerInfo = {
|
||||||
listworkflowLog: [],
|
listworkflowLog: [],
|
||||||
@ -34,6 +35,9 @@ const containerInfo = {
|
|||||||
}) {
|
}) {
|
||||||
const pageSize = 0
|
const pageSize = 0
|
||||||
const pageToken = 0
|
const pageToken = 0
|
||||||
|
if (isEmptyValue(tableName) && (isEmptyValue(recordId) || isEmptyValue(recordUuid))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
return requestListEntityLogs({
|
return requestListEntityLogs({
|
||||||
tableName,
|
tableName,
|
||||||
recordId,
|
recordId,
|
||||||
|
@ -110,6 +110,9 @@ export default {
|
|||||||
case this.$t('field.preference'):
|
case this.$t('field.preference'):
|
||||||
component = () => import('@/components/ADempiere/Field/contextMenuField/preference/index')
|
component = () => import('@/components/ADempiere/Field/contextMenuField/preference/index')
|
||||||
break
|
break
|
||||||
|
case this.$t('field.logsField'):
|
||||||
|
component = () => import('@/components/ADempiere/Field/contextMenuField/changeLogs/index')
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return component
|
return component
|
||||||
},
|
},
|
||||||
@ -355,6 +358,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
getRecord(value) {
|
getRecord(value) {
|
||||||
|
if (value && this.getTableName && this.recordId && this.isEmptyValue(this.gettersListRecordLogs)) {
|
||||||
|
this.$store.dispatch('listRecordLogs', {
|
||||||
|
tableName: this.getTableName,
|
||||||
|
recordId: this.recordId,
|
||||||
|
recordUuid: value.UUID
|
||||||
|
})
|
||||||
|
}
|
||||||
if (!this.isEmptyValue(this.windowMetadata.currentTab.tableName) && !this.isEmptyValue(value) && (!this.isEmptyValue(this.$route.query) && this.$route.query.typeAction === 'recordAccess')) {
|
if (!this.isEmptyValue(this.windowMetadata.currentTab.tableName) && !this.isEmptyValue(value) && (!this.isEmptyValue(this.$route.query) && this.$route.query.typeAction === 'recordAccess')) {
|
||||||
this.$store.commit('setRecordAccess', true)
|
this.$store.commit('setRecordAccess', true)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user