Files
gzth/sun_badge_menu/models/ir_ui_menu.py
T
2025-12-23 10:03:45 +08:00

117 lines
4.9 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import re
from odoo import models, fields
def compute_badge_count_recursive(web_menus, menu_id):
"""
递归计算菜单的徽章数
:param web_menus: 包含所有菜单项的字典
:param menu_id: 当前菜单项的ID
:return: 如果有子菜单,则返回子菜单的 badge_count 的和;如果没有子菜单, 则返回当前菜单的 badge_count
"""
menu = web_menus[menu_id]
# 如果有子菜单,返回所有子菜单的badge_count之和
if menu['children']:
children_badge_count = 0
for child_id in menu['children']:
children_badge_count += compute_badge_count_recursive(web_menus, child_id)
return children_badge_count
# 如果没有子菜单,返回当前菜单的badge_count
return menu['badge_count']
class IrUiMenu(models.Model):
_inherit = "ir.ui.menu"
show_badge_count = fields.Boolean(string="显示菜单角标",default=True)
def load_web_menus(self, debug):
""" Loads all menu items (all applications and their sub-menus) and
processes them to be used by the webclient. Mainly, it associates with
each application (top level menu) the action of its first child menu
that is associated with an action (recursively), i.e. with the action
to execute when the opening the app.
:return: the menus (including the images in Base64)
"""
menus = self.load_menus(debug)
web_menus = {}
for menu in menus.values():
if not menu['id']:
# special root menu case
web_menus['root'] = {
"id": 'root',
"name": menu['name'],
"children": menu['children'],
"appID": False,
"xmlid": "",
"actionID": False,
"actionModel": False,
"actionPath": False,
"webIcon": None,
"webIconData": None,
"webIconDataMimetype": None,
"backgroundImage": menu.get('backgroundImage')
}
else:
action = menu['action']
if menu['id'] == menu['app_id']:
# if it's an app take action of first (sub)child having one defined
child = menu
while child and not action:
action = child['action']
child = menus[child['children'][0]] if child['children'] else False
action_model, action_id = action.split(',') if action else (False, False)
action_id = int(action_id) if action_id else False
badge_count = 0
res_model = False
if action_model and action_id:
action_record = self.env[action_model].browse(action_id).sudo()
if action_model == 'ir.actions.act_window' and action_record.view_mode != 'form':
# 不仅仅是 form 表单,获取 model
res_model = action_record.res_model
if res_model in self.env:
if hasattr(self.env[res_model], 'get_menu_badge_count'):
badge_count = self.env[res_model].get_menu_badge_count(action_record)
elif hasattr(self.env[res_model], 'get_no_read_count'):
badge_count = self.env[res_model].get_no_read_count()
elif hasattr(res_model, 'read_number'):
badge_count = self.env[res_model].read_number()
elif hasattr(res_model, 'read_coming_count'):
badge_count = self.env[res_model].read_coming_count()
elif hasattr(res_model, 'read_due_count'):
badge_count = self.env[res_model].read_due_count()
web_menus[menu['id']] = {
"id": menu['id'],
"name": menu['name'],
"children": menu['children'],
"appID": menu['app_id'],
"xmlid": menu['xmlid'],
"actionID": action_id,
"actionModel": action_model,
"webIcon": menu['web_icon'],
"webIconData": menu['web_icon_data'],
"webIconDataMimetype": menu['web_icon_data_mimetype'],
"badge_count": badge_count,
"res_model": res_model
}
# 计算父级的菜单的徽章数
for k, v in web_menus.items():
if v['children']:
web_menus[k]['badge_count'] = compute_badge_count_recursive(web_menus, k)
# 对 root 节点重新计算
return web_menus