VUE条件树查询 自定义条件节点

之前实现过的简单的条件树功能如下图:

 经过最新客户需求确认,上述条件树还需要再次改造,以满足正常需要!

最新暴改后的功能如下红框所示:

 

页面功能

主页面逻辑代码:

<template>
    <div class="flex-col">
        <div id="container" class="c-view"></div>
        <el-button type="primary" plain style="width: 120px;" @click="doQuery">开始搜索</el-button>
    </div>
</template>
<script>
import { Graph } from '@antv/x6'
import Hierarchy from '@antv/hierarchy'
import '@antv/x6-vue-shape'
import querytrees from './queryCondition.vue' //这是我的vue组件,作为子节点展示在思维导图上
import queryrelative from './queryRelative.vue'

import { findItem, lastChild, setData, addChildNode, removeNode, randomId } from './fun'


export default {
    data() {
        return {
            graphData: {
                'id': '1',
                'type': 'original—add',
                'width': 80,
                'height': 30,
                "children": [
                    // {
                    //     "id": 0.28207584597793156,
                    //     "type": "queryrelative", //关系节点
                    //     "width": 44,
                    //     "height": 44,
                    //     "data": {
                    //         "relative": "and" //and并且 or或者
                    //     },
                    //     "children": [
                    //         {
                    //             "id": 0.32858917851150116,
                    //             "type": "condition-text", //条件节点
                    //             "width": 90,
                    //             "height": 44,
                    //             "level": 1, //判断它是第几级的条件节点
                    //             "edgeText": "",
                    //             "data": {
                    //                 "complete": true,
                    //                 "form": {} //你的业务数据
                    //             }
                    //         },
                    //         {
                    //             "id": 0.30546487070416783,
                    //             "type": "vue-shape", //自定义组件 业务节点
                    //             "width": 744,
                    //             "height": 44,
                    //             "level": 1,
                    //             "edgeText": "",
                    //             "data": {
                    //                 "complete": false,
                    //                 "form": {} //你的业务数据
                    //             }
                    //         }
                    //     ]
                    // }
                ]
            } //默认只有一个根节点
        }
    },
    mounted() {
        this.init()
    },
    methods: {
        //初始化⽅法
        doQuery() {
            let vft = (obj) => {
                let empty = obj.children.length == 0
                if (obj.type == 'relative') {
                    empty = false
                }
                else {
                    if (obj.data) {
                        empty = !obj.data.complete
                    }
                    else {
                        for (let i = 0; i < obj.children.length; i++) {
                            empty = vft(obj.children[i])
                            if (empty) {
                                break
                            }
                        }
                    }
                }

                return empty
            }


            if (vft(this.graphData)) {
                this.$modal.msgError("请先确认查询条件")
            }
            else {
                //组装查询语句
                // let cft = (obj) => {
                //     let stms = null
                //     if (obj.type == 'relative') {
                //         obj.children.forEach(e => {
                //             if (e.children && e.children.length > 0) {
                //                 e.children.forEach(p => {
                //                     let at = cft(p)
                //                     if (!stms) {
                //                         stms = at
                //                     }
                //                     else {
                //                         stms = stms + ' ' + e.data.relative + ' ' + at
                //                     }
                //                 })
                //             }
                //             else {
                //                 if (!stms) {
                //                     stms = e.data.form.topForm.value + e.data.form.conditionForm.value + e.data.form.valueForm.value
                //                 }
                //                 else {
                //                     let t = e.data.form.topForm.value + e.data.form.conditionForm.value + e.data.form.valueForm.value
                //                     stms = stms + ' ' + obj.data.relative + ' ' + t
                //                 }
                //             }
                //         })
                //     }
                //     else {
                //         obj.children.forEach(p => {
                //             debugger
                //             let at = cft(p)
                //             if (!stms) {
                //                 stms = at
                //             }
                //             else {
                //                 stms = stms + p.data.relative + at
                //             }
                //         })
                //     }

                //     return stms
                // }
                this.$emit('input', { sql: "", tree: this.graphData.children })
            }
        },
        init() {
            let self = this
            Graph.registerNode(
                'original—add',
                {
                    inherit: 'rect',
                    width: 80,
                    height: 30,
                    label: '+纳入条件',
                    attrs: { //样式代码
                        body: {
                            rx: 4,
                            ry: 4,
                            stroke: '#037AFB',
                            fill: '#037AFB',
                            strokeWidth: 1,
                            event: 'add:original' //根节点点击事件
                        },
                        label: {
                            fontSize: 14,
                            fill: 'white',
                            event: 'add:original'//根节点点击事件
                        }
                    }
                },
                true,
            )

            //自定义vue 业务节点
            Graph.registerVueComponent('queryrelative',
                {
                    template: `<queryrelative/>`,
                    components: {
                        queryrelative
                    }
                },
                true
            )

            //自定义vue 业务节点
            Graph.registerVueComponent('querytrees',
                {
                    template: `<querytrees/>`,
                    components: {
                        querytrees
                    }
                },
                true
            )
            // 弯的边
            Graph.registerEdge(
                'mindmap-edge',
                {
                    inherit: 'edge',
                    router: {
                        name: 'manhattan',
                        args: {
                            startDirections: ['right'],
                            endDirections: ['left']
                        }
                    },
                    connector: {
                        name: 'rounded'
                    },
                    attrs: {
                        line: {
                            targetMarker: '',
                            stroke: '#A2B1C3',
                            strokeWidth: 2
                        }
                    }, //样式代码
                    zIndex: 0
                },
                true,
            )

            // 直的边
            Graph.registerEdge(
                'straight-edge',
                {
                    inherit: 'edge',
                    attrs: {}, //样式代码
                    zIndex: 0
                },
                true,
            )

            //新增限定条件
            Graph.registerNodeTool('add-condition',
                {
                    inherit: 'button', // 基类名称,使用已经注册的工具名称。
                    markup: [
                        {
                            tagName: 'rect',
                            selector: 'button',
                            attrs: {
                                fill: '#296FFF',
                                cursor: 'pointer',
                                width: 32,
                                height: 28
                            }
                        },
                        {
                            tagName: 'image',
                            selector: 'icon',
                            attrs: {
                                'xlink:href': 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SYCuQ6HHs5cAAAAAAAAAAAAAARQnAQ',
                                cursor: 'pointer',
                                width: 16,
                                height: 16,
                                x: 8,
                                y: 6
                            }
                        }
                    ],
                    x: '100%',
                    y: '100%',
                    offset: { x: -32, y: -72 },
                    onClick({ cell }) {
                        const { id } = cell
                        const dataItem = findItem(this.graphData, id).node
                        const lastNode = lastChild(dataItem)//找到当前node的最后一级,添加
                        if (addChildNode(lastNode.id, '并且', graphData)) {
                            render(graph, this.graphData)
                        }
                    }
                }, true)

            //关系节点 点击增加条件事件
            Graph.registerNodeTool('relative:add-condition', {
                inherit: 'button', // 基类名称,使用已经注册的工具名称。
                markup: [
                    {
                        tagName: 'rect',
                        selector: 'button',
                        attrs: {
                            fill: '#296FFF',
                            cursor: 'pointer',
                            width: 32,
                            height: 28
                        }
                    },
                    {
                        tagName: 'image',
                        selector: 'icon',
                        attrs: {
                            'xlink:href': 'https://gw.alipayobjects.com/mdn/rms_43231b/afts/img/A*SYCuQ6HHs5cAAAAAAAAAAAAAARQnAQ',
                            cursor: 'pointer',
                            width: 16,
                            height: 16,
                            x: 8,
                            y: 6
                        }
                    }
                ],
                x: '100%',
                y: '100%',
                offset: { x: -32, y: -72 },
                onClick({ cell }) {
                    const { id } = cell
                    if (addChildNode(id, '', this.graphData)) render(graph, this.graphData)
                }
            }, true)

            //边增加条件
            Graph.registerEdgeTool('edge:add-condition', {
                inherit: 'button', // 基类名称,使用已经注册的工具名称。
                markup: [
                    {
                        tagName: 'rect',
                        selector: 'button',
                        attrs: {
                            fill: '#296FFF',
                            cursor: 'pointer',
                            fontSize: 16,
                            width: 20,
                            height: 20,
                            rx: 2,
                            ry: 2,
                            stroke: '#296FFF',
                            strokeWidth: 1
                        }
                    },
                    {
                        tagName: 'text',
                        selector: 'label',
                        textContent: '+',
                        attrs: {
                            x: 5,
                            y: 15,
                            fontSize: 16,
                            cursor: 'pointer',
                            fill: '#ffff'
                        }
                    }
                ],
                distance: '100%',
                offset: { y: -10, x: -10 },
                onClick({ cell }) {
                    debugger
                    const { node, parent } = findItem(self.graphData, cell.target.cell)
                    const newId = randomId()
                    const childP = {
                        children: [node],
                        id: newId,
                        type: 'vue-shape',
                        width: 80,
                        height: 40,
                        level: 2,
                        component: 'queryrelative',
                        data: { relative: 'and', type: 'document', options: [{ label: '同病人', value: '1' }, { label: '同病历', value: '2' }, { label: '同报告', value: '3' }], defaultValue: '1' }
                    }
                    const currentIndex = parent.children.findIndex(item => item.id === node.id)
                    parent.children[currentIndex] = childP
                    let anode = addChildNode(newId, '', self.graphData)
                    anode.width = 550
                    anode.component = 'querytrees'
                    if (anode) {
                        render(graph, self.graphData)
                    }
                }
            }, true)

            let graph = new Graph({
                background: { color: '#fff' },
                container: document.getElementById('container'),
                panning: { enabled: true },
                selecting: { enabled: true },
                keyboard: { enabled: true },
                grid: true,
                mousewheel: {
                    enabled: true,
                    modifiers: ['ctrl', 'meta']
                },
                interacting: { nodeMovable: false }
            })

            const render = (graph, graphData) => {
                const result = Hierarchy.mindmap(graphData, {
                    direction: 'H',
                    getHeight(d) {
                        return d.height
                    },
                    getWidth(d) {
                        return d.width
                    },
                    getHGap() {
                        return 40
                    },
                    getVGap() {
                        return 20
                    },
                    getSide: () => {
                        return 'right'
                    }
                })
                const cells = []
                const traverse = (hierarchyItem, parentId) => {
                    if (hierarchyItem) {
                        const { data, children } = hierarchyItem
                        const node = graph.createNode({
                            ...data,
                            shape: data.type,
                            x: hierarchyItem.x,
                            y: hierarchyItem.y,
                            component: data.component
                        })
                        if (parentId) {
                            //有父级则插入父级
                            const parent = graph.getCellById(parentId)
                            parent && parent.addChild(node)
                        }

                        cells.push(node)
                        //子节点边
                        if (children) {
                            children.forEach((item) => {
                                const { id, data: itemData } = item
                                cells.push(
                                    graph.createEdge({
                                        shape: itemData.edgeText ? 'straight-edge' : 'mindmap-edge',
                                        source: {
                                            cell: hierarchyItem.id,
                                            anchor: {
                                                name: itemData.type === 'topic-child' ? 'right' : 'center',
                                                args: {
                                                    dx: itemData.type === 'topic-child' ? -16 : '25%'
                                                }
                                            }
                                        },
                                        target: { cell: id, anchor: { name: 'left' } },
                                        labels: [{ attrs: { text: { text: itemData.edgeText || '' } } }]
                                    }),
                                )
                                traverse(item, node.id)
                            })
                        }
                    }
                }
                traverse(result)
                graph.resetCells(cells)
                // graph.scaleContentToFit({ maxScale: 1 })
                graph.centerContent()
            }
            //根结点添加
            graph.on('add:original', ({ node }) => {
                debugger
                if (this.graphData.children.length == 0) {
                    const { id } = node
                    let anode = addChildNode(id, '', this.graphData)
                    anode.id = randomId()
                    anode.type = "vue-shape" //自定义组件 业务节点
                    anode.width = 550
                    anode.height = 44
                    anode.level = 1
                    anode.edgeText = ""
                    anode.data = {
                        complete: false,
                        form: {
                            formType: 1,
                            topForm: {
                                label: '',
                                value: ''
                            },
                            conditionForm: {},
                            valueForm: {
                                label: '',
                                value: ''
                            },
                            extra: {}
                        } //你的业务数据
                    }
                    anode.component = 'querytrees'
                    anode.children = []
                    if (anode) {
                        render(graph, this.graphData)
                    }
                }
                else if (this.graphData.children.lastObject().type != 'relative') {
                    const { id } = node
                    let tlist = this.graphData.children
                    this.graphData.children = []

                    let anode = addChildNode(id, '', this.graphData)
                    anode.type = "vue-shape"
                    anode.width = 80;
                    anode.height = 40;
                    anode.level = 1;
                    anode.component = 'queryrelative';
                    anode.data = {
                        "relative": "and" //and并且 or或者
                        , options: [{ label: '同病人', value: '1' }, { label: '同病历', value: '2' }, { label: '同报告', value: '3' }], defaultValue: '1'
                    }

                    let xlist = []
                    tlist.forEach(element => {
                        element.id = randomId(),
                            xlist.push(element)
                    });
                    xlist.push({
                        id: randomId(),
                        type: "vue-shape", //自定义组件 业务节点
                        width: 550,
                        height: 44,
                        level: 1,
                        edgeText: "",
                        component: 'querytrees',
                        data: {
                            complete: false,
                            form: {
                                formType: 1,
                                topForm: {
                                    label: '',
                                    value: ''
                                },
                                conditionForm: {},
                                valueForm: {
                                    label: '',
                                    value: ''
                                },
                                extra: {}
                            } //你的业务数据
                        }
                    })
                    anode.children = xlist
                    if (anode) {
                        render(graph, this.graphData)
                    }
                }
                else {
                    const { id } = node
                    let tlist = this.graphData.children
                    this.graphData.children = []

                    let anode = addChildNode(id, '', this.graphData)
                    anode.type = "vue-shape"
                    anode.component = 'queryrelative'
                    anode.width = 80;
                    anode.height = 40;
                    anode.level = 1;
                    anode.data = {
                        "relative": "and" //and并且 or或者
                    }

                    let xlist = []
                    tlist.forEach(x => {
                        xlist.push(x)
                    })
                    xlist.push({
                        id: randomId(),
                        type: "vue-shape", //自定义组件 业务节点
                        width: 550,
                        height: 44,
                        level: 1,
                        edgeText: "",
                        component: 'querytrees',
                        data: {
                            complete: false,
                            form: {
                                formType: 1,
                                topForm: {
                                    label: '',
                                    value: ''
                                },
                                conditionForm: {},
                                valueForm: {
                                    label: '',
                                    value: ''
                                },
                                extra: {}
                            } //你的业务数据
                        }
                    })
                    anode.children = xlist
                    // tlist.push(anode)
                    this.graphData.children = [anode]
                    if (anode) {
                        render(graph, this.graphData)
                    }
                }
            })
            //节点数据变化
            graph.on('node:change:data', ({ cell, node }) => {
                debugger
                setData(self.graphData, node.id, node.data)
                const dataItem = node.getData()
                cell.setData({ ...dataItem, complete: dataItem.complete, isEdit: true })
            })
            graph.on('node:removed', ({ cell, node }) => {
                removeNode(node.id, self.graphData)
                render(graph, self.graphData)
            })
            //节点聚焦 增加工具栏目
            graph.on('node:mouseenter', ({ node }) => {
                // if (['condition-text', 'relative'].includes(node.shape)) {
                //     if (!this.isExistUnComplete()) { //判断当前是否有未填写完成的vue组件节点
                //         if (node.shape === 'condition-text') {
                //             node.setAttrs({ body: { fill: '#E9F0FF', stroke: '#296FFF' } })
                //         }
                //         this.addTool(node)
                //     }
                // }
            })
            //节点失焦 移除工具栏
            graph.on('node:mouseleave', ({ node }) => {
                // if (['condition-text', 'relative'].includes(node.shape)) {
                //     if (node.shape === 'condition-text') {
                //         node.setAttrs({ body: { stroke: '#CCC', fill: '#fff' } })
                //     }
                //     this.removeTool(node)
                // }
            })
            //边 悬浮事件
            graph.on('edge:mouseenter', ({ edge }) => {
                //不是 根结点下第一个关系节点 并且 没有未完成的节点 可添加
                const targetNode = graph.getCellById(edge.target.cell)
                const targetNodeData = findItem(this.graphData, edge.target.cell).node
                const isChild = targetNodeData.level ? targetNodeData.level === 1 : true //不是限定节点 可添加
                if (!(edge.source.cell === '1' && targetNode.shape === 'relative') && isChild && !this.isExistUnComplete()) {
                    edge.addTools(['edge:add-condition'])
                }
            })
            //边 失焦
            graph.on('edge:mouseleave', ({ edge }) => {
                if (!this.isExistUnComplete()) {//判断当前是否有未填写完成的vue组件节点
                    edge.removeTools(['edge:add-condition'])
                }
            })
            render(graph, this.graphData)
        },
        isExistUnComplete() {
            return false
        }
    }
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.flex-col {
    width: 100%;
    height: 310px;

    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.c-view {
    height: 260px;
    width: 100%;
}

.topic-image {
    visibility: hidden;
    cursor: pointer;
}

.x6-node:hover .topic-image {
    visibility: visible;
}

.x6-node-selected rect {
    stroke-width: 2px;
}
</style>

涉及到的组件一 

queryCondition.vue

<template>
    <div class="condition" :class="[complete ? 'ny-view' : 'dy-view']" :style="{ width: lineTextWidth + 'px' }">
        <el-form v-if="!complete" ref="form" :model="form" label-width="0" inline>
            <el-row :gutter="10">
                <el-col :span="(form.formType != 2) ? 9 : 6">
                    <el-form-item class="w-100 flex-row">
                        <el-select class="search-options" v-model="form.topForm.value" filterable clearable
                            placeholder="请选择" :loading="remoteLoading" remote :remote-method="searchKeysAction">
                            <el-option v-for="item in topFormOptions" :key="item.formItemId" :label="item.label"
                                :value="item.formItemId">
                            </el-option>
                        </el-select>
                        <el-button class="search-icon" icon="el-icon-plus" @click="showCheck = true"></el-button>
                    </el-form-item>
                </el-col>
                <el-col :span=5>
                    <el-form-item class="w-100">
                        <el-select v-model="form.conditionForm.value" placeholder="关系" @change="conditionFormChanged">
                            <el-option v-for="item in optionsList()" :key="item.label" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="(form.formType != 2) ? 5 : 8">
                    <el-form-item class="w-100">
                        <el-select v-if="form.formType == 3" v-model="form.valueForm.value" placeholder="请选择">
                            <el-option v-for="item in valuesOptions" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                        <div v-else-if="form.formType == 2" :key="renderKey">
                            <el-date-picker class="w-100"
                                v-if="(form.conditionForm.value != '9' && form.conditionForm.value != '10')"
                                v-model="form.valueForm.value" format="yyyy.MM.dd" type="date"
                                placeholder="选择日期"></el-date-picker>
                            <el-date-picker class="w-100" v-else v-model="form.valueForm.value" format="yy.MM.dd"
                                type="daterange" range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间">
                            </el-date-picker>
                        </div>
                        <el-input class="w-100" v-else v-model="form.valueForm.value" placeholder="对比值"></el-input>
                    </el-form-item>
                </el-col>
                <el-col :span=5>
                    <el-form-item class="w-100">
                        <div class="flex-row w-100">
                            <el-button type="danger" @click="onDelAction">删除</el-button>
                            <el-button type="primary" @click="onSubmit">确定</el-button>
                        </div>
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
        <div v-else :style="{ width: lineTextWidth + 'px' }" @click="reEditAction">
            <span class="top-view">{{ topText }}</span>
            <span class="con-view">{{ conditionText }}</span>
            <span class="val-view">{{ valueText }}</span>
        </div>
        <check-crf v-if="showCheck" @input="itemSelected" :inTreeQuery="true" :workSingle="true" />
    </div>
</template>

<script>

// import { elForm, elFormItem, elInput, elSelect, elOption } from 'element-ui'//在这需要再次按需引入对应组件
import { getTextWidth, setData, removeNode, randomId } from "./fun"
import CheckCrf from '../crf/components/check-crf.vue'
import project from '../../api/project/project'

export default {
    name: 'queryCondition',
    inject: ["getGraph", "getNode"],
    components: { CheckCrf },
    data() {
        return {
            showCheck: false,
            complete: false,
            form: {
                //1数值型条件 conditionForm为等于、不等于、大于、大于等于、小于、小于等于、为空、不为空
                //2日期条件 conditionForm为晚于、不晚于、早于、不早于、时间段内、时间段外、为空、不为空
                //3复选框 conditionForm为是、否
                //4其他类型 conditionForm为包含、不包含、等于、不等于、为空、不为空

                formType: 1,
                topForm: {
                    label: '',
                    value: ''
                },
                conditionForm: {
                    label: '',
                    value: ''
                },
                valueForm: {
                    label: '',
                    value: '',
                },
                //原始组件所有属性
                extra: {}
            },
            topFormOptions: [],
            lineTextWidth: 550,
            topText: '用户姓名',
            conditionText: '包含',
            valueText: 'dudu',
            renderKey: randomId(),
            valuesOptions: [],
            remoteLoading: false
        }
    },
    mounted() {
        const self = this;
        let node = this.getNode()
        const data = node.getData();
        if (data) {
            this.complete = data.complete
            this.form = data.form

            this.topText = this.form.topForm.label
            this.conditionText = this.form.conditionForm.label

            if (this.form.formType == 3) {
                this.valueText = this.form.valueForm.label
            }
            else {
                this.valueText = this.form.valueForm.value
            }
        }
        // 监听数据改变事件
        // node.on("change:data", ({ current }) => {
        //     debugger
        // });
        this.renderUI()
    },
    methods: {
        conditionFormChanged(e) {
            if (this.form.formType == 2) {
                //必须强制刷新一下对应的DOM,否则会出现日期选择框弹出位置错误或者无法弹出的问题
                this.renderKey = randomId()
                this.form.valueForm.value = ""
            }
        },
        searchKeysAction(query) {
            if (query !== '') {
                this.remoteLoading = true;
                project.getCrfKeys(query).then(res => {
                    res.forEach(element => {
                        element.formItemId = element.code
                    });
                    this.remoteLoading = false
                    this.topFormOptions = res
                })
            } else {
                this.options = [];
            }
        },
        itemSelected(raw) {
            let e = raw.firstObject()
            let cp = e.component
            let label = cp.config.label
            let fid = e.code

            this.form.topForm.label = label
            this.form.topForm.value = fid
            this.form.extra = e
            if (!this.topFormOptions.containsObject(fid)) {
                let p = { ...e, label: label, formItemId: fid }

                this.topFormOptions.addObject(p)
            }

            if (cp.typeId === 'INPUT') {
                this.form.formType = 1
            }
            else if (cp.typeId === 'DATE') {
                this.form.formType = 2
            }
            else if (cp.typeId === 'SELECT' || cp.typeId === 'CHECKBOX' || cp.typeId === 'RADIO') {
                this.form.formType = 3
                this.valuesOptions = cp.config.options
            }
            else {
                this.form.formType = 4
            }

            this.showCheck = false
        },
        renderUI() {
            let width = getTextWidth(this.topText + this.conditionText + this.valueText, 14, "Arial, Helvetica, sans-serif")
            this.lineTextWidth = width;
            this.lineTextWidth += 10;
            this.lineTextWidth += 20;
        },
        optionsList() {
            if (this.form.formType == 1) {
                let opList = [
                    { label: '包含', value: '11' },
                    { label: '等于', value: '7' },
                    { label: '不等于', value: '8' },
                    { label: '大于', value: '3' },
                    { label: '大于等于', value: '4' },
                    { label: '小于', value: '5' },
                    { label: '小于等于', value: '6' },
                    { label: '为空', value: '2' },
                    { label: '不为空', value: '1' }
                ]
                return opList
            }
            else if (this.form.formType == 2) {
                let opList = [
                    { label: '等于', value: '7' },
                    { label: '不等于', value: '8' },
                    { label: '晚于', value: '5' },
                    { label: '不晚于', value: '4' },
                    { label: '早于', value: '3' },
                    { label: '不早于', value: '6' },
                    { label: '时间段内', value: '9' },
                    { label: '时间段外', value: '10' },
                    { label: '为空', value: '2' },
                    { label: '不为空', value: '1' }
                ]
                return opList
            }
            else if (this.form.formType == 3) {
                let opList = [
                    { label: '等于', value: '7' },
                    { label: '不等于', value: '8' },
                ]
                return opList
            }
            else {
                let opList = [
                    { label: '包含', value: '11' },
                    { label: '不包含', value: '12' },
                    { label: '等于', value: '7' },
                    { label: '不等于', value: '8' },
                    { label: '为空', value: '2' },
                    { label: '不为空', value: '1' }
                ]
                return opList
            }
        },
        onSubmit() {
            let flabel = this.optionsList().filter(p => p.value == this.form.conditionForm.value).firstObject()?.label
            let ext = this.topFormOptions.filter(p => p.formItemId == this.form.topForm.value)
            let topText = ext.firstObject()?.label
            let vtext = this.form.valueForm.value
            let tipText = null
            if (!topText || topText.length == 0) {
                tipText = '未选择条件字段'
            }
            else if (!flabel || flabel.length == 0) {
                tipText = '未选择条件关系'
            }
            else if (!vtext || vtext.length == 0) {
                tipText = '未选择条件对比值'
            }

            if (tipText) {
                this.$modal.msgError(tipText)
            }
            else {
                this.form.conditionForm.label = flabel
                this.topText = topText
                this.conditionText = flabel

                if (this.form.formType == 3) {
                    vtext = this.valuesOptions.filter(p => p.value == this.form.valueForm.value)[0].label
                    this.form.valueForm.label = vtext
                }
                this.valueText = vtext
                this.form.extra = ext.firstObject()

                this.complete = true
                let node = this.getNode()
                const dataItem = {
                    complete: this.complete,
                    form: {
                        ...this.form
                    }
                }
                let graphData = node.parent
                setData(graphData, node.id, dataItem)

                this.renderUI()

                let data = {
                    mapDbName: this.form.extra.mapDbName,
                    mapTblName: this.form.extra.mapTblName,
                    dataDbName: this.form.extra.dataDbName,
                    dataTblName: this.form.extra.dataTblName,
                    dataColName: this.form.extra.dataColName,
                    fieldType: this.form.extra.fieldType,
                    fieldSource: this.form.extra.fieldSource,
                    code: this.form.topForm.value,
                    operator: this.form.conditionForm.value,
                    value: this.form.valueForm.value
                }

                let cv = parseInt(this.form.conditionForm.value)
                if (this.form.formType == 2 && ((cv == 9 || cv == 10)))
                {
                    data.start = this.form.valueForm.value[0].date2text("yyyy-MM-dd") + " 00:00:00"
                    data.end = this.form.valueForm.value[1].date2text("yyyy-MM-dd") + " 23:59:59"
                }
                project.queryTreeAction(data).then(res => {

                })
            }
        },
        onDelAction() {
            let graph = this.getGraph()
            let node = this.getNode()

            this.$confirm('确定删除此条件?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then((cmd) => {
                if (cmd == 'confirm') {
                    graph.removeNode(node.id)
                }
            })
        },
        reEditAction() {
            this.complete = false
        },
        checkBtnGroupClose() {
            this.showCheck = false
        }
    }
}
</script>

<style lang="scss" scoped>
.condition {
    padding: 0px 10px;
    height: 100%;
    background: white;
    border-radius: 6px;
    border: 1px solid #EFF4FF;

    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.dy-view {
    min-width: 550px;
    background: #EFF4FF;
    border: 1px solid #5F95FF;
}


.ny-view {
    width: auto;
}


.flex-row {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.top-view {
    white-space: nowrap;
    color: black;
    font-size: 14px;
    font-family: Arial, Helvetica, sans-serif;
}

.con-view {
    color: gray;
    font-size: 14px;
    padding: 0px 5px;
    font-family: Arial, Helvetica, sans-serif;
}

.val-view {
    color: black;
    font-size: 14px;
    font-family: Arial, Helvetica, sans-serif;
}


.search-options {
    width: calc(100% - 34px);
}

.search-icon {
    position: absolute;
    border-left: none;
    width: 32px;
    height: 32px;
    margin-left: -4px;
    background-color: #F5F7FA;
}

::v-deep {
    .el-form-item--small {
        margin: 0px;
        vertical-align: middle !important;
    }

    .el-button--small {
        padding-left: 10px;
        padding-right: 10px;
    }

    .el-input-group__append {
        padding-right: 15px;
    }

    .el-range__close-icon {
        display: none;
    }

    .el-checkbox--small {
        height: auto !important;
    }
}
</style>

涉及到组件二

queryRelative.vue

<template>
    <div class="condition dy-view flex-row">
        <div class="flex-row l-flex l-hover" style="position: relative;" :class="{ 'nl-flex': relative == 'or' }">
            <el-popover placement="bottom" ref="refPop" width="80" trigger="hover" class="h-100 flex-row"
                popper-class="pop-grid-view">
                <el-radio-group v-model="radio" @input="radioChanged">
                    <el-radio :label="item.value" v-for="item in optionsList">{{ item.label }}</el-radio>
                </el-radio-group>
                <el-image slot="reference" style="width: 20px; height: 20px"
                    :src="require('@/assets/images/sameR.png')"></el-image>
            </el-popover>
            <el-image class="m-view" :src="require('@/assets/images/downArrow.png')"></el-image>
        </div>
        <div class="flex-row r-flex label-text" :class="{ 'nr-flex': relative == 'or' }" @click="relativeChanged">
            {{ relative == 'or' ? '或者' : '并且' }}
        </div>
    </div>
</template>

<script>

// import { elForm, elFormItem, elInput, elSelect, elOption } from 'element-ui'//在这需要再次按需引入对应组件
import { getTextWidth, setData, removeNode, randomId } from "./fun"

export default {
    name: 'queryRelative',
    inject: ["getGraph", "getNode"],
    components: {},
    data() {
        return {
            radio: '1',
            relative: 'and',
            optionsList: [],
        }
    },
    mounted() {
        let node = this.getNode()
        const data = node.getData();

        this.relative = data.relative
        this.optionsList = data.options
        this.radio = data.defaultValue
    },
    methods: {
        radioChanged() {
            this.$refs['refPop'][0].doClose()
        },
        relativeChanged() {
            this.relative = this.relative == 'and' ? 'or' : 'and'

            let node = this.getNode()
            const dataItem = {
                relative:this.relative,
                defaultValue:this.radio
            }
            let graphData = node.parent
            setData(graphData, node.id, dataItem)
        }
    }
}
</script>

<style lang="scss" scoped>
.condition {
    padding: 0px;
    height: 100%;
    border-radius: 5px;
    width: 80px;
    height: 40px;
    background-color: white;
    overflow: hidden;

    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.flex-row {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}

.l-flex {
    width: 35px;
    height: 100%;
    background-color: rgb(109, 162, 243);

    &:hover {
        background-color: rgb(129, 182, 255);
    }
}


.r-flex {
    width: 45px;
    height: 100%;
    background-color: rgb(154, 188, 247);

    &:hover {
        background-color: rgb(129, 182, 255);
    }
}

.nl-flex {
    background-color: rgb(41, 195, 193);

    &:hover {
        background-color: rgb(61, 215, 213);
    }
}

.nr-flex {
    background-color: rgb(102, 213, 233);

    &:hover {
        background-color: rgb(61, 215, 213);
    }
}

.label-text {
    color: white;
    font-size: 13px;
}


.m-view {
    position: absolute;
    right: 3px;
    bottom: 3px;
    width: 6px;
    height: 6px;
}

::v-deep {
    .el-form-item--small {
        margin: 0px;
        vertical-align: middle !important;
    }

    .el-button--small {
        padding-left: 10px;
        padding-right: 10px;
    }

    .el-input-group__append {
        padding-right: 15px;
    }

    .el-range__close-icon {
        display: none;
    }

    .el-checkbox--small {
        height: auto !important;
    }

    .el-radio {
        line-height: 1.5;
    }

    .el-radio__label {
        padding-left: 5px;
    }
}
</style>


<style lang="scss">
.pop-grid-view.el-popper {
    min-width: 90px;
}
</style>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/948176.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游戏如何检测iOS越狱

不同于安卓的开源生态&#xff0c;iOS一直秉承着安全性更高的闭源生态&#xff0c;系统中的硬件、软件和服务会经过严格审核和测试&#xff0c;来保障安全性与稳定性。 据FairGurd观察&#xff0c;虽然iOS系统具备一定的安全性&#xff0c;但并非没有漏洞&#xff0c;如市面上…

GraphRAG vs 传统 RAG:如何通过知识图谱提升 AI 检索能力

相比传统 RAG 仅能独立检索文本片段的局限性&#xff0c;GraphRAG通过构建实体关系图谱实现了信息间的连接&#xff0c;让 AI 能更完整地理解和检索复杂的关联信息&#xff0c;从而生成更准确和连贯的回答 问题背景: 想象有一本详细记录某人(X)成就的传记,每个章节都描述了他的…

Linux平台下实现的小程序-进度条

目录 1.换行、回车概念 2.缓冲区 2.1缓冲区 2.2强制刷新 3.进度条程序 Makefile文件 ProgressBar.h ProgressBar.c Main.c 执行结果 1.换行、回车概念 /n&#xff1a;换行回车&#xff08;\r&#xff1a;回车&#xff09; 2.缓冲区 如下图在vim编辑器中的命令模式下…

【顶刊TPAMI 2025】多头编码(MHE)之Part 6:极限分类无需预处理

目录 1 标签分解方法的消融研究2 标签分解对泛化的影响3 讨论4 结论 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者&#xff1a;Daojun Liang, Haixia Zhang, Dongfeng Yuan and Minggao Zhang 单位&#xff1a;山东大学 代码&#xff1a;https:…

【Leetcode】732. 我的日程安排表 III

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 当 k k k 个日程存在一些非空交集时&#xff08;即, k k k 个日程包含了一些相同时间&#xff09;&#xff0c;就会产生 k k k 次预订。 给你一些日程安排 [startTime, endTime…

Tableau数据可视化与仪表盘搭建-数据连接

连接数据有三种类型 第一种&#xff0c;连接到本地文件&#xff0c;例如Excel&#xff0c;csv&#xff0c;JSON等 第二种&#xff0c;连接到数据库&#xff0c;例如MySQL 注意&#xff1a;连接到数据库要安装对应的数据库的驱动的 连接本地文件

Chapter4.2:Normalizing activations with layer normalization

文章目录 4 Implementing a GPT model from Scratch To Generate Text4.2 Normalizing activations with layer normalization 4 Implementing a GPT model from Scratch To Generate Text 4.2 Normalizing activations with layer normalization 通过层归一化&#xff08;La…

搭建开源版Ceph分布式存储

系统&#xff1a;Rocky8.6 三台2H4G 三块10G的硬盘的虚拟机 node1 192.168.2.101 node2 192.168.2.102 node3 192.168.2.103 三台虚拟机环境准备 1、配置主机名和IP的映射关系 2、关闭selinux和firewalld防火墙 3、配置时间同步且所有节点chronyd服务开机自启 1、配置主机名和…

GPIO、RCC库函数

void GPIO_DeInit(GPIO_TypeDef* GPIOx); void GPIO_AFIODeInit(void); void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); //输出 读 uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx,…

使用JMeter玩转tidb压测

作者&#xff1a; du拉松 原文来源&#xff1a; https://tidb.net/blog/3f1ada39 一、前言 tidb是mysql协议的&#xff0c;所以在使用过程中使用tidb的相关工具连接即可。因为jmeter是java开发的相关工具&#xff0c;直接使用mysql的jdbc驱动包即可。 二、linux下安装jmet…

Launcher3主页面加载显示流程分析

布局结构 抓取布局后&#xff0c;可以看到每个图标是一个DoubleShadowBubbleTextView&#xff0c;父布局是CellLayout、workspace。 我们可以在CellLayout添加子view打印出调用堆栈信息&#xff0c;可以整体上看页面加载显示流程。 主要类 Launcher.java&#xff1a;主界面&…

开发培训:慧集通(DataLinkX)iPaaS集成平台-基于接口的连接器开发(不需要认证机制)

一、开发一个简单的应用0源&#xff0c;本实例中对接的应用不需要接口认证 1、【连接管理-自建】新建应用源&#xff0c;保存并发布 代码示例 return {$$ - >//日志打印$$.$Log.info(日志打印) } 二、使用应用&#xff0c;建立应用连接 1、实例创建&#xff0c;【连接管理…

pikachu靶场--目录遍历和敏感信息泄露

pikachu靶场—目录遍历和敏感信息泄露 目录遍历 概述 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量&#xff0c;从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时&#xff0c;便会将请求的这个文件的值(比如文件名称)传递到后台&#xff0c;后台再…

机器学习详解(13):CNN图像数据增强(解决过拟合问题)

在之前的文章卷积神经网络CNN之手语识别代码详解中&#xff0c;我们发现最后的训练和验证损失的曲线的波动非常大&#xff0c;而且验证集的准确率仍然落后于训练集的准确率&#xff0c;这表明模型出现了过拟合现象&#xff1a;在验证数据集测试时&#xff0c;模型对未见过的数据…

Word2Vec解读

Word2Vec: 一种词向量的训练方法 简单地讲&#xff0c;Word2Vec是建模了一个单词预测的任务&#xff0c;通过这个任务来学习词向量。假设有这样一句话Pineapples are spiked and yellow&#xff0c;现在假设spiked这个单词被删掉了&#xff0c;现在要预测这个位置原本的单词是…

#渗透测试#漏洞挖掘#WAF分类及绕过思路

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

电子应用设计方案85:智能 AI门前柜系统设计

智能 AI 门前柜系统设计 一、引言 智能 AI 门前柜系统旨在提供便捷、安全和智能的物品存储与管理解决方案&#xff0c;适用于家庭、公寓或办公场所的入口区域。 二、系统概述 1. 系统目标 - 实现无接触式物品存取&#xff0c;减少交叉感染风险。 - 具备智能识别和分类功能&am…

如何在不丢失数据的情况下从 IOS 14 回滚到 IOS 13

您是否后悔在 iPhone、iPad 或 iPod touch 上安装 iOS 14&#xff1f;如果你这样做&#xff0c;你并不孤单。许多升级到 iOS 14 beta 的 iPhone、iPad 和 iPod touch 用户不再适应它。 如果您在正式发布日期之前升级到 iOS 14 以享受其功能&#xff0c;但您不再适应 iOS 14&am…

线性代数考研笔记

行列式 背景 分子行列式&#xff1a;求哪个未知数&#xff0c;就把b1&#xff0c;b2放在对应的位置 分母行列式&#xff1a;系数对应写即可 全排列与逆序数 1 3 2&#xff1a;逆序数为1 奇排列 1 2 3&#xff1a;逆序数为0 偶排列 将 1 3 2 只需将3 2交换1次就可以还原原…

设计心得——流程图和数据流图绘制

一、流程图和数据流图 在软件开发中&#xff0c;画流程图和数据流图可以说是几乎每个人都会遇到。 1、数据流&#xff08;程&#xff09;图 Data Flow Diagram&#xff0c;DFG。它可以称为数据流图或数据流程图。其主要用来描述系统中数据流程的一种图形工具&#xff0c;可以将…