117 lines
4.9 KiB
Python
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
|