You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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模块是适配版本,可通过模型关联实现活动与日历的同步:

  1. 在活动模型中添加关联字段并编写同步逻辑:
    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
    
  2. 在活动页面添加按钮,直接打开关联的日历视图,或嵌入日历片段并过滤出当前活动相关的日历事件

三、快速替代方案:日期筛选器+活动列表

若不想开发,可通过配置视图快速实现核心需求:

  • 在活动模型的搜索视图中添加日期筛选字段:
    <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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 01:36:02