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

如何配置Redmine限制用户仅可记录过去3天的工时?

当然可以实现!针对你提到的Redmine限制用户仅能记录过去3天(含当天)工时的需求,我整理了几个实用的方案,你可以根据自己的技术能力和部署场景选择:

1. 插件方案(最省心的选择)

Redmine社区有不少专注于工时管理的插件,部分支持自定义日期范围限制。比如你可以找找类似redmine_time_limit这类插件(如果找不到完全匹配的,也可以基于Redmine的插件开发框架自行简单定制)。

这类插件的优势是:

  • 自带前端验证:用户选择超出3天的日期时,会直接弹出友好提示,阻止提交
  • 后端兜底校验:防止有人绕过前端限制提交不符合要求的记录
  • 配置简单:下载插件放到Redmine的plugins目录,执行bundle install和数据库迁移命令后,在Redmine后台设置里就能配置允许的日期范围(设为过去3天即可)

2. 数据库触发器方案(无需修改Redmine代码)

如果不想折腾插件,直接在数据库层面加触发器是个简单粗暴但有效的办法。以MySQL为例,Redmine的工时记录存在time_entries表,其中spent_on字段是工时对应的日期,我们可以创建两个触发器来拦截不符合要求的操作:

-- 拦截新增不符合日期要求的工时记录
DELIMITER //
CREATE TRIGGER check_time_entry_insert BEFORE INSERT ON time_entries
FOR EACH ROW
BEGIN
  IF NEW.spent_on < DATE_SUB(CURDATE(), INTERVAL 3 DAY) THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '仅允许记录过去3天(含当天)的工时';
  END IF;
END //
DELIMITER ;

-- 拦截修改为不符合日期要求的工时记录
DELIMITER //
CREATE TRIGGER check_time_entry_update BEFORE UPDATE ON time_entries
FOR EACH ROW
BEGIN
  IF NEW.spent_on < DATE_SUB(CURDATE(), INTERVAL 3 DAY) THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '仅允许记录过去3天(含当天)的工时';
  END IF;
END //
DELIMITER ;

这个方案的好处是不需要修改Redmine的任何代码,不管用户通过前端还是API提交,数据库都会直接拒绝。唯一的小缺点是用户在前端不会得到友好提示,只会看到数据库报错,所以如果追求更好的体验,可以配合一点点前端的提示代码。

3. 自定义代码方案(最灵活,体验最佳)

如果你有一定的Ruby开发能力,直接修改Redmine代码可以实现最友好的限制效果:

前端校验

在工时录入页面的模板文件(比如app/views/time_entries/_form.html.erb)中添加一段JavaScript,监听日期选择框的变化:

document.getElementById('time_entry_spent_on').addEventListener('change', function() {
  const selectedDate = new Date(this.value);
  const threeDaysAgo = new Date();
  threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
  // 只保留日期部分比较,忽略时间
  const selectedDateOnly = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), selectedDate.getDate());
  const threeDaysAgoOnly = new Date(threeDaysAgo.getFullYear(), threeDaysAgo.getMonth(), threeDaysAgo.getDate());
  
  const submitBtn = document.querySelector('input[type="submit"]');
  const errorMsg = document.createElement('div');
  errorMsg.className = 'error';
  errorMsg.textContent = '仅允许记录过去3天(含当天)的工时';
  
  if (selectedDateOnly < threeDaysAgoOnly) {
    submitBtn.disabled = true;
    // 移除已存在的提示,避免重复添加
    const existingError = document.querySelector('.error');
    if (existingError) existingError.remove();
    this.parentNode.appendChild(errorMsg);
  } else {
    submitBtn.disabled = false;
    const existingError = document.querySelector('.error');
    if (existingError) existingError.remove();
  }
});

后端校验

在app/models/time_entry.rb中添加自定义校验规则,作为前端校验的兜底:

validate :validate_spent_on_date_range

private

def validate_spent_on_date_range
  if spent_on.present? && spent_on < 3.days.ago.to_date
    errors.add(:spent_on, "仅允许记录过去3天(含当天)的工时")
  end
end

这种方案的优势是用户能在前端得到即时的友好提示,后端也有严格的校验,体验最好,但需要维护自定义代码,Redmine版本升级时要注意兼容性。

以上三种方案各有优劣,你可以根据自己的实际情况来选择~

内容的提问来源于stack exchange,提问作者Darshan Faldu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:19:39