Odoo 16 活动页面日历集成需求:点击日期查看当日事件
适配Odoo 16的活动页面日历组件实现方案
一、自定义轻量日历组件(最直接可控)
基于Odoo原生的QWeb视图和JavaScript逻辑开发,无需依赖第三方模块:
- 在活动模型(假设为
event.event)的页面视图中添加日历容器和渲染脚本:<!-- 活动页面中插入日历容器 --> <div class="activity-calendar" t-att-data-model="event.event"></div> <!-- 用于展示当日活动的容器 --> <div class="event-list mt-3"></div> <!-- 日历渲染逻辑脚本 --> <script type="text/javascript"> odoo.define('event_calendar.custom_calendar', function (require) { 'use strict'; var rpc = require('web.rpc'); // 生成当月日历HTML function generateCalendarHTML() { const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); const firstDay = new Date(year, month, 1).getDay(); const daysInMonth = new Date(year, month + 1, 0).getDate(); let html = '<div class="calendar-grid">'; // 填充空白日期 for (let i = 0; i < firstDay; i++) { html += '<div class="calendar-day empty"></div>'; } // 填充当月日期 for (let day = 1; day <= daysInMonth; day++) { const dateStr = `${year}-${String(month+1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; html += `<div class="calendar-day" data-date="${dateStr}">${day}</div>`; } html += '</div>'; return html; } // 绑定日期点击事件 function bindCalendarEvents(container, model) { container.addEventListener('click', function(e) { if (e.target.classList.contains('calendar-day') && !e.target.classList.contains('empty')) { const selectedDate = e.target.dataset.date; // 调用RPC获取当日活动 rpc.query({ model: model, method: 'search_read', args: [[['start_date', '=', selectedDate]]], kwargs: {fields: ['name', 'start_date', 'description']} }).then(function(events) { const eventList = document.querySelector('.event-list'); if (events.length === 0) { eventList.innerHTML = '<p>当日无活动</p>'; return; } // 渲染活动列表 eventList.innerHTML = events.map(event => ` <div class="card mb-2"> <div class="card-body"> <h5 class="card-title">${event.name}</h5> <p class="card-text">${event.start_date}</p> <p class="card-text small">${event.description || ''}</p> </div> </div> `).join(''); }); } }); } // 页面加载时初始化日历 document.addEventListener('DOMContentLoaded', function() { const calendarContainer = document.querySelector('.activity-calendar'); if (calendarContainer) { calendarContainer.innerHTML = generateCalendarHTML(); bindCalendarEvents(calendarContainer, calendarContainer.dataset.model); } }); }); </script> - 若活动是跨日期的,可调整RPC搜索条件为
[['|', ['start_date', '<=', selectedDate], ['end_date', '>=', selectedDate]]]
二、改造原生主日历模块实现同步
Odoo 16自带的calendar模块是适配版本,可通过模型关联实现活动与日历的同步:
- 在活动模型中添加关联字段并编写同步逻辑:
from odoo import models, fields, api class EventEvent(models.Model): _inherit = 'event.event' calendar_event_id = fields.Many2one('calendar.event', string='关联日历事件') @api.model def create(self, vals): res = super().create(vals) if res.start_date: calendar_vals = { 'name': res.name, 'start': res.start_date, 'stop': res.end_date or res.start_date, 'description': res.description, 'res_id': res.id, 'res_model': 'event.event' } calendar_event = self.env['calendar.event'].create(calendar_vals) res.calendar_event_id = calendar_event.id return res def write(self, vals): res = super().write(vals) for rec in self: if not rec.calendar_event_id and vals.get('start_date'): # 首次创建关联日历事件 calendar_vals = { 'name': vals.get('name') or rec.name, 'start': vals['start_date'], 'stop': vals.get('end_date') or vals['start_date'], 'description': vals.get('description') or rec.description, 'res_id': rec.id, 'res_model': 'event.event' } calendar_event = self.env['calendar.event'].create(calendar_vals) rec.calendar_event_id = calendar_event.id elif rec.calendar_event_id: # 更新已关联的日历事件 update_vals = {} if 'name' in vals: update_vals['name'] = vals['name'] if 'start_date' in vals: update_vals['start'] = vals['start_date'] if 'end_date' in vals: update_vals['stop'] = vals['end_date'] if 'description' in vals: update_vals['description'] = vals['description'] if update_vals: rec.calendar_event_id.write(update_vals) return res - 在活动页面添加按钮,直接打开关联的日历视图,或嵌入日历片段并过滤出当前活动相关的日历事件
三、快速替代方案:日期筛选器+活动列表
若不想开发,可通过配置视图快速实现核心需求:
- 在活动模型的搜索视图中添加日期筛选字段:
<search> <field name="start_date" widget="date" string="选择日期"/> <group expand="0" string="分组"> <filter name="by_date" string="按日期分组" context="{'group_by': 'start_date'}"/> </group> </search> - 用户选择日期后,列表自动过滤显示当日活动,虽无日历点击交互,但能满足查看当日活动的核心需求
内容的提问来源于stack exchange,提问作者Headie
相关产品推荐
相关产品推荐

