u
This commit is contained in:
1 parent
1903861354
commit
1b1a54f7dd
35 files changed
+1185
-535
No files matched your search
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourcePerFileMappings">
|
||||
<file url="file://$PROJECT_DIR$/db/queries/finance_category_default.sql" value="4db2dbd4-857e-4234-ba5e-f8cbf0ba6e5d" />
|
||||
<file url="file://$PROJECT_DIR$/db/queries/finance_category_space.sql" value="4db2dbd4-857e-4234-ba5e-f8cbf0ba6e5d" />
|
||||
<file url="file://$PROJECT_DIR$/db/queries/space.sql" value="4db2dbd4-857e-4234-ba5e-f8cbf0ba6e5d" />
|
||||
</component>
|
||||
</project>
|
||||
+2
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/db/queries/finance_category_default.sql" dialect="PostgreSQL" />
|
||||
<file url="file://$PROJECT_DIR$/db/queries/finance_category_space.sql" dialect="PostgreSQL" />
|
||||
<file url="file://$PROJECT_DIR$/db/queries/space.sql" dialect="PostgreSQL" />
|
||||
<file url="file://$PROJECT_DIR$/db/queries/space_member.sql" dialect="GenericSQL" />
|
||||
<file url="file://$PROJECT_DIR$/db/queries/user.sql" dialect="GenericSQL" />
|
||||
|
||||
@@ -154,7 +154,7 @@ func handleThirdLogin(
|
||||
openid string,
|
||||
nickname string,
|
||||
avatar string,
|
||||
loginType int32, // 0=微信 1=QQ
|
||||
loginType int16, // 0=微信 1=QQ
|
||||
vo *types.LoginVO,
|
||||
) error {
|
||||
user, err := db.Queries.FindUserByOpenID(c.Context(), repo.FindUserByOpenIDParams{
|
||||
@@ -191,7 +191,7 @@ func handleThirdLogin(
|
||||
}
|
||||
|
||||
// 注册用户
|
||||
func registerUser(c fiber.Ctx, openid, nickname, avatar string, loginType int32, vo *types.LoginVO) error {
|
||||
func registerUser(c fiber.Ctx, openid, nickname, avatar string, loginType int16, vo *types.LoginVO) error {
|
||||
userId := uniqueid.NextId()
|
||||
|
||||
if nickname == "" {
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package space
|
||||
|
||||
import (
|
||||
"allapp/api/router/middleware"
|
||||
"allapp/api/types"
|
||||
"allapp/db"
|
||||
"allapp/db/repo"
|
||||
"allapp/utils"
|
||||
"allapp/utils/errorx"
|
||||
"allapp/utils/requestx"
|
||||
"allapp/utils/responsex"
|
||||
"allapp/utils/uniqueid"
|
||||
"context"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
// CreateSpace 创建空间
|
||||
func CreateSpace(c fiber.Ctx) error {
|
||||
dto := new(types.CreateSpaceDTO)
|
||||
vo := new(types.CreateSpaceVO)
|
||||
|
||||
if err := requestx.BindAndValidate(c, dto); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userID, err2 := middleware.GetUserID(c)
|
||||
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
var inviteCode string
|
||||
|
||||
for {
|
||||
// 生成邀请码
|
||||
code := utils.GenerateCode(6)
|
||||
|
||||
// 检查数据库是否存在
|
||||
|
||||
_, err := db.Queries.GetSpaceByInviteCode(c.Context(), code)
|
||||
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
inviteCode = code
|
||||
break
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spaceId := uniqueid.NextId()
|
||||
|
||||
err := db.WithTx(c.Context(), func(q *repo.Queries) error {
|
||||
// 创建空间
|
||||
params := repo.InsertSpaceParams{
|
||||
ID: spaceId,
|
||||
Name: dto.Name,
|
||||
InviteCode: inviteCode,
|
||||
}
|
||||
|
||||
err := q.InsertSpace(c.Context(), params)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将创建用户默认添加到该空间内
|
||||
spaceMemberParams := repo.InsertSpaceMemberParams{
|
||||
ID: uniqueid.NextId(),
|
||||
SpaceID: spaceId,
|
||||
UserID: userID,
|
||||
Role: 0,
|
||||
}
|
||||
|
||||
err = q.InsertSpaceMember(c.Context(), spaceMemberParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化记账
|
||||
err = initFinanceCategory(c.Context(), q, spaceId, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vo.SpaceId = spaceId
|
||||
vo.InviteCode = inviteCode
|
||||
|
||||
return responsex.OK(c, vo)
|
||||
}
|
||||
|
||||
func initFinanceCategory(ctx context.Context, q *repo.Queries, spaceId int64, userId int64) error {
|
||||
categoryDefaults, err := q.ListFinanceCategoryDefault(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(categoryDefaults) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
categorySpaces := make([]repo.BatchInsertFinanceCategorySpaceParams, 0, len(categoryDefaults))
|
||||
|
||||
for _, sysCat := range categoryDefaults {
|
||||
categorySpaces = append(categorySpaces, repo.BatchInsertFinanceCategorySpaceParams{
|
||||
ID: uniqueid.NextId(),
|
||||
SpaceID: spaceId,
|
||||
Name: sysCat.Name,
|
||||
Icon: sysCat.Icon,
|
||||
Type: sysCat.Type,
|
||||
SortNumber: sysCat.SortNumber,
|
||||
CreateBy: userId,
|
||||
UpdateBy: userId,
|
||||
})
|
||||
}
|
||||
|
||||
if _, err := q.BatchInsertFinanceCategorySpace(ctx, categorySpaces); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -13,7 +13,6 @@ const CtxUserIDKey = "user_id"
|
||||
// Auth 登录校验中间件
|
||||
func Auth() fiber.Handler {
|
||||
return func(c fiber.Ctx) error {
|
||||
|
||||
token := strings.TrimSpace(c.Get("Token"))
|
||||
if token == "" {
|
||||
return responsex.Unauthorized(c, "未登录")
|
||||
|
||||
@@ -2,6 +2,8 @@ package router
|
||||
|
||||
import (
|
||||
"allapp/api/handler/auth"
|
||||
"allapp/api/handler/space"
|
||||
"allapp/api/router/middleware"
|
||||
"allapp/config"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
@@ -14,7 +16,7 @@ func SetupRouters(app *fiber.App) {
|
||||
publicGroup := api.Group("")
|
||||
|
||||
// 2️⃣ 需要登录
|
||||
//authGroup := api.Group("", middleware.Auth())
|
||||
authGroup := api.Group("", middleware.Auth())
|
||||
//
|
||||
//// 3️⃣ 需要登录 + 需要空间
|
||||
//spaceGroup := api.Group("", middleware.Auth(), middleware.SpaceGuard())
|
||||
@@ -25,7 +27,8 @@ func SetupRouters(app *fiber.App) {
|
||||
authRouter.Post("/login/qq", auth.LoginQq)
|
||||
authRouter.Post("/login/wechat", auth.LoginWechat)
|
||||
|
||||
// 示例
|
||||
// 空间操作
|
||||
authGroup.Post("/space/create", space.CreateSpace)
|
||||
// authGroup.Get("/user/profile", user.GetProfile)
|
||||
// spaceGroup.Get("/space/info", space.GetInfo)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package types
|
||||
|
||||
type CreateSpaceDTO struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateSpaceVO struct {
|
||||
SpaceId int64 `json:"space_id"`
|
||||
InviteCode string `json:"invite_code"`
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
-- name: ListFinanceCategoryDefault :many
|
||||
SELECT * FROM finance_category_default;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- name: BatchInsertFinanceCategorySpace :copyfrom
|
||||
INSERT INTO finance_category_space (id, space_id, name, icon, type, sort_number,create_by,update_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6,$7,$8);
|
||||
@@ -2,3 +2,17 @@
|
||||
-- 根据id获取分享空间信息
|
||||
-- name: GetSpaceById :one
|
||||
SELECT * FROM space WHERE id = $1;
|
||||
|
||||
-- 创建空间
|
||||
-- name: InsertSpace :exec
|
||||
INSERT INTO space (
|
||||
id,name,invite_code,create_time,update_time
|
||||
) VALUES ($1,$2,$3,NOW(),NOW());
|
||||
|
||||
-- 删除空间
|
||||
-- name: DeleteSpace :exec
|
||||
DELETE FROM space WHERE id = $1;
|
||||
|
||||
-- 根据邀请码获取
|
||||
-- name: GetSpaceByInviteCode :one
|
||||
SELECT * FROM space WHERE invite_code = $1;
|
||||
@@ -3,4 +3,13 @@
|
||||
SELECT role
|
||||
FROM space_member
|
||||
WHERE user_id = $1
|
||||
AND space_id = $2;
|
||||
AND space_id = $2;
|
||||
|
||||
-- name: InsertSpaceMember :exec
|
||||
INSERT INTO space_member(id,space_id,user_id,role,is_default,join_time,update_time)
|
||||
VALUES ($1,$2,$3,$4,$5,NOW(),NOW());
|
||||
|
||||
-- name: CountUserSpaces :one
|
||||
SELECT COUNT(1)
|
||||
FROM space_member
|
||||
WHERE user_id = $1;
|
||||
@@ -0,0 +1,49 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: copyfrom.go
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// iteratorForBatchInsertFinanceCategorySpace implements pgx.CopyFromSource.
|
||||
type iteratorForBatchInsertFinanceCategorySpace struct {
|
||||
rows []BatchInsertFinanceCategorySpaceParams
|
||||
skippedFirstNextCall bool
|
||||
}
|
||||
|
||||
func (r *iteratorForBatchInsertFinanceCategorySpace) 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 iteratorForBatchInsertFinanceCategorySpace) Values() ([]interface{}, error) {
|
||||
return []interface{}{
|
||||
r.rows[0].ID,
|
||||
r.rows[0].SpaceID,
|
||||
r.rows[0].Name,
|
||||
r.rows[0].Icon,
|
||||
r.rows[0].Type,
|
||||
r.rows[0].SortNumber,
|
||||
r.rows[0].CreateBy,
|
||||
r.rows[0].UpdateBy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r iteratorForBatchInsertFinanceCategorySpace) Err() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *Queries) BatchInsertFinanceCategorySpace(ctx context.Context, arg []BatchInsertFinanceCategorySpaceParams) (int64, error) {
|
||||
return q.db.CopyFrom(ctx, []string{"finance_category_space"}, []string{"id", "space_id", "name", "icon", "type", "sort_number", "create_by", "update_by"}, &iteratorForBatchInsertFinanceCategorySpace{rows: arg})
|
||||
}
|
||||
@@ -15,6 +15,7 @@ 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 {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: finance_category_default.sql
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const listFinanceCategoryDefault = `-- name: ListFinanceCategoryDefault :many
|
||||
SELECT id, name, icon, type, sort_number, create_time, update_time FROM finance_category_default
|
||||
`
|
||||
|
||||
func (q *Queries) ListFinanceCategoryDefault(ctx context.Context) ([]FinanceCategoryDefault, error) {
|
||||
rows, err := q.db.Query(ctx, listFinanceCategoryDefault)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []FinanceCategoryDefault
|
||||
for rows.Next() {
|
||||
var i FinanceCategoryDefault
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Icon,
|
||||
&i.Type,
|
||||
&i.SortNumber,
|
||||
&i.CreateTime,
|
||||
&i.UpdateTime,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: finance_category_space.sql
|
||||
|
||||
package repo
|
||||
|
||||
type BatchInsertFinanceCategorySpaceParams struct {
|
||||
ID int64
|
||||
SpaceID int64
|
||||
Name string
|
||||
Icon string
|
||||
Type int16
|
||||
SortNumber int32
|
||||
CreateBy int64
|
||||
UpdateBy int64
|
||||
}
|
||||
@@ -8,11 +8,33 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type FinanceCategoryDefault struct {
|
||||
ID int64
|
||||
Name string
|
||||
Icon string
|
||||
Type int16
|
||||
SortNumber int32
|
||||
CreateTime pgtype.Timestamptz
|
||||
UpdateTime pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type FinanceCategorySpace struct {
|
||||
ID int64
|
||||
SpaceID int64
|
||||
Name string
|
||||
Icon string
|
||||
Type int16
|
||||
SortNumber int32
|
||||
CreateBy int64
|
||||
CreateTime pgtype.Timestamptz
|
||||
UpdateBy int64
|
||||
UpdateTime pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type Space struct {
|
||||
ID int64
|
||||
Name string
|
||||
InviteCode string
|
||||
OwnerID int64
|
||||
CreateTime pgtype.Timestamptz
|
||||
UpdateTime pgtype.Timestamptz
|
||||
}
|
||||
@@ -22,6 +44,7 @@ type SpaceMember struct {
|
||||
SpaceID int64
|
||||
UserID int64
|
||||
Role int16
|
||||
IsDefault int16
|
||||
JoinTime pgtype.Timestamptz
|
||||
UpdateTime pgtype.Timestamptz
|
||||
}
|
||||
@@ -30,7 +53,7 @@ type User struct {
|
||||
ID int64
|
||||
Nickname string
|
||||
Avatar string
|
||||
Status int32
|
||||
Status int16
|
||||
LastLoginTime pgtype.Timestamptz
|
||||
CreateTime pgtype.Timestamptz
|
||||
UpdateTime pgtype.Timestamptz
|
||||
@@ -39,7 +62,7 @@ type User struct {
|
||||
type UserOauth struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
Type int32
|
||||
Type int16
|
||||
Openid string
|
||||
CreateTime pgtype.Timestamptz
|
||||
UpdateTime pgtype.Timestamptz
|
||||
|
||||
@@ -9,8 +9,18 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const deleteSpace = `-- name: DeleteSpace :exec
|
||||
DELETE FROM space WHERE id = $1
|
||||
`
|
||||
|
||||
// 删除空间
|
||||
func (q *Queries) DeleteSpace(ctx context.Context, id int64) error {
|
||||
_, err := q.db.Exec(ctx, deleteSpace, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getSpaceById = `-- name: GetSpaceById :one
|
||||
SELECT id, name, invite_code, owner_id, create_time, update_time FROM space WHERE id = $1
|
||||
SELECT id, name, invite_code, create_time, update_time FROM space WHERE id = $1
|
||||
`
|
||||
|
||||
// 根据id获取分享空间信息
|
||||
@@ -21,9 +31,44 @@ func (q *Queries) GetSpaceById(ctx context.Context, id int64) (Space, error) {
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.InviteCode,
|
||||
&i.OwnerID,
|
||||
&i.CreateTime,
|
||||
&i.UpdateTime,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getSpaceByInviteCode = `-- name: GetSpaceByInviteCode :one
|
||||
SELECT id, name, invite_code, create_time, update_time FROM space WHERE invite_code = $1
|
||||
`
|
||||
|
||||
// 根据邀请码获取
|
||||
func (q *Queries) GetSpaceByInviteCode(ctx context.Context, inviteCode string) (Space, error) {
|
||||
row := q.db.QueryRow(ctx, getSpaceByInviteCode, inviteCode)
|
||||
var i Space
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.InviteCode,
|
||||
&i.CreateTime,
|
||||
&i.UpdateTime,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertSpace = `-- name: InsertSpace :exec
|
||||
INSERT INTO space (
|
||||
id,name,invite_code,create_time,update_time
|
||||
) VALUES ($1,$2,$3,NOW(),NOW())
|
||||
`
|
||||
|
||||
type InsertSpaceParams struct {
|
||||
ID int64
|
||||
Name string
|
||||
InviteCode string
|
||||
}
|
||||
|
||||
// 创建空间
|
||||
func (q *Queries) InsertSpace(ctx context.Context, arg InsertSpaceParams) error {
|
||||
_, err := q.db.Exec(ctx, insertSpace, arg.ID, arg.Name, arg.InviteCode)
|
||||
return err
|
||||
}
|
||||
@@ -9,6 +9,19 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const countUserSpaces = `-- name: CountUserSpaces :one
|
||||
SELECT COUNT(1)
|
||||
FROM space_member
|
||||
WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) CountUserSpaces(ctx context.Context, userID int64) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, countUserSpaces, userID)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const getUserSpaceRole = `-- name: GetUserSpaceRole :one
|
||||
SELECT role
|
||||
FROM space_member
|
||||
@@ -28,3 +41,27 @@ func (q *Queries) GetUserSpaceRole(ctx context.Context, arg GetUserSpaceRolePara
|
||||
err := row.Scan(&role)
|
||||
return role, err
|
||||
}
|
||||
|
||||
const insertSpaceMember = `-- name: InsertSpaceMember :exec
|
||||
INSERT INTO space_member(id,space_id,user_id,role,is_default,join_time,update_time)
|
||||
VALUES ($1,$2,$3,$4,$5,NOW(),NOW())
|
||||
`
|
||||
|
||||
type InsertSpaceMemberParams struct {
|
||||
ID int64
|
||||
SpaceID int64
|
||||
UserID int64
|
||||
Role int16
|
||||
IsDefault int16
|
||||
}
|
||||
|
||||
func (q *Queries) InsertSpaceMember(ctx context.Context, arg InsertSpaceMemberParams) error {
|
||||
_, err := q.db.Exec(ctx, insertSpaceMember,
|
||||
arg.ID,
|
||||
arg.SpaceID,
|
||||
arg.UserID,
|
||||
arg.Role,
|
||||
arg.IsDefault,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -26,15 +26,15 @@ LIMIT 1
|
||||
|
||||
type FindUserByOpenIDParams struct {
|
||||
Openid string
|
||||
Type int32
|
||||
Type int16
|
||||
}
|
||||
|
||||
type FindUserByOpenIDRow struct {
|
||||
UserID int64
|
||||
Nickname string
|
||||
Avatar string
|
||||
Status int32
|
||||
LoginType int32
|
||||
Status int16
|
||||
LoginType int16
|
||||
Openid string
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ type InsertUserParams struct {
|
||||
ID int64
|
||||
Nickname string
|
||||
Avatar string
|
||||
Status int32
|
||||
Status int16
|
||||
}
|
||||
|
||||
func (q *Queries) InsertUser(ctx context.Context, arg InsertUserParams) error {
|
||||
|
||||
@@ -25,7 +25,7 @@ INSERT INTO user_oauth (
|
||||
type InsertUserOAuthParams struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
Type int32
|
||||
Type int16
|
||||
Openid string
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ create table "user"
|
||||
primary key,
|
||||
nickname varchar(255) not null,
|
||||
avatar varchar(255) not null,
|
||||
status int default 0 not null,
|
||||
status smallint default 0 not null,
|
||||
last_login_time timestamp with time zone,
|
||||
create_time timestamp with time zone default now(),
|
||||
update_time timestamp with time zone default now()
|
||||
@@ -15,7 +15,7 @@ create table user_oauth
|
||||
id bigint not null
|
||||
primary key,
|
||||
user_id bigint not null,
|
||||
type int default 0 not null,
|
||||
type smallint default 0 not null,
|
||||
openid varchar(255) not null,
|
||||
create_time timestamp with time zone default now(),
|
||||
update_time timestamp with time zone default now()
|
||||
@@ -27,7 +27,6 @@ create table space
|
||||
primary key,
|
||||
name varchar(255) not null,
|
||||
invite_code varchar(30) not null,
|
||||
owner_id bigint not null,
|
||||
create_time timestamp with time zone default now(),
|
||||
update_time timestamp with time zone default now()
|
||||
);
|
||||
@@ -39,6 +38,36 @@ create table space_member
|
||||
space_id bigint not null,
|
||||
user_id bigint not null,
|
||||
role smallint default 2 not null,
|
||||
is_default smallint default 0 not null,
|
||||
join_time timestamp with time zone default now(),
|
||||
update_time timestamp with time zone default now()
|
||||
);
|
||||
|
||||
create table finance_category_default
|
||||
(
|
||||
id bigint not null
|
||||
primary key,
|
||||
name varchar(64) not null,
|
||||
icon varchar(64) not null,
|
||||
type smallint default 0 not null,
|
||||
sort_number integer default 0 not null,
|
||||
create_time timestamp with time zone default now(),
|
||||
update_time timestamp with time zone default now()
|
||||
);
|
||||
|
||||
create table finance_category_space
|
||||
(
|
||||
id bigint not null
|
||||
primary key,
|
||||
space_id bigint not null,
|
||||
name varchar(64) not null,
|
||||
icon varchar(64) not null,
|
||||
type smallint default 0 not null,
|
||||
sort_number integer default 0 not null,
|
||||
create_by bigint not null,
|
||||
create_time timestamp with time zone default now(),
|
||||
update_by bigint not null,
|
||||
update_time timestamp with time zone default now()
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package utils
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// JSONStringToStruct 将 JSON 字符串反序列化到指定结构体类型
|
||||
func JSONStringToStruct[T any](jsonStr string) (*T, error) {
|
||||
@@ -18,3 +22,24 @@ func JSONStringToMap(jsonStr string) (map[string]interface{}, error) {
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GenerateCode 生成指定长度的随机邀请码(大写字母+数字)
|
||||
// 不会返回错误,如果随机失败,会自动重试
|
||||
func GenerateCode(length int) string {
|
||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
code := make([]byte, length)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
for {
|
||||
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
||||
if err != nil {
|
||||
// 随机失败,重试
|
||||
continue
|
||||
}
|
||||
code[i] = charset[num.Int64()]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return string(code)
|
||||
}
|
||||
File renamed without changes.
Reference in new issue
Block a user