chore: initial commit
This commit is contained in:
48
internal/db/db.go
Normal file
48
internal/db/db.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"server/internal/config"
|
||||
"server/internal/db/sqlc"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
func NewDB(lc fx.Lifecycle, cfg *config.Config) (*pgxpool.Pool, error) {
|
||||
ctx := context.Background()
|
||||
dbConfig := cfg.Database
|
||||
|
||||
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
||||
dbConfig.Host, dbConfig.Port, dbConfig.User, dbConfig.Password, dbConfig.DBName, dbConfig.SSLMode)
|
||||
|
||||
// 创建连接池
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 注册fx生命周期钩子
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
return nil
|
||||
},
|
||||
OnStop: func(ctx context.Context) error {
|
||||
pool.Close()
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
// 测试连接
|
||||
if err = pool.Ping(ctx); err != nil {
|
||||
pool.Close()
|
||||
return nil, fmt.Errorf("failed to ping database: %w", err)
|
||||
}
|
||||
|
||||
return pool, nil
|
||||
}
|
||||
|
||||
func NewQueries(pool *pgxpool.Pool) *db.Queries {
|
||||
return db.New(pool)
|
||||
}
|
||||
32
internal/db/migrations/000001_init.down.sql
Normal file
32
internal/db/migrations/000001_init.down.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
-- migrate/down.sql
|
||||
-- 此文件用于撤销 up.sql 文件的所有操作
|
||||
-- 注意:执行此脚本将会永久删除相关表和数据!
|
||||
|
||||
-- 移除表上的触发器
|
||||
-- 必须在删除表和函数之前移除依赖它们的触发器
|
||||
DROP TRIGGER IF EXISTS update_sys_users_updated_at ON sys_users;
|
||||
DROP TRIGGER IF EXISTS update_sys_roles_updated_at ON sys_roles;
|
||||
DROP TRIGGER IF EXISTS update_sys_menus_updated_at ON sys_menus;
|
||||
DROP TRIGGER IF EXISTS update_sys_permissions_updated_at ON sys_permissions;
|
||||
DROP TRIGGER IF EXISTS update_sys_apis_updated_at ON sys_apis;
|
||||
DROP TRIGGER IF EXISTS update_files_updated_at ON files;
|
||||
|
||||
-- 删除索引
|
||||
DROP INDEX IF EXISTS idx_sys_users_account;
|
||||
|
||||
-- 移除表
|
||||
-- 按照与创建相反的顺序删除,先删除依赖其他表的表
|
||||
DROP TABLE IF EXISTS sys_api_permission;
|
||||
DROP TABLE IF EXISTS sys_apis;
|
||||
DROP TABLE IF EXISTS sys_menu_permission;
|
||||
DROP TABLE IF EXISTS sys_role_permission;
|
||||
DROP TABLE IF EXISTS sys_user_role;
|
||||
DROP TABLE IF EXISTS sys_permissions;
|
||||
DROP TABLE IF EXISTS sys_menus;
|
||||
DROP TABLE IF EXISTS sys_roles;
|
||||
DROP TABLE IF EXISTS sys_users;
|
||||
DROP TABLE IF EXISTS files;
|
||||
|
||||
-- 移除触发器函数
|
||||
-- 在所有使用此函数的触发器都被移除后,可以安全地删除此函数
|
||||
DROP FUNCTION IF EXISTS update_updated_at_column;
|
||||
221
internal/db/migrations/000001_init.up.sql
Normal file
221
internal/db/migrations/000001_init.up.sql
Normal file
@@ -0,0 +1,221 @@
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
-- function
|
||||
CREATE
|
||||
OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS
|
||||
$$
|
||||
BEGIN
|
||||
NEW.updated_at
|
||||
:= NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$
|
||||
language 'plpgsql';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_users
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
account TEXT NOT NULL UNIQUE,
|
||||
username TEXT NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
avatar_id INTEGER,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sys_users_account ON sys_users (account);
|
||||
|
||||
CREATE TRIGGER update_sys_users_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_users
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
|
||||
COMMENT ON COLUMN sys_users.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_users.account IS '用户账号';
|
||||
COMMENT ON COLUMN sys_users.username IS '用户名称';
|
||||
COMMENT ON COLUMN sys_users.password_hash IS 'hash密码';
|
||||
COMMENT ON COLUMN sys_users.avatar_id IS '头像文件id';
|
||||
COMMENT ON COLUMN sys_users.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_users.updated_at IS '更新时间';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_roles
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
code TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_sys_roles_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_roles
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_roles.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_roles.name IS '角色名称';
|
||||
COMMENT ON COLUMN sys_roles.code IS '角色编码,唯一';
|
||||
COMMENT ON COLUMN sys_roles.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_roles.updated_at IS '更新时间';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_permissions
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
code TEXT UNIQUE,
|
||||
type SMALLINT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT unique_type_code UNIQUE (type, code)
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_sys_permissions_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_permissions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_permissions.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_permissions.code IS '权限字符,唯一';
|
||||
COMMENT ON COLUMN sys_permissions.code IS '权限类型,0: 菜单 1: api';
|
||||
COMMENT ON COLUMN sys_permissions.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_permissions.updated_at IS '更新时间';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_menus
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
component TEXT,
|
||||
type SMALLINT NOT NULL,
|
||||
hidden BOOLEAN DEFAULT FALSE,
|
||||
sort INTEGER DEFAULT 0,
|
||||
status SMALLINT NOT NULL DEFAULT 1,
|
||||
parent_id INTEGER,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
CHECK (type IN (0, 1, 2)),
|
||||
CHECK (status IN (0, 1))
|
||||
);
|
||||
|
||||
|
||||
CREATE TRIGGER update_sys_menus_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_menus
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_menus.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_menus.name IS '菜单名称';
|
||||
COMMENT ON COLUMN sys_menus.path IS '菜单路径';
|
||||
COMMENT ON COLUMN sys_menus.component IS '组件路径';
|
||||
COMMENT ON COLUMN sys_menus.type IS '菜单类型 0: 目录 1: 菜单 2: button';
|
||||
COMMENT ON COLUMN sys_menus.sort IS '菜单排序';
|
||||
COMMENT ON COLUMN sys_menus.hidden IS '是否隐藏菜单';
|
||||
COMMENT ON COLUMN sys_menus.status IS '菜单状态 1: 启用 0: 禁用';
|
||||
COMMENT ON COLUMN sys_menus.parent_id IS '父级id';
|
||||
COMMENT ON COLUMN sys_menus.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_menus.updated_at IS '更新时间';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_apis
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
group_name TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
method TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
sort INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
UNIQUE (method, path)
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_sys_apis_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_apis
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_apis.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_apis.group_name IS '分组名称';
|
||||
COMMENT ON COLUMN sys_apis.name IS '接口名称';
|
||||
COMMENT ON COLUMN sys_apis.method IS 'api方法';
|
||||
COMMENT ON COLUMN sys_apis.path IS 'api路径';
|
||||
COMMENT ON COLUMN sys_apis.sort IS '排序';
|
||||
COMMENT ON COLUMN sys_apis.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_apis.updated_at IS '更新时间';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE files
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
file_name TEXT NOT NULL,
|
||||
file_path TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
folder_name TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL,
|
||||
file_size BIGINT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_files_updated_at
|
||||
BEFORE UPDATE
|
||||
ON files
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN files.id IS '主键ID';
|
||||
COMMENT ON COLUMN files.file_name IS '文件名 xxx.jpg';
|
||||
COMMENT ON COLUMN files.file_path IS '文件路径 带path /xxx/xxx.jpg';
|
||||
COMMENT ON COLUMN files.original_name IS '原始文件名';
|
||||
COMMENT ON COLUMN files.folder_name IS '文件夹名称';
|
||||
COMMENT ON COLUMN files.mime_type IS 'mime_type';
|
||||
COMMENT ON COLUMN files.file_size IS '文件大小';
|
||||
COMMENT ON COLUMN files.created_at IS '上传时间';
|
||||
COMMENT ON COLUMN files.updated_at IS '修改时间';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_user_role
|
||||
(
|
||||
user_id INTEGER NOT NULL,
|
||||
role_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (user_id, role_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_user_role.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN sys_user_role.role_id IS '角色ID';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_role_permission
|
||||
(
|
||||
role_id INTEGER NOT NULL,
|
||||
permission_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (role_id, permission_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_role_permission.role_id IS '角色id';
|
||||
COMMENT ON COLUMN sys_role_permission.permission_id IS '权限id';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_menu_permission
|
||||
(
|
||||
menu_id INTEGER NOT NULL,
|
||||
permission_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (menu_id, permission_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_menu_permission.menu_id IS '菜单id';
|
||||
COMMENT ON COLUMN sys_menu_permission.permission_id IS '权限id';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
CREATE TABLE sys_api_permission
|
||||
(
|
||||
api_id INTEGER NOT NULL,
|
||||
permission_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (api_id, permission_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_api_permission.api_id IS 'api ID';
|
||||
COMMENT ON COLUMN sys_api_permission.permission_id IS '权限id';
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
0
internal/db/migrations/000002_seed.down.sql
Normal file
0
internal/db/migrations/000002_seed.down.sql
Normal file
83
internal/db/migrations/000002_seed.up.sql
Normal file
83
internal/db/migrations/000002_seed.up.sql
Normal file
@@ -0,0 +1,83 @@
|
||||
-- 创建用户
|
||||
INSERT INTO sys_users (account, username, password_hash, avatar_id, created_at)
|
||||
VALUES ('admin', '管理员', '$2a$10$d/xYJVUFTmpSVUaV3uawZ.7hj6FanbooMJ9YjsFOmQKNopWc6oR9i', NULL,
|
||||
'2025-10-18 03:05:54.692714');
|
||||
|
||||
-- 批量插入菜单及关联权限
|
||||
WITH input(name, path, component, type, sort, status, code)
|
||||
AS (VALUES ('首页', '/', '/system/home/index', 1, 0, 1, 'home'),
|
||||
('用户管理', '/user', '/system/user/index', 1, 1, 1, 'user'),
|
||||
('角色管理', '/role', '/system/role/index', 1, 2, 1, 'role'),
|
||||
('菜单管理', '/menu', '/system/menu/index', 1, 3, 1, 'menu'),
|
||||
('接口管理', '/sys_api', '/system/api/index', 1, 4, 1, 'api'),
|
||||
('文件管理', '/file', '/system/file/index', 1, 5, 1, 'file')),
|
||||
-- 插入菜单
|
||||
inserted_menus AS (
|
||||
INSERT INTO sys_menus (name, path, component, type, sort, status)
|
||||
SELECT name, path, component, type, sort, status FROM input RETURNING id),
|
||||
menu_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn FROM inserted_menus),
|
||||
-- 插入权限
|
||||
inserted_permissions AS (
|
||||
INSERT INTO sys_permissions (type, code)
|
||||
SELECT 0, code FROM input RETURNING id),
|
||||
permission_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn FROM inserted_permissions)
|
||||
-- 关联权限
|
||||
INSERT
|
||||
INTO sys_menu_permission(menu_id, permission_id)
|
||||
SELECT m.id, p.id
|
||||
FROM menu_rows m
|
||||
JOIN permission_rows p ON m.rn = p.rn;
|
||||
|
||||
-- 批量插入接口及关联权限
|
||||
WITH inserted_apis AS (
|
||||
-- 插入菜单
|
||||
INSERT INTO sys_apis (group_name, name, method, path)
|
||||
VALUES ('用户管理', '用户列表', 'GET', '/admin/user'),
|
||||
('用户管理', '用户信息', 'GET', '/admin/user/info'),
|
||||
('用户管理', '查询用户', 'GET', '/admin/user/{id}'),
|
||||
('用户管理', '用户角色', 'GET', '/admin/user/{id}/roles'),
|
||||
('用户管理', '创建用户', 'POST', '/admin/user'),
|
||||
('用户管理', '修改用户', 'PATCH', '/admin/user/{id}'),
|
||||
('用户管理', '删除用户', 'DELETE', '/admin/user/{id}'),
|
||||
('用户管理', '分配用户角色', 'PUT', '/admin/user/{id}/roles'),
|
||||
('用户管理', '修改密码', 'PATCH', '/admin/user/{id}/password'),
|
||||
--
|
||||
('角色管理', '角色列表', 'GET', '/admin/role'),
|
||||
('角色管理', '创建角色', 'POST', '/admin/role'),
|
||||
('角色管理', '所有角色', 'GET', '/admin/role/all'),
|
||||
('角色管理', '单个角色', 'GET', '/admin/role/{id}'),
|
||||
('角色管理', '角色菜单', 'GET', '/admin/role/{id}/menus'),
|
||||
('角色管理', '角色接口', 'GET', '/admin/role/{id}/apis'),
|
||||
('角色管理', '修改角色', 'PATCH', '/admin/role/{id}'),
|
||||
('角色管理', '删除角色', 'DELETE', '/admin/role/{id}'),
|
||||
('角色管理', '分配角色菜单', 'PUT', '/admin/role/{id}/menus'),
|
||||
('角色管理', '分配角色接口', 'PUT', '/admin/role/{id}/apis'),
|
||||
--
|
||||
('接口管理', '接口列表', 'GET', '/admin/api'),
|
||||
('接口管理', '所有接口', 'GET', '/admin/api/all'),
|
||||
('接口管理', '接口分组', 'GET', '/admin/api/group_names'),
|
||||
('接口管理', '创建接口', 'POST', '/admin/api'),
|
||||
('接口管理', '修改接口', 'PATCH', '/admin/api/{id}'),
|
||||
('接口管理', '删除接口', 'DELETE', '/admin/api/{id}'),
|
||||
--
|
||||
('菜单管理', '菜单列表', 'GET', '/admin/menu'),
|
||||
('菜单管理', '创建菜单', 'POST', '/admin/menu'),
|
||||
('菜单管理', '所有菜单', 'GET', '/admin/menu/all'),
|
||||
('菜单管理', '修改菜单', 'PATCH', '/admin/menu/{id}'),
|
||||
('菜单管理', '删除菜单', 'DELETE', '/admin/menu/{id}'),
|
||||
--
|
||||
('文件管理', '文件列表', 'GET', '/admin/file'),
|
||||
('文件管理', '上传文件', 'POST', '/admin/file') RETURNING id),
|
||||
api_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn
|
||||
FROM inserted_apis),
|
||||
-- 创建权限
|
||||
inserted_permissions AS (
|
||||
INSERT INTO sys_permissions (type)
|
||||
SELECT 1 FROM api_rows RETURNING id),
|
||||
permission_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn
|
||||
FROM inserted_permissions)
|
||||
INSERT
|
||||
INTO sys_api_permission(api_id, permission_id)
|
||||
SELECT a.id, b.id
|
||||
FROM api_rows a
|
||||
INNER JOIN permission_rows b ON a.rn = b.rn;
|
||||
19
internal/db/migrations/000003_add_posts.down.sql
Normal file
19
internal/db/migrations/000003_add_posts.down.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
DELETE FROM sys_api_permission
|
||||
WHERE api_id IN (SELECT id FROM sys_apis WHERE group_name = '文章管理');
|
||||
|
||||
DELETE FROM sys_permissions
|
||||
WHERE id IN (
|
||||
SELECT permission_id FROM sys_api_permission
|
||||
WHERE api_id IN (SELECT id FROM sys_apis WHERE group_name = '文章管理')
|
||||
);
|
||||
|
||||
DELETE FROM sys_apis WHERE group_name = '文章管理';
|
||||
|
||||
DELETE FROM sys_menu_permission
|
||||
WHERE menu_id IN (SELECT id FROM sys_menus WHERE path = '/post');
|
||||
|
||||
DELETE FROM sys_permissions WHERE code = 'post' AND type = 1;
|
||||
|
||||
DELETE FROM sys_menus WHERE path = '/post';
|
||||
|
||||
DROP TABLE IF EXISTS posts;
|
||||
82
internal/db/migrations/000003_add_posts.up.sql
Normal file
82
internal/db/migrations/000003_add_posts.up.sql
Normal file
@@ -0,0 +1,82 @@
|
||||
CREATE TABLE posts
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
title TEXT NOT NULL,
|
||||
cover_id INTEGER,
|
||||
slug TEXT UNIQUE NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
summary TEXT NOT NULL,
|
||||
status SMALLINT NOT NULL DEFAULT 1,
|
||||
view INTEGER DEFAULT 0,
|
||||
sort INTEGER DEFAULT 0,
|
||||
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
CHECK (status IN (0, 1, 2))
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_posts_updated_at
|
||||
BEFORE UPDATE
|
||||
ON posts
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
|
||||
COMMENT ON COLUMN posts.id IS '主键ID';
|
||||
COMMENT ON COLUMN posts.title IS '文章标题';
|
||||
COMMENT ON COLUMN posts.cover_id IS '文章封面图片id';
|
||||
COMMENT ON COLUMN posts.slug IS 'URL友好地址';
|
||||
COMMENT ON COLUMN posts.content IS '文章正文';
|
||||
COMMENT ON COLUMN posts.summary IS '摘要';
|
||||
COMMENT ON COLUMN posts.status IS '状态 0:草稿 1:已发布 2:已下线';
|
||||
COMMENT ON COLUMN posts.view IS '阅读量';
|
||||
COMMENT ON COLUMN posts.sort IS '文章排序';
|
||||
COMMENT ON COLUMN posts.published_at IS '发布时间';
|
||||
COMMENT ON COLUMN posts.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN posts.updated_at IS '修改时间';
|
||||
|
||||
-- 批量插入菜单及关联权限
|
||||
WITH input(name, path, component, type, sort, status, code)
|
||||
AS (VALUES ('文章管理', '/post', '/blog/post/index', 1, 6, 1, 'post'),
|
||||
('文章编辑', '/post/edit', '/blog/post-edit/index', 1, 7, 1, 'post:edit')
|
||||
),
|
||||
-- 插入菜单
|
||||
inserted_menus AS (
|
||||
INSERT INTO sys_menus (name, path, component, type, sort, status)
|
||||
SELECT name, path, component, type, sort, status FROM input RETURNING id),
|
||||
menu_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn FROM inserted_menus),
|
||||
-- 插入权限
|
||||
inserted_permissions AS (
|
||||
INSERT INTO sys_permissions (type, code)
|
||||
SELECT 0, code FROM input RETURNING id),
|
||||
permission_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn FROM inserted_permissions)
|
||||
-- 关联权限
|
||||
INSERT
|
||||
INTO sys_menu_permission(menu_id, permission_id)
|
||||
SELECT m.id, p.id
|
||||
FROM menu_rows m
|
||||
JOIN permission_rows p ON m.rn = p.rn;
|
||||
|
||||
-- 批量插入接口及关联权限
|
||||
WITH inserted_apis AS (
|
||||
-- 插入菜单
|
||||
INSERT INTO sys_apis (group_name, name, method, path)
|
||||
VALUES ('文章管理', '文章列表', 'GET', '/admin/post'),
|
||||
('文章管理', '创建文章', 'POST', '/admin/post'),
|
||||
('文章管理', '修改文章', 'PATCH', '/admin/post/{id}'),
|
||||
('文章管理', '删除文章', 'DELETE', '/admin/post/{id}')
|
||||
RETURNING id),
|
||||
api_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn
|
||||
FROM inserted_apis),
|
||||
-- 创建权限
|
||||
inserted_permissions AS (
|
||||
INSERT INTO sys_permissions (type)
|
||||
SELECT 1 FROM api_rows RETURNING id),
|
||||
permission_rows AS (SELECT id, ROW_NUMBER() OVER () AS rn
|
||||
FROM inserted_permissions)
|
||||
INSERT
|
||||
INTO sys_api_permission(api_id, permission_id)
|
||||
SELECT a.id, b.id
|
||||
FROM api_rows a
|
||||
INNER JOIN permission_rows b ON a.rn = b.rn;
|
||||
2
internal/db/migrations/000004_add_categories.down.sql
Normal file
2
internal/db/migrations/000004_add_categories.down.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
DROP TABLE IF EXISTS categories;
|
||||
DROP TABLE IF EXISTS post_category;
|
||||
30
internal/db/migrations/000004_add_categories.up.sql
Normal file
30
internal/db/migrations/000004_add_categories.up.sql
Normal file
@@ -0,0 +1,30 @@
|
||||
-- 分类表
|
||||
CREATE TABLE categories
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_categories_updated_at
|
||||
BEFORE UPDATE
|
||||
ON categories
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN categories.id IS '分类ID';
|
||||
COMMENT ON COLUMN categories.name IS '分类名称';
|
||||
COMMENT ON COLUMN categories.code IS '分类编码';
|
||||
|
||||
-- 关联表
|
||||
CREATE TABLE post_category
|
||||
(
|
||||
post_id INT NOT NULL,
|
||||
category_id INT NOT NULL,
|
||||
PRIMARY KEY (post_id, category_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN post_category.post_id IS '文章ID';
|
||||
COMMENT ON COLUMN post_category.category_id IS '分类ID';
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS post_stats;
|
||||
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE post_stats
|
||||
(
|
||||
post_id INTEGER PRIMARY KEY,
|
||||
view INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN post_stats.post_id IS '文章id';
|
||||
COMMENT ON COLUMN post_stats.view IS '文章阅读量';
|
||||
|
||||
-- 删除view字段
|
||||
ALTER TABLE posts
|
||||
DROP COLUMN IF EXISTS view;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE sys_menus
|
||||
DROP COLUMN IF EXISTS icon;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE sys_menus
|
||||
ADD COLUMN IF NOT EXISTS icon INTEGER;
|
||||
1
internal/db/migrations/000007_add_post_viewers.down.sql
Normal file
1
internal/db/migrations/000007_add_post_viewers.down.sql
Normal file
@@ -0,0 +1 @@
|
||||
DROP TABLE IF EXISTS post_viewers;
|
||||
12
internal/db/migrations/000007_add_post_viewers.up.sql
Normal file
12
internal/db/migrations/000007_add_post_viewers.up.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE post_viewers
|
||||
(
|
||||
post_id INTEGER NOT NULL,
|
||||
ip INET NOT NULL,
|
||||
last_viewed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY(post_id, ip)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN post_viewers.post_id IS '文章id';
|
||||
COMMENT ON COLUMN post_viewers.ip IS '访问ip';
|
||||
COMMENT ON COLUMN post_viewers.last_viewed_at IS '最后访问时间';
|
||||
42
internal/db/query/category.sql
Normal file
42
internal/db/query/category.sql
Normal file
@@ -0,0 +1,42 @@
|
||||
-- name: CreateCategory :exec
|
||||
INSERT INTO categories(name, code)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: ListCategories :many
|
||||
SELECT *
|
||||
FROM categories
|
||||
ORDER BY id LIMIT $1
|
||||
OFFSET $2;
|
||||
|
||||
-- name: CountCategories :one
|
||||
SELECT COUNT(*)
|
||||
FROM categories;
|
||||
|
||||
-- name: ListAllCategories :many
|
||||
SELECT *
|
||||
FROM categories;
|
||||
|
||||
-- name: GetCategoryById :one
|
||||
SELECT *
|
||||
FROM categories
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: UpdateCategory :execrows
|
||||
UPDATE categories
|
||||
SET name = coalesce(sqlc.narg('name'), name),
|
||||
code = coalesce(sqlc.narg('code'), code)
|
||||
WHERE id = sqlc.arg('id');
|
||||
|
||||
-- name: DeleteCategory :execrows
|
||||
DELETE
|
||||
FROM categories
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: CreatePostCategory :exec
|
||||
INSERT INTO post_category(post_id, category_id)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: DeletePostCategory :exec
|
||||
DELETE
|
||||
FROM post_category
|
||||
WHERE post_id = $1;
|
||||
13
internal/db/query/file.sql
Normal file
13
internal/db/query/file.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
-- name: CreateFile :one
|
||||
INSERT INTO files(file_name, file_path, original_name, folder_name, mime_type, file_size)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING id,file_path,file_name;
|
||||
|
||||
-- name: GetFiles :many
|
||||
SELECT *
|
||||
FROM files
|
||||
ORDER BY id LIMIT $1
|
||||
OFFSET $2;
|
||||
|
||||
-- name: CountFiles :one
|
||||
SELECT COUNT(*)
|
||||
FROM files;
|
||||
145
internal/db/query/post.sql
Normal file
145
internal/db/query/post.sql
Normal file
@@ -0,0 +1,145 @@
|
||||
-- name: CreatePost :one
|
||||
INSERT INTO posts(title, cover_id, slug, content, summary, status, sort, published_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id;
|
||||
|
||||
-- name: ListPosts :many
|
||||
WITH paginated_posts AS (
|
||||
-- 第一步:先精准查出当前页需要的文章 ID
|
||||
SELECT id,
|
||||
title,
|
||||
cover_id,
|
||||
slug,
|
||||
summary,
|
||||
status,
|
||||
sort,
|
||||
published_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM posts
|
||||
ORDER BY sort DESC, published_at DESC, id DESC
|
||||
LIMIT $1 OFFSET $2)
|
||||
-- 第二步:用这极少量的记录去进行 JOIN
|
||||
SELECT p.*,
|
||||
f.file_path AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
FROM paginated_posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC;
|
||||
|
||||
-- name: CountPosts :one
|
||||
SELECT COUNT(*)
|
||||
FROM posts;
|
||||
|
||||
-- name: GetPostById :one
|
||||
SELECT p.*,
|
||||
f.file_path AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id
|
||||
FROM posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
WHERE p.id = $1
|
||||
LIMIT 1;
|
||||
|
||||
-- name: UpdatePost :execrows
|
||||
UPDATE posts
|
||||
SET title = coalesce(sqlc.narg('title'), title),
|
||||
cover_id = coalesce(sqlc.narg('cover_id'), cover_id),
|
||||
slug = coalesce(sqlc.narg('slug'), slug),
|
||||
content = coalesce(sqlc.narg('content'), content),
|
||||
summary = coalesce(sqlc.narg('summary'), summary),
|
||||
status = coalesce(sqlc.narg('status'), status),
|
||||
sort = coalesce(sqlc.narg('sort'), sort),
|
||||
published_at = coalesce(sqlc.narg('published_at'), published_at)
|
||||
WHERE id = sqlc.arg('id');
|
||||
|
||||
-- name: DeletePost :execrows
|
||||
DELETE
|
||||
FROM posts
|
||||
WHERE id = $1;
|
||||
|
||||
-- web -------------------------------------------------------
|
||||
|
||||
-- name: GetPublicPostBySlug :one
|
||||
SELECT p.*,
|
||||
f.file_path AS cover,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
FROM posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
WHERE p.slug = $1
|
||||
AND p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListPublishedPosts :many
|
||||
WITH paginated_posts AS (
|
||||
-- 第一步:先精准查出当前页需要的文章 ID
|
||||
SELECT id,
|
||||
title,
|
||||
cover_id,
|
||||
slug,
|
||||
summary,
|
||||
sort,
|
||||
published_at
|
||||
FROM posts
|
||||
WHERE status = 1
|
||||
AND published_at < NOW()
|
||||
ORDER BY sort DESC, published_at DESC, id DESC
|
||||
LIMIT $1 OFFSET $2)
|
||||
SELECT p.*,
|
||||
f.file_path AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
FROM paginated_posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC;
|
||||
|
||||
-- name: CountPublishedPosts :one
|
||||
SELECT COUNT(*)
|
||||
FROM posts
|
||||
WHERE status = 1
|
||||
AND published_at < NOW();
|
||||
|
||||
-- name: ListArchives :many
|
||||
SELECT
|
||||
p.id,
|
||||
p.slug,
|
||||
p.title,
|
||||
p.published_at,
|
||||
c."name" AS category_name
|
||||
FROM
|
||||
posts p
|
||||
LEFT JOIN post_category pc ON p.id = pc.post_id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
WHERE
|
||||
p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
ORDER BY
|
||||
p.published_at DESC, p.id DESC;
|
||||
|
||||
-- name: ListCategoryStats :many
|
||||
SELECT
|
||||
c.id,
|
||||
c.name,
|
||||
COUNT(p.id) AS post_count
|
||||
FROM
|
||||
categories c
|
||||
LEFT JOIN post_category pc ON c.id = pc.category_id
|
||||
LEFT JOIN posts p ON p.id = pc.post_id
|
||||
AND p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
GROUP BY
|
||||
c.id,
|
||||
c.name;
|
||||
29
internal/db/query/post_stats.sql
Normal file
29
internal/db/query/post_stats.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- name: IncrementPostStatsView :exec
|
||||
WITH visitor AS (
|
||||
INSERT INTO post_viewers (
|
||||
post_id,
|
||||
ip,
|
||||
last_viewed_at
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (post_id, ip)
|
||||
DO UPDATE
|
||||
SET last_viewed_at = NOW()
|
||||
WHERE post_viewers.last_viewed_at < NOW() - INTERVAL '30 minutes'
|
||||
RETURNING post_id
|
||||
)
|
||||
INSERT INTO post_stats (
|
||||
post_id,
|
||||
view
|
||||
)
|
||||
SELECT
|
||||
post_id,
|
||||
1
|
||||
FROM visitor
|
||||
ON CONFLICT (post_id)
|
||||
DO UPDATE
|
||||
SET view = post_stats.view + 1;
|
||||
58
internal/db/query/sys_api.sql
Normal file
58
internal/db/query/sys_api.sql
Normal file
@@ -0,0 +1,58 @@
|
||||
-- name: CreateSysApi :one
|
||||
INSERT INTO sys_apis (name, group_name, method, path, sort)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id;
|
||||
|
||||
-- name: GetSysApis :many
|
||||
SELECT *
|
||||
FROM sys_apis
|
||||
ORDER BY id
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountSysApis :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_apis;
|
||||
|
||||
-- name: GetSysApiByID :one
|
||||
SELECT *
|
||||
FROM sys_apis
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: UpdateSysApi :execrows
|
||||
UPDATE sys_apis
|
||||
SET name = $2,
|
||||
method = $3,
|
||||
path = $4,
|
||||
sort = $5,
|
||||
group_name = $6
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteSysApi :execrows
|
||||
DELETE
|
||||
FROM sys_apis
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: CreateSysApiPermission :exec
|
||||
INSERT INTO sys_api_permission (api_id, permission_id)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: DeleteSysApiPermission :exec
|
||||
DELETE
|
||||
FROM sys_api_permission
|
||||
WHERE api_id = $1;
|
||||
|
||||
-- name: DeleteSysPermissionBySysApiID :exec
|
||||
DELETE
|
||||
FROM sys_permissions
|
||||
WHERE id IN (SELECT permission_id
|
||||
FROM sys_api_permission
|
||||
WHERE api_id = $1);
|
||||
|
||||
-- name: GetSysApiGroupNames :many
|
||||
SELECT DISTINCT group_name
|
||||
FROM sys_apis;
|
||||
|
||||
-- name: GetAllSysApis :many
|
||||
SELECT *
|
||||
FROM sys_apis
|
||||
ORDER BY sort ASC;
|
||||
71
internal/db/query/sys_menu.sql
Normal file
71
internal/db/query/sys_menu.sql
Normal file
@@ -0,0 +1,71 @@
|
||||
-- name: CreateSysMenu :one
|
||||
INSERT INTO sys_menus (name, path, component, type, hidden, sort, status, parent_id, icon)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING id;
|
||||
|
||||
-- name: ListSysMenus :many
|
||||
SELECT m.*, p.code AS permission_code
|
||||
FROM sys_menus m
|
||||
LEFT JOIN sys_menu_permission mp ON m.id = mp.menu_id
|
||||
LEFT JOIN sys_permissions p ON mp.permission_id = p.id
|
||||
ORDER BY m.id
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountSysMenus :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_menus;
|
||||
|
||||
-- name: GetAllSysMenus :many
|
||||
SELECT m.*,
|
||||
p.code AS permission_code
|
||||
FROM sys_menus m
|
||||
LEFT JOIN sys_menu_permission mp ON m.id = mp.menu_id
|
||||
LEFT JOIN sys_permissions p ON p.id = mp.permission_id
|
||||
ORDER BY m.sort ASC,
|
||||
m.id ASC;
|
||||
|
||||
-- name: GetSysMenuByID :one
|
||||
SELECT *
|
||||
FROM sys_menus
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: UpdateSysMenu :execrows
|
||||
UPDATE sys_menus
|
||||
SET name = coalesce(sqlc.narg('name'), name),
|
||||
path = coalesce(sqlc.narg('path'), path),
|
||||
component = coalesce(sqlc.narg('component'), component),
|
||||
type = coalesce(sqlc.narg('type'), type),
|
||||
hidden = coalesce(sqlc.narg('hidden'), hidden),
|
||||
sort = coalesce(sqlc.narg('sort'), sort),
|
||||
status = coalesce(sqlc.narg('status'), status),
|
||||
icon = coalesce(sqlc.narg('icon'), status),
|
||||
parent_id = CASE WHEN @update_parent_id::boolean THEN @parent_id ELSE parent_id END
|
||||
WHERE id = sqlc.arg('id');
|
||||
|
||||
-- name: DeleteSysMenu :execrows
|
||||
DELETE
|
||||
FROM sys_menus
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: CreateSysMenuPermission :exec
|
||||
INSERT INTO sys_menu_permission (menu_id, permission_id)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: DeleteSysMenuPermission :exec
|
||||
DELETE
|
||||
FROM sys_menu_permission
|
||||
WHERE menu_id = $1;
|
||||
|
||||
-- name: DeleteSysPermissionByMenuID :exec
|
||||
DELETE
|
||||
FROM sys_permissions
|
||||
WHERE id IN (SELECT permission_id
|
||||
FROM sys_menu_permission
|
||||
WHERE menu_id = $1);
|
||||
|
||||
-- name: UpdateSysMenuPermissionCode :exec
|
||||
UPDATE sys_permissions p
|
||||
SET code = coalesce(sqlc.narg('code'), code)
|
||||
FROM sys_menu_permission mp
|
||||
WHERE p.id = mp.permission_id
|
||||
AND mp.menu_id = $1;
|
||||
14
internal/db/query/sys_permission.sql
Normal file
14
internal/db/query/sys_permission.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- name: CreateSysPermission :one
|
||||
INSERT INTO sys_permissions(type,code)
|
||||
VALUES ($1,$2) RETURNING id;
|
||||
|
||||
-- name: UpdateSysPermission :exec
|
||||
UPDATE sys_permissions
|
||||
SET code = $2
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteSysPermission :exec
|
||||
DELETE
|
||||
FROM sys_permissions
|
||||
WHERE id = $1;
|
||||
|
||||
76
internal/db/query/sys_role.sql
Normal file
76
internal/db/query/sys_role.sql
Normal file
@@ -0,0 +1,76 @@
|
||||
-- name: CreateSysRole :exec
|
||||
INSERT INTO sys_roles (name, code)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: ListSysRoles :many
|
||||
SELECT *
|
||||
FROM sys_roles
|
||||
ORDER BY id
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountSysRoles :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_roles;
|
||||
|
||||
-- name: GetSysRoleByID :one
|
||||
SELECT *
|
||||
FROM sys_roles
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ExistsSysRoleCode :one
|
||||
SELECT EXISTS(SELECT 1
|
||||
FROM sys_roles
|
||||
WHERE code = sqlc.arg(code)
|
||||
AND (
|
||||
sqlc.narg(id)::integer IS NULL
|
||||
OR id <> sqlc.narg(id)::integer
|
||||
));
|
||||
|
||||
-- name: UpdateSysRole :execrows
|
||||
UPDATE sys_roles
|
||||
SET name = coalesce(sqlc.narg('name'), name)
|
||||
WHERE id = sqlc.arg('id');
|
||||
|
||||
-- name: DeleteSysRole :execrows
|
||||
DELETE
|
||||
FROM sys_roles
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: CreateSysRolePermission :copyfrom
|
||||
INSERT INTO sys_role_permission (role_id, permission_id)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: GetSysPermissionIdsByMenuIDs :many
|
||||
SELECT permission_id
|
||||
FROM sys_menu_permission
|
||||
WHERE menu_id = ANY ($1::int[]);
|
||||
|
||||
-- name: GetSysPermissionIdsByApiIDs :many
|
||||
SELECT permission_id
|
||||
FROM sys_api_permission
|
||||
WHERE api_id = ANY ($1::int[]);
|
||||
|
||||
-- name: GetAllSysRoles :many
|
||||
SELECT *
|
||||
from sys_roles;
|
||||
|
||||
-- name: GetSysRoleMenus :many
|
||||
SELECT m.id, m.name
|
||||
FROM sys_role_permission rp
|
||||
JOIN sys_menu_permission mp ON mp.permission_id = rp.permission_id
|
||||
JOIN sys_menus m ON m.id = mp.menu_id
|
||||
WHERE rp.role_id = $1;
|
||||
|
||||
-- name: GetSysRoleApis :many
|
||||
SELECT a.id, a."name"
|
||||
FROM sys_role_permission rp
|
||||
JOIN sys_api_permission ap ON ap.permission_id = rp.permission_id
|
||||
JOIN sys_apis a ON a.id = ap.api_id
|
||||
WHERE rp.role_id = $1;
|
||||
|
||||
-- name: DeleteSysRolePermission :exec
|
||||
DELETE
|
||||
FROM sys_role_permission rp USING sys_permissions p
|
||||
WHERE rp.permission_id = p.id
|
||||
AND p."type" = $2
|
||||
AND rp.role_id = $1;
|
||||
107
internal/db/query/sys_user.sql
Normal file
107
internal/db/query/sys_user.sql
Normal file
@@ -0,0 +1,107 @@
|
||||
-- name: CreateSysUser :exec
|
||||
INSERT INTO sys_users (account, username, password_hash, avatar_id)
|
||||
VALUES ($1, $2, $3, $4);
|
||||
|
||||
-- name: GetSysUserByID :one
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.avatar_id,
|
||||
f.file_path AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
WHERE u.id = $1;
|
||||
|
||||
-- name: GetSysUserByAccount :one
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.password_hash,
|
||||
u.avatar_id,
|
||||
f.file_path AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
WHERE u.account = $1;
|
||||
|
||||
-- name: ListSysUsers :many
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.avatar_id,
|
||||
f.file_path AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
ORDER BY u.id
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountSysUsers :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_users;
|
||||
|
||||
-- name: UpdateSysUser :execrows
|
||||
UPDATE sys_users
|
||||
SET username = coalesce(sqlc.narg('username'), username),
|
||||
avatar_id = CASE WHEN @update_avatar_id::boolean THEN @avatar_id ELSE avatar_id END
|
||||
WHERE id = sqlc.arg('id');
|
||||
|
||||
-- name: UpdateSysUserPassword :execrows
|
||||
UPDATE sys_users
|
||||
SET password_hash = $2
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteSysUser :execrows
|
||||
DELETE
|
||||
FROM sys_users
|
||||
WHERE id = $1
|
||||
AND id <> 1;
|
||||
|
||||
-- name: ClearSysUserRoles :exec
|
||||
DELETE
|
||||
FROM sys_user_role
|
||||
WHERE user_id = $1;
|
||||
|
||||
-- name: CreateSysUserRole :exec
|
||||
INSERT INTO sys_user_role (user_id, role_id)
|
||||
VALUES ($1, $2);
|
||||
|
||||
-- name: GetSysUserRoles :many
|
||||
SELECT r.*
|
||||
FROM sys_roles r
|
||||
JOIN sys_user_role ur ON r.id = ur.role_id
|
||||
WHERE ur.user_id = $1;
|
||||
|
||||
-- name: GetSysAdminMenus :many
|
||||
SELECT *
|
||||
FROM sys_menus
|
||||
ORDER BY sort, id;
|
||||
|
||||
-- name: GetSysUserMenus :many
|
||||
SELECT DISTINCT m.*
|
||||
FROM sys_users u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.id
|
||||
JOIN sys_roles r ON r.id = ur.role_id
|
||||
JOIN sys_role_permission rp ON rp.role_id = r.id
|
||||
JOIN sys_permissions p ON p.id = rp.permission_id
|
||||
JOIN sys_menu_permission mp ON mp.permission_id = p.id
|
||||
JOIN sys_menus m ON m.id = mp.menu_id
|
||||
WHERE u.id = $1
|
||||
ORDER BY m.sort, m.id;
|
||||
|
||||
-- name: GetSysUserApis :many
|
||||
SELECT DISTINCT a.id,
|
||||
a.PATH,
|
||||
a.METHOD
|
||||
FROM sys_users u
|
||||
JOIN sys_user_role ur ON u.id = ur.user_id
|
||||
JOIN sys_role_permission rp ON rp.role_id = ur.role_id
|
||||
JOIN sys_permissions p ON p.id = rp.permission_id
|
||||
AND p.TYPE = 1
|
||||
JOIN sys_api_permission ap ON ap.permission_id = p.id
|
||||
JOIN sys_apis a ON a.id = ap.api_id
|
||||
WHERE u.id = $1;
|
||||
19
internal/db/schema/categories.sql
Normal file
19
internal/db/schema/categories.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
-- 分类表
|
||||
CREATE TABLE categories
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_categories_updated_at
|
||||
BEFORE UPDATE
|
||||
ON categories
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN categories.id IS '分类ID';
|
||||
COMMENT ON COLUMN categories.name IS '分类名称';
|
||||
COMMENT ON COLUMN categories.code IS '分类编码';
|
||||
28
internal/db/schema/files.sql
Normal file
28
internal/db/schema/files.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
CREATE TABLE files
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
file_name TEXT NOT NULL,
|
||||
file_path TEXT NOT NULL,
|
||||
original_name TEXT NOT NULL,
|
||||
folder_name TEXT NOT NULL,
|
||||
mime_type TEXT NOT NULL,
|
||||
file_size BIGINT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_files_updated_at
|
||||
BEFORE UPDATE
|
||||
ON files
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN files.id IS '主键ID';
|
||||
COMMENT ON COLUMN files.file_name IS '文件名 xxx.jpg';
|
||||
COMMENT ON COLUMN files.file_path IS '文件路径 带path /xxx/xxx.jpg';
|
||||
COMMENT ON COLUMN files.original_name IS '原始文件名';
|
||||
COMMENT ON COLUMN files.folder_name IS '文件夹名称';
|
||||
COMMENT ON COLUMN files.mime_type IS 'mime_type';
|
||||
COMMENT ON COLUMN files.file_size IS '文件大小';
|
||||
COMMENT ON COLUMN files.created_at IS '上传时间';
|
||||
COMMENT ON COLUMN files.updated_at IS '修改时间';
|
||||
11
internal/db/schema/func.sql
Normal file
11
internal/db/schema/func.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
CREATE
|
||||
OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS
|
||||
$$
|
||||
BEGIN
|
||||
NEW.updated_at
|
||||
:= NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$
|
||||
language 'plpgsql';
|
||||
9
internal/db/schema/post_category.sql
Normal file
9
internal/db/schema/post_category.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE post_category
|
||||
(
|
||||
post_id INT NOT NULL,
|
||||
category_id INT NOT NULL,
|
||||
PRIMARY KEY (post_id, category_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN post_category.post_id IS '文章ID';
|
||||
COMMENT ON COLUMN post_category.category_id IS '分类ID';
|
||||
8
internal/db/schema/post_stats.sql
Normal file
8
internal/db/schema/post_stats.sql
Normal file
@@ -0,0 +1,8 @@
|
||||
CREATE TABLE post_stats
|
||||
(
|
||||
post_id INTEGER PRIMARY KEY,
|
||||
view INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN post_stats.post_id IS '文章id';
|
||||
COMMENT ON COLUMN post_stats.view IS '文章阅读量';
|
||||
12
internal/db/schema/post_viewers.sql
Normal file
12
internal/db/schema/post_viewers.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE post_viewers
|
||||
(
|
||||
post_id INTEGER NOT NULL,
|
||||
ip INET NOT NULL,
|
||||
last_viewed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY(post_id, ip)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN post_viewers.post_id IS '文章id';
|
||||
COMMENT ON COLUMN post_viewers.ip IS '访问ip';
|
||||
COMMENT ON COLUMN post_viewers.last_viewed_at IS '最后访问时间';
|
||||
35
internal/db/schema/posts.sql
Normal file
35
internal/db/schema/posts.sql
Normal file
@@ -0,0 +1,35 @@
|
||||
CREATE TABLE posts
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
title TEXT NOT NULL,
|
||||
cover_id INTEGER,
|
||||
slug TEXT UNIQUE NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
summary TEXT NOT NULL,
|
||||
status SMALLINT NOT NULL DEFAULT 1,
|
||||
sort INTEGER DEFAULT 0,
|
||||
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
CHECK (status IN (0, 1, 2))
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_posts_updated_at
|
||||
BEFORE UPDATE
|
||||
ON posts
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
|
||||
COMMENT ON COLUMN posts.id IS '主键ID';
|
||||
COMMENT ON COLUMN posts.title IS '文章标题';
|
||||
COMMENT ON COLUMN posts.cover_id IS '文章封面图片id';
|
||||
COMMENT ON COLUMN posts.slug IS 'URL友好地址';
|
||||
COMMENT ON COLUMN posts.content IS '文章正文';
|
||||
COMMENT ON COLUMN posts.summary IS '摘要';
|
||||
COMMENT ON COLUMN posts.status IS '状态 0:草稿 1:已发布 2:已下线';
|
||||
COMMENT ON COLUMN posts.sort IS '文章排序';
|
||||
COMMENT ON COLUMN posts.published_at IS '发布时间';
|
||||
COMMENT ON COLUMN posts.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN posts.updated_at IS '修改时间';
|
||||
9
internal/db/schema/sys_api_permission.sql
Normal file
9
internal/db/schema/sys_api_permission.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE sys_api_permission
|
||||
(
|
||||
api_id INTEGER NOT NULL,
|
||||
permission_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (api_id, permission_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_api_permission.api_id IS 'api ID';
|
||||
COMMENT ON COLUMN sys_api_permission.permission_id IS '权限id';
|
||||
28
internal/db/schema/sys_apis.sql
Normal file
28
internal/db/schema/sys_apis.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
CREATE TABLE sys_apis
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
group_name TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
method TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
sort INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
UNIQUE (method, path)
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_sys_apis_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_apis
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_apis.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_apis.group_name IS '分组名称';
|
||||
COMMENT ON COLUMN sys_apis.name IS '接口名称';
|
||||
COMMENT ON COLUMN sys_apis.method IS 'api方法';
|
||||
COMMENT ON COLUMN sys_apis.path IS 'api路径';
|
||||
COMMENT ON COLUMN sys_apis.sort IS '排序';
|
||||
COMMENT ON COLUMN sys_apis.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_apis.updated_at IS '更新时间';
|
||||
9
internal/db/schema/sys_menu_permission.sql
Normal file
9
internal/db/schema/sys_menu_permission.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE sys_menu_permission
|
||||
(
|
||||
menu_id INTEGER NOT NULL,
|
||||
permission_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (menu_id, permission_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_menu_permission.menu_id IS '菜单id';
|
||||
COMMENT ON COLUMN sys_menu_permission.permission_id IS '权限id';
|
||||
38
internal/db/schema/sys_menus.sql
Normal file
38
internal/db/schema/sys_menus.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
CREATE TABLE sys_menus
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
component TEXT,
|
||||
type SMALLINT NOT NULL,
|
||||
hidden BOOLEAN DEFAULT FALSE,
|
||||
sort INTEGER DEFAULT 0,
|
||||
status SMALLINT NOT NULL DEFAULT 1,
|
||||
parent_id INTEGER,
|
||||
icon INTEGER,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
CHECK (type IN (0, 1, 2)),
|
||||
CHECK (status IN (0, 1))
|
||||
);
|
||||
|
||||
|
||||
CREATE TRIGGER update_sys_menus_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_menus
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_menus.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_menus.name IS '菜单名称';
|
||||
COMMENT ON COLUMN sys_menus.path IS '菜单路径';
|
||||
COMMENT ON COLUMN sys_menus.component IS '组件路径';
|
||||
COMMENT ON COLUMN sys_menus.type IS '菜单类型 0: 目录 1: 菜单 2: button';
|
||||
COMMENT ON COLUMN sys_menus.sort IS '菜单排序';
|
||||
COMMENT ON COLUMN sys_menus.hidden IS '是否隐藏菜单';
|
||||
COMMENT ON COLUMN sys_menus.status IS '菜单状态 1: 启用 0: 禁用';
|
||||
COMMENT ON COLUMN sys_menus.parent_id IS '父级id';
|
||||
COMMENT ON COLUMN sys_menus.icon IS '菜单icon';
|
||||
COMMENT ON COLUMN sys_menus.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_menus.updated_at IS '更新时间';
|
||||
22
internal/db/schema/sys_permissions.sql
Normal file
22
internal/db/schema/sys_permissions.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
CREATE TABLE sys_permissions
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
code TEXT UNIQUE,
|
||||
type SMALLINT NOT NULL,
|
||||
created_at TIMESTAMPTZtz NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT unique_type_code UNIQUE (type, code)
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_sys_permissions_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_permissions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_permissions.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_permissions.code IS '权限字符,唯一';
|
||||
COMMENT ON COLUMN sys_permissions.code IS '权限类型,0: 菜单 1: api';
|
||||
COMMENT ON COLUMN sys_permissions.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_permissions.updated_at IS '更新时间';
|
||||
9
internal/db/schema/sys_role_permission.sql
Normal file
9
internal/db/schema/sys_role_permission.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE sys_role_permission
|
||||
(
|
||||
role_id INTEGER NOT NULL,
|
||||
permission_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (role_id, permission_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_role_permission.role_id IS '角色id';
|
||||
COMMENT ON COLUMN sys_role_permission.permission_id IS '权限id';
|
||||
20
internal/db/schema/sys_roles.sql
Normal file
20
internal/db/schema/sys_roles.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
CREATE TABLE sys_roles
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL,
|
||||
code TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_sys_roles_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_roles
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
COMMENT ON COLUMN sys_roles.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_roles.name IS '角色名称';
|
||||
COMMENT ON COLUMN sys_roles.code IS '角色编码,唯一';
|
||||
COMMENT ON COLUMN sys_roles.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_roles.updated_at IS '更新时间';
|
||||
9
internal/db/schema/sys_user_role.sql
Normal file
9
internal/db/schema/sys_user_role.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE sys_user_role
|
||||
(
|
||||
user_id INTEGER NOT NULL,
|
||||
role_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (user_id, role_id)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN sys_user_role.user_id IS '用户ID';
|
||||
COMMENT ON COLUMN sys_user_role.role_id IS '角色ID';
|
||||
27
internal/db/schema/sys_users.sql
Normal file
27
internal/db/schema/sys_users.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
CREATE TABLE sys_users
|
||||
(
|
||||
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
account TEXT NOT NULL UNIQUE,
|
||||
username TEXT NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
avatar_id INTEGER,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sys_users_account ON sys_users (account);
|
||||
|
||||
CREATE TRIGGER update_sys_users_updated_at
|
||||
BEFORE UPDATE
|
||||
ON sys_users
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
|
||||
COMMENT ON COLUMN sys_users.id IS '主键ID';
|
||||
COMMENT ON COLUMN sys_users.account IS '用户账号';
|
||||
COMMENT ON COLUMN sys_users.username IS '用户名称';
|
||||
COMMENT ON COLUMN sys_users.password_hash IS 'hash密码';
|
||||
COMMENT ON COLUMN sys_users.avatar_id IS '头像文件id';
|
||||
COMMENT ON COLUMN sys_users.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_users.updated_at IS '更新时间';
|
||||
186
internal/db/sqlc/category.sql.go
Normal file
186
internal/db/sqlc/category.sql.go
Normal file
@@ -0,0 +1,186 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: category.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const countCategories = `-- name: CountCategories :one
|
||||
SELECT COUNT(*)
|
||||
FROM categories
|
||||
`
|
||||
|
||||
func (q *Queries) CountCategories(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countCategories)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createCategory = `-- name: CreateCategory :exec
|
||||
INSERT INTO categories(name, code)
|
||||
VALUES ($1, $2)
|
||||
`
|
||||
|
||||
type CreateCategoryParams struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateCategory(ctx context.Context, arg CreateCategoryParams) error {
|
||||
_, err := q.db.Exec(ctx, createCategory, arg.Name, arg.Code)
|
||||
return err
|
||||
}
|
||||
|
||||
const createPostCategory = `-- name: CreatePostCategory :exec
|
||||
INSERT INTO post_category(post_id, category_id)
|
||||
VALUES ($1, $2)
|
||||
`
|
||||
|
||||
type CreatePostCategoryParams struct {
|
||||
PostID int32 `json:"post_id"`
|
||||
CategoryID int32 `json:"category_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePostCategory(ctx context.Context, arg CreatePostCategoryParams) error {
|
||||
_, err := q.db.Exec(ctx, createPostCategory, arg.PostID, arg.CategoryID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteCategory = `-- name: DeleteCategory :execrows
|
||||
DELETE
|
||||
FROM categories
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteCategory(ctx context.Context, id int32) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deleteCategory, id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const deletePostCategory = `-- name: DeletePostCategory :exec
|
||||
DELETE
|
||||
FROM post_category
|
||||
WHERE post_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeletePostCategory(ctx context.Context, postID int32) error {
|
||||
_, err := q.db.Exec(ctx, deletePostCategory, postID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getCategoryById = `-- name: GetCategoryById :one
|
||||
SELECT id, name, code, created_at, updated_at
|
||||
FROM categories
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetCategoryById(ctx context.Context, id int32) (Category, error) {
|
||||
row := q.db.QueryRow(ctx, getCategoryById, id)
|
||||
var i Category
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listAllCategories = `-- name: ListAllCategories :many
|
||||
SELECT id, name, code, created_at, updated_at
|
||||
FROM categories
|
||||
`
|
||||
|
||||
func (q *Queries) ListAllCategories(ctx context.Context) ([]Category, error) {
|
||||
rows, err := q.db.Query(ctx, listAllCategories)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []Category{}
|
||||
for rows.Next() {
|
||||
var i Category
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listCategories = `-- name: ListCategories :many
|
||||
SELECT id, name, code, created_at, updated_at
|
||||
FROM categories
|
||||
ORDER BY id LIMIT $1
|
||||
OFFSET $2
|
||||
`
|
||||
|
||||
type ListCategoriesParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListCategories(ctx context.Context, arg ListCategoriesParams) ([]Category, error) {
|
||||
rows, err := q.db.Query(ctx, listCategories, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []Category{}
|
||||
for rows.Next() {
|
||||
var i Category
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateCategory = `-- name: UpdateCategory :execrows
|
||||
UPDATE categories
|
||||
SET name = coalesce($1, name),
|
||||
code = coalesce($2, code)
|
||||
WHERE id = $3
|
||||
`
|
||||
|
||||
type UpdateCategoryParams struct {
|
||||
Name *string `json:"name"`
|
||||
Code *string `json:"code"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateCategory(ctx context.Context, arg UpdateCategoryParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updateCategory, arg.Name, arg.Code, arg.ID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
43
internal/db/sqlc/copyfrom.go
Normal file
43
internal/db/sqlc/copyfrom.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: copyfrom.go
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// iteratorForCreateSysRolePermission implements pgx.CopyFromSource.
|
||||
type iteratorForCreateSysRolePermission struct {
|
||||
rows []CreateSysRolePermissionParams
|
||||
skippedFirstNextCall bool
|
||||
}
|
||||
|
||||
func (r *iteratorForCreateSysRolePermission) Next() bool {
|
||||
if len(r.rows) == 0 {
|
||||
return false
|
||||
}
|
||||
if !r.skippedFirstNextCall {
|
||||
r.skippedFirstNextCall = true
|
||||
return true
|
||||
}
|
||||
r.rows = r.rows[1:]
|
||||
return len(r.rows) > 0
|
||||
}
|
||||
|
||||
func (r iteratorForCreateSysRolePermission) Values() ([]interface{}, error) {
|
||||
return []interface{}{
|
||||
r.rows[0].RoleID,
|
||||
r.rows[0].PermissionID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r iteratorForCreateSysRolePermission) Err() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysRolePermission(ctx context.Context, arg []CreateSysRolePermissionParams) (int64, error) {
|
||||
return q.db.CopyFrom(ctx, []string{"sys_role_permission"}, []string{"role_id", "permission_id"}, &iteratorForCreateSysRolePermission{rows: arg})
|
||||
}
|
||||
33
internal/db/sqlc/db.go
Normal file
33
internal/db/sqlc/db.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error)
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
98
internal/db/sqlc/file.sql.go
Normal file
98
internal/db/sqlc/file.sql.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: file.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const countFiles = `-- name: CountFiles :one
|
||||
SELECT COUNT(*)
|
||||
FROM files
|
||||
`
|
||||
|
||||
func (q *Queries) CountFiles(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countFiles)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createFile = `-- name: CreateFile :one
|
||||
INSERT INTO files(file_name, file_path, original_name, folder_name, mime_type, file_size)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING id,file_path,file_name
|
||||
`
|
||||
|
||||
type CreateFileParams struct {
|
||||
FileName string `json:"file_name"`
|
||||
FilePath string `json:"file_path"`
|
||||
OriginalName string `json:"original_name"`
|
||||
FolderName string `json:"folder_name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
FileSize int64 `json:"file_size"`
|
||||
}
|
||||
|
||||
type CreateFileRow struct {
|
||||
ID int32 `json:"id"`
|
||||
FilePath string `json:"file_path"`
|
||||
FileName string `json:"file_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateFile(ctx context.Context, arg CreateFileParams) (CreateFileRow, error) {
|
||||
row := q.db.QueryRow(ctx, createFile,
|
||||
arg.FileName,
|
||||
arg.FilePath,
|
||||
arg.OriginalName,
|
||||
arg.FolderName,
|
||||
arg.MimeType,
|
||||
arg.FileSize,
|
||||
)
|
||||
var i CreateFileRow
|
||||
err := row.Scan(&i.ID, &i.FilePath, &i.FileName)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getFiles = `-- name: GetFiles :many
|
||||
SELECT id, file_name, file_path, original_name, folder_name, mime_type, file_size, created_at, updated_at
|
||||
FROM files
|
||||
ORDER BY id LIMIT $1
|
||||
OFFSET $2
|
||||
`
|
||||
|
||||
type GetFilesParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetFiles(ctx context.Context, arg GetFilesParams) ([]File, error) {
|
||||
rows, err := q.db.Query(ctx, getFiles, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []File{}
|
||||
for rows.Next() {
|
||||
var i File
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.FileName,
|
||||
&i.FilePath,
|
||||
&i.OriginalName,
|
||||
&i.FolderName,
|
||||
&i.MimeType,
|
||||
&i.FileSize,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
206
internal/db/sqlc/models.go
Normal file
206
internal/db/sqlc/models.go
Normal file
@@ -0,0 +1,206 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Category struct {
|
||||
// 分类ID
|
||||
ID int32 `json:"id"`
|
||||
// 分类名称
|
||||
Name string `json:"name"`
|
||||
// 分类编码
|
||||
Code string `json:"code"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type File struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 文件名 xxx.jpg
|
||||
FileName string `json:"file_name"`
|
||||
// 文件路径 带path /xxx/xxx.jpg
|
||||
FilePath string `json:"file_path"`
|
||||
// 原始文件名
|
||||
OriginalName string `json:"original_name"`
|
||||
// 文件夹名称
|
||||
FolderName string `json:"folder_name"`
|
||||
// mime_type
|
||||
MimeType string `json:"mime_type"`
|
||||
// 文件大小
|
||||
FileSize int64 `json:"file_size"`
|
||||
// 上传时间
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// 修改时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Post struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 文章标题
|
||||
Title string `json:"title"`
|
||||
// 文章封面图片id
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
// URL友好地址
|
||||
Slug string `json:"slug"`
|
||||
// 文章正文
|
||||
Content string `json:"content"`
|
||||
// 摘要
|
||||
Summary string `json:"summary"`
|
||||
// 状态 0:草稿 1:已发布 2:已下线
|
||||
Status int16 `json:"status"`
|
||||
// 文章排序
|
||||
Sort *int32 `json:"sort"`
|
||||
// 发布时间
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
// 创建时间
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// 修改时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type PostCategory struct {
|
||||
// 文章ID
|
||||
PostID int32 `json:"post_id"`
|
||||
// 分类ID
|
||||
CategoryID int32 `json:"category_id"`
|
||||
}
|
||||
|
||||
type PostStat struct {
|
||||
// 文章id
|
||||
PostID int32 `json:"post_id"`
|
||||
// 文章阅读量
|
||||
View int32 `json:"view"`
|
||||
}
|
||||
|
||||
type PostViewer struct {
|
||||
// 文章id
|
||||
PostID int32 `json:"post_id"`
|
||||
// 访问ip
|
||||
Ip netip.Addr `json:"ip"`
|
||||
// 最后访问时间
|
||||
LastViewedAt time.Time `json:"last_viewed_at"`
|
||||
}
|
||||
|
||||
type SysApi struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 分组名称
|
||||
GroupName string `json:"group_name"`
|
||||
// 接口名称
|
||||
Name string `json:"name"`
|
||||
// api方法
|
||||
Method string `json:"method"`
|
||||
// api路径
|
||||
Path string `json:"path"`
|
||||
// 排序
|
||||
Sort *int32 `json:"sort"`
|
||||
// 创建时间
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// 更新时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SysApiPermission struct {
|
||||
// api ID
|
||||
ApiID int32 `json:"api_id"`
|
||||
// 权限id
|
||||
PermissionID int32 `json:"permission_id"`
|
||||
}
|
||||
|
||||
type SysMenu struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 菜单名称
|
||||
Name string `json:"name"`
|
||||
// 菜单路径
|
||||
Path string `json:"path"`
|
||||
// 组件路径
|
||||
Component *string `json:"component"`
|
||||
// 菜单类型 0: 目录 1: 菜单 2: button
|
||||
Type int16 `json:"type"`
|
||||
// 是否隐藏菜单
|
||||
Hidden *bool `json:"hidden"`
|
||||
// 菜单排序
|
||||
Sort *int32 `json:"sort"`
|
||||
// 菜单状态 1: 启用 0: 禁用
|
||||
Status int16 `json:"status"`
|
||||
// 父级id
|
||||
ParentID *int32 `json:"parent_id"`
|
||||
// 菜单icon
|
||||
Icon *int32 `json:"icon"`
|
||||
// 创建时间
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// 更新时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SysMenuPermission struct {
|
||||
// 菜单id
|
||||
MenuID int32 `json:"menu_id"`
|
||||
// 权限id
|
||||
PermissionID int32 `json:"permission_id"`
|
||||
}
|
||||
|
||||
type SysPermission struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 权限类型,0: 菜单 1: api
|
||||
Code *string `json:"code"`
|
||||
Type int16 `json:"type"`
|
||||
// 创建时间
|
||||
CreatedAt interface{} `json:"created_at"`
|
||||
// 更新时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SysRole struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 角色名称
|
||||
Name string `json:"name"`
|
||||
// 角色编码,唯一
|
||||
Code string `json:"code"`
|
||||
// 创建时间
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// 更新时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SysRolePermission struct {
|
||||
// 角色id
|
||||
RoleID int32 `json:"role_id"`
|
||||
// 权限id
|
||||
PermissionID int32 `json:"permission_id"`
|
||||
}
|
||||
|
||||
type SysUser struct {
|
||||
// 主键ID
|
||||
ID int32 `json:"id"`
|
||||
// 用户账号
|
||||
Account string `json:"account"`
|
||||
// 用户名称
|
||||
Username string `json:"username"`
|
||||
// hash密码
|
||||
PasswordHash string `json:"password_hash"`
|
||||
// 头像文件id
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
// 创建时间
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// 更新时间
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type SysUserRole struct {
|
||||
// 用户ID
|
||||
UserID int32 `json:"user_id"`
|
||||
// 角色ID
|
||||
RoleID int32 `json:"role_id"`
|
||||
}
|
||||
491
internal/db/sqlc/post.sql.go
Normal file
491
internal/db/sqlc/post.sql.go
Normal file
@@ -0,0 +1,491 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: post.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const countPosts = `-- name: CountPosts :one
|
||||
SELECT COUNT(*)
|
||||
FROM posts
|
||||
`
|
||||
|
||||
func (q *Queries) CountPosts(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countPosts)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const countPublishedPosts = `-- name: CountPublishedPosts :one
|
||||
SELECT COUNT(*)
|
||||
FROM posts
|
||||
WHERE status = 1
|
||||
AND published_at < NOW()
|
||||
`
|
||||
|
||||
func (q *Queries) CountPublishedPosts(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countPublishedPosts)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createPost = `-- name: CreatePost :one
|
||||
INSERT INTO posts(title, cover_id, slug, content, summary, status, sort, published_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type CreatePostParams struct {
|
||||
Title string `json:"title"`
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
Slug string `json:"slug"`
|
||||
Content string `json:"content"`
|
||||
Summary string `json:"summary"`
|
||||
Status int16 `json:"status"`
|
||||
Sort *int32 `json:"sort"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreatePost(ctx context.Context, arg CreatePostParams) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, createPost,
|
||||
arg.Title,
|
||||
arg.CoverID,
|
||||
arg.Slug,
|
||||
arg.Content,
|
||||
arg.Summary,
|
||||
arg.Status,
|
||||
arg.Sort,
|
||||
arg.PublishedAt,
|
||||
)
|
||||
var id int32
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const deletePost = `-- name: DeletePost :execrows
|
||||
DELETE
|
||||
FROM posts
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeletePost(ctx context.Context, id int32) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deletePost, id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const getPostById = `-- name: GetPostById :one
|
||||
SELECT p.id, p.title, p.cover_id, p.slug, p.content, p.summary, p.status, p.sort, p.published_at, p.created_at, p.updated_at,
|
||||
f.file_path AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id
|
||||
FROM posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
WHERE p.id = $1
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetPostByIdRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
Slug string `json:"slug"`
|
||||
Content string `json:"content"`
|
||||
Summary string `json:"summary"`
|
||||
Status int16 `json:"status"`
|
||||
Sort *int32 `json:"sort"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
Cover *string `json:"cover"`
|
||||
CategoryName *string `json:"category_name"`
|
||||
CategoryID *int32 `json:"category_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetPostById(ctx context.Context, id int32) (GetPostByIdRow, error) {
|
||||
row := q.db.QueryRow(ctx, getPostById, id)
|
||||
var i GetPostByIdRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.CoverID,
|
||||
&i.Slug,
|
||||
&i.Content,
|
||||
&i.Summary,
|
||||
&i.Status,
|
||||
&i.Sort,
|
||||
&i.PublishedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Cover,
|
||||
&i.CategoryName,
|
||||
&i.CategoryID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getPublicPostBySlug = `-- name: GetPublicPostBySlug :one
|
||||
|
||||
SELECT p.id, p.title, p.cover_id, p.slug, p.content, p.summary, p.status, p.sort, p.published_at, p.created_at, p.updated_at,
|
||||
f.file_path AS cover,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
FROM posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
WHERE p.slug = $1
|
||||
AND p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetPublicPostBySlugRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
Slug string `json:"slug"`
|
||||
Content string `json:"content"`
|
||||
Summary string `json:"summary"`
|
||||
Status int16 `json:"status"`
|
||||
Sort *int32 `json:"sort"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
Cover *string `json:"cover"`
|
||||
View int32 `json:"view"`
|
||||
}
|
||||
|
||||
// web -------------------------------------------------------
|
||||
func (q *Queries) GetPublicPostBySlug(ctx context.Context, slug string) (GetPublicPostBySlugRow, error) {
|
||||
row := q.db.QueryRow(ctx, getPublicPostBySlug, slug)
|
||||
var i GetPublicPostBySlugRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.CoverID,
|
||||
&i.Slug,
|
||||
&i.Content,
|
||||
&i.Summary,
|
||||
&i.Status,
|
||||
&i.Sort,
|
||||
&i.PublishedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Cover,
|
||||
&i.View,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listArchives = `-- name: ListArchives :many
|
||||
SELECT
|
||||
p.id,
|
||||
p.slug,
|
||||
p.title,
|
||||
p.published_at,
|
||||
c."name" AS category_name
|
||||
FROM
|
||||
posts p
|
||||
LEFT JOIN post_category pc ON p.id = pc.post_id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
WHERE
|
||||
p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
ORDER BY
|
||||
p.published_at DESC, p.id DESC
|
||||
`
|
||||
|
||||
type ListArchivesRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Slug string `json:"slug"`
|
||||
Title string `json:"title"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
CategoryName *string `json:"category_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListArchives(ctx context.Context) ([]ListArchivesRow, error) {
|
||||
rows, err := q.db.Query(ctx, listArchives)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListArchivesRow{}
|
||||
for rows.Next() {
|
||||
var i ListArchivesRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Slug,
|
||||
&i.Title,
|
||||
&i.PublishedAt,
|
||||
&i.CategoryName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listCategoryStats = `-- name: ListCategoryStats :many
|
||||
SELECT
|
||||
c.id,
|
||||
c.name,
|
||||
COUNT(p.id) AS post_count
|
||||
FROM
|
||||
categories c
|
||||
LEFT JOIN post_category pc ON c.id = pc.category_id
|
||||
LEFT JOIN posts p ON p.id = pc.post_id
|
||||
AND p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
GROUP BY
|
||||
c.id,
|
||||
c.name
|
||||
`
|
||||
|
||||
type ListCategoryStatsRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PostCount int64 `json:"post_count"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListCategoryStats(ctx context.Context) ([]ListCategoryStatsRow, error) {
|
||||
rows, err := q.db.Query(ctx, listCategoryStats)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListCategoryStatsRow{}
|
||||
for rows.Next() {
|
||||
var i ListCategoryStatsRow
|
||||
if err := rows.Scan(&i.ID, &i.Name, &i.PostCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listPosts = `-- name: ListPosts :many
|
||||
WITH paginated_posts AS (
|
||||
-- 第一步:先精准查出当前页需要的文章 ID
|
||||
SELECT id,
|
||||
title,
|
||||
cover_id,
|
||||
slug,
|
||||
summary,
|
||||
status,
|
||||
sort,
|
||||
published_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM posts
|
||||
ORDER BY sort DESC, published_at DESC, id DESC
|
||||
LIMIT $1 OFFSET $2)
|
||||
SELECT p.id, p.title, p.cover_id, p.slug, p.summary, p.status, p.sort, p.published_at, p.created_at, p.updated_at,
|
||||
f.file_path AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
FROM paginated_posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC
|
||||
`
|
||||
|
||||
type ListPostsParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
type ListPostsRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
Slug string `json:"slug"`
|
||||
Summary string `json:"summary"`
|
||||
Status int16 `json:"status"`
|
||||
Sort *int32 `json:"sort"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
Cover *string `json:"cover"`
|
||||
CategoryName *string `json:"category_name"`
|
||||
CategoryID *int32 `json:"category_id"`
|
||||
View int32 `json:"view"`
|
||||
}
|
||||
|
||||
// 第二步:用这极少量的记录去进行 JOIN
|
||||
func (q *Queries) ListPosts(ctx context.Context, arg ListPostsParams) ([]ListPostsRow, error) {
|
||||
rows, err := q.db.Query(ctx, listPosts, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListPostsRow{}
|
||||
for rows.Next() {
|
||||
var i ListPostsRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.CoverID,
|
||||
&i.Slug,
|
||||
&i.Summary,
|
||||
&i.Status,
|
||||
&i.Sort,
|
||||
&i.PublishedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Cover,
|
||||
&i.CategoryName,
|
||||
&i.CategoryID,
|
||||
&i.View,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listPublishedPosts = `-- name: ListPublishedPosts :many
|
||||
WITH paginated_posts AS (
|
||||
-- 第一步:先精准查出当前页需要的文章 ID
|
||||
SELECT id,
|
||||
title,
|
||||
cover_id,
|
||||
slug,
|
||||
summary,
|
||||
sort,
|
||||
published_at
|
||||
FROM posts
|
||||
WHERE status = 1
|
||||
AND published_at < NOW()
|
||||
ORDER BY sort DESC, published_at DESC, id DESC
|
||||
LIMIT $1 OFFSET $2)
|
||||
SELECT p.id, p.title, p.cover_id, p.slug, p.summary, p.sort, p.published_at,
|
||||
f.file_path AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
FROM paginated_posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC
|
||||
`
|
||||
|
||||
type ListPublishedPostsParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
type ListPublishedPostsRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
Slug string `json:"slug"`
|
||||
Summary string `json:"summary"`
|
||||
Sort *int32 `json:"sort"`
|
||||
PublishedAt time.Time `json:"published_at"`
|
||||
Cover *string `json:"cover"`
|
||||
CategoryName *string `json:"category_name"`
|
||||
CategoryID *int32 `json:"category_id"`
|
||||
View int32 `json:"view"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListPublishedPosts(ctx context.Context, arg ListPublishedPostsParams) ([]ListPublishedPostsRow, error) {
|
||||
rows, err := q.db.Query(ctx, listPublishedPosts, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListPublishedPostsRow{}
|
||||
for rows.Next() {
|
||||
var i ListPublishedPostsRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Title,
|
||||
&i.CoverID,
|
||||
&i.Slug,
|
||||
&i.Summary,
|
||||
&i.Sort,
|
||||
&i.PublishedAt,
|
||||
&i.Cover,
|
||||
&i.CategoryName,
|
||||
&i.CategoryID,
|
||||
&i.View,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updatePost = `-- name: UpdatePost :execrows
|
||||
UPDATE posts
|
||||
SET title = coalesce($1, title),
|
||||
cover_id = coalesce($2, cover_id),
|
||||
slug = coalesce($3, slug),
|
||||
content = coalesce($4, content),
|
||||
summary = coalesce($5, summary),
|
||||
status = coalesce($6, status),
|
||||
sort = coalesce($7, sort),
|
||||
published_at = coalesce($8, published_at)
|
||||
WHERE id = $9
|
||||
`
|
||||
|
||||
type UpdatePostParams struct {
|
||||
Title *string `json:"title"`
|
||||
CoverID *int32 `json:"cover_id"`
|
||||
Slug *string `json:"slug"`
|
||||
Content *string `json:"content"`
|
||||
Summary *string `json:"summary"`
|
||||
Status *int16 `json:"status"`
|
||||
Sort *int32 `json:"sort"`
|
||||
PublishedAt *time.Time `json:"published_at"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdatePost(ctx context.Context, arg UpdatePostParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updatePost,
|
||||
arg.Title,
|
||||
arg.CoverID,
|
||||
arg.Slug,
|
||||
arg.Content,
|
||||
arg.Summary,
|
||||
arg.Status,
|
||||
arg.Sort,
|
||||
arg.PublishedAt,
|
||||
arg.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
52
internal/db/sqlc/post_stats.sql.go
Normal file
52
internal/db/sqlc/post_stats.sql.go
Normal file
@@ -0,0 +1,52 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: post_stats.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
const incrementPostStatsView = `-- name: IncrementPostStatsView :exec
|
||||
WITH visitor AS (
|
||||
INSERT INTO post_viewers (
|
||||
post_id,
|
||||
ip,
|
||||
last_viewed_at
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
NOW()
|
||||
)
|
||||
ON CONFLICT (post_id, ip)
|
||||
DO UPDATE
|
||||
SET last_viewed_at = NOW()
|
||||
WHERE post_viewers.last_viewed_at < NOW() - INTERVAL '30 minutes'
|
||||
RETURNING post_id
|
||||
)
|
||||
INSERT INTO post_stats (
|
||||
post_id,
|
||||
view
|
||||
)
|
||||
SELECT
|
||||
post_id,
|
||||
1
|
||||
FROM visitor
|
||||
ON CONFLICT (post_id)
|
||||
DO UPDATE
|
||||
SET view = post_stats.view + 1
|
||||
`
|
||||
|
||||
type IncrementPostStatsViewParams struct {
|
||||
PostID int32 `json:"post_id"`
|
||||
Ip netip.Addr `json:"ip"`
|
||||
}
|
||||
|
||||
func (q *Queries) IncrementPostStatsView(ctx context.Context, arg IncrementPostStatsViewParams) error {
|
||||
_, err := q.db.Exec(ctx, incrementPostStatsView, arg.PostID, arg.Ip)
|
||||
return err
|
||||
}
|
||||
259
internal/db/sqlc/sys_api.sql.go
Normal file
259
internal/db/sqlc/sys_api.sql.go
Normal file
@@ -0,0 +1,259 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: sys_api.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const countSysApis = `-- name: CountSysApis :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_apis
|
||||
`
|
||||
|
||||
func (q *Queries) CountSysApis(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countSysApis)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createSysApi = `-- name: CreateSysApi :one
|
||||
INSERT INTO sys_apis (name, group_name, method, path, sort)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type CreateSysApiParams struct {
|
||||
Name string `json:"name"`
|
||||
GroupName string `json:"group_name"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
Sort *int32 `json:"sort"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysApi(ctx context.Context, arg CreateSysApiParams) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, createSysApi,
|
||||
arg.Name,
|
||||
arg.GroupName,
|
||||
arg.Method,
|
||||
arg.Path,
|
||||
arg.Sort,
|
||||
)
|
||||
var id int32
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const createSysApiPermission = `-- name: CreateSysApiPermission :exec
|
||||
INSERT INTO sys_api_permission (api_id, permission_id)
|
||||
VALUES ($1, $2)
|
||||
`
|
||||
|
||||
type CreateSysApiPermissionParams struct {
|
||||
ApiID int32 `json:"api_id"`
|
||||
PermissionID int32 `json:"permission_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysApiPermission(ctx context.Context, arg CreateSysApiPermissionParams) error {
|
||||
_, err := q.db.Exec(ctx, createSysApiPermission, arg.ApiID, arg.PermissionID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSysApi = `-- name: DeleteSysApi :execrows
|
||||
DELETE
|
||||
FROM sys_apis
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysApi(ctx context.Context, id int32) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deleteSysApi, id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const deleteSysApiPermission = `-- name: DeleteSysApiPermission :exec
|
||||
DELETE
|
||||
FROM sys_api_permission
|
||||
WHERE api_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysApiPermission(ctx context.Context, apiID int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteSysApiPermission, apiID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSysPermissionBySysApiID = `-- name: DeleteSysPermissionBySysApiID :exec
|
||||
DELETE
|
||||
FROM sys_permissions
|
||||
WHERE id IN (SELECT permission_id
|
||||
FROM sys_api_permission
|
||||
WHERE api_id = $1)
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysPermissionBySysApiID(ctx context.Context, apiID int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteSysPermissionBySysApiID, apiID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllSysApis = `-- name: GetAllSysApis :many
|
||||
SELECT id, group_name, name, method, path, sort, created_at, updated_at
|
||||
FROM sys_apis
|
||||
ORDER BY sort ASC
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllSysApis(ctx context.Context) ([]SysApi, error) {
|
||||
rows, err := q.db.Query(ctx, getAllSysApis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysApi{}
|
||||
for rows.Next() {
|
||||
var i SysApi
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.GroupName,
|
||||
&i.Name,
|
||||
&i.Method,
|
||||
&i.Path,
|
||||
&i.Sort,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysApiByID = `-- name: GetSysApiByID :one
|
||||
SELECT id, group_name, name, method, path, sort, created_at, updated_at
|
||||
FROM sys_apis
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysApiByID(ctx context.Context, id int32) (SysApi, error) {
|
||||
row := q.db.QueryRow(ctx, getSysApiByID, id)
|
||||
var i SysApi
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.GroupName,
|
||||
&i.Name,
|
||||
&i.Method,
|
||||
&i.Path,
|
||||
&i.Sort,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSysApiGroupNames = `-- name: GetSysApiGroupNames :many
|
||||
SELECT DISTINCT group_name
|
||||
FROM sys_apis
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysApiGroupNames(ctx context.Context) ([]string, error) {
|
||||
rows, err := q.db.Query(ctx, getSysApiGroupNames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []string{}
|
||||
for rows.Next() {
|
||||
var group_name string
|
||||
if err := rows.Scan(&group_name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, group_name)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysApis = `-- name: GetSysApis :many
|
||||
SELECT id, group_name, name, method, path, sort, created_at, updated_at
|
||||
FROM sys_apis
|
||||
ORDER BY id
|
||||
LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type GetSysApisParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSysApis(ctx context.Context, arg GetSysApisParams) ([]SysApi, error) {
|
||||
rows, err := q.db.Query(ctx, getSysApis, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysApi{}
|
||||
for rows.Next() {
|
||||
var i SysApi
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.GroupName,
|
||||
&i.Name,
|
||||
&i.Method,
|
||||
&i.Path,
|
||||
&i.Sort,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateSysApi = `-- name: UpdateSysApi :execrows
|
||||
UPDATE sys_apis
|
||||
SET name = $2,
|
||||
method = $3,
|
||||
path = $4,
|
||||
sort = $5,
|
||||
group_name = $6
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateSysApiParams struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
Sort *int32 `json:"sort"`
|
||||
GroupName string `json:"group_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysApi(ctx context.Context, arg UpdateSysApiParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updateSysApi,
|
||||
arg.ID,
|
||||
arg.Name,
|
||||
arg.Method,
|
||||
arg.Path,
|
||||
arg.Sort,
|
||||
arg.GroupName,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
327
internal/db/sqlc/sys_menu.sql.go
Normal file
327
internal/db/sqlc/sys_menu.sql.go
Normal file
@@ -0,0 +1,327 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: sys_menu.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const countSysMenus = `-- name: CountSysMenus :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_menus
|
||||
`
|
||||
|
||||
func (q *Queries) CountSysMenus(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countSysMenus)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createSysMenu = `-- name: CreateSysMenu :one
|
||||
INSERT INTO sys_menus (name, path, component, type, hidden, sort, status, parent_id, icon)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type CreateSysMenuParams struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Component *string `json:"component"`
|
||||
Type int16 `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Sort *int32 `json:"sort"`
|
||||
Status int16 `json:"status"`
|
||||
ParentID *int32 `json:"parent_id"`
|
||||
Icon *int32 `json:"icon"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysMenu(ctx context.Context, arg CreateSysMenuParams) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, createSysMenu,
|
||||
arg.Name,
|
||||
arg.Path,
|
||||
arg.Component,
|
||||
arg.Type,
|
||||
arg.Hidden,
|
||||
arg.Sort,
|
||||
arg.Status,
|
||||
arg.ParentID,
|
||||
arg.Icon,
|
||||
)
|
||||
var id int32
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const createSysMenuPermission = `-- name: CreateSysMenuPermission :exec
|
||||
INSERT INTO sys_menu_permission (menu_id, permission_id)
|
||||
VALUES ($1, $2)
|
||||
`
|
||||
|
||||
type CreateSysMenuPermissionParams struct {
|
||||
MenuID int32 `json:"menu_id"`
|
||||
PermissionID int32 `json:"permission_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysMenuPermission(ctx context.Context, arg CreateSysMenuPermissionParams) error {
|
||||
_, err := q.db.Exec(ctx, createSysMenuPermission, arg.MenuID, arg.PermissionID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSysMenu = `-- name: DeleteSysMenu :execrows
|
||||
DELETE
|
||||
FROM sys_menus
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysMenu(ctx context.Context, id int32) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deleteSysMenu, id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const deleteSysMenuPermission = `-- name: DeleteSysMenuPermission :exec
|
||||
DELETE
|
||||
FROM sys_menu_permission
|
||||
WHERE menu_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysMenuPermission(ctx context.Context, menuID int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteSysMenuPermission, menuID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSysPermissionByMenuID = `-- name: DeleteSysPermissionByMenuID :exec
|
||||
DELETE
|
||||
FROM sys_permissions
|
||||
WHERE id IN (SELECT permission_id
|
||||
FROM sys_menu_permission
|
||||
WHERE menu_id = $1)
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysPermissionByMenuID(ctx context.Context, menuID int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteSysPermissionByMenuID, menuID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAllSysMenus = `-- name: GetAllSysMenus :many
|
||||
SELECT m.id, m.name, m.path, m.component, m.type, m.hidden, m.sort, m.status, m.parent_id, m.icon, m.created_at, m.updated_at,
|
||||
p.code AS permission_code
|
||||
FROM sys_menus m
|
||||
LEFT JOIN sys_menu_permission mp ON m.id = mp.menu_id
|
||||
LEFT JOIN sys_permissions p ON p.id = mp.permission_id
|
||||
ORDER BY m.sort ASC,
|
||||
m.id ASC
|
||||
`
|
||||
|
||||
type GetAllSysMenusRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Component *string `json:"component"`
|
||||
Type int16 `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Sort *int32 `json:"sort"`
|
||||
Status int16 `json:"status"`
|
||||
ParentID *int32 `json:"parent_id"`
|
||||
Icon *int32 `json:"icon"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
PermissionCode *string `json:"permission_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetAllSysMenus(ctx context.Context) ([]GetAllSysMenusRow, error) {
|
||||
rows, err := q.db.Query(ctx, getAllSysMenus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []GetAllSysMenusRow{}
|
||||
for rows.Next() {
|
||||
var i GetAllSysMenusRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Path,
|
||||
&i.Component,
|
||||
&i.Type,
|
||||
&i.Hidden,
|
||||
&i.Sort,
|
||||
&i.Status,
|
||||
&i.ParentID,
|
||||
&i.Icon,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.PermissionCode,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysMenuByID = `-- name: GetSysMenuByID :one
|
||||
SELECT id, name, path, component, type, hidden, sort, status, parent_id, icon, created_at, updated_at
|
||||
FROM sys_menus
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysMenuByID(ctx context.Context, id int32) (SysMenu, error) {
|
||||
row := q.db.QueryRow(ctx, getSysMenuByID, id)
|
||||
var i SysMenu
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Path,
|
||||
&i.Component,
|
||||
&i.Type,
|
||||
&i.Hidden,
|
||||
&i.Sort,
|
||||
&i.Status,
|
||||
&i.ParentID,
|
||||
&i.Icon,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listSysMenus = `-- name: ListSysMenus :many
|
||||
SELECT m.id, m.name, m.path, m.component, m.type, m.hidden, m.sort, m.status, m.parent_id, m.icon, m.created_at, m.updated_at, p.code AS permission_code
|
||||
FROM sys_menus m
|
||||
LEFT JOIN sys_menu_permission mp ON m.id = mp.menu_id
|
||||
LEFT JOIN sys_permissions p ON mp.permission_id = p.id
|
||||
ORDER BY m.id
|
||||
LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type ListSysMenusParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
type ListSysMenusRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Component *string `json:"component"`
|
||||
Type int16 `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Sort *int32 `json:"sort"`
|
||||
Status int16 `json:"status"`
|
||||
ParentID *int32 `json:"parent_id"`
|
||||
Icon *int32 `json:"icon"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
PermissionCode *string `json:"permission_code"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListSysMenus(ctx context.Context, arg ListSysMenusParams) ([]ListSysMenusRow, error) {
|
||||
rows, err := q.db.Query(ctx, listSysMenus, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListSysMenusRow{}
|
||||
for rows.Next() {
|
||||
var i ListSysMenusRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Path,
|
||||
&i.Component,
|
||||
&i.Type,
|
||||
&i.Hidden,
|
||||
&i.Sort,
|
||||
&i.Status,
|
||||
&i.ParentID,
|
||||
&i.Icon,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.PermissionCode,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateSysMenu = `-- name: UpdateSysMenu :execrows
|
||||
UPDATE sys_menus
|
||||
SET name = coalesce($1, name),
|
||||
path = coalesce($2, path),
|
||||
component = coalesce($3, component),
|
||||
type = coalesce($4, type),
|
||||
hidden = coalesce($5, hidden),
|
||||
sort = coalesce($6, sort),
|
||||
status = coalesce($7, status),
|
||||
icon = coalesce($8, status),
|
||||
parent_id = CASE WHEN $9::boolean THEN $10 ELSE parent_id END
|
||||
WHERE id = $11
|
||||
`
|
||||
|
||||
type UpdateSysMenuParams struct {
|
||||
Name *string `json:"name"`
|
||||
Path *string `json:"path"`
|
||||
Component *string `json:"component"`
|
||||
Type *int16 `json:"type"`
|
||||
Hidden *bool `json:"hidden"`
|
||||
Sort *int32 `json:"sort"`
|
||||
Status *int16 `json:"status"`
|
||||
Icon *int32 `json:"icon"`
|
||||
UpdateParentID bool `json:"update_parent_id"`
|
||||
ParentID *int32 `json:"parent_id"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysMenu(ctx context.Context, arg UpdateSysMenuParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updateSysMenu,
|
||||
arg.Name,
|
||||
arg.Path,
|
||||
arg.Component,
|
||||
arg.Type,
|
||||
arg.Hidden,
|
||||
arg.Sort,
|
||||
arg.Status,
|
||||
arg.Icon,
|
||||
arg.UpdateParentID,
|
||||
arg.ParentID,
|
||||
arg.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const updateSysMenuPermissionCode = `-- name: UpdateSysMenuPermissionCode :exec
|
||||
UPDATE sys_permissions p
|
||||
SET code = coalesce($2, code)
|
||||
FROM sys_menu_permission mp
|
||||
WHERE p.id = mp.permission_id
|
||||
AND mp.menu_id = $1
|
||||
`
|
||||
|
||||
type UpdateSysMenuPermissionCodeParams struct {
|
||||
MenuID int32 `json:"menu_id"`
|
||||
Code *string `json:"code"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysMenuPermissionCode(ctx context.Context, arg UpdateSysMenuPermissionCodeParams) error {
|
||||
_, err := q.db.Exec(ctx, updateSysMenuPermissionCode, arg.MenuID, arg.Code)
|
||||
return err
|
||||
}
|
||||
54
internal/db/sqlc/sys_permission.sql.go
Normal file
54
internal/db/sqlc/sys_permission.sql.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: sys_permission.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const createSysPermission = `-- name: CreateSysPermission :one
|
||||
INSERT INTO sys_permissions(type,code)
|
||||
VALUES ($1,$2) RETURNING id
|
||||
`
|
||||
|
||||
type CreateSysPermissionParams struct {
|
||||
Type int16 `json:"type"`
|
||||
Code *string `json:"code"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysPermission(ctx context.Context, arg CreateSysPermissionParams) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, createSysPermission, arg.Type, arg.Code)
|
||||
var id int32
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const deleteSysPermission = `-- name: DeleteSysPermission :exec
|
||||
DELETE
|
||||
FROM sys_permissions
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysPermission(ctx context.Context, id int32) error {
|
||||
_, err := q.db.Exec(ctx, deleteSysPermission, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateSysPermission = `-- name: UpdateSysPermission :exec
|
||||
UPDATE sys_permissions
|
||||
SET code = $2
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateSysPermissionParams struct {
|
||||
ID int32 `json:"id"`
|
||||
Code *string `json:"code"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysPermission(ctx context.Context, arg UpdateSysPermissionParams) error {
|
||||
_, err := q.db.Exec(ctx, updateSysPermission, arg.ID, arg.Code)
|
||||
return err
|
||||
}
|
||||
321
internal/db/sqlc/sys_role.sql.go
Normal file
321
internal/db/sqlc/sys_role.sql.go
Normal file
@@ -0,0 +1,321 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: sys_role.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const countSysRoles = `-- name: CountSysRoles :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_roles
|
||||
`
|
||||
|
||||
func (q *Queries) CountSysRoles(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countSysRoles)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createSysRole = `-- name: CreateSysRole :exec
|
||||
INSERT INTO sys_roles (name, code)
|
||||
VALUES ($1, $2)
|
||||
`
|
||||
|
||||
type CreateSysRoleParams struct {
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysRole(ctx context.Context, arg CreateSysRoleParams) error {
|
||||
_, err := q.db.Exec(ctx, createSysRole, arg.Name, arg.Code)
|
||||
return err
|
||||
}
|
||||
|
||||
type CreateSysRolePermissionParams struct {
|
||||
RoleID int32 `json:"role_id"`
|
||||
PermissionID int32 `json:"permission_id"`
|
||||
}
|
||||
|
||||
const deleteSysRole = `-- name: DeleteSysRole :execrows
|
||||
DELETE
|
||||
FROM sys_roles
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysRole(ctx context.Context, id int32) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deleteSysRole, id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const deleteSysRolePermission = `-- name: DeleteSysRolePermission :exec
|
||||
DELETE
|
||||
FROM sys_role_permission rp USING sys_permissions p
|
||||
WHERE rp.permission_id = p.id
|
||||
AND p."type" = $2
|
||||
AND rp.role_id = $1
|
||||
`
|
||||
|
||||
type DeleteSysRolePermissionParams struct {
|
||||
RoleID int32 `json:"role_id"`
|
||||
Type int16 `json:"type"`
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteSysRolePermission(ctx context.Context, arg DeleteSysRolePermissionParams) error {
|
||||
_, err := q.db.Exec(ctx, deleteSysRolePermission, arg.RoleID, arg.Type)
|
||||
return err
|
||||
}
|
||||
|
||||
const existsSysRoleCode = `-- name: ExistsSysRoleCode :one
|
||||
SELECT EXISTS(SELECT 1
|
||||
FROM sys_roles
|
||||
WHERE code = $1
|
||||
AND (
|
||||
$2::integer IS NULL
|
||||
OR id <> $2::integer
|
||||
))
|
||||
`
|
||||
|
||||
type ExistsSysRoleCodeParams struct {
|
||||
Code string `json:"code"`
|
||||
ID *int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) ExistsSysRoleCode(ctx context.Context, arg ExistsSysRoleCodeParams) (bool, error) {
|
||||
row := q.db.QueryRow(ctx, existsSysRoleCode, arg.Code, arg.ID)
|
||||
var exists bool
|
||||
err := row.Scan(&exists)
|
||||
return exists, err
|
||||
}
|
||||
|
||||
const getAllSysRoles = `-- name: GetAllSysRoles :many
|
||||
SELECT id, name, code, created_at, updated_at
|
||||
from sys_roles
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllSysRoles(ctx context.Context) ([]SysRole, error) {
|
||||
rows, err := q.db.Query(ctx, getAllSysRoles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysRole{}
|
||||
for rows.Next() {
|
||||
var i SysRole
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysPermissionIdsByApiIDs = `-- name: GetSysPermissionIdsByApiIDs :many
|
||||
SELECT permission_id
|
||||
FROM sys_api_permission
|
||||
WHERE api_id = ANY ($1::int[])
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysPermissionIdsByApiIDs(ctx context.Context, dollar_1 []int32) ([]int32, error) {
|
||||
rows, err := q.db.Query(ctx, getSysPermissionIdsByApiIDs, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []int32{}
|
||||
for rows.Next() {
|
||||
var permission_id int32
|
||||
if err := rows.Scan(&permission_id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, permission_id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysPermissionIdsByMenuIDs = `-- name: GetSysPermissionIdsByMenuIDs :many
|
||||
SELECT permission_id
|
||||
FROM sys_menu_permission
|
||||
WHERE menu_id = ANY ($1::int[])
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysPermissionIdsByMenuIDs(ctx context.Context, dollar_1 []int32) ([]int32, error) {
|
||||
rows, err := q.db.Query(ctx, getSysPermissionIdsByMenuIDs, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []int32{}
|
||||
for rows.Next() {
|
||||
var permission_id int32
|
||||
if err := rows.Scan(&permission_id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, permission_id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysRoleApis = `-- name: GetSysRoleApis :many
|
||||
SELECT a.id, a."name"
|
||||
FROM sys_role_permission rp
|
||||
JOIN sys_api_permission ap ON ap.permission_id = rp.permission_id
|
||||
JOIN sys_apis a ON a.id = ap.api_id
|
||||
WHERE rp.role_id = $1
|
||||
`
|
||||
|
||||
type GetSysRoleApisRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSysRoleApis(ctx context.Context, roleID int32) ([]GetSysRoleApisRow, error) {
|
||||
rows, err := q.db.Query(ctx, getSysRoleApis, roleID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []GetSysRoleApisRow{}
|
||||
for rows.Next() {
|
||||
var i GetSysRoleApisRow
|
||||
if err := rows.Scan(&i.ID, &i.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysRoleByID = `-- name: GetSysRoleByID :one
|
||||
SELECT id, name, code, created_at, updated_at
|
||||
FROM sys_roles
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysRoleByID(ctx context.Context, id int32) (SysRole, error) {
|
||||
row := q.db.QueryRow(ctx, getSysRoleByID, id)
|
||||
var i SysRole
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSysRoleMenus = `-- name: GetSysRoleMenus :many
|
||||
SELECT m.id, m.name
|
||||
FROM sys_role_permission rp
|
||||
JOIN sys_menu_permission mp ON mp.permission_id = rp.permission_id
|
||||
JOIN sys_menus m ON m.id = mp.menu_id
|
||||
WHERE rp.role_id = $1
|
||||
`
|
||||
|
||||
type GetSysRoleMenusRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSysRoleMenus(ctx context.Context, roleID int32) ([]GetSysRoleMenusRow, error) {
|
||||
rows, err := q.db.Query(ctx, getSysRoleMenus, roleID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []GetSysRoleMenusRow{}
|
||||
for rows.Next() {
|
||||
var i GetSysRoleMenusRow
|
||||
if err := rows.Scan(&i.ID, &i.Name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listSysRoles = `-- name: ListSysRoles :many
|
||||
SELECT id, name, code, created_at, updated_at
|
||||
FROM sys_roles
|
||||
ORDER BY id
|
||||
LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type ListSysRolesParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListSysRoles(ctx context.Context, arg ListSysRolesParams) ([]SysRole, error) {
|
||||
rows, err := q.db.Query(ctx, listSysRoles, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysRole{}
|
||||
for rows.Next() {
|
||||
var i SysRole
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateSysRole = `-- name: UpdateSysRole :execrows
|
||||
UPDATE sys_roles
|
||||
SET name = coalesce($1, name)
|
||||
WHERE id = $2
|
||||
`
|
||||
|
||||
type UpdateSysRoleParams struct {
|
||||
Name *string `json:"name"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysRole(ctx context.Context, arg UpdateSysRoleParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updateSysRole, arg.Name, arg.ID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
426
internal/db/sqlc/sys_user.sql.go
Normal file
426
internal/db/sqlc/sys_user.sql.go
Normal file
@@ -0,0 +1,426 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: sys_user.sql
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const clearSysUserRoles = `-- name: ClearSysUserRoles :exec
|
||||
DELETE
|
||||
FROM sys_user_role
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ClearSysUserRoles(ctx context.Context, userID int32) error {
|
||||
_, err := q.db.Exec(ctx, clearSysUserRoles, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
const countSysUsers = `-- name: CountSysUsers :one
|
||||
SELECT COUNT(*)
|
||||
FROM sys_users
|
||||
`
|
||||
|
||||
func (q *Queries) CountSysUsers(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countSysUsers)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const createSysUser = `-- name: CreateSysUser :exec
|
||||
INSERT INTO sys_users (account, username, password_hash, avatar_id)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
`
|
||||
|
||||
type CreateSysUserParams struct {
|
||||
Account string `json:"account"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysUser(ctx context.Context, arg CreateSysUserParams) error {
|
||||
_, err := q.db.Exec(ctx, createSysUser,
|
||||
arg.Account,
|
||||
arg.Username,
|
||||
arg.PasswordHash,
|
||||
arg.AvatarID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const createSysUserRole = `-- name: CreateSysUserRole :exec
|
||||
INSERT INTO sys_user_role (user_id, role_id)
|
||||
VALUES ($1, $2)
|
||||
`
|
||||
|
||||
type CreateSysUserRoleParams struct {
|
||||
UserID int32 `json:"user_id"`
|
||||
RoleID int32 `json:"role_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateSysUserRole(ctx context.Context, arg CreateSysUserRoleParams) error {
|
||||
_, err := q.db.Exec(ctx, createSysUserRole, arg.UserID, arg.RoleID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteSysUser = `-- name: DeleteSysUser :execrows
|
||||
DELETE
|
||||
FROM sys_users
|
||||
WHERE id = $1
|
||||
AND id <> 1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteSysUser(ctx context.Context, id int32) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, deleteSysUser, id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const getSysAdminMenus = `-- name: GetSysAdminMenus :many
|
||||
SELECT id, name, path, component, type, hidden, sort, status, parent_id, icon, created_at, updated_at
|
||||
FROM sys_menus
|
||||
ORDER BY sort, id
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysAdminMenus(ctx context.Context) ([]SysMenu, error) {
|
||||
rows, err := q.db.Query(ctx, getSysAdminMenus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysMenu{}
|
||||
for rows.Next() {
|
||||
var i SysMenu
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Path,
|
||||
&i.Component,
|
||||
&i.Type,
|
||||
&i.Hidden,
|
||||
&i.Sort,
|
||||
&i.Status,
|
||||
&i.ParentID,
|
||||
&i.Icon,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysUserApis = `-- name: GetSysUserApis :many
|
||||
SELECT DISTINCT a.id,
|
||||
a.PATH,
|
||||
a.METHOD
|
||||
FROM sys_users u
|
||||
JOIN sys_user_role ur ON u.id = ur.user_id
|
||||
JOIN sys_role_permission rp ON rp.role_id = ur.role_id
|
||||
JOIN sys_permissions p ON p.id = rp.permission_id
|
||||
AND p.TYPE = 1
|
||||
JOIN sys_api_permission ap ON ap.permission_id = p.id
|
||||
JOIN sys_apis a ON a.id = ap.api_id
|
||||
WHERE u.id = $1
|
||||
`
|
||||
|
||||
type GetSysUserApisRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSysUserApis(ctx context.Context, id int32) ([]GetSysUserApisRow, error) {
|
||||
rows, err := q.db.Query(ctx, getSysUserApis, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []GetSysUserApisRow{}
|
||||
for rows.Next() {
|
||||
var i GetSysUserApisRow
|
||||
if err := rows.Scan(&i.ID, &i.Path, &i.Method); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysUserByAccount = `-- name: GetSysUserByAccount :one
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.password_hash,
|
||||
u.avatar_id,
|
||||
f.file_path AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
WHERE u.account = $1
|
||||
`
|
||||
|
||||
type GetSysUserByAccountRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Account string `json:"account"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
AvatarUrl *string `json:"avatar_url"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSysUserByAccount(ctx context.Context, account string) (GetSysUserByAccountRow, error) {
|
||||
row := q.db.QueryRow(ctx, getSysUserByAccount, account)
|
||||
var i GetSysUserByAccountRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Account,
|
||||
&i.Username,
|
||||
&i.PasswordHash,
|
||||
&i.AvatarID,
|
||||
&i.AvatarUrl,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSysUserByID = `-- name: GetSysUserByID :one
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.avatar_id,
|
||||
f.file_path AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
WHERE u.id = $1
|
||||
`
|
||||
|
||||
type GetSysUserByIDRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Account string `json:"account"`
|
||||
Username string `json:"username"`
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
AvatarUrl *string `json:"avatar_url"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetSysUserByID(ctx context.Context, id int32) (GetSysUserByIDRow, error) {
|
||||
row := q.db.QueryRow(ctx, getSysUserByID, id)
|
||||
var i GetSysUserByIDRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Account,
|
||||
&i.Username,
|
||||
&i.AvatarID,
|
||||
&i.AvatarUrl,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSysUserMenus = `-- name: GetSysUserMenus :many
|
||||
SELECT DISTINCT m.id, m.name, m.path, m.component, m.type, m.hidden, m.sort, m.status, m.parent_id, m.icon, m.created_at, m.updated_at
|
||||
FROM sys_users u
|
||||
JOIN sys_user_role ur ON ur.user_id = u.id
|
||||
JOIN sys_roles r ON r.id = ur.role_id
|
||||
JOIN sys_role_permission rp ON rp.role_id = r.id
|
||||
JOIN sys_permissions p ON p.id = rp.permission_id
|
||||
JOIN sys_menu_permission mp ON mp.permission_id = p.id
|
||||
JOIN sys_menus m ON m.id = mp.menu_id
|
||||
WHERE u.id = $1
|
||||
ORDER BY m.sort, m.id
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysUserMenus(ctx context.Context, id int32) ([]SysMenu, error) {
|
||||
rows, err := q.db.Query(ctx, getSysUserMenus, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysMenu{}
|
||||
for rows.Next() {
|
||||
var i SysMenu
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Path,
|
||||
&i.Component,
|
||||
&i.Type,
|
||||
&i.Hidden,
|
||||
&i.Sort,
|
||||
&i.Status,
|
||||
&i.ParentID,
|
||||
&i.Icon,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getSysUserRoles = `-- name: GetSysUserRoles :many
|
||||
SELECT r.id, r.name, r.code, r.created_at, r.updated_at
|
||||
FROM sys_roles r
|
||||
JOIN sys_user_role ur ON r.id = ur.role_id
|
||||
WHERE ur.user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSysUserRoles(ctx context.Context, userID int32) ([]SysRole, error) {
|
||||
rows, err := q.db.Query(ctx, getSysUserRoles, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []SysRole{}
|
||||
for rows.Next() {
|
||||
var i SysRole
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Code,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listSysUsers = `-- name: ListSysUsers :many
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.avatar_id,
|
||||
f.file_path AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
ORDER BY u.id
|
||||
LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type ListSysUsersParams struct {
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
}
|
||||
|
||||
type ListSysUsersRow struct {
|
||||
ID int32 `json:"id"`
|
||||
Account string `json:"account"`
|
||||
Username string `json:"username"`
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
AvatarUrl *string `json:"avatar_url"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListSysUsers(ctx context.Context, arg ListSysUsersParams) ([]ListSysUsersRow, error) {
|
||||
rows, err := q.db.Query(ctx, listSysUsers, arg.Limit, arg.Offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := []ListSysUsersRow{}
|
||||
for rows.Next() {
|
||||
var i ListSysUsersRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Account,
|
||||
&i.Username,
|
||||
&i.AvatarID,
|
||||
&i.AvatarUrl,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateSysUser = `-- name: UpdateSysUser :execrows
|
||||
UPDATE sys_users
|
||||
SET username = coalesce($1, username),
|
||||
avatar_id = CASE WHEN $2::boolean THEN $3 ELSE avatar_id END
|
||||
WHERE id = $4
|
||||
`
|
||||
|
||||
type UpdateSysUserParams struct {
|
||||
Username *string `json:"username"`
|
||||
UpdateAvatarID bool `json:"update_avatar_id"`
|
||||
AvatarID *int32 `json:"avatar_id"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysUser(ctx context.Context, arg UpdateSysUserParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updateSysUser,
|
||||
arg.Username,
|
||||
arg.UpdateAvatarID,
|
||||
arg.AvatarID,
|
||||
arg.ID,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const updateSysUserPassword = `-- name: UpdateSysUserPassword :execrows
|
||||
UPDATE sys_users
|
||||
SET password_hash = $2
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateSysUserPasswordParams struct {
|
||||
ID int32 `json:"id"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSysUserPassword(ctx context.Context, arg UpdateSysUserPasswordParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, updateSysUserPassword, arg.ID, arg.PasswordHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
Reference in New Issue
Block a user