|
@@ -14,83 +14,174 @@
|
|
|
:can-delete="false"
|
|
:can-delete="false"
|
|
|
@pageHandleChange="pageHandleChange"
|
|
@pageHandleChange="pageHandleChange"
|
|
|
>
|
|
>
|
|
|
|
|
+ <template #record_type="{ item }">
|
|
|
|
|
+ {{ item.record_type === 'redundancy' ? '疑似冗余' : '疑似变动' }}
|
|
|
|
|
+ </template>
|
|
|
<template #status="{ item }">
|
|
<template #status="{ item }">
|
|
|
- <v-chip small :color="item.status === 'active' ? 'success' : 'error'">
|
|
|
|
|
- {{ item.status === 'active' ? '启用' : '禁用' }}
|
|
|
|
|
|
|
+ <v-chip small :color="item.status === 'pending' ? 'warning' : item.status === 'resolved' ? 'success' : ''">
|
|
|
|
|
+ {{ item.status === 'pending' ? '待处理' : item.status === 'resolved' ? '已处理' : '已忽略' }}
|
|
|
</v-chip>
|
|
</v-chip>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+ <template #created_at="{ item }">
|
|
|
|
|
+ {{ formatDate(item.created_at) }}
|
|
|
|
|
+ </template>
|
|
|
<template #actions="{ item }">
|
|
<template #actions="{ item }">
|
|
|
- <v-btn color="primary" text class="mr-2" @click="onEdit(item)">编辑</v-btn>
|
|
|
|
|
- <v-btn color="error" text @click="onDelete(item)">删除</v-btn>
|
|
|
|
|
|
|
+ <v-btn color="success" text class="mr-2" @click="handleAction(item)">详情</v-btn>
|
|
|
|
|
+ <v-btn v-if="item.status === 'pending'" color="primary" text @click="handleAction(item)">处理</v-btn>
|
|
|
</template>
|
|
</template>
|
|
|
</m-table>
|
|
</m-table>
|
|
|
- <m-dialog title="数据去重" :visible.sync="show" fullscreen :footer="false">
|
|
|
|
|
- <edit-page v-if="show" ref="edit" :item-data="itemData" @success="show = false; init()"></edit-page>
|
|
|
|
|
- </m-dialog>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <edit-dialog :visible.sync="show" title="数据审核详情" fullscreen :footer="false">
|
|
|
|
|
+ <!-- 疑似冗余 -->
|
|
|
|
|
+ <redundancy-component
|
|
|
|
|
+ v-if="info?.record_type === 'redundancy'"
|
|
|
|
|
+ :info="info"
|
|
|
|
|
+ @selectCandidateMeta="val => candidateMetaId = val"
|
|
|
|
|
+ />
|
|
|
|
|
+ <!-- 疑似变动 -->
|
|
|
|
|
+ <change-component
|
|
|
|
|
+ v-if="info?.record_type === 'change'"
|
|
|
|
|
+ :info="info"
|
|
|
|
|
+ />
|
|
|
|
|
+ <template v-if="info?.status === 'pending'" #footer>
|
|
|
|
|
+ <v-divider></v-divider>
|
|
|
|
|
+ <v-card-actions>
|
|
|
|
|
+ <v-spacer></v-spacer>
|
|
|
|
|
+ <v-btn v-if="info?.record_type === 'redundancy'" text color="pink" class="mr-2" @click="handleSubmit(info, 'alias')">设为别名</v-btn>
|
|
|
|
|
+ <v-btn v-if="info?.record_type === 'redundancy'" text color="primary" class="mr-2" @click="handleSubmit(info, 'create_new')">创建新元数据</v-btn>
|
|
|
|
|
+ <v-btn v-if="info?.record_type === 'change'" text color="success" class="mr-2" @click="handleSubmit(info, 'accept_change')">接受变动</v-btn>
|
|
|
|
|
+ <v-btn v-if="info?.record_type === 'change'" text color="error" class="mr-2" @click="handleSubmit(info, 'reject_change')">拒绝变动</v-btn>
|
|
|
|
|
+ <v-btn text color="warning" @click="handleSubmit(info, 'ignore')">忽略</v-btn>
|
|
|
|
|
+ </v-card-actions>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </edit-dialog>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 创建新元数据 -->
|
|
|
|
|
+ <edit-dialog :visible.sync="createNew.show" title="创建新元数据" @submit="handleCreateNew">
|
|
|
|
|
+ <v-text-field
|
|
|
|
|
+ v-model="createNew.name_zh"
|
|
|
|
|
+ label="中文名称"
|
|
|
|
|
+ outlined
|
|
|
|
|
+ clearable
|
|
|
|
|
+ dense
|
|
|
|
|
+ hide-details
|
|
|
|
|
+ placeholder="请输入元数据中文名称"
|
|
|
|
|
+ />
|
|
|
|
|
+ </edit-dialog>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import MFilter from '@/components/Filter'
|
|
import MFilter from '@/components/Filter'
|
|
|
import MTable from '@/components/List/table.vue'
|
|
import MTable from '@/components/List/table.vue'
|
|
|
-import MDialog from '@/components/Dialog'
|
|
|
|
|
-import EditPage from './components/edit'
|
|
|
|
|
|
|
+import EditDialog from '@/components/Dialog'
|
|
|
|
|
+import RedundancyComponent from './components/redundancy.vue'
|
|
|
|
|
+import ChangeComponent from './components/change.vue'
|
|
|
|
|
+import { dataReviewList, dataReviewDetail, dataReviewResolve } from '@/api/dataDeduplication'
|
|
|
import { api } from '@/api/dataGovernance'
|
|
import { api } from '@/api/dataGovernance'
|
|
|
export default {
|
|
export default {
|
|
|
name: 'dataProcess',
|
|
name: 'dataProcess',
|
|
|
components: {
|
|
components: {
|
|
|
MFilter,
|
|
MFilter,
|
|
|
MTable,
|
|
MTable,
|
|
|
- MDialog,
|
|
|
|
|
- EditPage
|
|
|
|
|
|
|
+ EditDialog,
|
|
|
|
|
+ RedundancyComponent,
|
|
|
|
|
+ ChangeComponent
|
|
|
},
|
|
},
|
|
|
data () {
|
|
data () {
|
|
|
return {
|
|
return {
|
|
|
- loading: false,
|
|
|
|
|
show: false,
|
|
show: false,
|
|
|
|
|
+ loading: false,
|
|
|
filter: {
|
|
filter: {
|
|
|
list: [
|
|
list: [
|
|
|
- { type: 'textField', value: '', label: '关键词', key: 'title' }
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'textField',
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ label: '关键词',
|
|
|
|
|
+ key: 'keyword'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'autocomplete',
|
|
|
|
|
+ value: null,
|
|
|
|
|
+ label: '业务域',
|
|
|
|
|
+ itemValue: 'id',
|
|
|
|
|
+ itemText: 'name_zh',
|
|
|
|
|
+ key: 'business_domain_id',
|
|
|
|
|
+ items: []
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'autocomplete',
|
|
|
|
|
+ value: null,
|
|
|
|
|
+ label: '记录类型',
|
|
|
|
|
+ key: 'record_type',
|
|
|
|
|
+ items: [{ label: '疑似冗余', value: 'redundancy' }, { label: '疑似变动', value: 'change' }]
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'autocomplete',
|
|
|
|
|
+ value: 'pending',
|
|
|
|
|
+ label: '状态',
|
|
|
|
|
+ key: 'status',
|
|
|
|
|
+ items: [{ label: '待处理', value: 'pending' }, { label: '已处理', value: 'resolved' }, { label: '已忽略', value: 'ignored' }]
|
|
|
|
|
+ }
|
|
|
]
|
|
]
|
|
|
},
|
|
},
|
|
|
queryData: {
|
|
queryData: {
|
|
|
- title: null
|
|
|
|
|
|
|
+ keyword: null,
|
|
|
|
|
+ status: 'pending',
|
|
|
|
|
+ business_domain_id: null,
|
|
|
|
|
+ record_type: null
|
|
|
},
|
|
},
|
|
|
headers: [
|
|
headers: [
|
|
|
- { text: '中文名称', align: 'start', value: 'name_zh' },
|
|
|
|
|
- { text: '英文名称', align: 'start', value: 'name_en' },
|
|
|
|
|
|
|
+ { text: '中文名称', align: 'start', value: 'new_meta.name_zh' },
|
|
|
|
|
+ { text: '英文名称', align: 'start', value: 'new_meta.name_en' },
|
|
|
|
|
+ { text: '记录类型', align: 'center', value: 'record_type' },
|
|
|
{ text: '状态', align: 'center', value: 'status' },
|
|
{ text: '状态', align: 'center', value: 'status' },
|
|
|
- { text: '分类', align: 'center', value: 'category' },
|
|
|
|
|
- { text: '作者', align: 'center', value: 'leader' },
|
|
|
|
|
- { text: '机构', align: 'center', value: 'organization' },
|
|
|
|
|
- { text: '描述', align: 'start', value: 'describe' },
|
|
|
|
|
{ text: '创建时间', align: 'start', value: 'created_at' },
|
|
{ text: '创建时间', align: 'start', value: 'created_at' },
|
|
|
- { text: '更新时间', align: 'start', value: 'updated_at' },
|
|
|
|
|
{ text: '操作', align: 'start', value: 'actions' }
|
|
{ text: '操作', align: 'start', value: 'actions' }
|
|
|
],
|
|
],
|
|
|
- itemData: {},
|
|
|
|
|
items: [],
|
|
items: [],
|
|
|
pageInfo: {
|
|
pageInfo: {
|
|
|
size: 10,
|
|
size: 10,
|
|
|
current: 1
|
|
current: 1
|
|
|
},
|
|
},
|
|
|
- total: 0
|
|
|
|
|
|
|
+ candidateMetaId: null,
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+ info: {},
|
|
|
|
|
+ createNew: {
|
|
|
|
|
+ show: false,
|
|
|
|
|
+ name_zh: null,
|
|
|
|
|
+ params: {}
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
created () {
|
|
created () {
|
|
|
- // this.init()
|
|
|
|
|
|
|
+ this.getBusinessDomainList()
|
|
|
|
|
+ this.init()
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ // 获取业务域列表
|
|
|
|
|
+ async getBusinessDomainList () {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const { data } = await api.getBusinessDomainList2()
|
|
|
|
|
+ const businessDomain = this.filter.list.find(item => item.key === 'business_domain_id')
|
|
|
|
|
+ if (!data || !data?.length) {
|
|
|
|
|
+ businessDomain.items = []
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ businessDomain.items = data
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ this.$snackbar.error(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
async init () {
|
|
async init () {
|
|
|
this.loading = true
|
|
this.loading = true
|
|
|
try {
|
|
try {
|
|
|
- const { data } = await api.getDataFlowList({
|
|
|
|
|
- page: this.pageInfo.current,
|
|
|
|
|
- page_size: this.pageInfo.size,
|
|
|
|
|
- search: this.queryData.title || undefined
|
|
|
|
|
|
|
+ const { data } = await dataReviewList({
|
|
|
|
|
+ ...this.pageInfo,
|
|
|
|
|
+ ...this.queryData
|
|
|
})
|
|
})
|
|
|
- this.items = data.list
|
|
|
|
|
- this.total = data.pagination.total
|
|
|
|
|
|
|
+ this.items = data.records
|
|
|
|
|
+ this.total = data.total
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
this.$snackbar.error(error)
|
|
this.$snackbar.error(error)
|
|
|
} finally {
|
|
} finally {
|
|
@@ -102,29 +193,96 @@ export default {
|
|
|
this.pageInfo.current = 1
|
|
this.pageInfo.current = 1
|
|
|
this.init()
|
|
this.init()
|
|
|
},
|
|
},
|
|
|
- handleAdd () {
|
|
|
|
|
- this.itemData = {}
|
|
|
|
|
- this.show = true
|
|
|
|
|
- },
|
|
|
|
|
- async onEdit (item) {
|
|
|
|
|
- this.itemData = item
|
|
|
|
|
- this.show = true
|
|
|
|
|
- },
|
|
|
|
|
- onDelete ({ id }) {
|
|
|
|
|
- this.$confirm('提示', '是否删除该选项')
|
|
|
|
|
- .then(async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- await api.deleteDataFlow(id)
|
|
|
|
|
- this.$snackbar.success('删除成功')
|
|
|
|
|
- this.init()
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- this.$snackbar.error('删除失败')
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- },
|
|
|
|
|
pageHandleChange (page) {
|
|
pageHandleChange (page) {
|
|
|
this.pageInfo.current = page
|
|
this.pageInfo.current = page
|
|
|
this.init()
|
|
this.init()
|
|
|
|
|
+ },
|
|
|
|
|
+ // 详情、处理
|
|
|
|
|
+ async handleAction (item) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const { data } = await dataReviewDetail(item.id)
|
|
|
|
|
+ this.info = data || {}
|
|
|
|
|
+ this.show = true
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ this.$snackbar.error(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 作为新元数据创建
|
|
|
|
|
+ async handleCreateNew () {
|
|
|
|
|
+ if (!this.createNew.name_zh) {
|
|
|
|
|
+ this.$snackbar.warning('请输入元数据中文名称')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.createNew.params.payload = {
|
|
|
|
|
+ new_name_zh: this.createNew.name_zh
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ await dataReviewResolve(this.createNew.params)
|
|
|
|
|
+ this.$snackbar.success('操作成功')
|
|
|
|
|
+ this.createNew.show = false
|
|
|
|
|
+ this.show = false
|
|
|
|
|
+ this.init()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ this.$snackbar.error(error.message)
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ this.createNew = {
|
|
|
|
|
+ name_zh: null,
|
|
|
|
|
+ params: {},
|
|
|
|
|
+ show: false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 设为别名、接受变动、拒绝变动、忽略
|
|
|
|
|
+ async handleSubmit (item, action) {
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ id: item.id,
|
|
|
|
|
+ action: action,
|
|
|
|
|
+ resolved_by: this.$store.getters.userInfo.username,
|
|
|
|
|
+ notes: ''
|
|
|
|
|
+ }
|
|
|
|
|
+ // 作为新元数据创建
|
|
|
|
|
+ if (action === 'create_new') {
|
|
|
|
|
+ this.createNew = {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ name_zh: item.new_meta.name_zh,
|
|
|
|
|
+ params
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设为某候选元数据别名
|
|
|
|
|
+ if (action === 'alias') {
|
|
|
|
|
+ if (!this.candidateMetaId) {
|
|
|
|
|
+ this.$snackbar.warning('请选择候选元数据')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ params.payload = {
|
|
|
|
|
+ candidate_meta_id: this.candidateMetaId
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (action === 'accept_change') { // 接受变动
|
|
|
|
|
+ params.payload = {
|
|
|
|
|
+ meta_id: item?.old_meta?.meta_id
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ await dataReviewResolve(params)
|
|
|
|
|
+ this.$snackbar.success('操作成功')
|
|
|
|
|
+ this.show = false
|
|
|
|
|
+ this.init()
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ this.$snackbar.error(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ formatDate (date) {
|
|
|
|
|
+ if (!date) return '-'
|
|
|
|
|
+ const d = new Date(date)
|
|
|
|
|
+ if (isNaN(d.getTime())) return date
|
|
|
|
|
+ const year = d.getFullYear()
|
|
|
|
|
+ const month = String(d.getMonth() + 1).padStart(2, '0')
|
|
|
|
|
+ const day = String(d.getDate()).padStart(2, '0')
|
|
|
|
|
+ const hours = String(d.getHours()).padStart(2, '0')
|
|
|
|
|
+ const minutes = String(d.getMinutes()).padStart(2, '0')
|
|
|
|
|
+ const seconds = String(d.getSeconds()).padStart(2, '0')
|
|
|
|
|
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|