·仿造odoo采购模块,在列表头部增加自定义内容
·效果图展示:????????
?实现方法:
1. 定义xml
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<!-- This template is for a table at the top of purchase views that shows some KPIs. -->
<t t-name="cost.costTypeAnalyze">
<div>
<FDatePicker t-model="valueState.value" allowClear="state.allowClear" autoFocus="state.autoFocus"
bordered="state.bordered"
disabled="state.disabled" inputReadOnly="state.inputReadOnly" range="state.range"
showTime="state.showTime"
showNow="state.showNow"
picker="state.picker"/>
</div>
<div class="dashboard-head">
<div class="analyze-card">
<div class="dashboard-title">xxxx</div>
<div class="dashboard-value">
<t t-esc="values['synthesis']['cost']"/>
</div>
<div class="analyze-data">
<div class="analyze-type">
<div class="dashboard-change">
<t t-esc="values['synthesis']['change']"/>
</div>
<div class="dashboard-change">xxxx</div>
</div>
<div class="analyze-type">
<div t-foreach="values['synthesis']['analyze']" t-as="analyze">
<t t-if="analyze['cost']">
<div>
<t t-esc="analyze['name']"/>:
<t t-esc="analyze['cost']"/>
</div>
</t>
<t t-else="">
<div class="analyze-hidden">
<t t-esc="analyze['name']"/>:
<t t-esc="analyze['cost']"/>
</div>
</t>
</div>
</div>
</div>
</div>
<div class="analyze-card">
<div class="dashboard-title">xxxxx</div>
<div class="dashboard-value">
<t t-esc="values['maintain']['cost']"/>
</div>
<div class="analyze-data">
<div class="analyze-type">
<div class="dashboard-change">
<t t-esc="values['maintain']['change']"/>
</div>
<div class="dashboard-change">环比</div>
</div>
<div class="analyze-type">
<div t-foreach="values['maintain']['analyze']" t-as="analyze">
<t t-if="analyze['cost']">
<div>
<t t-esc="analyze['name']"/>:
<t t-esc="analyze['cost']"/>
</div>
</t>
<t t-else="">
<div class="analyze-hidden">
<t t-esc="analyze['name']"/>:
<t t-esc="analyze['cost']"/>
</div>
</t>
</div>
</div>
</div>
</div>
<div class="analyze-card">
<div class="dashboard-title">xxxx</div>
<div class="dashboard-value">
<t t-esc="values['operation']['cost']"/>
</div>
<div class="analyze-data">
<div class="analyze-type">
<div class="dashboard-change">
<t t-esc="values['operation']['change']"/>
</div>
<div class="dashboard-change">环比</div>
</div>
<div class="analyze-type">
<div t-foreach="values['operation']['analyze']" t-as="analyze">
<t t-if="analyze['cost']">
<div>
<t t-esc="analyze['name']"/>:
<t t-esc="analyze['cost']"/>
</div>
</t>
<t t-else="">
<div class="analyze-hidden">
<t t-esc="analyze['name']"/>:
<t t-esc="analyze['cost']"/>
</div>
</t>
</div>
</div>
</div>
</div>
</div>
<div class="export-button">
<button class="o_dashboard_action btn btn-primary" string="导出">导出</button>
<button class="o_preview_click btn btn-primary" string="导出">预览</button>
</div>
</t>
</templates>
2. 扩展list的js
odoo.define('cost.costTypeAnalyze', function (require) {
"use strict";
/**
* 扩展tree视图, 在上方展示统计结果
*/
var core = require('web.core');
var ListController = require('web.ListController');
var ListModel = require('web.ListModel');
var ListRenderer = require('web.ListRenderer');
var ListView = require('web.ListView');
var SampleServer = require('web.SampleServer');
var view_registry = require('web.view_registry');
const session = require('web.session');
var QWeb = core.qweb;
// Add mock of method 'retrieve_dashboard' in SampleServer, so that we can have
// the sample data in empty purchase kanban and list view
let dashboardValues;
SampleServer.mockRegistry.add('repair.manage.cost.analyze/retrieve_dashboard', () => {
return Object.assign({}, dashboardValues);
});
//--------------------------------------------------------------------------
// List View
//--------------------------------------------------------------------------
var CostListDashboardRenderer = ListRenderer.extend({
events:_.extend({}, ListRenderer.prototype.events, {
'click .o_dashboard_action': '_onDashboardActionClicked',
'click .o_preview_click': '_onPreviewClick',
}),
/**
* @override
* @private
* @returns {Promise}
*/
_renderView: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
var values = self.state.dashboardValues;
var purchase_dashboard = QWeb.render('cost.costTypeAnalyze', {
values: values,
});
self.$el.prepend(purchase_dashboard);
});
},
_onDashboardActionClicked() {
// return this._rpc({route: '/download/statistic/excel', 'target': 'new'});
window.open(window.origin + '/download/statistic/excel')
},
_onPreviewClick() {
this.do_action({
name: '预览',
type: 'ir.actions.client',
tag: 'handover_iframe_client',
params: {
'url': '/repair_manage_cost/static/html/成本统计下载文件.html',
'downloadUrl': '/download/statistic/excel'
},
target: 'new'
}, {
on_close: function () {
}
})
}
});
var CostListDashboardModel = ListModel.extend({
/**
* @override
*/
init: function () {
this.dashboardValues = {};
this._super.apply(this, arguments);
},
/**
* @override
*/
__get: function (localID) {
var result = this._super.apply(this, arguments);
if (_.isObject(result)) {
result.dashboardValues = this.dashboardValues[localID];
}
return result;
},
/**
* @override
* @returns {Promise}
*/
__load: function () {
return this._loadDashboard(this._super.apply(this, arguments));
},
/**
* @override
* @returns {Promise}
*/
__reload: function () {
// 处理筛选条件
let domain = []
for (let argument of arguments) {
if (argument.domain) {
domain = domain.concat(argument.domain)
}
}
return this._loadDashboard(this._super.apply(this, arguments), domain);
},
/**
* @private
* @param {Promise} super_def a promise that resolves with a dataPoint id
* @param {domain} domain
* @returns {Promise -> string} resolves to the dataPoint id
*/
_loadDashboard: function (super_def, domain=[]) {
var self = this;
var dashboard_def = this._rpc({
model: 'repair.manage.cost.analyze',
method: 'retrieve_dashboard',
context: session.user_context,
kwargs: {
domain: domain
}
});
return Promise.all([super_def, dashboard_def]).then(function(results) {
var id = results[0];
dashboardValues = results[1];
self.dashboardValues[id] = dashboardValues;
return id;
});
},
});
var CostListDashboardController = ListController.extend({
});
var CostListDashboardView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Model: CostListDashboardModel,
Renderer: CostListDashboardRenderer,
Controller: CostListDashboardController,
}),
});
view_registry.add('cost_analyze', CostListDashboardView);
return {
CostListDashboardModel: CostListDashboardModel,
CostListDashboardRenderer: CostListDashboardRenderer,
CostListDashboardController: CostListDashboardController,
};
});
3.css样式:
?
.dashboard-head {
display: flex;
margin: 20px auto;
.analyze-card {
border-radius: 5px;
border: 2px solid #D3D3D3;
width: 32%;
margin: auto auto;
background-color: white;
.dashboard-title {
font-size: 16px;
margin-top: 10px;
margin-left: 20px
}
.dashboard-value {
font-size: 30px;
font-weight: bold;
margin-top: 10px;
margin-left: 20px;
color: red;
}
.analyze-data {
display: flex;
.dashboard-change {
}
.analyze-type {
width: 49%;
margin: 10px 20px;
.analyze-hidden {
color: white;
}
}
}
}
.export-button {
height: 30px
}
}
4.__manifest__中引入自定义文件
'assets': {
'web.assets_qweb': [
'repair_manage_plan/static/xml/*.xml',
'repair_manage_cost/static/xml/template.xml'
],
'web.assets_backend': [
'repair_manage_cost/static/src/scss/cost_dashboard.scss',
'repair_manage_cost/static/src/js/costTypeAnalyze.js',
],
},