update
This commit is contained in:
parent
96d537c044
commit
b71e718308
24
Makefile
24
Makefile
@ -6,11 +6,11 @@ network:
|
|||||||
|
|
||||||
.PHONY: redis
|
.PHONY: redis
|
||||||
redis:
|
redis:
|
||||||
docker run --network management --name rd -d -p 6379:6379 redis:7.2.4 --requirepass "secret"
|
docker run --network management --name rd -d -p 6379:6379 redis:7.4-alpine --requirepass "secret"
|
||||||
|
|
||||||
.PHONY: postgres
|
.PHONY: postgres
|
||||||
postgres:
|
postgres:
|
||||||
docker run --name postgres --network management -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -d postgres:16-alpine
|
docker run --name postgres --network management -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=secret -d postgres:17-alpine
|
||||||
|
|
||||||
.PHONY: create_db
|
.PHONY: create_db
|
||||||
create_db:
|
create_db:
|
||||||
@ -26,31 +26,19 @@ psql:
|
|||||||
|
|
||||||
.PHONY: migrate_init
|
.PHONY: migrate_init
|
||||||
migrate_init:
|
migrate_init:
|
||||||
migrate create -ext sql -dir internal/db/migration -seq init_schema
|
migrate create -ext sql -dir internal/erpserver/repository/migration -seq init_schema
|
||||||
|
|
||||||
.PHONY: migrate_up
|
.PHONY: migrate_up
|
||||||
migrate_up:
|
migrate_up:
|
||||||
migrate -path internal/db/migration -database "$(DB_URL)" -verbose up
|
migrate -path internal/erpserver/repository/migration -database "$(DB_URL)" -verbose up
|
||||||
|
|
||||||
.PHONY: migrate_down
|
.PHONY: migrate_down
|
||||||
migrate_down:
|
migrate_down:
|
||||||
migrate -path internal/db/migration -database "$(DB_URL)" -verbose down
|
migrate -path internal/erpserver/repository/migration -database "$(DB_URL)" -verbose down
|
||||||
|
|
||||||
.PHONY: db
|
|
||||||
db:
|
|
||||||
sql2dbml --postgres doc/ss.sql -o doc/db.dbm
|
|
||||||
|
|
||||||
.PHONY: db_docs
|
|
||||||
db_docs:
|
|
||||||
dbdocs build doc/db.dbml
|
|
||||||
|
|
||||||
.PHONY: db_schema
|
.PHONY: db_schema
|
||||||
db_schema:
|
db_schema:
|
||||||
dbml2sql --postgres -o internal/db/migration/000001_init_schema.up.sql doc/db.dbml
|
dbml2sql --postgres -o internal/erpserver/repository/migration/000001_init_schema.up.sql doc/db.dbml
|
||||||
|
|
||||||
.PHONY: sqlc
|
|
||||||
sqlc:
|
|
||||||
sqlc generate
|
|
||||||
|
|
||||||
.PHONY: wire
|
.PHONY: wire
|
||||||
wire:
|
wire:
|
||||||
|
|||||||
20
cmd/erp.go
20
cmd/erp.go
@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"management/internal/erpserver"
|
"management/internal/erpserver"
|
||||||
|
"management/internal/erpserver/repository/seed"
|
||||||
"management/internal/pkg/config"
|
"management/internal/pkg/config"
|
||||||
|
|
||||||
"github.com/drhin/logger"
|
"github.com/drhin/logger"
|
||||||
@ -50,11 +51,22 @@ func runErp() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mux, fn, err := erpserver.NewWire(conf, l)
|
app, fn, err := erpserver.NewWire(conf, l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// database seed
|
||||||
|
if err = seed.Init(
|
||||||
|
app.ConfigRepo,
|
||||||
|
app.DepartmentRepo,
|
||||||
|
app.RoleRepo,
|
||||||
|
app.UserRepo,
|
||||||
|
app.MenuRepo,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
defer fn()
|
defer fn()
|
||||||
|
|
||||||
address := fmt.Sprintf("%s:%d", conf.App.Host, conf.App.Port)
|
address := fmt.Sprintf("%s:%d", conf.App.Host, conf.App.Port)
|
||||||
@ -63,19 +75,21 @@ func runErp() error {
|
|||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
Addr: address,
|
Addr: address,
|
||||||
Handler: mux,
|
Handler: app.Router,
|
||||||
ReadTimeout: 20 * time.Second,
|
ReadTimeout: 20 * time.Second,
|
||||||
WriteTimeout: 20 * time.Second,
|
WriteTimeout: 20 * time.Second,
|
||||||
MaxHeaderBytes: 1 << 20,
|
MaxHeaderBytes: 1 << 20,
|
||||||
}
|
}
|
||||||
return s.ListenAndServe()
|
return s.ListenAndServe()
|
||||||
} else {
|
} else {
|
||||||
s := endless.NewServer(address, mux)
|
s := endless.NewServer(address, app.Router)
|
||||||
s.ReadHeaderTimeout = 20 * time.Second
|
s.ReadHeaderTimeout = 20 * time.Second
|
||||||
s.WriteTimeout = 20 * time.Second
|
s.WriteTimeout = 20 * time.Second
|
||||||
s.MaxHeaderBytes = 1 << 20
|
s.MaxHeaderBytes = 1 << 20
|
||||||
return s.ListenAndServe()
|
return s.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@ -8,6 +8,11 @@ db:
|
|||||||
username: root
|
username: root
|
||||||
password: secret
|
password: secret
|
||||||
db_name: management
|
db_name: management
|
||||||
|
max_idle_conns: 10
|
||||||
|
max_open_conns: 100
|
||||||
|
conn_max_lifetime: 7h
|
||||||
|
conn_max_idle_time: 30m
|
||||||
|
log_mode: true
|
||||||
redis:
|
redis:
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 6379
|
port: 6379
|
||||||
|
|||||||
@ -34,8 +34,6 @@ Table "sys_user_login_log" {
|
|||||||
"id" BIGSERIAL [not null, increment]
|
"id" BIGSERIAL [not null, increment]
|
||||||
"created_at" TIMESTAMPTZ [not null, default: `NOW()`, note: '创建时间']
|
"created_at" TIMESTAMPTZ [not null, default: `NOW()`, note: '创建时间']
|
||||||
"email" VARCHAR(100) [not null, note: '邮箱地址']
|
"email" VARCHAR(100) [not null, note: '邮箱地址']
|
||||||
"username" VARCHAR(100) [not null, note: '用户名称']
|
|
||||||
"user_uuid" uuid [not null, note: '用户uuid']
|
|
||||||
"is_success" Boolean [not null, note: '是否登陆成功']
|
"is_success" Boolean [not null, note: '是否登陆成功']
|
||||||
"message" VARCHAR(300) [not null, note: '登陆消息']
|
"message" VARCHAR(300) [not null, note: '登陆消息']
|
||||||
"referer_url" VARCHAR(500) [not null, note: '上一个链接']
|
"referer_url" VARCHAR(500) [not null, note: '上一个链接']
|
||||||
@ -48,7 +46,6 @@ Table "sys_user_login_log" {
|
|||||||
id [pk]
|
id [pk]
|
||||||
created_at
|
created_at
|
||||||
email
|
email
|
||||||
username
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,8 +53,6 @@ Table "sys_audit_log" {
|
|||||||
"id" BIGSERIAL [not null, increment]
|
"id" BIGSERIAL [not null, increment]
|
||||||
"created_at" TIMESTAMPTZ [not null, default: `NOW()`, note: '创建时间']
|
"created_at" TIMESTAMPTZ [not null, default: `NOW()`, note: '创建时间']
|
||||||
"email" VARCHAR(100) [not null, note: '邮箱地址']
|
"email" VARCHAR(100) [not null, note: '邮箱地址']
|
||||||
"username" VARCHAR(100) [not null, note: '用户名称']
|
|
||||||
"user_uuid" uuid [not null, note: '用户uuid']
|
|
||||||
"start_at" TIMESTAMPTZ [not null, note: '请求开始时间']
|
"start_at" TIMESTAMPTZ [not null, note: '请求开始时间']
|
||||||
"end_at" TIMESTAMPTZ [not null, note: '请求结束时间']
|
"end_at" TIMESTAMPTZ [not null, note: '请求结束时间']
|
||||||
"duration" VARCHAR(10) [not null, note: '请求总时间']
|
"duration" VARCHAR(10) [not null, note: '请求总时间']
|
||||||
@ -74,7 +69,6 @@ Table "sys_audit_log" {
|
|||||||
id [pk]
|
id [pk]
|
||||||
created_at
|
created_at
|
||||||
email
|
email
|
||||||
username
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
go.mod
10
go.mod
@ -26,14 +26,16 @@ require (
|
|||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/crypto v0.38.0
|
golang.org/x/crypto v0.38.0
|
||||||
gorm.io/driver/postgres v1.5.11
|
gorm.io/driver/postgres v1.5.11
|
||||||
gorm.io/gorm v1.26.1
|
gorm.io/gorm v1.30.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.9.2 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
@ -54,9 +56,11 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/image v0.27.0 // indirect
|
golang.org/x/image v0.27.0 // indirect
|
||||||
golang.org/x/net v0.40.0 // indirect
|
golang.org/x/net v0.40.0 // indirect
|
||||||
golang.org/x/sync v0.14.0 // indirect
|
golang.org/x/sync v0.15.0 // indirect
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
golang.org/x/text v0.25.0 // indirect
|
golang.org/x/text v0.26.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
gorm.io/datatypes v1.2.5 // indirect
|
||||||
|
gorm.io/driver/mysql v1.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
14
go.sum
14
go.sum
@ -1,3 +1,5 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/alexedwards/scs/postgresstore v0.0.0-20250417082927-ab20b3feb5e9 h1:FGBhs+LG4w1y511QLcuLr1xfhI7Fbyq6Da1TCf6EQq4=
|
github.com/alexedwards/scs/postgresstore v0.0.0-20250417082927-ab20b3feb5e9 h1:FGBhs+LG4w1y511QLcuLr1xfhI7Fbyq6Da1TCf6EQq4=
|
||||||
@ -38,6 +40,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||||
|
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
||||||
|
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
@ -166,6 +170,8 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||||
|
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -199,6 +205,8 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
@ -217,7 +225,13 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
|
||||||
|
gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
|
||||||
|
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
|
||||||
|
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
|
||||||
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
|
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
|
||||||
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||||
gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw=
|
gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw=
|
||||||
gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
|
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
|
||||||
|
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
|
|||||||
46
internal/erpserver/app.go
Normal file
46
internal/erpserver/app.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package erpserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"management/internal/erpserver/model/system"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
UserRepo system.UserRepository
|
||||||
|
RoleRepo system.RoleRepository
|
||||||
|
MenuRepo system.MenuRepository
|
||||||
|
RoleMenuRepo system.RoleMenuRepository
|
||||||
|
DepartmentRepo system.DepartmentRepository
|
||||||
|
ConfigRepo system.ConfigRepository
|
||||||
|
LoginLogRepo system.LoginLogRepository
|
||||||
|
AuditLogRepo system.AuditLogRepository
|
||||||
|
|
||||||
|
Router *chi.Mux
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApp(
|
||||||
|
UserRepo system.UserRepository,
|
||||||
|
RoleRepo system.RoleRepository,
|
||||||
|
MenuRepo system.MenuRepository,
|
||||||
|
RoleMenuRepo system.RoleMenuRepository,
|
||||||
|
DepartmentRepo system.DepartmentRepository,
|
||||||
|
ConfigRepo system.ConfigRepository,
|
||||||
|
LoginLogRepo system.LoginLogRepository,
|
||||||
|
AuditLogRepo system.AuditLogRepository,
|
||||||
|
|
||||||
|
Router *chi.Mux,
|
||||||
|
) App {
|
||||||
|
return App{
|
||||||
|
UserRepo: UserRepo,
|
||||||
|
RoleRepo: RoleRepo,
|
||||||
|
MenuRepo: MenuRepo,
|
||||||
|
RoleMenuRepo: RoleMenuRepo,
|
||||||
|
DepartmentRepo: DepartmentRepo,
|
||||||
|
ConfigRepo: ConfigRepo,
|
||||||
|
LoginLogRepo: LoginLogRepo,
|
||||||
|
AuditLogRepo: AuditLogRepo,
|
||||||
|
|
||||||
|
Router: Router,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -101,7 +101,7 @@ func (h *ConfigHandler) Save(w http.ResponseWriter, r *http.Request) {
|
|||||||
if id == 0 {
|
if id == 0 {
|
||||||
arg := &systemModel.Config{
|
arg := &systemModel.Config{
|
||||||
Key: key,
|
Key: key,
|
||||||
Value: value,
|
Value: []byte(value),
|
||||||
}
|
}
|
||||||
err := h.configService.Create(ctx, arg)
|
err := h.configService.Create(ctx, arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -121,7 +121,7 @@ func (h *ConfigHandler) Save(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Value = value
|
res.Value = []byte(value)
|
||||||
err = h.configService.Update(ctx, res)
|
err = h.configService.Update(ctx, res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.JSONErr(w, err.Error())
|
h.JSONErr(w, err.Error())
|
||||||
|
|||||||
@ -33,12 +33,12 @@ func (h *HomeHandler) Dashboard(w http.ResponseWriter, r *http.Request) {
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
auth := h.AuthUser(ctx)
|
auth := h.AuthUser(ctx)
|
||||||
user, _ := h.userService.Get(ctx, auth.ID)
|
user, _ := h.userService.Get(ctx, auth.ID)
|
||||||
t := h.loginLogService.LoginLatestTime(ctx, auth.Email)
|
lt, _ := h.loginLogService.LoginTime(ctx, auth.Email)
|
||||||
c := h.loginLogService.LoginCount(ctx, auth.Email)
|
c := h.loginLogService.LoginCount(ctx, auth.Email)
|
||||||
h.HTML(w, r, "home/dashboard.tmpl", map[string]any{
|
h.HTML(w, r, "home/dashboard.tmpl", map[string]any{
|
||||||
"Auth": auth,
|
"Auth": auth,
|
||||||
"User": user,
|
"User": user,
|
||||||
"LastLoginTime": t,
|
"LoginTime": lt,
|
||||||
"LoginCount": c,
|
"LoginCount": c,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,3 +54,8 @@ type SysMenuDto struct {
|
|||||||
|
|
||||||
Children []*SysMenuDto `json:"children"`
|
Children []*SysMenuDto `json:"children"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LoginTimeDto struct {
|
||||||
|
ThisLoginTime time.Time
|
||||||
|
LastLoginTime time.Time
|
||||||
|
}
|
||||||
|
|||||||
@ -5,22 +5,26 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
|
|
||||||
|
"gorm.io/datatypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigRepository interface {
|
type ConfigRepository interface {
|
||||||
|
Initialize(ctx context.Context) error
|
||||||
Create(ctx context.Context, obj *Config) error
|
Create(ctx context.Context, obj *Config) error
|
||||||
Update(ctx context.Context, obj *Config) error
|
Update(ctx context.Context, obj *Config) error
|
||||||
Get(ctx context.Context, id int32) (*Config, error)
|
Get(ctx context.Context, id int32) (*Config, error)
|
||||||
GetByKey(ctx context.Context, key string) (*Config, error)
|
GetByKey(ctx context.Context, key string) (*Config, error)
|
||||||
|
GetValueByKey(ctx context.Context, key string) ([]byte, error)
|
||||||
List(ctx context.Context, q dto.SearchDto) ([]*Config, int64, error)
|
List(ctx context.Context, q dto.SearchDto) ([]*Config, int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ID int32 `json:"id" gorm:"primaryKey;autoIncrement;not null"`
|
ID int32 `json:"id" gorm:"primaryKey;autoIncrement;not null"`
|
||||||
Key string `json:"key" gorm:"type:varchar(200);not null;uniqueIndex"`
|
Key string `json:"key" gorm:"type:varchar(200);not null;uniqueIndex"`
|
||||||
Value string `json:"value" gorm:"type:jsonb;not null;"`
|
Value datatypes.JSON `json:"value" gorm:"type:jsonb;not null;"`
|
||||||
CreatedAt time.Time `json:"created_at" gorm:"type:timestamptz;not null;default:'now()'"`
|
CreatedAt time.Time `json:"created_at" gorm:"type:timestamptz;not null;default:'now()'"`
|
||||||
UpdatedAt time.Time `json:"updated_at" gorm:"type:timestamptz;not null;default:'0001-01-01 00:00:00+8';"`
|
UpdatedAt time.Time `json:"updated_at" gorm:"type:timestamptz;not null;default:'0001-01-01 00:00:00+8';"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Config) TableName() string {
|
func (Config) TableName() string {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DepartmentRepository interface {
|
type DepartmentRepository interface {
|
||||||
|
Initialize(ctx context.Context) error
|
||||||
Create(ctx context.Context, obj *Department) error
|
Create(ctx context.Context, obj *Department) error
|
||||||
Update(ctx context.Context, obj *Department) error
|
Update(ctx context.Context, obj *Department) error
|
||||||
Get(ctx context.Context, id int32) (*Department, error)
|
Get(ctx context.Context, id int32) (*Department, error)
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type LoginLogRepository interface {
|
type LoginLogRepository interface {
|
||||||
Create(ctx context.Context, obj *LoginLog) error
|
Create(ctx context.Context, obj *LoginLog) error
|
||||||
GetLatest(ctx context.Context, email string) (*LoginLog, error)
|
GetLatest(ctx context.Context, email string) ([]*LoginLog, error)
|
||||||
List(ctx context.Context, q dto.SearchDto) ([]*LoginLog, int64, error)
|
List(ctx context.Context, q dto.SearchDto) ([]*LoginLog, int64, error)
|
||||||
Count(ctx context.Context, email string) (int64, error)
|
Count(ctx context.Context, email string) (int64, error)
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ type LoginLog struct {
|
|||||||
Browser string `json:"browser" gorm:"type:varchar(100);not null;"`
|
Browser string `json:"browser" gorm:"type:varchar(100);not null;"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (LoginLog) TableName() string {
|
func (*LoginLog) TableName() string {
|
||||||
return "sys_user_login_log"
|
return "sys_user_login_log"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MenuRepository interface {
|
type MenuRepository interface {
|
||||||
Create(ctx context.Context, obj *Menu) error
|
Initialize(ctx context.Context) error
|
||||||
|
Create(ctx context.Context, obj *Menu) (*Menu, error)
|
||||||
Update(ctx context.Context, obj *Menu) error
|
Update(ctx context.Context, obj *Menu) error
|
||||||
Get(ctx context.Context, id int32) (*Menu, error)
|
Get(ctx context.Context, id int32) (*Menu, error)
|
||||||
GetByUrl(ctx context.Context, url string) (*Menu, error)
|
GetByUrl(ctx context.Context, url string) (*Menu, error)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RoleRepository interface {
|
type RoleRepository interface {
|
||||||
|
Initialize(ctx context.Context) (*Role, error)
|
||||||
Create(ctx context.Context, obj *Role) error
|
Create(ctx context.Context, obj *Role) error
|
||||||
Update(ctx context.Context, obj *Role) error
|
Update(ctx context.Context, obj *Role) error
|
||||||
Get(ctx context.Context, id int32) (*Role, error)
|
Get(ctx context.Context, id int32) (*Role, error)
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UserRepository interface {
|
type UserRepository interface {
|
||||||
|
Initialize(ctx context.Context, departId, roleId int32) error
|
||||||
Create(ctx context.Context, obj *User) error
|
Create(ctx context.Context, obj *User) error
|
||||||
Update(ctx context.Context, obj *User) error
|
Update(ctx context.Context, obj *User) error
|
||||||
Get(ctx context.Context, id int32) (*User, error)
|
Get(ctx context.Context, id int32) (*User, error)
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
DROP TABLE IF EXISTS sys_user;
|
||||||
|
DROP TABLE IF EXISTS sys_user_login_log;
|
||||||
|
DROP TABLE IF EXISTS sys_audit_log;
|
||||||
|
DROP TABLE IF EXISTS sessions;
|
||||||
|
DROP TABLE IF EXISTS sys_department;
|
||||||
|
DROP TABLE IF EXISTS sys_role;
|
||||||
|
DROP TABLE IF EXISTS sys_menu;
|
||||||
|
DROP TABLE IF EXISTS sys_role_menu;
|
||||||
|
DROP TABLE IF EXISTS sys_config;
|
||||||
|
DROP TABLE IF EXISTS categories;
|
||||||
|
DROP TABLE IF EXISTS customers;
|
||||||
|
DROP TABLE IF EXISTS customer_contact;
|
||||||
|
DROP TABLE IF EXISTS projects;
|
||||||
|
DROP TABLE IF EXISTS project_files;
|
||||||
|
DROP TABLE IF EXISTS budgets;
|
||||||
|
DROP TABLE IF EXISTS incomes;
|
||||||
|
DROP TABLE IF EXISTS expenses;
|
||||||
@ -0,0 +1,666 @@
|
|||||||
|
-- SQL dump generated using DBML (dbml.dbdiagram.io)
|
||||||
|
-- Database: PostgreSQL
|
||||||
|
-- Generated at: 2025-06-12T01:21:05.629Z
|
||||||
|
|
||||||
|
CREATE TABLE "sys_user" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"uuid" uuid NOT NULL,
|
||||||
|
"email" VARCHAR(100) NOT NULL,
|
||||||
|
"username" VARCHAR(100) NOT NULL,
|
||||||
|
"hashed_password" bytea NOT NULL,
|
||||||
|
"salt" VARCHAR(20) NOT NULL,
|
||||||
|
"avatar" VARCHAR(200) NOT NULL,
|
||||||
|
"gender" INT NOT NULL DEFAULT 0,
|
||||||
|
"department_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"role_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"status" INT NOT NULL DEFAULT 0,
|
||||||
|
"change_password_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_user_login_log" (
|
||||||
|
"id" BIGSERIAL NOT NULL,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"email" VARCHAR(100) NOT NULL,
|
||||||
|
"is_success" Boolean NOT NULL,
|
||||||
|
"message" VARCHAR(300) NOT NULL,
|
||||||
|
"referer_url" VARCHAR(500) NOT NULL,
|
||||||
|
"url" VARCHAR(500) NOT NULL,
|
||||||
|
"os" VARCHAR(50) NOT NULL,
|
||||||
|
"ip" VARCHAR(20) NOT NULL,
|
||||||
|
"browser" VARCHAR(100) NOT NULL,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_audit_log" (
|
||||||
|
"id" BIGSERIAL NOT NULL,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"email" VARCHAR(100) NOT NULL,
|
||||||
|
"start_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"end_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"duration" VARCHAR(10) NOT NULL,
|
||||||
|
"url" VARCHAR(500) NOT NULL,
|
||||||
|
"method" VARCHAR(50) NOT NULL,
|
||||||
|
"parameters" VARCHAR NOT NULL,
|
||||||
|
"referer_url" VARCHAR(500) NOT NULL,
|
||||||
|
"os" VARCHAR(50) NOT NULL,
|
||||||
|
"ip" VARCHAR(20) NOT NULL,
|
||||||
|
"browser" VARCHAR(100) NOT NULL,
|
||||||
|
"remark" VARCHAR(300) NOT NULL,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sessions" (
|
||||||
|
"token" TEXT NOT NULL,
|
||||||
|
"data" BYTEA NOT NULL,
|
||||||
|
"expiry" TIMESTAMPTZ NOT NULL,
|
||||||
|
PRIMARY KEY ("token")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_department" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"name" VARCHAR(200) NOT NULL,
|
||||||
|
"parent_id" INT NOT NULL,
|
||||||
|
"parent_path" VARCHAR(500) NOT NULL,
|
||||||
|
"status" INT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_role" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"name" VARCHAR(200) NOT NULL,
|
||||||
|
"display_name" VARCHAR(200) NOT NULL,
|
||||||
|
"parent_id" INT NOT NULL,
|
||||||
|
"parent_path" VARCHAR(500) NOT NULL,
|
||||||
|
"vip" Boolean NOT NULL,
|
||||||
|
"status" INT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_menu" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"name" VARCHAR(200) NOT NULL,
|
||||||
|
"display_name" VARCHAR(200) NOT NULL,
|
||||||
|
"url" VARCHAR(200) NOT NULL,
|
||||||
|
"type" VARCHAR(50) NOT NULL,
|
||||||
|
"parent_id" INT NOT NULL,
|
||||||
|
"parent_path" VARCHAR(500) NOT NULL,
|
||||||
|
"avatar" VARCHAR(100) NOT NULL,
|
||||||
|
"style" VARCHAR(100) NOT NULL,
|
||||||
|
"visible" Boolean NOT NULL,
|
||||||
|
"is_list" Boolean NOT NULL,
|
||||||
|
"status" INT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_role_menu" (
|
||||||
|
"role_id" INT NOT NULL,
|
||||||
|
"menu_id" INT NOT NULL,
|
||||||
|
PRIMARY KEY ("role_id", "menu_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "sys_config" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"key" VARCHAR(100) NOT NULL,
|
||||||
|
"value" jsonb NOT NULL,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "categories" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"name" VARCHAR(100) NOT NULL,
|
||||||
|
"icon" VARCHAR(300) NOT NULL DEFAULT '',
|
||||||
|
"description" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"letter" VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
"parent_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"parent_path" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "customers" (
|
||||||
|
"id" BIGINT NOT NULL,
|
||||||
|
"name" VARCHAR(100) NOT NULL,
|
||||||
|
"category" INT NOT NULL DEFAULT 0,
|
||||||
|
"source" INT NOT NULL DEFAULT 0,
|
||||||
|
"address" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"contact_name" VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
"contact_phone" VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_by" INT NOT NULL DEFAULT 0,
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"updated_by" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "customer_contact" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"name" VARCHAR(100) NOT NULL,
|
||||||
|
"telephone" VARCHAR(50) NOT NULL,
|
||||||
|
"customer_id" BIGINT NOT NULL,
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_by" INT NOT NULL DEFAULT 0,
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"updated_by" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "projects" (
|
||||||
|
"id" BIGINT NOT NULL,
|
||||||
|
"name" VARCHAR(100) NOT NULL,
|
||||||
|
"start_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"end_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"customer_id" BIGINT NOT NULL,
|
||||||
|
"total_money" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
"description" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"apply_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"apply_user_id" INT NOT NULL,
|
||||||
|
"manager_id" INT NOT NULL,
|
||||||
|
"members" VARCHAR(1000) NOT NULL,
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"updated_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "project_files" (
|
||||||
|
"id" BIGINT NOT NULL,
|
||||||
|
"name" VARCHAR(100) NOT NULL,
|
||||||
|
"path" VARCHAR(500) NOT NULL,
|
||||||
|
"project_id" BIGINT NOT NULL,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "budgets" (
|
||||||
|
"id" BIGSERIAL NOT NULL,
|
||||||
|
"project_id" BIGINT NOT NULL,
|
||||||
|
"name" VARCHAR(100) NOT NULL,
|
||||||
|
"budget_type" INT NOT NULL,
|
||||||
|
"category" INT NOT NULL,
|
||||||
|
"start_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"end_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"amount" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
"used_amount" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
"remaining_amount" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
"remark" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"sort" INT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"updated_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "incomes" (
|
||||||
|
"id" BIGSERIAL NOT NULL,
|
||||||
|
"project_id" BIGINT NOT NULL,
|
||||||
|
"budget_id" BIGINT NOT NULL DEFAULT 0,
|
||||||
|
"amount" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
"income_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"income_type" INT NOT NULL,
|
||||||
|
"income_bank" INT NOT NULL,
|
||||||
|
"remark" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"updated_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE "expenses" (
|
||||||
|
"id" BIGSERIAL NOT NULL,
|
||||||
|
"project_id" BIGINT NOT NULL,
|
||||||
|
"budget_id" BIGINT NOT NULL DEFAULT 0,
|
||||||
|
"amount" DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
"expenses_at" TIMESTAMPTZ NOT NULL,
|
||||||
|
"expenses_type" INT NOT NULL,
|
||||||
|
"remark" VARCHAR(500) NOT NULL DEFAULT '',
|
||||||
|
"status" SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT (NOW()),
|
||||||
|
"created_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT ('0001-01-01 00:00:00+8'),
|
||||||
|
"updated_user_id" INT NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_user" ("uuid");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_user" ("username");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_user" ("email");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_user" ("status");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_user_login_log" ("created_at");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_user_login_log" ("email");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_audit_log" ("created_at");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_audit_log" ("email");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sessions" ("expiry");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_department" ("name");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_department" ("status");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_role" ("name");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_role" ("display_name");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_role" ("status");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_menu" ("url");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_menu" ("type");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_menu" ("parent_id");
|
||||||
|
|
||||||
|
CREATE INDEX ON "sys_menu" ("status");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "sys_config" ("key");
|
||||||
|
|
||||||
|
CREATE INDEX ON "categories" ("name");
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX ON "categories" ("letter");
|
||||||
|
|
||||||
|
CREATE INDEX ON "customers" ("name");
|
||||||
|
|
||||||
|
CREATE INDEX ON "customer_contact" ("name");
|
||||||
|
|
||||||
|
CREATE INDEX ON "customer_contact" ("telephone");
|
||||||
|
|
||||||
|
CREATE INDEX ON "projects" ("name");
|
||||||
|
|
||||||
|
CREATE INDEX ON "project_files" ("name");
|
||||||
|
|
||||||
|
CREATE INDEX ON "budgets" ("project_id");
|
||||||
|
|
||||||
|
CREATE INDEX ON "budgets" ("category");
|
||||||
|
|
||||||
|
CREATE INDEX ON "incomes" ("project_id");
|
||||||
|
|
||||||
|
CREATE INDEX ON "incomes" ("budget_id");
|
||||||
|
|
||||||
|
CREATE INDEX ON "incomes" ("income_type");
|
||||||
|
|
||||||
|
CREATE INDEX ON "expenses" ("project_id");
|
||||||
|
|
||||||
|
CREATE INDEX ON "expenses" ("budget_id");
|
||||||
|
|
||||||
|
CREATE INDEX ON "expenses" ("expenses_type");
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."email" IS '邮箱地址';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."username" IS '用户名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."hashed_password" IS '加密密码';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."salt" IS '密码盐值';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."avatar" IS '头像';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."gender" IS '性别';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."department_id" IS '部门';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."role_id" IS '角色';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."change_password_at" IS '密码修改时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."email" IS '邮箱地址';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."is_success" IS '是否登陆成功';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."message" IS '登陆消息';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."referer_url" IS '上一个链接';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."url" IS '链接';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."os" IS '系统';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."ip" IS 'ip';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_user_login_log"."browser" IS '浏览器';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."email" IS '邮箱地址';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."start_at" IS '请求开始时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."end_at" IS '请求结束时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."duration" IS '请求总时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."url" IS '请求链接';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."method" IS '请求类型';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."parameters" IS '请求参数';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."referer_url" IS '上一个链接';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."os" IS '系统';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."ip" IS 'ip';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."browser" IS '浏览器';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_audit_log"."remark" IS '备注';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sessions"."token" IS 'token';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sessions"."data" IS 'data';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sessions"."expiry" IS 'expiry';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."name" IS '部门名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."parent_id" IS '上级id';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."parent_path" IS '树路径';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_department"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."display_name" IS '显示名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."parent_id" IS '上级id';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."parent_path" IS '树路径';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."vip" IS '是否vip';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."display_name" IS '显示名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."url" IS '菜单url';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."type" IS '菜单类型(node, menu, btn)';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."parent_id" IS '上级id';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."parent_path" IS '树路径';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."avatar" IS '菜单图标';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."style" IS '菜单样式';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."visible" IS '是否可见';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."is_list" IS '是否列表';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_menu"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role_menu"."role_id" IS '角色id';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_role_menu"."menu_id" IS '菜单id';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_config"."key" IS '存储键';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_config"."value" IS '存储值';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_config"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "sys_config"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."icon" IS '图标';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."description" IS '描述';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."letter" IS '拼音';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."parent_id" IS '父级ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."parent_path" IS '树路径';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "categories"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."category" IS '类别';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."source" IS '来源';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."address" IS '地址';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."contact_name" IS '主要联系人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."contact_phone" IS '主要联系人手机';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."created_by" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customers"."updated_by" IS '更新人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."telephone" IS '联系方式';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."customer_id" IS '客户ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."created_by" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "customer_contact"."updated_by" IS '更新人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."start_at" IS '开始时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."end_at" IS '结束时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."customer_id" IS '客户ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."total_money" IS '总金额';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."description" IS '简介';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."apply_at" IS '申请时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."apply_user_id" IS '申请人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."manager_id" IS '项目经理';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."members" IS '项目成员';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."created_user_id" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "projects"."updated_user_id" IS '更新人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."path" IS '路径';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."project_id" IS '项目ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "project_files"."created_user_id" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."project_id" IS '项目ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."name" IS '名称';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."budget_type" IS '预算类型: 收入/支出';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."category" IS '类别';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."start_at" IS '开始时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."end_at" IS '结束时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."amount" IS '预算金额';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."used_amount" IS '已使用金额';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."remaining_amount" IS '剩余金额';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."remark" IS '备注';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."sort" IS '排序';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."created_user_id" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "budgets"."updated_user_id" IS '更新人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."project_id" IS '项目ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."budget_id" IS '预算ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."amount" IS '收入金额';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."income_at" IS '收入时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."income_type" IS '收入类型';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."income_bank" IS '收入银行';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."remark" IS '备注';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."created_user_id" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "incomes"."updated_user_id" IS '更新人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."id" IS 'ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."project_id" IS '项目ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."budget_id" IS '预算ID';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."amount" IS '支出金额';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."expenses_at" IS '支出时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."expenses_type" IS '支出类型';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."remark" IS '备注';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."status" IS '状态';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."created_at" IS '创建时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."created_user_id" IS '创建人';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."updated_at" IS '更新时间';
|
||||||
|
|
||||||
|
COMMENT ON COLUMN "expenses"."updated_user_id" IS '更新人';
|
||||||
46
internal/erpserver/repository/seed/seed.go
Normal file
46
internal/erpserver/repository/seed/seed.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package seed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"management/internal/erpserver/model/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(
|
||||||
|
configRepository system.ConfigRepository,
|
||||||
|
departmentRepository system.DepartmentRepository,
|
||||||
|
roleRepository system.RoleRepository,
|
||||||
|
userRepository system.UserRepository,
|
||||||
|
menuRepository system.MenuRepository,
|
||||||
|
) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// 后台pear配置
|
||||||
|
if err := configRepository.Initialize(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 部门
|
||||||
|
err := departmentRepository.Initialize(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 角色
|
||||||
|
role, err := roleRepository.Initialize(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户
|
||||||
|
if err := userRepository.Initialize(ctx, 0, role.ID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单
|
||||||
|
if err = menuRepository.Initialize(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/drhin/logger"
|
"github.com/drhin/logger"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
gl "gorm.io/gorm/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type txCtxKey struct{}
|
type txCtxKey struct{}
|
||||||
@ -59,15 +60,19 @@ func NewDB(log *logger.Logger, config *config.Config) (*gorm.DB, func(), error)
|
|||||||
config.DB.DBName,
|
config.DB.DBName,
|
||||||
config.DB.Port,
|
config.DB.Port,
|
||||||
)
|
)
|
||||||
db, err := gorm.Open(postgres.New(postgres.Config{
|
pgConfig := postgres.Config{
|
||||||
DSN: dsn,
|
DSN: dsn,
|
||||||
PreferSimpleProtocol: true, // disables implicit prepared statement usage
|
PreferSimpleProtocol: true, // disables implicit prepared statement usage
|
||||||
}), &gorm.Config{})
|
}
|
||||||
|
db, err := gorm.Open(postgres.New(pgConfig), &gorm.Config{
|
||||||
|
Logger: getGormLogger(config),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
db = db.Debug()
|
// db.Debug 会默认显示日志
|
||||||
|
//db = db.Debug()
|
||||||
|
|
||||||
// Connection Pool config
|
// Connection Pool config
|
||||||
sqlDB, err := db.DB()
|
sqlDB, err := db.DB()
|
||||||
@ -75,9 +80,24 @@ func NewDB(log *logger.Logger, config *config.Config) (*gorm.DB, func(), error)
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlDB.SetMaxIdleConns(10)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
sqlDB.SetMaxOpenConns(100)
|
defer cancel()
|
||||||
sqlDB.SetConnMaxLifetime(time.Hour)
|
|
||||||
|
if err := sqlDB.PingContext(ctx); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置最大空闲连接数(默认 2)
|
||||||
|
sqlDB.SetMaxIdleConns(config.DB.MaxIdleConns)
|
||||||
|
|
||||||
|
// 设置最大打开连接数(默认 0 无限制)
|
||||||
|
sqlDB.SetMaxOpenConns(config.DB.MaxOpenConns)
|
||||||
|
|
||||||
|
// 设置连接最大存活时间
|
||||||
|
sqlDB.SetConnMaxLifetime(config.DB.ConnMaxLifetime)
|
||||||
|
|
||||||
|
// 设置连接最大空闲时间
|
||||||
|
sqlDB.SetConnMaxIdleTime(config.DB.ConnMaxIdleTime)
|
||||||
|
|
||||||
cleanup := func() {
|
cleanup := func() {
|
||||||
if err := sqlDB.Close(); err != nil {
|
if err := sqlDB.Close(); err != nil {
|
||||||
@ -88,6 +108,13 @@ func NewDB(log *logger.Logger, config *config.Config) (*gorm.DB, func(), error)
|
|||||||
return db, cleanup, nil
|
return db, cleanup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGormLogger(config *config.Config) gl.Interface {
|
||||||
|
if config.DB.LogMode {
|
||||||
|
return gl.Default.LogMode(gl.Info) // 开发环境显示日志
|
||||||
|
}
|
||||||
|
return gl.Default.LogMode(gl.Silent)
|
||||||
|
}
|
||||||
|
|
||||||
//var (
|
//var (
|
||||||
// once sync.Once
|
// once sync.Once
|
||||||
// // 全局变量,方便其它包直接调用已初始化好的 datastore 实例.
|
// // 全局变量,方便其它包直接调用已初始化好的 datastore 实例.
|
||||||
|
|||||||
@ -2,10 +2,15 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/erpserver/model/system"
|
"management/internal/erpserver/model/system"
|
||||||
"management/internal/erpserver/repository"
|
"management/internal/erpserver/repository"
|
||||||
|
"management/internal/pkg/database"
|
||||||
|
"management/internal/pkg/know/pearadmin"
|
||||||
|
|
||||||
|
"gorm.io/datatypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type configRepository struct {
|
type configRepository struct {
|
||||||
@ -18,6 +23,26 @@ func NewConfigRepository(repo *repository.Repository) system.ConfigRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *configRepository) Initialize(ctx context.Context) error {
|
||||||
|
_, err := r.GetByKey(ctx, pearadmin.PearKey)
|
||||||
|
if err != nil {
|
||||||
|
if database.IsNoRows(err) {
|
||||||
|
b, e := json.Marshal(pearadmin.PearJson)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
s := system.Config{
|
||||||
|
Key: pearadmin.PearKey,
|
||||||
|
Value: datatypes.JSON(b),
|
||||||
|
}
|
||||||
|
return r.Create(ctx, &s)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *configRepository) Create(ctx context.Context, obj *system.Config) error {
|
func (r *configRepository) Create(ctx context.Context, obj *system.Config) error {
|
||||||
return r.repo.DB(ctx).Create(obj).Error
|
return r.repo.DB(ctx).Create(obj).Error
|
||||||
}
|
}
|
||||||
@ -44,6 +69,15 @@ func (r *configRepository) GetByKey(ctx context.Context, key string) (*system.Co
|
|||||||
return &obj, nil
|
return &obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *configRepository) GetValueByKey(ctx context.Context, key string) ([]byte, error) {
|
||||||
|
var obj system.Config
|
||||||
|
err := r.repo.DB(ctx).Where("key = ?", key).First(&obj).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *configRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.Config, int64, error) {
|
func (r *configRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.Config, int64, error) {
|
||||||
query := r.repo.DB(ctx).
|
query := r.repo.DB(ctx).
|
||||||
Model(&system.Config{}).
|
Model(&system.Config{}).
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/erpserver/model/system"
|
"management/internal/erpserver/model/system"
|
||||||
@ -18,6 +19,26 @@ func NewDepartmentRepository(repo *repository.Repository) system.DepartmentRepos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *departmentRepository) Initialize(ctx context.Context) error {
|
||||||
|
var count int64
|
||||||
|
if err := r.repo.DB(ctx).Model(&system.Department{}).Count(&count).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
obj := system.Department{
|
||||||
|
Name: "公司",
|
||||||
|
ParentID: 0,
|
||||||
|
ParentPath: ",0,",
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
return r.Create(ctx, &obj)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *departmentRepository) Create(ctx context.Context, obj *system.Department) error {
|
func (r *departmentRepository) Create(ctx context.Context, obj *system.Department) error {
|
||||||
return r.repo.DB(ctx).Create(obj).Error
|
return r.repo.DB(ctx).Create(obj).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,17 +22,18 @@ func (s *loginLogRepository) Create(ctx context.Context, obj *system.LoginLog) e
|
|||||||
return s.repo.DB(ctx).Create(obj).Error
|
return s.repo.DB(ctx).Create(obj).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *loginLogRepository) GetLatest(ctx context.Context, email string) (*system.LoginLog, error) {
|
func (s *loginLogRepository) GetLatest(ctx context.Context, email string) ([]*system.LoginLog, error) {
|
||||||
var log system.LoginLog
|
var logs []*system.LoginLog
|
||||||
err := s.repo.DB(ctx).
|
err := s.repo.DB(ctx).
|
||||||
Where("email = ?", email).
|
Where("email = ?", email).
|
||||||
Order("id DESC").
|
Order("id DESC").
|
||||||
First(&log).
|
Limit(2).
|
||||||
|
Find(&logs).
|
||||||
Error
|
Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &log, nil
|
return logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *loginLogRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.LoginLog, int64, error) {
|
func (s *loginLogRepository) List(ctx context.Context, q dto.SearchDto) ([]*system.LoginLog, int64, error) {
|
||||||
|
|||||||
@ -17,8 +17,12 @@ func NewMenuRepository(repo *repository.Repository) system.MenuRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *menuRepository) Create(ctx context.Context, obj *system.Menu) error {
|
func (r *menuRepository) Create(ctx context.Context, obj *system.Menu) (*system.Menu, error) {
|
||||||
return r.repo.DB(ctx).Create(obj).Error
|
err := r.repo.DB(ctx).Create(obj).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *menuRepository) Update(ctx context.Context, obj *system.Menu) error {
|
func (r *menuRepository) Update(ctx context.Context, obj *system.Menu) error {
|
||||||
|
|||||||
828
internal/erpserver/repository/system/menu_seed.go
Normal file
828
internal/erpserver/repository/system/menu_seed.go
Normal file
@ -0,0 +1,828 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"management/internal/erpserver/model/system"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *menuRepository) Initialize(ctx context.Context) error {
|
||||||
|
var count int64
|
||||||
|
if err := r.repo.DB(ctx).Model(&system.Menu{}).Count(&count).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sys, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "系统管理",
|
||||||
|
DisplayName: "系统管理",
|
||||||
|
Url: uuid.Must(uuid.NewRandom()).String(),
|
||||||
|
Type: "node",
|
||||||
|
ParentID: 0,
|
||||||
|
ParentPath: ",0,",
|
||||||
|
Avatar: "layui-icon layui-icon-set",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
accountPermission, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "账户权限",
|
||||||
|
DisplayName: "账户权限",
|
||||||
|
Url: uuid.Must(uuid.NewRandom()).String(),
|
||||||
|
Type: "node",
|
||||||
|
ParentID: sys.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", sys.ParentPath, sys.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-vercode",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
systemMenu, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "菜单管理",
|
||||||
|
DisplayName: "菜单管理",
|
||||||
|
Url: "/system/menu/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: accountPermission.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", accountPermission.ParentPath, accountPermission.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
systemRole, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "角色管理",
|
||||||
|
DisplayName: "角色管理",
|
||||||
|
Url: "/system/role/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: accountPermission.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", accountPermission.ParentPath, accountPermission.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
systemDepartment, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "部门管理",
|
||||||
|
DisplayName: "部门管理",
|
||||||
|
Url: "/system/department/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: accountPermission.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", accountPermission.ParentPath, accountPermission.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
systemUser, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "用户管理",
|
||||||
|
DisplayName: "用户管理",
|
||||||
|
Url: "/system/user/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: accountPermission.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", accountPermission.ParentPath, accountPermission.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "登陆日志",
|
||||||
|
DisplayName: "登陆日志",
|
||||||
|
Url: "/system/login_log/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: accountPermission.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", accountPermission.ParentPath, accountPermission.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "审计日志",
|
||||||
|
DisplayName: "审计日志",
|
||||||
|
Url: "/system/audit_log/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: accountPermission.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", accountPermission.ParentPath, accountPermission.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增",
|
||||||
|
DisplayName: "新增",
|
||||||
|
Url: "/system/menu/add",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemMenu.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemMenu.ParentPath, systemMenu.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增子菜单",
|
||||||
|
DisplayName: "新增子菜单",
|
||||||
|
Url: "/system/menu/add_children",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemMenu.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemMenu.ParentPath, systemMenu.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "编辑",
|
||||||
|
DisplayName: "编辑",
|
||||||
|
Url: "/system/menu/edit",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemMenu.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemMenu.ParentPath, systemMenu.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-edit",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "保存",
|
||||||
|
DisplayName: "保存",
|
||||||
|
Url: "/system/menu/save",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemMenu.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemMenu.ParentPath, systemMenu.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-ok",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "数据",
|
||||||
|
DisplayName: "数据",
|
||||||
|
Url: "/system/menu/data",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemMenu.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemMenu.ParentPath, systemMenu.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "刷新",
|
||||||
|
DisplayName: "刷新",
|
||||||
|
Url: "/system/menu/refresh_cache",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemMenu.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemMenu.ParentPath, systemMenu.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 角色
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增",
|
||||||
|
DisplayName: "新增",
|
||||||
|
Url: "/system/role/add",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "编辑",
|
||||||
|
DisplayName: "编辑",
|
||||||
|
Url: "/system/role/edit",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-edit",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "保存",
|
||||||
|
DisplayName: "保存",
|
||||||
|
Url: "/system/role/save",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-ok",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "数据",
|
||||||
|
DisplayName: "数据",
|
||||||
|
Url: "/system/role/data",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "刷新",
|
||||||
|
DisplayName: "刷新",
|
||||||
|
Url: "/system/role/refresh",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "重建父路径",
|
||||||
|
DisplayName: "重建父路径",
|
||||||
|
Url: "/system/role/rebuild_parent_path",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-danger pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "权限刷新",
|
||||||
|
DisplayName: "权限刷新",
|
||||||
|
Url: "/system/role/refresh_role_menus",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "设置权限",
|
||||||
|
DisplayName: "设置权限",
|
||||||
|
Url: "/system/role/set_menu",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemRole.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemRole.ParentPath, systemRole.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-set",
|
||||||
|
Style: "pear-btn-danger pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 部门
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增",
|
||||||
|
DisplayName: "新增",
|
||||||
|
Url: "/system/department/add",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增子部门",
|
||||||
|
DisplayName: "新增子部门",
|
||||||
|
Url: "/system/department/add_children",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "编辑",
|
||||||
|
DisplayName: "编辑",
|
||||||
|
Url: "/system/department/edit",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-edit",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "保存",
|
||||||
|
DisplayName: "保存",
|
||||||
|
Url: "/system/department/save",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-ok",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "数据",
|
||||||
|
DisplayName: "数据",
|
||||||
|
Url: "/system/department/data",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "刷新",
|
||||||
|
DisplayName: "刷新",
|
||||||
|
Url: "/system/department/refresh",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "重建父路径",
|
||||||
|
DisplayName: "重建父路径",
|
||||||
|
Url: "/system/department/rebuild_parent_path",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemDepartment.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemDepartment.ParentPath, systemDepartment.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-danger pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增",
|
||||||
|
DisplayName: "新增",
|
||||||
|
Url: "/system/user/add",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemUser.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemUser.ParentPath, systemUser.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "编辑",
|
||||||
|
DisplayName: "编辑",
|
||||||
|
Url: "/system/user/edit",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemUser.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemUser.ParentPath, systemUser.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-edit",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "基本资料",
|
||||||
|
DisplayName: "基本资料",
|
||||||
|
Url: "/system/user/profile",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemUser.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemUser.ParentPath, systemUser.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "保存",
|
||||||
|
DisplayName: "保存",
|
||||||
|
Url: "/system/user/save",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemUser.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemUser.ParentPath, systemUser.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-ok",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 基础数据
|
||||||
|
basicData, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "基础数据",
|
||||||
|
DisplayName: "基础数据",
|
||||||
|
Url: uuid.Must(uuid.NewRandom()).String(),
|
||||||
|
Type: "node",
|
||||||
|
ParentID: sys.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", sys.ParentPath, sys.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-vercode",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 系统配置
|
||||||
|
systemConfig, err := r.Create(ctx, &system.Menu{
|
||||||
|
Name: "系统属性",
|
||||||
|
DisplayName: "系统属性",
|
||||||
|
Url: "/system/config/list",
|
||||||
|
Type: "menu",
|
||||||
|
ParentID: basicData.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", basicData.ParentPath, basicData.ID),
|
||||||
|
Avatar: "",
|
||||||
|
Style: "",
|
||||||
|
Visible: true,
|
||||||
|
IsList: true,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "新增",
|
||||||
|
DisplayName: "新增",
|
||||||
|
Url: "/system/config/add",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemConfig.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemConfig.ParentPath, systemConfig.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-add-1",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "编辑",
|
||||||
|
DisplayName: "编辑",
|
||||||
|
Url: "/system/config/edit",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemConfig.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemConfig.ParentPath, systemConfig.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-edit",
|
||||||
|
Style: "pear-btn-primary pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "保存",
|
||||||
|
DisplayName: "保存",
|
||||||
|
Url: "/system/config/save",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemConfig.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemConfig.ParentPath, systemConfig.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-ok",
|
||||||
|
Style: "pear-btn-primary pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "重置Pear",
|
||||||
|
DisplayName: "重置Pear",
|
||||||
|
Url: "/system/config/reset_pear",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemConfig.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemConfig.ParentPath, systemConfig.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-danger pear-btn-sm",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.Create(ctx, &system.Menu{
|
||||||
|
Name: "刷新",
|
||||||
|
DisplayName: "刷新",
|
||||||
|
Url: "/system/config/refresh",
|
||||||
|
Type: "btn",
|
||||||
|
ParentID: systemConfig.ID,
|
||||||
|
ParentPath: fmt.Sprintf("%s%d,", systemConfig.ParentPath, systemConfig.ID),
|
||||||
|
Avatar: "layui-icon layui-icon-refresh",
|
||||||
|
Style: "pear-btn-xs",
|
||||||
|
Visible: true,
|
||||||
|
IsList: false,
|
||||||
|
Status: 0,
|
||||||
|
Sort: 6666,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -2,6 +2,8 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/erpserver/model/system"
|
"management/internal/erpserver/model/system"
|
||||||
@ -18,6 +20,50 @@ func NewRoleRepository(repo *repository.Repository) system.RoleRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *roleRepository) Initialize(ctx context.Context) (*system.Role, error) {
|
||||||
|
var count int64
|
||||||
|
if err := r.repo.DB(ctx).Model(&system.Role{}).Count(&count).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
obj := system.Role{
|
||||||
|
Name: "Company",
|
||||||
|
DisplayName: "公司",
|
||||||
|
Vip: false,
|
||||||
|
ParentID: 0,
|
||||||
|
ParentPath: ",0,",
|
||||||
|
Status: 0,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
if err := r.Create(ctx, &obj); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj1 := system.Role{
|
||||||
|
Name: "SuperAdmin",
|
||||||
|
DisplayName: "超级管理员",
|
||||||
|
Vip: true,
|
||||||
|
ParentID: obj.ID,
|
||||||
|
ParentPath: fmt.Sprintf(",0,%d,", obj.ID),
|
||||||
|
Status: 0,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
if err := r.Create(ctx, &obj1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &obj1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var role system.Role
|
||||||
|
err := r.repo.DB(ctx).Where("vip = ?", true).First(&role).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &role, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *roleRepository) Create(ctx context.Context, obj *system.Role) error {
|
func (r *roleRepository) Create(ctx context.Context, obj *system.Role) error {
|
||||||
return r.repo.DB(ctx).Create(obj).Error
|
return r.repo.DB(ctx).Create(obj).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,15 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/erpserver/model/system"
|
"management/internal/erpserver/model/system"
|
||||||
"management/internal/erpserver/repository"
|
"management/internal/erpserver/repository"
|
||||||
|
"management/internal/pkg/crypto"
|
||||||
|
"management/internal/pkg/rand"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type userRepository struct {
|
type userRepository struct {
|
||||||
@ -18,6 +23,49 @@ func NewUserRepository(repo *repository.Repository) system.UserRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *userRepository) Initialize(ctx context.Context, departId, roleId int32) error {
|
||||||
|
var count int64
|
||||||
|
if err := s.repo.DB(ctx).Model(&system.User{}).Count(&count).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
salt, err := rand.String(10)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
password := "secret"
|
||||||
|
hashedPassword, err := crypto.BcryptHashPassword(password + salt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
initTime, err := time.ParseInLocation(time.DateTime, "0001-01-01 00:00:00", time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
user := system.User{
|
||||||
|
Uuid: uuid.Must(uuid.NewV7()),
|
||||||
|
Email: "1185230223@qq.com",
|
||||||
|
Username: "kenneth",
|
||||||
|
HashedPassword: hashedPassword,
|
||||||
|
Salt: salt,
|
||||||
|
Avatar: "/statics/admin/images/avatar.jpg",
|
||||||
|
Gender: 1,
|
||||||
|
DepartmentID: departId,
|
||||||
|
RoleID: roleId,
|
||||||
|
Status: 0,
|
||||||
|
ChangePasswordAt: initTime,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
return s.Create(ctx, &user)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *userRepository) Create(ctx context.Context, obj *system.User) error {
|
func (s *userRepository) Create(ctx context.Context, obj *system.User) error {
|
||||||
return s.repo.DB(ctx).Create(obj).Error
|
return s.repo.DB(ctx).Create(obj).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/erpserver/model/form"
|
"management/internal/erpserver/model/form"
|
||||||
@ -67,7 +66,7 @@ type LoginLogService interface {
|
|||||||
Create(ctx context.Context, req *system.LoginLog) error
|
Create(ctx context.Context, req *system.LoginLog) error
|
||||||
List(ctx context.Context, q dto.SearchDto) ([]*system.LoginLog, int64, error)
|
List(ctx context.Context, q dto.SearchDto) ([]*system.LoginLog, int64, error)
|
||||||
|
|
||||||
LoginLatestTime(ctx context.Context, email string) time.Time
|
LoginTime(ctx context.Context, email string) (dto.LoginTimeDto, error)
|
||||||
LoginCount(ctx context.Context, email string) int64
|
LoginCount(ctx context.Context, email string) int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,17 @@ func (s *configService) Pear(ctx context.Context) (*dto.PearConfig, error) {
|
|||||||
var res *dto.PearConfig
|
var res *dto.PearConfig
|
||||||
key := know.GetManageKey(ctx, know.PearAdmin)
|
key := know.GetManageKey(ctx, know.PearAdmin)
|
||||||
err := util.GetOrSetCache(ctx, s.Redis, key, util.GetCacheExpire(), func() (any, error) {
|
err := util.GetOrSetCache(ctx, s.Redis, key, util.GetCacheExpire(), func() (any, error) {
|
||||||
return s.repo.GetByKey(ctx, pearadmin.PearKey)
|
conf, err := s.repo.GetByKey(ctx, pearadmin.PearKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pc dto.PearConfig
|
||||||
|
err = json.Unmarshal(conf.Value, &pc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pc, nil
|
||||||
}, &res)
|
}, &res)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@ -72,7 +82,7 @@ func (s *configService) ResetPear(ctx context.Context) error {
|
|||||||
// create
|
// create
|
||||||
conf = &system.Config{
|
conf = &system.Config{
|
||||||
Key: pearadmin.PearKey,
|
Key: pearadmin.PearKey,
|
||||||
Value: string(b),
|
Value: b,
|
||||||
}
|
}
|
||||||
err = s.Create(ctx, conf)
|
err = s.Create(ctx, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,7 +90,7 @@ func (s *configService) ResetPear(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// update
|
// update
|
||||||
conf.Value = string(b)
|
conf.Value = b
|
||||||
conf.UpdatedAt = time.Now()
|
conf.UpdatedAt = time.Now()
|
||||||
err = s.Update(ctx, conf)
|
err = s.Update(ctx, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"management/internal/erpserver/model/dto"
|
"management/internal/erpserver/model/dto"
|
||||||
"management/internal/erpserver/model/system"
|
"management/internal/erpserver/model/system"
|
||||||
@ -29,12 +28,20 @@ func (s *loginLogService) List(ctx context.Context, q dto.SearchDto) ([]*system.
|
|||||||
return s.repo.List(ctx, q)
|
return s.repo.List(ctx, q)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *loginLogService) LoginLatestTime(ctx context.Context, email string) time.Time {
|
func (s *loginLogService) LoginTime(ctx context.Context, email string) (dto.LoginTimeDto, error) {
|
||||||
log, err := s.repo.GetLatest(ctx, email)
|
var res dto.LoginTimeDto
|
||||||
|
logs, err := s.repo.GetLatest(ctx, email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Time{}
|
return res, err
|
||||||
}
|
}
|
||||||
return log.CreatedAt
|
if len(logs) == 2 {
|
||||||
|
res.ThisLoginTime = logs[0].CreatedAt
|
||||||
|
res.LastLoginTime = logs[1].CreatedAt
|
||||||
|
} else if len(logs) == 1 {
|
||||||
|
res.ThisLoginTime = logs[0].CreatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *loginLogService) LoginCount(ctx context.Context, email string) int64 {
|
func (s *loginLogService) LoginCount(ctx context.Context, email string) int64 {
|
||||||
|
|||||||
@ -36,7 +36,8 @@ func NewMenuService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *menuService) Create(ctx context.Context, req *system.Menu) error {
|
func (s *menuService) Create(ctx context.Context, req *system.Menu) error {
|
||||||
return s.repo.Create(ctx, req)
|
_, err := s.repo.Create(ctx, req)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *menuService) Update(ctx context.Context, req *system.Menu) error {
|
func (s *menuService) Update(ctx context.Context, req *system.Menu) error {
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import (
|
|||||||
"management/internal/pkg/session"
|
"management/internal/pkg/session"
|
||||||
|
|
||||||
"github.com/drhin/logger"
|
"github.com/drhin/logger"
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -65,9 +64,10 @@ var handlerSet = wire.NewSet(
|
|||||||
|
|
||||||
var serverSet = wire.NewSet(
|
var serverSet = wire.NewSet(
|
||||||
NewHTTPServer,
|
NewHTTPServer,
|
||||||
|
NewApp,
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewWire(*config.Config, *logger.Logger) (*chi.Mux, func(), error) {
|
func NewWire(*config.Config, *logger.Logger) (App, func(), error) {
|
||||||
panic(wire.Build(
|
panic(wire.Build(
|
||||||
repositorySet,
|
repositorySet,
|
||||||
redis.New,
|
redis.New,
|
||||||
|
|||||||
@ -8,7 +8,6 @@ package erpserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drhin/logger"
|
"github.com/drhin/logger"
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
"management/internal/erpserver/handler"
|
"management/internal/erpserver/handler"
|
||||||
common2 "management/internal/erpserver/handler/common"
|
common2 "management/internal/erpserver/handler/common"
|
||||||
@ -26,51 +25,51 @@ import (
|
|||||||
|
|
||||||
// Injectors from wire.go:
|
// Injectors from wire.go:
|
||||||
|
|
||||||
func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (*chi.Mux, func(), error) {
|
func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (App, func(), error) {
|
||||||
db, cleanup, err := repository.NewDB(loggerLogger, configConfig)
|
db, cleanup, err := repository.NewDB(loggerLogger, configConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return App{}, nil, err
|
||||||
}
|
}
|
||||||
|
repositoryRepository := repository.NewRepository(db, loggerLogger)
|
||||||
|
userRepository := system.NewUserRepository(repositoryRepository)
|
||||||
|
roleRepository := system.NewRoleRepository(repositoryRepository)
|
||||||
|
menuRepository := system.NewMenuRepository(repositoryRepository)
|
||||||
|
roleMenuRepository := system.NewRoleMenuRepository(repositoryRepository)
|
||||||
|
departmentRepository := system.NewDepartmentRepository(repositoryRepository)
|
||||||
|
configRepository := system.NewConfigRepository(repositoryRepository)
|
||||||
|
loginLogRepository := system.NewLoginLogRepository(repositoryRepository)
|
||||||
|
auditLogRepository := system.NewAuditLogRepository(repositoryRepository)
|
||||||
manager, err := session.NewSCSManager(db, configConfig)
|
manager, err := session.NewSCSManager(db, configConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanup()
|
cleanup()
|
||||||
return nil, nil, err
|
return App{}, nil, err
|
||||||
}
|
}
|
||||||
repositoryRepository := repository.NewRepository(db, loggerLogger)
|
|
||||||
transaction := repository.NewTransaction(repositoryRepository)
|
transaction := repository.NewTransaction(repositoryRepository)
|
||||||
cache, cleanup2, err := redis.New(configConfig, loggerLogger)
|
cache, cleanup2, err := redis.New(configConfig, loggerLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanup()
|
cleanup()
|
||||||
return nil, nil, err
|
return App{}, nil, err
|
||||||
}
|
}
|
||||||
service := v1.NewService(loggerLogger, transaction, manager, cache)
|
service := v1.NewService(loggerLogger, transaction, manager, cache)
|
||||||
menuRepository := system.NewMenuRepository(repositoryRepository)
|
|
||||||
roleRepository := system.NewRoleRepository(repositoryRepository)
|
|
||||||
roleService := system2.NewRoleService(service, roleRepository)
|
roleService := system2.NewRoleService(service, roleRepository)
|
||||||
roleMenuRepository := system.NewRoleMenuRepository(repositoryRepository)
|
|
||||||
roleMenuService := system2.NewRoleMenuService(service, roleMenuRepository)
|
roleMenuService := system2.NewRoleMenuService(service, roleMenuRepository)
|
||||||
menuService := system2.NewMenuService(service, menuRepository, roleService, roleMenuService)
|
menuService := system2.NewMenuService(service, menuRepository, roleService, roleMenuService)
|
||||||
auditLogRepository := system.NewAuditLogRepository(repositoryRepository)
|
|
||||||
auditLogService := system2.NewAuditLogService(service, auditLogRepository)
|
auditLogService := system2.NewAuditLogService(service, auditLogRepository)
|
||||||
renderRender, err := render.New(manager, menuService)
|
renderRender, err := render.New(manager, menuService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanup2()
|
cleanup2()
|
||||||
cleanup()
|
cleanup()
|
||||||
return nil, nil, err
|
return App{}, nil, err
|
||||||
}
|
}
|
||||||
handlerHandler := handler.NewHandler(configConfig, loggerLogger, manager, renderRender)
|
handlerHandler := handler.NewHandler(configConfig, loggerLogger, manager, renderRender)
|
||||||
captchaService := common.NewCaptchaService()
|
captchaService := common.NewCaptchaService()
|
||||||
captchaHandler := common2.NewCaptchaHandler(handlerHandler, captchaService)
|
captchaHandler := common2.NewCaptchaHandler(handlerHandler, captchaService)
|
||||||
uploadHandler := common2.NewUploadHandler(handlerHandler)
|
uploadHandler := common2.NewUploadHandler(handlerHandler)
|
||||||
configRepository := system.NewConfigRepository(repositoryRepository)
|
|
||||||
configService := system2.NewConfigService(service, configRepository)
|
configService := system2.NewConfigService(service, configRepository)
|
||||||
configHandler := system3.NewConfigHandler(handlerHandler, configService)
|
configHandler := system3.NewConfigHandler(handlerHandler, configService)
|
||||||
userRepository := system.NewUserRepository(repositoryRepository)
|
|
||||||
loginLogRepository := system.NewLoginLogRepository(repositoryRepository)
|
|
||||||
loginLogService := system2.NewLoginLogService(service, loginLogRepository)
|
loginLogService := system2.NewLoginLogService(service, loginLogRepository)
|
||||||
userService := system2.NewUserService(service, userRepository, roleService, loginLogService)
|
userService := system2.NewUserService(service, userRepository, roleService, loginLogService)
|
||||||
homeHandler := system3.NewHomeHandler(handlerHandler, userService, loginLogService)
|
homeHandler := system3.NewHomeHandler(handlerHandler, userService, loginLogService)
|
||||||
departmentRepository := system.NewDepartmentRepository(repositoryRepository)
|
|
||||||
departmentService := system2.NewDepartmentService(service, departmentRepository)
|
departmentService := system2.NewDepartmentService(service, departmentRepository)
|
||||||
userHandler := system3.NewUserHandler(handlerHandler, captchaService, userService, roleService, departmentService)
|
userHandler := system3.NewUserHandler(handlerHandler, captchaService, userService, roleService, departmentService)
|
||||||
loginLogHandler := system3.NewLoginLogHandler(handlerHandler, loginLogService)
|
loginLogHandler := system3.NewLoginLogHandler(handlerHandler, loginLogService)
|
||||||
@ -79,7 +78,8 @@ func NewWire(configConfig *config.Config, loggerLogger *logger.Logger) (*chi.Mux
|
|||||||
roleHandler := system3.NewRoleHandler(handlerHandler, roleService, menuService)
|
roleHandler := system3.NewRoleHandler(handlerHandler, roleService, menuService)
|
||||||
departmentHandler := system3.NewDepartmentHandler(handlerHandler, departmentService)
|
departmentHandler := system3.NewDepartmentHandler(handlerHandler, departmentService)
|
||||||
mux := NewHTTPServer(manager, loggerLogger, menuService, auditLogService, captchaHandler, uploadHandler, configHandler, homeHandler, userHandler, loginLogHandler, auditHandler, menuHandler, roleHandler, departmentHandler)
|
mux := NewHTTPServer(manager, loggerLogger, menuService, auditLogService, captchaHandler, uploadHandler, configHandler, homeHandler, userHandler, loginLogHandler, auditHandler, menuHandler, roleHandler, departmentHandler)
|
||||||
return mux, func() {
|
app := NewApp(userRepository, roleRepository, menuRepository, roleMenuRepository, departmentRepository, configRepository, loginLogRepository, auditLogRepository, mux)
|
||||||
|
return app, func() {
|
||||||
cleanup2()
|
cleanup2()
|
||||||
cleanup()
|
cleanup()
|
||||||
}, nil
|
}, nil
|
||||||
@ -95,4 +95,5 @@ var handlerSet = wire.NewSet(handler.NewHandler, common2.NewCaptchaHandler, comm
|
|||||||
|
|
||||||
var serverSet = wire.NewSet(
|
var serverSet = wire.NewSet(
|
||||||
NewHTTPServer,
|
NewHTTPServer,
|
||||||
|
NewApp,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -42,14 +42,17 @@ type Config struct {
|
|||||||
Prod bool `mapstructure:"prod"` // 是否正式
|
Prod bool `mapstructure:"prod"` // 是否正式
|
||||||
} `mapstructure:"app"`
|
} `mapstructure:"app"`
|
||||||
DB struct {
|
DB struct {
|
||||||
Driver string `mapstructure:"driver"` // 数据库类型
|
Driver string `mapstructure:"driver"` // 数据库类型
|
||||||
Host string `mapstructure:"host"` // 数据库地址
|
Host string `mapstructure:"host"` // 数据库地址
|
||||||
Port int `mapstructure:"port"` // 数据库端口
|
Port int `mapstructure:"port"` // 数据库端口
|
||||||
Username string `mapstructure:"username"` // 数据库用户
|
Username string `mapstructure:"username"` // 数据库用户
|
||||||
Password string `mapstructure:"password"` // 数据库密码
|
Password string `mapstructure:"password"` // 数据库密码
|
||||||
DBName string `mapstructure:"db_name"` // 数据库名称
|
DBName string `mapstructure:"db_name"` // 数据库名称
|
||||||
MaxOpenConns int `mapstructure:"max_open_conns"` // 数据库名称
|
MaxIdleConns int `mapstructure:"max_idle_conns"` // 最大空闲连接数
|
||||||
MaxIdleConns int `mapstructure:"max_idle_conns"` // 数据库名称
|
MaxOpenConns int `mapstructure:"max_open_conns"` // 最大打开连接数
|
||||||
|
ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime"` // 连接最大存活时间
|
||||||
|
ConnMaxIdleTime time.Duration `mapstructure:"conn_max_idle_time"` // 连接最大空闲时间
|
||||||
|
LogMode bool `mapstructure:"log_mode"` // 是否开启日志
|
||||||
} `mapstructure:"db"`
|
} `mapstructure:"db"`
|
||||||
Redis struct {
|
Redis struct {
|
||||||
Host string `mapstructure:"host"` // redis地址
|
Host string `mapstructure:"host"` // redis地址
|
||||||
|
|||||||
@ -25,10 +25,10 @@ type PostgreSQLOptions struct {
|
|||||||
|
|
||||||
// DSN return DSN from PostgreSQLOptions.
|
// DSN return DSN from PostgreSQLOptions.
|
||||||
func (o *PostgreSQLOptions) DSN() string {
|
func (o *PostgreSQLOptions) DSN() string {
|
||||||
splited := strings.Split(o.Addr, ":")
|
split := strings.Split(o.Addr, ":")
|
||||||
host, port := splited[0], "5432"
|
host, port := split[0], "5432"
|
||||||
if len(splited) > 1 {
|
if len(split) > 1 {
|
||||||
port = splited[1]
|
port = split[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(`user=%s password=%s host=%s port=%s dbname=%s sslmode=disable TimeZone=Asia/Shanghai`,
|
return fmt.Sprintf(`user=%s password=%s host=%s port=%s dbname=%s sslmode=disable TimeZone=Asia/Shanghai`,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@ -18,19 +19,24 @@ func Audit(sess session.Manager, auditLogService v1.AuditLogService, log *logger
|
|||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
|
// 提前获取用户信息(同步操作)
|
||||||
|
user, err := sess.GetUser(r.Context(), know.StoreName)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("获取用户会话失败", err)
|
||||||
|
next.ServeHTTP(w, r) // 继续处理请求
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
go func() {
|
go func() {
|
||||||
ctx := r.Context()
|
if user.ID == 0 {
|
||||||
user, err := sess.GetUser(ctx, know.StoreName)
|
log.Error("用户信息为空", errors.New("scs get user is empty"))
|
||||||
if err != nil {
|
|
||||||
log.Error(err.Error(), err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.ID == 0 {
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
log.Error("scs get user is empty", errors.New("scs get user is empty"))
|
defer cancel()
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
al := systemmodel.NewAuditLog(r, user.Email, user.OS, user.Browser, start, time.Now())
|
al := systemmodel.NewAuditLog(r, user.Email, user.OS, user.Browser, start, time.Now())
|
||||||
if err := auditLogService.Create(ctx, al); err != nil {
|
if err := auditLogService.Create(ctx, al); err != nil {
|
||||||
|
|||||||
@ -17,6 +17,7 @@ var publicRoutes = map[string]bool{
|
|||||||
"/upload/file": true,
|
"/upload/file": true,
|
||||||
"/upload/multi_files": true,
|
"/upload/multi_files": true,
|
||||||
"/pear.json": true,
|
"/pear.json": true,
|
||||||
|
"/logout": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func Authorize(
|
func Authorize(
|
||||||
|
|||||||
@ -57,5 +57,9 @@ func Methods() map[string]any {
|
|||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res["add"] = func(n1, n2 int64) int64 {
|
||||||
|
return n1 + n2
|
||||||
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
# start manage
|
# start manage
|
||||||
**/*.go **/**/**/*.tmpl **/**/**/**/*.tmpl !web/*.go !**/*_test.go {
|
**/*.go **/**/**/*.tmpl **/**/**/**/*.tmpl !web/*.go !**/*_test.go {
|
||||||
prep: go build -o ./management .
|
prep: go build -o ./management .
|
||||||
daemon +sigterm: ./management erp -c config.dev.yaml
|
daemon +sigterm: ./management erp -c configs/config.dev.yaml
|
||||||
}
|
}
|
||||||
@ -6,7 +6,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<p class="name">欢迎您,{{.Auth.Username}} ({{.Auth.RoleName}})</p>
|
<p class="name">欢迎您,{{.Auth.Username}} ({{.Auth.RoleName}})</p>
|
||||||
<p>这是您第 {{.LoginCount}} 次登录,上次登录日期:{{dateFormat .LastLoginTime}},如果不是您本人登录,请及时修改密码 。</p>
|
{{if eq .LoginCount 1}}
|
||||||
|
<p>这是您第 1 次登录,本次登录日期:{{dateFormat .LoginTime.ThisLoginTime}},如果不是您本人登录,请及时修改密码 。</p>
|
||||||
|
{{else}}
|
||||||
|
<p>这是您第 {{.LoginCount}} 次登录,本次登录日期:{{dateFormat .LoginTime.ThisLoginTime}},
|
||||||
|
上次登录日期:{{dateFormat .LoginTime.LastLoginTime}},如果不是您本人登录,请及时修改密码 。</p>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user