功能增加和优化

- 隐藏头部菜单默认为:True
- 增加开启/关闭全屏功能
- 简易过滤的样式优化
- 仪表台编辑只有管理员可见
This commit is contained in:
夜未央
2025-09-06 23:58:22 +08:00
parent daf2d0c869
commit 3399f2eb7c
8 changed files with 923 additions and 785 deletions
@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<!-- 快速筛选组件 -->
<!-- 快速筛选组件 -->
<t t-name="header_search_panel.QuickFilter" owl="1">
<div t-if="props.showLabel" class="header-filter-label">
<span><t t-esc="props.string" /></span>
</div>
<!-- quick filter 内的筛选循环 -->
<div class="header-filter-value">
<div class="selection-options">
<!-- <div t-if="props.showLabel" class="header-filter-label">
<span>
<t t-esc="props.string" />
</span>
</div> -->
<!-- quick filter 内的筛选循环 -->
<div class="header-filter-value">
<div class="selection-options">
<t t-foreach="filters" t-as="filter" t-key="filter_index">
<input
t-att-type="props.isSingle ? 'radio' : 'checkbox'"
@@ -19,13 +20,14 @@
t-on-change="onFilterSelected"
t-att-checked="filter.isChecked"
/>
<label t-att-for="filter.inputId" t-esc="filter.description"/>
<!-- Lucky Edit By 20250906 增加class和样式 -->
<label class="btn btn-primary" t-att-for="filter.inputId" t-esc="filter.description"/>
<!-- End Edit -->
</t>
</div>
</div>
<button class="filter-reset" type="button" aria-label="重置筛选" t-on-click="resetFilter">
<i class="fa fa-close fa-lg"/>
</button>
</div>
</t>
</templates>
<i class="fa fa-close fa-lg"/>
</button>
</div>
</t>
</templates>
@@ -0,0 +1,56 @@
/* label 基础样式 */
.header-filter-value .selection-options label {
display: inline-block;
margin: 6px 8px 6px 0;
padding: 6px 16px;
font-size: 14px;
line-height: 1.5;
color: #444;
background: #fafafa;
border: 1px solid #e0e0e0;
border-radius: 999px;
/* 完全圆角 chip */
cursor: pointer;
transition: all 0.25s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
text-decoration: none !important;
/* 🔥 去掉下划线 */
user-select: none;
/* 防止文字选中 */
}
/* hover 效果 */
.header-filter-value .selection-options label:hover {
border-color: #4a90e2;
color: #4a90e2;
background: #f0f7ff;
box-shadow: 0 2px 6px rgba(74, 144, 226, 0.15);
}
/* 选中效果 */
.header-filter-value .selection-options input:checked+label {
background: linear-gradient(135deg, #4a90e2, #357ABD);
border-color: #357ABD;
color: #fff;
font-weight: 500;
box-shadow: 0 3px 8px rgba(74, 144, 226, 0.3);
}
/* 小动画:点击时轻微缩放 */
.header-filter-value .selection-options label:active {
transform: scale(0.95);
}
#header_search_collapse {
.header-search-filter {
.header-filter-value {
.selection-options {
input[type="radio"]:checked+label,
input[type="checkbox"]:checked+label {
left: 0 !important;
}
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -2,7 +2,7 @@
<templates xml:space="preserve">
<!--Dashboard Header : Show title and dashboard settings button-->
<t t-name="ks_dashboard_ninja.KsDashboardNinjaHeader" owl="1">
<t t-if="state.ks_dashboard_manager">
<t t-if="state.ks_dashboard_manager and isAdmin">
<div class="ks_dashboard_header d-flex p-3 w-100 bg-white justify-content-between flex-column flex-lg-row"
t-ref="ks_dashboard_header">
<t t-if="state.ks_dashboard_manager and !this.ks_dashboard_data.ks_ai_explain_dash">
@@ -128,7 +128,7 @@
"sh_backmate_theme_adv_enterprise/static/src/js/navbar.js",
'sh_backmate_theme_adv_enterprise/static/src/js/dropdown.js',
"sh_backmate_theme_adv_enterprise/static/src/xml/menu.xml",
"sh_backmate_theme_adv_enterprise/static/src/scss/menu/fullscreen_toggle.scss",
#Theme Config
"sh_backmate_theme_adv_enterprise/static/src/js/theme_config_custom.js",
@@ -10,7 +10,7 @@ import { isMobileOS } from "@web/core/browser/feature_detection";
import { session } from "@web/session";
import { useService } from "@web/core/utils/hooks";
import { jsonrpc } from "@web/core/network/rpc_service";
import { onMounted } from "@odoo/owl";
import { onMounted, useState } from "@odoo/owl";
var icon_style = 'standard';
var sidebar_collapse_style = '';
@@ -29,21 +29,40 @@ patch(NavBar.prototype, {
this.getMenuBadgeData();
this.orm = useService("orm");
enable_multi_tab = session.sh_enable_multi_tab
// 定义状态
this.state = useState({
exFullscreen: false,
});
// 监听全屏状态变化(包括 ESC 退出)
document.addEventListener("fullscreenchange", () => {
this.state.exFullscreen = !!document.fullscreenElement;
});
document.addEventListener("webkitfullscreenchange", () => {
this.state.exFullscreen = !!document.webkitFullscreenElement;
});
document.addEventListener("mozfullscreenchange", () => {
this.state.exFullscreen = !!document.mozFullScreenElement;
});
document.addEventListener("MSFullscreenChange", () => {
this.state.exFullscreen = !!document.msFullscreenElement;
});
onMounted(() => {
if (enable_multi_tab){
this.addmultitabtags()
if (enable_multi_tab) {
this.addmultitabtags()
}
$('.direct_menu').on('click', function (ev) {
$('.sh_dropdown_div').find('.active').removeClass('active');
$('.dropdown-menu').find('.active').removeClass('active');
$(ev.currentTarget).addClass('active')
$('.sh_dropdown_div').find('.active').removeClass('active');
$('.dropdown-menu').find('.active').removeClass('active');
$(ev.currentTarget).addClass('active')
});
//默认隐藏top bar
this._click_hide_top_bar();
});
const data = await this.orm.searchRead(
"sh.back.theme.config.settings",
[['id', '=', 1]],
['icon_style','sidebar_collapse_style','search_style']
);
"sh.back.theme.config.settings",
[['id', '=', 1]],
['icon_style', 'sidebar_collapse_style', 'search_style']
);
if (data) {
var i;
for (i = 0; i < data.length; i++) {
@@ -59,9 +78,35 @@ patch(NavBar.prototype, {
}
}
}
},
/**
* 切换全屏显示
**/
_click_fullscreen_toggle(ev) {
const elem = document.documentElement;
if (
document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement
) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen(); // Safari
} else if (document.msExitFullscreen) {
document.msExitFullscreen(); // IE11
}
} else {
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen(); // Safari
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen(); // IE11
}
}
},
/**
* 获取菜单角标
* */
@@ -77,12 +122,12 @@ patch(NavBar.prototype, {
method: "POST",
dataType: 'json',
async: false, // 设置为同步请求
beforeSend: (xhr) => {xhr.setRequestHeader('Content-Type', 'application/json');},
data : JSON.stringify(jsonData),
beforeSend: (xhr) => { xhr.setRequestHeader('Content-Type', 'application/json'); },
data: JSON.stringify(jsonData),
success: (result) => {
this.menuBadgeInfo = result.result;
},
error: function(xhr, status, error) {
error: function (xhr, status, error) {
// 请求失败的处理逻辑
console.error("Error:", error);
}
@@ -118,123 +163,123 @@ patch(NavBar.prototype, {
return badgeCount;
},
onMouseenter_o_app2(ev){
onMouseenter_o_app2(ev) {
$(ev.target.parentElement).find('ul.show_ul').css("transition", "all 0.6s ease 0s;");
$(ev.target.parentElement).find('ul.show_ul').slideDown("slow");
},
onMouseenter_sh_backmate_theme_appmenu_div(ev){
onMouseenter_sh_backmate_theme_appmenu_div(ev) {
if ($('.o_web_client').hasClass('o_rtl')) {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
$('.o_action_manager').css("margin-right", '260px');
$('.o_menu_systray').css("width", '260px');
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("right", "260px");
$('.o_mail_systray_dropdown').css("right", "260px");
$('.o_switch_company_menu .dropdown-menu').css("right", "260px");
if (sidebar_collapse_style != 'expanded' && search_style != 'collapsed') {
$('.sh_search_container').css("margin-right", '190px');
$('#object1').css("padding-right", "0px");
$('.multi_tab_section').css("margin-right", '260px');
}
}
} else {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
$('.o_action_manager').css("margin-right", '260px');
$('.o_menu_systray').css("width", '260px');
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("right", "260px");
$('.o_mail_systray_dropdown').css("right", "260px");
$('.o_switch_company_menu .dropdown-menu').css("right", "260px");
if (sidebar_collapse_style != 'expanded' && search_style != 'collapsed') {
$('.sh_search_container').css("margin-right", '190px');
$('#object1').css("padding-right", "0px");
$('.multi_tab_section').css("margin-right", '260px');
}
}
} else {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
if (sidebar_collapse_style != 'expanded') {
$('.multi_tab_section').css("margin-left", '260px');
$('.o_action_manager').css("margin-left", '260px');
}
$('.o_menu_systray').css("width", '260px');
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("left", "260px");
$('.o_mail_systray_dropdown').css("left", "260px");
$('.o_switch_company_menu .dropdown-menu').css("left", "260px");
if (sidebar_collapse_style != 'expanded' && search_style != 'collapsed') {
$('.sh_search_container').css("margin-left", '190px');
$('#object1').css("padding-left", "0px");
}
}
}
if (sidebar_collapse_style != 'expanded') {
$('.multi_tab_section').css("margin-left", '260px');
$('.o_action_manager').css("margin-left", '260px');
}
$('.o_menu_systray').css("width", '260px');
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("left", "260px");
$('.o_mail_systray_dropdown').css("left", "260px");
$('.o_switch_company_menu .dropdown-menu').css("left", "260px");
if (sidebar_collapse_style != 'expanded' && search_style != 'collapsed') {
$('.sh_search_container').css("margin-left", '190px');
$('#object1').css("padding-left", "0px");
}
}
}
},
onMouseleave_sh_backmate_theme_appmenu_div(ev){
onMouseleave_sh_backmate_theme_appmenu_div(ev) {
if ($('.o_web_client').hasClass('o_rtl')) {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
if (sidebar_collapse_style != 'expanded') {
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').slideUp("slow");
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').css("transition", "all 0.6s ease 0s;");
$('#object1').css("padding-right", "0px");
$('.multi_tab_section').css("margin-right", '80px');
}
if (sidebar_collapse_style != 'expanded') {
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').slideUp("slow");
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').css("transition", "all 0.6s ease 0s;");
$('#object1').css("padding-right", "0px");
$('.multi_tab_section').css("margin-right", '80px');
}
$('.o_action_manager').css("margin-right", '68px');
$('.sh_search_container').css("margin-right", '0px');
$('.o_menu_systray').css("width", '68px');
if ($('ul.dropdown-menu.dropdown-menu-right').hasClass('show_ul')) {
}
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("right", "68px");
$('.o_mail_systray_dropdown').css("right", "68px");
$('.o_switch_company_menu .dropdown-menu').css("right", "68px");
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').css("display", "none");
}
} else {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
if (sidebar_collapse_style != 'expanded') {
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').slideUp("slow");
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').css("transition", "all 0.6s ease 0s;");
$('#object1').css("padding-left", "0px");
$('.multi_tab_section').css("margin-left", '80px');
$('.o_action_manager').css("margin-left", '68px');
}
$('.o_action_manager').css("margin-right", '68px');
$('.sh_search_container').css("margin-right", '0px');
$('.o_menu_systray').css("width", '68px');
if ($('ul.dropdown-menu.dropdown-menu-right').hasClass('show_ul')) {
}
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("right", "68px");
$('.o_mail_systray_dropdown').css("right", "68px");
$('.o_switch_company_menu .dropdown-menu').css("right", "68px");
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').css("display", "none");
}
} else {
if ($('#js_bar_toggle_btn_mobile').css("top") == '0px') {
if (sidebar_collapse_style != 'expanded') {
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').slideUp("slow");
$(ev.target).find('.o_app2.sh_dropdown.active').parents('.sh_dropdown_div').find('ul.show_ul').css("transition", "all 0.6s ease 0s;");
$('#object1').css("padding-left", "0px");
$('.multi_tab_section').css("margin-left", '80px');
$('.o_action_manager').css("margin-left", '68px');
}
$('.sh_search_container').css("margin-left", '0px');
$('.o_menu_systray').css("width", '68px');
if ($('ul.dropdown-menu.dropdown-menu-right').hasClass('show_ul')) {
}
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("left", "68px");
$('.o_mail_systray_dropdown').css("left", "68px");
$('.o_switch_company_menu .dropdown-menu').css("left", "68px");
$('.sh_search_container').css("margin-left", '0px');
$('.o_menu_systray').css("width", '68px');
if ($('ul.dropdown-menu.dropdown-menu-right').hasClass('show_ul')) {
}
$('.o_main_navbar ul.o_menu_systray .o_debug_manager .dropdown-menu.show').css("left", "68px");
$('.o_mail_systray_dropdown').css("left", "68px");
$('.o_switch_company_menu .dropdown-menu').css("left", "68px");
}
}
}
}
},
_click_o_app(ev){
_click_o_app(ev) {
$(".sh_backmate_theme_appmenu_div").toggleClass("sidebar_toggle");
$(".blur_div").toggleClass("blur_toggle");
$('.o_menu_systray').css("opacity", '1');
/*todo later*/
/*$(this).parents('.sh_dropdown_div').find('.sh_dropdown').removeClass('sh_dropdown');
$(this).parents('.sh_dropdown_div').find('.show_ul').css("display", "none");*/
$(this).parents('.sh_dropdown_div').find('.show_ul').css("display", "none");*/
},
_click_toggle_bar(ev){
_click_toggle_bar(ev) {
if ($("#toggle_bar").hasClass("fa-bars")) {
ev.target.classList.toggle('fa-times');
$("#toggle_bar").removeClass('fa-bars');
} else {
ev.target.classList.toggle('fa-bars');
$("#toggle_bar").removeClass('fa-times');
}
ev.target.classList.toggle('fa-times');
$("#toggle_bar").removeClass('fa-bars');
} else {
ev.target.classList.toggle('fa-bars');
$("#toggle_bar").removeClass('fa-times');
}
},
_click_js_bar_toggle_btn_mobile(ev){
_click_js_bar_toggle_btn_mobile(ev) {
$(".sh_backmate_theme_appmenu_div").toggleClass("sidebar_toggle");
$(".blur_div").toggleClass("blur_toggle");
$('.o_menu_systray').css("opacity", '1');
if ($('.sidebar_toggle').css("max-width") != '100%') {
$('.o_action_manager').css("margin-left" , '0px');
$('.o_menu_systray').css("width", '0px');
$('.o_menu_systray').css("opacity", '0');
$('ul.dropdown-menu.dropdown-menu-right').css("display", 'none');
$('ul.dropdown-menu.dropdown-menu-right').removeClass('show_ul');
$('span.sh_dropdown').removeClass('sh_dropdown');
$("#toggle_bar").addClass('fa-bars');
$("#toggle_bar").removeClass('fa-times');
$("#js_bar_toggle_btn_mobile").css("display","none");
$('.o_action_manager').css("margin-left", '0px');
$('.o_menu_systray').css("width", '0px');
$('.o_menu_systray').css("opacity", '0');
$('ul.dropdown-menu.dropdown-menu-right').css("display", 'none');
$('ul.dropdown-menu.dropdown-menu-right').removeClass('show_ul');
$('span.sh_dropdown').removeClass('sh_dropdown');
$("#toggle_bar").addClass('fa-bars');
$("#toggle_bar").removeClass('fa-times');
$("#js_bar_toggle_btn_mobile").css("display", "none");
} else {
$('.o_action_manager').css("margin-left" , '310px');
$('.o_action_manager').css("margin-left", '310px');
$('.o_menu_systray').css("width", '100%');
$('.o_menu_systray').css("opacity", '1');
$("#toggle_bar").removeClass('fa-bars');
@@ -242,16 +287,16 @@ patch(NavBar.prototype, {
}
},
_click_blur_div(ev){
_click_blur_div(ev) {
if ($('#js_bar_toggle_btn_mobile').css("top") != '0px') {
if (!$('.blur_div').hasClass('blur_toggle')) {
$(".sh_backmate_theme_appmenu_div").toggleClass("sidebar_toggle");
$(".blur_div").toggleClass("blur_toggle");
$('.o_menu_systray').css("opacity", '1');
}
}
if (!$('.blur_div').hasClass('blur_toggle')) {
$(".sh_backmate_theme_appmenu_div").toggleClass("sidebar_toggle");
$(".blur_div").toggleClass("blur_toggle");
$('.o_menu_systray').css("opacity", '1');
}
}
},
_click_hide_top_bar(ev){
_click_hide_top_bar(ev) {
$('.o_main_navbar').css("width", "0px");
$('.o_main_navbar').css("height", "0px");
$('.o_main_navbar').css("min-height", "0px");
@@ -266,7 +311,7 @@ patch(NavBar.prototype, {
$("#hide_top_bar").css("display", "none");
},
_click_show_top_bar(ev){
_click_show_top_bar(ev) {
$('.o_main_navbar').css("width", "100%");
$('.o_main_navbar').css("height", "4rem");
$('.o_main_navbar').css("min-height", "4rem");
@@ -278,7 +323,7 @@ patch(NavBar.prototype, {
$("#show_top_bar").css("display", "none");
},
get_current_company(){
get_current_company() {
let current_company_id;
if (session.user_context.allowed_company_ids) {
current_company_id = session.user_context.allowed_company_ids[0];
@@ -298,14 +343,14 @@ patch(NavBar.prototype, {
$(".sh_backmate_theme_appmenu_div").toggleClass("sidebar_toggle");
$(".blur_div").toggleClass("blur_toggle");
$('.o_menu_systray').css("opacity", '1');
if (enable_multi_tab){
if(window.event.shiftKey){
if (enable_multi_tab) {
if (window.event.shiftKey) {
this._createMultiTab(menu)
}else{
} else {
}
}
if(this.websiteCustomMenus){
if (this.websiteCustomMenus) {
const websiteMenu = this.websiteCustomMenus.get(menu.xmlid);
if (websiteMenu) {
return this.websiteCustomMenus.open(menu);
@@ -318,114 +363,114 @@ patch(NavBar.prototype, {
},
_createMultiTab: function (ev) {
var tab_name = ev.name
var url = '#menu_id='+ev.id + '&action='+ ev.actionID
var actionId = ev.actionID
var menuId = ev.id
var menu_xmlid = ev.xmlid
var self = this
localStorage.setItem('LastCreatedTab',actionId)
var tab_name = ev.name
var url = '#menu_id=' + ev.id + '&action=' + ev.actionID
var actionId = ev.actionID
var menuId = ev.id
var menu_xmlid = ev.xmlid
var self = this
localStorage.setItem('LastCreatedTab', actionId)
jsonrpc('/add/mutli/tab', {
'name':tab_name,
'url':url,
'actionId':actionId,
'menuId':menuId,
'menu_xmlid':menu_xmlid,
}).then((rec) => {
self.addmultitabtags(ev)
});
},
jsonrpc('/add/mutli/tab', {
'name': tab_name,
'url': url,
'actionId': actionId,
'menuId': menuId,
'menu_xmlid': menu_xmlid,
}).then((rec) => {
self.addmultitabtags(ev)
});
},
addmultitabtags: async function (ev) {
var self = this
var rec = await jsonrpc('/get/mutli/tab', {});
if (rec){
if (theme_style == 'theme_style'){ $('body > header').css("height", "48px"); }
$('.multi_tab_section').empty()
$.each(rec, function( key, value ) {
var tab_tag = '<div class="d-flex justify-content-between multi_tab_div align-items-center"><a href="'+ value.url +'"'+' class="flex-fill" data-xml-id="'+ value.menu_xmlid +'" data-menu="'+ value.menuId +'" data-action-id="'+ value.actionId +'" multi_tab_id="'+value.id+'" multi_tab_name="'+value.name+'"><span>'+value.name+'</span></a><span class="remove_tab ml-4">X</span></div>'
$('.multi_tab_section').append(tab_tag)
})
var ShstoredActionId = sessionStorage.getItem("sh_current_action_id");
var ShstoredAction = sessionStorage.getItem("sh_current_action");
if (ShstoredActionId){
var TabDiv = $('.multi_tab_section .multi_tab_div');
var ActiveMenu = TabDiv.find('a[data-action-id="'+ ShstoredActionId +'"]');
ActiveMenu.parent().addClass('tab_active')
}
var self = this
var rec = await jsonrpc('/get/mutli/tab', {});
if (rec) {
if (theme_style == 'theme_style') { $('body > header').css("height", "48px"); }
$('.multi_tab_section').empty()
$.each(rec, function (key, value) {
var tab_tag = '<div class="d-flex justify-content-between multi_tab_div align-items-center"><a href="' + value.url + '"' + ' class="flex-fill" data-xml-id="' + value.menu_xmlid + '" data-menu="' + value.menuId + '" data-action-id="' + value.actionId + '" multi_tab_id="' + value.id + '" multi_tab_name="' + value.name + '"><span>' + value.name + '</span></a><span class="remove_tab ml-4">X</span></div>'
$('.multi_tab_section').append(tab_tag)
})
var ShstoredActionId = sessionStorage.getItem("sh_current_action_id");
var ShstoredAction = sessionStorage.getItem("sh_current_action");
if (ShstoredActionId) {
var TabDiv = $('.multi_tab_section .multi_tab_div');
var ActiveMenu = TabDiv.find('a[data-action-id="' + ShstoredActionId + '"]');
ActiveMenu.parent().addClass('tab_active')
}
if (ev) {
var actionId = ev.actionID
var menu_xmlid = ev.xmlid
if(localStorage.getItem('LastCreatedTab')){
var target = '.multi_tab_section .multi_tab_div a[data-action-id="'+ localStorage.getItem('LastCreatedTab') +'"]'
$(target).parent().addClass('tab_active')
localStorage.removeItem('LastCreatedTab')
} else {
var target = '.multi_tab_section .multi_tab_div a[data-xml-id="'+ menu_xmlid +'"]'
$(target).parent().addClass('tab_active')
}
}
$('body').addClass("multi_tab_enabled");
if (ev) {
var actionId = ev.actionID
var menu_xmlid = ev.xmlid
if (localStorage.getItem('LastCreatedTab')) {
var target = '.multi_tab_section .multi_tab_div a[data-action-id="' + localStorage.getItem('LastCreatedTab') + '"]'
$(target).parent().addClass('tab_active')
localStorage.removeItem('LastCreatedTab')
} else {
$('body').removeClass("multi_tab_enabled");
var target = '.multi_tab_section .multi_tab_div a[data-xml-id="' + menu_xmlid + '"]'
$(target).parent().addClass('tab_active')
}
$('.multi_tab_section .remove_tab').on('click', function (ev) {
self._RemoveTab(ev)
});
$('.multi_tab_section .multi_tab_div a').on('click', function (ev) {
self._TabClicked(ev)
});
},
}
$('body').addClass("multi_tab_enabled");
} else {
$('body').removeClass("multi_tab_enabled");
}
$('.multi_tab_section .remove_tab').on('click', function (ev) {
self._RemoveTab(ev)
});
$('.multi_tab_section .multi_tab_div a').on('click', function (ev) {
self._TabClicked(ev)
});
},
_RemoveTab: function (ev) {
var self = this
var multi_tab_id = $(ev.target).parent().find('a').attr('multi_tab_id')
jsonrpc('/remove/multi/tab', {
'multi_tab_id':multi_tab_id,
}).then(function(rec) {
if (rec){
if(rec['removeTab']){
$(ev.target).parent().remove()
var FirstTab = $('.multi_tab_section').find('.multi_tab_div:first-child')
if(FirstTab.length){
$(FirstTab).find('a')[0].click()
$(FirstTab).addClass('tab_active')
}
}
if(rec['multi_tab_count'] == 0){
$('body').removeClass("multi_tab_enabled");
var self = this
var multi_tab_id = $(ev.target).parent().find('a').attr('multi_tab_id')
jsonrpc('/remove/multi/tab', {
'multi_tab_id': multi_tab_id,
}).then(function (rec) {
if (rec) {
if (rec['removeTab']) {
$(ev.target).parent().remove()
var FirstTab = $('.multi_tab_section').find('.multi_tab_div:first-child')
if (FirstTab.length) {
$(FirstTab).find('a')[0].click()
$(FirstTab).addClass('tab_active')
}
}
});
},
if (rec['multi_tab_count'] == 0) {
$('body').removeClass("multi_tab_enabled");
}
}
});
},
_TabClicked: function (ev){
localStorage.setItem("TabClick", true);
localStorage.setItem("TabClickTilteUpdate", true);
if($(ev.target).data('action-id')){
$('.multi_tab_section').find('.tab_active').removeClass('tab_active');
$(ev.target).parent().addClass('tab_active')
console.log('$(ev.target).parent()',$(ev.target).parent())
}
else{
if($(ev.currentTarget).data('action-id')){
_TabClicked: function (ev) {
localStorage.setItem("TabClick", true);
localStorage.setItem("TabClickTilteUpdate", true);
if ($(ev.target).data('action-id')) {
$('.multi_tab_section').find('.tab_active').removeClass('tab_active');
$(ev.currentTarget).parent().addClass('tab_active')
console.log('$(ev.target).parent()',$(ev.target).parent())
$(ev.target).parent().addClass('tab_active')
console.log('$(ev.target).parent()', $(ev.target).parent())
}
else {
if ($(ev.currentTarget).data('action-id')) {
$('.multi_tab_section').find('.tab_active').removeClass('tab_active');
$(ev.currentTarget).parent().addClass('tab_active')
console.log('$(ev.target).parent()', $(ev.target).parent())
}
}
}
},
onNavBarDropdownItemClick(ev) {
if(ev.shiftKey){
localStorage.setItem("sh_add_tab",1)
}else{
localStorage.setItem("sh_add_tab",0)
if (ev.shiftKey) {
localStorage.setItem("sh_add_tab", 1)
} else {
localStorage.setItem("sh_add_tab", 0)
}
},
getAppClassName(app){
getAppClassName(app) {
var app_name = app.xmlid
return app_name.replaceAll('.', '_')
},
@@ -504,7 +549,7 @@ patch(NavBar.prototype, {
menuList.forEach(menu => {
// 为当前菜单添加 level 属性
menu.level = level;
// 如果有子菜单,递归给子菜单添加等级
// 如果有子菜单,递归给子菜单添加等级
if (menu.childrenTree && menu.childrenTree.length > 0) {
this.addLevelToMenu(menu.childrenTree, level + 1); // 递归调用,增加等级
}
@@ -514,7 +559,7 @@ patch(NavBar.prototype, {
// 获取一级菜单的子菜单
currentMenuAppSections(app_id) {
const childrenMenu = (this.menuService.getMenuAsTree(app_id).childrenTree) || [];
// 给每个子菜单及其子菜单递归添加等级
// 给每个子菜单及其子菜单递归添加等级
this.addLevelToMenu(childrenMenu);
return childrenMenu;
},
@@ -0,0 +1,37 @@
#fullscreen_toggle {
/* 浅灰背景 */
background-color: #f5f5f5;
/* 黑色图标 */
color: #000;
/* 圆形 */
border-radius: 50%;
/* 固定宽度 */
width: 30px;
/* 固定高度 */
height: 30px;
display: flex;
/* 居中对齐 */
align-items: center;
justify-content: center;
/* 图标大小 */
font-size: 18px;
cursor: pointer;
/* 动画 */
transition: all 0.3s ease;
/* 去掉边框 */
border: none;
}
#fullscreen_toggle:hover {
/* 悬停时更深一点 */
background-color: #e0e0e0;
/* 微微放大 */
transform: scale(1.05);
}
#fullscreen_toggle:active {
/* 点击时更深 */
background-color: #d6d6d6;
/* 点击时缩小一点 */
transform: scale(0.95);
}
@@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="AppIcon" owl="1">
<t t-set="app_id" t-value="app.id" />
<t t-set="menu_badge_count" t-value="app.badge_count" />
<a t-att-href="getMenuItemHref(app)" >
<t t-if="icon_style == 'standard'">
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&amp;field=web_icon_data&amp;id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
</t>
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&amp;field=web_icon_data&amp;id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
</t>
<t t-elif="icon_style == 'line_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"/>
@@ -41,12 +40,11 @@
</span>
</a>
</t>
<!-- 菜单递归模板 -->
<t t-name="AppsTreeMenu" owl="1">
<!-- 子菜单 -->
<t t-set="children_menus" t-value="menu.childrenTree" />
<!-- <t t-set="menu_badge_count" t-value="this.getMenuBadgeCount(menu)" />-->
<!-- <t t-set="menu_badge_count" t-value="this.getMenuBadgeCount(menu)" />-->
<t t-set="menu_badge_count" t-value="menu.badge_count" />
<!-- 不存在子菜单 -->
<t t-if="!children_menus.length">
@@ -73,7 +71,6 @@
<t t-else="">
<div class="dropdown-header o_menu_header_lvl_1" >
<a class="sh_dropdown_toggle dropdown-item dropdown-toggle" t-on-click.stop="OnClickDropdown">
<span class="fa fa-circle-thin" t-attf-style="margin-left: {{ menu.level * 15 }}px;position: relative;">
<t t-if="menu_badge_count != 0">
<span class="menu-badge">
@@ -89,7 +86,7 @@
<t t-foreach="children_menus" t-as="children" t-key="children.id">
<t t-set="children_sub_menus" t-value="children.childrenTree" />
<t t-set="children_menu_badge_count" t-value="children.badge_count" />
<!-- <t t-set="children_menu_badge_count" t-value="this.getMenuBadgeCount(children)" />-->
<!-- <t t-set="children_menu_badge_count" t-value="this.getMenuBadgeCount(children)" />-->
<t t-if="children_sub_menus.length">
<t t-call="AppsTreeMenu">
<t t-set="menu" t-value="children" />
@@ -104,10 +101,10 @@
>
<span class="fa fa-circle-thin" t-attf-style="margin-left: {{ children.level * 15 }}px;position: relative;">
<t t-if="children_menu_badge_count != 0">
<span class="menu-badge">
<t t-esc="children_menu_badge_count"/>
</span>
</t>
<span class="menu-badge">
<t t-esc="children_menu_badge_count"/>
</span>
</t>
</span>
<span>
<t t-esc="children.name"/>
@@ -120,7 +117,6 @@
</div>
</t>
</t>
<t t-name="sh.NavBar.AppsMenu" owl="1">
<a style="z-index:1111;display:none;" id="js_bar_toggle_btn_mobile" t-on-click="_click_js_bar_toggle_btn_mobile" class="">
<i class="fa fa-bars" id="toggle_bar" t-on-click="_click_toggle_bar" />
@@ -139,6 +135,14 @@
<div class="logo" style="width: 100%;display: flex;max-width: 100%;align-items: center;margin-top: 20px;">
<img t-attf-src="/web/image?model=res.company&amp;field=company_name_logo&amp;id={{get_current_company()}}" id="company_logo" style="margin-left: 10px;height: 30px;width: 30px;max-width: 30px;margin-right: 19px;" />
<img class="img" t-attf-src="/web/image?model=res.company&amp;field=logo&amp;id={{get_current_company()}}" style="height: 3rem;padding: 10px 0;width: 55%;padding-left: 0;" id="company_name_logo" />
<span class="btn btn-light"
id="fullscreen_toggle"
t-att-title="state.exFullscreen ? '退出全屏' : '开启全屏'"
t-on-click="_click_fullscreen_toggle"
style="margin-left: 25px;">
<i class="fa fa-expand" aria-hidden="true" t-if="!state.exFullscreen"></i>
<i class="fa fa-compress" aria-hidden="true" t-if="state.exFullscreen"></i>
</span>
<span class="icon-top_hide fa fa-toggle-on" id="hide_top_bar" t-on-click="_click_hide_top_bar" style="margin-left: 25px;margin-top: 0px; font-size: 20px;"/>
<span class="icon-top_show fa fa-toggle-off" id="show_top_bar" t-on-click="_click_show_top_bar" style="margin-left: 25px;margin-top: 0px;font-size: 20px;"/>
</div>
@@ -176,27 +180,25 @@
<span class="dropdown-item o_app direct_menu" t-on-click="_click_o_app" payload="app">
<t t-call="AppIcon"/>
</span>
<!-- </MenuItem> -->
<!-- </MenuItem> -->
</div>
</t>
</t>
</Dropdown>
</div>
</t>
<t t-name="web.NavBar" t-inherit="web.NavBar" t-inherit-mode="extension" owl="1">
<xpath expr="//nav[hasclass('o_main_navbar')]" position="after">
<!-- MULTI TAB START -->
<!-- MULTI TAB START -->
<div class="multi_tab_section"/>
<!-- MULTI TAB END -->
<!-- MULTI TAB END -->
</xpath>
<xpath expr="//nav[hasclass('o_main_navbar')]" position="replace">
<nav class="o_main_navbar" data-command-category="navbar">
<t t-call="sh.NavBar.AppsMenu">
<t t-set="apps" t-value="menuService.getApps()" />
<xpath expr="//nav[hasclass('o_main_navbar')]" position="replace">
<nav class="o_main_navbar" data-command-category="navbar">
<t t-call="sh.NavBar.AppsMenu">
<t t-set="apps" t-value="menuService.getApps()" />
</t>
<DropdownItem
<DropdownItem
t-if="currentApp"
href="getMenuItemHref(currentApp)"
t-esc="currentApp.name"
@@ -204,12 +206,10 @@
dataset="{ menuXmlid: currentApp.xmlid, section: currentApp.id }"
onSelected="() => this.onNavBarDropdownItemSelection(currentApp)"
/>
<!-- Current App Sections -->
<t t-if="currentAppSections.length" t-call="web.NavBar.SectionsMenu">
<t t-set="sections" t-value="currentAppSections" />
</t>
<!-- Systray -->
<div class="o_menu_systray d-flex flex-shrink-0 ms-auto" role="menu">
<t t-foreach="systrayItems" t-as="item" t-key="item.key">
@@ -219,10 +219,9 @@
</ErrorHandler>
</t>
</div>
</nav>
</xpath>
</t>
</nav>
</xpath>
</t>
<t t-name="Menu.link">
<t t-set="depth" t-value="(depth || 0) + 1"/>
<t t-if="!menu.childrenTree.length">
@@ -269,5 +268,4 @@
</li>
</t>
</t>
</templates>
</templates>