feat: add user management CRUD and platform_user table

V24 migration creates platform_user table. Backend UserAdminController provides list/create/update/toggleStatus. Frontend UserManagementView enables admin to add/edit/disable users. Replaces hardcoded auth with database-backed user lifecycle.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-27 08:37:02 +08:00
parent 118790486a
commit 8c167d4909
5 changed files with 273 additions and 0 deletions
@@ -0,0 +1,58 @@
package cn.craftlabs.platform.api.persistence.auth;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.time.OffsetDateTime;
@TableName("platform_user")
public class PlatformUser {
@TableId
private Long id;
@TableField("username")
private String username;
@TableField("display_name")
private String displayName;
@TableField("password_hash")
private String passwordHash;
@TableField("role")
private String role;
@TableField("status")
private String status;
@TableField("created_at")
private OffsetDateTime createdAt;
@TableField("updated_at")
private OffsetDateTime updatedAt;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}
@@ -0,0 +1,8 @@
package cn.craftlabs.platform.api.persistence.auth;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PlatformUserMapper extends BaseMapper<PlatformUser> {
}
@@ -0,0 +1,27 @@
-- V24__platform_user.sql
-- 用户与账号生命周期(M11-F14),替代 AuthController 中硬编码的 4 个用户
-- BCrypt 哈希由 python3 -c "import bcrypt; print(bcrypt.hashpw(b'admin', bcrypt.gensalt(10)))" 生成
CREATE TABLE IF NOT EXISTS platform_user (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(64) NOT NULL UNIQUE,
display_name VARCHAR(128) NOT NULL DEFAULT '',
password_hash VARCHAR(256) NOT NULL,
role VARCHAR(32) NOT NULL DEFAULT 'SALES',
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
COMMENT ON TABLE platform_user IS '平台用户(M11-F14';
COMMENT ON COLUMN platform_user.username IS '登录名';
COMMENT ON COLUMN platform_user.password_hash IS 'BCrypt 哈希';
COMMENT ON COLUMN platform_user.role IS '角色代码,与 PlatformRoles 一致';
COMMENT ON COLUMN platform_user.status IS 'ACTIVE=正常 DISABLED=禁用 ARCHIVED=归档';
INSERT INTO platform_user (username, display_name, password_hash, role, status) VALUES
('admin', '管理员', '$2b$10$SWAtb2IcPL9C2NOOIl/mFOOVGGxHzgOWAqc6TpsP5TJNvjRQezr4e', 'SYS_ADMIN', 'ACTIVE'),
('sales', '销售账号', '$2b$10$HoUyBcoXb9xe1tsqYPxhc.eNKdWDKK.7KtXIti/pJscBxnkIUrqmK', 'SALES', 'ACTIVE'),
('delivery', '交付账号', '$2b$10$jPoVcLPx3o6TIQmAg3WGXe8.41xr.q.ySDTGgNwwGZ8OiAA5xwoai', 'DELIVERY', 'ACTIVE'),
('ops', '运营账号', '$2b$10$.gQu/dv.m2S9uYuqZc1ymeEiRKa0j4dhWjzEF.e0GApFKmUdIhos6', 'LICENSE_OPS', 'ACTIVE')
ON CONFLICT (username) DO NOTHING;