diff --git a/menu_many2many_checkboxes/__init__.py b/menu_many2many_checkboxes/__init__.py
new file mode 100644
index 000000000..40a96afc6
--- /dev/null
+++ b/menu_many2many_checkboxes/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/menu_many2many_checkboxes/__manifest__.py b/menu_many2many_checkboxes/__manifest__.py
new file mode 100644
index 000000000..fcf76a74c
--- /dev/null
+++ b/menu_many2many_checkboxes/__manifest__.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': 'Menu Many2many Checkboxes',
+ 'summary': 'Menu Many2many Checkboxes',
+ 'description': 'Menu Many2many Checkboxes',
+ 'author': 'CY',
+ 'website': '',
+ 'category': 'Tools',
+ 'version': '17.0',
+ 'depends': ['base'],
+ 'data': [
+ 'views/res_users_views.xml',
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ '/menu_many2many_checkboxes/static/src/**/*',
+ ]
+ }
+}
+
diff --git a/menu_many2many_checkboxes/static/src/menu_many2many_checkboxes_field.js b/menu_many2many_checkboxes/static/src/menu_many2many_checkboxes_field.js
new file mode 100644
index 000000000..430bb9457
--- /dev/null
+++ b/menu_many2many_checkboxes/static/src/menu_many2many_checkboxes_field.js
@@ -0,0 +1,88 @@
+/** @odoo-module **/
+import { registry } from "@web/core/registry";
+import { useSpecialData } from "@web/views/fields/relational_utils";
+import { Many2ManyCheckboxesField, many2ManyCheckboxesField } from "@web/views/fields/many2many_checkboxes/many2many_checkboxes_field";
+
+export class MenuMany2ManyCheckboxesField extends Many2ManyCheckboxesField {
+ static template = "menu_many2many_checkboxes.Many2ManyCheckboxesField";
+ setup() {
+ super.setup();
+ this.specialData = useSpecialData((orm, props) => {
+ const { relation } = props.record.fields[props.name];
+ const kwargs = {
+ specification: {
+ id: {},
+ name: {},
+ parent_id: {},
+ },
+ domain: [],
+ limit: 10000,
+ };
+ return orm.call(relation, "web_search_read", [], kwargs);
+ });
+ }
+
+ get items() {
+ function buildTree(data) {
+ // 创建一个 map,用于快速查找节点
+ const nodeMap = new Map();
+ // 初始化节点
+ data.forEach(item => {
+ nodeMap.set(item.id, { ...item, children: [] });
+ });
+ // 构建树
+ const tree = [];
+ data.forEach(item => {
+ const node = nodeMap.get(item.id);
+ if (item.parent_id) {
+ // 如果有 parent_id,将当前节点挂到父节点的 children 下
+ const parentNode = nodeMap.get(item.parent_id);
+ if (parentNode) {
+ parentNode.children.push(node);
+ }
+ } else {
+ // 如果没有 parent_id,说明是根节点,直接加入树
+ tree.push(node);
+ }
+ });
+
+ return tree;
+ }
+ if (this.specialData.data?.records) {
+ return buildTree(this.specialData.data.records);
+ }
+ return [];
+ }
+
+ updateTreeSelection(resId, checked, tree) {
+ for (let node of tree) {
+ if (node.id === resId) {
+ // 同步点击子节点
+ if (node.children && node.children.length > 0) {
+ node.children.forEach(child => {
+ this.onChange(child.id, checked)
+ });
+ }
+ }
+ // 如果当前节点有子节点,递归更新子节点
+ if (node.children && node.children.length > 0) {
+ this.updateTreeSelection(resId, checked, node.children);
+ }
+ }
+ }
+
+ onChange(resId, checked) {
+ // 在 onChange 方法中更新选中状态
+ this.updateTreeSelection(resId, checked, this.items);
+ return super.onChange(resId, checked);
+ }
+
+}
+
+
+export const menuMany2ManyCheckboxesField = {
+ ...many2ManyCheckboxesField,
+ component: MenuMany2ManyCheckboxesField,
+}
+
+registry.category("fields").add("menu_many2many_checkboxes", menuMany2ManyCheckboxesField);
\ No newline at end of file
diff --git a/menu_many2many_checkboxes/static/src/menu_many2many_checkboxes_field.xml b/menu_many2many_checkboxes/static/src/menu_many2many_checkboxes_field.xml
new file mode 100644
index 000000000..5f96469bb
--- /dev/null
+++ b/menu_many2many_checkboxes/static/src/menu_many2many_checkboxes_field.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/menu_many2many_checkboxes/views/res_users_views.xml b/menu_many2many_checkboxes/views/res_users_views.xml
new file mode 100644
index 000000000..a504aee7b
--- /dev/null
+++ b/menu_many2many_checkboxes/views/res_users_views.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ res.groups.inherit
+ res.groups
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file