<template>
    <!-- 计算公式 -->
    <div>
        <basic-edit></basic-edit>
        <div>
            <div class="title">计算公式：</div>
            <el-button class="edit" @click="edit" :disabled="formItem.formulaFixed">编辑计算公式</el-button>
            <div class="tips">
                根据计算公式来完成表单中数据的自动计算
                <el-link type="primary" @click="detailVisible = true">详细说明</el-link>
            </div>
        </div>
        <div>
            <el-popover trigger="manual" v-model="formItem.verifyError">
            <p class="error-tips">计算公式无法计算，请重新编辑</p>
            <div class="content show" slot="reference">
                <div
                    :class="[
                        item.mold,
                        { active: activeIndex === index },
                        { point: item.title === '.' && item.mold === 'number' },
                    ]"
                    v-for="(item, index) in formItem.formula"
                    :key="index"
                >{{item.title}}</div>
            </div>
        </el-popover>
        </div>

        <el-dialog class="detail" title="详细说明" :visible.sync="detailVisible">
            <p class="head">可作为计算对象的控件：</p>
            <p>    1、【单行输入框】且文本验证为数字类型</p>
            <p>    2、【日期区间】且开启自动计算时长</p>
            <p>    3、【计算公式】且没有被其他计算公式使用</p>

            <p class="head">计算规则：</p>
            <p>    1、计算对象在子表单外：</p>
            <p>        1.1、无论计算公式在子表单外或内都是直接获取值进行计算</p>
            <p>    2、计算对象在子表单内：</p>
            <p>        2.1、如果计算公式和这个计算对象处于同一个子表单，则获取当前子表单内这个计算对象的值</p>
            <p>        2.2、如果计算公式和这个计算对象不处于同一个子表单，则获取所有子表单内这个计算对象所有值的总和</p>
        </el-dialog>

        <!-- 编辑计算公式 -->
        <el-dialog title="编辑计算公式" :visible.sync="visible">
            <div class="box">
                <div class="left">计算公式</div>
                <div class="right calc">
                    <div class="tips" v-if="!list.length">在下方选择计算对象和计算符号完成编辑</div>
                    <div class="content">
                        <div
                            :class="[
                                item.mold,
                                { active: activeIndex === index },
                                { point: item.title === '.' && item.mold === 'number' },
                            ]"
                            v-for="(item, index) in list"
                            :key="index"
                            @click="activeIndex = activeIndex === index ? -1 : index"
                        >{{item.title}}</div>
                    </div>
                    <div class="handle">
                        <div class="clear" v-if="activeIndex > -1" @click="list.splice(activeIndex, 1), activeIndex = -1">
                            <i class="el-icon-delete"></i>删除
                        </div>
                        <div class="back" v-if="list.length" @click="list.pop(), activeIndex === list.length ? activeIndex = -1 : ''">
                            <i class="el-icon-back"></i>后退
                        </div>
                        <div class="clear" v-if="list.length" @click="list = [], activeIndex = -1">
                            <i class="el-icon-delete-solid"></i>清空
                        </div>
                    </div>
                </div>
            </div>
            <div class="box">
                <div class="left">计算对象</div>
                <div class="right ">
                    <div
                        class="tips"
                        v-if="!itemList.length"
                    >
                        没有可计算的对象，请返回表单设计重新添加。
                        可作为计算对象的控件：【单行输入框】且文本验证为数字类型，【日期区间】且开启自动计算时长，【计算公式】
                    </div>
                    <div class="content">
                        <div
                            class="item"
                            v-for="(item, index) in itemList"
                            :key="index"
                            @click="add('item', item.title, item.type, item.uuid)"
                        >{{item.title}}</div>
                    </div>
                </div>
            </div>
            <div class="box">
                <div class="left">计算符号</div>
                <div class="right">
                    <div class="content">
                        <div class="item" v-for="(item, index) in symbol" :key="index" @click="add('symbol', item)">{{item}}</div>
                    </div>
                </div>
            </div>
            <div class="box">
                <div class="left">数字键盘</div>
                <div class="right">
                    <div class="content nine">
                        <div class="item" v-for="(item, index) in number" :key="index" @click="add('number', item)">{{item}}</div>
                    </div>
                </div>
            </div>
            <span slot="footer" class="dialog-footer">
                <el-button @click="visible = false, activeIndex = -1">取 消</el-button>
                <el-button type="primary" @click="save">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
export default {
    name: 'FormCalculate',
    components: {
        BasicEdit: () => import('@/common/formDesign/components/formEdit/components/BasicEdit')
    },
    data () {
        return {
            formItem: this.$store.state.form.formItem,
            visible: false, // 是否显示编辑计算公式
            detailVisible: false, // 是否显示详细说明
            list: [], // 公式列表
            itemList: [], // 计算对象列表
            activeIndex: -1, // 选中的符号
            symbol: '+-*/()', // 符号
            number: '1234567890.' // 数字
        }
    },
    created () {
        !this.formItem.formula ? this.init() : this.verifyTips()
        this.getItemList()
    },
    methods: {
        // 初始化
        init () {
            this.$set(this.formItem, 'formula', [])
        },
        // 获取计算对象（排除自己和已经被其他计算公式所使用的，避免死循环）
        getItemList () {
            const list = []
            const some = item => item.uuid === this.formItem.uuid
            const selfOrUsed = item => item.uuid === this.formItem.uuid || (item.formula && item.formula.some(some))
            const isNumber = item => item.inputType === 'number'
            const isCalculate = item => item.type === 'calculate' && !selfOrUsed(item)
            const isDateRange = item => item.type === 'dateRange' && item.date.time
            this.$parent.list.forEach(item => {
                if (isNumber(item) || isCalculate(item)) list.push(item)
                if (isDateRange(item)) {
                    const newItem = JSON.parse(JSON.stringify(item))
                    newItem.title = item.date.title
                    list.push(newItem)
                }
                if (item.type === 'subform') {
                    item.list.forEach(n => {
                        if (isNumber(n) || isCalculate(n)) {
                            const newN = JSON.parse(JSON.stringify(n))
                            newN.title = item.title + ' · ' + n.title
                            list.push(newN)
                        }
                        if (isDateRange(n)) {
                            const newN = JSON.parse(JSON.stringify(n))
                            newN.title = item.title + ' · ' + n.date.title
                            list.push(newN)
                        }
                    })
                }
            })
            this.itemList = list
        },
        // 添加计算
        add (mold, title, type, uuid) {
            if (this.itemList.length) {
                const item = { mold, title }
                if (type) {
                    item.type = type
                    item.uuid = uuid
                }
                if (this.activeIndex === -1) {
                    this.list.push(item)
                } else {
                    this.list.splice(this.activeIndex, 1, item)
                    this.activeIndex = -1
                }
            } else {
                this.$message('没有可计算的对象，请先添加数字输入框')
            }
        },
        // 编辑计算公式
        edit () {
            this.list = JSON.parse(JSON.stringify(this.formItem.formula))
            this.visible = true
        },
        // 保存计算公式
        save () {
            // 避免计算对象接数字，例如计算对象 a 的值是 1，则 “a23” 会解析成 123，所以使用 '(1)' 避免连在一起
            const formula = this.list.map(item => item.mold === 'item' ? '(1)' : item.title).join('')
            let right = true
            // eslint-disable-next-line no-eval
            try { eval(formula) } catch (e) { right = false }
            if (right) {
                this.formItem.formula = this.list
                this.visible = false
                this.activeIndex = -1
                this.verifyTips()
            } else {
                this.$message.warning('计算公式不符合规则，无法计算，请重新编辑')
            }
        },
        // 初始化时提示文字的定位有误，需要重新刷新
        verifyTips () {
            this.$parent.verifyCalculate(this.formItem)
        }
    }
}
</script>

<style lang="less" scoped>
@import "~styles/varibles.less";
.edit {
    width: 100%;
}
.tips {
    color: #909399;
    font-size: 14px;
    margin-top: 5px;
}
.box {
    display: flex;
    border: 1px solid #DCDFE6;
    font-size: 16px;
    & + .box {
        margin-top: -1px;
    }
    .left {
        flex-shrink: 0;
        width: 120px;
        display: flex;
        justify-content: center;
        align-items: center;
        border-right: 1px solid #DCDFE6;
    }
    .right {
        padding: 10px;
        flex-grow: 1;
        .tips {
            margin-top: 0;
            line-height: 42px;
            padding-left: 5px;
            font-size: 16px;
        }
        &.calc {
            padding-bottom: 0;
        }
        .handle {
            height: 40px;
            line-height: 40px;
            text-align: center;
            font-size: 16px;
            display: flex;
            justify-content: flex-end;
            user-select: none;
            & > div {
                width: 80px;
                cursor: pointer;
                i {
                    margin-right: 5px;
                    font-size: 18px;
                }
            }
            .back:hover {
                color: @textBuleColor;
            }
            .clear:hover {
                color: #F56C6C;
            }
        }
    }
}
.content {
    display: flex;
    flex-wrap: wrap;
    &.show {
        margin: 15px -5px 0;
        display: inline-flex;
        & > div {
            cursor: default;
            &:hover {
                background-color: #F2F6FC;
            }
        }
    }
    &.nine {
        width: 180px;
    }
    .item, .symbol, .number {
        margin: 5px;
        cursor: pointer;
        text-align: center;
    }
    .item {
        min-width: 50px;
        padding: 0 10px;
        height: 32px;
        line-height: 30px;
        background-color: #F2F6FC;
        border: 1px solid #E4E7ED;
        border-radius: 4px;
        &:hover {
            background-color: #E4E7ED;
        }
        &.active {
            color: #fff;
            background-color: @textBuleColor;
        }
    }
    .symbol, .number {
        width: 10px;
        line-height: 32px;
        &:hover {
            color: #000;
        }
        &.active {
            color: @textBuleColor;
        }
        &.point {
            width: 5px;
            font-weight: bold;
        }
    }
    .number + .number, .number + .point, .point + .number {
        margin-left: -5px;
    }
}
.error-tips {
    text-align: center;
    color: #F56C6C;
}
.detail {
    /deep/ .el-dialog__body {
        padding: 10px 60px 40px;
    }
    p {
        white-space: pre-wrap;
        &.head {
            margin: 20px 0 5px;
            font-weight: bold;
            font-size: 16px;
        }
    }
}
</style>
