pengyuthon wechat
This commit is contained in:
@@ -10,77 +10,75 @@ import { useService } from "@web/core/utils/hooks";
|
||||
import { session } from "@web/session";
|
||||
|
||||
export class CalculaterSh extends Component {
|
||||
static template = "CalculatorTemplate";
|
||||
static template = "CalculatorTemplate";
|
||||
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.search_sh_enable_calculator_mode()
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.search_sh_enable_calculator_mode()
|
||||
}
|
||||
|
||||
search_sh_enable_calculator_mode() {
|
||||
this.sh_enable_calculator_mode = session.sh_enable_calculator_mode
|
||||
}
|
||||
|
||||
onClickCalculator() {
|
||||
if($('.calculator').length > 0){
|
||||
$(".sh_calc_results").html("");
|
||||
}else{
|
||||
// render template
|
||||
var qweb_data = `
|
||||
<script type="text/javascript" src="/sh_backmate_theme_adv_enterprise/static/src/js/calculate.js"></script>
|
||||
<div class="calculator" align="center">
|
||||
<div class="row displayBox">
|
||||
<p class="displayText" id="display">0</p>
|
||||
</div>
|
||||
<div class="row numberPad">
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<button class="btn clear hvr-back-pulse" id="clear">C</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="sqrt">√</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="square">x<sup>2</sup></button>
|
||||
<button id="divide" class="btn btn-operation hvr-fade">÷</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="seven">7</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="eight">8</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="nine">9</button>
|
||||
<button id="multiply" class="btn btn-operation hvr-fade">×</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="four">4</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="five">5</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="six">6</button>
|
||||
<button id="subtract" class="btn btn-operation hvr-fade">−</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="one">1</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="two">2</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="three">3</button>
|
||||
<button id="add" class="btn btn-operation hvr-fade">+</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="plus_minus">±</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="zero">0</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="decimal">.</button>
|
||||
<button id="equals" class="btn btn-operation equals hvr-back-pulse">=</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
$(".sh_calc_results").html(qweb_data);
|
||||
}
|
||||
|
||||
search_sh_enable_calculator_mode() {
|
||||
this.sh_enable_calculator_mode = session.sh_enable_calculator_mode
|
||||
if($('.sh_calc_util').hasClass('active')){
|
||||
$('.sh_calc_util').removeClass('active')
|
||||
}else{
|
||||
$('.sh_calc_util').addClass('active')
|
||||
}
|
||||
// close other popup
|
||||
$('.sh_user_language_list_cls').css("display","none")
|
||||
$('.sh_wqm_quick_menu_submenu_list_cls').css("display","none")
|
||||
$('.todo_layout').removeClass("sh_theme_model");
|
||||
}
|
||||
|
||||
onClickCalculator() {
|
||||
if($('.calculator').length > 0){
|
||||
$(".sh_calc_results").html("");
|
||||
}else{
|
||||
// render template
|
||||
var qweb_data = '<script type="text/javascript" src="/sh_backmate_theme_adv_enterprise/static/src/js/calculate.js"></script>
|
||||
<div class="calculator" align="center">
|
||||
<div class="row displayBox">
|
||||
<p class="displayText" id="display">0</p>
|
||||
</div>
|
||||
<div class="row numberPad">
|
||||
<div class="col-md-12">
|
||||
<div class="row">
|
||||
<button class="btn clear hvr-back-pulse" id="clear">C</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="sqrt">√</button>
|
||||
<button class="btn btn-calc hvr-radial-out hvr-radial-out" id="square">x<sup>2</sup></button>
|
||||
<button id="divide" class="btn btn-operation hvr-fade">÷</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="seven">7</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="eight">8</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="nine">9</button>
|
||||
<button id="multiply" class="btn btn-operation hvr-fade">×</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="four">4</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="five">5</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="six">6</button>
|
||||
<button id="subtract" class="btn btn-operation hvr-fade">−</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="one">1</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="two">2</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="three">3</button>
|
||||
<button id="add" class="btn btn-operation hvr-fade">+</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn btn-calc hvr-radial-out" id="plus_minus">±</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="zero">0</button>
|
||||
<button class="btn btn-calc hvr-radial-out" id="decimal">.</button>
|
||||
<button id="equals" class="btn btn-operation equals hvr-back-pulse">=</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>'
|
||||
$(".sh_calc_results").html(qweb_data);
|
||||
}
|
||||
|
||||
if($('.sh_calc_util').hasClass('active')){
|
||||
$('.sh_calc_util').removeClass('active')
|
||||
}else{
|
||||
$('.sh_calc_util').addClass('active')
|
||||
}
|
||||
|
||||
// close other popup
|
||||
$('.sh_user_language_list_cls').css("display","none")
|
||||
$('.sh_wqm_quick_menu_submenu_list_cls').css("display","none")
|
||||
$('.todo_layout').removeClass("sh_theme_model");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registry.category("systray").add("sh_entmate_theme.calculater_sh", { Component: CalculaterSh }, { sequence: 25 });
|
||||
|
||||
@@ -374,62 +374,76 @@ patch(NavBar.prototype, {
|
||||
getXmlID(app_id) {
|
||||
return this.menuService.getMenuAsTree(app_id).xmlid;
|
||||
},
|
||||
OnClickDropdown(ev){
|
||||
/*close pop-ups*/
|
||||
$('.backmate_theme_layout').removeClass("sh_theme_model");
|
||||
$('.todo_layout').removeClass("sh_theme_model");
|
||||
$('.todo').removeClass('todo_active');
|
||||
$('.sh_calc_util').removeClass("active")
|
||||
$(".sh_calc_results").html("");
|
||||
$('.sh_wqm_quick_menu_submenu_list_cls').css("display","none")
|
||||
$('.o_user_bookmark_menu').removeClass('bookmark_active')
|
||||
$('.sh_search_results').css("display", "none");
|
||||
if (!$(ev.currentTarget).next().hasClass('show_ul')) {
|
||||
$(ev.currentTarget).next('.dropdown-menu-right').first().slideDown('slow');
|
||||
/**
|
||||
* 处理点击下拉菜单事件
|
||||
*
|
||||
* @param {Event} ev - 触发事件的对象
|
||||
*/
|
||||
OnClickDropdown(ev) {
|
||||
// 1. 关闭弹出窗口
|
||||
$('.backmate_theme_layout').removeClass("sh_theme_model");
|
||||
$('.todo_layout').removeClass("sh_theme_model");
|
||||
$('.todo').removeClass('todo_active');
|
||||
$('.sh_calc_util').removeClass("active");
|
||||
$(".sh_calc_results").html(""); // 清空计算结果
|
||||
$('.sh_wqm_quick_menu_submenu_list_cls').css("display", "none");
|
||||
$('.o_user_bookmark_menu').removeClass('bookmark_active');
|
||||
$('.sh_search_results').css("display", "none");
|
||||
|
||||
// 2. 切换子菜单显示状态
|
||||
// 检查当前菜单项的下一个兄弟元素是否有 'show_ul' 类
|
||||
if (!$(ev.currentTarget).next().hasClass('show_ul')) {
|
||||
// 如果没有展开子菜单,则展开当前菜单
|
||||
$(ev.currentTarget).next('.dropdown-menu-right').first().slideDown('slow');
|
||||
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').slideUp(600)
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').css("display", "none !important")
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').removeClass('show_ul');
|
||||
// 隐藏其他已经展开的子菜单
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').slideUp(600); // 收起其他子菜单
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').css("display", "none !important"); // 强制隐藏
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').removeClass('show_ul'); // 移除 'show_ul' 类
|
||||
|
||||
// 3. 根据当前父元素的不同,调整子菜单的样式
|
||||
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length === 1) {
|
||||
// 如果当前菜单的父元素是 '.dropdown-header',则给它添加样式
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').addClass('sh_sub_dropdown');
|
||||
} else if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length > 1) {
|
||||
// 如果当前菜单的父元素是 '.dropdown-header',则给它添加样式
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').addClass('sh_sub_dropdown');
|
||||
} else {
|
||||
// 否则,调整其他菜单项的样式
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_dropdown').removeClass('sh_dropdown');
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.active').removeClass('active');
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('sh_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length == 1) {
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').addClass('sh_sub_dropdown');
|
||||
// 4. 如果子菜单已经展开,则隐藏它
|
||||
if ($(ev.currentTarget).next().hasClass('show_ul')) {
|
||||
// 如果当前子菜单已经展开,则收起它
|
||||
$(ev.currentTarget).next('.dropdown-menu-right').first().slideUp(600);
|
||||
|
||||
// 移除展开时的样式
|
||||
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length === 1) {
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').removeClass('sh_sub_dropdown');
|
||||
} else if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length > 1) {
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').first().children('.dropdown-item').removeClass('sh_sub_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').last().removeClass('sh_sub_dropdown');
|
||||
} else {
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('sh_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_dropdown').removeClass('sh_dropdown');
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.active').removeClass('active');
|
||||
|
||||
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('sh_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
if ($(ev.currentTarget).next().hasClass('show_ul')) {
|
||||
$(ev.currentTarget).next('.dropdown-menu-right').first().slideUp(600);
|
||||
|
||||
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length == 1) {
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').removeClass('sh_sub_dropdown');
|
||||
} else {
|
||||
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('sh_dropdown');
|
||||
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
var $subMenu = $(ev.currentTarget).next('.dropdown-menu');
|
||||
$subMenu.toggleClass('show_ul');
|
||||
|
||||
// 5. 切换当前子菜单的状态
|
||||
var $subMenu = $(ev.currentTarget).next('.dropdown-menu');
|
||||
$subMenu.toggleClass('show_ul'); // 切换子菜单的显示状态
|
||||
},
|
||||
currentMenuAppSections(app_id) {
|
||||
|
||||
return (
|
||||
(this.menuService.getMenuAsTree(app_id).childrenTree) ||
|
||||
[]
|
||||
);
|
||||
currentMenuAppSections(app_id) {
|
||||
return ((this.menuService.getMenuAsTree(app_id).childrenTree) || []);
|
||||
},
|
||||
|
||||
getThemeStyle(ev) {
|
||||
|
||||
@@ -560,6 +560,7 @@
|
||||
width: 260px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.o-dropdown--menu.dropdown-menu.d-block {
|
||||
width: 70px !important;
|
||||
min-width: 70px !important;
|
||||
|
||||
@@ -1,234 +1,159 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="ChildLink" owl="1">
|
||||
|
||||
<t t-if="!sub2_sections.length">
|
||||
<t t-set="depth" t-value="1" />
|
||||
<DropdownItem
|
||||
href="getMenuItemHref(sub_section)"
|
||||
dataset="{ menuXmlid: sub_section.xmlid, section: sub_section.id }"
|
||||
onSelected="() => this.onNavBarDropdownItemSelection(sub_section)"
|
||||
>
|
||||
<span>
|
||||
<t t-esc="sub_section.name"/>
|
||||
</span>
|
||||
</DropdownItem>
|
||||
|
||||
</t>
|
||||
<t t-else="">
|
||||
<a class="sh_dropdown_toggle dropdown-item dropdown-toggle" t-on-click.stop="OnClickDropdown">
|
||||
<span class="fa fa-circle-thin"></span>
|
||||
<span>
|
||||
<t t-esc="sub_section.name" />
|
||||
<t t-name="AppIcon" owl="1">
|
||||
<t t-set="app_id" t-value="app.id" />
|
||||
<a t-att-href="getMenuItemHref(app)" >
|
||||
<t t-if="icon_style == 'standard'">
|
||||
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&field=web_icon_data&id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
|
||||
</t>
|
||||
<t t-elif="icon_style == 'line_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'three_d'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<img class="img threed_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/3d_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'dual_tone'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}}-dt sh_fa_icon">
|
||||
<span class="path1"/>
|
||||
<span class="path2"/>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<t t-foreach="sub2_sections" t-as="sub2_section" t-key="sub2_section.id">
|
||||
<t t-set="sub2_sections" t-value="currentMenuAppSections(sub2_section.id)" />
|
||||
<t t-if="sub2_section.length">
|
||||
<t t-call="ChildLink">
|
||||
<t t-set="sub2_sections" t-value="sub2_sections" /></t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div t-attf-class="dropdown-header">
|
||||
<DropdownItem
|
||||
href="getMenuItemHref(sub2_section)"
|
||||
dataset="{ menuXmlid: sub2_section.xmlid, section: sub2_section.id }"
|
||||
onSelected="() => this.onNavBarDropdownItemSelection(sub2_section)"
|
||||
>
|
||||
<span class="fa fa-circle-thin"></span>
|
||||
|
||||
<span>
|
||||
<t t-esc="sub2_section.name"/>
|
||||
</span>
|
||||
</DropdownItem>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
</t>
|
||||
<t t-elif="icon_style == 'glass_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<img class="img glass_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/glass_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'light_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}}-l sh_fa_icon"/>
|
||||
</t>
|
||||
<span>
|
||||
<t t-esc="app.name"/>
|
||||
</span>
|
||||
</a>
|
||||
</t>
|
||||
|
||||
|
||||
<!-- 菜单递归模板 -->
|
||||
<t t-name="AppsTreeMenu" owl="1">
|
||||
<!-- 子菜单 -->
|
||||
<t t-set="children_menus" t-value="menu.childrenTree" />
|
||||
<!-- 不存在子菜单 -->
|
||||
<t t-if="!children_menus.length">
|
||||
<div class="dropdown-header dropdown-item o_menu_header_lvl_1">
|
||||
<DropdownItem
|
||||
href="getMenuItemHref(menu)"
|
||||
dataset="{ menu: menu.xmlid, section: menu.id }"
|
||||
onSelected="() => this.onNavBarDropdownItemSelection(menu)"
|
||||
>
|
||||
<span class="fa fa-circle-thin"/>
|
||||
<span>
|
||||
<t t-esc="menu.name"/>
|
||||
</span>
|
||||
</DropdownItem>
|
||||
</div>
|
||||
</t>
|
||||
<!-- 存在子菜单 -->
|
||||
<t t-else="">
|
||||
<div class="dropdown-header o_menu_header_lvl_2" >
|
||||
<a class="sh_dropdown_toggle dropdown-item dropdown-toggle" t-on-click.stop="OnClickDropdown">
|
||||
<span class="fa fa-circle-thin"/>
|
||||
<span>
|
||||
<t t-esc="menu.name" />
|
||||
</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<t t-foreach="children_menus" t-as="children" t-key="children.id">
|
||||
<t t-set="children_sub_menus" t-value="children.childrenTree" />
|
||||
<t t-if="children_sub_menus.length">
|
||||
<t t-call="AppsTreeMenu">
|
||||
<t t-set="menu" t-value="children" />
|
||||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="dropdown-header dropdown-item o_menu_header_lvl_1">
|
||||
<DropdownItem
|
||||
href="getMenuItemHref(children)"
|
||||
dataset="{ menu: children.xmlid, section: children.id }"
|
||||
onSelected="() => this.onNavBarDropdownItemSelection(children)"
|
||||
>
|
||||
<span class="fa fa-circle-thin"/>
|
||||
<span>
|
||||
<t t-esc="children.name"/>
|
||||
</span>
|
||||
</DropdownItem>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="sh.NavBar.AppsMenu" owl="1">
|
||||
<a style="z-index:1111;display:none;" id="js_bar_toggle_btn_mobile" t-on-click="_click_js_bar_toggle_btn_mobile" class="">
|
||||
<i class="fa fa-bars" id="toggle_bar" t-on-click="_click_toggle_bar" />
|
||||
</a>
|
||||
<div class="blur_div blur_toggle" t-on-click="_click_blur_div"></div>
|
||||
<a style="z-index:1111;display:none;" id="js_bar_toggle_btn_mobile" t-on-click="_click_js_bar_toggle_btn_mobile" class="">
|
||||
<i class="fa fa-bars" id="toggle_bar" t-on-click="_click_toggle_bar" />
|
||||
</a>
|
||||
<div class="blur_div blur_toggle" t-on-click="_click_blur_div"/>
|
||||
<div t-on-mouseenter="onMouseenter_sh_backmate_theme_appmenu_div" t-on-mouseleave="onMouseleave_sh_backmate_theme_appmenu_div">
|
||||
<Dropdown hotkey="'h'" title="'Home Menu'" class="'o_navbar_apps_menu sh_backmate_theme_appmenu_div'" t-on-mouseenter="onMouseenter_sh_backmate_theme_appmenu_div"
|
||||
t-on-mouseleave="onMouseleave_sh_backmate_theme_appmenu_div">
|
||||
<t t-set-slot="toggler">
|
||||
</t>
|
||||
<Dropdown
|
||||
hotkey="'h'"
|
||||
title="'Home Menu'"
|
||||
class="'o_navbar_apps_menu sh_backmate_theme_appmenu_div'"
|
||||
t-on-mouseenter="onMouseenter_sh_backmate_theme_appmenu_div"
|
||||
t-on-mouseleave="onMouseleave_sh_backmate_theme_appmenu_div"
|
||||
>
|
||||
<t t-set-slot="toggler"/>
|
||||
<!-- LOGO -->
|
||||
<div class="logo" style="width: 100%;display: flex;max-width: 100%;align-items: center;margin-top: 20px;">
|
||||
<img t-attf-src="/web/image?model=res.company&field=company_name_logo&id={{get_current_company()}}"
|
||||
id="company_logo" style="margin-left: 10px;height: 30px;width: 30px;max-width: 30px;margin-right: 19px;" />
|
||||
<img class="img" t-attf-src="/web/image?model=res.company&field=logo&id={{get_current_company()}}"
|
||||
style="height: 3rem;padding: 10px 0;width: 55%;padding-left: 0;" id="company_name_logo" />
|
||||
<img t-attf-src="/web/image?model=res.company&field=company_name_logo&id={{get_current_company()}}" id="company_logo" style="margin-left: 10px;height: 30px;width: 30px;max-width: 30px;margin-right: 19px;" />
|
||||
<img class="img" t-attf-src="/web/image?model=res.company&field=logo&id={{get_current_company()}}" style="height: 3rem;padding: 10px 0;width: 55%;padding-left: 0;" id="company_name_logo" />
|
||||
<span class="icon-top_hide fa fa-toggle-on" id="hide_top_bar" t-on-click="_click_hide_top_bar" style="margin-left: 25px;margin-top: 0px; font-size: 20px;"/>
|
||||
<span class="icon-top_show fa fa-toggle-off" id="show_top_bar" t-on-click="_click_show_top_bar" style="margin-left: 25px;margin-top: 0px;font-size: 20px;"/>
|
||||
</div>
|
||||
<!-- 菜单项 -->
|
||||
<t class="'o_app'" t-foreach="apps" t-as="app" t-key="app.id" t-on-click="_click_o_app">
|
||||
|
||||
<t t-set="app_icon" t-value="getXmlID(app.id)"/>
|
||||
<t t-set="icon_style" t-value="getIconStyle()"/>
|
||||
|
||||
<t t-if="currentMenuAppSections(app.id).length" >
|
||||
<t t-set="sections" t-value="currentMenuAppSections(app.id)" />
|
||||
<div class="sh_dropdown_div cssmenu">
|
||||
<span
|
||||
t-key="app.id"
|
||||
class="sh_dropdown_toggle dropdown-item child_app o_app2"
|
||||
payload="app" t-on-click.stop="OnClickDropdown" t-on-mouseenter="onMouseenter_o_app2"
|
||||
>
|
||||
<t t-set="app_id" t-value="app.id" />
|
||||
<a t-att-href="getMenuItemHref(app)" >
|
||||
|
||||
<t t-if="icon_style == 'standard'">
|
||||
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&field=web_icon_data&id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
|
||||
</t>
|
||||
<t t-elif="icon_style == 'line_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"></span>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'three_d'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<img class="img" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/3d_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'dual_tone'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}}-dt sh_fa_icon">
|
||||
<span class="path1"></span>
|
||||
<span class="path2"></span>
|
||||
</span>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'glass_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<img class="img" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/glass_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'light_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}}-l sh_fa_icon"></span>
|
||||
</t>
|
||||
<span>
|
||||
<t t-esc="app.name"/>
|
||||
</span>
|
||||
</a>
|
||||
</span>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<t t-foreach="sections" t-as="section" t-key="section.id">
|
||||
<t t-set="sub_sections" t-value="currentMenuAppSections(section.id)" />
|
||||
<t t-if="!sub_sections.length">
|
||||
<t t-set="depth" t-value="1" />
|
||||
<div class="dropdown-header dropdown-item o_menu_header_lvl_1">
|
||||
<DropdownItem
|
||||
href="getMenuItemHref(section)"
|
||||
dataset="{ menuXmlid: section.xmlid, section: section.id }"
|
||||
onSelected="() => this.onNavBarDropdownItemSelection(section)"
|
||||
>
|
||||
<span class="fa fa-circle-thin"></span>
|
||||
<span>
|
||||
<t t-esc="section.name"/>
|
||||
</span>
|
||||
</DropdownItem>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div t-attf-class="dropdown-header o_menu_header_lvl_1">
|
||||
<div class="sh_icon_text">
|
||||
<span class="fa fa-circle-thin"></span>
|
||||
<span>
|
||||
<t t-esc="section.name" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<t t-foreach="sub_sections" t-as="sub_section" t-key="sub_section.id">
|
||||
<t t-set="sub2_sections" t-value="currentMenuAppSections(sub_section.id)" />
|
||||
<div class="dropdown-header o_menu_header_lvl_2" >
|
||||
<t t-if="sub2_sections.length">
|
||||
<t t-call="ChildLink">
|
||||
<t t-set="sub2_sections" t-value="sub2_sections"></t>
|
||||
</t>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<DropdownItem
|
||||
href="getMenuItemHref(sub_section)"
|
||||
dataset="{ menuXmlid: sub_section.xmlid, section: sub_section.id }"
|
||||
onSelected="() => this.onNavBarDropdownItemSelection(sub_section)"
|
||||
>
|
||||
<span class="fa fa-circle-thin"></span>
|
||||
<span>
|
||||
<t t-esc="sub_section.name"/>
|
||||
</span>
|
||||
|
||||
</DropdownItem>
|
||||
</t>
|
||||
</div>
|
||||
<t t-set="app_icon" t-value="getXmlID(app.id)"/>
|
||||
<t t-set="icon_style" t-value="getIconStyle()"/>
|
||||
<!-- 子菜单 -->
|
||||
<t t-set="sections" t-value="currentMenuAppSections(app.id)"/>
|
||||
<!-- 有子菜单 -->
|
||||
<t t-if="sections.length" >
|
||||
<div class="sh_dropdown_div cssmenu">
|
||||
<!-- 菜单图标 -->
|
||||
<span t-key="app.id"
|
||||
class="sh_dropdown_toggle dropdown-item child_app o_app2"
|
||||
payload="app"
|
||||
t-on-click.stop="OnClickDropdown"
|
||||
t-on-mouseenter="onMouseenter_o_app2"
|
||||
>
|
||||
<t t-call="AppIcon"/>
|
||||
</span>
|
||||
<!-- 子菜单项 -->
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||
<t t-foreach="sections" t-as="section" t-key="section.id">
|
||||
<t t-call="AppsTreeMenu">
|
||||
<t t-set="menu" t-value="section" />
|
||||
</t>
|
||||
|
||||
|
||||
</t>
|
||||
</t>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="cssmenu">
|
||||
|
||||
<t t-set="app_id" t-value="app.id" />
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<!-- 没有子菜单,点击直接跳转 -->
|
||||
<div class="cssmenu">
|
||||
<span class="dropdown-item o_app direct_menu" t-on-click="_click_o_app" payload="app">
|
||||
|
||||
<a t-att-href="getMenuItemHref(app)">
|
||||
|
||||
<t t-if="icon_style == 'standard'">
|
||||
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&field=web_icon_data&id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
|
||||
</t>
|
||||
<t t-elif="icon_style == 'line_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"></span>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'three_d'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<img class="img threed_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/3d_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'dual_tone'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}}-dt sh_fa_icon">
|
||||
<span class="path1"></span>
|
||||
<span class="path2"></span>
|
||||
</span>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'glass_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<img class="img glass_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/glass_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
|
||||
</t>
|
||||
<t t-elif="icon_style == 'light_icon'">
|
||||
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
|
||||
<span t-attf-class="sh-{{app_cls_name}}-l sh_fa_icon"></span>
|
||||
</t>
|
||||
<span>
|
||||
<t t-esc="app.name"/>
|
||||
</span>
|
||||
|
||||
</a>
|
||||
<t t-call="AppIcon"/>
|
||||
</span>
|
||||
<!-- </MenuItem> -->
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
|
||||
</t>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
|
||||
<t t-name="web.NavBar" t-inherit="web.NavBar" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//nav[hasclass('o_main_navbar')]" position="after">
|
||||
@@ -259,21 +184,16 @@
|
||||
<!-- Systray -->
|
||||
<div class="o_menu_systray d-flex flex-shrink-0 ms-auto" role="menu">
|
||||
<t t-foreach="systrayItems" t-as="item" t-key="item.key">
|
||||
<div t-att-data-index="item.index"/>
|
||||
<ErrorHandler onError="error => this.handleItemError(error, item)">
|
||||
<t t-component="item.Component" t-props="item.props"/>
|
||||
</ErrorHandler>
|
||||
<div t-att-data-index="item.index"/>
|
||||
<ErrorHandler onError="error => this.handleItemError(error, item)">
|
||||
<t t-component="item.Component" t-props="item.props"/>
|
||||
</ErrorHandler>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
</xpath>
|
||||
|
||||
|
||||
</t>
|
||||
|
||||
|
||||
|
||||
<t t-name="Menu.link">
|
||||
<t t-set="depth" t-value="(depth || 0) + 1"/>
|
||||
<t t-if="!menu.childrenTree.length">
|
||||
@@ -304,7 +224,8 @@
|
||||
</span>
|
||||
</div>
|
||||
<t t-foreach="menu.childrenTree" t-as="menu" t-key="menu.id">
|
||||
<t t-call="Menu.link"/></t>
|
||||
<t t-call="Menu.link"/>
|
||||
</t>
|
||||
</t>
|
||||
<li t-else="" class="sh_profile_menu_section">
|
||||
<a href="#" t-attf-class="o_menu_entry_lvl_#{depth}" data-toggle="dropdown" role="button" aria-expanded="false" t-att-data-menu-xmlid="menu.xmlid" >
|
||||
@@ -313,11 +234,11 @@
|
||||
</a>
|
||||
<ul>
|
||||
<t t-foreach="menu.childrenTree" t-as="menu" t-key="menu.id">
|
||||
<t t-call="Menu.link"/></t>
|
||||
<t t-call="Menu.link"/>
|
||||
</t>
|
||||
</ul>
|
||||
</li>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -6,9 +6,5 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import base64
|
||||
import datetime
|
||||
from datetime import datetime, timedelta, time
|
||||
import logging
|
||||
import traceback
|
||||
from odoo import api, fields, models, tools, _
|
||||
@@ -14,7 +14,8 @@ class HrAttendanceDetailImage(models.Model):
|
||||
_name = "hr.attendance.detail.image"
|
||||
_description = "打卡原始抓取数据图片"
|
||||
|
||||
attendance_detail_id = fields.Many2one('hr.attendance.detail', string="原始打卡记录", ondelete="cascade", readonly=True)
|
||||
attendance_detail_id = fields.Many2one('hr.attendance.detail', string="原始打卡记录", ondelete="cascade",
|
||||
readonly=True)
|
||||
media_url = fields.Char(string='附件地址')
|
||||
media_file = fields.Binary(string='附件文件', compute="_compute_media_file")
|
||||
|
||||
@@ -55,7 +56,8 @@ class HrAttendanceDetail(models.Model):
|
||||
schedule_id = fields.Char(string='班次id')
|
||||
timeline_id = fields.Integer(string='时段id')
|
||||
|
||||
attendance_detail_image_ids = fields.One2many(string="打卡记录图片", comodel_name='hr.attendance.detail.image', inverse_name='attendance_detail_id')
|
||||
attendance_detail_image_ids = fields.One2many(string="打卡记录图片", comodel_name='hr.attendance.detail.image',
|
||||
inverse_name='attendance_detail_id')
|
||||
hr_attendance_id = fields.Many2one('hr.attendance', string="出勤记录", ondelete="cascade", readonly=True)
|
||||
|
||||
def action_show_details(self):
|
||||
@@ -97,8 +99,8 @@ class HrAttendanceDetail(models.Model):
|
||||
:return:
|
||||
"""
|
||||
# 先按照天抓取,时间戳
|
||||
now_time = datetime.datetime.now() + datetime.timedelta(hours=8)
|
||||
start_time = now_time - datetime.timedelta(days=30)
|
||||
now_time = datetime.now() + timedelta(hours=8)
|
||||
start_time = now_time - timedelta(days=30)
|
||||
start_time_stamp = int(start_time.timestamp())
|
||||
end_time_stamp = int(now_time.timestamp())
|
||||
# 整理请求信息
|
||||
@@ -127,7 +129,8 @@ class HrAttendanceDetail(models.Model):
|
||||
return []
|
||||
result = response.json()
|
||||
if result.get('errcode') != 0:
|
||||
_logger.error('获取外出打卡数据失败,异常:{0},用户列表{1}'.format(str(result.get('errmsg')), str(userid_limit)))
|
||||
_logger.error(
|
||||
'获取外出打卡数据失败,异常:{0},用户列表{1}'.format(str(result.get('errmsg')), str(userid_limit)))
|
||||
return []
|
||||
checkin_data = result.get('checkindata', [])
|
||||
if not checkin_data:
|
||||
@@ -148,8 +151,8 @@ class HrAttendanceDetail(models.Model):
|
||||
if not userid or not checkin_time_stamp:
|
||||
_logger.error('没有抓取到用户出勤信息,异常:{0},用户列表{1}'.format(str(data), str(userid_limit)))
|
||||
return False
|
||||
checkin_time = datetime.datetime.fromtimestamp(checkin_time_stamp) if checkin_time_stamp else None
|
||||
sch_checkin_time = datetime.datetime.fromtimestamp(sch_checkin_time_stamp) if sch_checkin_time_stamp else None
|
||||
checkin_time = datetime.fromtimestamp(checkin_time_stamp) if checkin_time_stamp else None
|
||||
sch_checkin_time = datetime.fromtimestamp(sch_checkin_time_stamp) if sch_checkin_time_stamp else None
|
||||
return checkin_time, sch_checkin_time
|
||||
|
||||
def _check_wx_attendance_media(self, data):
|
||||
@@ -172,7 +175,8 @@ class HrAttendanceDetail(models.Model):
|
||||
try:
|
||||
result, response = self.sudo().env["wecom.apps"].sync_media_get(data)
|
||||
if result:
|
||||
filename = response.headers['Content-Disposition'].split('; ')[2].replace('filename=', '').replace('"', '')
|
||||
filename = response.headers['Content-Disposition'].split('; ')[2].replace('filename=', '').replace(
|
||||
'"', '')
|
||||
wx_work_auth = self.env['auth.oauth.provider'].search([('name', '=', 'Wechat Card')], limit=1)
|
||||
wx_work_image = os.path.join(wx_work_auth.wx_work_image_path, str(filename))
|
||||
with open(wx_work_image, 'wb') as f:
|
||||
@@ -181,9 +185,11 @@ class HrAttendanceDetail(models.Model):
|
||||
'media_url': filename,
|
||||
}))
|
||||
else:
|
||||
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1}'.format(str(response), str(data)))
|
||||
_logger.error(
|
||||
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1}'.format(str(response), str(data)))
|
||||
except Exception as e:
|
||||
_logger.error('请求原始图片失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
|
||||
_logger.error('请求原始图片失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data),
|
||||
str(traceback.format_exc())))
|
||||
|
||||
return media_list
|
||||
|
||||
@@ -198,7 +204,8 @@ class HrAttendanceDetail(models.Model):
|
||||
"""
|
||||
userid = data.get("userid", "")
|
||||
# 查询是否存在数据
|
||||
if userid and checkin_time and self.env['hr.attendance.detail'].sudo().search_count([("userid", "=", userid), ("checkin_time", "=", checkin_time)]) <= 0:
|
||||
if userid and checkin_time and self.env['hr.attendance.detail'].sudo().search_count(
|
||||
[("userid", "=", userid), ("checkin_time", "=", checkin_time)]) <= 0:
|
||||
res_user_obj = self.env['res.users'].sudo().search([("oauth_uid", "=", userid)], limit=1)
|
||||
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "=", res_user_obj.id)], limit=1)
|
||||
if not res_user_obj or not hr_employee_obj:
|
||||
@@ -232,15 +239,18 @@ class HrAttendanceDetail(models.Model):
|
||||
media_list = self._check_wx_attendance_media(data)
|
||||
attendance_detail_obj.attendance_detail_image_ids = media_list
|
||||
except Exception as e:
|
||||
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
|
||||
_logger.error(
|
||||
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data),
|
||||
str(traceback.format_exc())))
|
||||
|
||||
userid = data.get("userid", "")
|
||||
# 区分当天的上班,下班,中午打卡,合并一个
|
||||
checkin_time_now = checkin_time + datetime.timedelta(hours=8) if checkin_time else None
|
||||
sch_checkin_time_now = sch_checkin_time + datetime.timedelta(hours=8) if sch_checkin_time else None
|
||||
current_data = (sch_checkin_time + datetime.timedelta(hours=8)).strftime("%Y-%m-%d") if sch_checkin_time_now else checkin_time_now.strftime("%Y-%m-%d")
|
||||
checkin_time_now = checkin_time + timedelta(hours=8) if checkin_time else None
|
||||
sch_checkin_time_now = sch_checkin_time + timedelta(hours=8) if sch_checkin_time else None
|
||||
current_data = (sch_checkin_time + timedelta(hours=8)).strftime("%Y-%m-%d") if sch_checkin_time_now else checkin_time_now.strftime("%Y-%m-%d")
|
||||
# 同步整理当天出勤数据
|
||||
attendance_obj = self.env['hr.attendance'].search([("userid", "=", userid), ("current_data", "=", current_data)], limit=1)
|
||||
attendance_obj = self.env['hr.attendance'].search(
|
||||
[("userid", "=", userid), ("current_data", "=", current_data)], limit=1)
|
||||
attendance_obj.attendance_type = "wx_work"
|
||||
checkin_type = data.get("checkin_type", "")
|
||||
exception_type = data.get("exception_type", "")
|
||||
@@ -255,10 +265,8 @@ class HrAttendanceDetail(models.Model):
|
||||
"attendance_type": "wx_work"
|
||||
})
|
||||
else:
|
||||
current_datetime_start = datetime.datetime.combine(
|
||||
datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.min)
|
||||
current_datetime_end = datetime.datetime.combine(
|
||||
datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.max)
|
||||
current_datetime_start = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.min.time())
|
||||
current_datetime_end = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.max.time())
|
||||
planning_slot_id = self.env['planning.slot'].search(
|
||||
[('resource_id', '=', hr_employee_obj.resource_id.id),
|
||||
('start_datetime', '>=', current_datetime_start),
|
||||
@@ -272,7 +280,7 @@ class HrAttendanceDetail(models.Model):
|
||||
"attendance_type": "wx_work"
|
||||
})
|
||||
if not hr_employee_obj.default_planning_role_id:
|
||||
# 获取考勤日历的上班下班时间
|
||||
# 获取考勤日历的上班下班时间
|
||||
min_hour_from = self.env['resource.calendar'].search([])[0].attendance_ids[0].hour_from
|
||||
min_hour = int(min_hour_from)
|
||||
min_minute = int(min_hour_from * 10 % min_hour_from)
|
||||
@@ -327,60 +335,67 @@ class HrAttendanceDetail(models.Model):
|
||||
else:
|
||||
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
|
||||
else:
|
||||
current_datetime_start = datetime.datetime.combine(datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.min)
|
||||
current_datetime_end = datetime.datetime.combine(datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.max)
|
||||
current_data = datetime.strptime(current_data, '%Y-%m-%d')
|
||||
# 获取当天的起始和结束时间
|
||||
current_datetime_start = datetime.combine(current_data, datetime.min.time())
|
||||
current_datetime_end = datetime.combine(current_data, datetime.max.time())
|
||||
# 获取本人当天的班次
|
||||
planning_id = self.env['planning.slot'].search([('resource_id', '=', hr_employee_obj.resource_id.id),
|
||||
('start_datetime', '>=', current_datetime_start),
|
||||
('start_datetime', '<=', current_datetime_end)])
|
||||
if planning_id:
|
||||
planning_start_time = planning_id.start_datetime
|
||||
planning_end_time = planning_id.end_datetime
|
||||
if planning_id.department_id.name == '保安部':
|
||||
planning_start_time = planning_id.start_datetime + timedelta(hours=8)
|
||||
planning_end_time = planning_id.end_datetime + timedelta(hours=8)
|
||||
if planning_id.role_id.name == '保安部':
|
||||
# {'白班': [['8:30', '9.30'], ['8:30', '9.30']]}white
|
||||
# {'中班': [['8:30', '9.30'], ['8:30', '9.30']]}mid
|
||||
# {'夜班': [['8:30', '9.30'], ['8:30', '9.30']]}night
|
||||
# 白班上班区间
|
||||
start_time = datetime.datetime.combine(current_data, datetime.time(6, 0))+ datetime.timedelta(hours=8)
|
||||
end_time = datetime.datetime.combine(current_data, datetime.time(9, 0))+ datetime.timedelta(hours=8)
|
||||
start_time = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
|
||||
end_time = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
|
||||
# 白班下班区间
|
||||
start_time1 = datetime.datetime.combine(current_data, datetime.time(2, 0))+ datetime.timedelta(hours=8)
|
||||
end_time1 = datetime.datetime.combine(current_data, datetime.time(4, 0))+ datetime.timedelta(hours=8)
|
||||
start_time1 = datetime.combine(current_data, time(2, 0)) + timedelta(hours=8)
|
||||
end_time1 = datetime.combine(current_data, time(4, 0)) + timedelta(hours=8)
|
||||
# 中班上班区间
|
||||
start_time2 = datetime.datetime.combine(current_data, datetime.time(14, 0))+ datetime.timedelta(hours=8)
|
||||
end_time2 = datetime.datetime.combine(current_data, datetime.time(17, 0))+ datetime.timedelta(hours=8)
|
||||
start_time2 = datetime.combine(current_data, time(14, 0)) + timedelta(hours=8)
|
||||
end_time2 = datetime.combine(current_data, time(17, 0)) + timedelta(hours=8)
|
||||
# 中班下班区间
|
||||
start_time3 = datetime.datetime.combine(current_data, datetime.time(22, 0))+ datetime.timedelta(hours=8)
|
||||
end_time3 = datetime.datetime.combine(current_data, datetime.time(1, 0))+ datetime.timedelta(hours=8)
|
||||
start_time3 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
|
||||
end_time3 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
|
||||
# 夜班上班区间
|
||||
start_time4 = datetime.datetime.combine(current_data, datetime.time(22, 0))+ datetime.timedelta(hours=8)
|
||||
end_time4 = datetime.datetime.combine(current_data, datetime.time(1, 0))+ datetime.timedelta(hours=8)
|
||||
start_time4 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
|
||||
end_time4 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
|
||||
# 夜班下班区间
|
||||
start_time5 = datetime.datetime.combine(current_data, datetime.time(6, 0))+ datetime.timedelta(hours=8)
|
||||
end_time5 = datetime.datetime.combine(current_data, datetime.time(9, 0))+ datetime.timedelta(hours=8)
|
||||
start_time5 = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
|
||||
end_time5 = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
|
||||
if checkin_time:
|
||||
if start_time<= checkin_time <=end_time and not attendance_obj.check_in and planning_id.template_id.planning_name == '白班':
|
||||
planning_name = planning_id.template_id.planning_name
|
||||
if start_time <= checkin_time <= end_time and planning_name == '白班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif start_time1<= checkin_time <=end_time1 and not attendance_obj.check_out and planning_id.template_id.planning_name == '白班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time> checkin_time,
|
||||
})
|
||||
elif start_time2 <= checkin_time <= end_time2 and not attendance_obj.check_in and planning_id.template_id.planning_name == '中班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif start_time3 <= checkin_time <= end_time3 and not attendance_obj.check_out and planning_id.template_id.planning_name == '中班':
|
||||
elif start_time1 <= checkin_time <= end_time1 and planning_name == '白班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time > checkin_time,
|
||||
})
|
||||
elif start_time4 <= checkin_time <= end_time4 and not attendance_obj.check_in and planning_id.template_id.planning_name == '夜班':
|
||||
elif start_time2 <= checkin_time <= end_time2 and planning_name == '中班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif start_time5 <= checkin_time <= end_time5 and not attendance_obj.check_out and planning_id.template_id.planning_name == '夜班':
|
||||
elif start_time3 <= checkin_time <= end_time3 and planning_name == '中班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time > checkin_time,
|
||||
})
|
||||
elif start_time4 <= checkin_time <= end_time4 and planning_name == '夜班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif start_time5 <= checkin_time <= end_time5 and planning_name == '夜班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time > checkin_time,
|
||||
@@ -389,107 +404,129 @@ class HrAttendanceDetail(models.Model):
|
||||
attendance_obj.sudo().write({"is_abnormal": True})
|
||||
else:
|
||||
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
|
||||
elif planning_id.role_id.name == '工程部':
|
||||
# 白班和白值上班区间
|
||||
start_time = datetime.datetime.combine(current_data, datetime.time(7, 0))+ datetime.timedelta(hours=8)
|
||||
end_time = datetime.datetime.combine(current_data, datetime.time(10, 0))+ datetime.timedelta(hours=8)
|
||||
# 白班和白值下班区间
|
||||
start_time1 = datetime.datetime.combine(current_data, datetime.time(16, 0))+ datetime.timedelta(hours=8)
|
||||
end_time1 = datetime.datetime.combine(current_data, datetime.time(19, 0))+ datetime.timedelta(hours=8)
|
||||
# 白值值班打卡区间
|
||||
start_time2 = datetime.datetime.combine(current_data, datetime.time(11,30))+ datetime.timedelta(hours=8)
|
||||
end_time2 = datetime.datetime.combine(current_data, datetime.time(13, 30))+ datetime.timedelta(hours=8)
|
||||
# 中夜上班区间 中夜下班区间跟白班上班区间一样
|
||||
start_time3 = datetime.datetime.combine(current_data, datetime.time(13, 0))+ datetime.timedelta(hours=8)
|
||||
end_time3 = datetime.datetime.combine(current_data, datetime.time(16, 0))+ datetime.timedelta(hours=8)
|
||||
# 中夜值班打卡区间
|
||||
start_time4 = datetime.datetime.combine(current_data, datetime.time(20, 0))+ datetime.timedelta(hours=8)
|
||||
end_time4 = datetime.datetime.combine(current_data, datetime.time(23, 0))+ datetime.timedelta(hours=8)
|
||||
if planning_id:
|
||||
if checkin_time:
|
||||
if start_time<= checkin_time <=end_time and not attendance_obj.check_in and (planning_id.template_id.planning_name in ['白班','白值']):
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif end_time1<= checkin_time <=start_time1 and not attendance_obj.check_out and (planning_id.template_id.planning_name in ['白班','白值']):
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time > checkin_time,
|
||||
})
|
||||
elif start_time3<= checkin_time <=end_time3 and not attendance_obj.check_in and planning_id.template_id.planning_name == '中夜':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif start_time<= checkin_time <=end_time and not attendance_obj.check_out and planning_id.template_id.planning_name == '中夜':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card":checkin_time > planning_start_time
|
||||
})
|
||||
elif planning_id.template_id.planning == '白值' and start_time2 <= checkin_time <= end_time2:
|
||||
attendance_obj.sudo().write({
|
||||
"sch_check_out_time": sch_checkin_time,
|
||||
"noon_duty": checkin_time,
|
||||
})
|
||||
elif planning_id.template_id.planning == '中夜' and start_time4 <= checkin_time <= end_time4:
|
||||
attendance_obj.sudo().write({
|
||||
"sch_check_out_time": sch_checkin_time,
|
||||
"night_duty": checkin_time,
|
||||
})
|
||||
# 异常情况处理,移到所有打卡逻辑之后
|
||||
if (attendance_obj.is_early_card or attendance_obj.is_late_card or
|
||||
(planning_id.template_id.planning == '白值' and not attendance_obj.noon_duty) or
|
||||
(planning_id.template_id.planning == '中夜' and not attendance_obj.night_duty)):
|
||||
attendance_obj.sudo().write({"is_abnormal": True})
|
||||
else:
|
||||
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
|
||||
elif planning_id.role_id.name == '联安粮储':
|
||||
# 白班上班区间
|
||||
start_time = datetime.datetime.combine(current_data, datetime.time(7, 0))+ datetime.timedelta(hours=8)
|
||||
end_time = datetime.datetime.combine(current_data, datetime.time(10, 0))+ datetime.timedelta(hours=8)
|
||||
# 白班下班区间
|
||||
start_time1 = datetime.datetime.combine(current_data, datetime.time(15, 0))+ datetime.timedelta(hours=8)
|
||||
end_time1 = datetime.datetime.combine(current_data, datetime.time(18, 0))+ datetime.timedelta(hours=8)
|
||||
# 白值上班
|
||||
start_time2 = datetime.datetime.combine(current_data, datetime.time(8,0 ))+ datetime.timedelta(hours=8)
|
||||
end_time2 = datetime.datetime.combine(current_data, datetime.time(10, 0))+ datetime.timedelta(hours=8)
|
||||
# 白值下班
|
||||
start_time4 = datetime.datetime.combine(current_data, datetime.time(4, 0))+ datetime.timedelta(hours=8)
|
||||
end_time4 = datetime.datetime.combine(current_data, datetime.time(7, 0))+ datetime.timedelta(hours=8)
|
||||
# 白值打卡区间、
|
||||
start_time3 = datetime.datetime.combine(current_data, datetime.time(11, 30))+ datetime.timedelta(hours=8)
|
||||
end_time3 = datetime.datetime.combine(current_data, datetime.time(13, 30))+ datetime.timedelta(hours=8)
|
||||
if planning_id:
|
||||
if start_time<= checkin_time <=end_time and not attendance_obj.check_in and planning_id.template_id.planning_name == '白班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time
|
||||
})
|
||||
elif start_time1<= checkin_time <=end_time1 and not attendance_obj.check_out and planning_id.template_id.planning_name == '白班':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time > checkin_time,
|
||||
})
|
||||
elif start_time2<= checkin_time <=end_time2 and not attendance_obj.check_in and planning_id.template_id.planning_name == '白值':
|
||||
attendance_obj.sudo().write({
|
||||
"check_in": checkin_time,
|
||||
"is_late_card": checkin_time > planning_start_time,
|
||||
})
|
||||
elif start_time4<= checkin_time <=end_time4 and not attendance_obj.check_out and planning_id.template_id.planning_name == '白值':
|
||||
attendance_obj.sudo().write({
|
||||
"check_out": checkin_time,
|
||||
"is_early_card": planning_end_time > checkin_time,
|
||||
})
|
||||
elif start_time3<= checkin_time <=end_time3 and planning_id.template_id.planning_name == '白值':
|
||||
attendance_obj.sudo().write({
|
||||
"noon_duty": checkin_time,
|
||||
})
|
||||
if (attendance_obj.is_early_card or attendance_obj.is_late_card or
|
||||
(planning_id.template_id.planning == '白值班' and not attendance_obj.noon_duty)):
|
||||
attendance_obj.sudo().write({"is_abnormal": True})
|
||||
else:
|
||||
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
|
||||
# elif planning_id.role_id.name == '工程部':
|
||||
# # 白班和白值上班区间
|
||||
# start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 白班和白值下班区间
|
||||
# start_time1 = datetime.combine(current_data,
|
||||
# time(16, 0)) + timedelta(hours=8)
|
||||
# end_time1 = datetime.combine(current_data, time(19, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 白值值班打卡区间
|
||||
# start_time2 = datetime.combine(current_data,
|
||||
# time(11, 30)) + timedelta(hours=8)
|
||||
# end_time2 = datetime.combine(current_data, time(13, 30)) + timedelta(
|
||||
# hours=8)
|
||||
# # 中夜上班区间 中夜下班区间跟白班上班区间一样
|
||||
# start_time3 = datetime.combine(current_data,
|
||||
# time(13, 0)) + timedelta(hours=8)
|
||||
# end_time3 = datetime.combine(current_data, time(16, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 中夜值班打卡区间
|
||||
# start_time4 = datetime.combine(current_data,
|
||||
# time(20, 0)) + timedelta(hours=8)
|
||||
# end_time4 = datetime.combine(current_data, time(23, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# if planning_id:
|
||||
# if checkin_time:
|
||||
# if start_time <= checkin_time <= end_time and not attendance_obj.check_in and (
|
||||
# planning_name in ['白班', '白值']):
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_in": checkin_time,
|
||||
# "is_late_card": checkin_time > planning_start_time
|
||||
# })
|
||||
# elif end_time1 <= checkin_time <= start_time1 and not attendance_obj.check_out and (
|
||||
# planning_name in ['白班', '白值']):
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_out": checkin_time,
|
||||
# "is_early_card": planning_end_time > checkin_time,
|
||||
# })
|
||||
# elif start_time3 <= checkin_time <= end_time3 and not attendance_obj.check_in and planning_name == '中夜':
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_in": checkin_time,
|
||||
# "is_late_card": checkin_time > planning_start_time
|
||||
# })
|
||||
# elif start_time <= checkin_time <= end_time and not attendance_obj.check_out and planning_name == '中夜':
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_out": checkin_time,
|
||||
# "is_early_card": checkin_time > planning_start_time
|
||||
# })
|
||||
# elif planning_id.template_id.planning == '白值' and start_time2 <= checkin_time <= end_time2:
|
||||
# attendance_obj.sudo().write({
|
||||
# "sch_check_out_time": sch_checkin_time,
|
||||
# "noon_duty": checkin_time,
|
||||
# })
|
||||
# elif planning_id.template_id.planning == '中夜' and start_time4 <= checkin_time <= end_time4:
|
||||
# attendance_obj.sudo().write({
|
||||
# "sch_check_out_time": sch_checkin_time,
|
||||
# "night_duty": checkin_time,
|
||||
# })
|
||||
# # 异常情况处理,移到所有打卡逻辑之后
|
||||
# if (attendance_obj.is_early_card or attendance_obj.is_late_card or
|
||||
# (planning_id.template_id.planning == '白值' and not attendance_obj.noon_duty) or
|
||||
# (planning_id.template_id.planning == '中夜' and not attendance_obj.night_duty)):
|
||||
# attendance_obj.sudo().write({"is_abnormal": True})
|
||||
# else:
|
||||
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
|
||||
# elif planning_id.role_id.name == '联安粮储':
|
||||
# # 白班上班区间
|
||||
# start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 白班下班区间
|
||||
# start_time1 = datetime.combine(current_data,
|
||||
# time(15, 0)) + timedelta(hours=8)
|
||||
# end_time1 = datetime.combine(current_data, time(18, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 白值上班
|
||||
# start_time2 = datetime.combine(current_data, time(8, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# end_time2 = datetime.combine(current_data, time(10, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 白值下班
|
||||
# start_time4 = datetime.combine(current_data, time(4, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# end_time4 = datetime.combine(current_data, time(7, 0)) + timedelta(
|
||||
# hours=8)
|
||||
# # 白值打卡区间、
|
||||
# start_time3 = datetime.combine(current_data,
|
||||
# time(11, 30)) + timedelta(hours=8)
|
||||
# end_time3 = datetime.combine(current_data, time(13, 30)) + timedelta(
|
||||
# hours=8)
|
||||
# if planning_id:
|
||||
# if start_time <= checkin_time <= end_time and not attendance_obj.check_in and planning_name == '白班':
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_in": checkin_time,
|
||||
# "is_late_card": checkin_time > planning_start_time
|
||||
# })
|
||||
# elif start_time1 <= checkin_time <= end_time1 and not attendance_obj.check_out and planning_name == '白班':
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_out": checkin_time,
|
||||
# "is_early_card": planning_end_time > checkin_time,
|
||||
# })
|
||||
# elif start_time2 <= checkin_time <= end_time2 and not attendance_obj.check_in and planning_name == '白值':
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_in": checkin_time,
|
||||
# "is_late_card": checkin_time > planning_start_time,
|
||||
# })
|
||||
# elif start_time4 <= checkin_time <= end_time4 and not attendance_obj.check_out and planning_name == '白值':
|
||||
# attendance_obj.sudo().write({
|
||||
# "check_out": checkin_time,
|
||||
# "is_early_card": planning_end_time > checkin_time,
|
||||
# })
|
||||
# elif start_time3 <= checkin_time <= end_time3 and planning_name == '白值':
|
||||
# attendance_obj.sudo().write({
|
||||
# "noon_duty": checkin_time,
|
||||
# })
|
||||
# if (attendance_obj.is_early_card or attendance_obj.is_late_card or
|
||||
# (planning_id.template_id.planning == '白值班' and not attendance_obj.noon_duty)):
|
||||
# attendance_obj.sudo().write({"is_abnormal": True})
|
||||
# else:
|
||||
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
|
||||
# 进行关联
|
||||
attendance_detail_obj.hr_attendance_id = attendance_obj.id
|
||||
return True
|
||||
@@ -508,13 +545,17 @@ class HrAttendanceDetail(models.Model):
|
||||
attendance_data = self._get_wx_attendance_data(userid_limit)
|
||||
attendance_result, response = self.sudo().env["wecom.apps"].sync_checkin_data(attendance_data)
|
||||
except Exception as e:
|
||||
_logger.error('获取企业微信的打卡信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit), str(traceback.format_exc())))
|
||||
_logger.error(
|
||||
'获取企业微信的打卡信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit),
|
||||
str(traceback.format_exc())))
|
||||
continue
|
||||
# 检查请求返回的信息是否正确
|
||||
try:
|
||||
checkin_data = self._check_wx_attendance_data(response, userid_limit)
|
||||
except Exception as e:
|
||||
_logger.error('检查请求返回的信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit), str(traceback.format_exc())))
|
||||
_logger.error(
|
||||
'检查请求返回的信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit),
|
||||
str(traceback.format_exc())))
|
||||
continue
|
||||
# 将原始数据存储
|
||||
for data in checkin_data:
|
||||
@@ -522,13 +563,17 @@ class HrAttendanceDetail(models.Model):
|
||||
try:
|
||||
checkin_time, sch_checkin_time = self._check_wx_attendance_time(data, userid_limit)
|
||||
except Exception as e:
|
||||
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
|
||||
_logger.error(
|
||||
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e),
|
||||
str(data),
|
||||
str(traceback.format_exc())))
|
||||
continue
|
||||
# 保存相关的企业微信的原始打卡信息
|
||||
try:
|
||||
self._save_wx_attendance_detail_data(data, checkin_time, sch_checkin_time)
|
||||
except Exception as e:
|
||||
_logger.error('保存相关的企业微信的原始打卡信息失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
|
||||
_logger.error(
|
||||
'保存相关的企业微信的原始打卡信息失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e),
|
||||
str(data),
|
||||
str(traceback.format_exc())))
|
||||
return True
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user