1. 由于视图已经使用了 js_class,无法重复使用(重复使用会导致序号覆盖)
2. 通过在 tree 视图添加 class形式进行了特殊判断.
This commit is contained in:
+5
-2
@@ -1,13 +1,16 @@
|
||||
/** @odoo-module **/
|
||||
/** This file will used to stick the selected header and column in the list view **/
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
|
||||
patch(ListRenderer.prototype, {
|
||||
/** super the setup function **/
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* function defining the button having t-on-click _onClick
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { loadJS, loadCSS } from "@web/core/assets";
|
||||
import { ListRendererCust } from "@tree_view_advanced_filter/tree_view_advanced_filter/tree"
|
||||
import { onWillDestroy, useEffect } from "@odoo/owl";
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {loadJS, loadCSS} from "@web/core/assets";
|
||||
import {ListRendererCust} from "@tree_view_advanced_filter/tree_view_advanced_filter/tree"
|
||||
import {onWillDestroy, useEffect} from "@odoo/owl";
|
||||
|
||||
patch(ListRenderer.prototype, {
|
||||
setup() {
|
||||
@@ -14,6 +14,8 @@ patch(ListRenderer.prototype, {
|
||||
}
|
||||
const computeFunction = this.computeFreeze.bind(this);
|
||||
const resizeObserver = new ResizeObserver(computeFunction);
|
||||
|
||||
|
||||
useEffect(
|
||||
(tableEl) => {
|
||||
if (tableEl) {
|
||||
@@ -28,6 +30,7 @@ patch(ListRenderer.prototype, {
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
freezeColumnWidths() {
|
||||
super.freezeColumnWidths();
|
||||
const table = this.tableRef.el;
|
||||
@@ -358,7 +361,7 @@ patch(ListRenderer.prototype, {
|
||||
tableRef.removeAttribute('style');
|
||||
const columns = this.getActiveColumns(this.props.list);
|
||||
|
||||
const $tr1 = $('<tr>', { class: 'o_filter_box' }).append(columns.map(col => this._renderHeaderCellSearch(col)));
|
||||
const $tr1 = $('<tr>', {class: 'o_filter_box'}).append(columns.map(col => this._renderHeaderCellSearch(col)));
|
||||
if (this.props.ooManagerSerialNum) $tr1.prepend($('<td>').addClass('web_list_num'));
|
||||
if (this.hasSelectors) $tr1.prepend($('<td>').addClass('o_list_record_selector'));
|
||||
if (this.isStudioEditable || this.displayOptionalFields) $tr1.append($('<td>').addClass('o_list_record_selector'));
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
overflow: visible;
|
||||
}
|
||||
.o_list_view .table-responsive .table thead {
|
||||
z-index: 5;
|
||||
z-index: 20;
|
||||
}
|
||||
.o_list_renderer .o_list_table thead {
|
||||
position: sticky;
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
'name': "yuthon salary",
|
||||
'summary': "薪资管理",
|
||||
'description': """
|
||||
|
||||
""",
|
||||
|
||||
""",
|
||||
'author': 'pengyuthon',
|
||||
'website': 'https://www.pengyuthon.com',
|
||||
'category': 'Human Resources/Attendances',
|
||||
'version': '0.1',
|
||||
'license': 'LGPL-3',
|
||||
'depends': ['mail', 'base', 'hr', 'yuthon_hr_employee','hr_payroll'],
|
||||
'depends': ['mail', 'base', 'hr', 'yuthon_hr_employee', 'hr_payroll'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/salary_security_rule.xml',
|
||||
@@ -47,26 +47,28 @@
|
||||
'wizard/salary_print_wizard_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'yuthon_salary/static/scss/approval.scss',
|
||||
'yuthon_salary/static/src/js/salary_documents_button.js',
|
||||
'yuthon_salary/static/src/js/salary_create_button.js',
|
||||
'yuthon_salary/static/src/js/salary_payslip_button.js',
|
||||
'yuthon_salary/static/src/js/salary_labor_button.js',
|
||||
'yuthon_salary/static/src/js/salary_return_button.js',
|
||||
'yuthon_salary/static/src/js/salary_retired_button.js',
|
||||
'yuthon_salary/static/src/js/salary_validation_button.js',
|
||||
'yuthon_salary/static/src/js/salary_year_button.js',
|
||||
'yuthon_salary/static/src/xml/salary_create_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_labor_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_retired_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_payslip_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_documents_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_validation_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_return_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_year_button.xml',
|
||||
],
|
||||
},
|
||||
'web.assets_backend': [
|
||||
'yuthon_salary/static/scss/approval.scss',
|
||||
'yuthon_salary/static/src/js/js_auto_hide_list_renderer.js',
|
||||
'yuthon_salary/static/src/js/salary_documents_button.js',
|
||||
'yuthon_salary/static/src/js/salary_create_button.js',
|
||||
'yuthon_salary/static/src/js/salary_payslip_button.js',
|
||||
'yuthon_salary/static/src/js/salary_labor_button.js',
|
||||
'yuthon_salary/static/src/js/salary_return_button.js',
|
||||
'yuthon_salary/static/src/js/salary_retired_button.js',
|
||||
'yuthon_salary/static/src/js/salary_validation_button.js',
|
||||
'yuthon_salary/static/src/js/salary_year_button.js',
|
||||
'yuthon_salary/static/src/xml/salary_create_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_labor_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_retired_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_payslip_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_documents_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_validation_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_return_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_year_button.xml',
|
||||
'yuthon_salary/static/src/views/list/*',
|
||||
]
|
||||
},
|
||||
'installable': True,
|
||||
'application': True,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
|
||||
export class JsAutoHideListRenderer extends ListRenderer {
|
||||
|
||||
getActiveColumns(list) {
|
||||
const columns = super.getActiveColumns(list);
|
||||
return columns
|
||||
let values;
|
||||
if (this.props.list.selection && this.props.list.selection.length) {
|
||||
values = this.props.list.selection.map((r) => r.data);
|
||||
} else if (this.props.list.isGrouped) {
|
||||
values = this.props.list.groups.map((g) => g.aggregates);
|
||||
} else {
|
||||
values = this.props.list.records.map((r) => r.data);
|
||||
}
|
||||
return columns.filter(column => {
|
||||
const fieldInfo = list.fields[column.name];
|
||||
if (!fieldInfo) {
|
||||
return true;
|
||||
}
|
||||
if (["float", "monetary"].includes(fieldInfo.type)) {
|
||||
const fieldValues = values.map((v) => v[fieldInfo.name] || 0);
|
||||
const aggregateValue = fieldValues.reduce((acc, val) => acc + val);
|
||||
if (!aggregateValue) {
|
||||
console.log(column)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
/** @odoo-module */
|
||||
import { ListController } from "@web/views/list/list_controller";
|
||||
import { registry } from '@web/core/registry';
|
||||
import { listView } from '@web/views/list/list_view';
|
||||
import {ListController} from "@web/views/list/list_controller";
|
||||
import {registry} from '@web/core/registry';
|
||||
import {listView} from '@web/views/list/list_view';
|
||||
import {JsAutoHideListRenderer} from "./js_auto_hide_list_renderer";
|
||||
|
||||
export class CustomSalaryStatementsController extends ListController {
|
||||
setup() {
|
||||
@@ -25,5 +26,5 @@ export class CustomSalaryStatementsController extends ListController {
|
||||
registry.category("views").add("custom_salary_button", {
|
||||
...listView,
|
||||
Controller: CustomSalaryStatementsController,
|
||||
buttonTemplate: "salary_module.ListView.Buttons",
|
||||
buttonTemplate: "salary_module.ListView.Buttons"
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
|
||||
export class JsAutoHideListRenderer extends ListRenderer {
|
||||
|
||||
getActiveColumns(list) {
|
||||
const columns = super.getActiveColumns(list);
|
||||
let values;
|
||||
if (this.props.list.selection && this.props.list.selection.length) {
|
||||
values = this.props.list.selection.map((r) => r.data);
|
||||
} else if (this.props.list.isGrouped) {
|
||||
values = this.props.list.groups.map((g) => g.aggregates);
|
||||
} else {
|
||||
values = this.props.list.records.map((r) => r.data);
|
||||
}
|
||||
return columns.filter(column => {
|
||||
const fieldInfo = list.fields[column.name];
|
||||
if (["float", "integer", "monetary"].includes(fieldInfo.type)) {
|
||||
const fieldValues = values.map((v) => v[fieldInfo.name] || 0);
|
||||
const aggregateValue = fieldValues.reduce((acc, val) => acc + val);
|
||||
if (!aggregateValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { listView } from "@web/views/list/list_view";
|
||||
import { JsAutoHideListRenderer } from "./js_auto_hide_list_renderer";
|
||||
|
||||
export const JsAutoHideListView = {
|
||||
...listView,
|
||||
Renderer: JsAutoHideListRenderer
|
||||
}
|
||||
|
||||
registry.category("views").add("jsAutoHideListView", JsAutoHideListView);
|
||||
@@ -0,0 +1,142 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import {ListRenderer} from "@web/views/list/list_renderer";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {loadJS, loadCSS} from "@web/core/assets";
|
||||
import {ListRendererCust} from "@tree_view_advanced_filter/tree_view_advanced_filter/tree"
|
||||
import {onWillDestroy, useEffect, onMounted} from "@odoo/owl";
|
||||
|
||||
patch(ListRenderer.prototype, {
|
||||
setup() {
|
||||
super.setup();
|
||||
// 固定两列
|
||||
onMounted(() => {
|
||||
this.freezeTwoColumns()
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 根据类名固定前两列和最后一列
|
||||
*/
|
||||
freezeTwoColumns() {
|
||||
|
||||
|
||||
const root = this.rootRef.el.closest('.sticky-enabled-two-columns');
|
||||
|
||||
if (!root) return;
|
||||
//
|
||||
const headers = this.rootRef.el.querySelectorAll("thead th");
|
||||
const dataRows = this.rootRef.el.querySelectorAll("tbody tr.o_data_row");
|
||||
const groupRows = this.rootRef.el.querySelectorAll("tbody tr.o_group_header");
|
||||
|
||||
//
|
||||
if (headers.length < 3) return; // 至少需要3列才能固定前两和最后一列
|
||||
|
||||
// 动态获取前两列宽度
|
||||
const leftOffsets = [];
|
||||
const colWidths = [];
|
||||
let leftWidthTotal = 0
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const width = headers[i].getBoundingClientRect().width;
|
||||
colWidths.push(width);
|
||||
leftWidthTotal = leftWidthTotal + width
|
||||
leftOffsets.push(leftWidthTotal)
|
||||
}
|
||||
console.log(leftOffsets)
|
||||
|
||||
const lastIndex = headers.length - 1;
|
||||
|
||||
// 前两列累计偏移
|
||||
|
||||
|
||||
// 固定前两列 header
|
||||
for (let i = 0; i < 5; i++) {
|
||||
this._makeSticky(headers[i], i === 0 ? 0 : leftOffsets[i - 1], "left");
|
||||
}
|
||||
|
||||
// 固定最后一列 header
|
||||
this._makeSticky(headers[lastIndex], 0, "right");
|
||||
|
||||
// 固定数据行的对应列
|
||||
dataRows.forEach(row => {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
this._makeSticky(row.children[i], i === 0 ? 0 : leftOffsets[i - 1], "left");
|
||||
}
|
||||
this._makeSticky(row.children[lastIndex], 0, "right");
|
||||
});
|
||||
|
||||
// 固定分组标题行(有些分组行列数会少于 header)
|
||||
// 分组只固定 前2 列
|
||||
groupRows.forEach(row => {
|
||||
const cells = row.querySelectorAll("td");
|
||||
|
||||
// 分组第一个必然固定
|
||||
this._makeSticky(cells[0], 0, "left", true);
|
||||
// 全部固定
|
||||
const cellThs = row.querySelectorAll("th")
|
||||
for (let i = 0; i < cellThs.length; i++) {
|
||||
const offset = leftOffsets[i];
|
||||
this._makeSticky(cellThs[i], offset, "left", true);
|
||||
}
|
||||
});
|
||||
},
|
||||
_makeSticky(cell, offset = 0, align = "left", isGroup = false) {
|
||||
|
||||
if (!cell) return;
|
||||
// cell 添加 class position-sticky
|
||||
cell.classList.add("position-sticky");
|
||||
cell.style.zIndex = isGroup ? "15" : "10";
|
||||
cell.style.background = "#fff";
|
||||
if (align === "left") {
|
||||
cell.style.left = `${offset}px`;
|
||||
} else if (align === "right") {
|
||||
cell.style.right = `${offset}px`;
|
||||
}
|
||||
},
|
||||
|
||||
toggleGroup(group) {
|
||||
super.toggleGroup(group)
|
||||
setTimeout(() => {
|
||||
this.freezeTwoColumns()
|
||||
}, 500)
|
||||
|
||||
},
|
||||
|
||||
getActiveColumns(list) {
|
||||
const columns = super.getActiveColumns(list);
|
||||
console.log(this.props.archInfo.className)
|
||||
// 判断 sticky-enabled-two-columns 在 this.props.archInfo.className
|
||||
if (!this.props.archInfo.className.includes('sticky-enabled-two-columns')) {
|
||||
return columns
|
||||
}
|
||||
|
||||
let values;
|
||||
if (this.props.list.selection && this.props.list.selection.length) {
|
||||
values = this.props.list.selection.map((r) => r.data);
|
||||
} else if (this.props.list.isGrouped) {
|
||||
values = this.props.list.groups.map((g) => g.aggregates);
|
||||
} else {
|
||||
values = this.props.list.records.map((r) => r.data);
|
||||
}
|
||||
return columns.filter(column => {
|
||||
const fieldInfo = list.fields[column.name];
|
||||
if (!fieldInfo) {
|
||||
return true;
|
||||
}
|
||||
if (["float","int", "monetary"].includes(fieldInfo.type)) {
|
||||
const fieldValues = values.map((v) => v[fieldInfo.name] || 0);
|
||||
const aggregateValue = fieldValues.reduce((acc, val) => acc + val);
|
||||
if (!aggregateValue) {
|
||||
console.log(column)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// ListRenderer.props.push('ooManagerColumns?');
|
||||
// ListRenderer.props.push('ooManagerFilter?');
|
||||
// ListRenderer.props.push('ooManagerSerialNum?');
|
||||
// ListRenderer.props.push('ooManagerStickyEnd?');
|
||||
@@ -10,6 +10,7 @@
|
||||
<attribute name="js_class">custom_salary_validation_button</attribute>
|
||||
<attribute name="default_order">employee_id</attribute>
|
||||
<attribute name="limit">20</attribute>
|
||||
<attribute name="class">sticky-enabled-two-columns</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='employee_id']" position="attributes">
|
||||
<attribute name="widget">false</attribute>
|
||||
@@ -415,7 +416,7 @@
|
||||
<field name="name">hr.payslip.tree.jtbb</field>
|
||||
<field name="model">hr.payslip</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="薪资计算" default_order="employee_id" js_class="custom_salary_button" editable="bottom" limit="20">
|
||||
<tree string="薪资计算" default_order="employee_id" js_class="custom_salary_button" class="sticky-enabled-two-columns" editable="bottom" limit="20">
|
||||
<header>
|
||||
<button name="action_put_wizard" string="推送" type="object" class="oe_highlight"/>
|
||||
<button name="action_temporary_payslip_wizard" string="导入工资项" type="object" class="oe_highlight"/>
|
||||
|
||||
Reference in New Issue
Block a user