up
This commit is contained in:
@@ -18,10 +18,8 @@ database:
|
|||||||
|
|
||||||
user:
|
user:
|
||||||
cookieTimeout: 604800
|
cookieTimeout: 604800
|
||||||
passHashType: "md5" #密码哈希类型 text md5
|
passHashType: "md5" #密码哈希类型 text md5 md5salt
|
||||||
avatarSavePath: "/data/avatar/" #头像保存的真实位置
|
|
||||||
avatarGinrouterPath: "/avatar/" #gin 路由的路径
|
|
||||||
avatarPath: "/static/avatars/def.png"
|
|
||||||
|
|
||||||
file:
|
file:
|
||||||
maxSize: 52428800
|
maxSize: 52428800
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
"apiErr":-1,
|
"apiErr":-1,
|
||||||
"postErr":-2,
|
"postErr":-2,
|
||||||
"jsonErr":-3,
|
"jsonErr":-3,
|
||||||
"userNameDup":-4
|
"userNameDup":-4,
|
||||||
|
"userNameNoFund":-41,
|
||||||
|
"userPassIncorrect":-42
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -15,11 +15,8 @@ type ConfigsWeb_ struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ConfigsUser_ struct {
|
type ConfigsUser_ struct {
|
||||||
CookieTimeout int `mapstructure:"cookieTimeout"`
|
CookieTimeout int `mapstructure:"cookieTimeout"`
|
||||||
PassHashType string `mapstructure:"passHashType"`
|
PassHashType string `mapstructure:"passHashType"`
|
||||||
AvatarSavePath string `mapstructure:"avatarSavePath"`
|
|
||||||
AvatarGinrouterPath string `mapstructure:"avatarGinrouterPath"`
|
|
||||||
AvatarPath string `mapstructure:"avatarPath"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigsFile_ struct {
|
type ConfigsFile_ struct {
|
||||||
|
|||||||
+10
-4
@@ -39,13 +39,19 @@ func Md5Str(str string) string {
|
|||||||
return hashString2
|
return hashString2
|
||||||
}
|
}
|
||||||
|
|
||||||
func HashUserPass(str string) string {
|
func HashUserPass(user *TabUser_) {
|
||||||
switch ConfigsUser.PassHashType {
|
switch ConfigsUser.PassHashType {
|
||||||
case "text":
|
case "text":
|
||||||
return str
|
break
|
||||||
case "md5":
|
case "md5":
|
||||||
return Md5Str(str)
|
user.Pass = Md5Str(user.Pass)
|
||||||
|
|
||||||
|
case "md5salt":
|
||||||
|
if user.Salt == "" {
|
||||||
|
user.Salt = RandStr32()
|
||||||
|
}
|
||||||
|
user.Pass = Md5Str(Md5Str(user.Pass) + user.Salt)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetCurrentTimeString() + RandStr32() //如果转换失败返回当前时间,避免撞库
|
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-10
@@ -1,17 +1,50 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
type APIRequestLog struct {
|
"github.com/gin-gonic/gin"
|
||||||
ID int64 `gorm:"primaryKey;column:id" json:"id"`
|
)
|
||||||
IPAddress string `gorm:"column:ip_address;size:45;not null" json:"ip_address"`
|
|
||||||
Path string `gorm:"column:path;size:500;not null" json:"path"`
|
// GetRealIP 获取真实IP(处理代理)
|
||||||
Method string `gorm:"column:method;size:10;not null" json:"method"`
|
func GetRealIP(c *gin.Context) string {
|
||||||
StatusCode int `gorm:"column:status_code;index" json:"status_code"`
|
// 优先级顺序
|
||||||
Message string `gorm:"column:error_message;type:text" json:"error_message"`
|
headers := []string{
|
||||||
CreatedAt time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP" json:"created_at"`
|
"CF-Connecting-IP", // Cloudflare
|
||||||
|
"True-Client-IP",
|
||||||
|
"X-Forwarded-For",
|
||||||
|
"X-Real-IP",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, header := range headers {
|
||||||
|
if ip := c.GetHeader(header); ip != "" {
|
||||||
|
// 处理多个IP的情况(如 X-Forwarded-For: client, proxy1, proxy2)
|
||||||
|
if strings.Contains(ip, ",") {
|
||||||
|
ips := strings.Split(ip, ",")
|
||||||
|
ip = strings.TrimSpace(ips[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if net.ParseIP(ip) != nil {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后使用Gin的ClientIP方法
|
||||||
|
return c.ClientIP()
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogAdd() {
|
func LogAdd(c *gin.Context, msg string) {
|
||||||
|
|
||||||
|
var logtemp APIRequestLog_
|
||||||
|
|
||||||
|
logtemp.IPAddress = GetRealIP(c)
|
||||||
|
logtemp.Path = c.Request.URL.Path
|
||||||
|
logtemp.Method = c.Request.Method
|
||||||
|
logtemp.Message = msg
|
||||||
|
|
||||||
|
//fmt.Println(logtemp)
|
||||||
|
DB.Create(&logtemp)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-18
@@ -25,11 +25,12 @@ type TabFileInfo_ struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TabUser_ struct {
|
type TabUser_ struct {
|
||||||
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
|
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
|
||||||
Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引
|
Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引
|
||||||
Email string `gorm:"size:255;index"` // 字符串长度限制100 索引
|
Email string `gorm:"size:255;index"` // 字符串长度限制100 索引
|
||||||
Pass string `gorm:"size:128"` // 建议存储哈希后的密码
|
Pass string `gorm:"size:128"` // 建议存储哈希后的密码
|
||||||
Type string `gorm:"size:64;default:user"` //
|
Type string `gorm:"size:64;default:user"` //
|
||||||
|
Salt string `gorm:"size:64;"`
|
||||||
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
|
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,19 +68,24 @@ type TabUserInfo_ struct {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
type TabCookie_ struct {
|
type TabCookie_ struct {
|
||||||
ID uint `gorm:"primaryKey;autoIncrement"`
|
ID uint `gorm:"primaryKey;autoIncrement"`
|
||||||
UserID uint `gorm:"size:16;not null"`
|
UserID uint `gorm:"size:16;not null"`
|
||||||
Name string `gorm:"size:255;not null;index"`
|
Name string `gorm:"size:255;not null;index"`
|
||||||
Value string `gorm:"size:255;not null;index"`
|
Value string `gorm:"size:255;not null;index"`
|
||||||
Domain string `gorm:"size:255;not null"`
|
ExpiresAt time.Time `gorm:"type:datetime;index"`
|
||||||
Path string `gorm:"size:255;not null;default:/"`
|
CreatedAt time.Time `gorm:"type:datetime;not null;default:CURRENT_TIMESTAMP"`
|
||||||
ExpiresAt time.Time `gorm:"type:datetime;index"`
|
UpdatedAt time.Time `gorm:"type:datetime;index;not null;default:CURRENT_TIMESTAMP"`
|
||||||
CreatedAt time.Time `gorm:"type:datetime;not null;default:CURRENT_TIMESTAMP"`
|
Remember bool `gorm:"default:false"`
|
||||||
UpdatedAt time.Time `gorm:"type:datetime;index;not null;default:CURRENT_TIMESTAMP"`
|
}
|
||||||
SecureFlag bool `gorm:"not null;default:false"`
|
|
||||||
HttpOnly bool `gorm:"not null;default:false"`
|
type APIRequestLog_ struct {
|
||||||
SameSite string `gorm:"size:10;not null;default:'Lax'"`
|
ID int64 `gorm:"primaryKey;column:id" json:"id"`
|
||||||
PartitionKey string `gorm:"size:50"`
|
IPAddress string `gorm:"column:ip_address;size:45;not null" json:"ip_address"`
|
||||||
|
Path string `gorm:"column:path;size:500;not null" json:"path"`
|
||||||
|
Method string `gorm:"column:method;size:10;not null" json:"method"`
|
||||||
|
StatusCode int `gorm:"column:status_code;index" json:"status_code"`
|
||||||
|
Message string `gorm:"column:error_message;type:text" json:"error_message"`
|
||||||
|
CreatedAt time.Time `gorm:"column:created_at;type:datetime;default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func DatabaseInit() error {
|
func DatabaseInit() error {
|
||||||
@@ -115,5 +121,7 @@ func DatabaseInit() error {
|
|||||||
|
|
||||||
DB.AutoMigrate(&TabFileInfo_{})
|
DB.AutoMigrate(&TabFileInfo_{})
|
||||||
|
|
||||||
|
DB.AutoMigrate(&APIRequestLog_{})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package routers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"ops/models"
|
"ops/models"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -20,8 +21,12 @@ func ApiInit() {
|
|||||||
if models.DB.Where(&user).First(&user).Error == nil {
|
if models.DB.Where(&user).First(&user).Error == nil {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("用户不存在")
|
//fmt.Println("用户不存在")
|
||||||
user.Pass = models.HashUserPass("adminpassword")
|
|
||||||
|
//对密码加盐
|
||||||
|
user.Salt = models.RandStr32()
|
||||||
|
user.Pass = "adminpassword"
|
||||||
|
models.HashUserPass(&user)
|
||||||
models.DB.Create(&user) // 传入指针
|
models.DB.Create(&user) // 传入指针
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +59,12 @@ type From_user_add struct {
|
|||||||
Userpass string `json:"userpass"`
|
Userpass string `json:"userpass"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type From_user_login struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Userpass string `json:"userpass"`
|
||||||
|
Remember bool `json:"remember"`
|
||||||
|
}
|
||||||
|
|
||||||
func ApiUser(r *gin.RouterGroup) {
|
func ApiUser(r *gin.RouterGroup) {
|
||||||
|
|
||||||
r.GET("/test", func(ctx *gin.Context) {
|
r.GET("/test", func(ctx *gin.Context) {
|
||||||
@@ -62,6 +73,67 @@ func ApiUser(r *gin.RouterGroup) {
|
|||||||
r.POST("/test", func(ctx *gin.Context) {
|
r.POST("/test", func(ctx *gin.Context) {
|
||||||
ReturnJson(ctx, "apiOK", nil)
|
ReturnJson(ctx, "apiOK", nil)
|
||||||
})
|
})
|
||||||
|
//用户登陆
|
||||||
|
r.POST("/login", func(ctx *gin.Context) {
|
||||||
|
var loginuser From_user_login
|
||||||
|
data, _ := SeparateData(ctx)
|
||||||
|
if data != nil {
|
||||||
|
if err := mapstructure.Decode(data, &loginuser); err == nil {
|
||||||
|
if loginuser.Username != "" && loginuser.Userpass != "" {
|
||||||
|
//传入的数据都ok,获取用户信息
|
||||||
|
|
||||||
|
getuser := models.TabUser_{
|
||||||
|
Name: loginuser.Username,
|
||||||
|
}
|
||||||
|
|
||||||
|
if models.DB.Where(&getuser).First(&getuser).Error == nil {
|
||||||
|
//倒入数据
|
||||||
|
user := models.TabUser_{
|
||||||
|
Pass: loginuser.Userpass, //密码明文
|
||||||
|
Salt: getuser.Salt, //保存的盐制
|
||||||
|
}
|
||||||
|
//哈希密
|
||||||
|
models.HashUserPass(&user)
|
||||||
|
if user.Pass == getuser.Pass {
|
||||||
|
//用户密码正确,生成cookie
|
||||||
|
cookie := models.TabCookie_{
|
||||||
|
UserID: getuser.ID,
|
||||||
|
Name: "login",
|
||||||
|
Value: models.RandStr32(),
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
ExpiresAt: time.Now().Add(time.Duration(models.ConfigsUser.CookieTimeout) * time.Second), //计算过期时间,
|
||||||
|
Remember: loginuser.Remember,
|
||||||
|
}
|
||||||
|
models.DB.Create(&cookie) // 传入指针
|
||||||
|
|
||||||
|
redata := map[string]interface{}{
|
||||||
|
"cookie": cookie,
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnJson(ctx, "apiOK", redata)
|
||||||
|
} else {
|
||||||
|
ReturnJson(ctx, "userPassIncorrect", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//用户不存在
|
||||||
|
ReturnJson(ctx, "userNameNoFund", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ReturnJson(ctx, "jsonErr", nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ReturnJson(ctx, "jsonErr", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ReturnJson(ctx, "postErr", nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//用户注册
|
||||||
r.POST("/register", func(ctx *gin.Context) {
|
r.POST("/register", func(ctx *gin.Context) {
|
||||||
//转换传进来的数据
|
//转换传进来的数据
|
||||||
var jsonData From_user_add
|
var jsonData From_user_add
|
||||||
@@ -79,8 +151,7 @@ func ApiUser(r *gin.RouterGroup) {
|
|||||||
// Date 字段无需赋值,数据库会自动填充默认值
|
// Date 字段无需赋值,数据库会自动填充默认值
|
||||||
}
|
}
|
||||||
if newUser.Name != "" && newUser.Pass != "" && newUser.Email != "" {
|
if newUser.Name != "" && newUser.Pass != "" && newUser.Email != "" {
|
||||||
//对用户的密码进行哈希替换
|
|
||||||
newUser.Pass = models.HashUserPass(newUser.Pass)
|
|
||||||
//用户名是唯一的,先读取是否有这个用户名
|
//用户名是唯一的,先读取是否有这个用户名
|
||||||
var user models.TabUser_
|
var user models.TabUser_
|
||||||
user.Name = newUser.Name
|
user.Name = newUser.Name
|
||||||
@@ -90,13 +161,18 @@ func ApiUser(r *gin.RouterGroup) {
|
|||||||
ReturnJson(ctx, "userNameDup", nil)
|
ReturnJson(ctx, "userNameDup", nil)
|
||||||
} else {
|
} else {
|
||||||
//fmt.Println("用户不存在")
|
//fmt.Println("用户不存在")
|
||||||
|
|
||||||
|
//对密码加盐
|
||||||
|
newUser.Salt = models.RandStr32()
|
||||||
|
|
||||||
|
//对用户的密码进行哈希替换
|
||||||
|
models.HashUserPass(&newUser)
|
||||||
|
|
||||||
models.DB.Create(&newUser) // 传入指针
|
models.DB.Create(&newUser) // 传入指针
|
||||||
|
|
||||||
// //创建info
|
//创建用户后写一个log
|
||||||
// var user_info models.TabUserInfo_
|
|
||||||
// user_info.AvatarPath = models.ConfigsUser.AvatarPath
|
models.LogAdd(ctx, "New user id:"+strconv.Itoa(int(newUser.ID)))
|
||||||
// user_info.UserID = newUser.ID
|
|
||||||
// models.DB.Create(&user_info) // 传入指针
|
|
||||||
|
|
||||||
ReturnJson(ctx, "apiOK", nil)
|
ReturnJson(ctx, "apiOK", nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,45 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { useUserStore } from "@/stores/user";
|
||||||
|
|
||||||
import { RouterLink} from 'vue-router'
|
import { RouterLink } from "vue-router";
|
||||||
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
import { myfuncs } from '@/myfunc.js'
|
import { myfuncs } from "@/myfunc.js";
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from "vue";
|
||||||
|
|
||||||
// 使用 vue-i18n 的 Composition API
|
// 使用 vue-i18n 的 Composition API
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n();
|
||||||
|
const userStore = useUserStore();
|
||||||
const theTeme = ref('light')
|
const theTeme = ref("light");
|
||||||
const lang_sele = ref(null)
|
const lang_sele = ref(null);
|
||||||
|
|
||||||
const isLogin = false
|
|
||||||
|
|
||||||
function set_them(temp) {
|
function set_them(temp) {
|
||||||
theTeme.value = temp
|
theTeme.value = temp;
|
||||||
myfuncs.setTheme(temp, true)
|
myfuncs.setTheme(temp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeLanguage(lang) {
|
function changeLanguage(lang) {
|
||||||
// 切换语言
|
// 切换语言
|
||||||
const selectElement = lang.target
|
const selectElement = lang.target;
|
||||||
const selectedLang = selectElement.value
|
const selectedLang = selectElement.value;
|
||||||
locale.value = selectedLang
|
locale.value = selectedLang;
|
||||||
myfuncs.save('userLanguage', selectedLang)
|
myfuncs.save("userLanguage", selectedLang);
|
||||||
//console.log("selectedLang:",selectedLang);
|
//console.log("selectedLang:",selectedLang);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const savedTheme = myfuncs.getThemefromStorge()
|
const savedTheme = myfuncs.getThemefromStorge();
|
||||||
theTeme.value = savedTheme
|
theTeme.value = savedTheme;
|
||||||
myfuncs.setTheme(savedTheme, false)
|
myfuncs.setTheme(savedTheme, false);
|
||||||
const userLang = myfuncs.load('userLanguage')
|
const userLang = myfuncs.load("userLanguage");
|
||||||
if (userLang) {
|
if (userLang) {
|
||||||
locale.value = userLang
|
locale.value = userLang;
|
||||||
if (lang_sele.value) {
|
if (lang_sele.value) {
|
||||||
;(lang_sele.value).value = userLang
|
lang_sele.value.value = userLang;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -60,7 +59,9 @@ onMounted(() => {
|
|||||||
</button>
|
</button>
|
||||||
<!-- END NAVBAR TOGGLER -->
|
<!-- END NAVBAR TOGGLER -->
|
||||||
<!-- BEGIN NAVBAR LOGO -->
|
<!-- BEGIN NAVBAR LOGO -->
|
||||||
<div class="navbar-brand navbar-brand-autodark d-none-navbar-horizontal pe-0 pe-md-3">
|
<div
|
||||||
|
class="navbar-brand navbar-brand-autodark d-none-navbar-horizontal pe-0 pe-md-3"
|
||||||
|
>
|
||||||
<router-link to="/" aria-label="Tabler">
|
<router-link to="/" aria-label="Tabler">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -137,8 +138,8 @@ onMounted(() => {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- 这里判断是否已经登陆 是则显示用户信息 否则显示登陆按钮 -->
|
<!-- 这里判断是否已经登陆 是则显示用户信息 否则显示登陆按钮 -->
|
||||||
<div v-if="!isLogin" class="nav-item">
|
<div v-if="!userStore.isLoggedIn" class="nav-item">
|
||||||
<router-link to="login" class="btn btn-outline-primary" >
|
<router-link to="login" class="btn btn-outline-primary">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="icon"
|
class="icon"
|
||||||
@@ -157,18 +158,21 @@ onMounted(() => {
|
|||||||
<path d="M19 22v-6"></path>
|
<path d="M19 22v-6"></path>
|
||||||
<path d="M22 19l-3 -3l-3 3"></path>
|
<path d="M22 19l-3 -3l-3 3"></path>
|
||||||
</svg>
|
</svg>
|
||||||
{{ t('message.login_or_register') }}
|
{{ t("message.login_or_register") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="isLogin" class="nav-item dropdown">
|
<div v-if="userStore.isLoggedIn" class="nav-item dropdown">
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
class="nav-link d-flex lh-1 p-0 px-2"
|
class="nav-link d-flex lh-1 p-0 px-2"
|
||||||
data-bs-toggle="dropdown"
|
data-bs-toggle="dropdown"
|
||||||
aria-label="Open user menu"
|
aria-label="Open user menu"
|
||||||
>
|
>
|
||||||
<span class="avatar avatar-sm" style="background-image: url(./static/avatars/000m.jpg)">
|
<span
|
||||||
|
class="avatar avatar-sm"
|
||||||
|
style="background-image: url(./static/avatars/000m.jpg)"
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
<div class="d-none d-xl-block ps-2">
|
<div class="d-none d-xl-block ps-2">
|
||||||
<div>Paweł Kuna</div>
|
<div>Paweł Kuna</div>
|
||||||
@@ -213,15 +217,23 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
<path d="M5 12l-2 0l9 -9l9 9l-2 0" />
|
<path d="M5 12l-2 0l9 -9l9 9l-2 0" />
|
||||||
<path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" />
|
<path d="M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7" />
|
||||||
<path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6" /></svg
|
<path
|
||||||
|
d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6"
|
||||||
|
/></svg
|
||||||
></span>
|
></span>
|
||||||
<span class="nav-link-title"> {{ t('appname.home') }} </span>
|
<span class="nav-link-title">
|
||||||
|
{{ t("appname.home") }}
|
||||||
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="ms-auto">
|
<div class="ms-auto">
|
||||||
<select class="form-select" @change="changeLanguage" ref="lang_sele">
|
<select
|
||||||
|
class="form-select"
|
||||||
|
@change="changeLanguage"
|
||||||
|
ref="lang_sele"
|
||||||
|
>
|
||||||
<option value="en">English</option>
|
<option value="en">English</option>
|
||||||
<option value="zh-CN">中文</option>
|
<option value="zh-CN">中文</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -37,7 +37,10 @@
|
|||||||
"network_err":"Network error",
|
"network_err":"Network error",
|
||||||
"username_dup":"Duplicate username",
|
"username_dup":"Duplicate username",
|
||||||
"registration_successful":"Registration successful!",
|
"registration_successful":"Registration successful!",
|
||||||
"server_error":"Server Error"
|
"server_error":"Server Error",
|
||||||
|
"user_not_found":"User not found",
|
||||||
|
"username_or_password_incorrect":"Username or password incorrect.",
|
||||||
|
"login_successful":"Login successful"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
|
|||||||
@@ -37,7 +37,10 @@
|
|||||||
"network_err":"网络错误",
|
"network_err":"网络错误",
|
||||||
"username_dup":"用户名重复",
|
"username_dup":"用户名重复",
|
||||||
"registration_successful":"注册成功!",
|
"registration_successful":"注册成功!",
|
||||||
"server_error":"服务端错误"
|
"server_error":"服务端错误",
|
||||||
|
"user_not_found":"找不到用户",
|
||||||
|
"username_or_password_incorrect":"用户或密码错误",
|
||||||
|
"login_successful":"登录成功"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"submit": "提交",
|
"submit": "提交",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const my_network_func = {
|
|||||||
//把cookie插入json
|
//把cookie插入json
|
||||||
var data = {};
|
var data = {};
|
||||||
data["data"] = json;
|
data["data"] = json;
|
||||||
var cookie = myfuncs.load_json("cookie");
|
var cookie = myfuncs.loadJson("cookie");
|
||||||
if (cookie) {
|
if (cookie) {
|
||||||
data["cookie"] = cookie.Value;
|
data["cookie"] = cookie.Value;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ export const my_network_func = {
|
|||||||
if (response.data.cookie.Value == "") {
|
if (response.data.cookie.Value == "") {
|
||||||
myfuncs.dele("cookie");
|
myfuncs.dele("cookie");
|
||||||
} else {
|
} else {
|
||||||
myfuncs.save_json("cookie", response.data.cookie);
|
myfuncs.saveJson("cookie", response.data.cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,31 @@ export const myfuncs = {
|
|||||||
console.log("myfuncs test ok");
|
console.log("myfuncs test ok");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//临时保存的数据,浏览器专属
|
||||||
|
saveT(key,data){
|
||||||
|
sessionStorage.setItem(key, data)
|
||||||
|
},
|
||||||
|
loadT(key){
|
||||||
|
return sessionStorage.getItem(key)
|
||||||
|
},
|
||||||
|
deleT(key){
|
||||||
|
sessionStorage.removeItem(key)
|
||||||
|
},
|
||||||
|
saveJsonT(key,data){
|
||||||
|
this.saveT(key,JSON.stringify(data))
|
||||||
|
},
|
||||||
|
|
||||||
|
loadJsonT(key){
|
||||||
|
const js_data=this.loadT(key)
|
||||||
|
if(js_data){
|
||||||
|
return JSON.parse(js_data)
|
||||||
|
}else{
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
save(key,data){
|
save(key,data){
|
||||||
localStorage.setItem(key, data)
|
localStorage.setItem(key, data)
|
||||||
},
|
},
|
||||||
@@ -18,11 +43,11 @@ export const myfuncs = {
|
|||||||
localStorage.removeItem(key)
|
localStorage.removeItem(key)
|
||||||
},
|
},
|
||||||
|
|
||||||
save_json(key,data){
|
saveJson(key,data){
|
||||||
this.save(key,JSON.stringify(data))
|
this.save(key,JSON.stringify(data))
|
||||||
},
|
},
|
||||||
|
|
||||||
load_json(key){
|
loadJson(key){
|
||||||
const js_data=this.load(key)
|
const js_data=this.load(key)
|
||||||
if(js_data){
|
if(js_data){
|
||||||
return JSON.parse(js_data)
|
return JSON.parse(js_data)
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
const login = () => {
|
const login = () => {
|
||||||
isLoggedIn.value = true;
|
isLoggedIn.value = true;
|
||||||
};
|
};
|
||||||
|
const loginUpdata = () => {
|
||||||
|
isLoggedIn.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userInfo,
|
userInfo,
|
||||||
@@ -22,5 +25,6 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
isLoggedIn,
|
isLoggedIn,
|
||||||
logout,
|
logout,
|
||||||
login,
|
login,
|
||||||
|
loginUpdata,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, watch, ref } from "vue";
|
import { onMounted, watch, ref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useUserStore } from "@/stores/user";
|
||||||
|
|
||||||
|
import { my_network_func } from "@/my_network_func";
|
||||||
|
import { myfuncs } from "@/myfunc.js";
|
||||||
import MyOffcanvas from "@/components/MyOffcanvas.vue";
|
import MyOffcanvas from "@/components/MyOffcanvas.vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
// 使用 vue-i18n 的 Composition API
|
// 使用 vue-i18n 的 Composition API
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
|
const router = useRouter();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const mos = ref();
|
const mos = ref();
|
||||||
|
|
||||||
@@ -11,6 +18,7 @@ const username = ref();
|
|||||||
const password = ref();
|
const password = ref();
|
||||||
const isRemember = ref();
|
const isRemember = ref();
|
||||||
|
|
||||||
|
|
||||||
const isShowPassword = ref(false);
|
const isShowPassword = ref(false);
|
||||||
function togglePasswordVisibility() {
|
function togglePasswordVisibility() {
|
||||||
isShowPassword.value = !isShowPassword.value;
|
isShowPassword.value = !isShowPassword.value;
|
||||||
@@ -42,7 +50,69 @@ function login() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("登录信息:", { user, pass, remember });
|
//console.log("登录信息:", { user, pass, remember });
|
||||||
|
|
||||||
|
my_network_func.postJson(
|
||||||
|
"/users/login",
|
||||||
|
{
|
||||||
|
username: user,
|
||||||
|
userpass: pass,
|
||||||
|
remember: remember,
|
||||||
|
},
|
||||||
|
(r) => {
|
||||||
|
console.log(r)
|
||||||
|
switch (r.statusCode) {
|
||||||
|
case 200:
|
||||||
|
switch (r.data.err_code) {
|
||||||
|
case -41:
|
||||||
|
username.value?.classList.add("is-invalid");
|
||||||
|
mos.value?.showAlert(
|
||||||
|
"warning",
|
||||||
|
t("message.user_not_found"),
|
||||||
|
5000
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case -42:
|
||||||
|
username.value?.classList.add("is-invalid");
|
||||||
|
password.value?.classList.add("is-invalid");
|
||||||
|
mos.value?.showAlert(
|
||||||
|
"warning",
|
||||||
|
t("message.username_or_password_incorrect"),
|
||||||
|
5000
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
//登录成功,载入cookie
|
||||||
|
//临时保存cookie
|
||||||
|
myfuncs.saveJsonT("userCookie",r.data.return.cookie)
|
||||||
|
if(remember){
|
||||||
|
//长期保存cookie
|
||||||
|
myfuncs.saveJson("userCookie",r.data.return.cookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
//userStore.isLoggedIn=true
|
||||||
|
//更新用户信息
|
||||||
|
|
||||||
|
mos.value?.showAlert(
|
||||||
|
"success",
|
||||||
|
t("message.login_successful"),
|
||||||
|
1000,
|
||||||
|
() => {
|
||||||
|
router.back()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mos.value?.showAlert("danger", t("message.server_error"), 5000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mos.value?.showAlert("danger", t("message.network_err"), 5000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function functionupdataTitle() {
|
function functionupdataTitle() {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ function createAccount() {
|
|||||||
userpass: userpassword.value?.value,
|
userpass: userpassword.value?.value,
|
||||||
},
|
},
|
||||||
(r) => {
|
(r) => {
|
||||||
console.log(r);
|
//console.log(r);
|
||||||
switch (r.statusCode) {
|
switch (r.statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
switch (r.data.err_code) {
|
switch (r.data.err_code) {
|
||||||
|
|||||||
Reference in New Issue
Block a user