# -*- coding: utf-8 -*- from odoo import api, fields, models, _ from odoo.osv import expression import pypinyin class IrUiMenu(models.Model): _inherit = 'ir.ui.menu' def _get_menu_pinyin(self, name): """计算菜单名的全拼+首字母""" if not name: return '' full_pinyin = ''.join(pypinyin.lazy_pinyin(name)).lower() first_letters = ''.join([p[0] for p in pypinyin.pinyin(name)]).lower() return f"{full_pinyin} {first_letters}" def name_search(self, name='', args=None, operator='ilike', limit=100): """支持全拼/首字母搜索菜单""" if args is None: args = [] if not name or operator not in ('ilike', 'like', '=', '=like'): return super().name_search(name=name, args=args, operator=operator, limit=limit) search_term = name.strip().lower().replace(' ', '') if not search_term: return super().name_search(name=name, args=args, operator=operator, limit=limit) # 生成搜索词的拼音和首字母 search_pinyin = ''.join(pypinyin.lazy_pinyin(search_term)).lower() search_first = ''.join([p[0] for p in pypinyin.pinyin(search_term)]).lower() # 原名搜索 name_domain = expression.AND([args, [('name', operator, name)]]) name_ids = self.search(name_domain, limit=limit).ids # Python 层拼音匹配 all_menus = self.search(args, limit=limit * 3) pinyin_ids = [] for menu in all_menus: if menu.id in name_ids: continue if not menu.name: continue pinyin = self._get_menu_pinyin(menu.name) if search_term in pinyin or search_pinyin in pinyin or search_first in pinyin: pinyin_ids.append(menu.id) all_ids = list(dict.fromkeys(name_ids + pinyin_ids))[:limit] return self.browse(all_ids).name_get()