在odoo14中当时使用:widget="progressbar" 时默认表现为:
但我想在不同的比例展示不同的颜色,和其他的样式颜色:
tree视图
form视图 也一样:
说明:进度0-30为蓝色,31-80为黄色,81-100为紫色、边框为红色,底色为绿色
这个组件 拥有普通组件widget=“progressbar“的所有功能,换言之 在widget=“progressbar“组件的js文件和模板文件的基础上进行改进,使其有更好的可移植性和可造性。
这是一个单独模块:
js文件
odoo.define('progressbar_dynamic_color.progressbar_dynamic', function (require) {
'use strict';
var AbstractField = require('web.AbstractField');
let fieldRegistry = require("web.field_registry");
var core = require('web.core');
var utils = require('web.utils');
var field_utils = require('web.field_utils');
require("web.zoomodoo");
var _t = core._t;
var _lt = core._lt;
var CustomProgressBarColorWidget = AbstractField.extend({
description: _lt("进度条"),
template: "Custom_ProgressBar",
events: {
'change input': 'on_change_input',
'input input': 'on_change_input',
'keyup input': function (e) {
if (e.which === $.ui.keyCode.ENTER) {
this.on_change_input(e);
}
},
},
supportedFieldTypes: ['integer', 'float'],
init: function () {
this._super.apply(this, arguments);
if (this.recordData[this.nodeOptions.current_value]) {
this.value = this.recordData[this.nodeOptions.current_value];
}
this.editable_readonly = !!this.nodeOptions.editable_readonly;
this.readonly = this.nodeOptions.readonly || !this.nodeOptions.editable;
this.canWrite = !this.readonly && (
this.mode === 'edit' ||
(this.editable_readonly && this.mode === 'readonly') ||
(this.viewType === 'kanban') // Keep behavior before commit
);
this.edit_max_value = !!this.nodeOptions.edit_max_value;
this.max_value = this.recordData[this.nodeOptions.max_value] || 100;
this.title = _t(this.attrs.title || this.nodeOptions.title) || '';
this.enableBarAsInput = false;
this.edit_on_click = this.enableBarAsInput && this.mode === 'readonly' && !this.edit_max_value;
this.write_mode = false;
},
_render: function () {
var self = this;
this._render_value();
if (this.canWrite) {
if (this.edit_on_click) {
this.$el.on('click', '.o_progress', function (e) {
var $target = $(e.currentTarget);
var numValue = Math.floor((e.pageX - $target.offset().left) / $target.outerWidth() * self.max_value);
self.on_update(numValue);
self._render_value();
});
} else {
this.$el.on('click', function () {
if (!self.write_mode) {
var $input = $('<input>', {type: 'text', class: 'o_custom_progressbar_value o_input'});
$input.on('blur', self.on_change_input.bind(self));
self.$('.o_custom_progressbar_value').replaceWith($input);
self.write_mode = true;
self._render_value();
}
});
}
}
return this._super();
},
on_update: function (value) {
if (this.edit_max_value) {
this.max_value = value;
this._isValid = true;
var changes = {};
changes[this.nodeOptions.max_value] = this.max_value;
this.trigger_up('field_changed', {
dataPointID: this.dataPointID,
changes: changes,
});
} else {
// _setValues accepts string and will parse it
var formattedValue = this._formatValue(value);
this._setValue(formattedValue);
}
},
on_change_input: function (e) {
var $input = $(e.target);
if (e.type === 'change' && !$input.is(':focus')) {
return;
}
var parsedValue;
try {
// Cover all numbers with parseFloat
parsedValue = field_utils.parse.float($input.val());
} catch (error) {
this.do_warn(false, _t("Please enter a numerical value"));
}
if (parsedValue !== undefined) {
if (e.type === 'input') { // ensure what has just been typed in the input is a number
// returns NaN if not a number
this._render_value(parsedValue);
if (parsedValue === 0) {
$input.select();
}
} else { // Implicit type === 'blur': we commit the value
if (this.edit_max_value) {
parsedValue = parsedValue || 100;
}
var $div = $('<div>', {class: 'o_custom_progressbar_value'});
this.$('.o_custom_progressbar_value').replaceWith($div);
this.write_mode = false;
this.on_update(parsedValue);
this._render_value();
}
}
},
_render_value: function (v) {
var value = this.value;
var max_value = this.max_value;
if (!isNaN(v)) {
if (this.edit_max_value) {
max_value = v;
} else {
value = v;
}
}
value = value || 0;
max_value = max_value || 0;
var widthComplete;
if (value <= max_value) {
widthComplete = value / max_value * 100;
} else {
widthComplete = 100;
}
var color_value = '#34c38f'
try {
if (this.attrs.options.colors) {
var colorJudgmentValue = this.attrs.options.colors
for (var key in this.attrs.options.colors) {
if (colorJudgmentValue.hasOwnProperty(key)) {
var range = colorJudgmentValue[key];
if (value >= range[0] && value < range[1]) {
color_value = key;
break; // 如果找到匹配的值,可以提前结束循环
}
}
}
}
} catch (error) {
}
var bordercolor = "white";
try {
if (this.attrs.options.bordercolor) {
var borderColorValue = this.attrs.options.bordercolor
if (borderColorValue) {
if (borderColorValue.color) {
bordercolor = borderColorValue.color
}
}
}
;
} catch (error) {
console.log("边框颜色动态改变输入的值有错误", error)
}
var basercolor = "white";
try {
if (this.attrs.options.basercolor) {
var baseColorValue = this.attrs.options.basercolor
if (baseColorValue) {
if (baseColorValue.color) {
basercolor = baseColorValue.color
}
}
}
;
} catch (error) {
console.log("边框底板颜色动态改变输入的值有错误", error)
}
var progressBarComplete = this.$('.o_custom_progressbar_complete');
progressBarComplete.css('background-color', color_value);
this.$('.o_custom_progress').toggleClass('o_custom_progress_overflow', value > max_value)
.attr('aria-valuemin', '0')
.attr('aria-valuemax', max_value)
.attr('aria-valuenow', value);
var progressBorderComplete = this.$('.o_custom_progress');
progressBorderComplete.css('border', `1px solid ${bordercolor}`);
progressBorderComplete.css('background-color', basercolor);
this.$('.o_custom_progressbar_complete').css('width', widthComplete + '%')
if (!this.write_mode) {
if (max_value !== 100) {
this.$('.o_custom_progressbar_value').text(utils.human_number(value) + " / " + utils.human_number(max_value));
} else {
this.$('.o_custom_progressbar_value').text(utils.human_number(value) + "%");
}
} else if (isNaN(v)) {
this.$('.o_custom_progressbar_value').val(this.edit_max_value ? max_value : value);
this.$('.o_custom_progressbar_value').focus().select();
}
},
_reset: function () {
this._super.apply(this, arguments);
var new_max_value = this.recordData[this.nodeOptions.max_value];
this.max_value = new_max_value !== undefined ? new_max_value : this.max_value;
},
isSet: function () {
return true;
},
});
// 注册widget
fieldRegistry.add('progressbar_dynamic_color', CustomProgressBarColorWidget);
return CustomProgressBarColorWidget;
});
scss文件:
.o_custom_progressbar {
> div {
display: inline-block;
}
.o_custom_progressbar_title {
white-space: nowrap;
padding-right: 10px;
}
.o_custom_progress {
width: 100px;
height: 15px;
vertical-align: middle;
//border: 1px solid lighten(white, 25%);
overflow: hidden;
//background-color: firebrick;
&.o_custom_progress_overflow {
background-color: white;
}
.o_custom_progressbar_complete {
//background-color: lawngreen;
height: 100%;
}
}
.o_custom_progressbar_value {
width: 100px;
white-space: nowrap;
padding-left: 10px;
}
}
progress_bar_template.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="Custom_ProgressBar">
<div class="o_custom_progressbar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div t-if="widget.title" class="o_custom_progressbar_title"><t t-esc="widget.title"/></div><div class="o_custom_progress">
<div class="o_custom_progressbar_complete"/>
</div><div class="o_custom_progressbar_value"/>
</div>
</t>
</templates>