基于前端技术实现的全面预算编制系统

前言

在现代商业环境中,预测销售数据和实际成本是每个公司CEO和领导都极为重视的关键指标。然而,由于市场的不断变化,准确地预测和管理这些数据变得愈发具有挑战性。为了应对这一挑战,建立一个高效的系统来管理和审查销售数据的重要性不言而喻。今天小编就将为大家介绍一下如何使用葡萄城公司的纯前端表格控件SpreadJS实现一个预算编制系统。

环境准备

Node.js

VSCode代码编辑器

完整代码Github地址(可在阅读本文时配合参考使用)

使用代码实现的在线Demo地址(可在阅读本文时配合参考使用)

实现步骤

1)自定义菜单栏

上图中红色方框划出来的菜单栏叫做在线表格编辑器(Designer),Designer的菜单提供了各种定制化的能力,如新增菜单,修改菜单执行的逻辑,修改图标,修改文字以及删除菜单等功能。

观察上图中,首先新建了一个“预算操作(定制按钮)”tab ,此tab内容包括了三部分,分别是“预算类型”、“预算编制”、“数据”。对应的代码如下:

let config = JSON.parse(JSON.stringify(GC.Spread.Sheets.Designer.DefaultConfig));
config.ribbon.push({id: "fill-custom",text: "预算操作(定制按钮)",buttonGroups: [{label:"预算类型",commandGroup:{}  },    {label: "预算编制", commandGroup:{}},{label: "数据", commandGroup:{}}]
})
designer.setConfig(config)

通过上述代码,我们来看看实现结果:

Ok ,发现添加了一个“预算操作(定制按钮)”tab,点击此tab,已经有了基础框架

接下来,继续,我们设置当前tab为激活状态,加上active属性,这样子页面初始化后看到的当前tab就是“预算操作(定制按钮)”

{id: "fill-custom",text: "预算操作(定制按钮)",active: true,buttonGroups: []
}

接下来,我们设置预算模型command, 我们再次看上面的第一张图,发现预算类型只有一个节点,且该节点是一个下拉框。对应的代码实现方式如下:

{label:"预算类型",commandGroup: {children: ["selectBudgetType"]}
}, 

接下来定义“selectBudgetType”,代码如下所示:( 关于定义下拉框子菜单的实现方法详细解释,可以参考此篇文章)

const budgetType = {cost: 'cost' ,   //成本预算sales: 'sales'   //销售预算
}
let selectBudgetType = {text: "选择预算类型",comboWidth: 120,type:"comboBox",commandName: "selectBudgetType",dropdownList:[{text:"成本预算",value: budgetType.cost},{text:"销售预算",value:budgetType.sales},],execute:(context,propertyName) => {console.log('选择',propertyName)},
}
config.commandMap = {selectBudgetType}
designer.setConfig(config)

上述代码为子菜单“selectBudgetType”定义了text,type ,以及dropdownList以及点击事件。exexute方法中propertyName对应的是dropdownList中的value值。

结果如下:

上述代码已经熟悉了如何定义菜单以及子菜单,接下来的两个子菜单(预算编制和数据)就不重复详细介绍,直接上代码:

config.ribbon.push({id: "fill-custom",text: "预算操作(定制按钮)",active: true,buttonGroups: [{label:"预算类型",commandGroup: {children: ["selectBudgetType"]}},    {label: "预算编制",thumbnailClass: "ribbon-thumbnail-editing",commandGroup: {children: [ "distributeTask"]}},{label: "数据",commandGroup: {children: ["clearLocalData"]}}]
})
config.commandMap = {selectBudgetType:{text: "选择预算类型",comboWidth: 120,type:"comboBox",commandName: "selectBudgetType",dropdownList:[{text:"成本预算",value: budgetType.cost},{text:"销售预算",value:budgetType.sales},],execute:(context,propertyName) => {console.log('选择',propertyName)}},distributeTask: {title: "下发预算任务",text: "预算编制",iconClass: "distribute-icon",bigButton: true,commandName: "distributeTask",execute: function (context) {}},clearLocalData: {title: "清除本地缓存",text: "清除本地缓存",iconClass: "clear-local-icon",bigButton: true,commandName: "clearLocalData",execute: function () {localStorage.clear()}},
}
designer.setConfig(config)

icon相关代码,注意iconClass要添加相应的背景图片。

.clear-local-icon {background: url("../assets/clear.png");background-size: 35px 35px;
}
.distribute-icon {background: url("../assets/distribute.png");background-size: 35px 35px;
}

上述三个子菜单中的execute方法需要自定义,如选择选择预算类型后,模板需要进行切换。

2)设置模板

当“选择预算类型”选择“成本预算”时,加载cost.json文件

当“选择预算类型”选择“销售预算”时,加载sales.json文件

let selectBudgetType = {text: "选择预算类型",comboWidth: 120,type:"comboBox",commandName: "selectBudgetType",dropdownList:[{text:"成本预算",value: budgetType.cost},{text:"销售预算",value:budgetType.sales},],execute:(context,propertyName) => {if(propertyName){selectedBudget.value = propertyNameloadTemplate(context,propertyName,taskId)}  },getState:(context)=>{return selectedBudget.value},
}const loadTemplate = async (designer,fileName,taskId) => {let templateStr = await BusinessType.getTemplate(fileName)let template = JSON.parse(templateStr)let spread = designer.getWorkbook()spread.fromJSON(template)  
}

上述代码介绍了【选择预算类型】下拉框选中的事件,选中后,导入对应的json文件,通过fromJSON进行导入。

对于需要设置的模板,可以通过Designer中菜单快速设计,其菜单基本与Excel一致,对于熟悉Excel的用户来说,真的很友好。

3)设置数据源

下面小编以“销售预算”模板为例,介绍如何设置数据源:

点击“数据”tab,接下来点击“工作表绑定”,此时出现右侧字段列表Panel。发现字段列表中存在“id”和“name ",这是因为在模板(sales.json)中已经设置好字段。

此时进行数据绑定setDataSource():

const bindInitialData = (spread,type,taskId) => {// 绑定初始数据let data = defaultBudgetData[type]let source = new GC.Spread.Sheets.Bindings.CellBindingSource(data)spread.suspendPaint()let sheetCount = spread.getSheetCount()for(let i=0; i<sheetCount;i++){let sheet = spread.getSheet(i)sheet.setDataSource(source)}spread.resumePaint()taskId.value = data.id
}
const defaultBudgetData = {[budgetType.cost]: {id:`成本NV-${getNowTime()}`,//项目编号name:'',    //项目名称city: '',   //项目所在地customer: '',    //客户名称price: 0        //本次报价
},[budgetType.sales]:{id: `销售NV-${getNowTime()}`,name:''}
}

4)任务下发

(1)在任务下发前 ,需要确认预测因子,预测因子基于往年数据,确认接下来的销售计划。

(2)填写预算名称 。

(3)点击“预算编制”菜单。

distributeTask: {title: "下发预算任务",text: "预算编制",iconClass: "distribute-icon",bigButton: true,commandName: "distributeTask",execute: function (context) {confirmDistribute(context,selectedBudget,distributeVisible)}
},const confirmDistribute = (context,selectBudgetType,distributeVisible) => {/**预算任务下发时必填信息校验 */let sheet = context.getWorkbook().getSheet(0)let source = sheet.getDataSource().getSource()for(let key in source){if(!source[key]){ElMessage.error("红色区域必填项信息缺失")return}}// 确认是否下发编制任务ElMessageBox.confirm("确认下发预算编制任务吗?","下发确认",{confirmButtonText:'确认',cancelButtonText:"取消",type:'warning'}).then(() => {// 确认下发,存储当前预算模板,下发部门信息saveBudgetRecord(context, selectBudgetType)distributeBudgetTask(context,distributeVisible)}).catch(() => {ElMessage({type:'error',message:'取消发布'})})
}

在上述代码confirmDistribute()中,通过getDataSource()获取数据源,来判断红色区域的必填项是否填写。当确认下发任务后,执行saveBudgetRecord 、distributeBudgetTask方法。

5)填写任务

当确定下发任务后,对不同部门生成不同的编制链接。此弹窗可以参考代码中的OnlineDesigner.vue文件。

部门经理获取链接,打开链接,显示内容是自己部门区域预算明细填写和实际填写,此时,部门经理可以在左侧蓝色区域填写,而其他单元格不能编辑,这个是怎么做到的呢?具体可以参考这篇文章中第二点对少部分单元格可以编辑。

var defaultStyle = new GC.Spread.Sheets.Style();
defaultStyle.locked = false;
sheet.setDefaultStyle(defaultStyle, GC.Spread.Sheets.SheetArea.viewport);
// 设置第1行不可编辑
var style = new GC.Spread.Sheets.Style();
style.locked = true;
style.backColor = "red";
sheet.setStyle(0, -1, style);
// 设置表单保护
sheet.options.isProtected = true;  

介绍完单元格的权限后,我们再来看下上图中还有哪些值得说一说的功能。

(1)添加签名

当经理设置完预算后,可以在区域总监单元格右键,看到多出来两个菜单“添加签名”和“添加手写签名”。

所以接下来介绍如何在右键菜单中新增菜单并定义其事件,代码如下:

let signMenu = {text:"添加签名",name:"signName",command:"signMenuCommand",workArea: "viewport"
}
spread.contextMenu.menuData.push(signMenu)

上述代码在spread.contextMenu.menuData中push了一条对象,结果就是可以在右键菜单中看见“添加签名菜单” ,观察到上述对象定义了command属性,接下来定义“signMenuCommand”:

let signMenuCommand = {canUndo: true,execute: function(context,options,isUndo){if(isUndo){GC.Spread.Sheets.Commands.undoTransaction(context,options)return true}else{GC.Spread.Sheets.Commands.startTransaction(context,options)let {activeRow,activeCol,sheetName} = optionslet sheet = context.getSheetFromName(sheetName)sheet.getCell(activeRow,activeCol).value(user).backColor('#F7A711').font('bold normal 15px normal')GC.Spread.Sheets.Commands.endTransaction(context,options)return true}}
}
commandManager.register("signMenuCommand",signMenuCommand,null, false, false, false, false)

上述代码是SpreadJS中注册命令的方法,并提供了撤销机制。我们主要看else里面的内容:首先从上下文context中获取sheet对象,接着获取单元格并设置内容、背景色、字体等。上述两段代码就实现了在SpreadJS中在右键菜单中添加菜单,并完整相应的点击逻辑。

(2)添加手写签名

接下来,我们看看如何设置“添加手写签名”:

// 注册签名的右键菜单
let commandManager = spread.commandManager()
let signMenu = {text:"添加手写签名",name:"handWriteName",command:"handWriteCommand",workArea: "viewport"
}
spread.contextMenu.menuData.push(signMenu)
let handWriteCommand = {canUndo: false,execute: function(context,options,isUndo){showWriteDialog.value = true}
}
commandManager.register("handWriteCommand",handWriteCommand,null, false, false, false, false)

添加菜单和菜单命令的方式与前文一致,不同的就是execute的执行逻辑。

最后,签名设置后,就可以点击“提交预算”按钮。

对了,如果数据不符合预期,可能会有红色预警,比如

这个是SpreadJS的数据验证功能,我们可以通过UI方式设置。如下图所示:

6)编制完成

当所有部门经理填写完预算后,就可以点击“编制完成”

此时点击“预算审核”,预算类型设置为“销售预算”,可以看到有一条待审核的标签,点进去看看。

看到了我们熟悉的页面

此时点击“华东”sheet看看

这个时候就看到了华东部门经理填写的销售预测数据,这个时候点击右上角的“导入年度实际销售数据”看看。

嗯,表格内容基本上填写完整了,这时候审核员(副总经理)如果对销售数据表示满意,可以签上自己的大名,就可以点击“审核完毕了”

当四个sheet都“审核完毕”,此时返回首页,发现标签变了。

这时候可以进行打印了。

最后

简单的全面预算编制系统就算介绍完了。大家可以在Demo地址实际体验下。总结下本文介绍的SpreadJS的几个知识点:

1、自定义Designer菜单

2、导入模板

3、设置数据源

4、获取数据源

5、自定义右键菜单

6、单元格权限

如果您想了解更多的信息,欢迎点击这篇参考资料查看。

扩展链接:

【干货放送】财务报表勾稽分析要点,一文读尽!

为什么你的财务报表不出色?推荐你了解这四个设计要点和!

纯前端类 Excel 表格控件在报表勾稽分析领域的应用场景解析

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hbuilderx打包苹果证书获取步骤

简介&#xff1a; 目前app开发&#xff0c;很多企业都用H5框架来开发&#xff0c;而uniapp又是这些h5框架里面最成熟的&#xff0c;因此hbuilderx就成为了开发者的首选。然而,打包APP是需要证书的&#xff0c;那么这个证书又是如何获得呢&#xff1f; 生成苹果证书相对复杂一些…

操作系统:进程间的通信

进程间通信方式 管道 单向传输&#xff0c;先进先出&#xff0c;容量较小&#xff0c;效率低 匿名管道 特点 作用于父子进程间只能保持一个读端一个写端生命周期应当保持一致 管道只剩下读端时会进入非阻塞状态&#xff0c;只剩下写端的时候写满然后阻塞等待读端读数据 …

flask_restful规范返回值之参数设置

设置重命名属性和默认值 使用 attribute 配置这种映射 , 比如&#xff1a; fields.String(attributeusername) 使用 default 指定默认值&#xff0c;比如&#xff1a; fields.String(defaultsxt) from flask import Flask,render_template from flask_restful import A…

商城小程序项目实现监控的可观测性最佳实践

前言 微信小程序是一种轻量级的应用程序&#xff0c;用户可以在微信内直接使用&#xff0c;无需下载安装。它具有独立的开发框架和生态系统&#xff0c;支持丰富的功能和交互&#xff0c;包括社交、购物、服务等。 观测云对微信小程序的监控能够实时收集性能指标、错误日志和…

AIGC,ChatGPT,Prompt 万能提示词

AIGC ChatGPT 职场案例 AI 绘画 与 短视频制作 PowerBI 商业智能 68集 Mysql 8.0 54集 Oracle 21C 142集 Office 2021实战应用 Python 数据分析实战&#xff0c; ETL Informatica 数据仓库案例实战 51集 Excel 2021实操 100集&#xff0c; Excel 2021函数大全 80集 Excel 2021…

使用 NocoDB 一键将各种数据库转换为智能表格

NocoDB 是一款开源的无代码数据库平台&#xff0c;可以进行数据管理和应用开发。它的灵感来自 Airtable&#xff0c;支持与 Airtable 类似的电子表格式交互、关系型数据库 Schema 设计、API 自动生成等特性。 但与 Airtable 相比&#xff0c;NocoDB 完全免费且代码开源&#xf…

MySQL查询约束

1 DML DML 数据操作语句 插入 insert 更新 update 删除 delete 1.1 更新 语法 update 表名 set 字段 值 [, 字段2 值2, ... ] [where 字段 值]; -- [, 字段2 值2, ... ] 是指,可选的,可以同时修改多个列的值 -- [where 字段 值] 是指,可选的,加上是指过滤,只更新符合条…

安达发|电子产品制造企业APS生产排程软件

在电子脉动的世界中&#xff0c;时间是芯片上的电流&#xff0c;效率是电路板上的速度。在这个时代&#xff0c;每一微秒都蕴藏着无限可能&#xff0c;每一决策都关乎着企业的生死存亡。APS生产排程软件&#xff0c;是您的电子制造帝国中的智慧大脑&#xff0c;以卓越的创造力&…

科技引领趋势:3D元宇宙展厅在各行业中的应用及其未来展望

随着技术的不断进步&#xff0c;3D元宇宙展厅正逐渐成为各行各业展示产品的新选择。相较于传统的线下展厅&#xff0c;3D元宇宙展厅以其独特的优势&#xff0c;为产品展示和品牌推广提供了全新的可能性。 一、虚拟与现实的完美融合 3D元宇宙展厅是指在虚拟世界中构建的三维展览…

k8s记录-基础配置1

1、基础yaml文件格式 1.1、namespace apiVersion: v1 kind: Namespace metadata:name: namelabels:name: namekubectl apply -f namespace.yaml 1.2、Service service示例 apiVersion: v1 kind: Service metadata:name: ilanni-httpd-svcnamespace: ilanni-namespace spec:…

HarmonyOS入门笔记1配置环境

文章目录 下载安装DevEco Studio配置环境先认识DevEco Studio界面工程目录工程级目录模块级目录 app.json5module.json5main_pages.json通知栏预览区 运行模拟器 下载安装DevEco Studio 去官网下载DevEco Studio完了安装 配置环境 打开已安装的DevEco Studio快捷方式进入配置…

微服务高级篇(五):可靠消息服务

文章目录 一、消息队列MQ存在的问题&#xff1f;二、如何保证 消息可靠性 &#xff1f;2.1 生产者消息确认【对生产者配置】2.2 消息持久化2.3 消费者消息确认【对消费者配置】2.4 消费失败重试机制2.5 消费者失败消息处理策略2.6 总结 三、处理延迟消息&#xff1f;死信交换机…