Initial commit: GovAI 政务AI平台
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
func NewPool(ctx context.Context, databaseURL string) (*pgxpool.Pool, error) {
|
||||
config, err := pgxpool.ParseConfig(databaseURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse database url: %w", err)
|
||||
}
|
||||
|
||||
config.MaxConns = 20
|
||||
config.MinConns = 5
|
||||
|
||||
pool, err := pgxpool.NewWithConfig(ctx, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create pool: %w", err)
|
||||
}
|
||||
|
||||
if err := pool.Ping(ctx); err != nil {
|
||||
return nil, fmt.Errorf("ping database: %w", err)
|
||||
}
|
||||
|
||||
return pool, nil
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
-- name: CreateApplication :one
|
||||
INSERT INTO applications (
|
||||
name, slug, description, long_description, icon_url,
|
||||
category_id, creator_id, dept_id,
|
||||
dify_app_id, dify_app_type, dify_api_key,
|
||||
app_config, welcome_message, suggested_prompts,
|
||||
max_tokens, temperature, status, visibility, is_template
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19
|
||||
) RETURNING *;
|
||||
|
||||
-- name: GetApplicationByID :one
|
||||
SELECT * FROM applications WHERE id = $1;
|
||||
|
||||
-- name: GetApplicationBySlug :one
|
||||
SELECT * FROM applications WHERE slug = $1;
|
||||
|
||||
-- name: UpdateApplication :one
|
||||
UPDATE applications
|
||||
SET name = COALESCE(sqlc.narg('name'), name),
|
||||
description = COALESCE(sqlc.narg('description'), description),
|
||||
long_description = COALESCE(sqlc.narg('long_description'), long_description),
|
||||
icon_url = COALESCE(sqlc.narg('icon_url'), icon_url),
|
||||
category_id = COALESCE(sqlc.narg('category_id'), category_id),
|
||||
app_config = COALESCE(sqlc.narg('app_config'), app_config),
|
||||
welcome_message = COALESCE(sqlc.narg('welcome_message'), welcome_message),
|
||||
suggested_prompts = COALESCE(sqlc.narg('suggested_prompts'), suggested_prompts),
|
||||
max_tokens = COALESCE(sqlc.narg('max_tokens'), max_tokens),
|
||||
temperature = COALESCE(sqlc.narg('temperature'), temperature),
|
||||
visibility = COALESCE(sqlc.narg('visibility'), visibility)
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateApplicationStatus :exec
|
||||
UPDATE applications SET status = $2 WHERE id = $1;
|
||||
|
||||
-- name: DeleteApplication :exec
|
||||
DELETE FROM applications WHERE id = $1 AND status = 'draft';
|
||||
|
||||
-- name: ListStoreApps :many
|
||||
SELECT a.*, c.name as category_name, c.slug as category_slug, u.name as creator_name
|
||||
FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.status = 'approved'
|
||||
AND a.visibility = 'public'
|
||||
AND (sqlc.narg('category_slug')::VARCHAR IS NULL OR c.slug = sqlc.narg('category_slug'))
|
||||
AND (sqlc.narg('search')::VARCHAR IS NULL
|
||||
OR to_tsvector('simple', a.name || ' ' || COALESCE(a.description, ''))
|
||||
@@ plainto_tsquery('simple', sqlc.narg('search')))
|
||||
ORDER BY
|
||||
CASE WHEN sqlc.narg('sort')::VARCHAR = 'popular' THEN a.usage_count END DESC,
|
||||
CASE WHEN sqlc.narg('sort')::VARCHAR = 'rating' THEN a.avg_rating END DESC,
|
||||
CASE WHEN sqlc.narg('sort')::VARCHAR IS NULL OR sqlc.narg('sort') = 'latest' THEN EXTRACT(EPOCH FROM a.published_at) END DESC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountStoreApps :one
|
||||
SELECT COUNT(*) FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
WHERE a.status = 'approved'
|
||||
AND a.visibility = 'public'
|
||||
AND (sqlc.narg('category_slug')::VARCHAR IS NULL OR c.slug = sqlc.narg('category_slug'))
|
||||
AND (sqlc.narg('search')::VARCHAR IS NULL
|
||||
OR to_tsvector('simple', a.name || ' ' || COALESCE(a.description, ''))
|
||||
@@ plainto_tsquery('simple', sqlc.narg('search')));
|
||||
|
||||
-- name: ListFeaturedApps :many
|
||||
SELECT a.*, c.name as category_name, u.name as creator_name
|
||||
FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.is_featured = true AND a.status = 'approved' AND a.visibility = 'public'
|
||||
ORDER BY a.usage_count DESC
|
||||
LIMIT $1;
|
||||
|
||||
-- name: ListTopApps :many
|
||||
SELECT a.*, c.name as category_name, u.name as creator_name
|
||||
FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.status = 'approved' AND a.visibility = 'public'
|
||||
ORDER BY a.usage_count DESC
|
||||
LIMIT $1;
|
||||
|
||||
-- name: ListCreatorApps :many
|
||||
SELECT a.*, c.name as category_name
|
||||
FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
WHERE a.creator_id = $1
|
||||
ORDER BY a.updated_at DESC
|
||||
LIMIT $2 OFFSET $3;
|
||||
|
||||
-- name: ListTemplates :many
|
||||
SELECT a.*, c.name as category_name
|
||||
FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
WHERE a.is_template = true AND a.status = 'approved'
|
||||
ORDER BY a.usage_count DESC;
|
||||
|
||||
-- name: IncrementUsageCount :exec
|
||||
UPDATE applications SET usage_count = usage_count + 1 WHERE id = $1;
|
||||
|
||||
-- name: UpdateFavoriteCount :exec
|
||||
UPDATE applications SET favorite_count = favorite_count + $2 WHERE id = $1;
|
||||
|
||||
-- name: UpdateAppRating :exec
|
||||
UPDATE applications
|
||||
SET avg_rating = $2, rating_count = $3
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ListAllApps :many
|
||||
SELECT a.*, c.name as category_name, u.name as creator_name
|
||||
FROM applications a
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE (sqlc.narg('status')::VARCHAR IS NULL OR a.status = sqlc.narg('status'))
|
||||
ORDER BY a.created_at DESC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountAllApps :one
|
||||
SELECT COUNT(*) FROM applications
|
||||
WHERE (sqlc.narg('status')::VARCHAR IS NULL OR status = sqlc.narg('status'));
|
||||
@@ -0,0 +1,23 @@
|
||||
-- name: CreateAuditLog :exec
|
||||
INSERT INTO audit_logs (user_id, action, resource_type, resource_id, details, ip_address, user_agent)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7);
|
||||
|
||||
-- name: ListAuditLogs :many
|
||||
SELECT al.*, u.name as user_name
|
||||
FROM audit_logs al
|
||||
LEFT JOIN users u ON al.user_id = u.id
|
||||
WHERE (sqlc.narg('user_id')::UUID IS NULL OR al.user_id = sqlc.narg('user_id'))
|
||||
AND (sqlc.narg('action')::VARCHAR IS NULL OR al.action = sqlc.narg('action'))
|
||||
AND (sqlc.narg('resource_type')::VARCHAR IS NULL OR al.resource_type = sqlc.narg('resource_type'))
|
||||
AND (sqlc.narg('start_time')::TIMESTAMPTZ IS NULL OR al.created_at >= sqlc.narg('start_time'))
|
||||
AND (sqlc.narg('end_time')::TIMESTAMPTZ IS NULL OR al.created_at <= sqlc.narg('end_time'))
|
||||
ORDER BY al.created_at DESC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountAuditLogs :one
|
||||
SELECT COUNT(*) FROM audit_logs
|
||||
WHERE (sqlc.narg('user_id')::UUID IS NULL OR user_id = sqlc.narg('user_id'))
|
||||
AND (sqlc.narg('action')::VARCHAR IS NULL OR action = sqlc.narg('action'))
|
||||
AND (sqlc.narg('resource_type')::VARCHAR IS NULL OR resource_type = sqlc.narg('resource_type'))
|
||||
AND (sqlc.narg('start_time')::TIMESTAMPTZ IS NULL OR created_at >= sqlc.narg('start_time'))
|
||||
AND (sqlc.narg('end_time')::TIMESTAMPTZ IS NULL OR created_at <= sqlc.narg('end_time'));
|
||||
@@ -0,0 +1,10 @@
|
||||
-- name: ListCategories :many
|
||||
SELECT * FROM categories
|
||||
WHERE status = 'active'
|
||||
ORDER BY sort_order ASC;
|
||||
|
||||
-- name: GetCategoryByID :one
|
||||
SELECT * FROM categories WHERE id = $1;
|
||||
|
||||
-- name: GetCategoryBySlug :one
|
||||
SELECT * FROM categories WHERE slug = $1;
|
||||
@@ -0,0 +1,37 @@
|
||||
-- name: AddFavorite :exec
|
||||
INSERT INTO app_favorites (user_id, app_id) VALUES ($1, $2)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- name: RemoveFavorite :exec
|
||||
DELETE FROM app_favorites WHERE user_id = $1 AND app_id = $2;
|
||||
|
||||
-- name: IsFavorited :one
|
||||
SELECT EXISTS(SELECT 1 FROM app_favorites WHERE user_id = $1 AND app_id = $2);
|
||||
|
||||
-- name: ListUserFavorites :many
|
||||
SELECT a.*, c.name as category_name
|
||||
FROM app_favorites f
|
||||
JOIN applications a ON f.app_id = a.id
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
WHERE f.user_id = $1
|
||||
ORDER BY f.created_at DESC
|
||||
LIMIT $2 OFFSET $3;
|
||||
|
||||
-- name: UpsertRating :one
|
||||
INSERT INTO app_ratings (app_id, user_id, score, comment)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
ON CONFLICT (app_id, user_id)
|
||||
DO UPDATE SET score = EXCLUDED.score, comment = EXCLUDED.comment
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetAppAvgRating :one
|
||||
SELECT COALESCE(AVG(score)::REAL, 0) as avg_rating, COUNT(*) as rating_count
|
||||
FROM app_ratings WHERE app_id = $1;
|
||||
|
||||
-- name: ListAppRatings :many
|
||||
SELECT r.*, u.name as user_name, u.avatar_url as user_avatar
|
||||
FROM app_ratings r
|
||||
JOIN users u ON r.user_id = u.id
|
||||
WHERE r.app_id = $1
|
||||
ORDER BY r.created_at DESC
|
||||
LIMIT $2 OFFSET $3;
|
||||
@@ -0,0 +1,40 @@
|
||||
-- name: CreateReview :one
|
||||
INSERT INTO app_reviews (app_id, version, submitter_id, submit_comment)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetReviewByID :one
|
||||
SELECT * FROM app_reviews WHERE id = $1;
|
||||
|
||||
-- name: ListPendingReviews :many
|
||||
SELECT r.*, a.name as app_name, a.description as app_description,
|
||||
a.icon_url as app_icon, u.name as submitter_name
|
||||
FROM app_reviews r
|
||||
JOIN applications a ON r.app_id = a.id
|
||||
JOIN users u ON r.submitter_id = u.id
|
||||
WHERE r.status = 'pending'
|
||||
ORDER BY r.submitted_at ASC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountPendingReviews :one
|
||||
SELECT COUNT(*) FROM app_reviews WHERE status = 'pending';
|
||||
|
||||
-- name: ApproveReview :exec
|
||||
UPDATE app_reviews
|
||||
SET status = 'approved', reviewer_id = $2, review_comment = $3, reviewed_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: RejectReview :exec
|
||||
UPDATE app_reviews
|
||||
SET status = 'rejected', reviewer_id = $2, review_comment = $3, reviewed_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: WithdrawReview :exec
|
||||
UPDATE app_reviews SET status = 'withdrawn' WHERE id = $1 AND status = 'pending';
|
||||
|
||||
-- name: ListAppReviews :many
|
||||
SELECT r.*, u.name as reviewer_name
|
||||
FROM app_reviews r
|
||||
LEFT JOIN users u ON r.reviewer_id = u.id
|
||||
WHERE r.app_id = $1
|
||||
ORDER BY r.created_at DESC;
|
||||
@@ -0,0 +1,34 @@
|
||||
-- name: CreateUsageLog :one
|
||||
INSERT INTO app_usage_logs (
|
||||
app_id, user_id, dept_id, conversation_id, message_count,
|
||||
prompt_tokens, completion_tokens, total_tokens, model_name,
|
||||
estimated_cost, duration_ms, is_successful, error_message, client_type
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetRecentUsedApps :many
|
||||
SELECT DISTINCT ON (a.id) a.*, c.name as category_name, l.created_at as last_used_at
|
||||
FROM app_usage_logs l
|
||||
JOIN applications a ON l.app_id = a.id
|
||||
LEFT JOIN categories c ON a.category_id = c.id
|
||||
WHERE l.user_id = $1
|
||||
ORDER BY a.id, l.created_at DESC
|
||||
LIMIT $2;
|
||||
|
||||
-- name: GetUserStats :one
|
||||
SELECT
|
||||
COUNT(*) as total_conversations,
|
||||
COALESCE(SUM(total_tokens), 0) as total_tokens,
|
||||
COALESCE(SUM(estimated_cost), 0) as total_cost
|
||||
FROM app_usage_logs
|
||||
WHERE user_id = $1
|
||||
AND created_at >= $2;
|
||||
|
||||
-- name: GetOverviewStats :one
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM users WHERE status = 'active') as total_users,
|
||||
(SELECT COUNT(*) FROM applications WHERE status = 'approved') as total_apps,
|
||||
(SELECT COUNT(DISTINCT user_id) FROM app_usage_logs WHERE created_at >= $1) as active_users,
|
||||
(SELECT COUNT(*) FROM app_usage_logs WHERE created_at >= $1) as total_conversations,
|
||||
(SELECT COALESCE(SUM(total_tokens), 0) FROM app_usage_logs WHERE created_at >= $2) as monthly_tokens,
|
||||
(SELECT COALESCE(SUM(estimated_cost), 0) FROM app_usage_logs WHERE created_at >= $2) as monthly_cost;
|
||||
@@ -0,0 +1,52 @@
|
||||
-- name: GetUserByID :one
|
||||
SELECT * FROM users WHERE id = $1;
|
||||
|
||||
-- name: GetUserByEmail :one
|
||||
SELECT * FROM users WHERE email = $1;
|
||||
|
||||
-- name: GetUserByEmployeeID :one
|
||||
SELECT * FROM users WHERE employee_id = $1;
|
||||
|
||||
-- name: CreateUser :one
|
||||
INSERT INTO users (name, email, password_hash, phone, avatar_url, role, status, sso_provider, sso_external_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateUserProfile :one
|
||||
UPDATE users
|
||||
SET name = COALESCE(sqlc.narg('name'), name),
|
||||
phone = COALESCE(sqlc.narg('phone'), phone),
|
||||
avatar_url = COALESCE(sqlc.narg('avatar_url'), avatar_url)
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: UpdateUserRole :exec
|
||||
UPDATE users SET role = $2 WHERE id = $1;
|
||||
|
||||
-- name: UpdateUserStatus :exec
|
||||
UPDATE users SET status = $2 WHERE id = $1;
|
||||
|
||||
-- name: UpdateUserLogin :exec
|
||||
UPDATE users
|
||||
SET last_login_at = NOW(), login_count = login_count + 1
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ListUsers :many
|
||||
SELECT * FROM users
|
||||
WHERE (sqlc.narg('role')::VARCHAR IS NULL OR role = sqlc.narg('role'))
|
||||
AND (sqlc.narg('status')::VARCHAR IS NULL OR status = sqlc.narg('status'))
|
||||
AND (sqlc.narg('search')::VARCHAR IS NULL
|
||||
OR name ILIKE '%' || sqlc.narg('search') || '%'
|
||||
OR email ILIKE '%' || sqlc.narg('search') || '%'
|
||||
OR employee_id ILIKE '%' || sqlc.narg('search') || '%')
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountUsers :one
|
||||
SELECT COUNT(*) FROM users
|
||||
WHERE (sqlc.narg('role')::VARCHAR IS NULL OR role = sqlc.narg('role'))
|
||||
AND (sqlc.narg('status')::VARCHAR IS NULL OR status = sqlc.narg('status'))
|
||||
AND (sqlc.narg('search')::VARCHAR IS NULL
|
||||
OR name ILIKE '%' || sqlc.narg('search') || '%'
|
||||
OR email ILIKE '%' || sqlc.narg('search') || '%'
|
||||
OR employee_id ILIKE '%' || sqlc.narg('search') || '%');
|
||||
Reference in New Issue
Block a user