Odoo 16中能否同时使用password="1"与widget="CopyClipboardChar"?
解决Odoo 16中字段掩码与剪贴板复制功能冲突的问题
问题根源
Odoo 16中,password="1"会强制字段使用原生密码掩码组件,直接覆盖CopyClipboardChar的渲染逻辑,导致两个功能无法同时生效。
解决方案
方案1:自定义组合Widget(推荐)
创建一个继承自CopyClipboardChar的自定义Widget,同时集成密码掩码和复制功能:
- 在模块的
static/src/js目录下创建masked_copy_clipboard_widget.js:
odoo.define('your_module.masked_copy_clipboard', function (require) { "use strict"; var CopyClipboardChar = require('web.CopyClipboardChar'); var fieldRegistry = require('web.field_registry'); var MaskedCopyClipboardChar = CopyClipboardChar.extend({ _renderReadonly: function () { this._super.apply(this, arguments); // 用*替换显示文本实现掩码 const originalValue = this.value; this.$el.text('*'.repeat(originalValue.length)); // 存储原始值用于复制 this.$el.data('original-value', originalValue); }, _onCopy: function () { const originalValue = this.$el.data('original-value'); this._copyToClipboard(originalValue); } }); fieldRegistry.add('masked_copy_clipboard', MaskedCopyClipboardChar); return MaskedCopyClipboardChar; });
- 在
views/assets.xml中注册Widget:
<odoo> <template id="assets_backend" name="masked copy clipboard assets" inherit_id="web.assets_backend"> <xpath expr="." position="inside"> <script type="text/javascript" src="/your_module/static/src/js/masked_copy_clipboard_widget.js"/> </xpath> </template> </odoo>
- 在字段定义中使用自定义Widget:
from odoo import fields, models class YourModel(models.Model): _name = 'your.model' _description = 'Your Model' sensitive_field = fields.Char( string='Sensitive Field', widget='masked_copy_clipboard' )
方案2:CSS实现前端掩码(轻量方案)
仅通过CSS实现前端显示掩码,保留CopyClipboardChar的复制功能:
- 字段定义添加自定义类:
sensitive_field = fields.Char( string='Sensitive Field', widget='CopyClipboardChar', attrs={'class': 'masked-field'} )
- 在
static/src/css目录下创建masked_field.css:
.masked-field .o_field_widget { position: relative; } .masked-field .o_field_widget::after { content: attr(data-mask); position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #fff; display: flex; align-items: center; padding: 0 .75rem; }
- 扩展Widget添加掩码数据属性:
odoo.define('your_module.masked_copy_clipboard_css', function (require) { "use strict"; var CopyClipboardChar = require('web.CopyClipboardChar'); CopyClipboardChar.include({ _renderReadonly: function () { this._super.apply(this, arguments); if (this.$el.hasClass('masked-field')) { const originalValue = this.value; this.$el.find('.o_field_widget').attr('data-mask', '*'.repeat(originalValue.length)); } } }); });
- 在
assets.xml引入CSS和扩展脚本:
<odoo> <template id="assets_backend" name="masked field assets" inherit_id="web.assets_backend"> <xpath expr="." position="inside"> <link rel="stylesheet" href="/your_module/static/src/css/masked_field.css"/> <script type="text/javascript" src="/your_module/static/src/js/masked_copy_clipboard_css.js"/> </xpath> </template> </odoo>
方案3:后端触发复制(仅内部系统适用)
保留password="1",通过按钮触发后端复制操作(需服务器安装pyperclip):
- 字段定义:
sensitive_field = fields.Char( string='Sensitive Field', password="1" )
- 视图添加复制按钮:
<field name="sensitive_field"/> <button name="action_copy_sensitive_field" string="Copy" type="object" class="btn btn-sm"/>
- 实现复制方法:
from odoo import models, api import pyperclip class YourModel(models.Model): _inherit = 'your.model' def action_copy_sensitive_field(self): self.ensure_one() pyperclip.copy(self.sensitive_field) return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'message': 'Copied to clipboard!', 'type': 'success', 'sticky': False, } }
内容的提问来源于stack exchange,提问作者arleite
相关产品推荐
相关产品推荐

