odoo12 实现工作台
desktop.py
# -*- coding: utf-8 -*-
from odoo import models, fields, api, exceptions
import traceback
import logging
_logger = logging.getLogger(__name__)
class hr_desktop_notice(models.Model):
# 私有属性:(_name, _description, _inherit, …)
_name = 'hr.desktop.notice'
_description = u'工作台公告'
_order = 'sequence'
# 默认方法和 _default_get
# Field 字段声明
name = fields.Char(string=u'标题')
content = fields.Html(string=u'正文')
active = fields.Boolean(string=u'是否有效')
sequence = fields.Integer(string=u'序列')
# Compute, inverse and search 等计算和搜索方法和字段声明顺序一致
# Selection 方法(返回 selection 字段的列表值)
# Constrains 约束方法(@api.constrains) and onchange 字段值变更方法 (@api.onchange)
# CRUD方法(ORM 覆盖与继承)
# Action方法
# 其他业务方法
class hr_desktop_menu(models.Model):
# 私有属性:(_name, _description, _inherit, …)
_name = 'hr.desktop.menu'
_description = '工作台菜单'
_order = 'group_name,sequence'
# 默认方法和 _default_get
# Field 字段声明
name= fields.Char(string=u'名称')
descrition = fields.Text(string=u'描述')
# 通过action的外部标识ID拼接url地址,从而达到跳转页面的效果
model_data_id = fields.Many2one('ir.model.data', string=u'外部标识', required=True)
group_name = fields.Many2one('hr.desktop.menu.group', string=u'分组')
sequence = fields.Integer(string=u'菜单序列')
groups_name = fields.Text(string=u'权限分组名')
target = fields.Selection([('_self', u'在被点击时的同一框架中打开被链接'),
('_blank', u'在新窗口中打开被链接'),
('_parent', u'在父框架中打开被链接'),
('_top', u'在窗口主体中打开被链接')],
string=u'打开方式', default='_self', required=True)
action_id = fields.Many2one('ir.action.act_window', string='Action')
action_type = fields.Selection([('ir.actions.act_window', 'Action Window'),
('ir.actions.client', 'Action Client'),
('ir.actions.server', 'Action Server'),
('ir.actions.act_url', 'Action Url')],
string='Action Type', required=True)
# Compute, inverse and search 等计算和搜索方法和字段声明顺序一致
# Selection 方法(返回 selection 字段的列表值)
# Constrains 约束方法(@api.constrains) and onchange 字段值变更方法 (@api.onchange)
@api.model
def create(self, vals):
model_data_obj = self.env['ir.model.data']
model_data_id = model_data_obj.browse(vals.get('model_data_id'))
if model_data_id.model != vals.get('action_type'):
raise exceptions.ValidationError(u'选定的外部标识关联的类型与Action Type不符。')
return super(hr_desktop_menu, self).create(vals)
# CRUD方法(ORM 覆盖与继承)
# Action方法
# 其他业务方法
class hr_desktop_menu_group(models.Model):
# 私有属性:(_name, _description, _inherit, …)
_name = 'hr.desktop.menu.group'
_description = u'工作台菜单分组'
_order = 'sequence'
# 默认方法和 _default_get
# Field 字段声明
name = fields.Char(string=u'名称')
descrition = fields.Text(string=u'描述')
sequence = fields.Integer(string=u'序列')
groups_name = fields.Text(string=u'权限分组名')
menu_ids = fields.One2many('hr.desktop.menu', 'group_name', string=u'关联菜单')
active = fields.Boolean(string='active')
# Compute, inverse and search 等计算和搜索方法和字段声明顺序一致
# Selection 方法(返回 selection 字段的列表值)
# Constrains 约束方法(@api.constrains) and onchange 字段值变更方法 (@api.onchange)
# CRUD方法(ORM 覆盖与继承)
# Action方法
# 其他业务方法
desktop_page.xml
视图界面不做记录。
desktop_template.xml
模板:desktop_index
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="xxx_desktop_index" inherit_id="portal.frontend_layout" name="Desktop Index">
<!-- <t t-call="website.layout">-->
<!-- <t t-call="portal.frontend_layout">-->
<xpath expr="//div[@id='wrapwrap']/header" position="replace">
<nav class="o_main_navbar">
<ul class="o_menu_apps">
<li class="dropdown">
<a class="full" data-toggle="dropdown" data-display="static" href="#">
<i class="fa fa-th-large"/>
</a>
<div class="dropdown-menu" role="menu">
<t t-foreach="menus" t-as="app">
<a role="menuitem" t-attf-href="/web{{ '?debug=true' if is_debug else '' }}#menu_id={{app.id}}"
class="dropdown-item o_app">
<t t-esc="app.name"/>
</a>
</t>
</div>
</li>
</ul>
<a class="o_menu_brand" role="button">工作台</a>
<ul class="o_menu_sections" role="menu"/>
<ul class="o_menu_systray" role="menu">
<li class="o_user_menu">
<a aria-expanded="false" class="dropdown-toggle" data-display="static"
data-toggle="dropdown" href="#" role="button">
<span class="oe_topbar_name"
t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) > 25 else user_id.name"/>
</a>
<div class="dropdown-menu dropdown-menu-right" role="menu">
<!-- <div class="dropdown-divider" role="separator"></div>-->
<a id="o_logout" class="dropdown-item" t-attf-href="/web/session/logout?redirect=/"
role="menuitem">注销
</a>
</div>
</li>
<!-- <li class="nav-item dropdown" t-ignore="true" t-if="not user_id._is_public()">-->
<!-- <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">-->
<!-- <b>-->
<!-- <span t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) > 25 else user_id.name"/>-->
<!-- </b>-->
<!-- </a>-->
<!-- <div class="dropdown-menu js_usermenu" role="menu">-->
<!-- <a id="o_logout" class="dropdown-item" t-attf-href="/web/session/logout?redirect=/" role="menuitem">注销</a>-->
<!-- </div>-->
<!-- </li>-->
</ul>
</nav>
</xpath>
<xpath expr="//main" position="replace">
<div class="oe_structure">
<!-- 大屏 -->
<!-- <section class="s_cover parallax bg-200 pt80 pb80 s_parallax_is_fixed"-->
<!-- data-scroll-background-ratio="1" style="background-image: none;">-->
<!--<!– <span class="s_parallax_bg oe_img_bg oe_custom_bg"–>-->
<!--<!– style="background-image: url("/web/image/website.s_cover_default_image"); background-position: 93.72% 96.85%;"/>–>-->
<!-- <div class="container">-->
<!-- <div class="row s_nb_column_fixed">-->
<!-- <div class="col-lg-12 s_title" data-name="Title">-->
<!-- <h1 class="s_title_thin" style="font-size: 46px; text-align: center;">人力资源管理系统</h1>-->
<!-- </div>-->
<!-- <div class="col-lg-12 s_text pt16 pb16" data-name="Text">-->
<!--<!– <p class="lead" style="text-align: center;">写一两段描述你的产品、服务或具体功能。<br/>要获得成功,你的内容需要对你的读者有用。–>-->
<!--<!– </p>–>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </section>-->
<!-- 大屏 end -->
<!-- 公告栏 -->
<section groups="base.group_user" class="s_text_image pt0 pb0 oe_custom_bg"
style="background-size: cover; background-position: 0.17% 100%;">
<!-- 背景颜色 .bg-200 -->
<div class="container">
<div class="row align-items-start">
<!-- 公告栏 -->
<t t-foreach="notices" t-as="notice">
<div class="pl-3 pt8 pb8">
<div style="padding-left:20px;padding-right:20px;border-style:groove;border-radius:5px;border-width:2px">
<div class="pt16 pb16">
<h2>
<t t-esc="notice.name"/>
</h2>
<span>
<t t-raw="notice.content"/>
</span>
</div>
</div>
</div>
</t>
<!-- 公告栏 end -->
<!-- <div class="col-lg-12 pt8 pb0 border-bottom border-secondary" data-name="Box">-->
<!-- <h5 class="text-primary">-->
<!-- <span style="color: rgb(0, 0, 0); font-family: "Microsoft YaHei", sans-serif; font-size: 18px; text-align: center;">-->
<!-- <b>点击</b>-->
<!-- </span>-->
<!-- <span class="fa fa-hand-o-down" style="" data-original-title="" title=""-->
<!-- aria-describedby="tooltip805461"/>-->
<!-- <span style="color: rgb(0, 0, 0); font-family: "Microsoft YaHei", sans-serif; font-size: 18px; text-align: center;">-->
<!-- <b>按钮链接到相应界面</b>-->
<!-- </span>-->
<!-- <br/>-->
<!-- </h5>-->
<!-- </div>-->
</div>
</div>
</section>
<!-- 工作台导航 -->
<section groups="base.group_user" class="s_features_grid oe_custom_bg pt12 pb24" style="">
<div class="container">
<t t-foreach="group_list" t-as="g">
<div class="s_col_no_bgcolor pt24 pb12 border-bottom border-secondary">
<div class="pb4">
<h3 class="">
<strong>
<t t-esc="g['name']"/>
</strong>
</h3>
<small class="text-muted">
<t t-esc="g['descrition']"/>
</small>
</div>
<div class="row">
<t t-foreach="g['menu_list']" t-as="m">
<div class="s_col_no_bgcolor pr24 pb4 col-md-2">
<div class="s_features_grid_content">
<h4>
<span style="color: rgb(119, 119, 119); font-family: Noto, "Lucida Grande", Helvetica, Verdana, Arial, sans-serif; font-size: 18px; white-space: nowrap;">
<a class="btn btn-outline-beta" t-att-target="m['target']"
t-att-href="m['res_id']" t-att-title="m['descrition']">
<t t-esc="m['name']"/>
</a>
</span>
<br/>
</h4>
<!-- 描述
<u class="small"><t t-esc="m['descrition']"/></u>
-->
</div>
</div>
</t>
</div>
</div>
</t>
</div>
</section>
<!-- 工作台导航 end -->
</div>
</xpath>
<xpath expr="//div[@id='wrapwrap']/footer" position="replace">
</xpath>
<!-- </t>-->
</template>
</odoo>
desktop_controller.py
路由管理:
# -*- coding: utf-8 -*-
from odoo import http
import datetime
from odoo.http import request
from odoo import models
class Desktop(http.Controller):
@http.route('/xxxx/index', auth='user', website=True)
def desktop(self, **kw):
now = datetime.datetime.now()
notice_obj= request.env['hr.desktop.notice']
menu_obj= request.env['hr.desktop.menu']
menu_group_obj= request.env['hr.desktop.menu.group']
notices = notice_obj.search([('active', '=', True)], order='sequence')
menu_groups = menu_group_obj.search([])
group_list = []
for g in menu_groups:
# 群组权限控制
if g.groups_name and not menu_obj.user_has_groups(g.groups_name):
continue
g_item = {}
menu_list = []
for m in g.menu_ids: # hr.desktop.menu
if m.groups_name and not menu_obj.user_has_groups(m.groups_name):
continue
m_vals = {
'name' : m.name,
'descrition': m.descrition,
'sequence': m.sequence,
'target': m.target
}
if m.action_type == 'ir.actions.act_window':
m_vals['res_id'] = '/web#action=' + str(m.model_data_id.res_id)
elif m.action_type == 'ir.actions.act_url':
m_vals['res_id'] = request.env['ir.actions.act_url'].browse(m.model_data_id.res_id).url
menu_list.append(m_vals)
g_item['name'] = g.name
g_item['descrition'] = g.descrition
g_item['sequence'] = g.sequence
g_item['groups_name'] = g.groups_name
g_item['menu_list'] = menu_list
group_list.append(g_item)
menu_ids = list(request.env['ir.ui.menu']._visible_menu_ids()) # 查询所有当前用户拥有权限的菜单
menu_list = request.env['ir.ui.menu'].search([('parent_id', '=', False), ('id', 'in', menu_ids)], order='sequence')
if menu_obj.user_has_groups('base.group_system'):
debug = True
else:
debug = False
return request.render('xxx_desktop.xxx_desktop_index',
{'notices':notices, 'now':now, 'group_list':group_list, 'menus': menu_list, 'is_debug':debug})