Add File
This commit is contained in:
313
frontend/src/views/system/permission/auth-tree/RowAuth.vue
Normal file
313
frontend/src/views/system/permission/auth-tree/RowAuth.vue
Normal file
@@ -0,0 +1,313 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import AuthTree from './AuthTree.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
const errorMessage = ref('')
|
||||
const logic = ref<'or' | 'and'>('or')
|
||||
const relationList = ref<any[]>([])
|
||||
|
||||
const svgRealinePath = computed(() => {
|
||||
const lg = relationList.value.length
|
||||
let a = { x: 0, y: 0, child: relationList.value }
|
||||
a.y = Math.floor(dfsXY(a, 0) / 2)
|
||||
if (!lg) return ''
|
||||
let path = calculateDepth(a)
|
||||
return path
|
||||
})
|
||||
|
||||
const svgDashinePath = computed(() => {
|
||||
const lg = relationList.value.length
|
||||
let a = { x: 0, y: 0, child: relationList.value }
|
||||
a.y = Math.floor(dfsXY(a, 0) / 2)
|
||||
if (!lg) return `M48 20 L68 20`
|
||||
let path = calculateDepthDash(a)
|
||||
return path
|
||||
})
|
||||
|
||||
const init = (expressionTree: any) => {
|
||||
const { logic: lg = 'or', items = [] } = expressionTree
|
||||
logic.value = lg
|
||||
relationList.value = dfsInit(items)
|
||||
}
|
||||
const submit = () => {
|
||||
errorMessage.value = ''
|
||||
emits('save', {
|
||||
logic: logic.value,
|
||||
items: dfsSubmit(relationList.value),
|
||||
errorMessage: errorMessage.value,
|
||||
})
|
||||
}
|
||||
const errorDetected = ({ filter_type, field_id, term, value }: any) => {
|
||||
if (!field_id) {
|
||||
errorMessage.value = t('permission.cannot_be_empty_')
|
||||
return
|
||||
}
|
||||
if (filter_type === 'logic') {
|
||||
if (!term) {
|
||||
errorMessage.value = t('permission.cannot_be_empty_de_ruler')
|
||||
return
|
||||
}
|
||||
if (!term.includes('null') && !term.includes('empty') && value === '') {
|
||||
errorMessage.value = t('permission.filter_value_can_null')
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
const dfsInit = (arr: any[]) => {
|
||||
const elementList: any[] = []
|
||||
arr.forEach((ele: any) => {
|
||||
const { sub_tree } = ele
|
||||
if (sub_tree) {
|
||||
const { items, logic } = sub_tree
|
||||
const child = dfsInit(items)
|
||||
elementList.push({ logic, child })
|
||||
} else {
|
||||
const { enum_value, field_id, filter_type, term, value, field } = ele
|
||||
const { name } = field || {}
|
||||
elementList.push({
|
||||
enum_value: enum_value.join(','),
|
||||
field_id,
|
||||
filter_type,
|
||||
term,
|
||||
value,
|
||||
name,
|
||||
})
|
||||
}
|
||||
})
|
||||
return elementList
|
||||
}
|
||||
const dfsSubmit = (arr: any[]) => {
|
||||
const items: any[] = []
|
||||
arr.forEach((ele) => {
|
||||
const { child = [] } = ele
|
||||
if (child.length) {
|
||||
const { logic } = ele
|
||||
const sub_tree = dfsSubmit(child)
|
||||
items.push({
|
||||
enum_value: [],
|
||||
field_id: '',
|
||||
filter_type: '',
|
||||
term: '',
|
||||
type: 'tree',
|
||||
value: '',
|
||||
sub_tree: { logic, items: sub_tree },
|
||||
})
|
||||
} else {
|
||||
const { enum_value, field_id, filter_type, term, value, name } = ele
|
||||
errorDetected({ enum_value, field_id, filter_type, term, value, name })
|
||||
if (field_id) {
|
||||
items.push({
|
||||
enum_value: enum_value ? enum_value.split(',') : [],
|
||||
field_id,
|
||||
filter_type,
|
||||
term,
|
||||
value,
|
||||
type: 'item',
|
||||
sub_tree: null,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
return items
|
||||
}
|
||||
const removeRelationList = () => {
|
||||
relationList.value = []
|
||||
}
|
||||
const getY: any = (arr: any[]) => {
|
||||
const [a] = arr
|
||||
if (a.child?.length) {
|
||||
return getY(a.child)
|
||||
}
|
||||
return a.y
|
||||
}
|
||||
const calculateDepthDash = (obj: any) => {
|
||||
const lg = obj.child?.length
|
||||
let path = ''
|
||||
if (!lg && Array.isArray(obj.child)) {
|
||||
const { x, y } = obj
|
||||
path += `M${48 + x * 68} ${y * 41.4 + 20} L${88 + x * 68} ${y * 41.4 + 20}`
|
||||
} else if (obj.child?.length) {
|
||||
let y = Math.max(dfsY(obj, 0), dfs(obj.child, 0) + getY(obj.child) - 1)
|
||||
let parent = (dfs(obj.child, 0) * 41.4) / 2 + (getY(obj.child) || 0) * 41.4
|
||||
const { x } = obj
|
||||
path += `M${24 + x * 68} ${parent} L${24 + x * 68} ${y * 41.4 + 20} L${
|
||||
64 + x * 68
|
||||
} ${y * 41.4 + 20}`
|
||||
obj.child.forEach((item: any) => {
|
||||
path += calculateDepthDash(item)
|
||||
})
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
const calculateDepth = (obj: any) => {
|
||||
const lg = obj.child.length
|
||||
if (!lg) return ''
|
||||
let path = ''
|
||||
const { x: depth, y } = obj
|
||||
obj.child.forEach((item: any, index: any) => {
|
||||
const { y: sibingLg, z } = item
|
||||
if (item.child?.length) {
|
||||
let parent = (dfs(obj.child, 0) * 41.4) / 2 + (getY(obj.child) || 0) * 41.4
|
||||
let children = (dfs(item.child, 0) * 41.4) / 2 + getY(item.child) * 41.4
|
||||
let path1 = 0
|
||||
let path2 = 0
|
||||
if (parent < children) {
|
||||
path1 = parent
|
||||
path2 = children
|
||||
} else {
|
||||
;[path1, path2] = [children, parent]
|
||||
}
|
||||
if (y >= sibingLg) {
|
||||
path1 = parent
|
||||
path2 = children
|
||||
}
|
||||
path += `M${24 + depth * 68} ${path1} L${24 + depth * 68} ${path2} L${
|
||||
68 + depth * 68
|
||||
} ${path2}`
|
||||
// path += a;
|
||||
path += calculateDepth(item)
|
||||
}
|
||||
if (!item.child?.length) {
|
||||
if (sibingLg >= y) {
|
||||
path += `M${24 + depth * 68} ${y * 40} L${24 + depth * 68} ${
|
||||
(sibingLg + 1) * 41.4 - 20.69921875
|
||||
} L${68 + depth * 68} ${(sibingLg + 1) * 41.4 - 20.69921875}`
|
||||
} else {
|
||||
path += `M${24 + depth * 68} ${
|
||||
(sibingLg +
|
||||
(lg === 1 && index === 0 ? 0 : 1) +
|
||||
(obj.child[index + 1]?.child?.length ? y - sibingLg - 1 : 0)) *
|
||||
41.4 +
|
||||
20 +
|
||||
(lg === 1 && index === 0 ? 26 : 0)
|
||||
} L${24 + depth * 68} ${
|
||||
(sibingLg + 1) * 41.4 - 20.69921875 - (lg === 1 && index === 0 ? (z || 0) * 1.4 : 0)
|
||||
} L${68 + depth * 68} ${
|
||||
(sibingLg + 1) * 41.4 - 20.69921875 - (lg === 1 && index === 0 ? (z || 0) * 1.4 : 0)
|
||||
}`
|
||||
}
|
||||
}
|
||||
})
|
||||
return path
|
||||
}
|
||||
const changeAndOrDfs = (arr: any, logic: any) => {
|
||||
arr.forEach((ele: any) => {
|
||||
if (ele.child) {
|
||||
ele.logic = logic === 'and' ? 'or' : 'and'
|
||||
changeAndOrDfs(ele.child, ele.logic)
|
||||
}
|
||||
})
|
||||
}
|
||||
const dfs = (arr: any[], count: any) => {
|
||||
arr.forEach((ele) => {
|
||||
if (ele.child?.length) {
|
||||
count = dfs(ele.child, count)
|
||||
} else {
|
||||
count += 1
|
||||
}
|
||||
})
|
||||
count += 1
|
||||
return count
|
||||
}
|
||||
const dfsY = (obj: any, count: any) => {
|
||||
obj.child.forEach((ele: any) => {
|
||||
if (ele.child?.length) {
|
||||
count = dfsY(ele, count)
|
||||
} else {
|
||||
count = Math.max(count, ele.y, obj.y)
|
||||
}
|
||||
})
|
||||
return count
|
||||
}
|
||||
const dfsXY = (obj: any, count: any) => {
|
||||
obj.child.forEach((ele: any) => {
|
||||
ele.x = obj.x + 1
|
||||
if (ele.child?.length) {
|
||||
let l = dfs(ele.child, 0)
|
||||
ele.y = Math.floor(l / 2) + count
|
||||
count = dfsXY(ele, count)
|
||||
} else {
|
||||
count += 1
|
||||
ele.y = count - 1
|
||||
}
|
||||
})
|
||||
count += 1
|
||||
return count
|
||||
}
|
||||
const addCondReal = (type: any, logic: any) => {
|
||||
relationList.value.push(
|
||||
type === 'condition'
|
||||
? {
|
||||
field_id: '',
|
||||
value: '',
|
||||
enum_value: '',
|
||||
term: '',
|
||||
filter_type: 'logic',
|
||||
name: '',
|
||||
}
|
||||
: { child: [], logic }
|
||||
)
|
||||
}
|
||||
const del = (index: any) => {
|
||||
relationList.value.splice(index, 1)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
submit,
|
||||
})
|
||||
const emits = defineEmits(['save'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="rowAuth">
|
||||
<auth-tree
|
||||
v-model:logic="logic"
|
||||
:relation-list="relationList"
|
||||
@del="(idx) => del(idx)"
|
||||
@add-cond-real="addCondReal"
|
||||
@remove-relation-list="removeRelationList"
|
||||
@change-and-or-dfs="(type) => changeAndOrDfs(relationList, type)"
|
||||
/>
|
||||
<svg width="388" height="100%" class="real-line">
|
||||
<path
|
||||
stroke-linejoin="round"
|
||||
stroke-linecap="round"
|
||||
:d="svgRealinePath"
|
||||
fill="none"
|
||||
stroke="#D9DCDF"
|
||||
stroke-width="0.5"
|
||||
></path>
|
||||
</svg>
|
||||
<svg width="388" height="100%" class="dash-line">
|
||||
<path
|
||||
stroke-linejoin="round"
|
||||
stroke-linecap="round"
|
||||
:d="svgDashinePath"
|
||||
fill="none"
|
||||
stroke="#D9DCDF"
|
||||
stroke-width="0.5"
|
||||
stroke-dasharray="4,4"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.rowAuth {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
position: relative;
|
||||
}
|
||||
.real-line,
|
||||
.dash-line {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user