yeg
2026-09-09 7100c8a4f7dd3fc7d53ffead4475d7a8abc51c12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.battery.business.service;
 
import java.sql.Timestamp;
import java.sql.Statement;
import java.util.List;
import javax.sql.DataSource;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
/** 独立待办持久化,负责人限制始终使用登录用户 ID,不依赖姓名或管理员身份。 */
@Service
public class TodoService {
    private final JdbcTemplate jdbc;
    public TodoService(DataSource source) { jdbc = new JdbcTemplate(source); }
    public record Todo(long id, String content, long ownerId, String owner, String status,
            String creator, long createdAt, long operatedAt, String handleRemark) {}
    public record UserOption(long id, String name) {}
    private static final String COLUMNS = "select todo_id,content,owner_id,owner_name,status,creator_name,created_at_utc,operated_at_utc,handle_remark from t_todo";
    private static final RowMapper<Todo> ROW = (rs, index) -> new Todo(rs.getLong(1), rs.getString(2), rs.getLong(3), rs.getString(4),
            rs.getString(5), rs.getString(6), rs.getTimestamp(7).getTime(), rs.getTimestamp(8).getTime(), rs.getString(9));
 
    /** 返回当前负责人自己的全部待办;包括已处理项,不向创建人或管理员额外开放。 */
    public List<Todo> list(long ownerId) {
        return jdbc.query(COLUMNS + " where owner_id=? order by operated_at_utc desc,todo_id desc", ROW, ownerId);
    }
 
    /** 供新增表单选择启用用户,不要求用户管理模块权限。 */
    public List<UserOption> owners() {
        return jdbc.query("select user_id,coalesce(nullif(nick_name,''),user_name) from sys_user where status='0' and del_flag='0' order by user_id",
                (rs, index) -> new UserOption(rs.getLong(1), rs.getString(2)));
    }
 
    /** 新增后仅返回确认主键,分配给别人时不把该待办回传给非负责人。 */
    @Transactional
    public long create(String content, long ownerId, long creatorId, String creator) {
        String value = required(content, 200, "待办内容");
        var owner = owners().stream().filter(user -> user.id() == ownerId).findFirst()
                .orElseThrow(() -> new ServiceException("请选择启用的负责人"));
        var now = new Timestamp(System.currentTimeMillis());
        var key = new GeneratedKeyHolder();
        // 主键从本次 INSERT 的 JDBC 结果取得,不跨连接使用会话相关的 last_insert_id。
        jdbc.update(connection -> {
            var statement = connection.prepareStatement("insert into t_todo(content,owner_id,owner_name,creator_id,creator_name,status,created_at_utc,operated_at_utc,handle_remark) values(?,?,?,?,?,'待处理',?,?,'')", Statement.RETURN_GENERATED_KEYS);
            statement.setString(1, value); statement.setLong(2, owner.id()); statement.setString(3, owner.name());
            statement.setLong(4, creatorId); statement.setString(5, creator); statement.setTimestamp(6, now); statement.setTimestamp(7, now);
            return statement;
        }, key);
        return key.getKey().longValue();
    }
 
    /** 负责人只能将自己的待处理事项完成一次;写入条件同时校验身份和当前状态。 */
    public void handle(long id, long ownerId, String remark) {
        String value = required(remark, 500, "处理说明");
        if (jdbc.update("update t_todo set status='已处理',handle_remark=?,operated_at_utc=? where todo_id=? and owner_id=? and status='待处理'",
                value, new Timestamp(System.currentTimeMillis()), id, ownerId) != 1)
            throw new ServiceException("待办不存在、已处理或无权处理");
    }
 
    /** 按现有删除交互物理删除自己的待办,不涉及测试或异常事实。 */
    public void remove(long id, long ownerId) {
        if (jdbc.update("delete from t_todo where todo_id=? and owner_id=?", id, ownerId) != 1)
            throw new ServiceException("待办不存在或无权删除");
    }
 
    private String required(String text, int max, String name) {
        if (text == null || text.trim().isEmpty() || text.trim().length() > max)
            throw new ServiceException(name + "不能为空且长度不能超过" + max);
        return text.trim();
    }
}