Ant Design Vue 树形表格计算盈收金额

news2024/10/6 14:35:59

树形表格计算

    • 一、盈收金额计算
      • 1、根据需要输入的子级位置,修改数据
      • 2、获取兄弟节点数据,并计算兄弟节点的金额合计
      • 3、金额合计,遍历给所有的父级

一、盈收金额计算

1、根据需要输入的子级位置,修改数据

2、获取兄弟节点数据,并计算兄弟节点的金额合计

3、金额合计,遍历给所有的父级

<template>
    <a-modal :title="titleMap[mode]" :visible="visible" :destroyOnClose="true" :maskClosable="false" @cancel="handleCancel"
        width="95%">
        <a-spin :spinning="spinning" tip="加载中...">
            <a-table :columns="columns" bordered :data-source="newSource" :scroll="{ x: 800, y: 500 }" :pagination="false"
                :rowKey="(record, index) => { return record.projectId }" :defaultExpandAllRows="true"
                v-if="newSource.length">
                <template slot="promote" slot-scope="text,record">
                    <span>
                        {{ rateCompute(record.preActual, record.budget) }}
                    </span>
                </template>
                <template slot="budget" slot-scope="text,record">
                    <div class="editable-cell">
                        <div v-if="editable" class="editable-cell-input-wrapper">
                            <div v-if="editableData[record.projectId]">
                                <a-input v-model="editableData[record.projectId]['budget']"
                                    @pressEnter="save(editableData[record.projectId])" type="number"
                                    @change="e => e.target.value = e.target.value.replace(/^0+(\d)|[^\d]+/g, '')" />
                                <a-icon type="check" @click="save(editableData[record.projectId])"
                                    style="margin-right: 20px;" />
                                <a-popconfirm title="确定取消?" @confirm="cancel(record.projectId)">
                                    <a-icon type="close" />
                                </a-popconfirm>
                            </div>
                            <div v-else>{{ text }}</div>
                        </div>
                        <div v-else class="editable-cell-text-wrapper">
                            <div v-if="record.children == null">
                                {{ text || ' ' }}
                                <a-icon type="edit" @click="edit(record)" />
                            </div>
                            <div v-else>
                                {{ text || ' ' }}
                            </div>
                        </div>
                    </div>
                </template>
            </a-table>
        </a-spin>
        <template slot="footer">
            <a-button key="back" @click="handleCancel">
                关闭
            </a-button>
            <a-button type="primary" :visible="visibleBtn" :loading="loadingBtn" @click="handleSubmit">
                保存
            </a-button>
        </template>
    </a-modal>
</template>

JS

import { cloneDeep } from 'lodash-es';
export default {
    data() {
        return {
            visible: false,
            dataSource: [],
            newSource: [], //变化的源数据
            spinning: true,
            columns: [],//头部表单

            editableData: {},// 修改的位置数据
            editable: false, //是否编辑
            visibleBtn: false,
            loadingBtn: false,
            mode: "add",
            titleMap: {
                add: '新增',
                edit: '修改'
            },
        }
    },
    methods: {
        //计算比率
        // 本月比上月情况=(本月数字-上月数字)/上月数字,如果本月大于上月,结果就是正数,即上升,反之为下降
        rateCompute(a, b) {
            if (a > 0 && b > 0) {
                if (a < b) return ((((b - a) / a) * 100).toFixed(2)) + '%'
                else if (b < a) '-' + ((((b - a) / a) * 100).toFixed(2)) + '%'
                else return '0%'
            } else {
                if (a == 0 && b > a) return '100%'
                else return '0%'
            }
        },
        edit(row) {
            this.editable = true
            this.editableData[row.projectId] = cloneDeep(row)
        },
        save(row) {
            this.editable = false
            this.calculate(row)
        },
        // 计算
        calculate(row) {
			//计算时,需要同步执行	
            this.fun1(row)
            delete this.editableData[row.projectId];
        },
        fun1(row) {
            if (row.inOrOut == 2) {
                if(Number(row.budget) > 0){
                    this.getObj(this.newSource, row.projectId, Number('-' + row.budget), row, callback)
                }
                else{
                    this.getObj(this.newSource, row.projectId, Number(row.budget), row, callback)
                }
                
            } else {
                this.getObj(this.newSource, row.projectId, Number(row.budget), row, callback)
               
            }
            // 使用回调,同步执行下面的方法
            function callback(isFind, _this, row) {
                if (isFind) {
                    _this.fun2(row)
                }
            }


        },
        fun2(row) {
            // 获取兄弟节点的父级id
            let brotherParentId = row.parentProjectId
            // 获取兄弟节点数据
            let brotherParentArr = this.getBrotherParentId(this.newSource, brotherParentId)
            console.log(brotherParentArr)
            if (brotherParentArr.length > 0) {
                // 兄弟数组的和  相差值
                let ParentVal = brotherParentArr.reduce((accumulator, currentValue) => Number(accumulator) + Number(currentValue));
                if (ParentVal) {
                    this.fun3(row, ParentVal)
                }
            }

        },
        fun3(row, ParentVal) {
            // 相关连的数据包括原来未改变的初始值
            let joinedArr = this.get_level_all(this.dataSource, row.projectId).filter(item => item.projectId != row.projectId)
            let _this = this
            // 相差值
            if (joinedArr.length > 0) {
                joinedArr.forEach((item) => {
                    _this.getParentId(_this.newSource, item.projectId, Number(ParentVal))
                });
            }
        },
        // 根据id ,找到当前元素的对象,并进行赋值
        getObj(data, id, val, row, callback) {
            let isFind = false
            data.find((item) => {
                if (item.projectId === id) {
                    if (val == 0) item.budget = '0'
                    else item.budget = Number(val)
                    item.promote = this.rateCompute(Number(item.preActual), Number(item.budget))
                    isFind = true
                } else if (item.children != null && item.children.length > 0) {
                    this.getObj(item.children, id, val, row, callback);
                }
            });
            if (isFind) {
                callback(isFind, this, row)
                return isFind
            }
        },
        // 根据id,找到所有的上级id
        get_level_all(data, id, arr = []) {
            data.find((item) => {
                if (item.projectId === id) {
                    arr.push(item);
                    return true;
                } else if (item.children != null && item.children.length > 0) {
                    arr = this.get_level_all(item.children, id, arr);
                    if (arr.length) {
                        arr.push(item);
                        return true;
                    } else {
                        return false;
                    }
                }
                return false;
            });
            return arr;
        },
        // 根据id,找到所有的同级数据
        getBrotherParentId(data, id, arr = []) {
            data.find((item) => {
                if (item.parentProjectId == id) {
                    // 收支类型,1:收入,2:支出,3:其它
                    // 支出:减
                    if(item.inOrOut == '2'){
                        if(Number(item.budget)>0){
                            arr.push((item.inOrOut == '2' ? Number(('-' + item.budget)) : Number(item.budget)));
                        }else{
                            arr.push(Number(item.budget));
                        }
                    }else{
                        arr.push(Number(item.budget));
                    }
                    
                } else if (item.children != null && item.children.length > 0) {
                    this.getBrotherParentId(item.children, id, arr);
                }
            });
            return arr;
        },
        // 根据相差值遍历相关的父级或祖级
        getParentId(arr, id, numDiffer) {
            arr.forEach(item => {
                if (item.projectId == id) {
                    item.budget = Number(this.sumChildren(item.children))
                    item.promote = this.rateCompute(item.preActual, item.budget)
                }
                if (item.children != null && item.children.length > 0) {
                    this.getParentId(item.children, id, numDiffer)
                }
            })
        },
        // 获取子集得计算和
        sumChildren(children) {
            let sum = 0
            children.map(item => {
                if (item.inOrOut == '2' && Number(item.budget) < 0) {
                    sum += Number(item.budget)
                } else {
                    sum += item.inOrOut == '2' ? Number(('-' + item.budget)) : Number(item.budget)
                }
            })
            return sum
        },
        // 取消
        cancel(key) {
            this.editable = false
            delete this.editableData[key];
        },
                //显示
        open(mode = 'add', par) {
            this.mode = mode;
            this.visible = true;
			//接口数据,在下面
            let headers = res.data.headers
            //去除不需要显示的列
            headers.map(item => {
                if (item.hidden == false) this.operator(item)
            })
            this.columns.push({
                title: '提升比率',
                dataIndex: 'promote',
                key: 'promote',
                align: 'left',
                width: 120,
                scopedSlots: { customRender: 'promote' }
            })
            let row = res.data.rows
            //树形表格,children没有数据需要为空
            this.handNull(row)
            this.dataSource = row
            this.spinning = false
            this.newSource = row
        },
        // 子集没数据,赋值为空 null
        handNull(data) {
            data.forEach((item) => {
            	//计算提升比率
                item.promote = this.rateCompute(item.preActual, item.budget)
                if (item.children.length == 0) {
                    item.children = null
                } else {
                    this.handNull(item.children);
                }
            });
        },
        // columns 表头赋值
        operator(item) {
            let obj = {}
            if (item.columnId == 'projectName') {
                obj['title'] = item.name
                obj.dataIndex = 'name'
                obj.key = 'name'
                obj.align = 'left'
            }
            else if (item.columnId == 'preActual') {
                obj['title'] = item.name
                obj.dataIndex = 'preActual'
                obj.key = 'preActual'
                obj.align = 'left'
                obj.width = 200
            }
            else if (item.columnId == 'budget') {
                obj['title'] = item.name
                obj.dataIndex = 'budget'
                obj.key = 'budget'
                obj.align = 'left'
                obj.width = 200
                obj.scopedSlots = { customRender: 'budget' }
            }
            else return;
            this.columns.push(obj)
        },
        //关闭
        handleCancel() {
            this.visible = false;
            this.editable = false
            this.$emit("close");
        },
        // 确认
        handleSubmit() {
            this.loadingBtn = true;
            this.visibleBtn = true;
            //新增或修改
            let Api = this.mode == 'add' ? add : edit
            Api(par).then(res => {
                if (res.code === 200) {
                    this.$notification['success']({
                        message: '提示',
                        description: '保存成功!',
                        duration: 8
                    })
                    this.visible = false
                    this.$emit("success");

                } else {
                    this.$notification['error']({
                        message: '提示',
                        description: res.message,
                        duration: 8
                    })
                }
                this.visibleBtn = false
                this.loadingBtn = false

            })
        },

 }

json


{
	"code": 200,
	"message": "操作成功",
	"data": {
		"title": "月度预算",
		"tabulatorId": "146",
		"storeId": "159",
		"storeName": "麓谷公园店",
		"tabulator": "李生",
		"headers": [{
				"columnId": "projectId",
				"name": "项目ID",
				"hidden": true,
				"primary": false
			},
			{
				"columnId": "projectName",
				"name": "项目名称",
				"hidden": false,
				"primary": false
			},
			{
				"columnId": "isLeaf",
				"name": "是否叶子",
				"hidden": true,
				"primary": false
			},
			{
				"columnId": "inOrOut",
				"name": "收支类型",
				"hidden": true,
				"primary": false
			},
			{
				"columnId": "parentProjectId",
				"name": "上级预算项目ID",
				"hidden": true,
				"primary": false
			},
			{
				"columnId": "preActual",
				"name": "10月",
				"hidden": false,
				"primary": false
			},
			{
				"columnId": "budget",
				"name": "11月预算",
				"hidden": false,
				"primary": true
			}
		],
		"rows": [{
			"projectId": "165",
			"name": "利润",
			"parentProjectId": null,
			"inOrOut": 1,
			"children": [{
					"projectId": "174",
					"name": "成本",
					"parentProjectId": "165",
					"inOrOut": 2,
					"children": [{
						"projectId": "175",
						"name": "原材料成本",
						"parentProjectId": "174",
						"inOrOut": 2,
						"children": [],
						"budget": "0",
						"preBudget": "",
						"preActual": "0",
						"leaf": true
					}],
					"preBudget": "",
					"preActual": "0",
					"budget": "0",
					"leaf": false
				},
				{
					"projectId": "173",
					"name": "税额",
					"parentProjectId": "165",
					"inOrOut": 2,
					"children": [],
					"preBudget": "",
					"preActual": "0",
					"budget": "0",
					"leaf": true
				},
				{
					"projectId": "166",
					"name": "营业收入",
					"parentProjectId": "165",
					"inOrOut": 1,
					"children": [{
						"projectId": "170",
						"name": "外卖折后营收",
						"parentProjectId": "166",
						"inOrOut": 1,
						"children": [{
								"projectId": "172",
								"name": "外卖优免",
								"parentProjectId": "170",
								"inOrOut": 2,
								"children": [],
								"preBudget": "",
								"preActual": "0",
								"budget": "0",
								"leaf": true
							},
							{
								"projectId": "171",
								"name": "外卖折前营收",
								"parentProjectId": "170",
								"inOrOut": 1,
								"children": [],
								"preBudget": "",
								"preActual": "0",
								"budget": "0",
								"leaf": true
							}
						],
						"preBudget": "",
						"preActual": "0",
						"budget": "0",
						"leaf": false
					}],
					"preBudget": "",
					"preActual": "0",
					"budget": "0",
					"leaf": false
				}
			],
			"preBudget": "",
			"preActual": "0",
			"budget": "0",
			"leaf": false
		}]
	}
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全面解析IEC 60364三种接地系统的概念、特点及应用

根据IEC 60364规定的各种保护方式、术语概念&#xff0c;低压配电系统按接地方式的不同分为三类&#xff0c;即 TT 、 TN 和 IT 系统。 1.TT系统TT grounding system TT供电系统&#xff1a;是指将电气设备的金属外壳直接接地的保护系统&#xff0c;称为保护接地系统&#xff…

运动装备经营小程序商城效果如何

运动装备可包含服装、帐篷、渔具、箱包鞋帽等&#xff0c;对喜欢外出的人来说&#xff0c;靠谱的装备是关键&#xff0c;往往更容易选择品牌和信得过的商家。 而对商家来说&#xff0c;如何打造品牌提升卖货经营效率和提升营收是重中之重&#xff1b;互联网时代需要商家拓展线…

sklearn模型中预测值的R2_score为负数

目录 正文评论区参考链接 正文 Sklearn.metrics下面的r2_score函数用于计算R&#xff08;确定系数&#xff1a;coefficient of determination&#xff09;。它用来度量未来的样本是否可能通过模型被很好地预测。 分值为 1 表示最好&#xff0c;但我们在使用过程中&#xff0c…

大结局!OpenAI创始人奥特曼和 Greg Brockman 将加入微软!!!

持续48小时的OpenAI政变大戏终于迎来了大结局&#xff01; 微软堪称最大赢家&#x1f4a5;&#x1f4a5;&#x1f4a5; 微软CEO刚刚宣布&#xff1a; 我们仍然致力于与 OpenAI 的合作伙伴关系&#xff0c;并对我们的产品路线图、我们在 Microsoft Ignite 上宣布的一切继续创…

单片机和FreeRTOS上跑机器人ROS的应用

机器人的应用越来越广泛了&#xff0c;大家熟知的稚晖君直接创业搞机器人&#xff0c;可想而至&#xff0c;接下来的十年&#xff0c;机器人绝对是热门的行业。 目前市面上很多机器人都是基于一套叫做ROS的系统开发的&#xff0c;今天就给大家分享一个跑在MCU上&#xff0c;基…

Notpad-- ubuntu下载安装

Notpad-- ubuntu下载安装 下载 Gitee链接&#xff1a; https://gitee.com/cxasm/notepad– 安装 sudo apt install *.deb运行 /opt/apps/com.hmja.notepad/files/Notepad--出错 需要安装qt5 sudo apt-get install qt5-default

数据结构~~~~ [队列] ~~~~

文章目录 队列队列的概念与结构队列的接口实现***队列的初始化******队列的销毁******队列的插入与创建节点******队列的删除******队列的队头数据******队列的队尾数据******队列的判空*** 队列 队列的概念与结构 队列的插入数据在队尾出数据在队头&#xff08;尾入头出&…

51单片机/STM32F103/STM32F407学习1_点亮LED灯

目录&#xff1a; 基础知识单片机从0实现单片机GPIO介绍 参考连接&#xff1a; 野火霸天虎教程 https://doc.embedfire.com/products/link/zh/latest/mcu/stm32/ebf_stm32f407_batianhu_v1_v2/download/stm32f407_batianhu_v1_v2.html x.1 基础知识 x.1.1 指针中的取地址&a…

房间够亮还有必要台灯吗?考研必备护眼台灯推荐

我认为不管台灯是否够亮还是需要使用台灯的&#xff01; 一般房间的吸顶灯距离桌面都有很长的一段距离&#xff0c;虽说我们正常观察时是觉得亮度很足了&#xff0c;不过实际上照射到桌面的光线是所剩无几的&#xff0c;远远达不到我们学习、办公时所需要的亮度。而且单开一盏室…

多协议数据库管理软件 Navicat Premium 16 mac中文版功能

Navicat Premium 16 mac是一款跨平台数据库管理工具&#xff0c;支持多种数据库类型&#xff0c;如MySQL、MariaDB、Oracle、SQLite、PostgreSQL等等。它提供了丰富的数据库管理功能和工具&#xff0c;可以帮助开发人员和数据库管理员快速地创建、管理和维护数据库。 Navicat P…

效率提升利器:Automa插件的实用指南

Automa是一个chrome扩展&#xff0c;通过拖拽0代码实现工作流&#xff0c;模拟网页的各种点击、表单填写等操作&#xff0c;使用时点击插件脚本一键执行&#xff0c;或者设置定时执行&#xff0c;从而简化我们的工作。 功能介绍 官方文档地址&#xff1a;Getting started | Au…

长期使用老旧、劣质、不合格电源线的危害有多大?

电源线作为电力、信息传输的重要工具&#xff0c;如今已经成为人类生活生产必不可少的产品之一&#xff0c;电气装备、电器照明、通信、家装、工业生产等多个行业&#xff0c;电源线都发挥着重要的载体作用。由于市场上电源线产品品类繁多&#xff0c;价格、品质参差不齐&#…

深度态势感知的含义

深度态势感知的含义 当年德国对苏联发动的侵略战争&#xff0c;本来是两个大国内讧的结果。这次入侵完全是希特勒和最高统帅部几个人就决定了的。他们是怎样对待关于苏联的情报呢&#xff1f;英国人写的《苏德战争》中有这样描述&#xff1a;"很多真实的情报对元首来说则毫…

六要素超声波微气象仪一款气象监测设备

WX-WQX6 随着科技的发展&#xff0c;人们对天气的预测和掌控能力越来越强。在这个领域&#xff0c;六要素超声波微气象仪以其精准、实时的气象监测能力&#xff0c;赢得了众多关注。这款仪器不仅可以实时监测温度、湿度、风速、风向、气压和雨量六个气象要素&#xff0c;还可以…

OFI libfabric原理及应用解析

Agenda 目录/议题 编译通信软件硬件和软件带来的挑战为什么需要libfabriclibfabric架构API分组socket应用 VS libfabric应用区别GPU数据传输示例 编译通信软件 可靠面向连接的TCP和无连接的数据报UDP协议高性能计算HPC或人工智能AI 软硬件复杂性带来的挑战 上千个节点的集群, …

SpringSecurity+JWT权限认证

SpringSecurity默认的是采用Session来判断请求的用户是否登录的&#xff0c;但是不方便分布式的扩展 虽然SpringSecurity也支持采用SpringSession来管理分布式下的用户状态&#xff0c;不过现在分布式的还是无状态的Jwt比较主流 一、创建SpringBoot的项目 spring-boot-starte…

buildAdmin 后端控制器的代码分析

buildAdmin的代码生成&#xff0c;很像是 fastadmin 的生成模式&#xff0c;当我们利用数据库生成了一个控制器的时候&#xff0c;我们可以看到&#xff0c; 它的生成代码很简洁 <?phpnamespace app\admin\controller\askanswer;use app\common\controller\Backend;/*** 回…

在Spring Boot中使用Thymeleaf开发Web页面

引言&#xff1a; 为啥写这篇文章呢&#xff1f;我明明就没怎么用过这个Thymeleaf进行web开发&#xff0c;用JSP也行&#xff0c;三剑客也行&#xff0c;或者Vue&#xff0c;React&#xff0c;PHP等等&#xff0c;不好吗&#xff1f; 那我为啥写这篇博客呢&#xff1f;这个写了…

1445 雉兔同笼

Tint(input()) for i in range(T):s input().split()head int(s[0])foot int(s[1])rabbitfoot/2-headchicken2*head-foot/2if rabbit>0 and chicken>0 and rabbit.is_integer():print(int(chicken),int(rabbit))else:print(-1)

Playcanvas后处理-辉光bloom

&#xff08;一&#xff09;Bloom介绍 Bloom&#xff08;辉光、光晕、泛光&#xff09;是一种常见的摄像机后处理&#xff08;PostProcessing&#xff09;效果&#xff0c;用于再现真实世界相机的成像伪影。这种效果会产生从图像中明亮区域边界延伸的光条纹&#xff08;或羽毛…