如何在Odoo中重写Owl服务companyService的start函数
Odoo 自定义company服务start函数重写方案
- 你可以通过Odoo前端服务注册机制替换原生
company服务的start方法,无需修改框架核心源码,只需将自定义JS文件放到自定义模块的静态资源路径下加载即可。 - 原代码中提供的
parseCompanyIds、computeAllowedCompanyIds为通用工具函数,重写时可直接复用,无需重复编写。
原生start函数核心逻辑
- 优先从路由hash、其次从浏览器cookie中读取用户历史保存的选中公司ID列表
- 校验读取到的公司ID是否都在用户权限范围内,非法值会被替换为用户当前默认公司ID
- 将最终生效的公司ID列表同步写入路由hash、cookie,同时更新用户上下文的
allowed_company_ids字段 - 对外暴露服务实例,提供可用公司查询、当前公司查询、公司切换三个核心能力
可直接修改的重写模板
/** @odoo-module **/ import { browser } from "@web/core/browser/browser"; import { registry } from "@web/core/registry"; import { symmetricalDifference } from "@web/core/utils/arrays"; import { session } from "@web/session"; function parseCompanyIds(cidsFromHash) { const cids = []; if (typeof cidsFromHash === "string") { cids.push(...cidsFromHash.split(",").map(Number)); } else if (typeof cidsFromHash === "number") { cids.push(cidsFromHash); } return cids; } function computeAllowedCompanyIds(cids) { const { user_companies } = session; let allowedCompanyIds = cids || []; const availableCompaniesFromSession = user_companies.allowed_companies; const notReallyAllowedCompanies = allowedCompanyIds.filter( (id) => !(id in availableCompaniesFromSession) ); if (!allowedCompanyIds.length || notReallyAllowedCompanies.length) { allowedCompanyIds = [user_companies.current_company]; } return allowedCompanyIds; } export const customCompanyService = { dependencies: ["user", "router", "cookie"], start(env, { user, router, cookie }) { let cids; if ("cids" in router.current.hash) { cids = parseCompanyIds(router.current.hash.cids); } else if ("cids" in cookie.current) { cids = parseCompanyIds(cookie.current.cids); } // -------------------------- // 在此区域编写自定义公司选择逻辑 // 示例1:默认加载用户所有有权限的公司(即你当前贴出的代码逻辑) let allowedCompanyIds = Object.values(session.user_companies.allowed_companies).map(company => company.id); // 示例2:恢复Odoo原生逻辑,默认加载用户上次选中的公司 // let allowedCompanyIds = computeAllowedCompanyIds(cids); // 示例3:固定只加载指定ID的公司 // let allowedCompanyIds = [1]; // -------------------------- const stringCIds = allowedCompanyIds.join(","); router.replaceState({ cids: stringCIds }, { lock: true }); cookie.setCookie("cids", stringCIds); user.updateContext({ allowed_company_ids: allowedCompanyIds }); const availableCompanies = session.user_companies.allowed_companies; return { availableCompanies, get allowedCompanyIds() { return allowedCompanyIds.slice(); }, get currentCompany() { return availableCompanies[allowedCompanyIds[0]]; }, setCompanies(mode, ...companyIds) { // 如需自定义公司切换规则,可修改此方法内的nextCompanyIds计算逻辑 let nextCompanyIds; if (mode === "toggle") { nextCompanyIds = symmetricalDifference(allowedCompanyIds, companyIds); } else if (mode === "loginto") { const companyId = companyIds[0]; if (allowedCompanyIds.length === 1) { nextCompanyIds = [companyId]; } else { nextCompanyIds = [ companyId, ...allowedCompanyIds.filter((id) => id !== companyId), ]; } } nextCompanyIds = nextCompanyIds.length ? nextCompanyIds : [companyIds[0]]; router.pushState({ cids: nextCompanyIds }, { lock: true }); cookie.setCookie("cids", nextCompanyIds); browser.setTimeout(() => browser.location.reload()); }, }; }, }; // 移除原有公司服务,注册自定义版本 registry.category("services").remove("company").add("company", customCompanyService);
重写注意事项
- 不可删除服务声明中的
dependencies配置,缺少依赖会导致服务启动失败 - 返回的服务实例必须保留
availableCompanies、allowedCompanyIds、currentCompany、setCompanies四个核心成员,否则依赖公司服务的其他前端组件会出现运行异常 - 自定义逻辑修改完成后,将文件放到自定义模块的
/static/src/js/路径下,在资源清单中引入即可生效
内容的提问来源于stack exchange,提问作者CHIU TZE CHEUNG
相关产品推荐
相关产品推荐

