<template>
    <hc-drawer v-model="isShow" ui="hc-project-list-edit-formula-drawer" to-id="hc-layout-box" is-close @close="drawerClose">
        <hc-card is-action-btn :scrollbar="isScrollBar">
            <div class="hc-project-list-edit-formula-card" :class="isScrollBar ? '' : 'is-no-scroll'">
                <!-- 顶部操作 -->
                <div class="hc-formula-card-box border-dashed-card hc-flex mb-14px h-58px">
                    <div class="retain hc-flex h-full w-174px">
                        <el-checkbox v-model="isRetain" size="large" />
                        <span class="ml-5px text-14px">保留</span>
                        <div class="relative ml-5px w-90px">
                            <el-input-number v-model="retainNum" block :step="1" :min="0" :max="5" :disabled="!isRetain" controls-position="right" />
                        </div>
                        <span class="ml-5px text-14px">位</span>
                    </div>
                    <div class="range hc-flex h-full w-155px">
                        <el-button :type="deviationRangeShow ? 'primary' : ''" @click="setDeviationRange">允许偏差值范围</el-button>
                    </div>
                    <div class="menu h-full flex-1">
                        <hc-body padding="0">
                            <el-menu :default-active="formulaMenuIndex" mode="horizontal" @select="handleFormulaMenu">
                                <el-sub-menu v-for="(arr, key, index) in formulaMenuList" :key="key" :index="key">
                                    <template #title>{{ key }}</template>
                                    <el-menu-item v-for="(item, i) in arr" :key="i" :index="`${index + 1}-${i + 1}`">{{ item?.name }}</el-menu-item>
                                </el-sub-menu>
                            </el-menu>
                        </hc-body>
                    </div>
                    <div class="hand hc-flex h-full w-100px">
                        <el-button @click="handWritClick">手写模式</el-button>
                    </div>
                </div>
                <!-- 函数公式 -->
                <div class="border-dashed-card hc-formula-card-math mb-14px">
                    <div class="header hc-flex">
                        <div class="name flex-1 text-14px">函数公式.</div>
                        <div class="extra relative ml-24px">
                            <el-button size="small" @click="clearResetFunClick">清除选择</el-button>
                            <el-button :type="isResetFun ? 'primary' : 'info'" size="small" @click="resetFunClick">重置函数</el-button>
                        </div>
                    </div>
                    <div class="body relative">
                        <template v-for="(item, index) in resultFormula" :key="index">
                            <span class="element-class text-22px" :class="item.selected ? 'is-cur' : ''" @click="resultFormulaItem(item, index)">{{ item.name }}</span>
                        </template>
                        <span class="ml-10px mr-10px text-24px">=</span>
                        <template v-for="(item, index) in processFormula" :key="index">
                            <el-tooltip :content="item.tableName" placement="top-start" :disabled="item.type !== 'Element' || isNullES(item.tableName)">
                                <span class="element-class text-22px" :class="item.selected ? 'is-cur' : ''" :data-name="getItemTableName(item)" @click="processFormulaItem(item, index)">{{ item.name }}</span>
                            </el-tooltip>
                        </template>
                    </div>
                </div>
                <!-- 重置函数 -->
                <div v-if="isResetFun" class="hc-formula-reset-fun mb-14px">
                    <hc-body split padding="0">
                        <template #left>
                            <hc-card class="reset-fun-left-card" scrollbar :loading="treeResetFunLoading">
                                <template #header>
                                    <hc-search-input v-model="resetFunTree" @search="resetFunTreeSearch" />
                                </template>
                                <el-tree
                                    v-if="isResetFunTreeLazy" ref="treeResetFunLazyRef" :default-expanded-keys="treeResetFunLazyExpanded" node-key="id"
                                    :props="defaultProps" :expand-on-click-node="false" lazy highlight-current :load="treeResetFunLazyLoad"
                                    @node-click="treeResetFunLazyClick"
                                />
                                <el-tree
                                    v-else ref="treeResetFunAllRef" :data="resetFunTreeAll" :props="defaultProps" node-key="id"
                                    :expand-on-click-node="false" @node-click="treeResetFunLazyClick"
                                />
                            </hc-card>
                        </template>
                        <hc-card class="reset-fun-right-card">
                            <template #header>
                                <hc-search-input v-model="resetFunEle" placeholder="请输入你想搜索的元素字段" @search="resetFunEleSearch" />
                            </template>
                            <div class="body h-full">
                                <div v-loading="isResetFunEleLoading" class="tag-box">
                                    <template v-for="(item, index) in resetFunEleData" :key="index">
                                        <el-button v-if="item.k" type="primary" plain size="small" @click="resetFunEleTagClick(item)">{{ item.name }}</el-button>
                                        <el-button v-else type="primary" plain size="small" @click="resetFunEleTagClick(item)">{{ item.eName }}</el-button>
                                    </template>
                                </div>
                                <div class="action-box hc-flex">
                                    <div class="left hc-flex flex-1">
                                        <div class="btn hc-flex-center" @click="resetFunText">
                                            <span class="text">输入值</span>
                                        </div>
                                        <div class="btn hc-flex-center" @click="resetFunBrackets('(')">
                                            <span class="symbol">(</span>
                                        </div>
                                        <div class="btn hc-flex-center" @click="resetFunBrackets(')')">
                                            <span class="symbol">)</span>
                                        </div>
                                        <div class="btn hc-flex-center" @click="resetFunOperator('+')">
                                            <i class="i-ri-add-line" />
                                        </div>
                                        <div class="btn hc-flex-center" @click="resetFunOperator('-')">
                                            <i class="i-ri-subtract-line" />
                                        </div>
                                        <div class="btn hc-flex-center" @click="resetFunOperator('*')">
                                            <i class="i-ri-close-line" />
                                        </div>
                                        <div class="btn hc-flex-center" @click="resetFunOperator('%')">
                                            <hc-icon name="divide" />
                                        </div>
                                    </div>
                                    <div class="right hc-flex">
                                        <el-tooltip content="删除元素" placement="top-end">
                                            <div class="btn hc-flex-center" @click="resetFunDel">
                                                <i class="i-ri-delete-back-2-line" />
                                            </div>
                                        </el-tooltip>
                                        <el-tooltip content="清空所有" placement="top-end">
                                            <div class="btn hc-flex-center" @click="resetFunClear">
                                                <i class="i-ri-delete-bin-3-line" />
                                            </div>
                                        </el-tooltip>
                                    </div>
                                </div>
                                <div class="input-box">
                                    <draggable v-model="selectEleFormula" item-key="index">
                                        <template #item="{ element }">
                                            <span class="element-class" :class="[`is-${element.type}`, element.selected ? 'is-cur' : '']" @click="selectEleFormulaItem(element)">{{ element.name }}</span>
                                        </template>
                                    </draggable>
                                </div>
                            </div>
                        </hc-card>
                    </hc-body>
                </div>
                <!-- 函数公式运算执行溯源 -->
                <div v-if="!isResetFun && !deviationRangeShow" class="border-dashed-card hc-formula-card-project mb-14px">
                    <div class="header mb-14px text-14px">函数公式运算执行溯源</div>
                    <div class="body relative">
                        <el-select v-model="projectId" filterable clearable class="mr-14px w-380px" placeholder="选择项目" @change="projectChange">
                            <el-option v-for="item in projectList" :key="item.id" :label="item.projectName" :value="item.id" />
                        </el-select>
                        <el-select v-model="contractId" filterable clearable class="mr-14px w-200px" placeholder="请选择合同段">
                            <el-option v-for="item in contractList" :key="item.id" :label="item.contractName" :value="item.id" />
                        </el-select>
                        <el-button type="info" @click="projectQueryClick">查询</el-button>
                    </div>
                </div>
                <!-- 允许偏差值范围 -->
                <div v-if="deviationRangeShow && !isResetFun" class="border-dashed-card hc-formula-card-range mb-14px" :class="isRangeSelectEle ? 'is-h' : ''">
                    <div class="hc-formula-card-range-form hc-flex mb-12px text-14px">
                        <div>允许偏差值范围：</div>
                        <div class="w-130px">
                            <el-select v-model="deviationRangeSymbol" filterable clearable placeholder="请选择允许偏差值范围">
                                <el-option label="【min,max】" value="【min,max】" />
                                <el-option label=">" value=">" />
                                <el-option label="<" value="<" />
                                <el-option label="≥" value="≥" />
                                <el-option label="≤" value="≤" />
                            </el-select>
                        </div>
                        <div class="ml-50px">模式：</div>
                        <div class="mr-50px w-100px">
                            <el-select v-model="deviationRangeResult" filterable clearable placeholder="请选择模式" @change="deviationRangeResultChange">
                                <el-option label="普通" value="1" />
                                <el-option label="自定义" value="2" />
                            </el-select>
                        </div>
                        <div v-if="deviationRangeResult === '1'" class="hc-flex mr-50px">
                            <VueTagsInput
                                v-if="!(deviationRangeSymbol === '<' || deviationRangeSymbol === '≤')" v-model="deviationRangeTag1" :tags="deviationRangeTags1"
                                placeholder="输入/参数" class="mr-12px" :class="curRangeFocusIndex === 1 ? 'cur' : ''" @focus="curRangeFocusIndex = 1"
                                @blur="deviationRangeBlur1" @before-adding-tag="rangeAddingTag"
                            />
                            <VueTagsInput
                                v-if="!(deviationRangeSymbol === '>' || deviationRangeSymbol === '≥')" v-model="deviationRangeTag2" :tags="deviationRangeTags2"
                                placeholder="输入/参数" :class="curRangeFocusIndex === 2 ? 'cur' : ''" @focus="curRangeFocusIndex = 2" @blur="deviationRangeBlur2"
                                @before-adding-tag="rangeAddingTag"
                            />
                        </div>
                        <el-button :type="isRangeSelectEle ? 'primary' : 'info'" @click="deviationRangeSelectEle">选择参数</el-button>
                    </div>
                    <div v-if="deviationRangeResult === '2'" class="hc-formula-card-range-param relative mb-12px">
                        <el-row :gutter="20">
                            <el-col v-if="!(deviationRangeSymbol === '<' || deviationRangeSymbol === '≤')" :span="12">
                                <div class="deviation-range-param-card" :class="curRangeFocusIndex === 3 ? 'cur' : ''" @click.capture="curRangeFocusIndex = 3">
                                    <div class="title-box">参数1</div>
                                    <div class="action-box hc-flex">
                                        <div class="left hc-flex flex-1">
                                            <div class="btn hc-flex-center" @click="resetFunText">
                                                <span class="text">输入值</span>
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunBrackets('(')">
                                                <span class="symbol">(</span>
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunBrackets(')')">
                                                <span class="symbol">)</span>
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('+')">
                                                <i class="i-ri-add-line" />
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('-')">
                                                <i class="i-ri-subtract-line" />
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('*')">
                                                <i class="i-ri-close-line" />
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('%')">
                                                <hc-icon name="divide" />
                                            </div>
                                        </div>
                                        <div class="right hc-flex">
                                            <el-tooltip content="删除元素" placement="top-end">
                                                <div class="btn hc-flex-center" @click="resetFunDel">
                                                    <i class="i-ri-delete-back-2-line" />
                                                </div>
                                            </el-tooltip>
                                            <el-tooltip content="清空所有" placement="top-end">
                                                <div class="btn hc-flex-center" @click="resetFunClear">
                                                    <i class="i-ri-delete-bin-3-line" />
                                                </div>
                                            </el-tooltip>
                                        </div>
                                    </div>
                                    <div class="input-box">
                                        <draggable v-if="selectEleFormula3.length > 0" v-model="selectEleFormula3" item-key="index">
                                            <template #item="{ element }">
                                                <span class="element-class" :class="[`is-${element.type}`, element.selected ? 'is-cur' : '']" @click="selectEleFormulaItem(element)">{{ element.name }}</span>
                                            </template>
                                        </draggable>
                                        <div v-else class="text-gray-5">请选择元素</div>
                                    </div>
                                </div>
                            </el-col>
                            <el-col v-if="!(deviationRangeSymbol === '>' || deviationRangeSymbol === '≥')" :span="12">
                                <div class="deviation-range-param-card" :class="curRangeFocusIndex === 4 ? 'cur' : ''" @click.capture="curRangeFocusIndex = 4">
                                    <div class="title-box">参数2</div>
                                    <div class="action-box hc-flex">
                                        <div class="left hc-flex flex-1">
                                            <div class="btn hc-flex-center" @click="resetFunText">
                                                <span class="text">输入值</span>
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunBrackets('(')">
                                                <span class="symbol">(</span>
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunBrackets(')')">
                                                <span class="symbol">)</span>
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('+')">
                                                <i class="i-ri-add-line" />
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('-')">
                                                <i class="i-ri-subtract-line" />
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('*')">
                                                <i class="i-ri-close-line" />
                                            </div>
                                            <div class="btn hc-flex-center" @click="resetFunOperator('%')">
                                                <hc-icon name="divide" />
                                            </div>
                                        </div>
                                        <div class="right hc-flex">
                                            <el-tooltip content="删除元素" placement="top-end">
                                                <div class="btn hc-flex-center" @click="resetFunDel">
                                                    <i class="i-ri-delete-back-2-line" />
                                                </div>
                                            </el-tooltip>
                                            <el-tooltip content="清空所有" placement="top-end">
                                                <div class="btn hc-flex-center" @click="resetFunClear">
                                                    <i class="i-ri-delete-bin-3-line" />
                                                </div>
                                            </el-tooltip>
                                        </div>
                                    </div>
                                    <div class="input-box">
                                        <draggable v-if="selectEleFormula4.length > 0" v-model="selectEleFormula4" item-key="index">
                                            <template #item="{ element }">
                                                <span class="element-class" :class="[`is-${element.type}`, element.selected ? 'is-cur' : '']" @click="selectEleFormulaItem(element)">{{ element.name }}</span>
                                            </template>
                                        </draggable>
                                        <div v-else class="text-gray-5">请选择元素</div>
                                    </div>
                                </div>
                            </el-col>
                        </el-row>
                    </div>
                    <div v-if="isRangeSelectEle" class="hc-formula-card-range-select relative">
                        <hc-body split padding="0">
                            <template #left>
                                <hc-card class="hc-formula-card-range-select-left-card" scrollbar :loading="treeResetFunLoading">
                                    <template #header>
                                        <hc-search-input v-model="resetFunTree" @search="resetFunTreeSearch" />
                                    </template>
                                    <el-tree
                                        v-if="isResetFunTreeLazy" ref="treeRangeSelectLazyRef" :default-expanded-keys="treeResetFunLazyExpanded" node-key="id"
                                        :props="defaultProps" :expand-on-click-node="false" lazy highlight-current :load="treeResetFunLazyLoad"
                                        @node-click="treeResetFunLazyClick"
                                    />
                                    <el-tree
                                        v-else ref="treeRangeSelectAllRef" :data="resetFunTreeAll" :props="defaultProps" node-key="id"
                                        :expand-on-click-node="false" @node-click="treeResetFunLazyClick"
                                    />
                                </hc-card>
                            </template>
                            <hc-card scrollbar class="hc-formula-card-range-select-right-card">
                                <template #header>
                                    <hc-search-input v-model="resetFunEle" placeholder="请输入你想搜索的元素字段" @search="resetFunEleSearch" />
                                </template>
                                <div v-loading="isResetFunEleLoading" class="body h-full">
                                    <template v-for="(item, index) in resetFunEleData" :key="index">
                                        <el-button v-if="item.k" type="primary" plain size="small" @click="resetFunEleTagClick(item)">{{ item.name }}</el-button>
                                        <el-button v-else type="primary" plain size="small" @click="resetFunEleTagClick(item)">{{ item.eName }}</el-button>
                                    </template>
                                </div>
                            </hc-card>
                        </hc-body>
                    </div>
                </div>
                <!-- 多标签处理 -->
                <div v-if="showFunDetail" class="hc-formula-card-tag mb-14px">
                    <el-tabs v-model="equationSelectIndex" type="border-card" closable :before-leave="leaveEquationSelect" @tab-remove="delEquationSelect">
                        <template v-for="(item, index) in equationSelectEle.children" :key="index">
                            <el-tab-pane :label="item.name" :name="index">
                                {{ item.name }} + {{ index }}
                            </el-tab-pane>
                        </template>
                    </el-tabs>
                </div>
            </div>
            <template #action>
                <el-button @click="drawerClose">取消</el-button>
                <el-button type="primary" :loading="submitLoading" @click="submitClick">保存</el-button>
            </template>
        </hc-card>
        <!-- 手写模式 -->
        <hc-dialog v-model="isHandWritEle" is-table widths="900px" title="手写模式" @close="handWritEleClose">
            <template #search>
                <div class="relative">
                    <div class="mb-6px text-orange-6">tips:手写模式不保证能转换成配置模式！！即使能转换也不保证正确！！！</div>
                    <div class="text-orange-6">无法在手写模式手写加入新的元素！新的节点参数！</div>
                </div>
            </template>
            <el-input v-model="handWritText" type="textarea" class="hc-formula-hand-writ-text" placeholder="请输入内容" />
            <template #footer>
                <el-button hc-btn @click="handWritEleClose">取消</el-button>
                <el-button hc-btn type="primary" @click="handWritTransform">转换</el-button>
            </template>
        </hc-dialog>
    </hc-drawer>
</template>

<script setup>
import { computed, nextTick, ref, watch } from 'vue'
import { useClick } from 'hc-vue3-ui'
import {
    arrIndex, deepClone, getArrValue, getObjVal, getObjValue,
    getRandom, isArray, isNullES, isString,
} from 'js-fast-way'
import { ElMessageBox } from 'element-plus'
import { VueTagsInput } from '@vojtechlanka/vue-tags-input'
import draggable from 'vuedraggable'

//辅助解析文件
import { rangeToString } from './formula/rangeToString'
import { formulaArrayToString } from './formula/formulaArrayToString'
import { formulaStringToArray } from './formula/formulaStringToArray'

//接口文件
import projectApi from '~api/project/project'
import contractApi from '~api/project/contract'
import formulaApi from '~api/project/formula'
import elementApi from '~api/project/element'
import privateApi from '~api/wbs/private'
import treeApi from '~api/wbs/tree'

const props = defineProps({
    data: {
        type: Object,
        default: () => ({}),
    },
})

//事件
const emit = defineEmits(['close', 'finish', 'uncheck'])

//双向绑定
const isShow = defineModel('modelValue', {
    default: false,
})

//监听数据
const dataInfo = ref(props.data)
watch(() => props.data, (data) => {
    dataInfo.value = getObjValue(data)
}, { immediate: true, deep: true })

//监听显示
watch(isShow, (val) => {
    if (val) getDataApi()
})

//基础变量
const symbolReg = /(\+|-|\*|\/)（.+）/ //加减乘除
const operatorReg = /^\+|-|\*|%/ //加减乘除
const startFCRegExp = /^FC\.([a-zA-Z\d]+)\(/ //匹配开始的FC.xxx(
const isScrollBar = ref(true)

//获取数据
const getDataApi = async () => {
    console.log(dataInfo.value)
    await getTypeMapApi()
    await getWbsFormElementData()
    await getFormulaStringToArrayApi()
    getProjectDataApi().then()
}

//保留位数
const isRetain = ref(false)
const retainNum = ref(2)

//把公式文本还原数组
const rightDict = ref([])
const formulaId = ref('')
const deviationRangeObj = ref({})
const getFormulaStringToArrayApi = async () => {
    const { eleId, globalType, nodeId, pid } = getObjValue(dataInfo.value)
    const { code, data } = await formulaApi.detail({
        projectId: pid,
        elementId: eleId,
        nodeId: nodeId,
        scope: globalType,
    })
    if (code !== 200) return
    const res = getObjValue(data)
    console.log(res)
    if (!isNullES(res.id)) {
        //获取右边元素的字典
        let dictMap = getObjValue(res.dict), dictArr = []
        //遍历
        for (let i in dictMap) {
            dictArr.push(dictMap[i])
        }
        rightDict.value = dictArr
        formulaId.value = res.id
        //把公式字符串还原成数组
        let formula = formulaStringToArray(res.formula, res.map, formulaMenuMap.value)
        processFormula.value = getArrValue(formula?.processFormula)
        const results = resultFormula.value
        formula.resultFormula[0].id = results[0].id
        formula.resultFormula[0].name = results[0].name
        formula.resultFormula[0].tableElementKey = results[0].tableElementKey
        resultFormula.value[0].children = formula.resultFormula[0].children
        //允许偏差值范围
        let mapObj = JSON.parse(res.map)
        if (mapObj.deviationRangeJson) {
            deviationRangeObj.value = JSON.parse(mapObj.deviationRangeJson)
        }
    }
    if (res.scale >= 0) {
        isRetain.value = true
        retainNum.value = res.scale
    } else {
        isRetain.value = false
        retainNum.value = 2
    }
}

//获取当前元素的表名
const getItemTableName = (item) => {
    if (item.type !== 'Element') {
        return
    }
    rightDict.value.forEach((ele) => {
        if (ele.ekey === item.tableElementKey) {
            item.tableName = ele.tableName
        }
    })
}

//允许偏差值范围
const deviationRangeShow = ref(false)
const setDeviationRange = () => {
    if (isResetFun.value) {
        window?.$message.warning('请先关闭重置函数')
        return
    }
    const val = !deviationRangeShow.value
    deviationRangeShow.value = val
    if (val) {
        const { symbol, model, arguments1, arguments2 } = deviationRangeObj.value
        deviationRangeSymbol.value = symbol
        deviationRangeResult.value = model
        curRangeFocusIndex.value = 1
        //公式
        if (isArray(arguments1) && arguments1.length > 1 || isArray(arguments2) && arguments2.length > 1) {
            //selectEleFormula.value = arguments1
            selectEleFormula3.value = arguments1
            selectEleFormula4.value = arguments2
            return
        }
        //参数1
        if (isString(arguments1)) {
            deviationRangeTag1.value = arguments1
        } else {
            deviationRangeTags1.value = arguments1
        }
        //参数2
        if (isString(arguments2)) {
            deviationRangeTag2.value = arguments2
        } else {
            deviationRangeTags2.value = arguments2
        }
    } else {
        curRangeFocusIndex.value = 0
    }
}

//获取顶部菜单数据
const formulaMenuMap = ref({})
const formulaMenuIndex = ref(null)
const formulaMenuList = ref({})
const getTypeMapApi = async () => {
    const { data } = await formulaApi.getTypeMap()
    const res = getObjValue(data)
    formulaMenuList.value = deepClone(res)
    //生成map，方便查找
    for (let key in res) {
        if (typeof(res[key]) === 'object') {
            res[key].forEach((formula)=>{
                formula.template = JSON.parse(formula.template)
                if (operatorReg.test(formula.template.ft)) {
                    formulaMenuMap.value[formula.template.ft] = formula
                } else if (startFCRegExp.test(formula.template.ft)) {
                    let regRes = formula.template.ft.match(startFCRegExp)
                    formulaMenuMap.value[regRes[0]] = formula
                }
            })
        }
    }
}

//菜单被选择
const handleFormulaMenu = (index, path) => {
    if (isResetFun.value) {
        //重置函数
        if (path[0] !== '基础运算') {
            window?.$message.warning('当前只能使用基础运算')
            return
        }
        try {
            let index = Number(path[1].split('-')[1]) - 1
            const item = formulaMenuList.value[path[0]][index]
            const val = symbolReg.exec(item.name)[1]
            resetFunOperator(val)
        } catch (e) {
            console.error(e)
        }
    } else {
        equationSelect(path)
    }
}

//在等式模式下点选计算式
const equationSelectIndex = ref(-1)
const equationSelect = (path) => {
    const selectEle = getObjVal(equationSelectEle.value)
    if (!selectEle || !['Element', 'ParamData'].includes(selectEle.type)) {
        window?.$message.warning('请先选中元素')
        return
    }
    console.log(selectEle)
    let obj = {}
    try {
        const index = Number(path[1].split('-')[1]) - 1
        const expression = formulaMenuList.value[path[0]][index]
        obj = deepClone(expression)
    } catch (error) {
        console.log(error)
    }
    if (obj.type === 1) return
    obj.arguments = new Array(obj.template.args.length)
    let ele = {}
    if (selectEle.type === 'ParamData') {
        ele = {
            type: 'ParamData',
            id: selectEle.id,
            v: selectEle.v,
            k: selectEle.k,
            name: selectEle.name,
            selected: false,
        }
    } else {
        ele = {
            type: 'Element',
            id: selectEle.id,
            name: selectEle.name,
            selected: false,
            tableElementKey: selectEle.tableElementKey,
        }
    }
    let tg = obj.template.args.findIndex(x => x.m !== '常量')
    obj.arguments[tg] = ele
    equationSelectEle.value.children.push(obj)
    //跳转到最新的标签
    equationSelectIndex.value = equationSelectEle.value.children.length - 1
}

//移除挂载的函数
const delEquationSelect = (name) => {
    console.log(name)
}

//切换公式tab标签
const leaveEquationSelect = (name, oldName) => {
    console.log(name, oldName)
}

//获取数据
const resultFormula = ref([])
const getWbsFormElementData = async () => {
    const { eleId } = getObjValue(dataInfo.value)
    resultFormula.value = []
    if (isNullES(eleId)) return
    const { data } = await elementApi.detail(eleId)
    const obj = getObjValue(data)
    resultFormula.value = [{
        type: 'Element',
        name: obj.eName,
        id: obj.id,
        selected: false,
        tableElementKey: obj.tableElementKey,
        children: [],
    }]
}

//左边被点击
const processIndex = ref(-1)
const processType = ref('')
const resultFormulaItem = (item, index) => {
    clearResetFunClick()
    //设置当前选中
    processIndex.value = index
    processType.value = 'resultFormula'
    item.selected = true
}

//右边被点击
const processFormulaItem = (item, index) => {
    clearResetFunClick()
    //设置当前选中
    processIndex.value = index
    processType.value = 'processFormula'
    item.selected = true
}

//清除选择
const clearResetFunClick = () => {
    //清除左边的选中
    resultFormula.value.forEach((obj) => {
        obj.selected = false
    })
    //清除右边的选中
    processFormula.value.forEach((obj) => {
        obj.selected = false
    })
    //设置当前选中
    processIndex.value = -1
    processType.value = ''
}


//获取当前选中的元素
const equationSelectEle = computed(() => {
    const type = processType.value
    if (isNullES(type)) return null
    const index = processIndex.value
    let arr = []
    if (type === 'resultFormula') {
        arr = resultFormula.value
    } else if (type === 'processFormula') {
        arr = processFormula.value
    }
    if (arr.length <= 0) return null
    return arr[index]
})

//显示函数详情
const showFunDetail = computed(() => {
    if (isResetFun.value) {
        // eslint-disable-next-line vue/no-side-effects-in-computed-properties
        isResetFun.value = false
    }
    if (deviationRangeShow.value) {
        // eslint-disable-next-line vue/no-side-effects-in-computed-properties
        deviationRangeShow.value = false
    }
    if (isNullES(equationSelectEle.value)) return false
    if (isNullES(equationSelectEle.value.children)) return false
    return equationSelectEle.value.children.length > 0
})


//是否重置函数
const isResetFun = ref(false)
const resetFunClick = () => {
    if (deviationRangeShow.value) {
        window?.$message.warning('请先关闭允许偏差值范围')
        return
    }
    const val = !isResetFun.value
    if (val) {
        curRangeFocusIndex.value = 99
    } else {
        curRangeFocusIndex.value = 0
    }
    isResetFun.value = val
    isScrollBar.value = !val
}

//tree树配置
const defaultProps = {
    label: 'title',
    children: 'children',
    isLeaf: (data) => {
        return !data.hasChildren
    },
}

//重置函数懒加载树
const treeResetFunLazyRef = ref(null)
const treeRangeSelectLazyRef = ref(null)
const treeResetFunAllRef = ref(null)
const treeRangeSelectAllRef = ref(null)
const treeResetFunLazyExpanded = ref([])

//获取重置函数懒加载树的数据
const treeResetFunLoading = ref(false)
const treeResetFunLazyLoad = async (node, resolve) => {
    const { level, data } = node
    treeResetFunItemData.value = data
    let parentId = level !== 0 ? data.id : 12345678910
    const { eleType, node: dataNode, tableType } = getObjValue(dataInfo.value)
    const treeNode = getObjValue(dataNode)
    if (level === 0) treeResetFunLoading.value = true
    if (!eleType) {
        //获取接口数据
        const { data } = await privateApi.tabTypeLazyTreeAll({
            parentId,
            current: 1,
            size: 99999,
            hasPartFormula: treeNode.hasPartFormula,
        })
        const res = getArrValue(data.records)
        treeResetFunLoading.value = false
        resolve(res)
        //处理返回的数据
        await nextTick()
        //处理展开
        try {
            const expandId = tableType ? Number(treeNode.tableType) - 1 : Number(treeNode.parentId) - 1
            if (!isNullES(expandId) && expandId >= 0) node.childNodes[expandId].expand()
        } catch { /* empty */ }
        //处理选中
        try {
            const paramsId = treeNode.initTableId
            if (!isNullES(paramsId)) {
                treeResetFunLazyRef.value?.setCurrentKey(paramsId)
                treeRangeSelectLazyRef.value?.setCurrentKey(paramsId)
            }
        } catch { /* empty */ }
        //获取节点详情
        await getNodeDetailApi(treeNode)
    } else if (eleType) {
        resolve([])
    }
}

//重置函数懒加载树点击
const treeResetFunItemData = ref({})
const treeResetFunNodeData = ref({})
const treeResetFunLazyClick = async (data, node) => {
    treeResetFunItemData.value = data
    treeResetFunNodeData.value = node
    await getNodeDetailApi(data)
}

//重置函数树搜索
const resetFunTree = ref('')
const resetFunTreeAll = ref([])
const isResetFunTreeLazy = ref(true)
const resetFunTreeSearch = async () => {
    if (isNullES(resetFunTree.value)) {
        isResetFunTreeLazy.value = true
        return
    }
    isResetFunTreeLazy.value = false
    treeResetFunLoading.value = true
    const obj = treeResetFunItemData.value
    const parentId = obj.hasChildren ? obj.id : ''
    const { data, code } = await privateApi.tabTypeLazyTreeAll({
        parentId: parentId,
        current:1,
        size:1000,
        titleName: resetFunTree.value,
    })
    if (code !== 200) {
        resetFunTreeAll.value = []
        treeResetFunLoading.value = false
        return
    }
    resetFunTreeAll.value = getArrValue(data?.records)
    treeResetFunLoading.value = false
}

//重置函数元素搜索
const resetFunEle = ref('')
const isResetFunEleLoading = ref(false)
const resetFunEleSearch = async () => {
    const { initTableId } = treeResetFunItemData.value
    if (isNullES(initTableId)) {
        resetFunEleData.value = []
        isResetFunEleLoading.value = false
        return
    }
    isResetFunEleLoading.value = true
    if (isNullES(resetFunEle.value)) {
        const { data } = await treeApi.getTableElments({
            id: initTableId,
        })
        resetFunEleData.value = getArrValue(data)
    } else {
        const { data } = await treeApi.getTableElments({
            id: initTableId,
            search: resetFunEle.value,
        })
        resetFunEleData.value = getArrValue(data)
    }
    isResetFunEleLoading.value = false
}

//获取节点详情
const resetFunEleData = ref([])
const getNodeDetailApi = async (item) => {
    await useClick(300)
    if (isNullES(item.initTableId)) {
        resetFunEleData.value = []
        isResetFunEleLoading.value = false
        return
    }
    if (item.hasChildren === false || item.isLinkTable === 2) {
        isResetFunEleLoading.value = true
        const { data } = await treeApi.getTableElments({
            id: item.initTableId,
        })
        resetFunEleData.value = getArrValue(data)
    } else {
        resetFunEleData.value = []
    }
    isResetFunEleLoading.value = false
}

//元素字段被点击
const selectEleFormula = ref([])
const selectEleFormula3 = ref([])
const selectEleFormula4 = ref([])
const resetFunEleTagClick = (item) => {
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    let arr = []
    if (index === 99) {
        //重置函数
        arr = selectEleFormula.value
    } else if (index === 3) {
        //参数1
        arr = selectEleFormula3.value
    } else if (index === 4) {
        //参数2
        arr = selectEleFormula4.value
    }
    let { type, name } = getObjValue(arr[arr.length - 1])
    if (type === 'Text') {
        window?.$message.warning('元素无法连续出现在输入值后面')
        return
    }
    if (type === 'Brackets' && name === ')') {
        window?.$message.warning('元素无法连续出现在右括号后面')
        return
    }
    if (arr.length === 0 || ['Operator', 'Brackets'].includes(type) || name === '(') {
        if (!isNullES(item.tableElementKey)) {
            const obj = {
                type: 'Element',
                name: item.eName,
                id: item.id,
                selected: false,
                tableElementKey: item.tableElementKey,
                index: getRandom(5),
                children: [],
            }
            if (index === 99) {
                selectEleFormula.value.push(obj)
            } else if (index === 3) {
                selectEleFormula3.value.push(obj)
            } else if (index === 4) {
                selectEleFormula4.value.push(obj)
            }
        }
    } else {
        window?.$message.warning('当前操作不符合要求')
    }
}

//输入弹窗
const promptMessageBox = async () => {
    return new Promise(resolve => {
        ElMessageBox.prompt('', '请输入值', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            inputErrorMessage: '请输入内容',
            inputValidator: (value) => {
                return !isNullES(value)
            },
        }).then(({ value }) => {
            resolve(value)
        }).catch(() => {
            resolve()
        })
    })
}

//输入值
const resetFunText = async () => {
    const val = await promptMessageBox()
    if (isNullES(val)) return
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    //获取数组
    let arr = []
    if (index === 99) {
        //重置函数
        arr = selectEleFormula.value
    } else if (index === 3) {
        //参数1
        arr = selectEleFormula3.value
    } else if (index === 4) {
        //参数2
        arr = selectEleFormula4.value
    }
    if (arr.length > 0) {
        let { type, name } = getObjValue(arr[arr.length - 1])
        if (type === 'Element') {
            window?.$message.warning('输入值无法连续出现在元素后面')
            return
        }
        if (type === 'Text') {
            window?.$message.warning('输入值无法连续出现在输入值后面')
            return
        }
        if (type === 'Brackets' && name === ')') {
            window?.$message.warning('输入值无法连续出现在右括号后面')
            return
        }
    }
    //公共对象
    const obj = {
        type: 'Text',
        name: val,
        selected: false,
        index: getRandom(5),
    }
    if (index === 99) {
        selectEleFormula.value.push(obj)
    } else if (index === 3) {
        selectEleFormula3.value.push(obj)
    } else if (index === 4) {
        selectEleFormula4.value.push(obj)
    }
}

//括号
const resetFunBrackets = (val) => {
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    //公共对象
    const obj = {
        type: 'Brackets',
        name: val,
        selected: false,
        index: getRandom(5),
    }
    if (index === 99) {
        //重置函数
        selectEleFormula.value.push(obj)
    } else if (index === 3) {
        //参数1
        selectEleFormula3.value.push(obj)
    } else if (index === 4) {
        //参数2
        selectEleFormula4.value.push(obj)
    }
}

//运算符
const resetFunOperator = (val) => {
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    //获取数组
    let arr = []
    if (index === 99) {
        //重置函数
        arr = selectEleFormula.value
    } else if (index === 3) {
        //参数1
        arr = selectEleFormula3.value
    } else if (index === 4) {
        //参数2
        arr = selectEleFormula4.value
    }
    const map = formulaMenuMap.value
    if (arr.length <= 0) {
        window?.$message.warning('公式开头不能是运算符号')
        return
    }
    let { type, name } = getObjValue(arr[arr.length - 1])
    if (type === 'Operator') {
        window?.$message.warning('运算符号无法连续出现在运算符号后面')
        return
    }
    if (type === 'Brackets' && name === '(') {
        window?.$message.warning('运算符号无法连续出现在左括号后面')
        return
    }
    const obj = getObjValue(map[val])
    //公共对象
    const data = {
        type: 'Operator',
        name: symbolReg.exec(obj.name)[1],
        selected: false,
        template: obj.template,
        index: getRandom(5),
    }
    if (index === 99) {
        selectEleFormula.value.push(data)
    } else if (index === 3) {
        selectEleFormula3.value.push(data)
    } else if (index === 4) {
        selectEleFormula4.value.push(data)
    }
}

//删除
const resetFunDel = () => {
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    //获取数组
    let arr = []
    if (index === 99) {
        //重置函数
        arr = selectEleFormula.value
    } else if (index === 3) {
        //参数1
        arr = selectEleFormula3.value
    } else if (index === 4) {
        //参数2
        arr = selectEleFormula4.value
    }
    const newArr = deepClone(arr)
    if (newArr.length <= 0) {
        window?.$message.warning('请先添加相关元素')
        return
    }
    const indexs = arrIndex(newArr, 'selected', true)
    if (indexs !== -1) {
        newArr.splice(indexs, 1)
        if (index === 99) {
            selectEleFormula.value = newArr
        } else if (index === 3) {
            selectEleFormula3.value = newArr
        } else if (index === 4) {
            selectEleFormula4.value = newArr
        }
    } else {
        newArr.splice(newArr.length - 1, 1)
        if (index === 99) {
            selectEleFormula.value = newArr
        } else if (index === 3) {
            selectEleFormula3.value = newArr
        } else if (index === 4) {
            selectEleFormula4.value = newArr
        }
    }
}

//清空
const resetFunClear = () => {
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    if (index === 99) {
        //重置函数
        selectEleFormula.value = []
    } else if (index === 3) {
        //参数1
        selectEleFormula3.value = []
    } else if (index === 4) {
        //参数2
        selectEleFormula4.value = []
    }
}

//被点击
const selectEleFormulaItem = (item) => {
    const index = curRangeFocusIndex.value
    if (index <= 0) {
        window?.$message.warning('非正常操作')
        return
    }
    //获取数组
    let arr = []
    if (index === 99) {
        //重置函数
        arr = selectEleFormula.value
    } else if (index === 3) {
        //参数1
        arr = selectEleFormula3.value
    } else if (index === 4) {
        //参数2
        arr = selectEleFormula4.value
    }
    for (let i = 0; i < arr.length; i++) {
        if (item.index === arr[i].index) {
            arr[i].selected = !arr[i].selected
        } else {
            arr[i].selected = false
        }
    }
    if (index === 99) {
        selectEleFormula.value = arr
    } else if (index === 3) {
        selectEleFormula3.value = arr
    } else if (index === 4) {
        selectEleFormula4.value = arr
    }
}

//赋值给等号右边的数组
const processFormula = ref([])
const setProcessFormula = () => {
    const arr = selectEleFormula.value
    let leftNum = 0, rightNum = 0
    arr.forEach(({ type, name }) => {
        if (type === 'Brackets') {
            if (name === '(') {
                leftNum++
            } else if (name === ')') {
                rightNum++
            }
        }
    })
    if (leftNum !== rightNum) {
        window?.$message.warning('左右括号数量不相等,请先检查是否正确')
        return
    }
    processFormula.value = deepClone(arr)
    isResetFun.value = false
    isScrollBar.value = true
}

//获取项目数据
const projectId = ref('')
const projectList = ref([])
const getProjectDataApi = async () => {
    const { data } = await projectApi.page({
        current: 1,
        size: 99999,
    })
    projectList.value = getArrValue(data?.records)
}

//项目被选择
const contractId = ref('')
const contractList = ref([])
const projectChange = async () => {
    contractId.value = ''
    const { data } = await contractApi.getList(projectId.value)
    contractList.value = getArrValue(data)
}

//项目查询
const projectQueryClick = () => {
    console.log('原来就没做这个功能')
}

//允许偏差值范围
const deviationRangeSymbol = ref('【min,max】')

//模式切换
const deviationRangeResult = ref('1')
const deviationRangeResultChange = () => {
    if (deviationRangeResult.value === '1') {
        if (!['<', '≤'].includes(deviationRangeSymbol.value)) {
            curRangeFocusIndex.value = 1
        } else if (!['>', '≥'].includes(deviationRangeSymbol.value)) {
            curRangeFocusIndex.value = 2
        }
    } else if (deviationRangeResult.value === '2') {
        if (!['<', '≤'].includes(deviationRangeSymbol.value)) {
            curRangeFocusIndex.value = 3
        } else if (!['>', '≥'].includes(deviationRangeSymbol.value)) {
            curRangeFocusIndex.value = 4
        }
    }
}

//允许偏差值范围1
const deviationRangeTag1 = ref('')
const deviationRangeTags1 = ref([])
const deviationRangeBlur1 = () => {
    if (deviationRangeTag1.value) {
        if (deviationRangeTag1.value && deviationRangeTags1.value[0]) {
            emit('uncheck', deviationRangeTags1.value[0].id)
        }
        deviationRangeTags1.value = []
    }
}

//允许偏差值范围2
const deviationRangeTag2 = ref('')
const deviationRangeTags2 = ref([])
const deviationRangeBlur2 = () => {
    if (deviationRangeTag2.value) {
        if (deviationRangeTag2.value && deviationRangeTags2.value[0]) {
            emit('uncheck', deviationRangeTags2.value[0].id)
        }
        deviationRangeTags2.value = []
    }
}

//当前在哪个输入框
const curRangeFocusIndex = ref(0)
const rangeAddingTag = () => {
    console.log('原来的版本就啥也没做')
}

//选择参数
const isRangeSelectEle = ref(false)
const deviationRangeSelectEle = () => {
    const val = !isRangeSelectEle.value
    isRangeSelectEle.value = val
    isScrollBar.value = !val
}

//手写模式
const handWritText = ref('')
const handWritEleMap = ref({})
const isHandWritEle = ref(false)
const handWritClick = () => {
    try {
        let { text, eleMap } = formulaArrayToString(processFormula.value, resultFormula.value)
        handWritText.value = text
        handWritEleMap.value = JSON.stringify(eleMap)
        isHandWritEle.value = true
    } catch (error) {
        console.log(error)
        window?.$message.error('生成公式文本失败')
    }
}

//手写模式转换
const handWritTransform = () => {
    try {
        let formula = formulaStringToArray(handWritText.value, handWritEleMap.value, formulaMenuMap.value)
        processFormula.value = getArrValue(formula.processFormula)
        const results = resultFormula.value
        formula.resultFormula[0].id = results[0].id
        formula.resultFormula[0].name = results[0].name
        formula.resultFormula[0].tableElementKey = results[0].tableElementKey
        resultFormula.value[0].children = formula.resultFormula[0].children
        handWritEleClose()
    } catch (error) {
        console.log(error)
        window?.$message.error('转成配置用的数组失败')
    }
}

//手写模式关闭
const handWritEleClose = () => {
    isHandWritEle.value = false
    handWritText.value = ''
    handWritEleMap.value = {}
}

const findNumber = (array) => {
    for (const item of array) {
        if (!item.children) continue
        const child = item.children.find(child => child.number)
        if (child) return child.number
    }
    return ''
}

//保存
const submitLoading = ref(false)
const submitClick = async () => {
    if (isResetFun.value) {
        //重置函数
        setProcessFormula()
    } else {
        //允许偏差值范围
        submitLoading.value = true
        const result = deviationRangeResult.value
        deviationRangeObj.value = {
            symbol: deviationRangeSymbol.value,
            model: result,
            arguments1: result === '2' ? selectEleFormula3.value : deviationRangeTag1.value,
            arguments2: result === '2' ? selectEleFormula4.value : deviationRangeTag2.value,
        }
        //处理数据
        const process = processFormula.value, results = resultFormula.value
        let obj = formulaArrayToString(process, results)
        let deviationRangeText = rangeToString(deviationRangeObj.value, obj.eleMap)
        obj.eleMap.deviationRangeJson = JSON.stringify(deviationRangeObj.value)
        //特殊公式会有number
        let number = findNumber(process) || findNumber(results)
        //发起请求
        const { eleId, globalType, nodeId, pid } = getObjValue(dataInfo.value)
        const formData = {
            formula: obj.text,
            remark: '',
            nodeId: nodeId,
            elementId: eleId,
            scale: isRetain.value ? retainNum.value : '',
            number: number,
            map: JSON.stringify(obj.eleMap),
            scope: globalType,
            projectId: projectId.value || pid,
            dev: deviationRangeText,
        }
        let res = {}
        if (isNullES(formulaId.value)) {
            //新增
            res = await formulaApi.save({ ...formData, ver:1 })
        } else {
            //更新
            res = await formulaApi.update({ id: formulaId.value, ...formData })
        }
        const { code, msg, data } = getObjValue(res)
        if (code !== 200) {
            submitLoading.value = false
            return
        }
        let msgStr = '保存成功'
        if (msg === '公式已删除') {
            formulaId.value = ''
            msgStr = msg
        } else if (!isNullES(data)) {
            formulaId.value = data
        }
        window?.$message.success(msgStr)
        getFormulaStringToArrayApi()
        submitLoading.value = false
    }
}

//关闭抽屉
const drawerClose = () => {
    if (isResetFun.value) {
        //重置函数
        isResetFun.value = false
        isScrollBar.value = true
        curRangeFocusIndex.value = 0
    } else if (deviationRangeShow.value) {
        //允许偏差值范围
        deviationRangeShow.value = false
        isRangeSelectEle.value = false
        curRangeFocusIndex.value = 0
    } else {
        isShow.value = false
        //重置元素
        isResetFun.value = false
        isScrollBar.value = true
        //允许偏差值范围
        deviationRangeShow.value = false
        curRangeFocusIndex.value = 0
        //选择的元素
        selectEleFormula.value = []
        selectEleFormula3.value = []
        selectEleFormula4.value = []
        //手写模式
        isHandWritEle.value = false
        handWritText.value = ''
        handWritEleMap.value = {}
        emit('close')
    }
}
</script>

<style lang="scss">
@import '~src/styles/view/project/edit-formula';
</style>
