事件demo
注意,有些触发事件不能同时存在,不然会报错,注意一下就好
frappe.ui.form.on('Scripting Test',{
// 页面刷新时的方法(保存时也会自动刷新)
refresh:function(frm){
frappe.msgprint("页面刷新时的方法---Hello D-cod")//弹窗弹出信息
frappe.show_alert({message: '这个右下角提示框',indicator: 'yellow'});
}
refresh:function(frm){
frappe.throw("This is an error------抛出异常,保存失败")//抛出异常,保存失败(好像并不会阻止到成功报错只是会弹)
}
//加载时输出信息
onload:function(frm){
frappe.msgprint("Hello Word from 'onload' event---加载时输出信息")
}
//验证时输出信息
validate:function(frm){
frappe.throw("Hello Word from 'validate' event验证时输出信息---验证时输出信息")
}
//保存前触发
before_save:function(frm){
frappe.throw("你好 Ikun 来自---保存前触发 报错信息'before_save' event")
}
//保存后触发
after_save:function(frm){
frappe.msgprint("你好 Ikun 来自---保存后触发 信息 'after_save' event")
}
//提交前触发
before_submit:function(frm){
frappe.throw("Hello Word from 'before_submit' event")
}
//提交时触发
on_submit:function(frm){
frappe.msgprint("Hello Word from 'on_submit' event")
}
//提交后触发
after_submit:function(frm){
frappe.msgprint("Hello Word from 'after_submit' event")
}
//取消前触发
before_cancel:function(frm){
frappe.throw("Hello Word from 'before_cancel' event")
} //有问题,会阻止取消
//取消后触发
after_cancel:function(frm){
frappe.msgprint("Hello Word from 'after_cancel' event")
}
//字段事件触发
enable:function(frm){
frappe.msgprint("Hello Word from 'enable' fieldname event")
} //勾选“启用”后会弹出
//子表事件触发
famlly_members_on_form_rendered:function(frm){
frappe.msgprint("Hello Word from 'famlly_members' child table fieldname event")
} //不懂跳过
after_save:function(frm){
//保存后输出全名
frappe.msgprint(__("The full name is '{0}'",
[frm.doc.first_name+" "+frm.doc.middle_name+" "+frm.doc.laste_name]))
//拼接打印内容
// //输出子表的关系
for (let row of frm.doc.famlly_members){
frappe.msgprint(__("{0},the family member name is '{1}' and relation is '{2}'",
[row.idx,row.name1,row.relation]))
}
} //循环打印子表信息
refresh:function(frm){
//进入单据时会出现一个蓝色提示框
frm.set_intro("你可以进行编辑此单据")
//判断这单据是否为新的单据
if(frm.is_new()){
//处于新单据时,会有以下提示内容
frm.set_intro("你现在在创建一个新的单据")
}
} //进去单据会有一个提示框内容
validate:function(frm){
//设置全名
frm.set_value('full_name',frm.doc.first_name+" "+frm.doc.middle_name+" "+frm.doc.laste_name)
//添加一个子表数据
let row = frm.add_child('famlly_members',{
name1:'tom',
relation:'father',
age:53,
})
} //提交后创建了一个全名框,内容为全名,并且子表自动填写了固定的数据
//当勾选enable时
enable:function(frm){
frm.set_df_property('first_name','reqd',1) //设置为必填字段
frm.refresh_field("first_name");//刷新
frm.set_df_property('middle_name','read_only',1) //设置为只读字段
frm.refresh_field("middle_name");//刷新
frm.toggle_reqd('age',true)//设置为必填字段
} //勾选后姓名和年龄带星号,变成必填,中间名消失
refresh:function(frm){
frm.add_custom_button("Click Me Button",() =>{
frappe.msgprint(__("You clicked me!"));
})
frm.add_custom_button("Click Me1",() =>{
frappe.msgprint(__("You clicked me1!"));
},'click me')
frm.add_custom_button("Click Me2",() =>{
frappe.msgprint(__("哎呦你干嘛点我!!"));
},'click me')
} //创建按钮,自定义按钮名字和点击按钮后输出的弹框内容
});
//子表
frappe.ui.form.on('Famlly Members', {
name1:function(frm){
frappe.msgprint("Hello Word from child table 'name1' fieldname event")
}
age(frm,cdt,cdn){
frappe.msgprint("Hello Word from child table 'age' fieldname event")
}
}) //点击子表添加字段,在子表name1(名字)字段填写内容,焦点离开后会弹出提示框
frm是要在框架方法里面才能用,如果想框架方法外面赋值可以用cur_frm.set_value('字段名','值');
案例
frappe.ui.form.on('Bill of materials', {
one: function(frm) {
update_layer_number(frm);
},
two: function(frm) {
update_layer_number(frm);
},
three: function(frm) {
update_layer_number(frm);
},
four: function(frm) {
update_layer_number(frm);
}
});
function update_layer_number(frm) {
const one = frm.doc.one!=undefined?`${frm.doc.one}`:"";
const two = frm.doc.two!=undefined?`.${frm.doc.two}`:"";
const three = frm.doc.three!=undefined?`.${frm.doc.three}`:"";
const four = frm.doc.four!=undefined?`.${frm.doc.four}`:"";
const layer_number = `${one}${two}${three}${four}`;
frm.set_value('layer_number', layer_number);
}
案例2
// 在'Order Tracking'表单上设置事件处理器
frappe.ui.form.on('Order Tracking',{
// 当表单加载时执行的函数
onload(frm){
// 设置查询条件,只查询类型为"发货公司"的记录
frm.set_query("dispatch_company",function(){
return {
filters:{
"type":"发货公司" // 过滤条件:类型为"发货公司"
}
};
});
// 设置查询条件,只查询类型为"收货公司"的记录
frm.set_query("receiving_company",function(){
return {
filters:{
"type":"收货公司" // 过滤条件:类型为"收货公司"
}
};
});
},
// 当unit_price字段发生变化时执行的函数
unit_price(frm){
// 如果weight和unit_price都有值,则计算amount的值
if(frm.doc.unit_price & frm.doc.pcs_all){
frm.set_value('amount',frm.doc.unit_price * frm.doc.pcs_all) // 计算amount的值
}
},
// 当unit_price字段发生变化时执行的函数
pcs_all(frm){
// 如果weight和unit_price都有值,则计算amount的值
if(frm.doc.unit_price & frm.doc.pcs_all){
frm.set_value('amount',frm.doc.unit_price * frm.doc.pcs_all) // 计算amount的值
}
},
// 当表单刷新时执行的函数
refresh(frm) {
// 在这里编写你的代码
}
})
案例3
通过api填表(((在获取部门方法里))),api在报表里面爬到的,+等等
frappe.ui.form.on('Stock Entry', {
refresh(frm) {
if (frm.is_new() && frm.doc.purpose == 'Material Transfer for Manufacture'){
frm.set_value('inspection_required', 0)
}
let batch_field = frm.get_docfield("items", "batch_no");
batch_field.get_route_options_for_new_doc = function(row) {
if (frm.is_new()) return;
return {
"item": row.doc.item_code,
}
}
//部门输入框为空时自动填部门------------------------------2023.10.10------10.12----------------
if(frm.doc.departments===""||frm.doc.departments===null||frm.doc.departments===undefined){
console.log('获取部门。。。。。。。。。。。。。。。'+frm.doc.departments)
获取部门(frm);
}
//显示评论
let 标签属性 = '[data-page-route="Stock Entry"] [class="comments-count"]';
const 评论控制 = setInterval(()=>{//如果出去了就不要显示了
if(window.location.href.includes('stock-entry/M')){
if (window.location.href!==url) {
显示评论(标签属性);
}
//侧边栏有显示的消息条数
if (document.querySelector(标签属性).innerText==0) {
显隐元素封装版('隐');
}
}
else{
console.log('出去了,隐藏掉');
显隐元素封装版('隐');
url = "你干嘛 哎呦";
clearInterval(评论控制); // 停止定时器
}
},444);
}
})
//-------------------------------------------2023.10.10------------------
function 获取部门(frm){
// 获取创建人的名字 找不到就 获取当前用户名
let userName = document.querySelectorAll('[data-page-route="Stock Entry"] .created-by b')[0]?.innerText ?? frappe.session.user_fullname;
userName = userName==='你'? frappe.session.user_fullname: userName;
console.log(`获取到的名字为${userName}`)
// 构造请求数据
const formData = new FormData();
formData.append('doctype', 'Employee');
formData.append('fields', '["`tabEmployee`.`department`"]');
formData.append('filters', `[["Employee","employee_name","like","${userName}"]]`);
// 设置请求头
const headers = new Headers();
headers.append('X-Frappe-CSRF-Token', frappe.csrf_token);
headers.append('Content-Type','application/x-www-form-urlencoded');
// 构造请求参数
const requestOptions = {
method: 'POST',
headers,
body: new URLSearchParams(formData).toString()
};
// 发送请求
fetch('/api/method/frappe.desk.reportview.get', requestOptions)
.then(res => res.json())
.then(data => {
frm.set_value('departments', data.message.values[0][0])
if(window.location.href.includes('stock-entry/M')){ //这样子新增的(stock-entry/new)就不会弹出来
frappe.show_alert({message: '原本部门为空,自动填写部门成功,保存才生效',indicator: 'green'})
}
})
.catch(error => frappe.show_alert({message: '自动填部门失败,请检查您是否在员工列表或者是否有读取员工列表的权限',indicator: 'yellow'}));
}
//-----------------------2023.10.10----------------------------------
// 仅适用于系统过渡期,方便车间人员等其他人员查看评论
//------------------------下面为评论代码------------------------------
var 显评吗 = true;
var url = null;
var 评论s = '';
function 显示评论(标签属性){
url = window.location.href;
//判断是否初始化了评论元素
if (!document.querySelector('#评论')){初始化评论元素();}
//先初始化评论2023.10.12
document.getElementById('评论').innerHTML = '没有评论<br>没有评论';
// 获取所有符合条件的元素
let elements = document.querySelectorAll(`[data-page-route="${标签属性.split('"')[1]}"] [data-doctype="Comment"] .content`);
if(elements.length>0/* && 显评吗*/){
评论s = ' ';
// 遍历元素innerText
elements.forEach(e => {评论s += `<div class="indicator-pill whitespace-nowrap red" style="max-width: 400px; height: auto; display: block; white-space: unset;"> ${e.innerText} </div><br>`; });
document.getElementById('评论').innerHTML ='评论: ' + 评论s; // 设置的文本内容
}else{
显隐元素封装版('隐');
}
//侧边栏有显示的消息条数*************************↓↓↓↓↓↓↓↓↓↓**
if (document.querySelector(标签属性).innerText>0) {
显隐元素封装版('显');
}
载入提示库();
}
function 显隐元素封装版(显隐){
显隐=显隐=='显'?"显示":"隐藏"; //2023.10.12
显评吗=显隐=='显'?false:true;
显隐元素('评论', 显隐)
显隐元素('显评按钮',显隐)
}
function 显隐元素(id,显隐){
try{document.getElementById(id).style.display = 显隐==="显示"?'block':'none';}catch(err){console.log(id+'还没有加载到页面')}
}
function 初始化评论元素(){
// 创建一个按钮固定在右下角
var btn = document.createElement("div"); // 创建一个元素
btn.setAttribute("class", "row form-section card-section visible-section");
btn.setAttribute("style", "opacity: 77%;");
btn.style.position = "fixed"; // 设置按钮的定位方式为固定
btn.style.top = "3px"; // 设置按钮距离底部的距离为10px
btn.style.left = `${document.querySelector('.navbar-nav').getBoundingClientRect().right}px`;
btn.style.zIndex = 1050;
btn.style.paddingBottom = 0;
btn.setAttribute("title", "点击直接到底部");
btn.id="评论";
btn.onclick = function() {window.scrollTo(0, document.body.scrollHeight);}; // 滚动到底部
document.body.appendChild(btn);
let x = document.createElement("div"); //2023.10.9-----点击隐藏评论
x.innerHTML="点击隐藏评论"
x.style.position = "fixed"; // 设置按钮的定位方式为固定
x.style.top = "3px"; // 设置按钮距离底部的距离为10px
x.style.zIndex = 1050;
x.style.top = "1px"; // 设置按钮距离底部的距离为10px
x.id="显评按钮";
x.style.left = `${document.querySelector('.navbar-nav').getBoundingClientRect().right}px`;
x.setAttribute("class", "btn btn-secondary btn-default btn-sm");
document.body.appendChild(x);
x.onclick = function() {
显评吗=!显评吗;
x.innerHTML=显评吗?'点击隐藏评论':'点击显示评论';
document.getElementById('评论').style.display = 显评吗?'block':'none';
};
}
function 载入提示库(){
// 如果未加载提示库,才动态插入
if (!是否加载了脚本('https://unpkg.com/tippy.js@5')) {
//导入提示库
const script1 = document.createElement('script');
script1.src = 'https://unpkg.com/popper.js@1';
const script2 = document.createElement('script');
script2.src = 'https://unpkg.com/tippy.js@5';
document.head.appendChild(script1);
// 在append script2前,确保script1加载完成
script1.onload = () => { document.head.appendChild(script2); }
script2.onload = () => {
// tippy.js 加载完成后,才能用方法
tippy('#评论', {
content: "点击直接到底部"
});
}
}else{tippy('#评论', {content: "点击直接到底部"}); }
}
function 是否加载了脚本(src) {
// 查找头部是否存在该src的script
const scripts = document.head.querySelectorAll('script');
for (let script of scripts) {
if (script.src === src) {return true;}
}
return false;
}
//------------------------上面为评论代码------------------------------
案例4(防呆
两个为空时,两个都非必填,但是填了一个就必须填另外一个(tippy方法要导入库,没就删掉没影响
frappe.ui.form.on('Production Record', {
//报废物料编号防呆2023.10.16+++++++++++++++++++++++++++++++++++
scrap_item_code(frm){
if(frm.doc.scrap_item_code){
frm.set_df_property("scrap_warehouse", "reqd", 1);
tippy('input[data-fieldname="scrap_warehouse"]', {
content: "填了这个要填报废品仓",
showOnCreate: true
});
}else{
frm.set_df_property("scrap_warehouse", "reqd", 0);
}
},
//报废品仓防呆2023.10.16+++++++++++++++++++++++++++++++++++
scrap_warehouse(frm){
if(frm.doc.scrap_warehouse){
frm.set_df_property("scrap_item_code", "reqd", 1);
tippy('input[data-fieldname="scrap_item_code"]', {
content: "填了这个要填报废物料编号",
showOnCreate: true
});
}else{
frm.set_df_property("scrap_item_code", "reqd", 0);
}
}
})
案例5(监控url
//监控url是否有变化
frappe.router.on('change', function() {
//alert("url有变化了");
if(window.location.href.includes('production-record/')){
document.getElementById('ikun').style.display = 'block';
}
else{
document.getElementById('ikun').style.display = 'none';
}
})