完成用户模块后端接口
This commit is contained in:
parent
068e8b9a0f
commit
a8a7fadcb1
|
@ -0,0 +1,34 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
*.exe
|
||||||
|
/storage
|
||||||
|
/deploy
|
||||||
|
/.idea
|
|
@ -0,0 +1,52 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bbs/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/contract"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuthMiddleware() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
envService := c.MustMake(contract.EnvKey).(contract.Env)
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
// 如果在调试模式下,根据参数的user_id 获取信息
|
||||||
|
if envService.AppEnv() == contract.EnvDevelopment {
|
||||||
|
userID, exist := c.DefaultQueryInt64("user_id", 0)
|
||||||
|
if exist {
|
||||||
|
authUser, _ := userService.GetUser(c, userID)
|
||||||
|
if authUser != nil {
|
||||||
|
c.Set("auth_user", authUser)
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := c.Cookie("hade_bbs")
|
||||||
|
if err != nil || token == "" {
|
||||||
|
c.ISetStatus(http.StatusUnauthorized).IText("请登录后操作")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
authUser, err := userService.VerifyLogin(c, token)
|
||||||
|
if err != nil || authUser == nil {
|
||||||
|
c.ISetStatus(http.StatusUnauthorized).IText("请登录后操作")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set("auth_user", authUser)
|
||||||
|
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAuthUser 获取已经验证的用户
|
||||||
|
func GetAuthUser(c *gin.Context) *user.User {
|
||||||
|
t, exist := c.Get("auth_user")
|
||||||
|
if !exist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return t.(*user.User)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package response
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ResponseHandler() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
c.Next()
|
||||||
|
fmt.Println("response handler")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bbs/app/http/middleware/auth"
|
||||||
|
"bbs/app/http/middleware/response"
|
||||||
|
"bbs/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserApi struct{}
|
||||||
|
|
||||||
|
// RegisterRoutes 注册路由
|
||||||
|
func RegisterRoutes(r *gin.Engine) error {
|
||||||
|
api := &UserApi{}
|
||||||
|
|
||||||
|
if !r.IsBind(user.UserKey) {
|
||||||
|
r.Bind(&user.UserProvider{})
|
||||||
|
}
|
||||||
|
|
||||||
|
userGroup := r.Group("/user")
|
||||||
|
userGroup.Use(response.ResponseHandler())
|
||||||
|
{
|
||||||
|
// 登录
|
||||||
|
userGroup.POST("/login", api.Login)
|
||||||
|
// 登出
|
||||||
|
userGroup.GET("/logout", auth.AuthMiddleware(), api.Logout)
|
||||||
|
// 注册
|
||||||
|
userGroup.POST("/register", api.Register)
|
||||||
|
// 注册验证
|
||||||
|
userGroup.GET("/register/verify", api.Verify)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bbs/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type loginParam struct {
|
||||||
|
UserName string `json:"username" binding:"required"`
|
||||||
|
Password string `json:"password" binding:"required,gte=6"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login 代表登录
|
||||||
|
// @Summary 用户登录
|
||||||
|
// @accept json
|
||||||
|
// @produce json
|
||||||
|
// @Tags user
|
||||||
|
// @Param loginParam body loginParam true "login with param"
|
||||||
|
// @Success 200 string Token "token"
|
||||||
|
// @Router /user/login [post]
|
||||||
|
func (api *UserApi) Login(c *gin.Context) {
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
param := &loginParam{}
|
||||||
|
if err := c.ShouldBind(param); err != nil {
|
||||||
|
c.ISetStatus(http.StatusBadRequest).IText("参数错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
model := &user.User{
|
||||||
|
UserName: param.UserName,
|
||||||
|
Password: param.Password,
|
||||||
|
}
|
||||||
|
|
||||||
|
userWithToken, err := userService.Login(c, model)
|
||||||
|
if err != nil {
|
||||||
|
c.ISetStatus(http.StatusInternalServerError).IText(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出
|
||||||
|
c.ISetOkStatus().IText(userWithToken.Token)
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bbs/app/http/middleware/auth"
|
||||||
|
"bbs/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logout 代表登出
|
||||||
|
// @Summary 用户登出
|
||||||
|
// @Description 调用表示用户登出
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Tags user
|
||||||
|
// @Success 200 {string} Message "用户登出成功"
|
||||||
|
// @Router /user/logout [get]
|
||||||
|
func (api *UserApi) Logout(c *gin.Context) {
|
||||||
|
authUser := auth.GetAuthUser(c)
|
||||||
|
if authUser == nil {
|
||||||
|
c.ISetStatus(500).IText("用户未登录")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
if err := userService.Logout(c, authUser); err != nil {
|
||||||
|
c.ISetStatus(500).IText(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//c.ISetOkStatus().IText("用户登出成功")
|
||||||
|
c.IRedirect("/#/login")
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bbs/app/provider/user"
|
||||||
|
"fmt"
|
||||||
|
"github.com/Superdanda/hade/framework/contract"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type registerParam struct {
|
||||||
|
UserName string `json:"username" binding:"required"`
|
||||||
|
Password string `json:"password" binding:"required,gte=6"`
|
||||||
|
Email string `json:"email" binding:"required,gte=6"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register 注册
|
||||||
|
// @Summary 用户注册
|
||||||
|
// @Description 用户注册接口
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Tags user
|
||||||
|
// @Param registerParam body registerParam true "注册参数"
|
||||||
|
// @Success 200 string Message "注册成功"
|
||||||
|
// @Router /user/register [post]
|
||||||
|
func (api *UserApi) Register(c *gin.Context) {
|
||||||
|
// 验证参数
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
logger := c.MustMake(contract.LogKey).(contract.Log)
|
||||||
|
|
||||||
|
param := ®isterParam{}
|
||||||
|
if err := c.ShouldBind(param); err != nil {
|
||||||
|
c.ISetStatus(400).IText("参数错误 ")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
model := &user.User{
|
||||||
|
UserName: param.UserName,
|
||||||
|
Password: param.Password,
|
||||||
|
Email: param.Email,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
// 注册
|
||||||
|
userWithToken, err := userService.Register(c, model)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(c, err.Error(), map[string]interface{}{
|
||||||
|
"stack": fmt.Sprintf("%+v", err),
|
||||||
|
})
|
||||||
|
c.ISetStatus(500).IText(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if userWithToken == nil {
|
||||||
|
c.ISetStatus(500).IText("注册失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := userService.SendRegisterMail(c, userWithToken); err != nil {
|
||||||
|
|
||||||
|
c.ISetStatus(500).IText("发送电子邮件失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ISetOkStatus().IText("注册成功,请前往邮箱查看邮件")
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bbs/app/provider/user"
|
||||||
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify 代表验证注册信息
|
||||||
|
// @Summary 验证注册信息
|
||||||
|
// @Description 使用token验证用户注册信息
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Tags user
|
||||||
|
// @Param token query string true "注册token"
|
||||||
|
// @Success 200 {string} Message "注册成功,请进入登录页面"
|
||||||
|
// @Router /user/register/verify [get]
|
||||||
|
func (api *UserApi) Verify(c *gin.Context) {
|
||||||
|
// 验证参数
|
||||||
|
userService := c.MustMake(user.UserKey).(user.Service)
|
||||||
|
token := c.Query("token")
|
||||||
|
if token == "" {
|
||||||
|
c.ISetStatus(400).IText("参数错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
verified, err := userService.VerifyRegister(c, token)
|
||||||
|
if err != nil {
|
||||||
|
c.ISetStatus(500).IText(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !verified {
|
||||||
|
c.ISetStatus(500).IText("验证错误")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出
|
||||||
|
c.IRedirect("/#/login").IText("注册成功,请进入登录页面")
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// UserDTO 表示输出到外部的用户信息
|
||||||
|
type UserDTO struct {
|
||||||
|
ID int64 `json:"id,omitempty"`
|
||||||
|
UserName string `json:"user_name,omitempty"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import "bbs/app/provider/user"
|
||||||
|
|
||||||
|
// ConvertUserToDTO 将user转换为UserDTO
|
||||||
|
func ConvertUserToDTO(user *user.User) *UserDTO {
|
||||||
|
if user == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &UserDTO{
|
||||||
|
ID: user.ID,
|
||||||
|
UserName: user.UserName,
|
||||||
|
CreatedAt: user.CreatedAt,
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bbs/app/http/module/demo"
|
"bbs/app/http/module/demo"
|
||||||
|
"bbs/app/http/module/user"
|
||||||
"github.com/Superdanda/hade/framework/contract"
|
"github.com/Superdanda/hade/framework/contract"
|
||||||
"github.com/Superdanda/hade/framework/gin"
|
"github.com/Superdanda/hade/framework/gin"
|
||||||
ginSwagger "github.com/Superdanda/hade/framework/middleware/gin-swagger"
|
ginSwagger "github.com/Superdanda/hade/framework/middleware/gin-swagger"
|
||||||
|
@ -22,6 +23,9 @@ func Routes(core *gin.Engine) {
|
||||||
core.Use(static.Serve("/", static.LocalFile("./dist", false)))
|
core.Use(static.Serve("/", static.LocalFile("./dist", false)))
|
||||||
|
|
||||||
err := demo.Register(core)
|
err := demo.Register(core)
|
||||||
|
|
||||||
|
err = user.RegisterRoutes(core)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,128 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/user/login": {
|
||||||
|
"post": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "用户登录",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "login with param",
|
||||||
|
"name": "loginParam",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/user.loginParam"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "token",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/logout": {
|
||||||
|
"get": {
|
||||||
|
"description": "调用表示用户登出",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "用户登出",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "用户登出成功",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/register": {
|
||||||
|
"post": {
|
||||||
|
"description": "用户注册接口",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "用户注册",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "注册参数",
|
||||||
|
"name": "registerParam",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/user.registerParam"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "注册成功",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/register/verify": {
|
||||||
|
"get": {
|
||||||
|
"description": "使用token验证用户注册信息",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "验证注册信息",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "注册token",
|
||||||
|
"name": "token",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "注册成功,请进入登录页面",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
@ -83,6 +205,43 @@ const docTemplate = `{
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"user.loginParam": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"password",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"password": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user.registerParam": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"email",
|
||||||
|
"password",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"email": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securityDefinitions": {
|
"securityDefinitions": {
|
||||||
|
|
|
@ -63,6 +63,128 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/user/login": {
|
||||||
|
"post": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "用户登录",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "login with param",
|
||||||
|
"name": "loginParam",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/user.loginParam"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "token",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/logout": {
|
||||||
|
"get": {
|
||||||
|
"description": "调用表示用户登出",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "用户登出",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "用户登出成功",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/register": {
|
||||||
|
"post": {
|
||||||
|
"description": "用户注册接口",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "用户注册",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "注册参数",
|
||||||
|
"name": "registerParam",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/user.registerParam"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "注册成功",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/user/register/verify": {
|
||||||
|
"get": {
|
||||||
|
"description": "使用token验证用户注册信息",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user"
|
||||||
|
],
|
||||||
|
"summary": "验证注册信息",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "注册token",
|
||||||
|
"name": "token",
|
||||||
|
"in": "query",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "注册成功,请进入登录页面",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
@ -76,6 +198,43 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"user.loginParam": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"password",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"password": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user.registerParam": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"email",
|
||||||
|
"password",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"email": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securityDefinitions": {
|
"securityDefinitions": {
|
||||||
|
|
|
@ -7,6 +7,32 @@ definitions:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
user.loginParam:
|
||||||
|
properties:
|
||||||
|
password:
|
||||||
|
minLength: 6
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- password
|
||||||
|
- username
|
||||||
|
type: object
|
||||||
|
user.registerParam:
|
||||||
|
properties:
|
||||||
|
email:
|
||||||
|
minLength: 6
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
minLength: 6
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- email
|
||||||
|
- password
|
||||||
|
- username
|
||||||
|
type: object
|
||||||
info:
|
info:
|
||||||
contact:
|
contact:
|
||||||
email: yejianfeng
|
email: yejianfeng
|
||||||
|
@ -50,6 +76,85 @@ paths:
|
||||||
summary: 获取所有学生
|
summary: 获取所有学生
|
||||||
tags:
|
tags:
|
||||||
- demo
|
- demo
|
||||||
|
/user/login:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
parameters:
|
||||||
|
- description: login with param
|
||||||
|
in: body
|
||||||
|
name: loginParam
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/user.loginParam'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: token
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
summary: 用户登录
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
/user/logout:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 调用表示用户登出
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: 用户登出成功
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
summary: 用户登出
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
/user/register:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 用户注册接口
|
||||||
|
parameters:
|
||||||
|
- description: 注册参数
|
||||||
|
in: body
|
||||||
|
name: registerParam
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/user.registerParam'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: 注册成功
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
summary: 用户注册
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
/user/register/verify:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: 使用token验证用户注册信息
|
||||||
|
parameters:
|
||||||
|
- description: 注册token
|
||||||
|
in: query
|
||||||
|
name: token
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: 注册成功,请进入登录页面
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
summary: 验证注册信息
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
securityDefinitions:
|
securityDefinitions:
|
||||||
ApiKeyAuth:
|
ApiKeyAuth:
|
||||||
in: header
|
in: header
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
const UserKey = "user"
|
|
||||||
|
|
||||||
type Service interface {
|
|
||||||
// 请在这里定义你的方法
|
|
||||||
Foo() string
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Superdanda/hade/framework"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UserProvider struct {
|
|
||||||
framework.ServiceProvider
|
|
||||||
|
|
||||||
c framework.Container
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sp *UserProvider) Name() string {
|
|
||||||
return UserKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sp *UserProvider) Register(c framework.Container) framework.NewInstance {
|
|
||||||
return NewUserService
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sp *UserProvider) IsDefer() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sp *UserProvider) Params(c framework.Container) []interface{} {
|
|
||||||
return []interface{}{c}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sp *UserProvider) Boot(c framework.Container) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import "github.com/Superdanda/hade/framework"
|
|
||||||
|
|
||||||
type UserService struct {
|
|
||||||
container framework.Container
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUserService(params ...interface{}) (interface{}, error) {
|
|
||||||
container := params[0].(framework.Container)
|
|
||||||
return &UserService{container: container}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *UserService) Foo() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
|
@ -15,4 +15,12 @@ dev: # 调试模式
|
||||||
port: 8890 # 后端监听端口,默认8072
|
port: 8890 # 后端监听端口,默认8072
|
||||||
monitor_folder: "" # 监听文件夹地址,为空或者不填默认为AppFolder
|
monitor_folder: "" # 监听文件夹地址,为空或者不填默认为AppFolder
|
||||||
frontend: # 前端调试模式配置
|
frontend: # 前端调试模式配置
|
||||||
port: 8889 # 前端监听端口, 默认8071
|
port: 8889 # 前端监听端口, 默认8071
|
||||||
|
|
||||||
|
|
||||||
|
smtp:
|
||||||
|
host: "smtp.126.com"
|
||||||
|
port: 25
|
||||||
|
from: "superdanda@126.com"
|
||||||
|
username: "superdanda"
|
||||||
|
password: "A10337191315."
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
conn_max_idle: 10 # 通用配置,连接池最大空闲连接数
|
conn_max_idle: 10 # 通用配置,连接池最大空闲连接数
|
||||||
conn_max_open: 100 # 通用配置,连接池最大连接数
|
conn_max_open: 100 # 通用配置,连接池最大连接数
|
||||||
conn_max_lifetime: 1h # 通用配置,连接数最大生命周期
|
conn_max_lifetime: 1h # 通用配置,连接数最大生命周期
|
||||||
protocol: tcp # 通用配置,传输协议
|
|
||||||
loc: Local # 通用配置,时区
|
|
||||||
|
|
||||||
default:
|
|
||||||
driver: mysql # 连接驱动
|
driver: mysql # 连接驱动
|
||||||
dsn: "" # dsn,如果设置了dsn, 以下的所有设置都不生效
|
dsn: "" # dsn,如果设置了dsn, 以下的所有设置都不生效
|
||||||
host: 47.97.21.20 # ip地址
|
host: 47.97.21.20 # ip地址
|
||||||
port: 3306 # 端口
|
port: 3306 # 端口
|
||||||
database: questionnaire # 数据库
|
database: questionnaire # 数据库
|
||||||
username: root # 用户名
|
username: root # 用户名
|
||||||
password: "kerowsqw34" # 密码
|
password: "kerowsqw34" # 密码
|
||||||
charset: utf8mb4 # 字符集
|
charset: utf8mb4 # 字符集
|
||||||
collation: utf8mb4_unicode_ci # 字符序
|
collation: utf8mb4_unicode_ci # 字符序
|
||||||
timeout: 10s # 连接超时
|
timeout: 10s # 连接超时
|
||||||
read_timeout: 2s # 读超时
|
read_timeout: 2s # 读超时
|
||||||
write_timeout: 2s # 写超时
|
write_timeout: 2s # 写超时
|
||||||
parse_time: true # 是否解析时间
|
parse_time: true # 是否解析时间
|
||||||
protocol: tcp # 传输协议
|
protocol: tcp # 传输协议
|
||||||
loc: Local # 时区
|
loc: Local # 时区
|
||||||
|
|
||||||
|
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -3,8 +3,9 @@ module bbs
|
||||||
go 1.23.2
|
go 1.23.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Superdanda/hade v1.0.2
|
github.com/Superdanda/hade v1.0.4
|
||||||
github.com/swaggo/swag v1.16.4
|
github.com/swaggo/swag v1.16.4
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -21,7 +22,7 @@ require (
|
||||||
github.com/robfig/cron/v3 v3.0.0 // indirect
|
github.com/robfig/cron/v3 v3.0.0 // indirect
|
||||||
github.com/sevlyar/go-daemon v0.1.6 // indirect
|
github.com/sevlyar/go-daemon v0.1.6 // indirect
|
||||||
github.com/spf13/cast v1.7.0 // indirect
|
github.com/spf13/cast v1.7.0 // indirect
|
||||||
gorm.io/gorm v1.25.12 // indirect
|
gorm.io/gorm v1.25.12
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -87,6 +88,7 @@ require (
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/term v0.25.0 // indirect
|
golang.org/x/term v0.25.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gorm.io/driver/clickhouse v0.6.1 // indirect
|
gorm.io/driver/clickhouse v0.6.1 // indirect
|
||||||
|
@ -126,7 +128,7 @@ require (
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.28.0 // indirect
|
golang.org/x/crypto v0.28.0
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.19.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -36,8 +36,8 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63n
|
||||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||||
github.com/Superdanda/hade v1.0.2 h1:AxlYNeUVO90j+LUHiZW6rg36DbGIXi6gUopURGVMzio=
|
github.com/Superdanda/hade v1.0.4 h1:NFsH8BBbsHmbedkGHdpjGk3e49GEJtRWU4ENOxp0sfU=
|
||||||
github.com/Superdanda/hade v1.0.2/go.mod h1:z52uXdtEfX25FRCj7YeQOctw6fho9nIaIWc/picNhuA=
|
github.com/Superdanda/hade v1.0.4/go.mod h1:z52uXdtEfX25FRCj7YeQOctw6fho9nIaIWc/picNhuA=
|
||||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
|
@ -443,11 +443,15 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -9,7 +9,12 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"element-ui": "^2.3.4",
|
"element-ui": "^2.3.4",
|
||||||
"vue": "^2.5.16"
|
"vue": "^2.5.16",
|
||||||
|
"vue-router": "^3.5.3",
|
||||||
|
"vue-style-loader": "^4.1.3",
|
||||||
|
"vuex": "^3.6.2",
|
||||||
|
"axios": "^0.24.0",
|
||||||
|
"js-cookie": "^3.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
|
|
16
src/App.vue
16
src/App.vue
|
@ -1,23 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<img src="./assets/logo.png">
|
<router-view></router-view>
|
||||||
<div>
|
|
||||||
<el-button @click="startHacking">Start</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startHacking () {
|
|
||||||
this.$notify({
|
|
||||||
title: 'It works! again',
|
|
||||||
type: 'success',
|
|
||||||
message: 'We\'ve laid the ground work for you. It\'s time for you to build something epic!',
|
|
||||||
duration: 5000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,10 +2,14 @@ import Vue from 'vue'
|
||||||
import ElementUI from 'element-ui'
|
import ElementUI from 'element-ui'
|
||||||
import 'element-ui/lib/theme-chalk/index.css'
|
import 'element-ui/lib/theme-chalk/index.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
import store from './store'
|
||||||
|
import router from './router/index.js'
|
||||||
|
|
||||||
Vue.use(ElementUI)
|
Vue.use(ElementUI)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
|
router: router,
|
||||||
|
store: store,
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "notfound",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
model: {
|
||||||
|
username: "",
|
||||||
|
password: ""
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="notfound">
|
||||||
|
<el-card>
|
||||||
|
<h2>页面找不到了</h2>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.notfound {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 240px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<script>
|
||||||
|
import BBSHeader from './header'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
'bbs-header': BBSHeader
|
||||||
|
},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-container>
|
||||||
|
<el-header>
|
||||||
|
<bbs-header></bbs-header>
|
||||||
|
</el-header>
|
||||||
|
<el-main>
|
||||||
|
<router-view></router-view>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,65 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-row type="flex" justify="center" align="middle">
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="hade_title"><a href="/" id="home-link" title="hadecast">hadecast</a></div>
|
||||||
|
</el-col>
|
||||||
|
<el-col class="" :span="8" :offset="8">
|
||||||
|
<div class="header_name">
|
||||||
|
<router-link class="to-link" :to="{path: '/create'}"><a title="hadecast">我要提问</a></router-link>
|
||||||
|
| jianfengye | <a href="/user/logout" title="hadecast">登出</a></div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.hade_title {
|
||||||
|
float: left;
|
||||||
|
vertical-align: top;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 0 15px 0 0;
|
||||||
|
line-height: 34px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_name {
|
||||||
|
float: right;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 0 15px 0 0;
|
||||||
|
line-height: 34px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #486e9b;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_name > a {
|
||||||
|
background-color: transparent;
|
||||||
|
color: #486e9b;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hade_title > a {
|
||||||
|
background-color: transparent;
|
||||||
|
color: #486e9b;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-header {
|
||||||
|
background-color: #409EFF;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 80px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,94 @@
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "login",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
model: {
|
||||||
|
username: "",
|
||||||
|
password: ""
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleLogin() {
|
||||||
|
this.$store.dispatch('user/login', this.model).then(() => {
|
||||||
|
this.$router.push({path: this.redirect || '/'})
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="login">
|
||||||
|
<el-card>
|
||||||
|
<h2>登录</h2>
|
||||||
|
<el-form
|
||||||
|
class="login-form"
|
||||||
|
>
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input v-model="model.username" placeholder="用户名"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input
|
||||||
|
placeholder="密码"
|
||||||
|
type="password"
|
||||||
|
v-model="model.password"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-row>
|
||||||
|
<el-col class="register">
|
||||||
|
还没有账号?请点击
|
||||||
|
<router-link class="to-link" :to="{path: '/register'}">
|
||||||
|
<el-link type="primary">注册</el-link>
|
||||||
|
</router-link>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
class="login-button"
|
||||||
|
type="primary"
|
||||||
|
native-type="submit"
|
||||||
|
@click="handleLogin"
|
||||||
|
block
|
||||||
|
>登录
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.to-link {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
width: 390px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forgot-password {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,100 @@
|
||||||
|
<script setup>
|
||||||
|
import request from '../../utils/request'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "register",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
email: '',
|
||||||
|
repassword: ''
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submitForm: function(e) {
|
||||||
|
if (this.form.repassword !== this.form.password) {
|
||||||
|
this.$message.error("两次输入密码不一致");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const that = this;
|
||||||
|
request({
|
||||||
|
url: '/user/register',
|
||||||
|
method: 'post',
|
||||||
|
data: this.form
|
||||||
|
}).then(function (response) {
|
||||||
|
debugger
|
||||||
|
const msg = response.data
|
||||||
|
that.$message.success(msg);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="register">
|
||||||
|
<el-card>
|
||||||
|
<h2>注册</h2>
|
||||||
|
<el-form v-model="form" class="register-form">
|
||||||
|
<el-form-item >
|
||||||
|
<el-input v-model="form.username" placeholder="用户名" ></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item >
|
||||||
|
<el-input v-model="form.email" placeholder="邮箱"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item >
|
||||||
|
<el-input
|
||||||
|
placeholder="密码"
|
||||||
|
type="password"
|
||||||
|
v-model="form.password"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item >
|
||||||
|
<el-input
|
||||||
|
placeholder="确认密码"
|
||||||
|
type="password"
|
||||||
|
v-model="form.repassword"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button
|
||||||
|
:loading="loading"
|
||||||
|
class="login-button"
|
||||||
|
type="primary"
|
||||||
|
native-type="submit"
|
||||||
|
@click="submitForm"
|
||||||
|
block
|
||||||
|
>注册</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.register {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
.register-form {
|
||||||
|
width: 390px;
|
||||||
|
}
|
||||||
|
.forgot-password {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.send_verify_code{
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -50,16 +50,16 @@ module.exports = (options = {}) => ({
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'~': resolve(__dirname, 'src')
|
'@': resolve(__dirname, 'src')
|
||||||
},
|
},
|
||||||
extensions: ['.js', '.vue', '.json', '.css']
|
extensions: ['.js', '.vue', '.json', '.css']
|
||||||
},
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
port: 8010,
|
port: 8890,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api/': {
|
'/api/': {
|
||||||
target: 'http://127.0.0.1:8080',
|
target: 'http://127.0.0.1:8890',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
'^/api': ''
|
'^/api': ''
|
||||||
|
|
54
yarn.lock
54
yarn.lock
|
@ -170,6 +170,13 @@ autoprefixer@^6.3.1, autoprefixer@^6.6.0:
|
||||||
postcss "^5.2.16"
|
postcss "^5.2.16"
|
||||||
postcss-value-parser "^3.2.3"
|
postcss-value-parser "^3.2.3"
|
||||||
|
|
||||||
|
axios@^0.24.0:
|
||||||
|
version "0.24.0"
|
||||||
|
resolved "https://registry.npmmirror.com/axios/-/axios-0.24.0.tgz"
|
||||||
|
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.14.4"
|
||||||
|
|
||||||
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0:
|
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0:
|
||||||
version "6.22.0"
|
version "6.22.0"
|
||||||
resolved "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.22.0.tgz"
|
resolved "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.22.0.tgz"
|
||||||
|
@ -1742,6 +1749,11 @@ flatten@^1.0.2:
|
||||||
resolved "http://registry.npm.taobao.org/flatten/download/flatten-1.0.2.tgz"
|
resolved "http://registry.npm.taobao.org/flatten/download/flatten-1.0.2.tgz"
|
||||||
integrity sha512-6u/bzbUK+6iOENlqGFkl94EqdAL/FVRhxMWbAE0OBmRsBl64BESxvVRD3CWdilAeka/3WlEZP+0MrKvtYpYFQQ==
|
integrity sha512-6u/bzbUK+6iOENlqGFkl94EqdAL/FVRhxMWbAE0OBmRsBl64BESxvVRD3CWdilAeka/3WlEZP+0MrKvtYpYFQQ==
|
||||||
|
|
||||||
|
follow-redirects@^1.14.4:
|
||||||
|
version "1.15.9"
|
||||||
|
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz"
|
||||||
|
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
|
||||||
|
|
||||||
for-in@^1.0.1:
|
for-in@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz"
|
resolved "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz"
|
||||||
|
@ -2207,6 +2219,11 @@ js-base64@^2.1.9:
|
||||||
resolved "http://registry.npm.taobao.org/js-base64/download/js-base64-2.1.9.tgz"
|
resolved "http://registry.npm.taobao.org/js-base64/download/js-base64-2.1.9.tgz"
|
||||||
integrity sha512-f+5mYh8iF7FlF7zgmj/yqvvYQUHI0kAxGiLjIfNxZzqJ7RQNc4sjgp8crVJw0Kzv2O6aFGZWgMTnO71I9utHSg==
|
integrity sha512-f+5mYh8iF7FlF7zgmj/yqvvYQUHI0kAxGiLjIfNxZzqJ7RQNc4sjgp8crVJw0Kzv2O6aFGZWgMTnO71I9utHSg==
|
||||||
|
|
||||||
|
js-cookie@^3.0.1:
|
||||||
|
version "3.0.5"
|
||||||
|
resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz"
|
||||||
|
integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==
|
||||||
|
|
||||||
js-tokens@^3.0.0:
|
js-tokens@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "http://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.1.tgz"
|
resolved "http://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.1.tgz"
|
||||||
|
@ -2310,16 +2327,7 @@ loader-utils@^0.2.16:
|
||||||
json5 "^0.5.0"
|
json5 "^0.5.0"
|
||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
|
|
||||||
loader-utils@^1.0.2:
|
loader-utils@^1.0.2, loader-utils@^1.1.0:
|
||||||
version "1.1.0"
|
|
||||||
resolved "http://registry.npm.taobao.org/loader-utils/download/loader-utils-1.1.0.tgz"
|
|
||||||
integrity sha512-gkD9aSEG9UGglyPcDJqY9YBTUtCLKaBK6ihD2VP1d1X60lTfFspNZNulGBBbUZLkPygy4LySYHyxBpq+VhjObQ==
|
|
||||||
dependencies:
|
|
||||||
big.js "^3.1.3"
|
|
||||||
emojis-list "^2.0.0"
|
|
||||||
json5 "^0.5.0"
|
|
||||||
|
|
||||||
loader-utils@^1.1.0:
|
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "http://registry.npm.taobao.org/loader-utils/download/loader-utils-1.1.0.tgz"
|
resolved "http://registry.npm.taobao.org/loader-utils/download/loader-utils-1.1.0.tgz"
|
||||||
integrity sha512-gkD9aSEG9UGglyPcDJqY9YBTUtCLKaBK6ihD2VP1d1X60lTfFspNZNulGBBbUZLkPygy4LySYHyxBpq+VhjObQ==
|
integrity sha512-gkD9aSEG9UGglyPcDJqY9YBTUtCLKaBK6ihD2VP1d1X60lTfFspNZNulGBBbUZLkPygy4LySYHyxBpq+VhjObQ==
|
||||||
|
@ -4000,10 +4008,23 @@ vue-loader@^13.3.0:
|
||||||
vue-style-loader "^3.0.0"
|
vue-style-loader "^3.0.0"
|
||||||
vue-template-es2015-compiler "^1.6.0"
|
vue-template-es2015-compiler "^1.6.0"
|
||||||
|
|
||||||
|
vue-router@^3.5.3:
|
||||||
|
version "3.6.5"
|
||||||
|
resolved "https://registry.npmmirror.com/vue-router/-/vue-router-3.6.5.tgz"
|
||||||
|
integrity sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==
|
||||||
|
|
||||||
vue-style-loader@^3.0.0:
|
vue-style-loader@^3.0.0:
|
||||||
version "3.0.1"
|
version "3.1.2"
|
||||||
resolved "https://registry.npmmirror.com/vue-style-loader/-/vue-style-loader-3.0.1.tgz"
|
resolved "https://registry.npmmirror.com/vue-style-loader/-/vue-style-loader-3.1.2.tgz"
|
||||||
integrity sha512-SjeCPpS6yWZwBOXsjayw8F2rqtFmjgmRsSMJQOTBZmaJVt1c+vLN6dBppeiIiQ4BGahYGiBvLfbCBoiKMoxJAQ==
|
integrity sha512-ICtVdK/p+qXWpdSs2alWtsXt9YnDoYjQe0w5616j9+/EhjoxZkbun34uWgsMFnC1MhrMMwaWiImz3K2jK1Yp2Q==
|
||||||
|
dependencies:
|
||||||
|
hash-sum "^1.0.2"
|
||||||
|
loader-utils "^1.0.2"
|
||||||
|
|
||||||
|
vue-style-loader@^4.1.3:
|
||||||
|
version "4.1.3"
|
||||||
|
resolved "https://registry.npmmirror.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz"
|
||||||
|
integrity sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==
|
||||||
dependencies:
|
dependencies:
|
||||||
hash-sum "^1.0.2"
|
hash-sum "^1.0.2"
|
||||||
loader-utils "^1.0.2"
|
loader-utils "^1.0.2"
|
||||||
|
@ -4021,11 +4042,16 @@ vue-template-es2015-compiler@^1.6.0:
|
||||||
resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz"
|
resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz"
|
||||||
integrity sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==
|
integrity sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==
|
||||||
|
|
||||||
vue@^2.5.16, vue@^2.5.2:
|
vue@^2.0.0, vue@^2.5.16, vue@^2.5.2:
|
||||||
version "2.5.16"
|
version "2.5.16"
|
||||||
resolved "https://registry.npmmirror.com/vue/-/vue-2.5.16.tgz"
|
resolved "https://registry.npmmirror.com/vue/-/vue-2.5.16.tgz"
|
||||||
integrity sha512-/ffmsiVuPC8PsWcFkZngdpas19ABm5mh2wA7iDqcltyCTwlgZjHGeJYOXkBMo422iPwIcviOtrTCUpSfXmToLQ==
|
integrity sha512-/ffmsiVuPC8PsWcFkZngdpas19ABm5mh2wA7iDqcltyCTwlgZjHGeJYOXkBMo422iPwIcviOtrTCUpSfXmToLQ==
|
||||||
|
|
||||||
|
vuex@^3.6.2:
|
||||||
|
version "3.6.2"
|
||||||
|
resolved "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz"
|
||||||
|
integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
|
||||||
|
|
||||||
watchpack@^1.3.1:
|
watchpack@^1.3.1:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "http://registry.npm.taobao.org/watchpack/download/watchpack-1.3.1.tgz"
|
resolved "http://registry.npm.taobao.org/watchpack/download/watchpack-1.3.1.tgz"
|
||||||
|
|
Loading…
Reference in New Issue