Browse Source

change login

master
godo 3 weeks ago
parent
commit
9938f17701
  1. 2
      os/auto-imports.d.ts
  2. 16
      os/src/api/auth.ts
  3. 11
      os/src/api/captcha.ts
  4. 40
      os/src/components/auth/PasswordLogin.vue
  5. 44
      os/src/components/auth/SlideCaptcha.vue
  6. 36
      os/src/components/auth/UserRegister.vue
  7. 12
      os/src/stores/login.ts
  8. 3
      os/src/styles/login.scss
  9. 2
      os/src/utils/request.ts
  10. 19
      server/app/user/auth.go
  11. 21
      server/app/user/captcha.go
  12. 10
      server/app/user/login/const.go
  13. 22
      server/app/user/login/factory.go
  14. 86
      server/app/user/login/password.go
  15. 19
      server/app/user/login/sms.go
  16. 12
      server/common/cache.go
  17. 2
      server/middleware/serve.go
  18. 8
      server/model/auto_migrate.go
  19. 6
      server/model/user.go
  20. 2
      server/tmp/build-errors.log
  21. BIN
      server/tmp/main.exe

2
os/auto-imports.d.ts

@ -6,5 +6,5 @@
// biome-ignore lint: disable // biome-ignore lint: disable
export {} export {}
declare global { declare global {
const ElMessage: typeof import('element-plus/es')['ElMessage']
} }

16
os/src/api/auth.ts

@ -3,13 +3,7 @@ import { get, getToken, setToken,post } from '@/utils/request'
import { getClientId } from '@/utils/uuid' import { getClientId } from '@/utils/uuid'
import { errMsg } from '@/utils/msg'; import { errMsg } from '@/utils/msg';
export function loginIn(params: any) { export function loginIn(params: any) {
return fetch('user/login', { return post('user/login', params).then(res => {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json()).then(res => {
if (res.success) { if (res.success) {
setToken(res.data.token) setToken(res.data.token)
} }
@ -72,11 +66,5 @@ export async function getSmsCode(phone: string) {
return await res.json() return await res.json()
} }
export async function register(params: any) { export async function register(params: any) {
return fetch('/user/register', { return post('/user/register', params)
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => res.json())
} }

11
os/src/api/captcha.ts

@ -1,4 +1,4 @@
import {noticeMsg,successMsg} from "@/utils/msg"; import { noticeMsg} from "@/utils/msg";
import { get, post } from '@/utils/request' import { get, post } from '@/utils/request'
import { onMounted, reactive, watch } from 'vue' import { onMounted, reactive, watch } from 'vue'
@ -22,7 +22,7 @@ export const useHandler = (domRef:any) => {
domRef.value.clear && domRef.value.clear() domRef.value.clear && domRef.value.clear()
get('user/getcaptcha').then((response) => { get('user/getcaptcha').then((response) => {
console.log(response) //console.log(response)
const { data = {} } = response; const { data = {} } = response;
if (response.code === 0) { if (response.code === 0) {
cData.image = data['image_base64'] || '' cData.image = data['image_base64'] || ''
@ -45,16 +45,17 @@ export const useHandler = (domRef:any) => {
} }
const confirmEvent = (point: any, clear: any) => { const confirmEvent = (point: any, clear: any) => {
console.log(cData) //console.log(cData)
post('user/checkcaptcha', { post('user/checkcaptcha', {
point: [point.x, point.y].join(','), point: [point.x, point.y].join(','),
key: cData.captKey || '' key: cData.captKey || ''
}).then((response) => { }).then((response) => {
console.log(response) //console.log(response)
if (response.success) { if (response.success) {
successMsg(`check data success`) //successMsg(`check data success`)
state.popoverVisible = false state.popoverVisible = false
state.type = "success" state.type = "success"
return;
} else { } else {
noticeMsg(`校验失败`, '提示', 'error') noticeMsg(`校验失败`, '提示', 'error')
//warningMsg(`check data failed`) //warningMsg(`check data failed`)

40
os/src/components/auth/PasswordLogin.vue

@ -42,15 +42,16 @@ const submitForm = () => {
}); });
}; };
const showCaptcha = ref(false); // const showCaptcha = ref(false); //
const captchaPassed = ref(false); // //const captchaPassed = ref(false); //
const handleCaptchaConfirm = (success: boolean) => { const handleCaptchaConfirm = (success: boolean) => {
if (success) { if (success) {
captchaPassed.value = true; //captchaPassed.value = true;
showCaptcha.value = false;
store.onLogin({ store.onLogin({
loginType: "password", loginType: "password",
params: store.loginForm, params: store.loginForm,
}); });
showCaptcha.value = false; // //
} else { } else {
ElMessage.error("验证码验证失败,请重试"); ElMessage.error("验证码验证失败,请重试");
showCaptcha.value = false; showCaptcha.value = false;
@ -81,12 +82,7 @@ const closeCaptcha = () => {
</el-form-item> </el-form-item>
</el-form> </el-form>
<teleport to="body"> <teleport to="body">
<div v-if="showCaptcha" class="custom-captcha-dialog"> <SlideCaptcha v-if="showCaptcha" @onSuccess="handleCaptchaConfirm" @onCancel="closeCaptcha" />
<div class="overlay" @click.self="closeCaptcha"></div>
<div class="dialog-content">
<SlideCaptcha ref="captcha" @onSuccess="handleCaptchaConfirm" />
</div>
</div>
</teleport> </teleport>
</template> </template>
@ -110,31 +106,5 @@ const closeCaptcha = () => {
border-radius: 50px; border-radius: 50px;
} }
.custom-captcha-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9998;
}
.dialog-content {
padding: 20px;
z-index: 9998;
width: 350px;
}
</style> </style>

44
os/src/components/auth/SlideCaptcha.vue

@ -1,23 +1,27 @@
<template> <template>
<div class="custom-captcha-dialog">
<div class="overlay" @click.self="close"></div>
<div class="dialog-content">
<gocaptcha-slide <gocaptcha-slide
:data="handler.data" :data="handler.data"
:scope="0" :scope="0"
:events="{ :events="{
close: handler.closeEvent, close: close,
refresh: handler.refreshEvent, refresh: handler.refreshEvent,
confirm: handler.confirmEvent, confirm: handler.confirmEvent,
}" }"
ref="domRef" ref="domRef"
/> />
</div>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {useHandler} from '@/api/captcha' import {useHandler} from '@/api/captcha'
import {ref, watch} from 'vue' import {ref, watch} from 'vue'
const emit = defineEmits(['onSuccess']) const emit = defineEmits(['onSuccess','onCancel'])
const domRef = ref(null) const domRef = ref(null)
const handler = useHandler(domRef) const handler = useHandler(domRef)
@ -34,10 +38,42 @@
state.popoverVisible = true state.popoverVisible = true
} }
const close = () => { const close = () => {
emit("onCancel",true)
state.popoverVisible = false state.popoverVisible = false
} }
defineExpose({open, close}) defineExpose({open, close})
</script> </script>
<style></style> <style>
.custom-captcha-dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9998;
}
.dialog-content {
padding: 20px;
z-index: 9998;
width: 350px;
}
</style>

36
os/src/components/auth/UserRegister.vue

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useLoginStore } from "@/stores/login"; import { useLoginStore } from "@/stores/login";
import { ElMessage } from "element-plus";
import { ref, Ref } from "vue"; import { ref, Ref } from "vue";
const store = useLoginStore(); const store = useLoginStore();
interface RegisterInfo { interface RegisterInfo {
@ -86,6 +87,36 @@ const rules = {
// }, // },
// ], // ],
}; };
const regFormRef = ref();
const showCaptcha = ref(false); //
const register = () => {
regFormRef.value.validate((valid:boolean) => {
if (valid) {
showCaptcha.value = true;
} else {
return false;
}
});
};
//const captchaPassed = ref(false); //
const handleCaptchaConfirm = (success: boolean) => {
if (success) {
//captchaPassed.value = true;
showCaptcha.value = false;
store.onRegister({
loginType: "password",
action: "register",
params: registerInfo.value,
})
//
} else {
ElMessage.error("验证码验证失败,请重试");
showCaptcha.value = false;
}
};
const closeCaptcha = () => {
showCaptcha.value = false;
};
</script> </script>
<template> <template>
<el-form label-position="left" label-width="0px" :model="registerInfo" ref="regFormRef" :rules="rules"> <el-form label-position="left" label-width="0px" :model="registerInfo" ref="regFormRef" :rules="rules">
@ -127,9 +158,12 @@ const rules = {
</el-form-item> </el-form-item>
<el-form-item class="button-center"> <el-form-item class="button-center">
<el-button class="login-button" type="primary" size="large" @click="store.onRegister(registerInfo)">注册</el-button> <el-button class="login-button" type="primary" size="large" @click="register">注册</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<teleport to="body">
<SlideCaptcha v-if="showCaptcha" @onSuccess="handleCaptchaConfirm" @onCancel="closeCaptcha" />
</teleport>
</template> </template>
<style scoped> <style scoped>
.button-center { .button-center {

12
os/src/stores/login.ts

@ -42,7 +42,7 @@ export const useLoginStore = defineStore('login', () => {
thirdPartyLoginMethod.value = 'password' thirdPartyLoginMethod.value = 'password'
} }
const onRegister = async (params: any) => { const onRegister = async (params: any) => {
delete params.confirmPassword delete params.param.confirmPassword
const res = await auth.register(params) const res = await auth.register(params)
if (res.success) { if (res.success) {
@ -56,15 +56,16 @@ export const useLoginStore = defineStore('login', () => {
const postData = { const postData = {
login_type: params.loginType, login_type: params.loginType,
client_id: getClientId(), client_id: getClientId(),
action: 'login',
param: params.params, param: params.params,
} }
auth.loginIn(postData).then((res: any) => { auth.loginIn(postData).then((res: any) => {
//console.log(res) //console.log(res)
if (!params.params.rememberMe) { if (!params.params.rememberMe) {
loginForm.value.rememberMe = false // loginForm.value.rememberMe = false
loginForm.value.username = '' // loginForm.value.username = ''
loginForm.value.password = '' // loginForm.value.password = ''
} }
if (res.success) { if (res.success) {
successMsg('登录成功') successMsg('登录成功')
@ -163,8 +164,7 @@ export const useLoginStore = defineStore('login', () => {
if (res.ok) { if (res.ok) {
const data = await res.json() const data = await res.json()
if (data.success) { if (data.success) {
console.log(data.data) (window as any).WwLogin({
; (window as any).WwLogin({
id: 'qywechat-qr-code', id: 'qywechat-qr-code',
appid: data.data.corp_id, appid: data.data.corp_id,
agentid: data.data.agent_id, agentid: data.data.agent_id,

3
os/src/styles/login.scss

@ -1,5 +1,6 @@
.login-container { .login-container {
height: 100vh; height: 96vh;
overflow: hidden;
.lockscreen { .lockscreen {
height: 100%; height: 100%;
width: 100%; width: 100%;

2
os/src/utils/request.ts

@ -84,7 +84,7 @@ request.interceptors.response.use(
(err) => { (err) => {
// 处理错误信息 // 处理错误信息
if (err) { if (err) {
//console.log(err) console.log(err)
if (err.response) { if (err.response) {
const status = err.response.status; const status = err.response.status;
const message = err.response.data; const message = err.response.data;

19
server/app/user/auth.go

@ -28,21 +28,21 @@ func loginHandle(c *gin.Context) {
var req login.LoginRequest var req login.LoginRequest
// 解析请求体 // 解析请求体
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
libs.Error(c, "参数错误,登录失败") libs.Error(c, "请求参数错误,登录失败")
return return
} }
fmt.Printf("request param: %+v\n", req) //fmt.Printf("request param: %+v\n", req)
factory := &login.LoginHandlerFactory{} factory := &login.LoginHandlerFactory{}
handler, err := factory.GetHandler(req.LoginType) req.Action = "login"
handler, err := factory.GetHandler(req)
if err != nil { if err != nil {
libs.Error(c, "登录失败:"+err.Error()) libs.Error(c, "适配失败:"+err.Error())
return return
} }
user, err := handler.Login(req.Param) user, err := handler.Login()
if err != nil { if err != nil || user == nil {
libs.Error(c, "登录失败:"+err.Error()) libs.Error(c, "登录失败:"+err.Error())
return return
} }
@ -197,13 +197,14 @@ func handleRegister(c *gin.Context) {
fmt.Printf("request param: %+v\n", req) fmt.Printf("request param: %+v\n", req)
factory := &login.LoginHandlerFactory{} factory := &login.LoginHandlerFactory{}
handler, err := factory.GetHandler(req.LoginType) req.Action = "register"
handler, err := factory.GetHandler(req)
if err != nil { if err != nil {
libs.Error(c, "适配失败:"+err.Error()) libs.Error(c, "适配失败:"+err.Error())
return return
} }
_, err = handler.Register(req.Param) _, err = handler.Register()
if err != nil { if err != nil {
libs.Error(c, "注册失败:"+err.Error()) libs.Error(c, "注册失败:"+err.Error())
return return

21
server/app/user/captcha.go

@ -109,7 +109,7 @@ func sendSmsCodeHandler(c *gin.Context) {
SendTime: time.Now().Unix(), SendTime: time.Now().Unix(),
Err: err.Error(), Err: err.Error(),
} }
common.SetCache("cloudsms", record, 60*24*30) common.SetCache("cloudsms", record, 60*time.Hour)
lastSenter = nil lastSenter = nil
libs.Error(c, "短信服务不可用") libs.Error(c, "短信服务不可用")
return return
@ -283,21 +283,12 @@ func checkSlideDataHandler(c *gin.Context) {
return return
} }
//log.Printf("cacheDataByte: %v", cacheDataByte) //log.Printf("cacheDataByte: %v", cacheDataByte)
var dataBytes []byte dataBytes := common.GetCacheVal(cacheDataByte)
switch v := cacheDataByte.(type) { //log.Printf("dataBytes: %v", dataBytes)
case string:
dataBytes = []byte(v)
case []byte:
dataBytes = v
default:
libs.Error(c, "invalid cache data type")
return
}
log.Printf("dataBytes: %v", dataBytes)
// 反序列化缓存中的数据 // 反序列化缓存中的数据
var dct *slide.Block var dct *slide.Block
if err := json.Unmarshal(dataBytes, &dct); err != nil { if err := json.Unmarshal(dataBytes, &dct); err != nil {
slog.Error("json unmarshal error", "err", err) //slog.Error("json unmarshal error", "err", err)
libs.Error(c, "illegal key") libs.Error(c, "illegal key")
return return
} }
@ -308,13 +299,13 @@ func checkSlideDataHandler(c *gin.Context) {
if len(src) == 2 { if len(src) == 2 {
sx, err := strconv.ParseFloat(src[0], 64) sx, err := strconv.ParseFloat(src[0], 64)
if err != nil { if err != nil {
slog.Error("parse point error", "err", err) //slog.Error("parse point error", "err", err)
libs.Error(c, "invalid point formatr") libs.Error(c, "invalid point formatr")
return return
} }
sy, err := strconv.ParseFloat(src[1], 64) sy, err := strconv.ParseFloat(src[1], 64)
if err != nil { if err != nil {
slog.Error("parse point error", "err", err) //slog.Error("parse point error", "err", err)
libs.Error(c, "invalid point format") libs.Error(c, "invalid point format")
return return
} }

10
server/app/user/login/const.go

@ -1,6 +1,7 @@
package login package login
import ( import (
"encoding/json"
"errors" "errors"
"godocms/model" "godocms/model"
) )
@ -28,8 +29,9 @@ const (
type LoginParam interface{} type LoginParam interface{}
type LoginHandler interface { type LoginHandler interface {
Login(param LoginParam) (*model.User, error) Init(req LoginRequest) error
Register(param LoginParam) (*model.User, error) Login() (*model.User, error)
Register() (*model.User, error)
} }
var ErrNeedRegister = errors.New("need register") var ErrNeedRegister = errors.New("need register")
@ -37,7 +39,8 @@ var ErrNeedRegister = errors.New("need register")
type LoginRequest struct { type LoginRequest struct {
ClientId string `json:"client_id" binding:"required"` ClientId string `json:"client_id" binding:"required"`
LoginType string `json:"login_type" binding:"required"` LoginType string `json:"login_type" binding:"required"`
Param LoginParam `json:"param" binding:"required"` Action string `json:"action" binding:"required"`
Param json.RawMessage `json:"param" binding:"required"`
} }
const ( const (
@ -49,6 +52,7 @@ const (
LoginPlatformMicrosoftADFS = "microsoft_adfs" LoginPlatformMicrosoftADFS = "microsoft_adfs"
LoginPlatformMicrosoftOIDC = "microsoft_oidc" LoginPlatformMicrosoftOIDC = "microsoft_oidc"
LoginPlatformLDAP = "ldap" LoginPlatformLDAP = "ldap"
LoginPlatformPassword = "password" // 密码登录
) )
// 密码登录参数 // 密码登录参数

22
server/app/user/login/factory.go

@ -1,16 +1,28 @@
package login package login
import "errors" import (
"errors"
"fmt"
)
type LoginHandlerFactory struct{} type LoginHandlerFactory struct{}
func (f *LoginHandlerFactory) GetHandler(loginType string) (LoginHandler, error) { // factory.go
switch loginType { func (f *LoginHandlerFactory) GetHandler(req LoginRequest) (LoginHandler, error) {
var handler LoginHandler
switch req.LoginType {
case LoginTypePassword: case LoginTypePassword:
return &PasswordLoginHandler{}, nil handler = &PasswordLoginHandler{}
case LoginTypeSmsCode: case LoginTypeSmsCode:
return &SmsCodeLoginHandler{}, nil handler = &SmsCodeLoginHandler{}
default: default:
return nil, errors.New("unsupported login type") return nil, errors.New("unsupported login type")
} }
if err := handler.Init(req); err != nil {
return nil, fmt.Errorf("参数初始化失败: %v", err)
}
return handler, nil
} }

86
server/app/user/login/password.go

@ -1,22 +1,88 @@
package login package login
import ( import (
"encoding/json"
"errors"
"godocms/common"
"godocms/model" "godocms/model"
"log" "godocms/pkg/db"
"godocms/utils"
"time"
"gorm.io/gorm"
) )
type PasswordLoginHandler struct{} type PasswordLoginHandler struct {
loginParam *PasswordLoginParam
}
func (h *PasswordLoginHandler) Login(param LoginParam) (*model.User, error) { func (h *PasswordLoginHandler) Init(req LoginRequest) error {
p := param.(PasswordLoginParam) //此处可以根据action处理不同的数据类型的解析
log.Printf("用户登录: %+v", p) h.loginParam = new(PasswordLoginParam)
return json.Unmarshal(req.Param, h.loginParam)
}
func (h *PasswordLoginHandler) Login() (user *model.User, err error) {
if !common.LoginConf.UserNameLogin.Enable {
return nil, errors.New("登录已关闭")
}
//log.Printf("用户登录: %+v", h.loginParam.Password)
user = new(model.User)
if err := db.DB.Where("username = ?", h.loginParam.Username).First(&user).Error; err != nil {
return nil, errors.New("用户不存在")
}
if utils.HashPassword(h.loginParam.Password, user.Salt) != user.Password {
return nil, errors.New("密码错误")
}
// 实现短信验证码登录逻辑 // 实现短信验证码登录逻辑
return nil, nil return user, nil
} }
func (h *PasswordLoginHandler) Register(param LoginParam) (*model.User, error) { func (h *PasswordLoginHandler) Register() (user *model.User, err error) {
p := param.(PasswordLoginParam) //log.Printf("用户登录: %+v", h.loginParam)
log.Printf("用户登录: %+v", p) // 检查用户名和邮箱是否已存在
var existingUser model.User
result := db.DB.Where("username = ?", h.loginParam.Username).First(&existingUser)
if result.RowsAffected > 0 {
return nil, errors.New("用户名或邮箱/手机号已存在")
}
salt, err := utils.GenerateSalt(16)
if err != nil {
return nil, err
}
hashedPassword := utils.HashPassword(h.loginParam.Password, salt)
user = &model.User{
Username: h.loginParam.Username,
Password: hashedPassword,
Salt: salt,
Email: "",
Nickname: h.loginParam.Username,
Phone: "",
RoleId: 1,
Status: 0,
DeptId: 1,
AddTime: int32(time.Now().Unix()),
UpTime: 0,
}
err = db.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&user).Error; err != nil {
return err
}
return nil, nil thirdInfo := &model.UserThird{
UserID: user.ID,
Platform: LoginPlatformPassword,
ThirdUserID: h.loginParam.Username,
UnionID: h.loginParam.Username,
}
if err := tx.Create(thirdInfo).Error; err != nil {
return err
}
return nil
})
if err != nil {
return user, err
}
return user, nil
} }

19
server/app/user/login/sms.go

@ -1,22 +1,27 @@
package login package login
import ( import (
"encoding/json"
"godocms/model" "godocms/model"
"log" "log"
) )
type SmsCodeLoginHandler struct{} type SmsCodeLoginHandler struct {
param *SmsCodeLoginParam
}
func (h *SmsCodeLoginHandler) Login(param LoginParam) (*model.User, error) { func (h *SmsCodeLoginHandler) Init(req LoginRequest) error {
p := param.(SmsCodeLoginParam) h.param = new(SmsCodeLoginParam)
log.Printf("手机号登录: %+v", p) return json.Unmarshal(req.Param, h.param)
}
func (h *SmsCodeLoginHandler) Login() (*model.User, error) {
log.Printf("用户登录: %+v", h.param)
// 实现短信验证码登录逻辑 // 实现短信验证码登录逻辑
return nil, nil return nil, nil
} }
func (h *SmsCodeLoginHandler) Register(param LoginParam) (*model.User, error) { func (h *SmsCodeLoginHandler) Register() (*model.User, error) {
p := param.(SmsCodeLoginParam) log.Printf("用户登录: %+v", h.param)
log.Printf("手机号登录: %+v", p)
// 实现短信验证码注册逻辑 // 实现短信验证码注册逻辑
return nil, nil return nil, nil
} }

12
server/common/cache.go

@ -5,6 +5,18 @@ import "time"
func GetCache(k string) (interface{}, error) { func GetCache(k string) (interface{}, error) {
return Cache.Get(k) return Cache.Get(k)
} }
func GetCacheVal(cacheDataByte interface{}) []byte {
var dataBytes []byte
switch v := cacheDataByte.(type) {
case string:
dataBytes = []byte(v)
case []byte:
dataBytes = v
default:
return dataBytes
}
return dataBytes
}
func SetCache(k string, v interface{}, t time.Duration) error { func SetCache(k string, v interface{}, t time.Duration) error {
return Cache.Set(k, v, t) return Cache.Set(k, v, t)
} }

2
server/middleware/serve.go

@ -1,6 +1,7 @@
package middleware package middleware
import ( import (
"godocms/libs"
"log" "log"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -18,6 +19,7 @@ func Recover(c *gin.Context) {
if r := recover(); r != nil { if r := recover(); r != nil {
// 打印错误堆栈信息 // 打印错误堆栈信息
log.Printf("panic: %v\n", r) log.Printf("panic: %v\n", r)
libs.Error(c, "服务器内部错误")
} }
}() }()

8
server/model/auto_migrate.go

@ -10,15 +10,15 @@ import (
func AutoMigrate() error { func AutoMigrate() error {
db.DB.AutoMigrate(&User{}) db.DB.AutoMigrate(&User{})
// 使用 GORM 的 CreateIndex 方法 // 使用 GORM 的 CreateIndex 方法
createIndexIfNotExists(db.DB, &User{}, "username", "idx_user_username") // createIndexIfNotExists(db.DB, &User{}, "username", "idx_user_username")
createIndexIfNotExists(db.DB, &User{}, "email", "idx_user_email") // createIndexIfNotExists(db.DB, &User{}, "email", "idx_user_email")
createIndexIfNotExists(db.DB, &User{}, "phone", "idx_user_phone") // createIndexIfNotExists(db.DB, &User{}, "phone", "idx_user_phone")
db.DB.AutoMigrate(&UserRole{}) db.DB.AutoMigrate(&UserRole{})
db.DB.AutoMigrate(&UserDept{}) db.DB.AutoMigrate(&UserDept{})
db.DB.AutoMigrate(&UserThird{}) db.DB.AutoMigrate(&UserThird{})
return nil return nil
} }
func createIndexIfNotExists(Db *gorm.DB, model interface{}, field, indexName string) { func CreateIndexIfNotExists(Db *gorm.DB, model interface{}, field, indexName string) {
if db.AppConfig.DBType != "mongodb" { if db.AppConfig.DBType != "mongodb" {
return return
} }

6
server/model/user.go

@ -6,13 +6,13 @@ const TableNameUser = "user"
type User struct { type User struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键" json:"id"` ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键" json:"id"`
GroupID int32 `gorm:"column:group_id;default:1;comment:租户ID" json:"group_id"` GroupID int32 `gorm:"column:group_id;default:1;comment:租户ID" json:"group_id"`
Username string `gorm:"column:username;not null;unique;comment:用户姓名--例如张三" json:"username"` // 添加 unique Username string `gorm:"column:username;not null;comment:用户姓名--例如张三" json:"username"` // 添加 unique
Nickname string `gorm:"column:nickname;not null;comment:用户真实姓名" json:"nickname"` Nickname string `gorm:"column:nickname;not null;comment:用户真实姓名" json:"nickname"`
Sex int32 `gorm:"column:sex;comment:性别,0:男,1:女" json:"sex"` Sex int32 `gorm:"column:sex;comment:性别,0:男,1:女" json:"sex"`
Password string `gorm:"column:password;comment:登陆密码" json:"password"` Password string `gorm:"column:password;comment:登陆密码" json:"password"`
Salt string `gorm:"column:salt;not null;comment:salt校验" json:"salt"` Salt string `gorm:"column:salt;not null;comment:salt校验" json:"salt"`
Email string `gorm:"column:email;unique;comment:电子邮箱" json:"email"` // 添加 unique Email string `gorm:"column:email;comment:电子邮箱" json:"email"` // 添加 unique
Phone string `gorm:"column:phone;unique;comment:手机号码" json:"phone"` // 添加 unique Phone string `gorm:"column:phone;comment:手机号码" json:"phone"` // 添加 unique
Status int32 `gorm:"column:status;comment:状态,0:正常,1:删除,2封禁" json:"status"` Status int32 `gorm:"column:status;comment:状态,0:正常,1:删除,2封禁" json:"status"`
Desc string `gorm:"column:desc;comment:用户描述信息" json:"desc"` Desc string `gorm:"column:desc;comment:用户描述信息" json:"desc"`
Remark string `gorm:"column:remark;comment:备注" json:"remark"` Remark string `gorm:"column:remark;comment:备注" json:"remark"`

2
server/tmp/build-errors.log

@ -1 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
server/tmp/main.exe

Binary file not shown.
Loading…
Cancel
Save