From 2b27ad3511431a514ffeac001a4a615cf1f64c2d Mon Sep 17 00:00:00 2001 From: sunjie Date: Tue, 23 Sep 2025 02:03:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=BB=E8=A1=A8=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_base/models/__init__.py | 5 +- yuthon_base/models/fields_piyin.py | 92 ++++++++++++++++++++++++++++++ yuthon_base/models/ir_model.py | 11 ++++ yuthon_base/models/res_partner.py | 7 +++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 yuthon_base/models/fields_piyin.py create mode 100644 yuthon_base/models/ir_model.py create mode 100644 yuthon_base/models/res_partner.py diff --git a/yuthon_base/models/__init__.py b/yuthon_base/models/__init__.py index 5858a6b82..00a22a461 100644 --- a/yuthon_base/models/__init__.py +++ b/yuthon_base/models/__init__.py @@ -1,2 +1,5 @@ +from . import ir_model from . import inherit_ir_attachment -from . import system_version \ No newline at end of file +from . import system_version +from . import fields_piyin +from . import res_partner \ No newline at end of file diff --git a/yuthon_base/models/fields_piyin.py b/yuthon_base/models/fields_piyin.py new file mode 100644 index 000000000..e212830a1 --- /dev/null +++ b/yuthon_base/models/fields_piyin.py @@ -0,0 +1,92 @@ +import pypinyin + +from odoo import fields, models, api +from odoo.models import BaseModel +import re + +_origin_search = BaseModel._search +_origin_read_group = BaseModel._read_group + + + +class CharWithPinyin(fields.Char): + pass + +# 把字段挂到 fields 命名空间 +fields.CharWithPinyin = CharWithPinyin + + +_origin_setup_fields = BaseModel._setup_fields + +def _my_setup_fields(self): + _origin_setup_fields(self) + # 把字段挂到 fields 命名空间 + cls = self.env.registry[self._name] + for name in list(cls._fields): + field = self._fields[name] + if isinstance(field, CharWithPinyin): + new_field_name = f'{name}_pinyin' + compute_method_name = f'_compute_{new_field_name}' + if new_field_name not in cls._fields: + def _compute_func(self, fn=name, nfn=new_field_name): + for rec in self: + value = rec[fn] or '' + rec[nfn] = ''.join(pypinyin.lazy_pinyin(value)) + + setattr(cls, compute_method_name, api.depends(name)(_compute_func)) + + cls._add_field( + self, + new_field_name, + fields.Char( + compute=_compute_func, + store=True, + index=True, + string=f"{field.string or name}拼音", + ) + ) + +BaseModel._setup_fields = _my_setup_fields + + +def _replace_char_with_pinyin_order(self, order): + """ + 将排序字符串中属于 CharWithPinyin 的字段替换为对应 _pinyin 字段 + """ + if not order: + return order + + # 拆分多字段排序,例如 "name desc, create_date asc" + parts = [p.strip() for p in order.split(',')] + new_parts = [] + for part in parts: + # 分离字段名和排序方向 + m = re.match(r'([^\s]+)(?:\s+(asc|desc))?$', part, re.IGNORECASE) + if not m: + new_parts.append(part) + continue + field_name, direction = m.groups() + field = self._fields.get(field_name) + if field and isinstance(field, fields.CharWithPinyin): + # 替换成 _pinyin 字段 + field_name = f"{field_name}_pinyin" + if direction: + new_parts.append(f"{field_name} {direction}") + else: + new_parts.append(field_name) + return ', '.join(new_parts) + + +# 重写 _search +def _my_search(self, domain, offset=0, limit=None, order=None, access_rights_uid=None): + order = _replace_char_with_pinyin_order(self, order) + return _origin_search(self, domain, offset=offset, limit=limit, order=order, access_rights_uid=access_rights_uid) + +# 重写 _read_group +def _my_read_group(self, domain, groupby=(), aggregates=(), having=(), offset=0, limit=None, order=None): + order = _replace_char_with_pinyin_order(self, order) + return _origin_read_group(self, domain, groupby=groupby, aggregates=aggregates, having=having, offset=offset, limit=limit, order=order) + +# Patch BaseModel +BaseModel._search = _my_search +BaseModel._read_group = _my_read_group \ No newline at end of file diff --git a/yuthon_base/models/ir_model.py b/yuthon_base/models/ir_model.py new file mode 100644 index 000000000..901d73965 --- /dev/null +++ b/yuthon_base/models/ir_model.py @@ -0,0 +1,11 @@ +from odoo import fields, models, api + + +class IrModelFields(models.Model): + _inherit = 'ir.model.fields' + + @api.model + def _is_manual_name(self, name): + return name.startswith('x_') or name.endswith('_pinyin') + + diff --git a/yuthon_base/models/res_partner.py b/yuthon_base/models/res_partner.py new file mode 100644 index 000000000..fabf15297 --- /dev/null +++ b/yuthon_base/models/res_partner.py @@ -0,0 +1,7 @@ +from odoo import fields, models, api + + +class ResParnter(models.Model): + _inherit = 'res.partner' + + name = fields.CharWithPinyin(default_export_compatible= True)