@@ -1,4 +1,4 @@ | |||
# applet | |||
# 广告站长平台 | |||
## 要看 nginx.conf 和 wap conf | |||
@@ -5,51 +5,17 @@ import ( | |||
) | |||
type Config struct { | |||
Debug bool `yaml:"debug"` | |||
Prd bool `yaml:"prd"` | |||
CurlDebug bool `yaml:"curldebug"` | |||
SrvAddr string `yaml:"srv_addr"` | |||
RedisAddr string `yaml:"redis_addr"` | |||
DB DBCfg `yaml:"db"` | |||
Log LogCfg `yaml:"log"` | |||
ArkID ArkIDCfg `yaml:"arkid"` | |||
Admin AdminCfg `yaml:"admin"` | |||
Official OfficialCfg `yaml:"official"` | |||
WxappletFilepath WxappletFilepathCfg `yaml:"wxapplet_filepath"` | |||
Local bool | |||
AppComm AppCommCfg `yaml:"app_comm"` | |||
Debug bool `yaml:"debug"` | |||
Prd bool `yaml:"prd"` | |||
CurlDebug bool `yaml:"curldebug"` | |||
SrvAddr string `yaml:"srv_addr"` | |||
RedisAddr string `yaml:"redis_addr"` | |||
DB DBCfg `yaml:"db"` | |||
Log LogCfg `yaml:"log"` | |||
Local bool | |||
} | |||
// 公共模块 | |||
type AppCommCfg struct { | |||
URL string `yaml:"url"` | |||
} | |||
// OfficialCfg is 官网 | |||
type OfficialCfg struct { | |||
URL string `yaml:"url"` | |||
} | |||
type WxappletFilepathCfg struct { | |||
URL string `yaml:"url"` | |||
} | |||
// AdminCfg is 后台接口调用需要 | |||
type AdminCfg struct { | |||
URL string `yaml:"url"` | |||
IURL string `yaml:"iurl"` | |||
AesKey string `yaml:"api_aes_key"` | |||
AesIV string `yaml:"api_aes_iv"` | |||
Host string `yaml:"host"` | |||
} | |||
type ArkIDCfg struct { | |||
Admin string `yaml:"admin"` | |||
AdminPassword string `yaml:"admin_password"` | |||
Url string `yaml:"url` | |||
} | |||
//数据库配置结构体 | |||
// 数据库配置结构体 | |||
type DBCfg struct { | |||
Host string `yaml:"host"` //ip及端口 | |||
Name string `yaml:"name"` //库名 | |||
@@ -62,7 +28,7 @@ type DBCfg struct { | |||
Path string `yaml:"path"` //日志文件存放路径 | |||
} | |||
//日志配置结构体 | |||
// 日志配置结构体 | |||
type LogCfg struct { | |||
AppName string `yaml:"app_name" ` | |||
Level string `yaml:"level"` | |||
@@ -7,24 +7,19 @@ import ( | |||
"gopkg.in/yaml.v2" | |||
) | |||
//配置文件数据,全局变量 | |||
// 配置文件数据,全局变量 | |||
var ( | |||
Debug bool | |||
Prd bool | |||
CurlDebug bool | |||
SrvAddr string | |||
RedisAddr string | |||
DB *DBCfg | |||
Log *LogCfg | |||
ArkID *ArkIDCfg | |||
Admin *AdminCfg | |||
Official *OfficialCfg | |||
WxappletFilepath *WxappletFilepathCfg | |||
Local bool | |||
AppComm *AppCommCfg | |||
Debug bool | |||
Prd bool | |||
CurlDebug bool | |||
SrvAddr string | |||
RedisAddr string | |||
DB *DBCfg | |||
Log *LogCfg | |||
Local bool | |||
) | |||
//初始化配置文件,将cfg.yml读入到内存 | |||
// 初始化配置文件,将cfg.yml读入到内存 | |||
func InitCfg() { | |||
//用指定的名称、默认值、使用信息注册一个string类型flag。 | |||
path := flag.String("c", "etc/cfg.yml", "config file") | |||
@@ -50,11 +45,6 @@ func InitCfg() { | |||
CurlDebug = conf.CurlDebug | |||
DB = &conf.DB | |||
Log = &conf.Log | |||
ArkID = &conf.ArkID | |||
RedisAddr = conf.RedisAddr | |||
SrvAddr = conf.SrvAddr | |||
Admin = &conf.Admin | |||
Official = &conf.Official | |||
WxappletFilepath = &conf.WxappletFilepath | |||
AppComm = &conf.AppComm | |||
} |
@@ -28,10 +28,8 @@ func InitTaskCfg() { | |||
Debug = conf.Debug | |||
DB = &conf.DB | |||
Log = &conf.Log | |||
Admin = &conf.Admin | |||
RedisAddr = conf.RedisAddr | |||
Local = conf.Local | |||
AppComm = &conf.AppComm | |||
} | |||
var MemCache mc.Cache | |||
@@ -0,0 +1,14 @@ | |||
package dao | |||
import "applet/app/db/model" | |||
type SysCfgDao interface { | |||
SysCfgGetAll() (*[]model.SysCfg, error) | |||
SysCfgGetOneNoDataNoErr(key string) (*model.SysCfg, error) | |||
SysCfgGetOne(key string) (*model.SysCfg, error) | |||
SysCfgInsert(key, val, memo string) bool | |||
SysCfgUpdate(key, val string) bool | |||
SysCfgGetWithDb(HKey string) string | |||
SysCfgDel(HKey string) error | |||
SysCfgFindWithDb(keys ...string) map[string]string | |||
} |
@@ -1,112 +0,0 @@ | |||
package db | |||
import ( | |||
"database/sql" | |||
"fmt" | |||
"os" | |||
"time" | |||
_ "github.com/go-sql-driver/mysql" //必须导入mysql驱动,否则会panic | |||
"xorm.io/xorm" | |||
"xorm.io/xorm/log" | |||
"applet/app/cfg" | |||
"applet/app/utils/logx" | |||
) | |||
var Db *xorm.Engine | |||
//根据DB配置文件初始化数据库 | |||
func InitDB(c *cfg.DBCfg) error { | |||
var ( | |||
err error | |||
f *os.File | |||
) | |||
//创建Orm引擎 | |||
if Db, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4", c.User, c.Psw, c.Host, c.Name)); err != nil { | |||
return err | |||
} | |||
Db.SetConnMaxLifetime(c.MaxLifetime * time.Second) //设置最长连接时间 | |||
Db.SetMaxOpenConns(c.MaxOpenConns) //设置最大打开连接数 | |||
Db.SetMaxIdleConns(c.MaxIdleConns) //设置连接池的空闲数大小 | |||
if err = Db.Ping(); err != nil { //尝试ping数据库 | |||
return err | |||
} | |||
if c.ShowLog { //根据配置文件设置日志 | |||
Db.ShowSQL(true) //设置是否打印sql | |||
Db.Logger().SetLevel(0) //设置日志等级 | |||
//修改日志文件存放路径文件名是%s.log | |||
path := fmt.Sprintf(c.Path, c.Name) | |||
f, err = os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777) | |||
if err != nil { | |||
os.RemoveAll(c.Path) | |||
if f, err = os.OpenFile(c.Path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777); err != nil { | |||
return err | |||
} | |||
} | |||
logger := log.NewSimpleLogger(f) | |||
logger.ShowSQL(true) | |||
Db.SetLogger(logger) | |||
} | |||
return nil | |||
} | |||
/********************************************* 公用方法 *********************************************/ | |||
// 数据批量插入 | |||
func DbInsertBatch(Db *xorm.Engine, m ...interface{}) error { | |||
if len(m) == 0 { | |||
return nil | |||
} | |||
id, err := Db.Insert(m...) | |||
if id == 0 || err != nil { | |||
return logx.Warn("cannot insert data :", err) | |||
} | |||
return nil | |||
} | |||
// QueryNativeString 查询原生sql | |||
func QueryNativeString(Db *xorm.Engine, sql string, args ...interface{}) ([]map[string]string, error) { | |||
results, err := Db.SQL(sql, args...).QueryString() | |||
return results, err | |||
} | |||
// UpdateComm common update | |||
func UpdateComm(Db *xorm.Engine, id interface{}, model interface{}) (int64, error) { | |||
row, err := Db.ID(id).Update(model) | |||
return row, err | |||
} | |||
// InsertComm common insert | |||
func InsertComm(Db *xorm.Engine, model interface{}) (int64, error) { | |||
row, err := Db.InsertOne(model) | |||
return row, err | |||
} | |||
// ExecuteOriginalSql 执行原生sql | |||
func ExecuteOriginalSql(session *xorm.Session, sql string) (sql.Result, error) { | |||
result, err := session.Exec(sql) | |||
if err != nil { | |||
_ = logx.Warn(err) | |||
return nil, err | |||
} | |||
return result, nil | |||
} | |||
// GetComm | |||
// payload *model | |||
// return *model,has,err | |||
func GetComm(Db *xorm.Engine, model interface{}) (interface{}, bool, error) { | |||
has, err := Db.Get(model) | |||
if err != nil { | |||
_ = logx.Warn(err) | |||
return nil, false, err | |||
} | |||
return model, has, nil | |||
} | |||
// InsertCommWithSession common insert | |||
func InsertCommWithSession(session *xorm.Session, model interface{}) (int64, error) { | |||
row, err := session.InsertOne(model) | |||
return row, err | |||
} |
@@ -1,82 +0,0 @@ | |||
package db | |||
import ( | |||
"applet/app/db/model" | |||
"applet/app/md" | |||
"applet/app/utils/cache" | |||
"applet/app/utils/logx" | |||
"fmt" | |||
"xorm.io/xorm" | |||
) | |||
// 系统配置get | |||
func SysCfgGetAll(Db *xorm.Engine) (*[]model.SysCfg, error) { | |||
var cfgList []model.SysCfg | |||
if err := Db.Cols("key,val,memo").Find(&cfgList); err != nil { | |||
return nil, logx.Error(err) | |||
} | |||
return &cfgList, nil | |||
} | |||
// 获取一条记录 | |||
func SysCfgGetOne(Db *xorm.Engine, key string) (*model.SysCfg, error) { | |||
var cfgList model.SysCfg | |||
if has, err := Db.Where("`key`=?", key).Get(&cfgList); err != nil || has == false { | |||
return nil, logx.Error(err) | |||
} | |||
return &cfgList, nil | |||
} | |||
// 返回最后插入id | |||
func SysCfgInsert(Db *xorm.Engine, key, val, memo string) bool { | |||
cfg := model.SysCfg{Key: key, Val: val, Memo: memo} | |||
_, err := Db.InsertOne(&cfg) | |||
if err != nil { | |||
logx.Error(err) | |||
return false | |||
} | |||
return true | |||
} | |||
func SysCfgUpdate(Db *xorm.Engine, key, val, memo string) bool { | |||
cfg := model.SysCfg{Key: key, Val: val, Memo: memo} | |||
_, err := Db.Where("`key`=?", key).Cols("val,memo").Update(&cfg) | |||
if err != nil { | |||
logx.Error(err) | |||
return false | |||
} | |||
return true | |||
} | |||
func SysCfgGetWithDb(eg *xorm.Engine, masterId string, HKey string) string { | |||
cacheKey := fmt.Sprintf(md.AppCfgCacheKey, masterId) + HKey | |||
get, err := cache.GetString(cacheKey) | |||
if err != nil || get == "" { | |||
cfg, err := SysCfgGetOne(eg, HKey) | |||
if err != nil || cfg == nil { | |||
_ = logx.Error(err) | |||
return "" | |||
} | |||
// key是否存在 | |||
cacheKeyExist := false | |||
if cache.Exists(cacheKey) { | |||
cacheKeyExist = true | |||
} | |||
// 设置缓存 | |||
_, err = cache.SetEx(cacheKey, cfg.Val, 30) | |||
if err != nil { | |||
_ = logx.Error(err) | |||
return "" | |||
} | |||
if !cacheKeyExist { // 如果是首次设置 设置过期时间 | |||
_, err := cache.Expire(cacheKey, md.CfgCacheTime) | |||
if err != nil { | |||
_ = logx.Error(err) | |||
return "" | |||
} | |||
} | |||
return cfg.Val | |||
} | |||
return get | |||
} |
@@ -1,104 +0,0 @@ | |||
package db | |||
import ( | |||
"fmt" | |||
"os" | |||
"time" | |||
"xorm.io/xorm" | |||
"xorm.io/xorm/log" | |||
"applet/app/cfg" | |||
"applet/app/db/model" | |||
"applet/app/utils/logx" | |||
) | |||
var DBs map[string]*xorm.Engine | |||
// 每个站长都要有自己的syscfg 缓存, 键是站长id,值是缓存名 | |||
// var SysCfgMapKey map[string]string | |||
func NewDB(c *cfg.DBCfg) (*xorm.Engine, error) { | |||
db, err := xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4", c.User, c.Psw, c.Host, c.Name)) | |||
if err != nil { | |||
return nil, err | |||
} | |||
db.SetConnMaxLifetime(c.MaxLifetime * time.Second) | |||
db.SetMaxOpenConns(c.MaxOpenConns) | |||
db.SetMaxIdleConns(c.MaxIdleConns) | |||
err = db.Ping() | |||
if err != nil { | |||
return nil, err | |||
} | |||
if c.ShowLog { | |||
db.ShowSQL(true) | |||
db.Logger().SetLevel(log.LOG_DEBUG) | |||
f, err := os.OpenFile(c.Path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777) | |||
if err != nil { | |||
os.RemoveAll(c.Path) | |||
if f, err = os.OpenFile(c.Path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777); err != nil { | |||
return nil, err | |||
} | |||
} | |||
logger := log.NewSimpleLogger(f) | |||
logger.ShowSQL(true) | |||
db.SetLogger(logger) | |||
} | |||
return db, nil | |||
} | |||
// InitDBs is 初始化多数据库 | |||
func InitDBs(ch chan int) { | |||
// 初始化多数据库 | |||
var tables *[]model.DbMapping | |||
InitMapDbs(cfg.DB, cfg.Prd) | |||
ch <- 1 | |||
// 每10s 查询一次模板数据库的db mapping 表,如果有新增数据库记录,则添加到 DBs中 | |||
ticker := time.NewTicker(time.Duration(time.Second * 120)) | |||
for range ticker.C { | |||
if cfg.Prd { | |||
tables = GetAllDatabasePrd() //默认获取全部 | |||
} else { | |||
tables = GetAllDatabaseDev() //默认获取全部 | |||
} | |||
if tables == nil { | |||
logx.Warn("no database tables data") | |||
continue | |||
} | |||
for _, item := range *tables { | |||
_, ok := DBs[item.DbMasterId] | |||
if !ok { | |||
// 不在db.DBs 则添加进去 | |||
dbCfg := cfg.DBCfg{ | |||
Name: item.DbName, | |||
ShowLog: cfg.DB.ShowLog, | |||
MaxLifetime: cfg.DB.MaxLifetime, | |||
MaxOpenConns: cfg.DB.MaxOpenConns, | |||
MaxIdleConns: cfg.DB.MaxIdleConns, | |||
Path: fmt.Sprintf(cfg.DB.Path, item.DbName), | |||
} | |||
if item.DbHost != "" && item.DbUsername != "" && item.DbPassword != "" { | |||
dbCfg.Host = item.DbHost | |||
dbCfg.User = item.DbUsername | |||
dbCfg.Psw = item.DbPassword | |||
} else { | |||
dbCfg.Host = cfg.DB.Host | |||
dbCfg.User = cfg.DB.User | |||
dbCfg.Psw = cfg.DB.Psw | |||
} | |||
e, err := NewDB(&dbCfg) | |||
if err != nil || e == nil { | |||
logx.Warnf("db engine can't create, please check config, params[host:%s, user:%s, psw: %s, name: %s], err: %v", dbCfg.Host, dbCfg.User, dbCfg.Psw, dbCfg.Name, err) | |||
} else { | |||
DBs[item.DbMasterId] = e | |||
} | |||
} | |||
// 如果 被禁用则删除 | |||
if item.DeletedAt == 1 { | |||
logx.Infof("%s have been removed", item.DbMasterId) | |||
delete(DBs, item.DbMasterId) | |||
} | |||
} | |||
} | |||
} |
@@ -1,194 +0,0 @@ | |||
package db | |||
import ( | |||
"errors" | |||
"fmt" | |||
"xorm.io/xorm" | |||
"applet/app/cfg" | |||
"applet/app/db/model" | |||
"applet/app/utils/logx" | |||
) | |||
func MapBaseExists() (bool, error) { | |||
return Db.IsTableExist("db_mapping") | |||
} | |||
func InitMapDbs(c *cfg.DBCfg, prd bool) { | |||
var tables *[]model.DbMapping | |||
exists, err := MapBaseExists() | |||
if !exists || err != nil { | |||
logx.Fatalf("db_mapping not exists : %v", err) | |||
} | |||
// tables := MapAllDatabases(debug) | |||
if prd { | |||
tables = GetAllDatabasePrd() //debug 获取生产 | |||
} else { | |||
tables = GetAllDatabaseDev() //debug 获取开发 | |||
} | |||
if tables == nil { | |||
logx.Fatal("no database tables data") | |||
} | |||
var e *xorm.Engine | |||
DBs = map[string]*xorm.Engine{} | |||
for _, v := range *tables { | |||
if v.DbName != "" && v.DeletedAt == 0 && v.DbName != c.Name { | |||
dbCfg := cfg.DBCfg{ | |||
Name: v.DbName, | |||
ShowLog: c.ShowLog, | |||
MaxLifetime: c.MaxLifetime, | |||
MaxOpenConns: c.MaxOpenConns, | |||
MaxIdleConns: c.MaxIdleConns, | |||
Path: fmt.Sprintf(c.Path, v.DbName), | |||
} | |||
if v.DbHost != "" && v.DbUsername != "" && v.DbPassword != "" { | |||
dbCfg.Host = v.DbHost | |||
dbCfg.User = v.DbUsername | |||
dbCfg.Psw = v.DbPassword | |||
} else { | |||
dbCfg.Host = c.Host | |||
dbCfg.User = c.User | |||
dbCfg.Psw = c.Psw | |||
} | |||
e, err = NewDB(&dbCfg) | |||
if err != nil || e == nil { | |||
logx.Warnf("db engine can't create, please check config, params[host:%s, user:%s, psw: %s, name: %s], err: %v", dbCfg.Host, dbCfg.User, dbCfg.Psw, dbCfg.Name, err) | |||
} else { | |||
DBs[v.DbMasterId] = e | |||
} | |||
} | |||
} | |||
} | |||
func MapAllDatabases(debug bool) *[]model.DbMapping { | |||
sql := "`db_name` != ?" | |||
if debug { | |||
sql = "`db_name` = ?" | |||
} | |||
var m []model.DbMapping | |||
if err := Db.Where(sql, cfg.DB.Name).Find(&m); err != nil || len(m) == 0 { | |||
logx.Warn(err) | |||
return nil | |||
} | |||
return &m | |||
} | |||
// GetAllDatabasePrd is 获取生成库 所有db 除了 deleted_at = 1 的 | |||
func GetAllDatabasePrd() *[]model.DbMapping { | |||
var m []model.DbMapping | |||
if err := Db.Where("deleted_at != ? AND is_dev = '0' ", 1).Find(&m); err != nil || len(m) == 0 { | |||
logx.Warn(err) | |||
return nil | |||
} | |||
return &m | |||
} | |||
// GetAllDatabaseDev is 获取开发库 所有db 除了 deleted_at = 1 的 | |||
func GetAllDatabaseDev() *[]model.DbMapping { | |||
var m []model.DbMapping | |||
var err error | |||
fmt.Println("cfg.Local is: ", cfg.Local) | |||
if cfg.Local { // 本地调试 加快速度 | |||
fmt.Println("notice:LOCAL TEST, only masterId:** 123456 ** available!") | |||
err = Db.Where("deleted_at != ? AND is_dev = '1' AND db_master_id=?", 1, 123456).Find(&m) | |||
} else { | |||
err = Db.Where("deleted_at != ? AND is_dev = '1' ", 1).Find(&m) | |||
} | |||
//err := Db.Where("deleted_at != ? AND is_dev = '1' and db_master_id='123456'", 1).Find(&m) | |||
if err != nil || len(m) == 0 { | |||
logx.Warn(err) | |||
return nil | |||
} | |||
return &m | |||
} | |||
//GetDatabaseByMasterID is 根据站长id 获取对应的的数据库信息 | |||
func GetDatabaseByMasterID(Db *xorm.Engine, id string) (*model.DbMapping, error) { | |||
var m model.DbMapping | |||
has, err := Db.Where("db_master_id=?", id).Get(&m) | |||
if !has { | |||
return nil, errors.New("Not Found DB data by " + id) | |||
} | |||
if err != nil { | |||
return nil, err | |||
} | |||
if m.DbHost == "" { | |||
m.DbHost = cfg.DB.Host | |||
m.DbUsername = cfg.DB.User | |||
m.DbPassword = cfg.DB.Psw | |||
} | |||
return &m, nil | |||
} | |||
//SessionGetDatabaseByMasterID is 根据站长id 获取对应的的数据库信息 | |||
func SessionGetDatabaseByMasterID(Db *xorm.Session, id string) (*model.DbMapping, error) { | |||
var m model.DbMapping | |||
has, err := Db.Where("db_master_id=?", id).Get(&m) | |||
if !has { | |||
return nil, errors.New("Not Found DB data by " + id) | |||
} | |||
if err != nil { | |||
return nil, err | |||
} | |||
if m.DbHost == "" { | |||
m.DbHost = cfg.DB.Host | |||
m.DbName = cfg.DB.Name | |||
m.DbUsername = cfg.DB.User | |||
m.DbPassword = cfg.DB.Psw | |||
} | |||
return &m, nil | |||
} | |||
// 获取自动任务队列 | |||
func MapCrontabCfg(eg *xorm.Engine) *[]model.SysCfg { | |||
var c []model.SysCfg | |||
// 数据库查询如果有下划线会认为是一个任意字符 | |||
if err := eg.Where("`key` LIKE 'mall_cron\\_%' AND val != ''").Cols("`key`,`val`").Find(&c); err != nil || len(c) == 0 { | |||
logx.Warn(err) | |||
return nil | |||
} | |||
return &c | |||
} | |||
// 获取官方域名 | |||
func GetOfficialDomainInfoByType(Db *xorm.Engine, masterId, key string) (string, error) { | |||
type SysCfg struct { | |||
K string | |||
V string | |||
Memo string | |||
} | |||
var domainBase SysCfg | |||
has, err := Db.Where("k=?", "domain_base").Get(&domainBase) | |||
if err != nil { | |||
return "", err | |||
} | |||
if has == false { | |||
return "", errors.New("can not find key by : domain_base") | |||
} | |||
if key == "wap" { | |||
return "h5." + masterId + "." + domainBase.V, nil | |||
} | |||
if key == "api" { | |||
var apiDomain SysCfg | |||
has, err = Db.Where("k=?", "domain_api_base").Get(&apiDomain) | |||
if err != nil { | |||
return "", err | |||
} | |||
if has == false { | |||
return "", errors.New("can not find key by : domain_api_base") | |||
} | |||
return apiDomain.V, nil | |||
} | |||
if key == "admin" { | |||
return "admin." + masterId + "." + domainBase.V, nil | |||
} | |||
// 默认返回H5的 | |||
return "h5." + masterId + "." + domainBase.V, nil | |||
} |
@@ -0,0 +1,124 @@ | |||
package implement | |||
import ( | |||
"applet/app/db/dao" | |||
"applet/app/db/model" | |||
"applet/app/md" | |||
"applet/app/utils/cache" | |||
"applet/app/utils/logx" | |||
"fmt" | |||
"xorm.io/xorm" | |||
) | |||
func NewSysCfgDb(engine *xorm.Engine, masterId string) dao.SysCfgDao { | |||
return &SysCfgDb{ | |||
Db: engine, | |||
MasterId: masterId, | |||
} | |||
} | |||
type SysCfgDb struct { | |||
Db *xorm.Engine | |||
MasterId string | |||
} | |||
func (s SysCfgDb) SysCfgGetAll() (*[]model.SysCfg, error) { | |||
var cfgList []model.SysCfg | |||
if err := s.Db.Cols("key,val,memo").Find(&cfgList); err != nil { | |||
return nil, logx.Error(err) | |||
} | |||
return &cfgList, nil | |||
} | |||
func (s SysCfgDb) SysCfgGetOneNoDataNoErr(key string) (*model.SysCfg, error) { | |||
var cfgList model.SysCfg | |||
has, err := s.Db.Where("`key`=?", key).Get(&cfgList) | |||
if err != nil { | |||
return nil, logx.Error(err) | |||
} | |||
if !has { | |||
return nil, nil | |||
} | |||
return &cfgList, nil | |||
} | |||
func (s SysCfgDb) SysCfgGetOne(key string) (*model.SysCfg, error) { | |||
var cfgList model.SysCfg | |||
if has, err := s.Db.Where("`key`=?", key).Get(&cfgList); err != nil || has == false { | |||
return nil, logx.Error(err) | |||
} | |||
return &cfgList, nil | |||
} | |||
func (s SysCfgDb) SysCfgInsert(key, val, memo string) bool { | |||
cfg := model.SysCfg{Key: key, Val: val, Memo: memo} | |||
_, err := s.Db.InsertOne(&cfg) | |||
if err != nil { | |||
logx.Error(err) | |||
return false | |||
} | |||
return true | |||
} | |||
func (s SysCfgDb) SysCfgUpdate(key, val string) bool { | |||
cfg := model.SysCfg{Key: key, Val: val} | |||
_, err := s.Db.Where("`key`=?", key).Cols("val").Update(&cfg) | |||
if err != nil { | |||
logx.Error(err) | |||
return false | |||
} | |||
s.SysCfgDel(key) | |||
return true | |||
} | |||
func (s SysCfgDb) SysCfgGetWithDb(HKey string) string { | |||
cacheKey := fmt.Sprintf(md.AppCfgCacheKey, s.MasterId, HKey[0:1]) | |||
get, err := cache.HGetString(cacheKey, HKey) | |||
if err != nil || get == "" { | |||
cfg, err := s.SysCfgGetOne(HKey) | |||
if err != nil || cfg == nil { | |||
_ = logx.Error(err) | |||
return "" | |||
} | |||
// key是否存在 | |||
cacheKeyExist := false | |||
if cache.Exists(cacheKey) { | |||
cacheKeyExist = true | |||
} | |||
// 设置缓存 | |||
_, err = cache.HSet(cacheKey, HKey, cfg.Val) | |||
if err != nil { | |||
_ = logx.Error(err) | |||
return "" | |||
} | |||
if !cacheKeyExist { // 如果是首次设置 设置过期时间 | |||
_, err := cache.Expire(cacheKey, md.CfgCacheTime) | |||
if err != nil { | |||
_ = logx.Error(err) | |||
return "" | |||
} | |||
} | |||
return cfg.Val | |||
} | |||
return get | |||
} | |||
func (s SysCfgDb) SysCfgDel(HKey string) error { | |||
cacheKey := fmt.Sprintf(md.AppCfgCacheKey, s.MasterId, HKey[0:1]) | |||
_, err := cache.HDel(cacheKey, HKey) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func (s SysCfgDb) SysCfgFindWithDb(keys ...string) map[string]string { | |||
res := map[string]string{} | |||
for _, v := range keys { | |||
val := s.SysCfgGetWithDb(v) | |||
res[v] = val | |||
} | |||
return res | |||
} |
@@ -0,0 +1,37 @@ | |||
package enum | |||
type AdminState int32 | |||
const ( | |||
AdminStateForNormal = 1 | |||
AdminStateForFreeze = 2 | |||
) | |||
func (gt AdminState) String() string { | |||
switch gt { | |||
case AdminStateForNormal: | |||
return "正常" | |||
case AdminStateForFreeze: | |||
return "冻结" | |||
default: | |||
return "未知" | |||
} | |||
} | |||
type IsSuperAdministrator int32 | |||
const ( | |||
IsSuperAdministratorTure = 1 | |||
IsSuperAdministratorFalse = 2 | |||
) | |||
func (gt IsSuperAdministrator) String() string { | |||
switch gt { | |||
case IsSuperAdministratorTure: | |||
return "超管" | |||
case IsSuperAdministratorFalse: | |||
return "非超管" | |||
default: | |||
return "未知" | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package enum | |||
type PermissionGroupState int32 | |||
const ( | |||
PermissionGroupStateForNormal = 1 | |||
PermissionGroupStateForDiscard = 2 | |||
) | |||
func (gt PermissionGroupState) String() string { | |||
switch gt { | |||
case PermissionGroupStateForNormal: | |||
return "正常" | |||
case PermissionGroupStateForDiscard: | |||
return "废弃" | |||
default: | |||
return "未知" | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package enum | |||
type RoleState int32 | |||
const ( | |||
RoleStateForNormal = 1 | |||
RoleStateForFreeze = 2 | |||
) | |||
func (gt RoleState) String() string { | |||
switch gt { | |||
case RoleStateForNormal: | |||
return "正常" | |||
case RoleStateForFreeze: | |||
return "冻结" | |||
default: | |||
return "未知" | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
package hdl | |||
import ( | |||
"applet/app/e" | |||
"applet/app/lib/validate" | |||
"applet/app/md" | |||
"applet/app/svc" | |||
"applet/app/utils" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"code.fnuoos.com/zhimeng/model.git/src/implement" | |||
"fmt" | |||
"github.com/gin-gonic/gin" | |||
) | |||
// Login 登陆 | |||
// @Summary 登陆 | |||
// @Tags 登录 | |||
// @Description 登入 | |||
// @Accept json | |||
// @Produce json | |||
// @Param req body md.LoginReq true "用户名密码" | |||
// @Success 200 {object} md.LoginResponse "token" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /login [post] | |||
func Login(c *gin.Context) { | |||
var req md.LoginReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
adminDb := implement.NewAdminDb(engine) | |||
admin, err := adminDb.GetAdminByUserName(req.UserName) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err) | |||
return | |||
} | |||
if admin == nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "账号不存在!") | |||
return | |||
} | |||
if utils.Md5(req.PassWord) != admin.Password { | |||
e.OutErr(c, e.ERR_INVALID_ARGS, "密码错误") | |||
return | |||
} | |||
ip := utils.GetIP(c.Request) | |||
key := fmt.Sprintf(md.JwtTokenKey, ip, utils.AnyToString(admin.AdmId)) | |||
token, err := svc.HandleLoginToken(key, admin) | |||
if err != nil { | |||
e.OutErr(c, e.ERR, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, md.LoginResponse{ | |||
Token: token, | |||
}, nil) | |||
return | |||
} |
@@ -0,0 +1,205 @@ | |||
package hdl | |||
import ( | |||
"applet/app/e" | |||
"applet/app/lib/validate" | |||
"applet/app/md" | |||
"applet/app/svc" | |||
"applet/app/utils" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"code.fnuoos.com/zhimeng/model.git/src/implement" | |||
model2 "code.fnuoos.com/zhimeng/model.git/src/model" | |||
implement2 "code.fnuoos.com/zhimeng/model.git/src/super/implement" | |||
"code.fnuoos.com/zhimeng/model.git/src/super/model" | |||
"github.com/gin-gonic/gin" | |||
"time" | |||
) | |||
// RegisterForMedium | |||
// @Summary 媒体注册 | |||
// @Tags 注册模块 | |||
// @Description 注册模块-媒体注册 | |||
// @Accept json | |||
// @Produce json | |||
// @Param req body md.RegisterForMediumReq true "用户名密码" | |||
// @Success 200 string "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /registerForMedium [post] | |||
func RegisterForMedium(c *gin.Context) { | |||
var req md.RegisterForMediumReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
masterId := svc.GetMasterId(c) | |||
engine := db.DBs[masterId] | |||
now := time.Now() | |||
//1、判断当前账号是否已存在 | |||
mediumDb := implement.NewMediumDb(engine) | |||
medium, err := mediumDb.GetMediumByUsername(req.Phone) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err) | |||
return | |||
} | |||
if medium != nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "账号已存在!") | |||
return | |||
} | |||
//2、生成 medium_list 记录 | |||
mediumListDb := implement2.NewMediumListDb(db.Db) | |||
mediumId := utils.GenerateUniqueRandomNumbers(8) | |||
mediumList := model.MediumList{ | |||
Uuid: utils.StrToInt(masterId), | |||
MediumId: utils.StrToInt(mediumId), | |||
Kind: 1, | |||
CompanyName: "", | |||
CompanyAbbreviation: "", | |||
UnifiedSocialCreditCode: "", | |||
CertificateType: 1, | |||
BusinessLicenseImgUrl: "", | |||
LegalRepresentative: "", | |||
CountryRegionId: 1, | |||
CountryRegion: "", | |||
RegisteredAddressProvinceId: 0, | |||
RegisteredAddressCityId: 0, | |||
RegisteredAddressCountyId: 0, | |||
RegisteredAddress: "", | |||
BusinessLicenseAddress: "", | |||
CertificateValidity: "", | |||
State: 0, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
} | |||
insertAffected, err := mediumListDb.MediumListInsert(&mediumList) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if insertAffected <= 0 { | |||
e.OutErr(c, e.ERR_DB_ORM, "生成 medium_list 记录失败") | |||
return | |||
} | |||
//3、新增 medium 记录 | |||
mediumModel := model2.Medium{ | |||
MediumId: utils.StrToInt(mediumId), | |||
Username: req.Phone, | |||
Password: utils.Md5(req.PassWord), | |||
State: 1, | |||
IsSuperAdministrator: 1, | |||
Memo: "", | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
} | |||
insertAffected, err = mediumDb.MediumInsert(&mediumModel) | |||
if err != nil { | |||
return | |||
} | |||
if insertAffected <= 0 { | |||
e.OutErr(c, e.ERR_DB_ORM, "新增 medium 记录失败") | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// RegisterForAgent | |||
// @Summary 渠道代理注册 | |||
// @Tags 注册模块 | |||
// @Description 注册模块-渠道代理注册 | |||
// @Accept json | |||
// @Produce json | |||
// @Param req body md.RegisterForAgentReq true "用户名密码" | |||
// @Success 200 string "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /registerForAgent [post] | |||
func RegisterForAgent(c *gin.Context) { | |||
var req md.RegisterForAgentReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
masterId := svc.GetMasterId(c) | |||
engine := db.DBs[masterId] | |||
now := time.Now() | |||
//1、判断当前账号是否已存在 | |||
agentDb := implement.NewAgentDb(engine) | |||
agent, err := agentDb.GetAgentByUsername(req.Phone) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err) | |||
return | |||
} | |||
if agent != nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "账号已存在!") | |||
return | |||
} | |||
//2、生成 agent_list 记录 | |||
agentListDb := implement2.NewAgentListDb(db.Db) | |||
agentId := utils.GenerateUniqueRandomNumbers(8) | |||
agentList := model.AgentList{ | |||
Uuid: utils.StrToInt(masterId), | |||
AgentId: utils.StrToInt(agentId), | |||
Kind: 1, | |||
CompanyName: "", | |||
CompanyAbbreviation: "", | |||
UnifiedSocialCreditCode: "", | |||
CertificateType: 1, | |||
BusinessLicenseImgUrl: "", | |||
LegalRepresentative: "", | |||
CountryRegionId: 1, | |||
CountryRegion: "", | |||
RegisteredAddressProvinceId: 0, | |||
RegisteredAddressCityId: 0, | |||
RegisteredAddressCountyId: 0, | |||
RegisteredAddress: "", | |||
BusinessLicenseAddress: "", | |||
CertificateValidity: "", | |||
State: 0, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
} | |||
insertAffected, err := agentListDb.AgentListInsert(&agentList) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if insertAffected <= 0 { | |||
e.OutErr(c, e.ERR_DB_ORM, "生成 medium_list 记录失败") | |||
return | |||
} | |||
//3、新增 agent 记录 | |||
agentModel := model2.Agent{ | |||
AgentId: utils.StrToInt(agentId), | |||
Username: req.Phone, | |||
Password: utils.Md5(req.PassWord), | |||
State: 1, | |||
IsSuperAdministrator: 1, | |||
Memo: "", | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
} | |||
insertAffected, err = agentDb.AgentInsert(&agentModel) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if insertAffected <= 0 { | |||
e.OutErr(c, e.ERR_DB_ORM, "新增 medium 记录失败") | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} |
@@ -0,0 +1,649 @@ | |||
package hdl | |||
import ( | |||
"applet/app/e" | |||
"applet/app/enum" | |||
"applet/app/lib/validate" | |||
"applet/app/md" | |||
"applet/app/svc" | |||
"applet/app/utils" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"code.fnuoos.com/zhimeng/model.git/src/implement" | |||
"code.fnuoos.com/zhimeng/model.git/src/model" | |||
"github.com/gin-gonic/gin" | |||
"time" | |||
) | |||
// PermissionGroupList | |||
// @Summary 权限组列表 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-权限组列表 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @param adm_id query string true "管理员id" | |||
// @Success 200 {string} "具体看返回内容" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/permissionGroupList [GET] | |||
func PermissionGroupList(c *gin.Context) { | |||
roleId := c.DefaultQuery("role_id", "") | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
qrcodeWithBatchRecordsDb := implement.NewPermissionGroupDb(engine) | |||
groupList, err := qrcodeWithBatchRecordsDb.FindPermissionGroup() | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
roleDb := implement.NewRoleDb(engine, utils.StrToInt(roleId)) | |||
list, _, err := roleDb.FindPermissionGroupByRole(utils.StrToInt(roleId)) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
var isHasPermissionGroupId []string | |||
for _, v := range list { | |||
isHasPermissionGroupId = append(isHasPermissionGroupId, utils.IntToStr(v.PermissionGroup.Id)) | |||
} | |||
var tempRespMap = map[string]*md.PermissionGroupListResp{} | |||
var tempRespMapKeys []string | |||
for _, v := range *groupList { | |||
isCheck := false | |||
if utils.InArr(utils.IntToStr(v.Id), isHasPermissionGroupId) { | |||
isCheck = true | |||
} | |||
tempRespMap[utils.IntToStr(v.Id)] = &md.PermissionGroupListResp{ | |||
Id: v.Id, | |||
Name: v.Name, | |||
Key: v.Key, | |||
State: v.State, | |||
ParentId: v.ParentId, | |||
CreateAt: v.CreateAt, | |||
UpdateAt: v.UpdateAt, | |||
IsCheck: isCheck, | |||
} | |||
tempRespMapKeys = append(tempRespMapKeys, utils.IntToStr(v.Id)) | |||
} | |||
for _, v := range tempRespMap { | |||
if v.ParentId != 0 && tempRespMap[utils.IntToStr(v.ParentId)].ParentId != 0 { | |||
tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList = append(tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList, *v) | |||
} | |||
} | |||
for _, v := range tempRespMap { | |||
if v.ParentId != 0 && tempRespMap[utils.IntToStr(v.ParentId)].ParentId == 0 { | |||
tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList = append(tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList, *v) | |||
} | |||
} | |||
var resp []*md.PermissionGroupListResp | |||
for _, v := range tempRespMapKeys { | |||
if tempRespMap[v].ParentId == 0 { | |||
resp = append(resp, tempRespMap[v]) | |||
} | |||
} | |||
e.OutSuc(c, map[string]interface{}{ | |||
"list": resp, | |||
"state": []map[string]interface{}{ | |||
{ | |||
"name": enum.PermissionGroupState(enum.PermissionGroupStateForNormal).String(), | |||
"value": enum.PermissionGroupStateForNormal, | |||
}, | |||
{ | |||
"name": enum.PermissionGroupState(enum.PermissionGroupStateForDiscard).String(), | |||
"value": enum.PermissionGroupStateForDiscard, | |||
}, | |||
}, | |||
}, nil) | |||
return | |||
} | |||
// RoleList | |||
// @Summary 角色列表 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-角色列表 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Success 200 {string} "具体看返回内容" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/roleList [GET] | |||
func RoleList(c *gin.Context) { | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
roleDb := implement.NewRoleDb(engine, 0) | |||
roleList, err := roleDb.FindRole() | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
adminRoleDb := implement.NewAdminRoleDb(engine) | |||
adminDb := implement.NewAdminDb(engine) | |||
var result []*md.RoleListResp | |||
for _, v := range *roleList { | |||
var temp md.RoleListResp | |||
temp.Data = v | |||
adminRoles, err1 := adminRoleDb.FindAdminRoleByRoleId(v.Id) | |||
if err1 != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err1.Error()) | |||
return | |||
} | |||
for _, adminRole := range *adminRoles { | |||
admin, err2 := adminDb.GetAdmin(adminRole.AdmId) | |||
if err2 != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err2.Error()) | |||
return | |||
} | |||
temp.AdminList = append(temp.AdminList, struct { | |||
Name string `json:"name"` | |||
}{ | |||
Name: admin.Username, | |||
}) | |||
} | |||
result = append(result, &temp) | |||
} | |||
e.OutSuc(c, map[string]interface{}{ | |||
"list": result, | |||
"state": []map[string]interface{}{ | |||
{ | |||
"name": enum.RoleState(enum.RoleStateForNormal).String(), | |||
"value": enum.RoleStateForNormal, | |||
}, | |||
{ | |||
"name": enum.RoleState(enum.RoleStateForFreeze).String(), | |||
"value": enum.RoleStateForFreeze, | |||
}, | |||
}, | |||
}, nil) | |||
return | |||
} | |||
// AddRole | |||
// @Summary 添加角色 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-添加角色 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.AddRoleReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/addRole [POST] | |||
func AddRole(c *gin.Context) { | |||
var req md.AddRoleReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
roleDb := implement.NewRoleDb(engine, 0) | |||
now := time.Now() | |||
_, err = roleDb.RoleInsert(&model.Role{ | |||
Name: req.Name, | |||
State: enum.RoleStateForNormal, | |||
Memo: req.Memo, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
}) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// UpdateRole | |||
// @Summary 修改角色 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-修改角色 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.UpdateRoleReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/updateRole [POST] | |||
func UpdateRole(c *gin.Context) { | |||
var req md.UpdateRoleReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
roleDb := implement.NewRoleDb(engine, req.RoleId) | |||
role, err := roleDb.GetRole() | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if role == nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "未查询到相应记录") | |||
return | |||
} | |||
role.Name = req.Name | |||
role.Memo = req.Memo | |||
_, err = roleDb.UpdateRole(role, "name", "memo") | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// RoleBindPermissionGroup | |||
// @Summary 角色绑定权限组 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-角色绑定权限组 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.RoleBindPermissionGroupReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/roleBindPermissionGroup [POST] | |||
func RoleBindPermissionGroup(c *gin.Context) { | |||
var req md.RoleBindPermissionGroupReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
err = svc.RoleBindPermissionGroup(c, req) | |||
if err != nil { | |||
e.OutErr(c, e.ERR, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// UpdateRoleState | |||
// @Summary 修改角色状态 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-修改角色状态 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.UpdateRoleStateReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/updateRole [POST] | |||
func UpdateRoleState(c *gin.Context) { | |||
var req md.UpdateRoleStateReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
roleDb := implement.NewRoleDb(engine, req.RoleId) | |||
role, err := roleDb.GetRole() | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if role == nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "未查询到相应记录") | |||
return | |||
} | |||
role.State = req.State | |||
_, err = roleDb.UpdateRole(role, "state") | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// DeleteRole | |||
// @Summary 删除角色 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-删除角色 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.UpdateRoleStateReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/deleteRole/{$id} [DELETE] | |||
func DeleteRole(c *gin.Context) { | |||
id := c.Param("id") | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
roleDb := implement.NewRoleDb(engine, utils.StrToInt(id)) | |||
role, err := roleDb.GetRole() | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if role == nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "未查询到相应记录") | |||
return | |||
} | |||
err = svc.DeleteRole(c, utils.StrToInt(id)) | |||
if err != nil { | |||
e.OutErr(c, e.ERR, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// AdminList | |||
// @Summary 管理员列表 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-管理员列表 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.AdminListReq true "请求参数" | |||
// @Success 200 {string} "具体看返回内容" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/adminList [POST] | |||
func AdminList(c *gin.Context) { | |||
var req md.AdminListReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
if req.Limit == 0 { | |||
req.Limit = 10 | |||
} | |||
if req.Page == 0 { | |||
req.Page = 10 | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
adminDb := implement.NewAdminDb(engine) | |||
adminList, total, err := adminDb.FindAdmin(req.UserName, req.State, req.Page, req.Limit) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
var result []md.AdminListResp | |||
for _, v := range adminList { | |||
permissionGroupList, _, err1 := adminDb.FindAdminRolePermissionGroup(v.AdmId) | |||
if err1 != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err1.Error()) | |||
return | |||
} | |||
var roleList []string | |||
for _, v1 := range permissionGroupList { | |||
roleList = append(roleList, v1.Role.Name) | |||
} | |||
result = append(result, md.AdminListResp{ | |||
AdmId: v.AdmId, | |||
Username: v.Username, | |||
State: v.State, | |||
IsSuperAdministrator: v.IsSuperAdministrator, | |||
Memo: v.Memo, | |||
CreateAt: v.CreateAt, | |||
UpdateAt: v.UpdateAt, | |||
RoleList: roleList, | |||
}) | |||
} | |||
e.OutSuc(c, map[string]interface{}{ | |||
"list": result, | |||
"total": total, | |||
"state": []map[string]interface{}{ | |||
{ | |||
"name": enum.RoleState(enum.RoleStateForNormal).String(), | |||
"value": enum.RoleStateForNormal, | |||
}, | |||
{ | |||
"name": enum.RoleState(enum.RoleStateForFreeze).String(), | |||
"value": enum.RoleStateForFreeze, | |||
}, | |||
}, | |||
}, nil) | |||
return | |||
} | |||
// UpdateAdminState | |||
// @Summary 修改管理员状态 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-修改管理员状态 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.UpdateAdminStateReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/updateAdminState [POST] | |||
func UpdateAdminState(c *gin.Context) { | |||
var req md.UpdateAdminStateReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
admDb := implement.NewAdminDb(engine) | |||
admin, err := admDb.GetAdmin(req.AdmId) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if admin == nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "未查询到相应记录") | |||
return | |||
} | |||
admin.State = req.State | |||
_, err = admDb.UpdateAdmin(admin, "state") | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// UpdateAdmin | |||
// @Summary 修改管理员信息 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-修改管理员信息 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.UpdateAdminReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/updateAdmin [POST] | |||
func UpdateAdmin(c *gin.Context) { | |||
var req md.UpdateAdminReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
admDb := implement.NewAdminDb(engine) | |||
admin, err := admDb.GetAdmin(req.AdmId) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if admin == nil { | |||
e.OutErr(c, e.ERR_NO_DATA, "未查询到相应记录") | |||
return | |||
} | |||
admin.Username = req.Username | |||
admin.Memo = req.Memo | |||
admin.Password = utils.Md5(req.Password) | |||
_, err = admDb.UpdateAdmin(admin, "username", "memo", "password") | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// AddAdmin | |||
// @Summary 新增管理员 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-新增管理员 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.AddAdminReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/addAdmin [POST] | |||
func AddAdmin(c *gin.Context) { | |||
var req md.AddAdminReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
admDb := implement.NewAdminDb(engine) | |||
isHasAdmin, err := admDb.GetAdminByUserName(req.Username) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
if isHasAdmin != nil { | |||
e.OutErr(c, e.ERR, "当前用户名已存在,请勿重复添加") | |||
return | |||
} | |||
admId, err := admDb.CreateAdminId() | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
admin := model.Admin{ | |||
AdmId: admId, | |||
Username: req.Username, | |||
Password: utils.Md5(req.Password), | |||
State: enum.AdminStateForNormal, | |||
IsSuperAdministrator: 0, | |||
Memo: req.Memo, | |||
CreateAt: time.Now().Format("2006-01-02 15:04:05"), | |||
UpdateAt: time.Now().Format("2006-01-02 15:04:05"), | |||
} | |||
_, err = admDb.AdminInsert(&admin) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// DeleteAdmin | |||
// @Summary 删除管理员 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-删除管理员 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/deleteAdmin/{$adm_id} [DELETE] | |||
func DeleteAdmin(c *gin.Context) { | |||
admId := c.Param("adm_id") | |||
err := svc.AdminDelete(c, []int{utils.StrToInt(admId)}) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// BindAdminRole | |||
// @Summary 管理员绑定角色 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-管理员绑定角色 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @Param args body md.BindAdminRoleReq true "请求参数" | |||
// @Success 200 {string} "success" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/bindAdminRole/ [POST] | |||
func BindAdminRole(c *gin.Context) { | |||
var req md.BindAdminRoleReq | |||
err := c.ShouldBindJSON(&req) | |||
if err != nil { | |||
err = validate.HandleValidateErr(err) | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
} | |||
err = svc.BindAdminRole(c, req) | |||
if err != nil { | |||
e.OutErr(c, e.ERR, err.Error()) | |||
return | |||
} | |||
e.OutSuc(c, "success", nil) | |||
return | |||
} | |||
// AdminInfo | |||
// @Summary 管理员信息 | |||
// @Tags 权限管理 | |||
// @Description 权限管理-管理员信息 | |||
// @param Authorization header string true "验证参数Bearer和token空格拼接" | |||
// @Accept json | |||
// @Produce json | |||
// @param adm_id query string true "管理员id" | |||
// @Success 200 {string} "具体看返回内容" | |||
// @Failure 400 {object} md.Response "具体错误" | |||
// @Router /role/adminInfo [GET] | |||
func AdminInfo(c *gin.Context) { | |||
admId := c.DefaultQuery("adm_id", "") | |||
engine := db.DBs[svc.GetMasterId(c)] | |||
admDb := implement.NewAdminDb(engine) | |||
admin, err := admDb.GetAdmin(utils.StrToInt(admId)) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err.Error()) | |||
return | |||
} | |||
admin.Password = "" | |||
e.OutSuc(c, map[string]interface{}{ | |||
"info": admin, | |||
"state": []map[string]interface{}{ | |||
{ | |||
"name": enum.RoleState(enum.RoleStateForNormal).String(), | |||
"value": enum.RoleStateForNormal, | |||
}, | |||
{ | |||
"name": enum.RoleState(enum.RoleStateForFreeze).String(), | |||
"value": enum.RoleStateForFreeze, | |||
}, | |||
}, | |||
}, nil) | |||
return | |||
} |
@@ -0,0 +1,39 @@ | |||
package auth | |||
import ( | |||
"errors" | |||
"github.com/dgrijalva/jwt-go" | |||
"time" | |||
) | |||
// GenToken 生成JWT | |||
func GenToken(admId int, username string) (string, error) { | |||
// 创建一个我们自己的声明 | |||
c := JWTUser{ | |||
AdmId: admId, | |||
Username: username, | |||
StandardClaims: jwt.StandardClaims{ | |||
ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间 | |||
Issuer: "advertisement", // 签发人 | |||
}, | |||
} | |||
// 使用指定的签名方法创建签名对象 | |||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) | |||
// 使用指定的secret签名并获得完整的编码后的字符串token | |||
return token.SignedString(Secret) | |||
} | |||
// ParseToken 解析JWT | |||
func ParseToken(tokenString string) (*JWTUser, error) { | |||
// 解析token | |||
token, err := jwt.ParseWithClaims(tokenString, &JWTUser{}, func(token *jwt.Token) (i interface{}, err error) { | |||
return Secret, nil | |||
}) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if claims, ok := token.Claims.(*JWTUser); ok && token.Valid { // 校验token | |||
return claims, nil | |||
} | |||
return nil, errors.New("invalid token") | |||
} |
@@ -7,17 +7,13 @@ import ( | |||
) | |||
// TokenExpireDuration is jwt 过期时间 | |||
const TokenExpireDuration = time.Hour * 4380 | |||
const TokenExpireDuration = time.Hour * 24 | |||
var Secret = []byte("zyos") | |||
var Secret = []byte("micro_group_admin") | |||
// JWTUser 如果想要保存更多信息,都可以添加到这个结构体中 | |||
type JWTUser struct { | |||
UID int `json:"uid"` | |||
Username string `json:"username"` | |||
Phone string `json:"phone"` | |||
AppName string `json:"app_name"` | |||
MiniOpenID string `json:"mini_open_id"` // 小程序的open_id | |||
MiniSK string `json:"mini_session_key"` // 小程序的session_key | |||
AdmId int `json:"adm_id"` | |||
Username string `json:"username"` | |||
jwt.StandardClaims | |||
} |
@@ -0,0 +1,33 @@ | |||
package validate | |||
import ( | |||
"applet/app/e" | |||
"applet/app/utils" | |||
"applet/app/utils/logx" | |||
"encoding/json" | |||
"fmt" | |||
"github.com/go-playground/validator/v10" | |||
) | |||
func HandleValidateErr(err error) error { | |||
switch err.(type) { | |||
case *json.UnmarshalTypeError: | |||
return e.NewErr(e.ERR_UNMARSHAL, "参数格式错误") | |||
case validator.ValidationErrors: | |||
errs := err.(validator.ValidationErrors) | |||
transMsgMap := errs.Translate(utils.ValidatorTrans) // utils.ValidatorTrans \app\utils\validator_err_trans.go::ValidatorTransInit初始化获得 | |||
transMsgOne := transMsgMap[GetOneKeyOfMapString(transMsgMap)] | |||
return e.NewErr(e.ERR_INVALID_ARGS, transMsgOne) | |||
default: | |||
_ = logx.Error(err) | |||
return e.NewErr(e.ERR, fmt.Sprintf("validate request params, err:%v\n", err)) | |||
} | |||
} | |||
// GetOneKeyOfMapString 取出Map的一个key | |||
func GetOneKeyOfMapString(collection map[string]string) string { | |||
for k := range collection { | |||
return k | |||
} | |||
return "" | |||
} |
@@ -2,9 +2,17 @@ package md | |||
// 缓存key统一管理, %s格式化为masterId | |||
const ( | |||
JwtTokenKey = "%s:advertisement_jwt_token:%s" // jwt, 占位符:ip, admin:id | |||
JwtTokenCacheTime = 3600 * 24 | |||
AppCfgCacheKey = "%s:cfg_cache:%s" // 占位符: masterId, key的第一个字母 | |||
UserFinValidUpdateLock = "%s:user_fin_valid_update_lock:%s" // 用户余额更新锁(能拿到锁才能更新余额) | |||
AdminRolePermissionCacheTime = 3600 * 24 * 0.5 | |||
KEY_SYS_CFG_CACHE = "sys_cfg_cache" | |||
CfgCacheTime = 86400 | |||
) |
@@ -0,0 +1,7 @@ | |||
package md | |||
type Response struct { | |||
Code string `json:"code" example:"响应码"` | |||
Data interface{} `json:"data" ` //内容 | |||
Msg string `json:"msg" example:"具体错误原因"` | |||
} |
@@ -0,0 +1,11 @@ | |||
package md | |||
type LoginReq struct { | |||
UserName string `json:"username" binding:"required" example:"登录账号"` | |||
PassWord string `json:"password" binding:"required" example:"登录密码"` | |||
Code string `json:"code" example:"验证码"` | |||
} | |||
type LoginResponse struct { | |||
Token string `json:"token"` | |||
} |
@@ -0,0 +1,13 @@ | |||
package md | |||
type RegisterForMediumReq struct { | |||
Phone string `json:"phone" binding:"required" example:"登录账号"` | |||
PassWord string `json:"password" binding:"required" example:"登录密码"` | |||
Code string `json:"code" example:"验证码"` | |||
} | |||
type RegisterForAgentReq struct { | |||
Phone string `json:"phone" binding:"required" example:"登录账号"` | |||
PassWord string `json:"password" binding:"required" example:"登录密码"` | |||
Code string `json:"code" example:"验证码"` | |||
} |
@@ -0,0 +1,91 @@ | |||
package md | |||
import ( | |||
"code.fnuoos.com/zhimeng/model.git/src/model" | |||
) | |||
type RoleListResp struct { | |||
Data model.Role `json:"data"` | |||
AdminList []struct { | |||
Name string `json:"name"` | |||
} `json:"admin_list"` | |||
} | |||
type UpdateRoleStateReq struct { | |||
RoleId int `json:"role_id" binding:"required" label:"id"` | |||
State int `json:"state" binding:"required" label:"状态"` | |||
} | |||
type AddRoleReq struct { | |||
Name string `json:"name" binding:"required" label:"名称"` | |||
Memo string `json:"memo" binding:"required" label:"备注"` | |||
} | |||
type UpdateRoleReq struct { | |||
RoleId int `json:"role_id" binding:"required" label:"id"` | |||
Name string `json:"name" binding:"required" label:"名称"` | |||
Memo string `json:"memo" binding:"required" label:"备注"` | |||
} | |||
type RoleBindPermissionGroupReq struct { | |||
RoleId int `json:"role_id" binding:"required" label:"id"` | |||
PermissionIds []int `json:"permission_ids" label:"权限组id"` | |||
} | |||
type PermissionGroupListResp struct { | |||
Id int `json:"id"` | |||
Name string `json:"name"` //菜单名称 | |||
Key string `json:"key"` //唯一标识符 | |||
State int `json:"state"` | |||
ParentId int `json:"parent_id"` //父级id,为0则代表没有父级 | |||
CreateAt string `json:"create_at"` | |||
UpdateAt string `json:"update_at"` | |||
IsCheck bool `json:"is_check"` //是否用用 | |||
SubPermissionGroupList []PermissionGroupListResp `json:"sub_permission_group_list"` //子集菜单 | |||
} | |||
type AdminListReq struct { | |||
Limit int `json:"limit"` | |||
Page int `json:"page" ` | |||
UserName string `json:"username"` | |||
State int `json:"state"` | |||
} | |||
type AdminListResp struct { | |||
AdmId int `json:"adm_id"` | |||
Username string `json:"username"` | |||
State int `json:"state"` | |||
IsSuperAdministrator int `json:"is_super_administrator"` | |||
Memo string `json:"memo"` | |||
CreateAt string `json:"create_at"` | |||
UpdateAt string `json:"update_at"` | |||
RoleList []string `json:"role_list"` | |||
} | |||
type UpdateAdminStateReq struct { | |||
AdmId int `json:"adm_id" binding:"required" label:"管理员id"` | |||
State int `json:"state" binding:"required" label:"状态"` | |||
} | |||
type AddAdminReq struct { | |||
Username string `json:"username" binding:"required" label:"名称"` | |||
Password string `json:"password" binding:"required" label:"密码"` | |||
Memo string `json:"memo" label:"备注"` | |||
} | |||
type UpdateAdminReq struct { | |||
AdmId int `json:"adm_id" binding:"required" label:"管理员id"` | |||
Username string `json:"username" binding:"required" label:"名称"` | |||
Password string `json:"password" binding:"required" label:"密码"` | |||
Memo string `json:"memo" label:"备注"` | |||
} | |||
type BindAdminRoleReq struct { | |||
AdmId int `json:"adm_id" binding:"required" label:"管理员id"` | |||
RoleIds []int `json:"role_ids" label:"角色id"` | |||
} | |||
type BindAdminWithEnterpriseReq struct { | |||
AdmId int `json:"adm_id" binding:"required" label:"管理员id"` | |||
Ids []int `json:"ids" label:"记录id"` | |||
} |
@@ -0,0 +1,5 @@ | |||
package md | |||
var WhiteUri = []string{ | |||
"/api/admin/comm/getMenuList", | |||
} |
@@ -1,72 +1,26 @@ | |||
package mw | |||
import ( | |||
"errors" | |||
"applet/app/db" | |||
"applet/app/e" | |||
"applet/app/lib/arkid" | |||
"applet/app/md" | |||
"applet/app/utils" | |||
"applet/app/svc" | |||
"github.com/gin-gonic/gin" | |||
) | |||
// 检查权限, 签名等等 | |||
func Auth(c *gin.Context) { | |||
for k, v := range c.Request.Header { | |||
c.Set(k, v[0]) | |||
} | |||
token, ok := c.Get("Token") | |||
if !ok { | |||
e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("没有找到token")) | |||
return | |||
} | |||
if token == "" { | |||
e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("token 不能为空")) | |||
return | |||
} | |||
tokenStr := utils.AnyToString(token) | |||
arkIdSdk := arkid.NewArkID() | |||
var err error | |||
signUser := &md.User{} | |||
arkIdUser := new(arkid.ArkIDUser) | |||
if err = arkIdSdk.SelectFunction("arkid_user_info"). | |||
WithArgs(arkid.RequestBody{Token: tokenStr}). | |||
Result(arkIdUser); err != nil { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, err) //token 不存在 | |||
return | |||
} | |||
if arkIdUser.Username == "" { | |||
e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("Token error")) | |||
return | |||
} | |||
if err = arkIdSdk.SelectFunction("arkid_login"). | |||
WithArgs(arkid.RequestBody{Username: arkIdUser.Username, Password: utils.Md5(arkIdUser.Username)}). | |||
Result(arkIdUser); err != nil { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, err) | |||
return | |||
} | |||
signUser.Ark = arkIdUser | |||
if signUser.Ark == nil { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, errors.New("无效token")) | |||
return | |||
} | |||
signUser.Info, err = db.UserFindByArkidUserName(db.DBs[c.GetString("mid")], arkIdUser.Username) | |||
admin, err := svc.CheckUser(c) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, err) | |||
return | |||
} | |||
if signUser.Info == nil { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, errors.New("无效token")) | |||
return | |||
} | |||
signUser.Profile, err = db.UserProfileFindByArkID(db.DBs[c.GetString("mid")], utils.IntToStr(arkIdUser.UserID)) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, err) | |||
return | |||
} | |||
c.Set("user", signUser) | |||
switch err.(type) { | |||
case e.E: | |||
err1 := err.(e.E) | |||
e.OutErr(c, err1.Code, err1.Error()) | |||
return | |||
default: | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, err.Error()) | |||
return | |||
} | |||
} | |||
// 将当前请求的username信息保存到请求的上下文c上 | |||
c.Set("admin", admin) | |||
c.Next() | |||
} |
@@ -1,96 +0,0 @@ | |||
package mw | |||
import ( | |||
"applet/app/db" | |||
"applet/app/e" | |||
"applet/app/md" | |||
"applet/app/utils" | |||
"applet/app/utils/cache" | |||
"applet/app/utils/logx" | |||
"errors" | |||
"fmt" | |||
"strings" | |||
"github.com/gin-gonic/gin" | |||
) | |||
// AuthJWT is jwt middleware | |||
func AuthJWT(c *gin.Context) { | |||
authHeader := c.Request.Header.Get("Authorization") | |||
if authHeader == "" { | |||
e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("token 不能为空")) | |||
return | |||
} | |||
// 按空格分割 | |||
parts := strings.SplitN(authHeader, " ", 2) | |||
if !(len(parts) == 2 && parts[0] == "Bearer") { | |||
e.OutErr(c, e.ERR_TOKEN_FORMAT, errors.New("token 格式不对")) | |||
return | |||
} | |||
// parts[1]是token | |||
mc, err := utils.ParseToken(parts[1]) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("token 过期或无效")) | |||
return | |||
} | |||
//fmt.Println(mc.UID) | |||
// 获取user | |||
u, err := db.UserFindByID(db.DBs[c.GetString("mid")], mc.UID) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err) | |||
return | |||
} | |||
if u == nil { | |||
e.OutErr(c, e.ERR_UNAUTHORIZED, errors.New("token 过期或无效")) | |||
return | |||
} | |||
// 检验账号是否未激活或被冻结 | |||
switch u.State { | |||
case 0: | |||
e.OutErr(c, e.ERR_USER_NO_ACTIVE) | |||
return | |||
case 2: | |||
e.OutErr(c, e.ERR_USER_IS_BAN) | |||
return | |||
} | |||
// 校验是否和缓存的token一致,只能有一个token 是真实有效 | |||
key := fmt.Sprintf("%s:token:%s", c.GetString("mid"), u.Username) | |||
//fmt.Println(key) | |||
cjwt, err := cache.GetString(key) | |||
//fmt.Println(cjwt) | |||
if err != nil { | |||
logx.Warn(err) | |||
goto NOCACHE | |||
} | |||
if parts[1] != cjwt { | |||
e.OutErr(c, e.ERR_TOKEN_AUTH, errors.New("token expired")) | |||
return | |||
} | |||
NOCACHE: | |||
// 获取user profile | |||
up, err := db.UserProfileFindByID(db.DBs[c.GetString("mid")], mc.UID) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err) | |||
return | |||
} | |||
// 获取user 等级 | |||
ul, err := db.UserLevelByID(db.DBs[c.GetString("mid")], u.Level) | |||
if err != nil { | |||
e.OutErr(c, e.ERR_DB_ORM, err) | |||
return | |||
} | |||
user := &md.User{ | |||
Info: u, | |||
Profile: up, | |||
Level: ul, | |||
} | |||
// 将当前请求的username信息保存到请求的上下文c上 | |||
c.Set("user", user) | |||
// 异步处理 有效会员和新会员 | |||
c.Next() // 后续的处理函数可以用过c.Get("user")来获取当前请求的用户信息 | |||
} |
@@ -1,22 +0,0 @@ | |||
package mw | |||
import ( | |||
"strings" | |||
"github.com/gin-gonic/gin" | |||
"applet/app/e" | |||
"applet/app/md" | |||
) | |||
// 检查设备等, 把头部信息下放到hdl可以获取 | |||
func Checker(c *gin.Context) { | |||
// 校验平台支持 | |||
platform := strings.ToLower(c.GetHeader("Platform")) | |||
//fmt.Println(platform) | |||
if _, ok := md.PlatformList[platform]; !ok { | |||
e.OutErr(c, e.ERR_PLATFORM) | |||
return | |||
} | |||
c.Next() | |||
} |
@@ -1,71 +1,22 @@ | |||
package mw | |||
import ( | |||
"applet/app/e" | |||
"applet/app/svc" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"errors" | |||
"fmt" | |||
"github.com/gin-gonic/gin" | |||
"strings" | |||
"applet/app/db" | |||
"applet/app/e" | |||
"applet/app/md" | |||
) | |||
// DB is 中间件 用来检查master_id是否有对应的数据库engine | |||
func DB(c *gin.Context) { | |||
fmt.Println(c.Request.Header) | |||
masterID := c.GetHeader("master_id") | |||
masterID := svc.GetMasterId(c) | |||
fmt.Println("master_id", masterID) | |||
if masterID == "" { | |||
fmt.Println("not found master_id found MasterId start") | |||
masterID = c.GetHeader("MasterId") | |||
fmt.Println("MasterId", masterID) | |||
// if masterID still emtpy | |||
if masterID == "" { | |||
platform := c.GetHeader("Platform") | |||
if platform == md.PLATFORM_WAP { | |||
// H5 要根据域名去获取mid | |||
hostList := strings.Split(c.Request.Host, ".") | |||
if len(hostList) == 4 && (hostList[2]+"."+hostList[3] == "zhiyingos.com" || hostList[2]+"."+hostList[3] == "izhyin.com") { | |||
// 官方域名 | |||
masterID = hostList[1] | |||
} else { | |||
// 自定义域名 | |||
masterID = svc.GetWebSiteDomainMasterId(md.PLATFORM_WAP, c.Request.Host) | |||
} | |||
//requestURL := cfg.Official.URL + "/api/user/check" | |||
//fmt.Println(c.Request.Host) | |||
//client := &http.Client{ | |||
// Timeout: time.Duration(time.Second * 2), | |||
//} | |||
//data := []byte(fmt.Sprintf(`{"domain":"%s"}`, c.Request.Host)) | |||
//body := bytes.NewReader(data) | |||
//request, err := http.NewRequest("POST", requestURL, body) | |||
//if err != nil { | |||
// e.OutErr(c, e.ERR_MASTER_ID, errors.New("not found master_id in DBs")) | |||
// return | |||
//} | |||
//request.Header.Set("Content-Type", "application/json;charset=UTF-8") | |||
//resp, err := client.Do(request.WithContext(context.TODO())) | |||
//if err != nil { | |||
// e.OutErr(c, e.ERR_MASTER_ID, err) | |||
// return | |||
//} | |||
//defer resp.Body.Close() | |||
//respBytes, err := ioutil.ReadAll(resp.Body) | |||
//if err != nil { | |||
// e.OutErr(c, e.ERR_MASTER_ID, err) | |||
// return | |||
//} | |||
//mid := gjson.GetBytes(respBytes, "data.db_master_id").String() | |||
//if mid == "" { | |||
// e.OutErr(c, e.ERR_MASTER_ID, errors.New("not found master_id in DBs")) | |||
// return | |||
//} | |||
//masterID = mid | |||
} | |||
} | |||
e.OutErr(c, e.ERR_MASTER_ID, errors.New("not found master_id")) | |||
return | |||
} | |||
_, ok := db.DBs[masterID] | |||
@@ -75,19 +26,5 @@ func DB(c *gin.Context) { | |||
} | |||
fmt.Println("master_id", masterID) | |||
c.Set("mid", masterID) | |||
//判断是否有独立域名 | |||
domain_wap_base := svc.GetWebSiteDomainInfo(c, "wap") | |||
httpStr := "http://" | |||
if c.GetHeader("Platform") == md.PLATFORM_WX_APPLET || c.GetHeader("Platform") == md.PLATFORM_ALIPAY_APPLET || c.GetHeader("Platform") == md.PLATFORM_BAIDU_APPLET || c.GetHeader("Platform") == md.PLATFORM_TOUTIAO_APPLET || c.GetHeader("Platform") == md.PLATFORM_TIKTOK_APPLET { | |||
httpStr = "https://" | |||
domain_wap_base = strings.Replace(domain_wap_base, "http://", httpStr, 1) | |||
} | |||
c.Set("domain_wap_base", domain_wap_base) | |||
c.Set("http_host", httpStr) | |||
c.Set("h5_api_secret_key", svc.SysCfgGet(c, "h5_api_secret_key")) | |||
c.Set("app_api_secret_key", svc.SysCfgGet(c, "app_api_secret_key")) | |||
c.Set("applet_api_secret_key", svc.SysCfgGet(c, "applet_api_secret_key")) | |||
c.Next() | |||
} |
@@ -6,6 +6,8 @@ import ( | |||
"applet/app/mw" | |||
_ "applet/docs" | |||
"github.com/gin-gonic/gin" | |||
swaggerFiles "github.com/swaggo/files" | |||
ginSwagger "github.com/swaggo/gin-swagger" | |||
) | |||
// 初始化路由 | |||
@@ -18,6 +20,11 @@ func Init() *gin.Engine { | |||
gin.SetMode(mode) | |||
//创建一个新的启动器 | |||
r := gin.New() | |||
r.GET("/api/swagger/*any", func(c *gin.Context) { | |||
//r.Use(mw.SwagAuth()) | |||
ginSwagger.DisablingWrapHandler(swaggerFiles.Handler, "SWAGGER")(c) | |||
}) | |||
r.Use(mw.ChangeHeader) | |||
// 是否打印访问日志, 在非正式环境都打印 | |||
@@ -38,8 +45,7 @@ func Init() *gin.Engine { | |||
c.JSON(405, gin.H{"code": 405, "msg": "method not allowed", "data": []struct{}{}}) | |||
}) | |||
r.Use(mw.Cors) | |||
route(r.Group("/api/v1/mall")) | |||
rInApi(r.Group("/inapi/mall")) | |||
route(r.Group("/api")) | |||
return r | |||
} | |||
@@ -48,27 +54,30 @@ func route(r *gin.RouterGroup) { | |||
r.Use(mw.DB) // 以下接口需要用到数据库 | |||
{ | |||
r.POST("/login", hdl.Login) | |||
} | |||
r.Use(mw.CheckBody) //body参数转换 | |||
r.Use(mw.CheckSign) //签名校验 | |||
r.Use(mw.Checker) // 以下接口需要检查Header: platform | |||
{ | |||
} | |||
r.POST("/registerForMedium", hdl.RegisterForMedium) | |||
r.POST("/registerForAgent", hdl.RegisterForAgent) | |||
r.Use(mw.AuthJWT) // 以下接口需要JWT验证 | |||
{ | |||
} | |||
r.Use(mw.Auth) // 以下接口需要JWT验证 | |||
rRole(r.Group("/role")) //权限管理 | |||
} | |||
func rInApi(r *gin.RouterGroup) { | |||
//TODO::该分组中所有的接口,支持开放平台调用 | |||
r.Use(mw.DB) // 以下接口需要用到数据库 | |||
{ | |||
} | |||
r.Use(mw.AuthJWT) // 以下接口需要JWT验证 | |||
{ | |||
} | |||
func rRole(r *gin.RouterGroup) { | |||
r.GET("/roleList", hdl.RoleList) //角色列表 | |||
r.POST("/addRole", hdl.AddRole) //角色添加 | |||
r.POST("/roleBindPermissionGroup", hdl.RoleBindPermissionGroup) //角色绑定权限组 | |||
r.POST("/updateRoleState", hdl.UpdateRoleState) //修改角色状态 | |||
r.POST("/updateRole", hdl.UpdateRole) //修改角色状态 | |||
r.DELETE("/deleteRole/:id", hdl.DeleteRole) //删除角色 | |||
r.GET("/permissionGroupList", hdl.PermissionGroupList) //权限组列表 | |||
r.POST("/adminList", hdl.AdminList) //管理员列表 | |||
r.POST("/updateAdminState", hdl.UpdateAdminState) //修改管理员状态 | |||
r.POST("/updateAdmin", hdl.UpdateAdmin) //修改管理员信息 | |||
r.POST("/addAdmin", hdl.AddAdmin) //新增管理员 | |||
r.DELETE("/deleteAdmin/:adm_id", hdl.DeleteAdmin) //删除管理员 | |||
r.GET("/adminInfo", hdl.AdminInfo) //获取管理员信息 | |||
r.POST("/bindAdminRole", hdl.BindAdminRole) //绑定角色 | |||
} |
@@ -0,0 +1,31 @@ | |||
package svc | |||
import ( | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"code.fnuoos.com/zhimeng/model.git/src/implement" | |||
"github.com/gin-gonic/gin" | |||
) | |||
func AdminDelete(c *gin.Context, admIds []int) (err error) { | |||
engine := db.DBs[GetMasterId(c)] | |||
session := engine.NewSession() | |||
defer session.Close() | |||
session.Begin() | |||
//1、删除 `admin` | |||
adminDb := implement.NewAdminDb(engine) | |||
_, err = adminDb.AdminDeleteBySession(session, admIds) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//2、删除 `admin_role` | |||
adminRoleDb := implement.NewAdminRoleDb(engine) | |||
_, err = adminRoleDb.AdminDeleteBySessionForAdmId(session, admIds) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
return session.Commit() | |||
} |
@@ -0,0 +1,53 @@ | |||
package svc | |||
import ( | |||
"applet/app/lib/auth" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"code.fnuoos.com/zhimeng/model.git/src/implement" | |||
"code.fnuoos.com/zhimeng/model.git/src/model" | |||
"errors" | |||
"github.com/gin-gonic/gin" | |||
"strings" | |||
) | |||
func GetUser(c *gin.Context) *model.Admin { | |||
user, _ := c.Get("admin") | |||
if user == nil { | |||
return &model.Admin{ | |||
AdmId: 0, | |||
Username: "", | |||
Password: "", | |||
State: 0, | |||
IsSuperAdministrator: 0, | |||
Memo: "", | |||
CreateAt: "", | |||
UpdateAt: "", | |||
} | |||
} | |||
return user.(*model.Admin) | |||
} | |||
func CheckUser(c *gin.Context) (*model.Admin, error) { | |||
token := c.GetHeader("Authorization") | |||
if token == "" { | |||
return nil, errors.New("token not exist") | |||
} | |||
// 按空格分割 | |||
parts := strings.SplitN(token, " ", 2) | |||
if !(len(parts) == 2 && parts[0] == "Bearer") { | |||
return nil, errors.New("token format error") | |||
} | |||
// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它 | |||
mc, err := auth.ParseToken(parts[1]) | |||
if err != nil { | |||
return nil, err | |||
} | |||
// 获取admin | |||
adminDb := implement.NewAdminDb(db.DBs[GetMasterId(c)]) | |||
admin, err := adminDb.GetAdmin(mc.AdmId) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return admin, nil | |||
} |
@@ -1,7 +1,7 @@ | |||
package svc | |||
import ( | |||
"applet/app/db" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"github.com/gin-gonic/gin" | |||
"xorm.io/xorm" | |||
) | |||
@@ -0,0 +1,33 @@ | |||
package svc | |||
import ( | |||
"applet/app/lib/auth" | |||
"applet/app/md" | |||
"applet/app/utils/cache" | |||
"applet/app/utils/logx" | |||
"code.fnuoos.com/zhimeng/model.git/src/model" | |||
) | |||
func HandleLoginToken(cacheKey string, admin *model.Admin) (string, error) { | |||
// 获取之前生成的token | |||
token, err := cache.GetString(cacheKey) | |||
if err != nil { | |||
_ = logx.Error(err) | |||
} | |||
// 没有获取到 | |||
if err != nil || token == "" { | |||
// 生成token | |||
token, err = auth.GenToken(admin.AdmId, admin.Username) | |||
if err != nil { | |||
return "", err | |||
} | |||
// 缓存token | |||
_, err = cache.SetEx(cacheKey, token, md.JwtTokenCacheTime) | |||
if err != nil { | |||
return "", err | |||
} | |||
return token, nil | |||
} | |||
return token, nil | |||
} |
@@ -0,0 +1,58 @@ | |||
package svc | |||
import ( | |||
"fmt" | |||
"github.com/gin-gonic/gin" | |||
"strconv" | |||
) | |||
func GetMasterId(c *gin.Context) (masterId string) { | |||
masterId = c.GetHeader("master_id") | |||
if masterId != "" { | |||
return | |||
} | |||
masterId = c.GetString("master_id") | |||
if masterId == "" { | |||
//TODO::通过域名查找masterId | |||
//host := c.Request.Host | |||
//fmt.Println("not found master_id found MasterId start") | |||
//masterId = c.GetHeader("MasterId") | |||
//if masterId == "" && c.GetHeader("Platform") == md.PLATFORM_WAP { // H5 要根据域名去获取mid | |||
// hostList := strings.Split(c.Request.Host, ".") | |||
// if isNumeric(hostList[0]) { | |||
// masterId = hostList[0] | |||
// } else if isNumeric(hostList[1]) { | |||
// masterId = hostList[1] | |||
// } else { | |||
// // 自定义域名 | |||
// masterId = svc.GetWebSiteDomainMasterId(baseDb, md.PLATFORM_WAP, c.Request.Host) | |||
// } | |||
//} | |||
//if masterId == "" && c.GetHeader("Platform") == md.PLATFORM_PC { // H5 要根据域名去获取mid | |||
// hostList := strings.Split(c.Request.Host, ".") | |||
// if isNumeric(hostList[0]) { | |||
// masterId = hostList[0] | |||
// } else if isNumeric(hostList[1]) { | |||
// masterId = hostList[1] | |||
// } else { | |||
// // 自定义域名 | |||
// masterId = svc.GetWebSiteDomainMasterId(baseDb, md.PLATFORM_PC, c.Request.Host) | |||
// } | |||
//} | |||
//if masterId == "" && c.GetHeader("Platform") == "" { // 无平台访问 | |||
// hostList := strings.Split(c.Request.Host, ".") | |||
// if isNumeric(hostList[0]) { | |||
// masterId = hostList[0] | |||
// } | |||
//} | |||
} | |||
fmt.Println("master_id:::::::", masterId) | |||
return | |||
} | |||
func isNumeric(str string) bool { | |||
_, err := strconv.ParseFloat(str, 64) | |||
return err == nil | |||
} |
@@ -0,0 +1,184 @@ | |||
package svc | |||
import ( | |||
"applet/app/md" | |||
"applet/app/utils" | |||
"applet/app/utils/cache" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"code.fnuoos.com/zhimeng/model.git/src/implement" | |||
"code.fnuoos.com/zhimeng/model.git/src/model" | |||
"encoding/json" | |||
"errors" | |||
"github.com/gin-gonic/gin" | |||
"regexp" | |||
"strings" | |||
"time" | |||
) | |||
func CheckUserRole(c *gin.Context, cacheKey, uri string, admId int) (isHasPermission bool, err error) { | |||
uri = utils.UriFilterExcludeQueryString(uri) //去除uri中?后的query参数 | |||
isHasPermission = false | |||
var rolePermission []string | |||
var rolePermissionString string | |||
rolePermissionString, _ = cache.GetString(cacheKey) | |||
//TODO::判断是否在白名单中 | |||
if utils.InArr(uri, md.WhiteUri) { | |||
isHasPermission = true | |||
return | |||
} | |||
if rolePermissionString != "" { | |||
//if false { | |||
if err = json.Unmarshal([]byte(rolePermissionString), &rolePermission); err != nil { | |||
return | |||
} | |||
} else { | |||
adminDb := implement.NewAdminDb(db.DBs[GetMasterId(c)]) | |||
list, _, err1 := adminDb.GetAdminRolePermission(admId) | |||
if err1 != nil { | |||
return isHasPermission, err1 | |||
} | |||
for _, v := range list { | |||
rolePermission = append(rolePermission, v.Permission.Action) | |||
} | |||
marshal, err1 := json.Marshal(rolePermission) | |||
if err1 != nil { | |||
return isHasPermission, err1 | |||
} | |||
rolePermissionString = string(marshal) | |||
_, err = cache.SetEx(cacheKey, rolePermissionString, md.AdminRolePermissionCacheTime) | |||
} | |||
if utils.InArr(uri, rolePermission) { | |||
isHasPermission = true | |||
} else { | |||
//正则匹配占位符情况 | |||
compileRegex := regexp.MustCompile("[0-9]+") | |||
matchArr := compileRegex.FindAllString(uri, -1) | |||
if len(matchArr) > 0 { | |||
uri = strings.Replace(uri, matchArr[len(matchArr)-1], ":id", 1) | |||
if utils.InArr(uri, rolePermission) { | |||
isHasPermission = true | |||
} | |||
} | |||
} | |||
return | |||
} | |||
func DeleteRole(c *gin.Context, roleId int) (err error) { | |||
session := db.Db.NewSession() | |||
defer session.Close() | |||
session.Begin() | |||
//1、删除 `role` | |||
roleDb := implement.NewRoleDb(db.DBs[GetMasterId(c)], roleId) | |||
_, err = roleDb.RoleDeleteBySession(session, roleId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//2、删除 `role_permission_group` | |||
rolePermissionGroupDb := implement.NewRolePermissionGroupDb(db.DBs[GetMasterId(c)]) | |||
_, err = rolePermissionGroupDb.RolePermissionGroupDeleteForRoleBySession(session, roleId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//3、删除 `admin_role` | |||
adminRoleDb := implement.NewAdminRoleDb(db.DBs[GetMasterId(c)]) | |||
_, err = adminRoleDb.AdminRoleDeleteForRoleBySession(session, roleId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
return session.Commit() | |||
} | |||
func RoleBindPermissionGroup(c *gin.Context, req md.RoleBindPermissionGroupReq) (err error) { | |||
session := db.Db.NewSession() | |||
defer session.Close() | |||
session.Begin() | |||
//1、查询 `role` | |||
roleDb := implement.NewRoleDb(db.DBs[GetMasterId(c)], req.RoleId) | |||
role, err := roleDb.GetRole() | |||
if err != nil { | |||
return | |||
} | |||
if role == nil { | |||
return errors.New("未查询到相应记录") | |||
} | |||
//1、删除 `role_permission_group` | |||
rolePermissionGroupDb := implement.NewRolePermissionGroupDb(db.DBs[GetMasterId(c)]) | |||
_, err = rolePermissionGroupDb.RolePermissionGroupDeleteForRoleBySession(session, req.RoleId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//2、新增 `role_permission_group`` | |||
var mm []*model.RolePermissionGroup | |||
now := time.Now() | |||
for _, v := range req.PermissionIds { | |||
mm = append(mm, &model.RolePermissionGroup{ | |||
RoleId: role.Id, | |||
GroupId: v, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
}) | |||
} | |||
_, err = rolePermissionGroupDb.BatchAddRolePermissionGroupBySession(session, mm) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
return session.Commit() | |||
} | |||
func BindAdminRole(c *gin.Context, req md.BindAdminRoleReq) (err error) { | |||
session := db.Db.NewSession() | |||
defer session.Close() | |||
session.Begin() | |||
//1、查询 `role` | |||
adminDb := implement.NewAdminDb(db.DBs[GetMasterId(c)]) | |||
role, err := adminDb.GetAdmin(req.AdmId) | |||
if err != nil { | |||
return | |||
} | |||
if role == nil { | |||
return errors.New("未查询到相应记录") | |||
} | |||
//1、删除 `admin_role` | |||
adminRoleDb := implement.NewAdminRoleDb(db.DBs[GetMasterId(c)]) | |||
_, err = adminRoleDb.AdminRoleDeleteBySession(session, req.AdmId) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
//2、新增 `删除 `admin_role`` | |||
var mm []*model.AdminRole | |||
now := time.Now() | |||
for _, v := range req.RoleIds { | |||
mm = append(mm, &model.AdminRole{ | |||
AdmId: req.AdmId, | |||
RoleId: v, | |||
State: 1, | |||
CreateAt: now.Format("2006-01-02 15:04:05"), | |||
UpdateAt: now.Format("2006-01-02 15:04:05"), | |||
}) | |||
} | |||
_, err = adminRoleDb.BatchAddAdminRoleBySession(session, mm) | |||
if err != nil { | |||
_ = session.Rollback() | |||
return | |||
} | |||
return session.Commit() | |||
} |
@@ -1,15 +1,11 @@ | |||
package svc | |||
import ( | |||
"errors" | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"github.com/gin-gonic/gin" | |||
"strings" | |||
"xorm.io/xorm" | |||
"applet/app/cfg" | |||
"applet/app/db" | |||
"applet/app/md" | |||
"applet/app/utils" | |||
"applet/app/utils/cache" | |||
) | |||
@@ -102,74 +98,3 @@ func SysCfgSet(c *gin.Context, key, val, memo string) bool { | |||
SysCfgCleanCache() | |||
return db.SysCfgUpdate(db.DBs[c.GetString("mid")], key, val, cfg.Memo) | |||
} | |||
// 多条记录获取 | |||
func SysCfgFindByIds(eg *xorm.Engine, keys ...string) map[string]string { | |||
key := utils.Md5(eg.DataSourceName() + md.KEY_SYS_CFG_CACHE) | |||
res := map[string]string{} | |||
c, ok := cfg.MemCache.Get(key).(map[string]string) | |||
if !ok || len(c) == 0 { | |||
cfgList, _ := db.DbsSysCfgGetAll(eg) | |||
if cfgList == nil { | |||
return nil | |||
} | |||
for _, v := range *cfgList { | |||
res[v.Key] = v.Val | |||
} | |||
cfg.MemCache.Put(key, res, 10) | |||
} else { | |||
res = c | |||
} | |||
if len(keys) == 0 { | |||
return res | |||
} | |||
tmp := map[string]string{} | |||
for _, v := range keys { | |||
if val, ok := res[v]; ok { | |||
tmp[v] = val | |||
} else { | |||
tmp[v] = "" | |||
} | |||
} | |||
return tmp | |||
} | |||
// 支付配置 | |||
func SysCfgFindPayment(c *gin.Context) ([]map[string]string, error) { | |||
platform := c.GetHeader("platform") | |||
payCfg := SysCfgFind(c, "pay_wx_pay_img", "pay_ali_pay_img", "pay_balance_img", "pay_type") | |||
if payCfg["pay_wx_pay_img"] == "" || payCfg["pay_ali_pay_img"] == "" || payCfg["pay_balance_img"] == "" || payCfg["pay_type"] == "" { | |||
return nil, errors.New("lack of payment config") | |||
} | |||
payCfg["pay_wx_pay_img"] = ImageFormat(c, payCfg["pay_wx_pay_img"]) | |||
payCfg["pay_ali_pay_img"] = ImageFormat(c, payCfg["pay_ali_pay_img"]) | |||
payCfg["pay_balance_img"] = ImageFormat(c, payCfg["pay_balance_img"]) | |||
var result []map[string]string | |||
if strings.Contains(payCfg["pay_type"], "aliPay") && platform != md.PLATFORM_WX_APPLET { | |||
item := make(map[string]string) | |||
item["pay_channel"] = "alipay" | |||
item["img"] = payCfg["pay_ali_pay_img"] | |||
item["name"] = "支付宝支付" | |||
result = append(result, item) | |||
} | |||
if strings.Contains(payCfg["pay_type"], "wxPay") { | |||
item := make(map[string]string) | |||
item["pay_channel"] = "wx" | |||
item["img"] = payCfg["pay_wx_pay_img"] | |||
item["name"] = "微信支付" | |||
result = append(result, item) | |||
} | |||
if strings.Contains(payCfg["pay_type"], "walletPay") { | |||
item := make(map[string]string) | |||
item["pay_channel"] = "fin" | |||
item["img"] = payCfg["pay_balance_img"] | |||
item["name"] = "余额支付" | |||
result = append(result, item) | |||
} | |||
return result, nil | |||
} |
@@ -1,12 +1,9 @@ | |||
package utils | |||
import ( | |||
"applet/app/cfg" | |||
"bytes" | |||
"crypto/aes" | |||
"crypto/cipher" | |||
"encoding/base64" | |||
"encoding/json" | |||
"fmt" | |||
) | |||
@@ -124,49 +121,3 @@ func pKCS5Trimming(encrypt []byte) []byte { | |||
padding := encrypt[len(encrypt)-1] | |||
return encrypt[:len(encrypt)-int(padding)] | |||
} | |||
// AesAdminCurlPOST is 与后台接口加密交互 | |||
func AesAdminCurlPOST(aesData string, url string) ([]byte, error) { | |||
adminKey := cfg.Admin.AesKey | |||
adminVI := cfg.Admin.AesIV | |||
crypto := AesCrypt{ | |||
Key: []byte(adminKey), | |||
Iv: []byte(adminVI), | |||
} | |||
encrypt, err := crypto.Encrypt([]byte(aesData)) | |||
if err != nil { | |||
return nil, err | |||
} | |||
// 发送请求到后台 | |||
postData := map[string]string{ | |||
"postData": base64.StdEncoding.EncodeToString(encrypt), | |||
} | |||
fmt.Println(adminKey) | |||
fmt.Println(adminVI) | |||
fmt.Println("=======ADMIN请求=====") | |||
fmt.Println(postData) | |||
postDataByte, _ := json.Marshal(postData) | |||
rdata, err := CurlPost(url, postDataByte, nil) | |||
fmt.Println(err) | |||
if err != nil { | |||
return nil, err | |||
} | |||
fmt.Println(rdata) | |||
pass, err := base64.StdEncoding.DecodeString(string(rdata)) | |||
if err != nil { | |||
return nil, err | |||
} | |||
fmt.Println(pass) | |||
decrypt, err := crypto.Decrypt(pass) | |||
fmt.Println(err) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return decrypt, nil | |||
} |
@@ -1,46 +0,0 @@ | |||
package utils | |||
import ( | |||
"errors" | |||
"time" | |||
"applet/app/lib/auth" | |||
"github.com/dgrijalva/jwt-go" | |||
) | |||
// GenToken 生成JWT | |||
func GenToken(uid int, username, phone, appname, MiniOpenID, MiniSK string) (string, error) { | |||
// 创建一个我们自己的声明 | |||
c := auth.JWTUser{ | |||
uid, | |||
username, | |||
phone, | |||
appname, | |||
MiniOpenID, | |||
MiniSK, | |||
jwt.StandardClaims{ | |||
ExpiresAt: time.Now().Add(auth.TokenExpireDuration).Unix(), // 过期时间 | |||
Issuer: "zyos", // 签发人 | |||
}, | |||
} | |||
// 使用指定的签名方法创建签名对象 | |||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) | |||
// 使用指定的secret签名并获得完整的编码后的字符串token | |||
return token.SignedString(auth.Secret) | |||
} | |||
// ParseToken 解析JWT | |||
func ParseToken(tokenString string) (*auth.JWTUser, error) { | |||
// 解析token | |||
token, err := jwt.ParseWithClaims(tokenString, &auth.JWTUser{}, func(token *jwt.Token) (i interface{}, err error) { | |||
return auth.Secret, nil | |||
}) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if claims, ok := token.Claims.(*auth.JWTUser); ok && token.Valid { // 校验token | |||
return claims, nil | |||
} | |||
return nil, errors.New("invalid token") | |||
} |
@@ -402,8 +402,11 @@ func Scan(cursor int64, pattern string, count int64) (int64, []string, error) { | |||
return newCursor, items, nil | |||
} | |||
func LPushMax(key string, data ...interface{}) (interface{}, error) { | |||
// set | |||
return Do("LPUSH", key, data) | |||
} | |||
} | |||
func SelectDb(db int) (interface{}, error) { | |||
return Do("SELECT", db) | |||
} |
@@ -0,0 +1,146 @@ | |||
package utils | |||
import ( | |||
"errors" | |||
"math" | |||
"net" | |||
"net/http" | |||
"strings" | |||
) | |||
func GetIP(r *http.Request) string { | |||
ip := ClientPublicIP(r) | |||
if ip == "" { | |||
ip = ClientIP(r) | |||
} | |||
if ip == "" { | |||
ip = "0000" | |||
} | |||
return ip | |||
} | |||
// HasLocalIPddr 检测 IP 地址字符串是否是内网地址 | |||
// Deprecated: 此为一个错误名称错误拼写的函数,计划在将来移除,请使用 HasLocalIPAddr 函数 | |||
func HasLocalIPddr(ip string) bool { | |||
return HasLocalIPAddr(ip) | |||
} | |||
// HasLocalIPAddr 检测 IP 地址字符串是否是内网地址 | |||
func HasLocalIPAddr(ip string) bool { | |||
return HasLocalIP(net.ParseIP(ip)) | |||
} | |||
// HasLocalIP 检测 IP 地址是否是内网地址 | |||
// 通过直接对比ip段范围效率更高,详见:https://github.com/thinkeridea/go-extend/issues/2 | |||
func HasLocalIP(ip net.IP) bool { | |||
if ip.IsLoopback() { | |||
return true | |||
} | |||
ip4 := ip.To4() | |||
if ip4 == nil { | |||
return false | |||
} | |||
return ip4[0] == 10 || // 10.0.0.0/8 | |||
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12 | |||
(ip4[0] == 169 && ip4[1] == 254) || // 169.254.0.0/16 | |||
(ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16 | |||
} | |||
// ClientIP 尽最大努力实现获取客户端 IP 的算法。 | |||
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。 | |||
func ClientIP(r *http.Request) string { | |||
ip := strings.TrimSpace(strings.Split(r.Header.Get("X-Forwarded-For"), ",")[0]) | |||
if ip != "" { | |||
return ip | |||
} | |||
ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")) | |||
if ip != "" { | |||
return ip | |||
} | |||
if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil { | |||
return ip | |||
} | |||
return "" | |||
} | |||
// ClientPublicIP 尽最大努力实现获取客户端公网 IP 的算法。 | |||
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。 | |||
func ClientPublicIP(r *http.Request) string { | |||
var ip string | |||
for _, ip = range strings.Split(r.Header.Get("X-Forwarded-For"), ",") { | |||
if ip = strings.TrimSpace(ip); ip != "" && !HasLocalIPAddr(ip) { | |||
return ip | |||
} | |||
} | |||
if ip = strings.TrimSpace(r.Header.Get("X-Real-Ip")); ip != "" && !HasLocalIPAddr(ip) { | |||
return ip | |||
} | |||
if ip = RemoteIP(r); !HasLocalIPAddr(ip) { | |||
return ip | |||
} | |||
return "" | |||
} | |||
// RemoteIP 通过 RemoteAddr 获取 IP 地址, 只是一个快速解析方法。 | |||
func RemoteIP(r *http.Request) string { | |||
ip, _, _ := net.SplitHostPort(r.RemoteAddr) | |||
return ip | |||
} | |||
// IPString2Long 把ip字符串转为数值 | |||
func IPString2Long(ip string) (uint, error) { | |||
b := net.ParseIP(ip).To4() | |||
if b == nil { | |||
return 0, errors.New("invalid ipv4 format") | |||
} | |||
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil | |||
} | |||
// Long2IPString 把数值转为ip字符串 | |||
func Long2IPString(i uint) (string, error) { | |||
if i > math.MaxUint32 { | |||
return "", errors.New("beyond the scope of ipv4") | |||
} | |||
ip := make(net.IP, net.IPv4len) | |||
ip[0] = byte(i >> 24) | |||
ip[1] = byte(i >> 16) | |||
ip[2] = byte(i >> 8) | |||
ip[3] = byte(i) | |||
return ip.String(), nil | |||
} | |||
// IP2Long 把net.IP转为数值 | |||
func IP2Long(ip net.IP) (uint, error) { | |||
b := ip.To4() | |||
if b == nil { | |||
return 0, errors.New("invalid ipv4 format") | |||
} | |||
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil | |||
} | |||
// Long2IP 把数值转为net.IP | |||
func Long2IP(i uint) (net.IP, error) { | |||
if i > math.MaxUint32 { | |||
return nil, errors.New("beyond the scope of ipv4") | |||
} | |||
ip := make(net.IP, net.IPv4len) | |||
ip[0] = byte(i >> 24) | |||
ip[1] = byte(i >> 16) | |||
ip[2] = byte(i >> 8) | |||
ip[3] = byte(i) | |||
return ip, nil | |||
} |
@@ -5,6 +5,7 @@ import ( | |||
"fmt" | |||
"math/big" | |||
"math/rand" | |||
"strconv" | |||
"time" | |||
) | |||
@@ -29,3 +30,30 @@ func RandNum() string { | |||
seed := time.Now().UnixNano() + rand.Int63() | |||
return fmt.Sprintf("%05v", rand.New(rand.NewSource(seed)).Int31n(1000000)) | |||
} | |||
func GenerateUniqueRandomNumbers(n int) string { | |||
rand.Seed(time.Now().UnixNano()) // 初始化随机种子 | |||
numbers := make([]int, n) // 创建一个切片来保存随机数 | |||
for i := range numbers { | |||
j := 0 | |||
for { | |||
b := rand.Intn(10) // 生成0-9之间的随机数 | |||
numbers[i] = b | |||
for _, num := range numbers[:i] { | |||
if num == b { | |||
j++ | |||
break | |||
} | |||
} | |||
if j == 0 { | |||
break | |||
} | |||
} | |||
} | |||
var numbersStr string | |||
for _, v := range numbers { | |||
numbersStr += strconv.Itoa(v) | |||
} | |||
return numbersStr | |||
} |
@@ -0,0 +1,16 @@ | |||
package utils | |||
import ( | |||
"net/url" | |||
"strings" | |||
) | |||
func UriFilterExcludeQueryString(uri string) string { | |||
URL, _ := url.Parse(uri) | |||
clearUri := strings.ReplaceAll(uri, URL.RawQuery, "") | |||
clearUri = strings.TrimRight(clearUri, "?") | |||
return strings.TrimRight(clearUri, "/") | |||
} |
@@ -0,0 +1,23 @@ | |||
@echo off | |||
setlocal | |||
set "BasePath=./" | |||
REM 假设已经提供了文件名作为参数 | |||
set "FileName=%~1" | |||
REM 将参数设置最终文件名 | |||
set "FinalFile=%BasePath%app\db\dao\%FileName%_dao.go" | |||
REM 将文件名转换成大驼峰格式并设置成最终接口名 | |||
for /f "delims=" %%i in ('powershell -File "%BasePath%etc\ps\ConvertToUpperCase.ps1" -inputString "%FileName%"') do set "InterfaceName=%%i" | |||
REM 使用 PowerShell 替换接口名称,并指定 UTF-8 编码 | |||
powershell -Command "(Get-Content '%BasePath%etc\template\template_interface.tpl') -replace 'DemoInterface', '%InterfaceName%' | Out-File -FilePath '%BasePath%temp_interface.go' -Encoding UTF8" | |||
REM 如果需要,将临时文件重命名为最终文件(取决于move Y?N) | |||
move /Y "%BasePath%temp_interface.go" "%FinalFile%" | |||
echo Interface file %FileName%_dao.go generated successfully. | |||
endlocal |
@@ -12,7 +12,7 @@ if "%one%" NEQ "" ( | |||
set BasePath="./" | |||
set DBUSER="root" | |||
set DBPSW="Fnuo123com@" | |||
set DBNAME="fnuoos_test1" | |||
set DBNAME="advertisement" | |||
set DBHOST="119.23.182.117" | |||
set DBPORT="3306" | |||
@@ -0,0 +1,23 @@ | |||
@echo off | |||
setlocal | |||
set "BasePath=./" | |||
REM 假设已经提供了文件名作为参数 | |||
set "FileName=%~1" | |||
REM 将参数设置最终文件名 | |||
set "FinalFile=%BasePath%app\db\implement\%FileName%_implement.go" | |||
REM 将文件名转换成大驼峰格式并设置成最终实现类名 | |||
for /f "delims=" %%i in ('powershell -File "%BasePath%etc\ps\ConvertToUpperCase.ps1" -inputString "%FileName%"') do set "ImplementName=%%i" | |||
REM 使用 PowerShell 替换接口名称,并指定 UTF-8 编码 | |||
powershell -Command "(Get-Content '%BasePath%etc\template\template_implement.tpl') -replace 'DemoImplement', '%ImplementName%' | Out-File -FilePath '%BasePath%temp_implement.go' -Encoding UTF8" | |||
REM 如果需要,将临时文件重命名为最终文件(取决于move Y?N) | |||
move /Y "%BasePath%temp_implement.go" "%FinalFile%" | |||
echo Implement file %FileName%_implement.go generated successfully. | |||
endlocal |
@@ -0,0 +1,9 @@ | |||
param($inputString) | |||
$words = $inputString.Split('_') | |||
$outputString = "" | |||
foreach ($word in $words) { | |||
$outputString += $word.Substring(0,1).ToUpper() + $word.Substring(1).ToLower() + "" | |||
} | |||
$outputString = $outputString.TrimEnd() | |||
$outputString -replace ' ', '' # 如果想要没有空格的字符串,取消注释这行代码 | |||
$outputString |
@@ -0,0 +1,14 @@ | |||
package implement | |||
import ( | |||
"applet/app/db/dao" | |||
"xorm.io/xorm" | |||
) | |||
func NewDemoImplementDb(engine *xorm.Engine) dao.DemoImplementDao { | |||
return &DemoImplementDb{Db: engine} | |||
} | |||
type DemoImplementDb struct { | |||
Db *xorm.Engine | |||
} |
@@ -0,0 +1,5 @@ | |||
package dao | |||
type DemoInterfaceDao interface { | |||
//TODO:: You can add specific method definitions here | |||
} |
@@ -2,54 +2,84 @@ module applet | |||
go 1.18 | |||
replace code.fnuoos.com/zhimeng/model.git => E:/company/ad/models | |||
require ( | |||
code.fnuoos.com/zhimeng/model.git v0.0.2 | |||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 | |||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 | |||
github.com/antchfx/htmlquery v1.3.2 // indirect | |||
github.com/antchfx/xmlquery v1.4.1 // indirect | |||
github.com/boombuler/barcode v1.0.1 | |||
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5 | |||
github.com/dgrijalva/jwt-go v3.2.0+incompatible | |||
github.com/forgoer/openssl v0.0.0-20201023062029-c3112b0c8700 | |||
github.com/gin-contrib/sessions v0.0.3 | |||
github.com/gin-gonic/gin v1.6.3 | |||
github.com/go-openapi/spec v0.20.3 // indirect | |||
github.com/go-openapi/swag v0.19.15 // indirect | |||
github.com/go-playground/locales v0.13.0 | |||
github.com/go-playground/universal-translator v0.17.0 | |||
github.com/go-playground/validator/v10 v10.4.2 | |||
github.com/gin-gonic/gin v1.9.0 | |||
github.com/go-playground/locales v0.14.1 | |||
github.com/go-playground/universal-translator v0.18.1 | |||
github.com/go-playground/validator/v10 v10.11.2 | |||
github.com/go-redis/redis v6.15.9+incompatible | |||
github.com/go-sql-driver/mysql v1.6.0 | |||
github.com/gobwas/glob v0.2.3 // indirect | |||
github.com/gocolly/colly v1.2.0 | |||
github.com/golang/protobuf v1.5.2 // indirect | |||
github.com/golang/snappy v0.0.3 // indirect | |||
github.com/gomodule/redigo v2.0.0+incompatible | |||
github.com/gookit/color v1.3.8 // indirect | |||
github.com/gorilla/sessions v1.2.1 // indirect | |||
github.com/iGoogle-ink/gopay v1.5.36 | |||
github.com/iGoogle-ink/gotil v1.0.20 | |||
github.com/json-iterator/go v1.1.10 // indirect | |||
github.com/kennygrant/sanitize v1.2.4 // indirect | |||
github.com/leodido/go-urn v1.2.1 // indirect | |||
github.com/mailru/easyjson v0.7.7 // indirect | |||
github.com/makiuchi-d/gozxing v0.0.0-20210324052758-57132e828831 | |||
github.com/pkg/errors v0.9.1 | |||
github.com/qiniu/api.v7/v7 v7.8.2 | |||
github.com/robfig/cron/v3 v3.0.1 | |||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect | |||
github.com/sony/sonyflake v1.0.0 | |||
github.com/swaggo/swag v1.7.0 | |||
github.com/syyongx/php2go v0.9.4 | |||
github.com/temoto/robotstxt v1.1.2 // indirect | |||
github.com/tidwall/gjson v1.7.4 | |||
github.com/ugorji/go v1.2.5 // indirect | |||
go.uber.org/multierr v1.6.0 // indirect | |||
github.com/swaggo/files v1.0.1 | |||
github.com/swaggo/gin-swagger v1.6.0 | |||
github.com/swaggo/swag v1.8.12 | |||
github.com/syyongx/php2go v0.9.8 | |||
go.uber.org/zap v1.16.0 | |||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect | |||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 | |||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 | |||
gopkg.in/yaml.v2 v2.4.0 | |||
xorm.io/xorm v1.3.1 | |||
) | |||
require ( | |||
filippo.io/edwards25519 v1.1.0 // indirect | |||
github.com/KyleBanks/depth v1.2.1 // indirect | |||
github.com/PuerkitoBio/purell v1.1.1 // indirect | |||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect | |||
github.com/bytedance/sonic v1.8.0 // indirect | |||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect | |||
github.com/gin-contrib/sse v0.1.0 // indirect | |||
github.com/go-openapi/jsonpointer v0.19.5 // indirect | |||
github.com/go-openapi/jsonreference v0.19.6 // indirect | |||
github.com/go-openapi/spec v0.20.4 // indirect | |||
github.com/go-openapi/swag v0.19.15 // indirect | |||
github.com/go-sql-driver/mysql v1.8.1 // indirect | |||
github.com/goccy/go-json v0.10.2 // indirect | |||
github.com/golang/snappy v0.0.4 // indirect | |||
github.com/gookit/color v1.3.8 // indirect | |||
github.com/gorilla/context v1.1.1 // indirect | |||
github.com/gorilla/securecookie v1.1.1 // indirect | |||
github.com/gorilla/sessions v1.2.1 // indirect | |||
github.com/josharian/intern v1.0.0 // indirect | |||
github.com/json-iterator/go v1.1.12 // indirect | |||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect | |||
github.com/leodido/go-urn v1.2.1 // indirect | |||
github.com/mailru/easyjson v0.7.7 // indirect | |||
github.com/mattn/go-isatty v0.0.19 // indirect | |||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | |||
github.com/modern-go/reflect2 v1.0.2 // indirect | |||
github.com/onsi/ginkgo v1.15.0 // indirect | |||
github.com/onsi/gomega v1.10.5 // indirect | |||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect | |||
github.com/pkg/errors v0.9.1 // indirect | |||
github.com/syndtr/goleveldb v1.0.0 // indirect | |||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | |||
github.com/ugorji/go/codec v1.2.9 // indirect | |||
go.uber.org/atomic v1.7.0 // indirect | |||
go.uber.org/multierr v1.6.0 // indirect | |||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect | |||
golang.org/x/crypto v0.5.0 // indirect | |||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect | |||
golang.org/x/net v0.10.0 // indirect | |||
golang.org/x/sync v0.1.0 // indirect | |||
golang.org/x/sys v0.8.0 // indirect | |||
golang.org/x/text v0.9.0 // indirect | |||
golang.org/x/tools v0.7.0 // indirect | |||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect | |||
google.golang.org/protobuf v1.28.1 // indirect | |||
gopkg.in/yaml.v3 v3.0.1 // indirect | |||
honnef.co/go/tools v0.0.1-2020.1.4 // indirect | |||
xorm.io/builder v0.3.9 // indirect | |||
xorm.io/xorm v1.0.7 | |||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect | |||
) |
@@ -1,6 +1,7 @@ | |||
package main | |||
import ( | |||
db "code.fnuoos.com/zhimeng/model.git/src" | |||
"context" | |||
"fmt" | |||
"log" | |||
@@ -11,12 +12,11 @@ import ( | |||
"time" | |||
"applet/app/cfg" | |||
"applet/app/db" | |||
"applet/app/router" | |||
"applet/app/utils" | |||
) | |||
//系统初始化 | |||
// 系统初始化 | |||
func init() { | |||
cfg.InitCfg() //配置初始化 | |||
cfg.InitLog() //日志初始化 | |||
@@ -33,16 +33,23 @@ func init() { | |||
} | |||
// @title 智莺生活移动端接口 | |||
// @title 广告联盟-站长平台 | |||
// @version 1.0 | |||
// @description 移动端接口 | |||
// @termsOfService 智莺生活后端组 | |||
// @contact.name sherlockwhite | |||
// @host localhost:5000 | |||
// @description 站长后台接口 | |||
// @termsOfService http://swagger.io/terms/ | |||
// @contact.name dengbiao | |||
// @contact.url http://www.swagger.io/support | |||
// @contact.email 1239118001@qq.com | |||
// @license.name Apache 2.0 | |||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html | |||
// @host localhost:1002 or xxxx.advertisement.dengbiao.top | |||
// @securityDefinitions.apikey MasterID | |||
// @in header | |||
// @name MasterID | |||
// @BasePath / | |||
// @BasePath /api | |||
func main() { | |||
// 启动获取所有品牌 | |||
//go taoke.GetAllBrand() | |||
@@ -1,156 +0,0 @@ | |||
package test | |||
import ( | |||
"fmt" | |||
"github.com/gocolly/colly" | |||
"github.com/gocolly/colly/extensions" | |||
"github.com/tidwall/gjson" | |||
"net/http" | |||
"regexp" | |||
"strings" | |||
) | |||
/* | |||
目前可用接口 | |||
[商品查询]https://www.showdoc.com.cn/59349170678610?page_id=339616554551473 | |||
[商品详情]https://www.showdoc.com.cn/59349170678610?page_id=339687047645094 | |||
*/ | |||
// Response is SDK Response | |||
type Response struct { | |||
Msg string `json:"msg"` | |||
Success int `json:"success"` | |||
Data interface{} `json:"data"` | |||
} | |||
func main() { | |||
// // JD | |||
// postData := map[string]string{"keyword": "联想", "p": "1", "size": "10"} | |||
// fmt.Println(postData["time"]) | |||
// res, _ := zhimeng.Send("jd", "getgoods", postData) | |||
// fmt.Println(string(res)) | |||
// p := Response{} | |||
// json.Unmarshal(res, &p) | |||
// fmt.Println(p) | |||
// // VIP | |||
// postData = map[string]string{"keyword": "联想", "p": "1", "size": "10", "order": "0"} | |||
// fmt.Println(postData["time"]) | |||
// res, _ = zhimeng.Send("wph", "seach_goods", postData) | |||
// fmt.Println(string(res)) | |||
// p = Response{} | |||
// json.Unmarshal(res, &p) | |||
// fmt.Println(p) | |||
// // PDD | |||
// postData = map[string]string{"keyword": "联想", "p": "1", "size": "10", "sort": "goods_price asc"} | |||
// res, _ = zhimeng.Send("pdd", "getgoods", postData) | |||
// fmt.Println(string(res)) | |||
// p = Response{} | |||
// json.Unmarshal(res, &p) | |||
// fmt.Println(p) | |||
for i := 0; i < 1000; i++ { | |||
fmt.Println(i) | |||
scrapPDD() | |||
} | |||
} | |||
func scrapJD() { | |||
c := colly.NewCollector(func(collector *colly.Collector) { | |||
extensions.RandomUserAgent(collector) | |||
}) | |||
c.OnResponse(func(r *colly.Response) { | |||
re, _ := regexp.Compile(`[(]//[^\s]*[)]`) | |||
body := r.Body | |||
fmt.Println(string(body)) | |||
urls := re.FindAllString(string(body), -1) | |||
fmt.Println(urls) | |||
for _, url := range urls { | |||
url = strip(url, "()") | |||
url = "https:" + url | |||
fmt.Println(url) | |||
} | |||
}) | |||
c.Visit("https://wqsitem.jd.com/detail/100008309360_d100008309360_normal.html") | |||
} | |||
func scrapPDD() { | |||
var cookies = []*http.Cookie{} | |||
var mapcookies = make(map[string]string) | |||
url := fmt.Sprintf("https://mobile.yangkeduo.com/goods.html?goods_id=%s", "156632692649") | |||
cs := "api_uid=CiHUKl9DZKpL6QBVK4qWAg==; _nano_fp=Xpdbl0PyX5Pxn0TynT_DTGXbst0kz5cjzGAQDnBR; ua=Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20Win64%3B%20x64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F84.0.4147.135%20Safari%2F537.36; webp=1; quick_entrance_click_record=20200824%2C1; PDDAccessToken=XRC6FNX7FRBL6AJRMRBRN4CDG2PZXO3YJZYHFUA4O2PLDAWVYXHA1125821; pdd_user_id=9622705741400; pdd_user_uin=F27EAZ4V5S7EGEVMCJI2P7RFLE_GEXDA; chat_config={'host_whitelist':['.yangkeduo.com','.pinduoduo.com','.10010.com/queen/tencent/pinduoduo-fill.html','.ha.10086.cn/pay/card-sale!toforward.action','wap.ha.10086.cn','m.10010.com']}; pdd_vds=gaLMNqmfGfyYEpyYiZGWopaCicNHbXGWtDNcOZnWLqiDNfLHOXnZaqtCLDiX" | |||
csList := strings.Split(cs, ";") | |||
for _, c := range csList { | |||
s := strings.Trim(c, " ") | |||
sList := strings.SplitN(s, "=", 2) | |||
mapcookies[sList[len(sList)-len(sList)]] = sList[(len(sList) - len(sList) + 1)] | |||
} | |||
fmt.Println(mapcookies) | |||
for key, value := range mapcookies { | |||
if key == "ua" { | |||
continue | |||
} | |||
cookies = append(cookies, &http.Cookie{Name: key, Value: value}) | |||
} | |||
c := colly.NewCollector( | |||
colly.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36"), | |||
) | |||
c.OnResponse(func(r *colly.Response) { | |||
re, _ := regexp.Compile(`window.rawData=.*}`) | |||
body := r.Body | |||
fmt.Println(string(body)) | |||
result := re.FindString(string(body)) | |||
// fmt.Println(result) | |||
result = strings.SplitN(result, "=", 2)[1] | |||
// fmt.Println(result) | |||
value := gjson.Get(result, "store.initDataObj.goods.detailGallery") | |||
// fmt.Println(value) | |||
list := value.Array() | |||
imageList := []string{} | |||
for _, v := range list { | |||
nv := gjson.Get(v.String(), "url") | |||
imageList = append(imageList, nv.String()) | |||
} | |||
fmt.Println(imageList) | |||
ck := c.Cookies("https://mobile.yangkeduo.com") | |||
fmt.Println(ck) | |||
cookies = ck | |||
}) | |||
c.SetCookies("https://mobile.yangkeduo.com", cookies) | |||
c.Visit(url) | |||
} | |||
func strip(ss string, charss string) string { | |||
s, chars := []rune(ss), []rune(charss) | |||
length := len(s) | |||
max := len(s) - 1 | |||
l, r := true, true //标记当左端或者右端找到正常字符后就停止继续寻找 | |||
start, end := 0, max | |||
tmpEnd := 0 | |||
charset := make(map[rune]bool) //创建字符集,也就是唯一的字符,方便后面判断是否存在 | |||
for i := 0; i < len(chars); i++ { | |||
charset[chars[i]] = true | |||
} | |||
for i := 0; i < length; i++ { | |||
if _, exist := charset[s[i]]; l && !exist { | |||
start = i | |||
l = false | |||
} | |||
tmpEnd = max - i | |||
if _, exist := charset[s[tmpEnd]]; r && !exist { | |||
end = tmpEnd | |||
r = false | |||
} | |||
if !l && !r { | |||
break | |||
} | |||
} | |||
if l && r { // 如果左端和右端都没找到正常字符,那么表示该字符串没有正常字符 | |||
return "" | |||
} | |||
return string(s[start : end+1]) | |||
} |