feat: release v1.0.0

This commit is contained in:
2026-07-29 22:10:36 +08:00
parent ee9f50b859
commit c903b5a6b5
81 changed files with 2776 additions and 1044 deletions

View File

@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"server/internal/config"
"server/internal/db/sqlc"
"github.com/jackc/pgx/v5/pgxpool"
"go.uber.org/fx"
@@ -42,7 +41,3 @@ func NewDB(lc fx.Lifecycle, cfg *config.Config) (*pgxpool.Pool, error) {
return pool, nil
}
func NewQueries(pool *pgxpool.Pool) *db.Queries {
return db.New(pool)
}

View File

@@ -0,0 +1,5 @@
ALTER TABLE sys_users
DROP COLUMN IF EXISTS status;
ALTER TABLE sys_roles
DROP COLUMN IF EXISTS status;

View File

@@ -0,0 +1,9 @@
ALTER TABLE sys_users
ADD COLUMN IF NOT EXISTS status SMALLINT NOT NULL DEFAULT 1;
ALTER TABLE sys_roles
ADD COLUMN IF NOT EXISTS status SMALLINT NOT NULL DEFAULT 1;
COMMENT ON COLUMN sys_users.status IS '用户状态0禁用1启用';
COMMENT ON COLUMN sys_roles.status IS '角色0禁用1启用';

View File

@@ -0,0 +1,6 @@
ALTER TABLE categories
DROP COLUMN IF EXISTS sort;
DROP TABLE IF EXISTS tags;
DROP TABLE IF EXISTS post_tag;

View File

@@ -0,0 +1,38 @@
-- 新增字段
ALTER TABLE categories
ADD COLUMN IF NOT EXISTS sort INTEGER DEFAULT 0;
COMMENT ON COLUMN categories.sort IS '分类排序';
-- tag表
CREATE TABLE tags
(
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
code TEXT UNIQUE NOT NULL,
sort INTEGER DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ
);
CREATE TRIGGER update_tags_updated_at
BEFORE UPDATE
ON tags
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
COMMENT ON COLUMN tags.id IS '标签ID';
COMMENT ON COLUMN tags.name IS '标签名称';
COMMENT ON COLUMN tags.code IS '标签编码';
COMMENT ON COLUMN tags.sort IS '标签排序';
-- 关联表
CREATE TABLE post_tag
(
post_id INT NOT NULL,
tag_id INT NOT NULL,
PRIMARY KEY (post_id, tag_id)
);
COMMENT ON COLUMN post_tag.post_id IS '文章ID';
COMMENT ON COLUMN post_tag.tag_id IS '标签id';

View File

@@ -0,0 +1,10 @@
ALTER TABLE sys_menus
DROP CONSTRAINT IF EXISTS sys_menus_path_required_check;
DROP INDEX IF EXISTS sys_menus_path_unique_idx;
ALTER TABLE sys_menus
ADD CONSTRAINT sys_menus_path_key UNIQUE (path);
ALTER TABLE sys_menus
ALTER COLUMN path SET NOT NULL;

View File

@@ -0,0 +1,18 @@
ALTER TABLE sys_menus
ALTER COLUMN path DROP NOT NULL;
ALTER TABLE sys_menus
DROP CONSTRAINT IF EXISTS sys_menus_path_key;
DROP INDEX IF EXISTS sys_menus_path_unique_idx;
CREATE UNIQUE INDEX sys_menus_path_unique_idx
ON sys_menus (path)
WHERE type IN (0, 1);
ALTER TABLE sys_menus
DROP CONSTRAINT IF EXISTS sys_menus_path_required_check;
ALTER TABLE sys_menus
ADD CONSTRAINT sys_menus_path_required_check
CHECK (type = 2 OR path IS NOT NULL);

View File

@@ -1,12 +1,12 @@
-- name: CreateCategory :exec
INSERT INTO categories(name, code)
VALUES ($1, $2);
INSERT INTO categories(name, code, sort)
VALUES ($1, $2, $3);
-- name: ListCategories :many
SELECT *
FROM categories
ORDER BY id LIMIT $1
OFFSET $2;
ORDER BY sort DESC, id
LIMIT $1 OFFSET $2;
-- name: CountCategories :one
SELECT COUNT(*)
@@ -14,17 +14,14 @@ FROM categories;
-- name: ListAllCategories :many
SELECT *
FROM categories;
-- name: GetCategoryById :one
SELECT *
FROM categories
WHERE id = $1;
ORDER BY sort DESC, id;
-- name: UpdateCategory :execrows
UPDATE categories
SET name = coalesce(sqlc.narg('name'), name),
code = coalesce(sqlc.narg('code'), code)
code = coalesce(sqlc.narg('code'), code),
sort = coalesce(sqlc.narg('sort'), sort)
WHERE id = sqlc.arg('id');
-- name: DeleteCategory :execrows
@@ -36,7 +33,12 @@ WHERE id = $1;
INSERT INTO post_category(post_id, category_id)
VALUES ($1, $2);
-- name: DeletePostCategory :exec
-- name: DeletePostCategoryByPostID :exec
DELETE
FROM post_category
WHERE post_id = $1;
WHERE post_id = $1;
-- name: DeletePostCategoryByCategoryID :exec
DELETE
FROM post_category
WHERE category_id = $1;

View File

@@ -18,18 +18,46 @@ WITH paginated_posts AS (
updated_at
FROM posts
ORDER BY sort DESC, published_at DESC, id DESC
LIMIT $1 OFFSET $2)
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
COALESCE(ps.view, 0) AS view,
COALESCE(
jsonb_agg(
jsonb_build_object(
'id', t.id,
'name', t.name,
'code', t.code
)
ORDER BY t.sort DESC, t.id
) FILTER (WHERE t.id IS NOT NULL),
'[]'::jsonb
) AS tags
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
LEFT JOIN post_tag pt ON pt.post_id = p.id
LEFT JOIN tags t ON t.id = pt.tag_id
GROUP BY 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,
c.name,
c.id,
ps.view
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC;
-- name: CountPosts :one
@@ -40,12 +68,21 @@ FROM posts;
SELECT p.*,
f.file_path AS cover,
c.name AS category_name,
c.id AS category_id
c.id AS category_id,
COALESCE(
array_agg(pt.tag_id ORDER BY pt.tag_id) FILTER (WHERE pt.tag_id IS NOT NULL),
ARRAY[]::integer[]
) AS tags
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
LEFT JOIN post_tag pt ON pt.post_id = p.id
WHERE p.id = $1
GROUP BY p.id,
f.file_path,
c.name,
c.id
LIMIT 1;
-- name: UpdatePost :execrows
@@ -98,12 +135,36 @@ SELECT p.*,
f.file_path AS cover,
c.name AS category_name,
c.id AS category_id,
COALESCE(ps.view, 0) AS view
COALESCE(ps.view, 0) AS view,
COALESCE(
jsonb_agg(
jsonb_build_object(
'id', t.id,
'name', t.name,
'code', t.code
)
ORDER BY t.sort DESC, t.id
) FILTER (WHERE t.id IS NOT NULL),
'[]'::jsonb
) AS tags
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
LEFT JOIN post_tag pt ON pt.post_id = p.id
LEFT JOIN tags t ON t.id = pt.tag_id
GROUP BY p.id,
p.title,
p.cover_id,
p.slug,
p.summary,
p.sort,
p.published_at,
f.file_path,
c.name,
c.id,
ps.view
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC;
-- name: CountPublishedPosts :one
@@ -142,4 +203,6 @@ FROM
AND p.published_at < NOW()
GROUP BY
c.id,
c.name;
c.sort,
c.name
ORDER BY c.sort DESC, c.id;

View File

@@ -6,12 +6,16 @@ RETURNING id;
-- name: GetSysApis :many
SELECT *
FROM sys_apis
WHERE (sqlc.arg('group_name')::text = '' OR group_name ILIKE '%' || sqlc.arg('group_name') || '%')
AND (sqlc.arg('method')::text = '' OR method = sqlc.arg('method'))
ORDER BY id
LIMIT $1 OFFSET $2;
-- name: CountSysApis :one
SELECT COUNT(*)
FROM sys_apis;
FROM sys_apis
WHERE (sqlc.arg('group_name')::text = '' OR group_name ILIKE '%' || sqlc.arg('group_name') || '%')
AND (sqlc.arg('method')::text = '' OR method = sqlc.arg('method'));
-- name: GetSysApiByID :one
SELECT *
@@ -41,13 +45,6 @@ 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;

View File

@@ -38,7 +38,7 @@ SET name = coalesce(sqlc.narg('name'), name),
hidden = coalesce(sqlc.narg('hidden'), hidden),
sort = coalesce(sqlc.narg('sort'), sort),
status = coalesce(sqlc.narg('status'), status),
icon = coalesce(sqlc.narg('icon'), status),
icon = CASE WHEN @update_icon::boolean THEN @icon ELSE icon END,
parent_id = CASE WHEN @update_parent_id::boolean THEN @parent_id ELSE parent_id END
WHERE id = sqlc.arg('id');

View File

@@ -12,3 +12,12 @@ DELETE
FROM sys_permissions
WHERE id = $1;
-- name: GetSysPermissionIDBySysApiID :one
SELECT permission_id
FROM sys_api_permission
WHERE api_id = $1;
-- name: GetSysPermissionIDBySysMenuID :one
SELECT permission_id
FROM sys_menu_permission
WHERE menu_id = $1;

View File

@@ -1,6 +1,6 @@
-- name: CreateSysRole :exec
INSERT INTO sys_roles (name, code)
VALUES ($1, $2);
INSERT INTO sys_roles (name, code, status)
VALUES ($1, $2, $3);
-- name: ListSysRoles :many
SELECT *
@@ -28,7 +28,8 @@ SELECT EXISTS(SELECT 1
-- name: UpdateSysRole :execrows
UPDATE sys_roles
SET name = coalesce(sqlc.narg('name'), name)
SET name = coalesce(sqlc.narg('name'), name),
status = coalesce(sqlc.narg('status'), status)
WHERE id = sqlc.arg('id');
-- name: DeleteSysRole :execrows
@@ -68,9 +69,24 @@ FROM sys_role_permission rp
JOIN sys_apis a ON a.id = ap.api_id
WHERE rp.role_id = $1;
-- name: DeleteSysRolePermission :exec
-- name: DeleteSysRolePermissionByType :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;
AND rp.role_id = $1
AND p."type" = $2;
-- name: DeleteSysRolePermissionByRoleID :exec
DELETE
FROM sys_role_permission
WHERE role_id = $1;
-- name: DeleteSysRolePermissionByPermissionID :exec
DELETE
FROM sys_role_permission
WHERE permission_id = $1;
-- name: DeleteSysUserRoleByRoleID :exec
DELETE
FROM sys_user_role
WHERE role_id = $1;

View File

@@ -1,12 +1,20 @@
-- name: CreateSysUser :exec
INSERT INTO sys_users (account, username, password_hash, avatar_id)
VALUES ($1, $2, $3, $4);
INSERT INTO sys_users (account, username, password_hash, status, avatar_id)
VALUES ($1, $2, $3, $4, $5);
-- name: GetActiveSysUserByID :one
-- 场景:用户登录、获取个人信息、刷新 Token严格校验 status = 1
SELECT id, account, username, status
FROM sys_users
WHERE id = $1
AND status = 1;
-- name: GetSysUserByID :one
SELECT u.id,
u.account,
u.username,
u.avatar_id,
u.status,
f.file_path AS avatar_url,
u.created_at,
u.updated_at
@@ -19,6 +27,7 @@ SELECT u.id,
u.account,
u.username,
u.password_hash,
u.status,
u.avatar_id,
f.file_path AS avatar_url,
u.created_at,
@@ -31,22 +40,26 @@ WHERE u.account = $1;
SELECT u.id,
u.account,
u.username,
u.status,
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 (sqlc.arg('username')::text = '' OR u.username ILIKE '%' || sqlc.arg('username') || '%')
ORDER BY u.id
LIMIT $1 OFFSET $2;
-- name: CountSysUsers :one
SELECT COUNT(*)
FROM sys_users;
FROM sys_users
WHERE (sqlc.arg('username')::text = '' OR username ILIKE '%' || sqlc.arg('username') || '%');
-- name: UpdateSysUser :execrows
UPDATE sys_users
SET username = coalesce(sqlc.narg('username'), username),
status = coalesce(sqlc.narg('status'), status),
avatar_id = CASE WHEN @update_avatar_id::boolean THEN @avatar_id ELSE avatar_id END
WHERE id = sqlc.arg('id');
@@ -66,7 +79,7 @@ DELETE
FROM sys_user_role
WHERE user_id = $1;
-- name: CreateSysUserRole :exec
-- name: CreateSysUserRole :copyfrom
INSERT INTO sys_user_role (user_id, role_id)
VALUES ($1, $2);
@@ -79,19 +92,44 @@ WHERE ur.user_id = $1;
-- name: GetSysAdminMenus :many
SELECT *
FROM sys_menus
WHERE status = 1
AND type <> 2
ORDER BY sort, id;
-- name: GetSysAdminPermissions :many
SELECT code
FROM sys_permissions
WHERE type = 0;
-- 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_menu_permission mp ON mp.permission_id = rp.permission_id
JOIN sys_menus m ON m.id = mp.menu_id
WHERE u.id = $1
AND u.status = 1
AND r.status = 1
AND m.status = 1
AND m.type <> 2
ORDER BY m.sort, m.id;
-- name: GetSysUserPermissions :many
SELECT DISTINCT p.code
FROM sys_users u
JOIN sys_user_role ur ON u.id = ur.user_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;
AND u.status = 1
AND r.status = 1
AND m.status = 1
AND p."type" = 0;
-- name: GetSysUserApis :many
SELECT DISTINCT a.id,
@@ -99,9 +137,10 @@ SELECT DISTINCT a.id,
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_roles r ON r.id = ur.role_id
JOIN sys_role_permission rp ON rp.role_id = r.id
JOIN sys_api_permission ap ON ap.permission_id = rp.permission_id
JOIN sys_apis a ON a.id = ap.api_id
WHERE u.id = $1;
WHERE u.id = $1
AND u.status = 1
AND r.status = 1;

View File

@@ -0,0 +1,44 @@
-- name: ListTags :many
SELECT *
FROM tags
ORDER BY sort DESC, id
LIMIT $1 OFFSET $2;
-- name: CountTags :one
SELECT COUNT(*)
FROM tags;
-- name: ListAllTags :many
SELECT *
FROM tags
ORDER BY sort DESC, id;
-- name: CreateTag :exec
INSERT INTO tags(name, code, sort)
VALUES ($1, $2, $3);
-- name: UpdateTag :execrows
UPDATE tags
SET name = coalesce(sqlc.narg('name'), name),
code = coalesce(sqlc.narg('code'), code),
sort = coalesce(sqlc.narg('sort'), sort)
WHERE id = sqlc.arg('id');
-- name: DeleteTag :execrows
DELETE
FROM tags
WHERE id = $1;
-- name: CreatePostTag :copyfrom
INSERT INTO post_tag(post_id, tag_id)
values ($1, $2);
-- name: DeletePostTagByPostID :exec
DELETE
FROM post_tag
WHERE post_id = $1;
-- name: DeletePostTagByTagID :exec
DELETE
FROM post_tag
WHERE tag_id = $1;

27
internal/db/redis.go Normal file
View File

@@ -0,0 +1,27 @@
package db
import (
"context"
"log/slog"
"github.com/redis/go-redis/v9"
"server/internal/config"
)
func NewRedisClient(cfg *config.Config) (*redis.Client, error) {
client := redis.NewClient(&redis.Options{
Addr: cfg.Redis.Addr,
Password: cfg.Redis.Password,
DB: cfg.Redis.DB,
})
if err := client.Ping(context.Background()).Err(); err != nil {
slog.Error("failed to connect redis", "error", err)
return nil, err
}
slog.Info("redis connected", "addr", cfg.Redis.Addr)
return client, nil
}

View File

@@ -4,6 +4,7 @@ CREATE TABLE categories
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
code TEXT UNIQUE NOT NULL,
sort INTEGER DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ
);
@@ -16,4 +17,5 @@ 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 '分类编码';
COMMENT ON COLUMN categories.code IS '分类编码';
COMMENT ON COLUMN categories.sort IS '分类排序';

View File

@@ -0,0 +1,9 @@
CREATE TABLE post_tag
(
post_id INT NOT NULL,
tag_id INT NOT NULL,
PRIMARY KEY (post_id, tag_id)
);
COMMENT ON COLUMN post_tag.post_id IS '文章ID';
COMMENT ON COLUMN post_tag.tag_id IS '标签id';

View File

@@ -2,7 +2,7 @@ CREATE TABLE sys_menus
(
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
path TEXT NOT NULL,
path TEXT,
component TEXT,
type SMALLINT NOT NULL,
hidden BOOLEAN DEFAULT FALSE,
@@ -17,6 +17,9 @@ CREATE TABLE sys_menus
CHECK (status IN (0, 1))
);
CREATE UNIQUE INDEX sys_menus_path_unique_idx
ON sys_menus (path)
WHERE type IN (0, 1);
CREATE TRIGGER update_sys_menus_updated_at
BEFORE UPDATE

View File

@@ -3,7 +3,7 @@ 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(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ,
CONSTRAINT unique_type_code UNIQUE (type, code)

View File

@@ -3,8 +3,11 @@ CREATE TABLE sys_roles
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
code TEXT NOT NULL UNIQUE,
status SMALLINT NOT NULL DEFAULT 1,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ
updated_at TIMESTAMPTZ,
CHECK (status IN (0, 1))
);
CREATE TRIGGER update_sys_roles_updated_at
@@ -16,5 +19,6 @@ 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.status IS '角色状态 0:禁用 1:启用';
COMMENT ON COLUMN sys_roles.created_at IS '创建时间';
COMMENT ON COLUMN sys_roles.updated_at IS '更新时间';

View File

@@ -1,12 +1,15 @@
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,
account TEXT NOT NULL UNIQUE,
username TEXT NOT NULL,
password_hash TEXT NOT NULL,
status SMALLINT NOT NULL DEFAULT 1,
avatar_id INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ
updated_at TIMESTAMPTZ,
CHECK (status IN (0, 1))
);
CREATE INDEX idx_sys_users_account ON sys_users (account);
@@ -22,6 +25,7 @@ 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.status IS '用户状态 0:禁用 1:启用';
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 '更新时间';

View File

@@ -0,0 +1,20 @@
CREATE TABLE tags
(
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name TEXT NOT NULL,
code TEXT UNIQUE NOT NULL,
sort INTEGER DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ
);
CREATE TRIGGER update_tags_updated_at
BEFORE UPDATE
ON tags
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
COMMENT ON COLUMN tags.id IS '标签ID';
COMMENT ON COLUMN tags.name IS '标签名称';
COMMENT ON COLUMN tags.code IS '标签编码';
COMMENT ON COLUMN tags.sort IS '标签排序';

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: category.sql
// source: categories.sql
package db
package sqlc
import (
"context"
@@ -22,17 +22,18 @@ func (q *Queries) CountCategories(ctx context.Context) (int64, error) {
}
const createCategory = `-- name: CreateCategory :exec
INSERT INTO categories(name, code)
VALUES ($1, $2)
INSERT INTO categories(name, code, sort)
VALUES ($1, $2, $3)
`
type CreateCategoryParams struct {
Name string `json:"name"`
Code string `json:"code"`
Sort *int32 `json:"sort"`
}
func (q *Queries) CreateCategory(ctx context.Context, arg CreateCategoryParams) error {
_, err := q.db.Exec(ctx, createCategory, arg.Name, arg.Code)
_, err := q.db.Exec(ctx, createCategory, arg.Name, arg.Code, arg.Sort)
return err
}
@@ -65,39 +66,32 @@ func (q *Queries) DeleteCategory(ctx context.Context, id int32) (int64, error) {
return result.RowsAffected(), nil
}
const deletePostCategory = `-- name: DeletePostCategory :exec
const deletePostCategoryByCategoryID = `-- name: DeletePostCategoryByCategoryID :exec
DELETE
FROM post_category
WHERE category_id = $1
`
func (q *Queries) DeletePostCategoryByCategoryID(ctx context.Context, categoryID int32) error {
_, err := q.db.Exec(ctx, deletePostCategoryByCategoryID, categoryID)
return err
}
const deletePostCategoryByPostID = `-- name: DeletePostCategoryByPostID :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)
func (q *Queries) DeletePostCategoryByPostID(ctx context.Context, postID int32) error {
_, err := q.db.Exec(ctx, deletePostCategoryByPostID, 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
SELECT id, name, code, sort, created_at, updated_at
FROM categories
ORDER BY sort DESC, id
`
func (q *Queries) ListAllCategories(ctx context.Context) ([]Category, error) {
@@ -113,6 +107,7 @@ func (q *Queries) ListAllCategories(ctx context.Context) ([]Category, error) {
&i.ID,
&i.Name,
&i.Code,
&i.Sort,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
@@ -127,10 +122,10 @@ func (q *Queries) ListAllCategories(ctx context.Context) ([]Category, error) {
}
const listCategories = `-- name: ListCategories :many
SELECT id, name, code, created_at, updated_at
SELECT id, name, code, sort, created_at, updated_at
FROM categories
ORDER BY id LIMIT $1
OFFSET $2
ORDER BY sort DESC, id
LIMIT $1 OFFSET $2
`
type ListCategoriesParams struct {
@@ -151,6 +146,7 @@ func (q *Queries) ListCategories(ctx context.Context, arg ListCategoriesParams)
&i.ID,
&i.Name,
&i.Code,
&i.Sort,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
@@ -167,18 +163,25 @@ func (q *Queries) ListCategories(ctx context.Context, arg ListCategoriesParams)
const updateCategory = `-- name: UpdateCategory :execrows
UPDATE categories
SET name = coalesce($1, name),
code = coalesce($2, code)
WHERE id = $3
code = coalesce($2, code),
sort = coalesce($3, sort)
WHERE id = $4
`
type UpdateCategoryParams struct {
Name *string `json:"name"`
Code *string `json:"code"`
Sort *int32 `json:"sort"`
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)
result, err := q.db.Exec(ctx, updateCategory,
arg.Name,
arg.Code,
arg.Sort,
arg.ID,
)
if err != nil {
return 0, err
}

View File

@@ -3,12 +3,45 @@
// sqlc v1.31.1
// source: copyfrom.go
package db
package sqlc
import (
"context"
)
// iteratorForCreatePostTag implements pgx.CopyFromSource.
type iteratorForCreatePostTag struct {
rows []CreatePostTagParams
skippedFirstNextCall bool
}
func (r *iteratorForCreatePostTag) 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 iteratorForCreatePostTag) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].PostID,
r.rows[0].TagID,
}, nil
}
func (r iteratorForCreatePostTag) Err() error {
return nil
}
func (q *Queries) CreatePostTag(ctx context.Context, arg []CreatePostTagParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"post_tag"}, []string{"post_id", "tag_id"}, &iteratorForCreatePostTag{rows: arg})
}
// iteratorForCreateSysRolePermission implements pgx.CopyFromSource.
type iteratorForCreateSysRolePermission struct {
rows []CreateSysRolePermissionParams
@@ -41,3 +74,36 @@ func (r iteratorForCreateSysRolePermission) Err() error {
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})
}
// iteratorForCreateSysUserRole implements pgx.CopyFromSource.
type iteratorForCreateSysUserRole struct {
rows []CreateSysUserRoleParams
skippedFirstNextCall bool
}
func (r *iteratorForCreateSysUserRole) 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 iteratorForCreateSysUserRole) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].UserID,
r.rows[0].RoleID,
}, nil
}
func (r iteratorForCreateSysUserRole) Err() error {
return nil
}
func (q *Queries) CreateSysUserRole(ctx context.Context, arg []CreateSysUserRoleParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"sys_user_role"}, []string{"user_id", "role_id"}, &iteratorForCreateSysUserRole{rows: arg})
}

View File

@@ -2,7 +2,7 @@
// versions:
// sqlc v1.31.1
package db
package sqlc
import (
"context"

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: file.sql
// source: files.sql
package db
package sqlc
import (
"context"

View File

@@ -2,7 +2,7 @@
// versions:
// sqlc v1.31.1
package db
package sqlc
import (
"net/netip"
@@ -15,7 +15,9 @@ type Category struct {
// 分类名称
Name string `json:"name"`
// 分类编码
Code string `json:"code"`
Code string `json:"code"`
// 分类排序
Sort *int32 `json:"sort"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
}
@@ -80,6 +82,13 @@ type PostStat struct {
View int32 `json:"view"`
}
type PostTag struct {
// 文章ID
PostID int32 `json:"post_id"`
// 标签id
TagID int32 `json:"tag_id"`
}
type PostViewer struct {
// 文章id
PostID int32 `json:"post_id"`
@@ -121,7 +130,7 @@ type SysMenu struct {
// 菜单名称
Name string `json:"name"`
// 菜单路径
Path string `json:"path"`
Path *string `json:"path"`
// 组件路径
Component *string `json:"component"`
// 菜单类型 0: 目录 1: 菜单 2: button
@@ -156,7 +165,7 @@ type SysPermission struct {
Code *string `json:"code"`
Type int16 `json:"type"`
// 创建时间
CreatedAt interface{} `json:"created_at"`
CreatedAt time.Time `json:"created_at"`
// 更新时间
UpdatedAt *time.Time `json:"updated_at"`
}
@@ -168,6 +177,8 @@ type SysRole struct {
Name string `json:"name"`
// 角色编码,唯一
Code string `json:"code"`
// 角色状态 0:禁用 1:启用
Status int16 `json:"status"`
// 创建时间
CreatedAt time.Time `json:"created_at"`
// 更新时间
@@ -190,6 +201,8 @@ type SysUser struct {
Username string `json:"username"`
// hash密码
PasswordHash string `json:"password_hash"`
// 用户状态 0:禁用 1:启用
Status int16 `json:"status"`
// 头像文件id
AvatarID *int32 `json:"avatar_id"`
// 创建时间
@@ -204,3 +217,16 @@ type SysUserRole struct {
// 角色ID
RoleID int32 `json:"role_id"`
}
type Tag struct {
// 标签ID
ID int32 `json:"id"`
// 标签名称
Name string `json:"name"`
// 标签编码
Code string `json:"code"`
// 标签排序
Sort *int32 `json:"sort"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
}

View File

@@ -3,7 +3,7 @@
// sqlc v1.31.1
// source: post.sql
package db
package sqlc
import (
"context"
@@ -87,30 +87,40 @@ 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
c.id AS category_id,
COALESCE(
array_agg(pt.tag_id ORDER BY pt.tag_id) FILTER (WHERE pt.tag_id IS NOT NULL),
ARRAY[]::integer[]
) AS tags
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
LEFT JOIN post_tag pt ON pt.post_id = p.id
WHERE p.id = $1
GROUP BY p.id,
f.file_path,
c.name,
c.id
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"`
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"`
Tags interface{} `json:"tags"`
}
func (q *Queries) GetPostById(ctx context.Context, id int32) (GetPostByIdRow, error) {
@@ -131,6 +141,7 @@ func (q *Queries) GetPostById(ctx context.Context, id int32) (GetPostByIdRow, er
&i.Cover,
&i.CategoryName,
&i.CategoryID,
&i.Tags,
)
return i, err
}
@@ -252,7 +263,9 @@ FROM
AND p.published_at < NOW()
GROUP BY
c.id,
c.sort,
c.name
ORDER BY c.sort DESC, c.id
`
type ListCategoryStatsRow struct {
@@ -296,17 +309,45 @@ WITH paginated_posts AS (
updated_at
FROM posts
ORDER BY sort DESC, published_at DESC, id DESC
LIMIT $1 OFFSET $2)
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
COALESCE(ps.view, 0) AS view,
COALESCE(
jsonb_agg(
jsonb_build_object(
'id', t.id,
'name', t.name,
'code', t.code
)
ORDER BY t.sort DESC, t.id
) FILTER (WHERE t.id IS NOT NULL),
'[]'::jsonb
) AS tags
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
LEFT JOIN post_tag pt ON pt.post_id = p.id
LEFT JOIN tags t ON t.id = pt.tag_id
GROUP BY 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,
c.name,
c.id,
ps.view
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC
`
@@ -316,20 +357,21 @@ type ListPostsParams struct {
}
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"`
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"`
Tags interface{} `json:"tags"`
}
// 第二步:用这极少量的记录去进行 JOIN
@@ -357,6 +399,7 @@ func (q *Queries) ListPosts(ctx context.Context, arg ListPostsParams) ([]ListPos
&i.CategoryName,
&i.CategoryID,
&i.View,
&i.Tags,
); err != nil {
return nil, err
}
@@ -387,12 +430,36 @@ 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
COALESCE(ps.view, 0) AS view,
COALESCE(
jsonb_agg(
jsonb_build_object(
'id', t.id,
'name', t.name,
'code', t.code
)
ORDER BY t.sort DESC, t.id
) FILTER (WHERE t.id IS NOT NULL),
'[]'::jsonb
) AS tags
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
LEFT JOIN post_tag pt ON pt.post_id = p.id
LEFT JOIN tags t ON t.id = pt.tag_id
GROUP BY p.id,
p.title,
p.cover_id,
p.slug,
p.summary,
p.sort,
p.published_at,
f.file_path,
c.name,
c.id,
ps.view
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC
`
@@ -402,17 +469,18 @@ type ListPublishedPostsParams struct {
}
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"`
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"`
Tags interface{} `json:"tags"`
}
func (q *Queries) ListPublishedPosts(ctx context.Context, arg ListPublishedPostsParams) ([]ListPublishedPostsRow, error) {
@@ -436,6 +504,7 @@ func (q *Queries) ListPublishedPosts(ctx context.Context, arg ListPublishedPosts
&i.CategoryName,
&i.CategoryID,
&i.View,
&i.Tags,
); err != nil {
return nil, err
}

View File

@@ -3,7 +3,7 @@
// sqlc v1.31.1
// source: post_stats.sql
package db
package sqlc
import (
"context"

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: sys_api.sql
// source: sys_apis.sql
package db
package sqlc
import (
"context"
@@ -12,10 +12,17 @@ import (
const countSysApis = `-- name: CountSysApis :one
SELECT COUNT(*)
FROM sys_apis
WHERE ($1::text = '' OR group_name ILIKE '%' || $1 || '%')
AND ($2::text = '' OR method = $2)
`
func (q *Queries) CountSysApis(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, countSysApis)
type CountSysApisParams struct {
GroupName string `json:"group_name"`
Method string `json:"method"`
}
func (q *Queries) CountSysApis(ctx context.Context, arg CountSysApisParams) (int64, error) {
row := q.db.QueryRow(ctx, countSysApis, arg.GroupName, arg.Method)
var count int64
err := row.Scan(&count)
return count, err
@@ -88,19 +95,6 @@ func (q *Queries) DeleteSysApiPermission(ctx context.Context, apiID int32) error
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
@@ -186,17 +180,26 @@ func (q *Queries) GetSysApiGroupNames(ctx context.Context) ([]string, error) {
const getSysApis = `-- name: GetSysApis :many
SELECT id, group_name, name, method, path, sort, created_at, updated_at
FROM sys_apis
WHERE ($3::text = '' OR group_name ILIKE '%' || $3 || '%')
AND ($4::text = '' OR method = $4)
ORDER BY id
LIMIT $1 OFFSET $2
`
type GetSysApisParams struct {
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
GroupName string `json:"group_name"`
Method string `json:"method"`
}
func (q *Queries) GetSysApis(ctx context.Context, arg GetSysApisParams) ([]SysApi, error) {
rows, err := q.db.Query(ctx, getSysApis, arg.Limit, arg.Offset)
rows, err := q.db.Query(ctx, getSysApis,
arg.Limit,
arg.Offset,
arg.GroupName,
arg.Method,
)
if err != nil {
return nil, err
}

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: sys_menu.sql
// source: sys_menus.sql
package db
package sqlc
import (
"context"
@@ -30,7 +30,7 @@ RETURNING id
type CreateSysMenuParams struct {
Name string `json:"name"`
Path string `json:"path"`
Path *string `json:"path"`
Component *string `json:"component"`
Type int16 `json:"type"`
Hidden *bool `json:"hidden"`
@@ -123,7 +123,7 @@ ORDER BY m.sort ASC,
type GetAllSysMenusRow struct {
ID int32 `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Path *string `json:"path"`
Component *string `json:"component"`
Type int16 `json:"type"`
Hidden *bool `json:"hidden"`
@@ -213,7 +213,7 @@ type ListSysMenusParams struct {
type ListSysMenusRow struct {
ID int32 `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Path *string `json:"path"`
Component *string `json:"component"`
Type int16 `json:"type"`
Hidden *bool `json:"hidden"`
@@ -269,9 +269,9 @@ SET name = coalesce($1, name),
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
icon = CASE WHEN $8::boolean THEN $9 ELSE icon END,
parent_id = CASE WHEN $10::boolean THEN $11 ELSE parent_id END
WHERE id = $12
`
type UpdateSysMenuParams struct {
@@ -282,6 +282,7 @@ type UpdateSysMenuParams struct {
Hidden *bool `json:"hidden"`
Sort *int32 `json:"sort"`
Status *int16 `json:"status"`
UpdateIcon bool `json:"update_icon"`
Icon *int32 `json:"icon"`
UpdateParentID bool `json:"update_parent_id"`
ParentID *int32 `json:"parent_id"`
@@ -297,6 +298,7 @@ func (q *Queries) UpdateSysMenu(ctx context.Context, arg UpdateSysMenuParams) (i
arg.Hidden,
arg.Sort,
arg.Status,
arg.UpdateIcon,
arg.Icon,
arg.UpdateParentID,
arg.ParentID,

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: sys_permission.sql
// source: sys_permissions.sql
package db
package sqlc
import (
"context"
@@ -37,6 +37,32 @@ func (q *Queries) DeleteSysPermission(ctx context.Context, id int32) error {
return err
}
const getSysPermissionIDBySysApiID = `-- name: GetSysPermissionIDBySysApiID :one
SELECT permission_id
FROM sys_api_permission
WHERE api_id = $1
`
func (q *Queries) GetSysPermissionIDBySysApiID(ctx context.Context, apiID int32) (int32, error) {
row := q.db.QueryRow(ctx, getSysPermissionIDBySysApiID, apiID)
var permission_id int32
err := row.Scan(&permission_id)
return permission_id, err
}
const getSysPermissionIDBySysMenuID = `-- name: GetSysPermissionIDBySysMenuID :one
SELECT permission_id
FROM sys_menu_permission
WHERE menu_id = $1
`
func (q *Queries) GetSysPermissionIDBySysMenuID(ctx context.Context, menuID int32) (int32, error) {
row := q.db.QueryRow(ctx, getSysPermissionIDBySysMenuID, menuID)
var permission_id int32
err := row.Scan(&permission_id)
return permission_id, err
}
const updateSysPermission = `-- name: UpdateSysPermission :exec
UPDATE sys_permissions
SET code = $2

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: sys_role.sql
// source: sys_roles.sql
package db
package sqlc
import (
"context"
@@ -22,17 +22,18 @@ func (q *Queries) CountSysRoles(ctx context.Context) (int64, error) {
}
const createSysRole = `-- name: CreateSysRole :exec
INSERT INTO sys_roles (name, code)
VALUES ($1, $2)
INSERT INTO sys_roles (name, code, status)
VALUES ($1, $2, $3)
`
type CreateSysRoleParams struct {
Name string `json:"name"`
Code string `json:"code"`
Name string `json:"name"`
Code string `json:"code"`
Status int16 `json:"status"`
}
func (q *Queries) CreateSysRole(ctx context.Context, arg CreateSysRoleParams) error {
_, err := q.db.Exec(ctx, createSysRole, arg.Name, arg.Code)
_, err := q.db.Exec(ctx, createSysRole, arg.Name, arg.Code, arg.Status)
return err
}
@@ -55,21 +56,54 @@ func (q *Queries) DeleteSysRole(ctx context.Context, id int32) (int64, error) {
return result.RowsAffected(), nil
}
const deleteSysRolePermission = `-- name: DeleteSysRolePermission :exec
const deleteSysRolePermissionByPermissionID = `-- name: DeleteSysRolePermissionByPermissionID :exec
DELETE
FROM sys_role_permission
WHERE permission_id = $1
`
func (q *Queries) DeleteSysRolePermissionByPermissionID(ctx context.Context, permissionID int32) error {
_, err := q.db.Exec(ctx, deleteSysRolePermissionByPermissionID, permissionID)
return err
}
const deleteSysRolePermissionByRoleID = `-- name: DeleteSysRolePermissionByRoleID :exec
DELETE
FROM sys_role_permission
WHERE role_id = $1
`
func (q *Queries) DeleteSysRolePermissionByRoleID(ctx context.Context, roleID int32) error {
_, err := q.db.Exec(ctx, deleteSysRolePermissionByRoleID, roleID)
return err
}
const deleteSysRolePermissionByType = `-- name: DeleteSysRolePermissionByType :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
AND p."type" = $2
`
type DeleteSysRolePermissionParams struct {
type DeleteSysRolePermissionByTypeParams 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)
func (q *Queries) DeleteSysRolePermissionByType(ctx context.Context, arg DeleteSysRolePermissionByTypeParams) error {
_, err := q.db.Exec(ctx, deleteSysRolePermissionByType, arg.RoleID, arg.Type)
return err
}
const deleteSysUserRoleByRoleID = `-- name: DeleteSysUserRoleByRoleID :exec
DELETE
FROM sys_user_role
WHERE role_id = $1
`
func (q *Queries) DeleteSysUserRoleByRoleID(ctx context.Context, roleID int32) error {
_, err := q.db.Exec(ctx, deleteSysUserRoleByRoleID, roleID)
return err
}
@@ -96,7 +130,7 @@ func (q *Queries) ExistsSysRoleCode(ctx context.Context, arg ExistsSysRoleCodePa
}
const getAllSysRoles = `-- name: GetAllSysRoles :many
SELECT id, name, code, created_at, updated_at
SELECT id, name, code, status, created_at, updated_at
from sys_roles
`
@@ -113,6 +147,7 @@ func (q *Queries) GetAllSysRoles(ctx context.Context) ([]SysRole, error) {
&i.ID,
&i.Name,
&i.Code,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
@@ -212,7 +247,7 @@ func (q *Queries) GetSysRoleApis(ctx context.Context, roleID int32) ([]GetSysRol
}
const getSysRoleByID = `-- name: GetSysRoleByID :one
SELECT id, name, code, created_at, updated_at
SELECT id, name, code, status, created_at, updated_at
FROM sys_roles
WHERE id = $1
`
@@ -224,6 +259,7 @@ func (q *Queries) GetSysRoleByID(ctx context.Context, id int32) (SysRole, error)
&i.ID,
&i.Name,
&i.Code,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
)
@@ -264,7 +300,7 @@ func (q *Queries) GetSysRoleMenus(ctx context.Context, roleID int32) ([]GetSysRo
}
const listSysRoles = `-- name: ListSysRoles :many
SELECT id, name, code, created_at, updated_at
SELECT id, name, code, status, created_at, updated_at
FROM sys_roles
ORDER BY id
LIMIT $1 OFFSET $2
@@ -288,6 +324,7 @@ func (q *Queries) ListSysRoles(ctx context.Context, arg ListSysRolesParams) ([]S
&i.ID,
&i.Name,
&i.Code,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
@@ -303,17 +340,19 @@ func (q *Queries) ListSysRoles(ctx context.Context, arg ListSysRolesParams) ([]S
const updateSysRole = `-- name: UpdateSysRole :execrows
UPDATE sys_roles
SET name = coalesce($1, name)
WHERE id = $2
SET name = coalesce($1, name),
status = coalesce($2, status)
WHERE id = $3
`
type UpdateSysRoleParams struct {
Name *string `json:"name"`
ID int32 `json:"id"`
Name *string `json:"name"`
Status *int16 `json:"status"`
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)
result, err := q.db.Exec(ctx, updateSysRole, arg.Name, arg.Status, arg.ID)
if err != nil {
return 0, err
}

View File

@@ -1,9 +1,9 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: sys_user.sql
// source: sys_users.sql
package db
package sqlc
import (
"context"
@@ -24,24 +24,26 @@ func (q *Queries) ClearSysUserRoles(ctx context.Context, userID int32) error {
const countSysUsers = `-- name: CountSysUsers :one
SELECT COUNT(*)
FROM sys_users
WHERE ($1::text = '' OR username ILIKE '%' || $1 || '%')
`
func (q *Queries) CountSysUsers(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, countSysUsers)
func (q *Queries) CountSysUsers(ctx context.Context, username string) (int64, error) {
row := q.db.QueryRow(ctx, countSysUsers, username)
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)
INSERT INTO sys_users (account, username, password_hash, status, avatar_id)
VALUES ($1, $2, $3, $4, $5)
`
type CreateSysUserParams struct {
Account string `json:"account"`
Username string `json:"username"`
PasswordHash string `json:"password_hash"`
Status int16 `json:"status"`
AvatarID *int32 `json:"avatar_id"`
}
@@ -50,26 +52,17 @@ func (q *Queries) CreateSysUser(ctx context.Context, arg CreateSysUserParams) er
arg.Account,
arg.Username,
arg.PasswordHash,
arg.Status,
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
@@ -85,9 +78,38 @@ func (q *Queries) DeleteSysUser(ctx context.Context, id int32) (int64, error) {
return result.RowsAffected(), nil
}
const getActiveSysUserByID = `-- name: GetActiveSysUserByID :one
SELECT id, account, username, status
FROM sys_users
WHERE id = $1
AND status = 1
`
type GetActiveSysUserByIDRow struct {
ID int32 `json:"id"`
Account string `json:"account"`
Username string `json:"username"`
Status int16 `json:"status"`
}
// 场景:用户登录、获取个人信息、刷新 Token严格校验 status = 1
func (q *Queries) GetActiveSysUserByID(ctx context.Context, id int32) (GetActiveSysUserByIDRow, error) {
row := q.db.QueryRow(ctx, getActiveSysUserByID, id)
var i GetActiveSysUserByIDRow
err := row.Scan(
&i.ID,
&i.Account,
&i.Username,
&i.Status,
)
return i, err
}
const getSysAdminMenus = `-- name: GetSysAdminMenus :many
SELECT id, name, path, component, type, hidden, sort, status, parent_id, icon, created_at, updated_at
FROM sys_menus
WHERE status = 1
AND type <> 2
ORDER BY sort, id
`
@@ -124,18 +146,45 @@ func (q *Queries) GetSysAdminMenus(ctx context.Context) ([]SysMenu, error) {
return items, nil
}
const getSysAdminPermissions = `-- name: GetSysAdminPermissions :many
SELECT code
FROM sys_permissions
WHERE type = 0
`
func (q *Queries) GetSysAdminPermissions(ctx context.Context) ([]*string, error) {
rows, err := q.db.Query(ctx, getSysAdminPermissions)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*string{}
for rows.Next() {
var code *string
if err := rows.Scan(&code); err != nil {
return nil, err
}
items = append(items, code)
}
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_roles r ON r.id = ur.role_id
JOIN sys_role_permission rp ON rp.role_id = r.id
JOIN sys_api_permission ap ON ap.permission_id = rp.permission_id
JOIN sys_apis a ON a.id = ap.api_id
WHERE u.id = $1
AND u.status = 1
AND r.status = 1
`
type GetSysUserApisRow struct {
@@ -169,6 +218,7 @@ SELECT u.id,
u.account,
u.username,
u.password_hash,
u.status,
u.avatar_id,
f.file_path AS avatar_url,
u.created_at,
@@ -183,6 +233,7 @@ type GetSysUserByAccountRow struct {
Account string `json:"account"`
Username string `json:"username"`
PasswordHash string `json:"password_hash"`
Status int16 `json:"status"`
AvatarID *int32 `json:"avatar_id"`
AvatarUrl *string `json:"avatar_url"`
CreatedAt time.Time `json:"created_at"`
@@ -197,6 +248,7 @@ func (q *Queries) GetSysUserByAccount(ctx context.Context, account string) (GetS
&i.Account,
&i.Username,
&i.PasswordHash,
&i.Status,
&i.AvatarID,
&i.AvatarUrl,
&i.CreatedAt,
@@ -210,6 +262,7 @@ SELECT u.id,
u.account,
u.username,
u.avatar_id,
u.status,
f.file_path AS avatar_url,
u.created_at,
u.updated_at
@@ -223,6 +276,7 @@ type GetSysUserByIDRow struct {
Account string `json:"account"`
Username string `json:"username"`
AvatarID *int32 `json:"avatar_id"`
Status int16 `json:"status"`
AvatarUrl *string `json:"avatar_url"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
@@ -236,6 +290,7 @@ func (q *Queries) GetSysUserByID(ctx context.Context, id int32) (GetSysUserByIDR
&i.Account,
&i.Username,
&i.AvatarID,
&i.Status,
&i.AvatarUrl,
&i.CreatedAt,
&i.UpdatedAt,
@@ -249,10 +304,13 @@ 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_menu_permission mp ON mp.permission_id = rp.permission_id
JOIN sys_menus m ON m.id = mp.menu_id
WHERE u.id = $1
AND u.status = 1
AND r.status = 1
AND m.status = 1
AND m.type <> 2
ORDER BY m.sort, m.id
`
@@ -289,8 +347,44 @@ func (q *Queries) GetSysUserMenus(ctx context.Context, id int32) ([]SysMenu, err
return items, nil
}
const getSysUserPermissions = `-- name: GetSysUserPermissions :many
SELECT DISTINCT p.code
FROM sys_users u
JOIN sys_user_role ur ON u.id = ur.user_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
AND u.status = 1
AND r.status = 1
AND m.status = 1
AND p."type" = 0
`
func (q *Queries) GetSysUserPermissions(ctx context.Context, id int32) ([]*string, error) {
rows, err := q.db.Query(ctx, getSysUserPermissions, id)
if err != nil {
return nil, err
}
defer rows.Close()
items := []*string{}
for rows.Next() {
var code *string
if err := rows.Scan(&code); err != nil {
return nil, err
}
items = append(items, code)
}
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
SELECT r.id, r.name, r.code, r.status, 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
@@ -309,6 +403,7 @@ func (q *Queries) GetSysUserRoles(ctx context.Context, userID int32) ([]SysRole,
&i.ID,
&i.Name,
&i.Code,
&i.Status,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
@@ -326,25 +421,29 @@ const listSysUsers = `-- name: ListSysUsers :many
SELECT u.id,
u.account,
u.username,
u.status,
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 ($3::text = '' OR u.username ILIKE '%' || $3 || '%')
ORDER BY u.id
LIMIT $1 OFFSET $2
`
type ListSysUsersParams struct {
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
Username string `json:"username"`
}
type ListSysUsersRow struct {
ID int32 `json:"id"`
Account string `json:"account"`
Username string `json:"username"`
Status int16 `json:"status"`
AvatarID *int32 `json:"avatar_id"`
AvatarUrl *string `json:"avatar_url"`
CreatedAt time.Time `json:"created_at"`
@@ -352,7 +451,7 @@ type ListSysUsersRow struct {
}
func (q *Queries) ListSysUsers(ctx context.Context, arg ListSysUsersParams) ([]ListSysUsersRow, error) {
rows, err := q.db.Query(ctx, listSysUsers, arg.Limit, arg.Offset)
rows, err := q.db.Query(ctx, listSysUsers, arg.Limit, arg.Offset, arg.Username)
if err != nil {
return nil, err
}
@@ -364,6 +463,7 @@ func (q *Queries) ListSysUsers(ctx context.Context, arg ListSysUsersParams) ([]L
&i.ID,
&i.Account,
&i.Username,
&i.Status,
&i.AvatarID,
&i.AvatarUrl,
&i.CreatedAt,
@@ -382,12 +482,14 @@ func (q *Queries) ListSysUsers(ctx context.Context, arg ListSysUsersParams) ([]L
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
status = coalesce($2, status),
avatar_id = CASE WHEN $3::boolean THEN $4 ELSE avatar_id END
WHERE id = $5
`
type UpdateSysUserParams struct {
Username *string `json:"username"`
Status *int16 `json:"status"`
UpdateAvatarID bool `json:"update_avatar_id"`
AvatarID *int32 `json:"avatar_id"`
ID int32 `json:"id"`
@@ -396,6 +498,7 @@ type UpdateSysUserParams struct {
func (q *Queries) UpdateSysUser(ctx context.Context, arg UpdateSysUserParams) (int64, error) {
result, err := q.db.Exec(ctx, updateSysUser,
arg.Username,
arg.Status,
arg.UpdateAvatarID,
arg.AvatarID,
arg.ID,

View File

@@ -0,0 +1,179 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: tags.sql
package sqlc
import (
"context"
)
const countTags = `-- name: CountTags :one
SELECT COUNT(*)
FROM tags
`
func (q *Queries) CountTags(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, countTags)
var count int64
err := row.Scan(&count)
return count, err
}
type CreatePostTagParams struct {
PostID int32 `json:"post_id"`
TagID int32 `json:"tag_id"`
}
const createTag = `-- name: CreateTag :exec
INSERT INTO tags(name, code, sort)
VALUES ($1, $2, $3)
`
type CreateTagParams struct {
Name string `json:"name"`
Code string `json:"code"`
Sort *int32 `json:"sort"`
}
func (q *Queries) CreateTag(ctx context.Context, arg CreateTagParams) error {
_, err := q.db.Exec(ctx, createTag, arg.Name, arg.Code, arg.Sort)
return err
}
const deletePostTagByPostID = `-- name: DeletePostTagByPostID :exec
DELETE
FROM post_tag
WHERE post_id = $1
`
func (q *Queries) DeletePostTagByPostID(ctx context.Context, postID int32) error {
_, err := q.db.Exec(ctx, deletePostTagByPostID, postID)
return err
}
const deletePostTagByTagID = `-- name: DeletePostTagByTagID :exec
DELETE
FROM post_tag
WHERE tag_id = $1
`
func (q *Queries) DeletePostTagByTagID(ctx context.Context, tagID int32) error {
_, err := q.db.Exec(ctx, deletePostTagByTagID, tagID)
return err
}
const deleteTag = `-- name: DeleteTag :execrows
DELETE
FROM tags
WHERE id = $1
`
func (q *Queries) DeleteTag(ctx context.Context, id int32) (int64, error) {
result, err := q.db.Exec(ctx, deleteTag, id)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}
const listAllTags = `-- name: ListAllTags :many
SELECT id, name, code, sort, created_at, updated_at
FROM tags
ORDER BY sort DESC, id
`
func (q *Queries) ListAllTags(ctx context.Context) ([]Tag, error) {
rows, err := q.db.Query(ctx, listAllTags)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Tag{}
for rows.Next() {
var i Tag
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Code,
&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 listTags = `-- name: ListTags :many
SELECT id, name, code, sort, created_at, updated_at
FROM tags
ORDER BY sort DESC, id
LIMIT $1 OFFSET $2
`
type ListTagsParams struct {
Limit int32 `json:"limit"`
Offset int32 `json:"offset"`
}
func (q *Queries) ListTags(ctx context.Context, arg ListTagsParams) ([]Tag, error) {
rows, err := q.db.Query(ctx, listTags, arg.Limit, arg.Offset)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Tag{}
for rows.Next() {
var i Tag
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Code,
&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 updateTag = `-- name: UpdateTag :execrows
UPDATE tags
SET name = coalesce($1, name),
code = coalesce($2, code),
sort = coalesce($3, sort)
WHERE id = $4
`
type UpdateTagParams struct {
Name *string `json:"name"`
Code *string `json:"code"`
Sort *int32 `json:"sort"`
ID int32 `json:"id"`
}
func (q *Queries) UpdateTag(ctx context.Context, arg UpdateTagParams) (int64, error) {
result, err := q.db.Exec(ctx, updateTag,
arg.Name,
arg.Code,
arg.Sort,
arg.ID,
)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}

68
internal/db/store.go Normal file
View File

@@ -0,0 +1,68 @@
package db
import (
"context"
"fmt"
db "server/internal/db/sqlc"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
type Store struct {
*db.Queries
pool *pgxpool.Pool
}
func NewStore(pool *pgxpool.Pool) *Store {
return &Store{
pool: pool,
Queries: db.New(pool),
}
}
func (store *Store) WithTx(ctx context.Context, fn func(q *db.Queries) error, opts ...pgx.TxOptions) error {
txOpt := pgx.TxOptions{}
if len(opts) > 0 {
txOpt = opts[0]
}
tx, err := store.pool.BeginTx(ctx, txOpt)
if err != nil {
return fmt.Errorf("begin tx: %w", err)
}
defer func() {
// 使用 context.Background() 确保即使请求 context 被取消,
// 回滚指令也能发送给 DB从而安全地回收连接而不是销毁连接。
_ = tx.Rollback(context.Background())
}()
q := store.Queries.WithTx(tx)
if err := fn(q); err != nil {
return err // 业务侧的错误保持原样返回
}
if err := tx.Commit(ctx); err != nil {
return fmt.Errorf("commit tx: %w", err)
}
return nil
}
// WithTxResult 带返回值的事务
func WithTxResult[T any](ctx context.Context, store *Store, fn func(q *db.Queries) (T, error), opts ...pgx.TxOptions) (T, error) {
var result T
err := store.WithTx(ctx, func(q *db.Queries) error {
r, err := fn(q)
if err != nil {
return err
}
result = r
return nil
}, opts...)
return result, err
}