Merge branch 'github-main'

# Conflicts:
#	go.mod
#	internal/entity/answer_entity.go
#	internal/schema/question_schema.go
#	internal/service/user_service.go
This commit is contained in:
LinkinStar 2022-11-01 15:37:22 +08:00
commit 6e5d89d593
72 changed files with 1731 additions and 679 deletions

View File

@ -1,4 +1,8 @@
# Contributing to answer
## Coding and documentation Style
To be developed.
## Submitting Modifications
To be developed.

View File

@ -6,9 +6,9 @@ Before installing Answer, you need to install the base environment first.
You can then install Answer in several ways:
- Deploy with Docker
- binary installation
- Source installation
- [Deploy with Docker](#Docker-compose-for-Answer)
- [Binary installation](#Install-Answer-using-binary)
- [Source installation](#Compile-the-image)
## Docker-compose for Answer
```bash
@ -17,15 +17,15 @@ $ wget https://raw.githubusercontent.com/answerdev/answer/main/docker-compose.ya
$ docker-compose up
```
browser open URL [http://127.0.0.1:9080/](http://127.0.0.1:9080/).
In browser, open URL [http://127.0.0.1:9080/](http://127.0.0.1:9080/).
You can log in with the default administrator username( **`admin@admin.com`** ) and password( **`admin`** ).
You can log in with the default administrator username (**`admin@admin.com`**) and password (**`admin`**).
## Docker for Answer
Visit Docker Hub or GitHub Container registry to see all available images and tags.
Visit [Docker Hub](https://hub.docker.com/r/answerdev/answer) or GitHub Container registry to see all available images and tags.
### Usage
To keep your data out of Docker container, we do a volume (/var/data -> /data) here, and you can change it based on your situation.
To persist data beyond the life of a Docker container, use a volume (/var/data -> /data). You can modify this based on your situation.
```
# Pull image from Docker Hub.
@ -35,9 +35,9 @@ $ docker pull answerdev/answer:latest
$ mkdir -p /var/data
# Run the image first
$ docker run --name=answer -p 9080:80 -v /var/data:/data answer/answer
$ docker run --name=answer -p 9080:80 -v /var/data:/data answerdev/answer
# After the first startup, a configuration file will be generated in the /var/data directory
# After successful first startup, a configuration file will be generated in the /var/data directory
# /var/data/conf/config.yaml
# Need to modify the Mysql database address in the configuration file
vim /var/data/conf/config.yaml
@ -46,34 +46,32 @@ vim /var/data/conf/config.yaml
# connection: [username]:[password]@tcp([host]:[port])/[DbName]
...
# After configuring the configuration file, you can start the mirror again to start the service
# After configuring the configuration file, you can start the container again to start the service
$ docker start answer
```
## Binary for Answer
## Install Answer using binary
1. Unzip the compressed package
2. Use the command cd to enter the directory you just created
3. Execute the command ./answer init
4. Answer will generate a ./data directory in the current directory
5. Enter the data directory and modify the config.yaml file
6. Modify the database connection address to your database connection address
connection: [username]:[password]@tcp([host]:[port])/[DbName]
7. Exit the data directory and execute ./answer run -c ./data/conf/config.yaml
2. Use the command `cd` to enter the directory you just created
3. Execute the command `./answer init`
4. Answer will generate a `./data` directory in the current directory
5. Enter the `data` directory and modify the `config.yaml` file
6. Modify the database connection identify your database connection information
`connection: [username]:[password]@tcp([host]:[port])/[DbName]`
7. Use `cd ..` to return the directory from step 2, and execute `./answer run -c ./data/conf/config.yaml`
## Available Commands
Usage: answer [command]
Usage: `answer [command]`
- help: Help about any command
- init: Init answer application
- run: Run answer application
- check: Check answer required environment
- dump: Backup answer data
- `help`: Help about any command
- `init`: Init answer application
- `run`: Run answer application
- `check`: Check answer required environment
- `dump`: Backup answer data
## config.yaml Description
Here is a sample/default config.yaml file, as would be created from `answer init`.
```
server:
http:
@ -97,9 +95,9 @@ service_config:
```
## Compile the image
If you have modified the source files and want to repackage the image, you can use the following statement to repackage the image
If you have modified the source files and want to repackage the image, you can use the following to repackage the image
```
docker build -t answer:v1.0.0 .
```
## common problem
1. The project cannot be started, answer the main program startup depends on the configuration file config.yaml, the internationalization translation directory/i18n, the upload file storage directory/upfiles, you need to ensure that the configuration file is loaded when the project starts, answer run -c config.yaml and the correct config.yaml The configuration items that specify the i18n and upfiles directories
1. The project cannot be started: the main program startup depends on proper configuraiton of the configuration file, `config.yaml`, as well as the internationalization translation directory (`i18n`), and the upload file storage directory (`upfiles`). Ensure that the configuration file is loaded when the project starts, such as when using `answer run -c config.yaml` and that the `config.yaml` correctly specifies the i18n and upfiles directories.

View File

@ -35,7 +35,7 @@ $ docker pull answerdev/answer:latest
$ mkdir -p /var/data
# 先运行一遍镜像
$ docker run --name=answer -p 9080:80 -v /var/data:/data answer/answer
$ docker run --name=answer -p 9080:80 -v /var/data:/data answerdev/answer
# 第一次启动后会在/var/data 目录下生成配置文件
# /var/data/conf/config.yaml

View File

@ -4,13 +4,14 @@
# Answer - Build Q&A community
An open-source knowledge based community software. You can use it to quickly build your Q&A community for product technical support, customer support, user communication, and more.
An open-source knowledge-based community software. You can use it to quickly build your Q&A community for product technical support, customer support, user communication, and more.
To learn more about the project, visit [answer.dev](https://answer.dev).
[![LICENSE](https://img.shields.io/badge/License-Apache-green)](https://github.com/answerdev/answer/blob/main/LICENSE)
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)
[![Language](https://img.shields.io/badge/Language-React-blue.svg)](https://reactjs.org/)
[![Go Report Card](https://goreportcard.com/badge/github.com/answerdev/answer)](https://goreportcard.com/report/github.com/answerdev/answer)
## Screenshots
@ -24,7 +25,7 @@ To learn more about the project, visit [answer.dev](https://answer.dev).
docker run -d -p 9080:80 -v $PWD/answer-data/data:/data --name answer answerdev/answer:latest
```
For more information you can see [INSTALL.md](./INSTALL.md)
For more information, see [INSTALL.md](./INSTALL.md)
## Contributing
@ -34,4 +35,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for ways to get started.
## License
[Apache](https://github.com/answerdev/answer/blob/main/LICENSE)
[Apache License 2.0](https://github.com/answerdev/answer/blob/main/LICENSE)

View File

@ -11,6 +11,7 @@
[![LICENSE](https://img.shields.io/badge/License-Apache-green)](https://github.com/answerdev/answer/blob/main/LICENSE)
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)
[![Language](https://img.shields.io/badge/Language-React-blue.svg)](https://reactjs.org/)
[![Go Report Card](https://goreportcard.com/badge/github.com/answerdev/answer)](https://goreportcard.com/report/github.com/answerdev/answer)
## 截图
@ -34,4 +35,4 @@ docker run -d -p 9080:80 -v $PWD/answer-data/data:/data --name answer answerdev/
## License
[Apache](https://github.com/answerdev/answer/blob/main/LICENSE)
[Apache License 2.0](https://github.com/answerdev/answer/blob/main/LICENSE)

View File

@ -48,7 +48,7 @@ To run answer, use:
Use: "run",
Short: "Run the application",
Long: `Run the application`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, _ []string) {
runApp()
},
}
@ -58,7 +58,7 @@ To run answer, use:
Use: "init",
Short: "init answer application",
Long: `init answer application`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, _ []string) {
cli.InstallAllInitialEnvironment(dataDirPath)
c, err := readConfig()
if err != nil {
@ -79,7 +79,7 @@ To run answer, use:
Use: "upgrade",
Short: "upgrade Answer version",
Long: `upgrade Answer version`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, _ []string) {
c, err := readConfig()
if err != nil {
fmt.Println("read config failed: ", err.Error())
@ -98,7 +98,7 @@ To run answer, use:
Use: "dump",
Short: "back up data",
Long: `back up data`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, _ []string) {
fmt.Println("Answer is backing up data")
c, err := readConfig()
if err != nil {
@ -119,7 +119,7 @@ To run answer, use:
Use: "check",
Short: "checking the required environment",
Long: `Check if the current environment meets the startup requirements`,
Run: func(cmd *cobra.Command, args []string) {
Run: func(_ *cobra.Command, _ []string) {
fmt.Println("Start checking the required environment...")
if cli.CheckConfigFile(configFilePath) {
fmt.Println("config file exists [✔]")

View File

@ -67,7 +67,7 @@ import (
// Injectors from wire.go:
// initApplication init application.
func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, cacheConf *data.CacheConf, i18nConf *translator.I18n, swaggerConf *router.SwaggerConfig, serviceConf *service_config.ServiceConfig, logConf log.Logger) (*pacman.Application, func(), error) {
func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, cacheConf *data.CacheConf, i18nConf *translator.I18n, swaggerConf *router.SwaggerConfig, serviceConf *service_config.ServiceConfig, _ log.Logger) (*pacman.Application, func(), error) {
staticRouter := router.NewStaticRouter(serviceConf)
i18nTranslator, err := translator.NewTranslator(i18nConf)
if err != nil {

170
i18n/it_IT.yaml Normal file
View File

@ -0,0 +1,170 @@
base:
success:
other: "Successo"
unknown:
other: "Errore sconosciuto"
request_format_error:
other: "Il formato della richiesta non è valido"
unauthorized_error:
other: "Non autorizzato"
database_error:
other: "Errore server dati"
email:
other: "email"
password:
other: "password"
email_or_password_wrong_error: &email_or_password_wrong
other: "Email o password errati"
error:
admin:
email_or_password_wrong: *email_or_password_wrong
answer:
not_found:
other: "Risposta non trovata"
comment:
edit_without_permission:
other: "Non si hanno di privilegi sufficienti per modificare il commento"
not_found:
other: "Commento non trovato"
email:
duplicate:
other: "email già esistente"
need_to_be_verified:
other: "email deve essere verificata"
verify_url_expired:
other: "l'url di verifica email è scaduto, si prega di reinviare la email"
lang:
not_found:
other: "lingua non trovata"
object:
captcha_verification_failed:
other: "captcha errato"
disallow_follow:
other: "Non sei autorizzato a seguire"
disallow_vote:
other: "non sei autorizzato a votare"
disallow_vote_your_self:
other: "Non puoi votare un tuo post!"
not_found:
other: "oggetto non trovato"
verification_failed:
other: "verifica fallita"
email_or_password_incorrect:
other: "email o password incorretti"
old_password_verification_failed:
other: "la verifica della vecchia password è fallita"
new_password_same_as_previous_setting:
other: "La nuova password è identica alla precedente"
question:
not_found:
other: "domanda non trovata"
rank:
fail_to_meet_the_condition:
other: "Condizioni non valide per il grado"
report:
handle_failed:
other: "Gestione del report fallita"
not_found:
other: "Report non trovato"
tag:
not_found:
other: "Etichetta non trovata"
theme:
not_found:
other: "tema non trovato"
user:
email_or_password_wrong:
other: *email_or_password_wrong
not_found:
other: "utente non trovato"
suspended:
other: "utente sospeso"
username_invalid:
other: "utente non valido"
username_duplicate:
other: "utente già in uso"
report:
spam:
name:
other: "spam"
description:
other: "Questo articolo è una pubblicità o vandalismo. Non è utile o rilevante all'argomento corrente"
rude:
name:
other: "scortese o violento"
description:
other: "Una persona ragionevole trova questo contenuto inappropriato a un discorso rispettoso"
duplicate:
name:
other: "duplicato"
description:
other: "Questa domanda è già stata posta e ha già una risposta."
not_answer:
name:
other: "non è una risposta"
description:
other: "Questo è stato postato come una risposta, ma non sta cercando di rispondere alla domanda. Dovrebbe essere una modifica, un commento, un'altra domanda o cancellato del tutto."
not_need:
name:
other: "non più necessario"
description:
other: "Questo commento è datato, conversazionale o non rilevante a questo articolo."
other:
name:
other: "altro"
description:
other: "Questo articolo richiede una supervisione dello staff per altre ragioni non listate sopra."
question:
close:
duplicate:
name:
other: "spam"
description:
other: "Questa domanda è già stata chiesta o ha già una risposta."
guideline:
name:
other: "motivo legato alla community"
description:
other: "Questa domanda non soddisfa le linee guida della comunità."
multiple:
name:
other: "richiede maggiori dettagli o chiarezza"
description:
other: "Questa domanda attualmente contiene più domande. Deve concentrarsi solamente su un unico problema."
other:
name:
other: "altro"
description:
other: "Questo articolo richiede un'altro motivo non listato sopra."
notification:
action:
update_question:
other: "domanda aggiornata"
answer_the_question:
other: "domanda risposta"
update_answer:
other: "risposta aggiornata"
adopt_answer:
other: "risposta accettata"
comment_question:
other: "domanda commentata"
comment_answer:
other: "risposta commentata"
reply_to_you:
other: "hai ricevuto risposta"
mention_you:
other: "sei stato menzionato"
your_question_is_closed:
other: "la tua domanda è stata chiusa"
your_question_was_deleted:
other: "la tua domanda è stata rimossa"
your_answer_was_deleted:
other: "la tua risposta è stata rimossa"
your_comment_was_deleted:
other: "il tuo commento è stato rimosso"

View File

@ -3,7 +3,7 @@ package constant
import "time"
const (
Default_PageSize = 20 //Default number of pages
DefaultPageSize = 20 // Default number of pages
UserStatusChangedCacheKey = "answer:user:status:"
UserStatusChangedCacheTime = 7 * 24 * time.Hour
UserTokenCacheKey = "answer:user:token:"

View File

@ -13,7 +13,7 @@ const (
ReportNotAnswerDescription = "report.not_answer.description"
ReportNotNeedName = "report.not_need.name"
ReportNotNeedDescription = "report.not_need.description"
//question close
// question close
QuestionCloseDuplicateName = "question.close.duplicate.name"
QuestionCloseDuplicateDescription = "question.close.duplicate.description"
QuestionCloseGuidelineName = "question.close.guideline.name"
@ -27,8 +27,8 @@ const (
const (
// TODO put this in database
// TODO need reason controller to resolve
QuestionCloseJson = `[{"name":"question.close.duplicate.name","description":"question.close.duplicate.description","source":"question","type":1,"have_content":false,"content_type":""},{"name":"question.close.guideline.name","description":"question.close.guideline.description","source":"question","type":2,"have_content":false,"content_type":""},{"name":"question.close.multiple.name","description":"question.close.multiple.description","source":"question","type":3,"have_content":true,"content_type":"text"},{"name":"question.close.other.name","description":"question.close.other.description","source":"question","type":4,"have_content":true,"content_type":"textarea"}]`
QuestionReportJson = `[{"name":"report.spam.name","description":"report.spam.description","source":"question","type":1,"have_content":false,"content_type":""},{"name":"report.rude.name","description":"report.rude.description","source":"question","type":2,"have_content":false,"content_type":""},{"name":"report.duplicate.name","description":"report.duplicate.description","source":"question","type":3,"have_content":true,"content_type":"text"},{"name":"report.other.name","description":"report.other.description","source":"question","type":4,"have_content":true,"content_type":"textarea"}]`
AnswerReportJson = `[{"name":"report.spam.name","description":"report.spam.description","source":"answer","type":1,"have_content":false,"content_type":""},{"name":"report.rude.name","description":"report.rude.description","source":"answer","type":2,"have_content":false,"content_type":""},{"name":"report.not_answer.name","description":"report.not_answer.description","source":"answer","type":3,"have_content":false,"content_type":""},{"name":"report.other.name","description":"report.other.description","source":"answer","type":4,"have_content":true,"content_type":"textarea"}]`
CommentReportJson = `[{"name":"report.spam.name","description":"report.spam.description","source":"comment","type":1,"have_content":false,"content_type":""},{"name":"report.rude.name","description":"report.rude.description","source":"comment","type":2,"have_content":false,"content_type":""},{"name":"report.not_need.name","description":"report.not_need.description","source":"comment","type":3,"have_content":true,"content_type":"text"},{"name":"report.other.name","description":"report.other.description","source":"comment","type":4,"have_content":true,"content_type":"textarea"}]`
QuestionCloseJSON = `[{"name":"question.close.duplicate.name","description":"question.close.duplicate.description","source":"question","type":1,"have_content":false,"content_type":""},{"name":"question.close.guideline.name","description":"question.close.guideline.description","source":"question","type":2,"have_content":false,"content_type":""},{"name":"question.close.multiple.name","description":"question.close.multiple.description","source":"question","type":3,"have_content":true,"content_type":"text"},{"name":"question.close.other.name","description":"question.close.other.description","source":"question","type":4,"have_content":true,"content_type":"textarea"}]`
QuestionReportJSON = `[{"name":"report.spam.name","description":"report.spam.description","source":"question","type":1,"have_content":false,"content_type":""},{"name":"report.rude.name","description":"report.rude.description","source":"question","type":2,"have_content":false,"content_type":""},{"name":"report.duplicate.name","description":"report.duplicate.description","source":"question","type":3,"have_content":true,"content_type":"text"},{"name":"report.other.name","description":"report.other.description","source":"question","type":4,"have_content":true,"content_type":"textarea"}]`
AnswerReportJSON = `[{"name":"report.spam.name","description":"report.spam.description","source":"answer","type":1,"have_content":false,"content_type":""},{"name":"report.rude.name","description":"report.rude.description","source":"answer","type":2,"have_content":false,"content_type":""},{"name":"report.not_answer.name","description":"report.not_answer.description","source":"answer","type":3,"have_content":false,"content_type":""},{"name":"report.other.name","description":"report.other.description","source":"answer","type":4,"have_content":true,"content_type":"textarea"}]`
CommentReportJSON = `[{"name":"report.spam.name","description":"report.spam.description","source":"comment","type":1,"have_content":false,"content_type":""},{"name":"report.rude.name","description":"report.rude.description","source":"comment","type":2,"have_content":false,"content_type":""},{"name":"report.not_need.name","description":"report.not_need.description","source":"comment","type":3,"have_content":true,"content_type":"text"},{"name":"report.other.name","description":"report.other.description","source":"comment","type":4,"have_content":true,"content_type":"textarea"}]`
)

View File

@ -7,7 +7,6 @@ import (
"github.com/answerdev/answer/pkg/dir"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
"github.com/segmentfault/pacman/cache"
"github.com/segmentfault/pacman/contrib/cache/memory"
"github.com/segmentfault/pacman/log"

View File

@ -40,7 +40,6 @@ func HandleResponse(ctx *gin.Context, err error, data interface{}) {
respBody.Data = data
}
ctx.JSON(myErr.Code, respBody)
return
}
// BindAndCheck bind request and check

View File

@ -14,9 +14,7 @@ import (
"github.com/segmentfault/pacman/errors"
)
var (
ctxUuidKey = "ctxUuidKey"
)
var ctxUUIDKey = "ctxUuidKey"
// AuthUserMiddleware auth user middleware
type AuthUserMiddleware struct {
@ -44,7 +42,7 @@ func (am *AuthUserMiddleware) Auth() gin.HandlerFunc {
return
}
if userInfo != nil {
ctx.Set(ctxUuidKey, userInfo)
ctx.Set(ctxUUIDKey, userInfo)
}
ctx.Next()
}
@ -82,7 +80,7 @@ func (am *AuthUserMiddleware) MustAuth() gin.HandlerFunc {
ctx.Abort()
return
}
ctx.Set(ctxUuidKey, userInfo)
ctx.Set(ctxUUIDKey, userInfo)
ctx.Next()
}
}
@ -107,7 +105,7 @@ func (am *AuthUserMiddleware) CmsAuth() gin.HandlerFunc {
ctx.Abort()
return
}
ctx.Set(ctxUuidKey, userInfo)
ctx.Set(ctxUUIDKey, userInfo)
}
ctx.Next()
}
@ -115,7 +113,7 @@ func (am *AuthUserMiddleware) CmsAuth() gin.HandlerFunc {
// GetLoginUserIDFromContext get user id from context
func GetLoginUserIDFromContext(ctx *gin.Context) (userID string) {
userInfo, exist := ctx.Get(ctxUuidKey)
userInfo, exist := ctx.Get(ctxUUIDKey)
if !exist {
return ""
}
@ -128,7 +126,7 @@ func GetLoginUserIDFromContext(ctx *gin.Context) (userID string) {
// GetUserInfoFromContext get user info from context
func GetUserInfoFromContext(ctx *gin.Context) (u *entity.UserCacheInfo) {
userInfo, exist := ctx.Get(ctxUuidKey)
userInfo, exist := ctx.Get(ctxUUIDKey)
if !exist {
return nil
}

View File

@ -28,7 +28,7 @@ const (
UsernameDuplicate = "error.user.username_duplicate"
UserSetAvatar = "error.user.set_avatar"
EmailDuplicate = "error.email.duplicate"
EmailVerifyUrlExpired = "error.email.verify_url_expired"
EmailVerifyURLExpired = "error.email.verify_url_expired"
EmailNeedToBeVerified = "error.email.need_to_be_verified"
UserSuspended = "error.user.suspended"
ObjectNotFound = "error.object.not_found"

View File

@ -9,7 +9,7 @@ import (
"github.com/go-playground/locales"
english "github.com/go-playground/locales/en"
zhongwen "github.com/go-playground/locales/zh"
"github.com/go-playground/universal-translator"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
"github.com/go-playground/validator/v10/translations/en"
"github.com/go-playground/validator/v10/translations/zh"
@ -31,10 +31,8 @@ type ErrorField struct {
Value string `json:"value"`
}
var (
// GlobalValidatorMapping is a mapping from validator to translator used
GlobalValidatorMapping = make(map[string]*MyValidator, 0)
)
// GlobalValidatorMapping is a mapping from validator to translator used
var GlobalValidatorMapping = make(map[string]*MyValidator, 0)
func init() {
zhTran, zhVal := getTran(zhongwen.New(), i18n.LanguageChinese.Abbr()), createDefaultValidator(i18n.LanguageChinese)

View File

@ -31,7 +31,6 @@ func InstallAllInitialEnvironment(dataDirPath string) {
installUploadDir()
installI18nBundle()
fmt.Println("install all initial environment done")
return
}
func installConfigFile() {
@ -96,7 +95,7 @@ func installI18nBundle() {
}
func writerFile(filePath, content string) error {
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0o666)
if err != nil {
return err
}

View File

@ -62,9 +62,9 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) {
// @Success 200 {string} string ""
func (ac *AnswerController) Get(ctx *gin.Context) {
id := ctx.Query("id")
userId := middleware.GetLoginUserIDFromContext(ctx)
userID := middleware.GetLoginUserIDFromContext(ctx)
info, questionInfo, has, err := ac.answerService.Get(ctx, id, userId)
info, questionInfo, has, err := ac.answerService.Get(ctx, id, userID)
if err != nil {
handler.HandleResponse(ctx, err, gin.H{})
return
@ -101,18 +101,18 @@ func (ac *AnswerController) Add(ctx *gin.Context) {
return
}
answerId, err := ac.answerService.Insert(ctx, req)
answerID, err := ac.answerService.Insert(ctx, req)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
info, questionInfo, has, err := ac.answerService.Get(ctx, answerId, req.UserID)
info, questionInfo, has, err := ac.answerService.Get(ctx, answerID, req.UserID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !has {
//todo !has
// todo !has
handler.HandleResponse(ctx, nil, nil)
return
}
@ -120,7 +120,6 @@ func (ac *AnswerController) Add(ctx *gin.Context) {
"info": info,
"question": questionInfo,
})
}
// Update godoc
@ -156,7 +155,7 @@ func (ac *AnswerController) Update(ctx *gin.Context) {
return
}
if !has {
//todo !has
// todo !has
handler.HandleResponse(ctx, nil, nil)
return
}

View File

@ -66,7 +66,7 @@ func (qc *QuestionController) CloseQuestion(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
req.UserId = middleware.GetLoginUserIDFromContext(ctx)
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
err := qc.questionService.CloseQuestion(ctx, req)
handler.HandleResponse(ctx, err, nil)
}
@ -114,7 +114,6 @@ func (qc *QuestionController) SimilarQuestion(ctx *gin.Context) {
"list": list,
"count": count,
})
}
// Index godoc

View File

@ -35,7 +35,8 @@ func NewUserController(
userService *service.UserService,
actionService *action.CaptchaService,
emailService *export.EmailService,
uploaderService *uploader.UploaderService) *UserController {
uploaderService *uploader.UploaderService,
) *UserController {
return &UserController{
authService: authService,
userService: userService,
@ -119,7 +120,7 @@ func (uc *UserController) UserEmailLogin(ctx *gin.Context) {
return
}
captchaPass := uc.actionService.ActionRecordVerifyCaptcha(ctx, schema.ActionRecord_Type_Login, ctx.ClientIP(), req.CaptchaID, req.CaptchaCode)
captchaPass := uc.actionService.ActionRecordVerifyCaptcha(ctx, schema.ActionRecordTypeLogin, ctx.ClientIP(), req.CaptchaID, req.CaptchaCode)
if !captchaPass {
resp := schema.UserVerifyEmailErrorResponse{
Key: "captcha_code",
@ -132,7 +133,7 @@ func (uc *UserController) UserEmailLogin(ctx *gin.Context) {
resp, err := uc.userService.EmailLogin(ctx, req)
if err != nil {
_, _ = uc.actionService.ActionRecordAdd(ctx, schema.ActionRecord_Type_Login, ctx.ClientIP())
_, _ = uc.actionService.ActionRecordAdd(ctx, schema.ActionRecordTypeLogin, ctx.ClientIP())
resp := schema.UserVerifyEmailErrorResponse{
Key: "e_mail",
Value: "error.object.email_or_password_incorrect",
@ -141,7 +142,7 @@ func (uc *UserController) UserEmailLogin(ctx *gin.Context) {
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), resp)
return
}
uc.actionService.ActionRecordDel(ctx, schema.ActionRecord_Type_Login, ctx.ClientIP())
uc.actionService.ActionRecordDel(ctx, schema.ActionRecordTypeLogin, ctx.ClientIP())
handler.HandleResponse(ctx, nil, resp)
}
@ -159,7 +160,7 @@ func (uc *UserController) RetrievePassWord(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
captchaPass := uc.actionService.ActionRecordVerifyCaptcha(ctx, schema.ActionRecord_Type_Find_Pass, ctx.ClientIP(), req.CaptchaID, req.CaptchaCode)
captchaPass := uc.actionService.ActionRecordVerifyCaptcha(ctx, schema.ActionRecordTypeFindPass, ctx.ClientIP(), req.CaptchaID, req.CaptchaCode)
if !captchaPass {
resp := schema.UserVerifyEmailErrorResponse{
Key: "captcha_code",
@ -169,7 +170,7 @@ func (uc *UserController) RetrievePassWord(ctx *gin.Context) {
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), resp)
return
}
_, _ = uc.actionService.ActionRecordAdd(ctx, schema.ActionRecord_Type_Find_Pass, ctx.ClientIP())
_, _ = uc.actionService.ActionRecordAdd(ctx, schema.ActionRecordTypeFindPass, ctx.ClientIP())
code, err := uc.userService.RetrievePassWord(ctx, req)
handler.HandleResponse(ctx, err, code)
}
@ -191,13 +192,13 @@ func (uc *UserController) UseRePassWord(ctx *gin.Context) {
req.Content = uc.emailService.VerifyUrlExpired(ctx, req.Code)
if len(req.Content) == 0 {
handler.HandleResponse(ctx, errors.Forbidden(reason.EmailVerifyUrlExpired),
&schema.ForbiddenResp{Type: schema.ForbiddenReasonTypeUrlExpired})
handler.HandleResponse(ctx, errors.Forbidden(reason.EmailVerifyURLExpired),
&schema.ForbiddenResp{Type: schema.ForbiddenReasonTypeURLExpired})
return
}
resp, err := uc.userService.UseRePassWord(ctx, req)
uc.actionService.ActionRecordDel(ctx, schema.ActionRecord_Type_Find_Pass, ctx.ClientIP())
uc.actionService.ActionRecordDel(ctx, schema.ActionRecordTypeFindPass, ctx.ClientIP())
handler.HandleResponse(ctx, err, resp)
}
@ -252,8 +253,8 @@ func (uc *UserController) UserVerifyEmail(ctx *gin.Context) {
req.Content = uc.emailService.VerifyUrlExpired(ctx, req.Code)
if len(req.Content) == 0 {
handler.HandleResponse(ctx, errors.Forbidden(reason.EmailVerifyUrlExpired),
&schema.ForbiddenResp{Type: schema.ForbiddenReasonTypeUrlExpired})
handler.HandleResponse(ctx, errors.Forbidden(reason.EmailVerifyURLExpired),
&schema.ForbiddenResp{Type: schema.ForbiddenReasonTypeURLExpired})
return
}
@ -263,7 +264,7 @@ func (uc *UserController) UserVerifyEmail(ctx *gin.Context) {
return
}
uc.actionService.ActionRecordDel(ctx, schema.ActionRecord_Type_Email, ctx.ClientIP())
uc.actionService.ActionRecordDel(ctx, schema.ActionRecordTypeEmail, ctx.ClientIP())
handler.HandleResponse(ctx, err, resp)
}
@ -289,7 +290,7 @@ func (uc *UserController) UserVerifyEmailSend(ctx *gin.Context) {
return
}
captchaPass := uc.actionService.ActionRecordVerifyCaptcha(ctx, schema.ActionRecord_Type_Email, ctx.ClientIP(),
captchaPass := uc.actionService.ActionRecordVerifyCaptcha(ctx, schema.ActionRecordTypeEmail, ctx.ClientIP(),
req.CaptchaID, req.CaptchaCode)
if !captchaPass {
resp := schema.UserVerifyEmailErrorResponse{
@ -301,7 +302,7 @@ func (uc *UserController) UserVerifyEmailSend(ctx *gin.Context) {
return
}
uc.actionService.ActionRecordAdd(ctx, schema.ActionRecord_Type_Email, ctx.ClientIP())
uc.actionService.ActionRecordAdd(ctx, schema.ActionRecordTypeEmail, ctx.ClientIP())
err := uc.userService.UserVerifyEmailSend(ctx, userInfo.UserID)
handler.HandleResponse(ctx, err, nil)
}
@ -321,7 +322,7 @@ func (uc *UserController) UserModifyPassWord(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
req.UserId = middleware.GetLoginUserIDFromContext(ctx)
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
oldPassVerification, err := uc.userService.UserModifyPassWordVerification(ctx, req)
if err != nil {
@ -367,7 +368,7 @@ func (uc *UserController) UserUpdateInfo(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
req.UserId = middleware.GetLoginUserIDFromContext(ctx)
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
err := uc.userService.UpdateInfo(ctx, req)
handler.HandleResponse(ctx, err, nil)
}
@ -445,7 +446,7 @@ func (uc *UserController) ActionRecord(ctx *gin.Context) {
if handler.BindAndCheck(ctx, req) {
return
}
req.Ip = ctx.ClientIP()
req.IP = ctx.ClientIP()
resp, err := uc.actionService.ActionRecord(ctx, req)
handler.HandleResponse(ctx, err, resp)
@ -467,8 +468,8 @@ func (uc *UserController) UserNoticeSet(ctx *gin.Context) {
return
}
req.UserId = middleware.GetLoginUserIDFromContext(ctx)
resp, err := uc.userService.UserNoticeSet(ctx, req.UserId, req.NoticeSwitch)
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
resp, err := uc.userService.UserNoticeSet(ctx, req.UserID, req.NoticeSwitch)
handler.HandleResponse(ctx, err, resp)
}
@ -527,8 +528,8 @@ func (uc *UserController) UserChangeEmailVerify(ctx *gin.Context) {
}
req.Content = uc.emailService.VerifyUrlExpired(ctx, req.Code)
if len(req.Content) == 0 {
handler.HandleResponse(ctx, errors.Forbidden(reason.EmailVerifyUrlExpired),
&schema.ForbiddenResp{Type: schema.ForbiddenReasonTypeUrlExpired})
handler.HandleResponse(ctx, errors.Forbidden(reason.EmailVerifyURLExpired),
&schema.ForbiddenResp{Type: schema.ForbiddenReasonTypeURLExpired})
return
}

View File

@ -3,9 +3,9 @@ package entity
import "time"
const (
Answer_Search_OrderBy_Default = "default"
Answer_Search_OrderBy_Time = "updated"
Answer_Search_OrderBy_Vote = "vote"
AnswerSearchOrderByDefault = "default"
AnswerSearchOrderByTime = "updated"
AnswerSearchOrderByVote = "vote"
AnswerStatusAvailable = 1
AnswerStatusDeleted = 10
@ -35,15 +35,15 @@ type Answer struct {
type AnswerSearch struct {
Answer
Order string `json:"order_by" ` // default or updated
Page int `json:"page" form:"page"` //Query number of pages
PageSize int `json:"page_size" form:"page_size"` //Search page size
Page int `json:"page" form:"page"` // Query number of pages
PageSize int `json:"page_size" form:"page_size"` // Search page size
}
type CmsAnswerSearch struct {
Page int `json:"page" form:"page"` //Query number of pages
PageSize int `json:"page_size" form:"page_size"` //Search page size
Page int `json:"page" form:"page"` // Query number of pages
PageSize int `json:"page_size" form:"page_size"` // Search page size
Status int `json:"-" form:"-"`
StatusStr string `json:"status" form:"status"` //Status 1 Available 2 closed 10 Deleted
StatusStr string `json:"status" form:"status"` // Status 1 Available 2 closed 10 Deleted
Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" ` //Query string
}

View File

@ -40,7 +40,7 @@ type User struct {
Avatar string `xorm:"not null default '' VARCHAR(255) avatar"`
Mobile string `xorm:"not null VARCHAR(20) mobile"`
Bio string `xorm:"not null TEXT bio"`
BioHtml string `xorm:"not null TEXT bio_html"`
BioHTML string `xorm:"not null TEXT bio_html"`
Website string `xorm:"not null default '' VARCHAR(255) website"`
Location string `xorm:"not null default '' VARCHAR(100) location"`
IPInfo string `xorm:"not null default '' VARCHAR(255) ip_info"`
@ -54,6 +54,6 @@ func (User) TableName() string {
type UserSearch struct {
User
Page int `json:"page" form:"page"` //Query number of pages
PageSize int `json:"page_size" form:"page_size"` //Search page size
Page int `json:"page" form:"page"` // Query number of pages
PageSize int `json:"page_size" form:"page_size"` // Search page size
}

View File

@ -8,27 +8,25 @@ import (
"xorm.io/xorm"
)
var (
tables = []interface{}{
&entity.Activity{},
&entity.Answer{},
&entity.Collection{},
&entity.CollectionGroup{},
&entity.Comment{},
&entity.Config{},
&entity.Meta{},
&entity.Notification{},
&entity.Question{},
&entity.Report{},
&entity.Revision{},
&entity.SiteInfo{},
&entity.Tag{},
&entity.TagRel{},
&entity.Uniqid{},
&entity.User{},
&entity.Version{},
}
)
var tables = []interface{}{
&entity.Activity{},
&entity.Answer{},
&entity.Collection{},
&entity.CollectionGroup{},
&entity.Comment{},
&entity.Config{},
&entity.Meta{},
&entity.Notification{},
&entity.Question{},
&entity.Report{},
&entity.Revision{},
&entity.SiteInfo{},
&entity.Tag{},
&entity.TagRel{},
&entity.Uniqid{},
&entity.User{},
&entity.Version{},
}
// InitDB init db
func InitDB(dataConf *data.Database) (err error) {
@ -95,91 +93,91 @@ func initSiteInfo(engine *xorm.Engine) error {
func initConfigTable(engine *xorm.Engine) error {
defaultConfigTable := []*entity.Config{
{1, "answer.accepted", `15`},
{2, "answer.voted_up", `10`},
{3, "question.voted_up", `10`},
{4, "tag.edit_accepted", `2`},
{5, "answer.accept", `2`},
{6, "answer.voted_down_cancel", `2`},
{7, "question.voted_down_cancel", `2`},
{8, "answer.vote_down_cancel", `1`},
{9, "question.vote_down_cancel", `1`},
{10, "user.activated", `1`},
{11, "edit.accepted", `2`},
{12, "answer.vote_down", `-1`},
{13, "question.voted_down", `-2`},
{14, "answer.voted_down", `-2`},
{15, "answer.accept_cancel", `-2`},
{16, "answer.deleted", `-5`},
{17, "question.voted_up_cancel", `-10`},
{18, "answer.voted_up_cancel", `-10`},
{19, "answer.accepted_cancel", `-15`},
{20, "object.reported", `-100`},
{21, "edit.rejected", `-2`},
{22, "daily_rank_limit", `200`},
{23, "daily_rank_limit.exclude", `["answer.accepted"]`},
{24, "user.follow", `0`},
{25, "comment.vote_up", `0`},
{26, "comment.vote_up_cancel", `0`},
{27, "question.vote_down", `0`},
{28, "question.vote_up", `0`},
{29, "question.vote_up_cancel", `0`},
{30, "answer.vote_up", `0`},
{31, "answer.vote_up_cancel", `0`},
{32, "question.follow", `0`},
{33, "email.config", `{"from_name":"answer","from_email":"answer@answer.com","smtp_host":"smtp.answer.org","smtp_port":465,"smtp_password":"answer","smtp_username":"answer@answer.com","smtp_authentication":true,"encryption":"","register_title":"[{{.SiteName}}] Confirm your new account","register_body":"Welcome to {{.SiteName}}<br><br>\n\nClick the following link to confirm and activate your new account:<br>\n<a href='{{.RegisterUrl}}' target='_blank'>{{.RegisterUrl}}</a><br><br>\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n","pass_reset_title":"[{{.SiteName }}] Password reset","pass_reset_body":"Somebody asked to reset your password on [{{.SiteName}}].<br><br>\n\nIf it was not you, you can safely ignore this email.<br><br>\n\nClick the following link to choose a new password:<br>\n<a href='{{.PassResetUrl}}' target='_blank'>{{.PassResetUrl}}</a>\n","change_title":"[{{.SiteName}}] Confirm your new email address","change_body":"Confirm your new email address for {{.SiteName}} by clicking on the following link:<br><br>\n\n<a href='{{.ChangeEmailUrl}}' target='_blank'>{{.ChangeEmailUrl}}</a><br><br>\n\nIf you did not request this change, please ignore this email.\n","test_title":"[{{.SiteName}}] Test Email","test_body":"This is a test email."}`},
{35, "tag.follow", `0`},
{36, "rank.question.add", `0`},
{37, "rank.question.edit", `0`},
{38, "rank.question.delete", `0`},
{39, "rank.question.vote_up", `0`},
{40, "rank.question.vote_down", `0`},
{41, "rank.answer.add", `0`},
{42, "rank.answer.edit", `0`},
{43, "rank.answer.delete", `0`},
{44, "rank.answer.accept", `0`},
{45, "rank.answer.vote_up", `0`},
{46, "rank.answer.vote_down", `0`},
{47, "rank.comment.add", `0`},
{48, "rank.comment.edit", `0`},
{49, "rank.comment.delete", `0`},
{50, "rank.report.add", `0`},
{51, "rank.tag.add", `0`},
{52, "rank.tag.edit", `0`},
{53, "rank.tag.delete", `0`},
{54, "rank.tag.synonym", `0`},
{55, "rank.link.url_limit", `0`},
{56, "rank.vote.detail", `0`},
{57, "reason.spam", `{"name":"spam","description":"This post is an advertisement, or vandalism. It is not useful or relevant to the current topic."}`},
{58, "reason.rude_or_abusive", `{"name":"rude or abusive","description":"A reasonable person would find this content inappropriate for respectful discourse."}`},
{59, "reason.something", `{"name":"something else","description":"This post requires staff attention for another reason not listed above.","content_type":"textarea"}`},
{60, "reason.a_duplicate", `{"name":"a duplicate","description":"This question has been asked before and already has an answer.","content_type":"text"}`},
{61, "reason.not_a_answer", `{"name":"not a answer","description":"This was posted as an answer, but it does not attempt to answer the question. It should possibly be an edit, a comment, another question, or deleted altogether.","content_type":""}`},
{62, "reason.no_longer_needed", `{"name":"no longer needed","description":"This comment is outdated, conversational or not relevant to this post."}`},
{63, "reason.community_specific", `{"name":"a community-specific reason","description":"This question doesnt meet a community guideline."}`},
{64, "reason.not_clarity", `{"name":"needs details or clarity","description":"This question currently includes multiple questions in one. It should focus on one problem only.","content_type":"text"}`},
{65, "reason.normal", `{"name":"normal","description":"A normal post available to everyone."}`},
{66, "reason.normal.user", `{"name":"normal","description":"A normal user can ask and answer questions."}`},
{67, "reason.closed", `{"name":"closed","description":"A closed question cant answer, but still can edit, vote and comment."}`},
{68, "reason.deleted", `{"name":"deleted","description":"All reputation gained and lost will be restored."}`},
{69, "reason.deleted.user", `{"name":"deleted","description":"Delete profile, authentication associations."}`},
{70, "reason.suspended", `{"name":"suspended","description":"A suspended user cant log in."}`},
{71, "reason.inactive", `{"name":"inactive","description":"An inactive user must re-validate their email."}`},
{72, "reason.looks_ok", `{"name":"looks ok","description":"This post is good as-is and not low quality."}`},
{73, "reason.needs_edit", `{"name":"needs edit, and I did it","description":"Improve and correct problems with this post yourself."}`},
{74, "reason.needs_close", `{"name":"needs close","description":"A closed question cant answer, but still can edit, vote and comment."}`},
{75, "reason.needs_delete", `{"name":"needs delete","description":"All reputation gained and lost will be restored."}`},
{76, "question.flag.reasons", `["reason.spam","reason.rude_or_abusive","reason.something","reason.a_duplicate"]`},
{77, "answer.flag.reasons", `["reason.spam","reason.rude_or_abusive","reason.something","reason.not_a_answer"]`},
{78, "comment.flag.reasons", `["reason.spam","reason.rude_or_abusive","reason.something","reason.no_longer_needed"]`},
{79, "question.close.reasons", `["reason.a_duplicate","reason.community_specific","reason.not_clarity","reason.something"]`},
{80, "question.status.reasons", `["reason.normal","reason.closed","reason.deleted"]`},
{81, "answer.status.reasons", `["reason.normal","reason.deleted"]`},
{82, "comment.status.reasons", `["reason.normal","reason.deleted"]`},
{83, "user.status.reasons", `["reason.normal.user","reason.suspended","reason.deleted.user","reason.inactive"]`},
{84, "question.review.reasons", `["reason.looks_ok","reason.needs_edit","reason.needs_close","reason.needs_delete"]`},
{85, "answer.review.reasons", `["reason.looks_ok","reason.needs_edit","reason.needs_delete"]`},
{86, "comment.review.reasons", `["reason.looks_ok","reason.needs_edit","reason.needs_delete"]`},
{ID: 1, Key: "answer.accepted", Value: `15`},
{ID: 2, Key: "answer.voted_up", Value: `10`},
{ID: 3, Key: "question.voted_up", Value: `10`},
{ID: 4, Key: "tag.edit_accepted", Value: `2`},
{ID: 5, Key: "answer.accept", Value: `2`},
{ID: 6, Key: "answer.voted_down_cancel", Value: `2`},
{ID: 7, Key: "question.voted_down_cancel", Value: `2`},
{ID: 8, Key: "answer.vote_down_cancel", Value: `1`},
{ID: 9, Key: "question.vote_down_cancel", Value: `1`},
{ID: 10, Key: "user.activated", Value: `1`},
{ID: 11, Key: "edit.accepted", Value: `2`},
{ID: 12, Key: "answer.vote_down", Value: `-1`},
{ID: 13, Key: "question.voted_down", Value: `-2`},
{ID: 14, Key: "answer.voted_down", Value: `-2`},
{ID: 15, Key: "answer.accept_cancel", Value: `-2`},
{ID: 16, Key: "answer.deleted", Value: `-5`},
{ID: 17, Key: "question.voted_up_cancel", Value: `-10`},
{ID: 18, Key: "answer.voted_up_cancel", Value: `-10`},
{ID: 19, Key: "answer.accepted_cancel", Value: `-15`},
{ID: 20, Key: "object.reported", Value: `-100`},
{ID: 21, Key: "edit.rejected", Value: `-2`},
{ID: 22, Key: "daily_rank_limit", Value: `200`},
{ID: 23, Key: "daily_rank_limit.exclude", Value: `["answer.accepted"]`},
{ID: 24, Key: "user.follow", Value: `0`},
{ID: 25, Key: "comment.vote_up", Value: `0`},
{ID: 26, Key: "comment.vote_up_cancel", Value: `0`},
{ID: 27, Key: "question.vote_down", Value: `0`},
{ID: 28, Key: "question.vote_up", Value: `0`},
{ID: 29, Key: "question.vote_up_cancel", Value: `0`},
{ID: 30, Key: "answer.vote_up", Value: `0`},
{ID: 31, Key: "answer.vote_up_cancel", Value: `0`},
{ID: 32, Key: "question.follow", Value: `0`},
{ID: 33, Key: "email.config", Value: `{"from_name":"answer","from_email":"answer@answer.com","smtp_host":"smtp.answer.org","smtp_port":465,"smtp_password":"answer","smtp_username":"answer@answer.com","smtp_authentication":true,"encryption":"","register_title":"[{{.SiteName}}] Confirm your new account","register_body":"Welcome to {{.SiteName}}<br><br>\n\nClick the following link to confirm and activate your new account:<br>\n<a href='{{.RegisterUrl}}' target='_blank'>{{.RegisterUrl}}</a><br><br>\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n","pass_reset_title":"[{{.SiteName }}] Password reset","pass_reset_body":"Somebody asked to reset your password on [{{.SiteName}}].<br><br>\n\nIf it was not you, you can safely ignore this email.<br><br>\n\nClick the following link to choose a new password:<br>\n<a href='{{.PassResetUrl}}' target='_blank'>{{.PassResetUrl}}</a>\n","change_title":"[{{.SiteName}}] Confirm your new email address","change_body":"Confirm your new email address for {{.SiteName}} by clicking on the following link:<br><br>\n\n<a href='{{.ChangeEmailUrl}}' target='_blank'>{{.ChangeEmailUrl}}</a><br><br>\n\nIf you did not request this change, please ignore this email.\n","test_title":"[{{.SiteName}}] Test Email","test_body":"This is a test email."}`},
{ID: 35, Key: "tag.follow", Value: `0`},
{ID: 36, Key: "rank.question.add", Value: `0`},
{ID: 37, Key: "rank.question.edit", Value: `0`},
{ID: 38, Key: "rank.question.delete", Value: `0`},
{ID: 39, Key: "rank.question.vote_up", Value: `0`},
{ID: 40, Key: "rank.question.vote_down", Value: `0`},
{ID: 41, Key: "rank.answer.add", Value: `0`},
{ID: 42, Key: "rank.answer.edit", Value: `0`},
{ID: 43, Key: "rank.answer.delete", Value: `0`},
{ID: 44, Key: "rank.answer.accept", Value: `0`},
{ID: 45, Key: "rank.answer.vote_up", Value: `0`},
{ID: 46, Key: "rank.answer.vote_down", Value: `0`},
{ID: 47, Key: "rank.comment.add", Value: `0`},
{ID: 48, Key: "rank.comment.edit", Value: `0`},
{ID: 49, Key: "rank.comment.delete", Value: `0`},
{ID: 50, Key: "rank.report.add", Value: `0`},
{ID: 51, Key: "rank.tag.add", Value: `0`},
{ID: 52, Key: "rank.tag.edit", Value: `0`},
{ID: 53, Key: "rank.tag.delete", Value: `0`},
{ID: 54, Key: "rank.tag.synonym", Value: `0`},
{ID: 55, Key: "rank.link.url_limit", Value: `0`},
{ID: 56, Key: "rank.vote.detail", Value: `0`},
{ID: 57, Key: "reason.spam", Value: `{"name":"spam","description":"This post is an advertisement, or vandalism. It is not useful or relevant to the current topic."}`},
{ID: 58, Key: "reason.rude_or_abusive", Value: `{"name":"rude or abusive","description":"A reasonable person would find this content inappropriate for respectful discourse."}`},
{ID: 59, Key: "reason.something", Value: `{"name":"something else","description":"This post requires staff attention for another reason not listed above.","content_type":"textarea"}`},
{ID: 60, Key: "reason.a_duplicate", Value: `{"name":"a duplicate","description":"This question has been asked before and already has an answer.","content_type":"text"}`},
{ID: 61, Key: "reason.not_a_answer", Value: `{"name":"not a answer","description":"This was posted as an answer, but it does not attempt to answer the question. It should possibly be an edit, a comment, another question, or deleted altogether.","content_type":""}`},
{ID: 62, Key: "reason.no_longer_needed", Value: `{"name":"no longer needed","description":"This comment is outdated, conversational or not relevant to this post."}`},
{ID: 63, Key: "reason.community_specific", Value: `{"name":"a community-specific reason","description":"This question doesnt meet a community guideline."}`},
{ID: 64, Key: "reason.not_clarity", Value: `{"name":"needs details or clarity","description":"This question currently includes multiple questions in one. It should focus on one problem only.","content_type":"text"}`},
{ID: 65, Key: "reason.normal", Value: `{"name":"normal","description":"A normal post available to everyone."}`},
{ID: 66, Key: "reason.normal.user", Value: `{"name":"normal","description":"A normal user can ask and answer questions."}`},
{ID: 67, Key: "reason.closed", Value: `{"name":"closed","description":"A closed question cant answer, but still can edit, vote and comment."}`},
{ID: 68, Key: "reason.deleted", Value: `{"name":"deleted","description":"All reputation gained and lost will be restored."}`},
{ID: 69, Key: "reason.deleted.user", Value: `{"name":"deleted","description":"Delete profile, authentication associations."}`},
{ID: 70, Key: "reason.suspended", Value: `{"name":"suspended","description":"A suspended user cant log in."}`},
{ID: 71, Key: "reason.inactive", Value: `{"name":"inactive","description":"An inactive user must re-validate their email."}`},
{ID: 72, Key: "reason.looks_ok", Value: `{"name":"looks ok","description":"This post is good as-is and not low quality."}`},
{ID: 73, Key: "reason.needs_edit", Value: `{"name":"needs edit, and I did it","description":"Improve and correct problems with this post yourself."}`},
{ID: 74, Key: "reason.needs_close", Value: `{"name":"needs close","description":"A closed question cant answer, but still can edit, vote and comment."}`},
{ID: 75, Key: "reason.needs_delete", Value: `{"name":"needs delete","description":"All reputation gained and lost will be restored."}`},
{ID: 76, Key: "question.flag.reasons", Value: `["reason.spam","reason.rude_or_abusive","reason.something","reason.a_duplicate"]`},
{ID: 77, Key: "answer.flag.reasons", Value: `["reason.spam","reason.rude_or_abusive","reason.something","reason.not_a_answer"]`},
{ID: 78, Key: "comment.flag.reasons", Value: `["reason.spam","reason.rude_or_abusive","reason.something","reason.no_longer_needed"]`},
{ID: 79, Key: "question.close.reasons", Value: `["reason.a_duplicate","reason.community_specific","reason.not_clarity","reason.something"]`},
{ID: 80, Key: "question.status.reasons", Value: `["reason.normal","reason.closed","reason.deleted"]`},
{ID: 81, Key: "answer.status.reasons", Value: `["reason.normal","reason.deleted"]`},
{ID: 82, Key: "comment.status.reasons", Value: `["reason.normal","reason.deleted"]`},
{ID: 83, Key: "user.status.reasons", Value: `["reason.normal.user","reason.suspended","reason.deleted.user","reason.inactive"]`},
{ID: 84, Key: "question.review.reasons", Value: `["reason.looks_ok","reason.needs_edit","reason.needs_close","reason.needs_delete"]`},
{ID: 85, Key: "answer.review.reasons", Value: `["reason.looks_ok","reason.needs_edit","reason.needs_delete"]`},
{ID: 86, Key: "comment.review.reasons", Value: `["reason.looks_ok","reason.needs_edit","reason.needs_delete"]`},
}
_, err := engine.Insert(defaultConfigTable)
return err

View File

@ -44,7 +44,6 @@ func NewAnswerActivityRepo(
userRankRepo rank.UserRankRepo,
) activity.AnswerActivityRepo {
return &AnswerActivityRepo{
data: data,
activityRepo: activityRepo,
userRankRepo: userRankRepo,
@ -125,7 +124,8 @@ func (ar *AnswerActivityRepo) DeleteQuestion(ctx context.Context, questionID str
// AcceptAnswer accept other answer
func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
answerObjID, questionUserID, answerUserID string, isSelf bool) (err error) {
answerObjID, questionUserID, answerUserID string, isSelf bool,
) (err error) {
addActivityList := make([]*entity.Activity, 0)
for _, action := range acceptActionList {
// get accept answer need add rank amount
@ -173,7 +173,7 @@ func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
}
if exists {
if _, e := session.Where("id = ?", existsActivity.ID).Cols("`cancelled`").
if _, e = session.Where("id = ?", existsActivity.ID).Cols("`cancelled`").
Update(&entity.Activity{Cancelled: entity.ActivityAvailable}); e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
@ -222,7 +222,8 @@ func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
// CancelAcceptAnswer accept other answer
func (ar *AnswerActivityRepo) CancelAcceptAnswer(ctx context.Context,
answerObjID, questionUserID, answerUserID string) (err error) {
answerObjID, questionUserID, answerUserID string,
) (err error) {
addActivityList := make([]*entity.Activity, 0)
for _, action := range acceptActionList {
// get accept answer need add rank amount

View File

@ -37,8 +37,8 @@ func NewFollowRepo(
}
}
func (ar *FollowRepo) Follow(ctx context.Context, objectId, userId string) error {
activityType, _, _, err := ar.activityRepo.GetActivityTypeByObjID(ctx, objectId, "follow")
func (ar *FollowRepo) Follow(ctx context.Context, objectID, userID string) error {
activityType, _, _, err := ar.activityRepo.GetActivityTypeByObjID(ctx, objectID, "follow")
if err != nil {
return err
}
@ -51,8 +51,8 @@ func (ar *FollowRepo) Follow(ctx context.Context, objectId, userId string) error
result = nil
has, err = session.Where(builder.Eq{"activity_type": activityType}).
And(builder.Eq{"user_id": userId}).
And(builder.Eq{"object_id": objectId}).
And(builder.Eq{"user_id": userID}).
And(builder.Eq{"object_id": objectID}).
Get(&existsActivity)
if err != nil {
@ -72,8 +72,8 @@ func (ar *FollowRepo) Follow(ctx context.Context, objectId, userId string) error
} else {
// update existing activity with new user id and u object id
_, err = session.Insert(&entity.Activity{
UserID: userId,
ObjectID: objectId,
UserID: userID,
ObjectID: objectID,
ActivityType: activityType,
Cancelled: 0,
Rank: 0,
@ -87,7 +87,7 @@ func (ar *FollowRepo) Follow(ctx context.Context, objectId, userId string) error
}
// start update followers when everything is fine
err = ar.updateFollows(ctx, session, objectId, 1)
err = ar.updateFollows(ctx, session, objectID, 1)
if err != nil {
log.Error(err)
}
@ -98,8 +98,8 @@ func (ar *FollowRepo) Follow(ctx context.Context, objectId, userId string) error
return err
}
func (ar *FollowRepo) FollowCancel(ctx context.Context, objectId, userId string) error {
activityType, _, _, err := ar.activityRepo.GetActivityTypeByObjID(ctx, objectId, "follow")
func (ar *FollowRepo) FollowCancel(ctx context.Context, objectID, userID string) error {
activityType, _, _, err := ar.activityRepo.GetActivityTypeByObjID(ctx, objectID, "follow")
if err != nil {
return err
}
@ -112,8 +112,8 @@ func (ar *FollowRepo) FollowCancel(ctx context.Context, objectId, userId string)
result = nil
has, err = session.Where(builder.Eq{"activity_type": activityType}).
And(builder.Eq{"user_id": userId}).
And(builder.Eq{"object_id": objectId}).
And(builder.Eq{"user_id": userID}).
And(builder.Eq{"object_id": objectID}).
Get(&existsActivity)
if err != nil || !has {
@ -130,24 +130,24 @@ func (ar *FollowRepo) FollowCancel(ctx context.Context, objectId, userId string)
}); err != nil {
return
}
err = ar.updateFollows(ctx, session, objectId, -1)
err = ar.updateFollows(ctx, session, objectID, -1)
return
})
return err
}
func (ar *FollowRepo) updateFollows(ctx context.Context, session *xorm.Session, objectId string, follows int) error {
objectType, err := obj.GetObjectTypeStrByObjectID(objectId)
func (ar *FollowRepo) updateFollows(ctx context.Context, session *xorm.Session, objectID string, follows int) error {
objectType, err := obj.GetObjectTypeStrByObjectID(objectID)
if err != nil {
return err
}
switch objectType {
case "question":
_, err = session.Where("id = ?", objectId).Incr("follow_count", follows).Update(&entity.Question{})
_, err = session.Where("id = ?", objectID).Incr("follow_count", follows).Update(&entity.Question{})
case "user":
_, err = session.Where("id = ?", objectId).Incr("follow_count", follows).Update(&entity.User{})
_, err = session.Where("id = ?", objectID).Incr("follow_count", follows).Update(&entity.User{})
case "tag":
_, err = session.Where("id = ?", objectId).Incr("follow_count", follows).Update(&entity.Tag{})
_, err = session.Where("id = ?", objectID).Incr("follow_count", follows).Update(&entity.Tag{})
default:
err = errors.InternalServer(reason.DisallowFollow).WithMsg("this object can't be followed")
}

View File

@ -2,9 +2,10 @@ package activity
import (
"context"
"github.com/answerdev/answer/pkg/converter"
"strings"
"github.com/answerdev/answer/pkg/converter"
"github.com/answerdev/answer/internal/base/pager"
"github.com/answerdev/answer/internal/service/config"
"github.com/answerdev/answer/internal/service/notice_queue"
@ -42,7 +43,8 @@ func NewVoteRepo(
configRepo config.ConfigRepo,
activityRepo activity_common.ActivityRepo,
userRankRepo rank.UserRankRepo,
voteCommon activity_common.VoteRepo) service.VoteRepo {
voteCommon activity_common.VoteRepo,
) service.VoteRepo {
return &VoteRepo{
data: data,
uniqueIDRepo: uniqueIDRepo,
@ -65,7 +67,7 @@ var LimitDownActions = map[string][]string{
"comment": {"vote_down"},
}
func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUserId string, actions []string) (resp *schema.VoteResp, err error) {
func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUserID string, actions []string) (resp *schema.VoteResp, err error) {
resp = &schema.VoteResp{}
_, err = vr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
result = nil
@ -75,24 +77,24 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
insertActivity entity.Activity
has bool
triggerUserID,
activityUserId string
activityUserID string
activityType, deltaRank, hasRank int
)
activityUserId, activityType, deltaRank, hasRank, err = vr.CheckRank(ctx, objectID, objectUserId, userID, action)
activityUserID, activityType, deltaRank, hasRank, err = vr.CheckRank(ctx, objectID, objectUserID, userID, action)
if err != nil {
return
}
triggerUserID = userID
if userID == activityUserId {
if userID == activityUserID {
triggerUserID = "0"
}
// check is voted up
has, _ = session.
Where(builder.Eq{"object_id": objectID}).
And(builder.Eq{"user_id": activityUserId}).
And(builder.Eq{"user_id": activityUserID}).
And(builder.Eq{"trigger_user_id": triggerUserID}).
And(builder.Eq{"activity_type": activityType}).
Get(&existsActivity)
@ -104,7 +106,7 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
insertActivity = entity.Activity{
ObjectID: objectID,
UserID: activityUserId,
UserID: activityUserID,
TriggerUserID: converter.StringToInt64(triggerUserID),
ActivityType: activityType,
Rank: deltaRank,
@ -114,7 +116,8 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
// trigger user rank and send notification
if hasRank != 0 {
isReachStandard, err := vr.userRankRepo.TriggerUserRank(ctx, session, activityUserId, deltaRank, activityType)
var isReachStandard bool
isReachStandard, err = vr.userRankRepo.TriggerUserRank(ctx, session, activityUserID, deltaRank, activityType)
if err != nil {
return nil, err
}
@ -122,7 +125,7 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
insertActivity.Rank = 0
}
vr.sendNotification(ctx, activityUserId, objectUserId, objectID)
vr.sendNotification(ctx, activityUserID, objectUserID, objectID)
}
if has {
@ -163,7 +166,7 @@ func (vr *VoteRepo) vote(ctx context.Context, objectID string, userID, objectUse
return
}
func (vr *VoteRepo) voteCancel(ctx context.Context, objectID string, userID, objectUserId string, actions []string) (resp *schema.VoteResp, err error) {
func (vr *VoteRepo) voteCancel(ctx context.Context, objectID string, userID, objectUserID string, actions []string) (resp *schema.VoteResp, err error) {
resp = &schema.VoteResp{}
_, err = vr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
for _, action := range actions {
@ -171,24 +174,24 @@ func (vr *VoteRepo) voteCancel(ctx context.Context, objectID string, userID, obj
existsActivity entity.Activity
has bool
triggerUserID,
activityUserId string
activityUserID string
activityType,
deltaRank, hasRank int
)
result = nil
activityUserId, activityType, deltaRank, hasRank, err = vr.CheckRank(ctx, objectID, objectUserId, userID, action)
activityUserID, activityType, deltaRank, hasRank, err = vr.CheckRank(ctx, objectID, objectUserID, userID, action)
if err != nil {
return
}
triggerUserID = userID
if userID == activityUserId {
if userID == activityUserID {
triggerUserID = "0"
}
has, err = session.
Where(builder.Eq{"user_id": activityUserId}).
Where(builder.Eq{"user_id": activityUserID}).
And(builder.Eq{"trigger_user_id": triggerUserID}).
And(builder.Eq{"activity_type": activityType}).
And(builder.Eq{"object_id": objectID}).
@ -211,12 +214,12 @@ func (vr *VoteRepo) voteCancel(ctx context.Context, objectID string, userID, obj
// trigger user rank and send notification
if hasRank != 0 {
_, err = vr.userRankRepo.TriggerUserRank(ctx, session, activityUserId, -deltaRank, activityType)
_, err = vr.userRankRepo.TriggerUserRank(ctx, session, activityUserID, -deltaRank, activityType)
if err != nil {
return
}
vr.sendNotification(ctx, activityUserId, objectUserId, objectID)
vr.sendNotification(ctx, activityUserID, objectUserID, objectID)
}
// update votes
@ -242,7 +245,7 @@ func (vr *VoteRepo) voteCancel(ctx context.Context, objectID string, userID, obj
return
}
func (vr *VoteRepo) VoteUp(ctx context.Context, objectID string, userID, objectUserId string) (resp *schema.VoteResp, err error) {
func (vr *VoteRepo) VoteUp(ctx context.Context, objectID string, userID, objectUserID string) (resp *schema.VoteResp, err error) {
resp = &schema.VoteResp{}
objectType, err := obj.GetObjectTypeStrByObjectID(objectID)
if err != nil {
@ -256,11 +259,11 @@ func (vr *VoteRepo) VoteUp(ctx context.Context, objectID string, userID, objectU
return
}
_, _ = vr.VoteDownCancel(ctx, objectID, userID, objectUserId)
return vr.vote(ctx, objectID, userID, objectUserId, actions)
_, _ = vr.VoteDownCancel(ctx, objectID, userID, objectUserID)
return vr.vote(ctx, objectID, userID, objectUserID, actions)
}
func (vr *VoteRepo) VoteDown(ctx context.Context, objectID string, userID, objectUserId string) (resp *schema.VoteResp, err error) {
func (vr *VoteRepo) VoteDown(ctx context.Context, objectID string, userID, objectUserID string) (resp *schema.VoteResp, err error) {
resp = &schema.VoteResp{}
objectType, err := obj.GetObjectTypeStrByObjectID(objectID)
if err != nil {
@ -273,14 +276,12 @@ func (vr *VoteRepo) VoteDown(ctx context.Context, objectID string, userID, objec
return
}
_, _ = vr.VoteUpCancel(ctx, objectID, userID, objectUserId)
return vr.vote(ctx, objectID, userID, objectUserId, actions)
_, _ = vr.VoteUpCancel(ctx, objectID, userID, objectUserID)
return vr.vote(ctx, objectID, userID, objectUserID, actions)
}
func (vr *VoteRepo) VoteUpCancel(ctx context.Context, objectID string, userID, objectUserId string) (resp *schema.VoteResp, err error) {
var (
objectType string
)
func (vr *VoteRepo) VoteUpCancel(ctx context.Context, objectID string, userID, objectUserID string) (resp *schema.VoteResp, err error) {
var objectType string
resp = &schema.VoteResp{}
objectType, err = obj.GetObjectTypeStrByObjectID(objectID)
@ -294,13 +295,11 @@ func (vr *VoteRepo) VoteUpCancel(ctx context.Context, objectID string, userID, o
return
}
return vr.voteCancel(ctx, objectID, userID, objectUserId, actions)
return vr.voteCancel(ctx, objectID, userID, objectUserID, actions)
}
func (vr *VoteRepo) VoteDownCancel(ctx context.Context, objectID string, userID, objectUserId string) (resp *schema.VoteResp, err error) {
var (
objectType string
)
func (vr *VoteRepo) VoteDownCancel(ctx context.Context, objectID string, userID, objectUserID string) (resp *schema.VoteResp, err error) {
var objectType string
resp = &schema.VoteResp{}
objectType, err = obj.GetObjectTypeStrByObjectID(objectID)
@ -314,22 +313,22 @@ func (vr *VoteRepo) VoteDownCancel(ctx context.Context, objectID string, userID,
return
}
return vr.voteCancel(ctx, objectID, userID, objectUserId, actions)
return vr.voteCancel(ctx, objectID, userID, objectUserID, actions)
}
func (vr *VoteRepo) CheckRank(ctx context.Context, objectID, objectUserId, userID string, action string) (activityUserId string, activityType, rank, hasRank int, err error) {
func (vr *VoteRepo) CheckRank(ctx context.Context, objectID, objectUserID, userID string, action string) (activityUserID string, activityType, rank, hasRank int, err error) {
activityType, rank, hasRank, err = vr.activityRepo.GetActivityTypeByObjID(ctx, objectID, action)
if err != nil {
return
}
activityUserId = userID
activityUserID = userID
if strings.Contains(action, "voted") {
activityUserId = objectUserId
activityUserID = objectUserID
}
return activityUserId, activityType, rank, hasRank, nil
return activityUserID, activityType, rank, hasRank, nil
}
func (vr *VoteRepo) GetVoteResultByObjectId(ctx context.Context, objectID string) (resp *schema.VoteResp, err error) {
@ -341,7 +340,7 @@ func (vr *VoteRepo) GetVoteResultByObjectId(ctx context.Context, objectID string
activityType int
)
activityType, _, _, err = vr.activityRepo.GetActivityTypeByObjID(ctx, objectID, action)
activityType, _, _, _ = vr.activityRepo.GetActivityTypeByObjID(ctx, objectID, action)
votes, err = vr.data.DB.Where(builder.Eq{"object_id": objectID}).
And(builder.Eq{"activity_type": activityType}).
@ -417,15 +416,15 @@ func (vr *VoteRepo) updateVotes(ctx context.Context, session *xorm.Session, obje
}
// sendNotification send rank triggered notification
func (vr *VoteRepo) sendNotification(ctx context.Context, activityUserId, objectUserId, objectID string) {
func (vr *VoteRepo) sendNotification(ctx context.Context, activityUserID, objectUserID, objectID string) {
objectType, err := obj.GetObjectTypeStrByObjectID(objectID)
if err != nil {
return
}
msg := &schema.NotificationMsg{
ReceiverUserID: activityUserId,
TriggerUserID: objectUserId,
ReceiverUserID: activityUserID,
TriggerUserID: objectUserID,
Type: schema.NotificationTypeAchievement,
ObjectID: objectID,
ObjectType: objectType,

View File

@ -33,27 +33,27 @@ func NewFollowRepo(
}
// GetFollowAmount get object id's follows
func (ar *FollowRepo) GetFollowAmount(ctx context.Context, objectId string) (follows int, err error) {
objectType, err := obj.GetObjectTypeStrByObjectID(objectId)
func (ar *FollowRepo) GetFollowAmount(ctx context.Context, objectID string) (follows int, err error) {
objectType, err := obj.GetObjectTypeStrByObjectID(objectID)
if err != nil {
return 0, err
}
switch objectType {
case "question":
model := &entity.Question{}
_, err = ar.data.DB.Where("id = ?", objectId).Cols("`follow_count`").Get(model)
_, err = ar.data.DB.Where("id = ?", objectID).Cols("`follow_count`").Get(model)
if err == nil {
follows = int(model.FollowCount)
}
case "user":
model := &entity.User{}
_, err = ar.data.DB.Where("id = ?", objectId).Cols("`follow_count`").Get(model)
_, err = ar.data.DB.Where("id = ?", objectID).Cols("`follow_count`").Get(model)
if err == nil {
follows = int(model.FollowCount)
}
case "tag":
model := &entity.Tag{}
_, err = ar.data.DB.Where("id = ?", objectId).Cols("`follow_count`").Get(model)
_, err = ar.data.DB.Where("id = ?", objectID).Cols("`follow_count`").Get(model)
if err == nil {
follows = int(model.FollowCount)
}
@ -95,6 +95,9 @@ func (ar *FollowRepo) GetFollowUserIDs(ctx context.Context, objectID string) (us
func (ar *FollowRepo) GetFollowIDs(ctx context.Context, userID, objectKey string) (followIDs []string, err error) {
followIDs = make([]string, 0)
activityType, err := ar.activityRepo.GetActivityTypeByObjKey(ctx, objectKey, "follow")
if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
session := ar.data.DB.Select("object_id")
session.Table(entity.Activity{}.TableName())
session.Where("user_id = ? AND activity_type = ?", userID, activityType)
@ -107,14 +110,14 @@ func (ar *FollowRepo) GetFollowIDs(ctx context.Context, userID, objectKey string
}
// IsFollowed check user if follow object or not
func (ar *FollowRepo) IsFollowed(userId, objectId string) (bool, error) {
activityType, _, _, err := ar.activityRepo.GetActivityTypeByObjID(nil, objectId, "follow")
func (ar *FollowRepo) IsFollowed(userID, objectID string) (bool, error) {
activityType, _, _, err := ar.activityRepo.GetActivityTypeByObjID(context.TODO(), objectID, "follow")
if err != nil {
return false, err
}
at := &entity.Activity{}
has, err := ar.data.DB.Where("user_id = ? AND object_id = ? AND activity_type = ?", userId, objectId, activityType).Get(at)
has, err := ar.data.DB.Where("user_id = ? AND object_id = ? AND activity_type = ?", userID, objectID, activityType).Get(at)
if err != nil {
return false, err
}

View File

@ -6,13 +6,11 @@ import (
"github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/service/activity_common"
"github.com/answerdev/answer/internal/service/unique"
)
// VoteRepo activity repository
type VoteRepo struct {
data *data.Data
uniqueIDRepo unique.UniqueIDRepo
activityRepo activity_common.ActivityRepo
}
@ -24,11 +22,14 @@ func NewVoteRepo(data *data.Data, activityRepo activity_common.ActivityRepo) act
}
}
func (vr *VoteRepo) GetVoteStatus(ctx context.Context, objectId, userId string) (status string) {
func (vr *VoteRepo) GetVoteStatus(ctx context.Context, objectID, userID string) (status string) {
for _, action := range []string{"vote_up", "vote_down"} {
at := &entity.Activity{}
activityType, _, _, err := vr.activityRepo.GetActivityTypeByObjID(ctx, objectId, action)
has, err := vr.data.DB.Where("object_id =? AND cancelled=0 AND activity_type=? AND user_id=?", objectId, activityType, userId).Get(at)
activityType, _, _, err := vr.activityRepo.GetActivityTypeByObjID(ctx, objectID, action)
if err != nil {
return ""
}
has, err := vr.data.DB.Where("object_id =? AND cancelled=0 AND activity_type=? AND user_id=?", objectID, activityType, userID).Get(at)
if err != nil {
return ""
}

View File

@ -37,14 +37,14 @@ func NewActivityRepo(
}
}
func (ar *ActivityRepo) GetActivityTypeByObjID(ctx context.Context, objectId string, action string) (activityType, rank, hasRank int, err error) {
objectKey, err := obj.GetObjectTypeStrByObjectID(objectId)
func (ar *ActivityRepo) GetActivityTypeByObjID(ctx context.Context, objectID string, action string) (activityType, rank, hasRank int, err error) {
objectKey, err := obj.GetObjectTypeStrByObjectID(objectID)
if err != nil {
return
}
confKey := fmt.Sprintf("%s.%s", objectKey, action)
activityType, err = ar.configRepo.GetConfigType(confKey)
activityType, _ = ar.configRepo.GetConfigType(confKey)
rank, err = ar.configRepo.GetInt(confKey)
hasRank = 0
@ -64,7 +64,8 @@ func (ar *ActivityRepo) GetActivityTypeByObjKey(ctx context.Context, objectKey,
}
func (ar *ActivityRepo) GetActivity(ctx context.Context, session *xorm.Session,
objectID, userID string, activityType int) (existsActivity *entity.Activity, exist bool, err error) {
objectID, userID string, activityType int,
) (existsActivity *entity.Activity, exist bool, err error) {
existsActivity = &entity.Activity{}
exist, err = session.
Where(builder.Eq{"object_id": objectID}).

View File

@ -92,7 +92,8 @@ func (ar *answerRepo) UpdateAnswerStatus(ctx context.Context, answer *entity.Ans
// GetAnswer get answer one
func (ar *answerRepo) GetAnswer(ctx context.Context, id string) (
answer *entity.Answer, exist bool, err error) {
answer *entity.Answer, exist bool, err error,
) {
answer = &entity.Answer{}
exist, err = ar.data.DB.ID(id).Get(answer)
if err != nil {
@ -123,20 +124,20 @@ func (ar *answerRepo) GetAnswerPage(ctx context.Context, page, pageSize int, ans
// UpdateAdopted
// If no answer is selected, the answer id can be 0
func (ar *answerRepo) UpdateAdopted(ctx context.Context, id string, questionId string) error {
if questionId == "" {
func (ar *answerRepo) UpdateAdopted(ctx context.Context, id string, questionID string) error {
if questionID == "" {
return nil
}
var data entity.Answer
data.ID = id
data.Adopted = schema.Answer_Adopted_Failed
_, err := ar.data.DB.Where("question_id =?", questionId).Cols("adopted").Update(&data)
data.Adopted = schema.AnswerAdoptedFailed
_, err := ar.data.DB.Where("question_id =?", questionID).Cols("adopted").Update(&data)
if err != nil {
return err
}
if id != "0" {
data.Adopted = schema.Answer_Adopted_Enable
data.Adopted = schema.AnswerAdoptedEnable
_, err = ar.data.DB.Where("id = ?", id).Cols("adopted").Update(&data)
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
@ -155,9 +156,9 @@ func (ar *answerRepo) GetByID(ctx context.Context, id string) (*entity.Answer, b
return &resp, has, nil
}
func (ar *answerRepo) GetByUserIdQuestionId(ctx context.Context, userId string, questionId string) (*entity.Answer, bool, error) {
func (ar *answerRepo) GetByUserIDQuestionID(ctx context.Context, userID string, questionID string) (*entity.Answer, bool, error) {
var resp entity.Answer
has, err := ar.data.DB.Where("question_id =? and user_id = ?", questionId, userId).Get(&resp)
has, err := ar.data.DB.Where("question_id =? and user_id = ?", questionID, userID).Get(&resp)
if err != nil {
return &resp, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -175,7 +176,7 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.Default_PageSize
search.PageSize = constant.DefaultPageSize
}
offset := search.Page * search.PageSize
session := ar.data.DB.Where("")
@ -186,14 +187,14 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc
if len(search.UserID) > 0 {
session = session.And("user_id = ?", search.UserID)
}
if search.Order == entity.Answer_Search_OrderBy_Time {
switch search.Order {
case entity.AnswerSearchOrderByTime:
session = session.OrderBy("created_at desc")
} else if search.Order == entity.Answer_Search_OrderBy_Vote {
case entity.AnswerSearchOrderByVote:
session = session.OrderBy("vote_count desc")
} else {
default:
session = session.OrderBy("adopted desc,vote_count desc")
}
session = session.And("status = ?", entity.AnswerStatusAvailable)
session = session.Limit(search.PageSize, offset)
@ -222,7 +223,7 @@ func (ar *answerRepo) CmsSearchList(ctx context.Context, search *entity.CmsAnswe
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.Default_PageSize
search.PageSize = constant.DefaultPageSize
}
// search by question title like or answer id

View File

@ -37,7 +37,7 @@ func (cr *collectionGroupRepo) AddCollectionGroup(ctx context.Context, collectio
func (cr *collectionGroupRepo) AddCollectionDefaultGroup(ctx context.Context, userID string) (collectionGroup *entity.CollectionGroup, err error) {
defaultGroup := &entity.CollectionGroup{
Name: "default",
DefaultGroup: schema.CG_DEFAULT,
DefaultGroup: schema.CGDefault,
UserID: userID,
}
_, err = cr.data.DB.Insert(defaultGroup)
@ -60,7 +60,8 @@ func (cr *collectionGroupRepo) UpdateCollectionGroup(ctx context.Context, collec
// GetCollectionGroup get collection group one
func (cr *collectionGroupRepo) GetCollectionGroup(ctx context.Context, id string) (
collectionGroup *entity.CollectionGroup, exist bool, err error) {
collectionGroup *entity.CollectionGroup, exist bool, err error,
) {
collectionGroup = &entity.CollectionGroup{}
exist, err = cr.data.DB.ID(id).Get(collectionGroup)
if err != nil {
@ -84,9 +85,9 @@ func (cr *collectionGroupRepo) GetCollectionGroupPage(ctx context.Context, page,
return
}
func (cr *collectionGroupRepo) GetDefaultID(ctx context.Context, userId string) (collectionGroup *entity.CollectionGroup, has bool, err error) {
func (cr *collectionGroupRepo) GetDefaultID(ctx context.Context, userID string) (collectionGroup *entity.CollectionGroup, has bool, err error) {
collectionGroup = &entity.CollectionGroup{}
has, err = cr.data.DB.Where("user_id =? and default_group = ?", userId, schema.CG_DEFAULT).Get(collectionGroup)
has, err = cr.data.DB.Where("user_id =? and default_group = ?", userID, schema.CGDefault).Get(collectionGroup)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return

View File

@ -74,9 +74,9 @@ func (cr *collectionRepo) GetCollectionList(ctx context.Context, collection *ent
}
// GetOneByObjectIDAndUser get one by object TagID and user
func (cr *collectionRepo) GetOneByObjectIDAndUser(ctx context.Context, userId string, objectId string) (collection *entity.Collection, exist bool, err error) {
func (cr *collectionRepo) GetOneByObjectIDAndUser(ctx context.Context, userID string, objectID string) (collection *entity.Collection, exist bool, err error) {
collection = &entity.Collection{}
exist, err = cr.data.DB.Where("user_id = ? and object_id = ?", userId, objectId).Get(collection)
exist, err = cr.data.DB.Where("user_id = ? and object_id = ?", userID, objectID).Get(collection)
if err != nil {
return nil, false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -84,9 +84,9 @@ func (cr *collectionRepo) GetOneByObjectIDAndUser(ctx context.Context, userId st
}
// SearchByObjectIDsAndUser search by object IDs and user
func (cr *collectionRepo) SearchByObjectIDsAndUser(ctx context.Context, userId string, objectIds []string) ([]*entity.Collection, error) {
func (cr *collectionRepo) SearchByObjectIDsAndUser(ctx context.Context, userID string, objectIDs []string) ([]*entity.Collection, error) {
collectionList := make([]*entity.Collection, 0)
err := cr.data.DB.Where("user_id = ?", userId).In("object_id", objectIds).Find(&collectionList)
err := cr.data.DB.Where("user_id = ?", userID).In("object_id", objectIDs).Find(&collectionList)
if err != nil {
return collectionList, err
}
@ -94,9 +94,9 @@ func (cr *collectionRepo) SearchByObjectIDsAndUser(ctx context.Context, userId s
}
// CountByObjectID count by object TagID
func (cr *collectionRepo) CountByObjectID(ctx context.Context, objectId string) (total int64, err error) {
func (cr *collectionRepo) CountByObjectID(ctx context.Context, objectID string) (total int64, err error) {
collection := &entity.Collection{}
total, err = cr.data.DB.Where("object_id = ?", objectId).Count(collection)
total, err = cr.data.DB.Where("object_id = ?", objectID).Count(collection)
if err != nil {
return 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -105,7 +105,6 @@ func (cr *collectionRepo) CountByObjectID(ctx context.Context, objectId string)
// GetCollectionPage get collection page
func (cr *collectionRepo) GetCollectionPage(ctx context.Context, page, pageSize int, collection *entity.Collection) (collectionList []*entity.Collection, total int64, err error) {
collectionList = make([]*entity.Collection, 0)
session := cr.data.DB.NewSession()
@ -124,9 +123,9 @@ func (cr *collectionRepo) GetCollectionPage(ctx context.Context, page, pageSize
}
// SearchObjectCollected check object is collected or not
func (cr *collectionRepo) SearchObjectCollected(ctx context.Context, userId string, objectIds []string) (map[string]bool, error) {
func (cr *collectionRepo) SearchObjectCollected(ctx context.Context, userID string, objectIds []string) (map[string]bool, error) {
collectedMap := make(map[string]bool)
list, err := cr.SearchByObjectIDsAndUser(ctx, userId, objectIds)
list, err := cr.SearchByObjectIDsAndUser(ctx, userID, objectIds)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return collectedMap, err
@ -148,7 +147,7 @@ func (cr *collectionRepo) SearchList(ctx context.Context, search *entity.Collect
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.Default_PageSize
search.PageSize = constant.DefaultPageSize
}
offset := search.Page * search.PageSize
session := cr.data.DB.Where("")

View File

@ -69,7 +69,8 @@ func (cr *commentRepo) UpdateComment(ctx context.Context, comment *entity.Commen
// GetComment get comment one
func (cr *commentRepo) GetComment(ctx context.Context, commentID string) (
comment *entity.Comment, exist bool, err error) {
comment *entity.Comment, exist bool, err error,
) {
comment = &entity.Comment{}
exist, err = cr.data.DB.ID(commentID).Get(comment)
if err != nil {
@ -80,7 +81,8 @@ func (cr *commentRepo) GetComment(ctx context.Context, commentID string) (
// GetCommentPage get comment page
func (cr *commentRepo) GetCommentPage(ctx context.Context, commentQuery *comment.CommentQuery) (
commentList []*entity.Comment, total int64, err error) {
commentList []*entity.Comment, total int64, err error,
) {
commentList = make([]*entity.Comment, 0)
session := cr.data.DB.NewSession()

View File

@ -37,15 +37,13 @@ func (cr *CommonRepo) GetRootObjectID(objectID string) (rootObjectID string, err
exist, err = cr.data.DB.ID(objectID).Get(&answer)
if !exist {
err = errors.BadRequest(reason.ObjectNotFound)
} else {
objectID = answer.QuestionID
}
case "comment":
exist, err = cr.data.DB.ID(objectID).Get(&comment)
exist, _ = cr.data.DB.ID(objectID).Get(&comment)
if !exist {
err = errors.BadRequest(reason.ObjectNotFound)
} else {
objectID, err = cr.GetRootObjectID(comment.ObjectID)
_, err = cr.GetRootObjectID(comment.ObjectID)
}
default:
rootObjectID = objectID
@ -72,7 +70,7 @@ func (cr *CommonRepo) GetObjectIDMap(objectID string) (objectIDMap map[string]st
}
switch objectType {
case "answer":
exist, err = cr.data.DB.ID(objectID).Get(&answer)
exist, _ = cr.data.DB.ID(objectID).Get(&answer)
if !exist {
err = errors.BadRequest(reason.ObjectNotFound)
} else {
@ -80,7 +78,7 @@ func (cr *CommonRepo) GetObjectIDMap(objectID string) (objectIDMap map[string]st
ID = answer.ID
}
case "comment":
exist, err = cr.data.DB.ID(objectID).Get(&comment)
exist, _ = cr.data.DB.ID(objectID).Get(&comment)
if !exist {
err = errors.BadRequest(reason.ObjectNotFound)
} else {

View File

@ -102,7 +102,7 @@ func (nr *notificationRepo) SearchList(ctx context.Context, search *schema.Notif
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.Default_PageSize
search.PageSize = constant.DefaultPageSize
}
offset := search.Page * search.PageSize
session := nr.data.DB.Where("")

View File

@ -67,27 +67,27 @@ func (qr *questionRepo) UpdateQuestion(ctx context.Context, question *entity.Que
return
}
func (qr *questionRepo) UpdatePvCount(ctx context.Context, questionId string) (err error) {
func (qr *questionRepo) UpdatePvCount(ctx context.Context, questionID string) (err error) {
question := &entity.Question{}
_, err = qr.data.DB.Where("id =?", questionId).Incr("view_count", 1).Update(question)
_, err = qr.data.DB.Where("id =?", questionID).Incr("view_count", 1).Update(question)
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return nil
}
func (qr *questionRepo) UpdateAnswerCount(ctx context.Context, questionId string, num int) (err error) {
func (qr *questionRepo) UpdateAnswerCount(ctx context.Context, questionID string, num int) (err error) {
question := &entity.Question{}
_, err = qr.data.DB.Where("id =?", questionId).Incr("answer_count", num).Update(question)
_, err = qr.data.DB.Where("id =?", questionID).Incr("answer_count", num).Update(question)
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return nil
}
func (qr *questionRepo) UpdateCollectionCount(ctx context.Context, questionId string, num int) (err error) {
func (qr *questionRepo) UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error) {
question := &entity.Question{}
_, err = qr.data.DB.Where("id =?", questionId).Incr("collection_count", num).Update(question)
_, err = qr.data.DB.Where("id =?", questionID).Incr("collection_count", num).Update(question)
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -122,7 +122,8 @@ func (qr *questionRepo) UpdateLastAnswer(ctx context.Context, question *entity.Q
// GetQuestion get question one
func (qr *questionRepo) GetQuestion(ctx context.Context, id string) (
question *entity.Question, exist bool, err error) {
question *entity.Question, exist bool, err error,
) {
question = &entity.Question{}
question.ID = id
exist, err = qr.data.DB.Where("id = ?", id).Get(question)
@ -182,7 +183,7 @@ func (qr *questionRepo) SearchList(ctx context.Context, search *schema.QuestionS
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.Default_PageSize
search.PageSize = constant.DefaultPageSize
}
offset := search.Page * search.PageSize
session := qr.data.DB.Table("question")
@ -190,7 +191,7 @@ func (qr *questionRepo) SearchList(ctx context.Context, search *schema.QuestionS
if len(search.TagIDs) > 0 {
session = session.Join("LEFT", "tag_rel", "question.id = tag_rel.object_id")
session = session.And("tag_rel.tag_id =?", search.TagIDs[0])
//session = session.In("tag_rel.tag_id ", search.TagIDs)
// session = session.In("tag_rel.tag_id ", search.TagIDs)
session = session.And("tag_rel.status =?", entity.TagRelStatusAvailable)
}
@ -202,8 +203,8 @@ func (qr *questionRepo) SearchList(ctx context.Context, search *schema.QuestionS
// if search.Status > 0 {
// session = session.And("question.status = ?", search.Status)
// }
//switch
//newest, active,frequent,score,unanswered
// switch
// newest, active,frequent,score,unanswered
switch search.Order {
case "newest":
session = session.OrderBy("question.created_at desc")
@ -245,7 +246,7 @@ func (qr *questionRepo) CmsSearchList(ctx context.Context, search *schema.CmsQue
search.Page = 0
}
if search.PageSize == 0 {
search.PageSize = constant.Default_PageSize
search.PageSize = constant.DefaultPageSize
}
// search by question title like or question id

View File

@ -34,26 +34,28 @@ func NewUserRankRepo(data *data.Data, configRepo config.ConfigRepo) rank.UserRan
// session is need provider, it means this action must be success or failure
// if outer action is failed then this action is need rollback
func (ur *UserRankRepo) TriggerUserRank(ctx context.Context,
session *xorm.Session, userId string, deltaRank int, activityType int) (isReachStandard bool, err error) {
session *xorm.Session, userID string, deltaRank int, activityType int,
) (isReachStandard bool, err error) {
if deltaRank == 0 {
return false, nil
}
if deltaRank < 0 {
// if user rank is lower than 1 after this action, then user rank will be set to 1 only.
isReachMin, err := ur.checkUserMinRank(ctx, session, userId, activityType)
var isReachMin bool
isReachMin, err = ur.checkUserMinRank(ctx, session, userID, activityType)
if err != nil {
return false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
if isReachMin {
_, err = session.Where(builder.Eq{"id": userId}).Update(&entity.User{Rank: 1})
_, err = session.Where(builder.Eq{"id": userID}).Update(&entity.User{Rank: 1})
if err != nil {
return false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return false, nil
}
} else {
isReachStandard, err = ur.checkUserTodayRank(ctx, session, userId, activityType)
isReachStandard, err = ur.checkUserTodayRank(ctx, session, userID, activityType)
if err != nil {
return false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -61,7 +63,7 @@ func (ur *UserRankRepo) TriggerUserRank(ctx context.Context,
return isReachStandard, nil
}
}
_, err = session.Where(builder.Eq{"id": userId}).Incr("`rank`", deltaRank).Update(&entity.User{})
_, err = session.Where(builder.Eq{"id": userID}).Incr("`rank`", deltaRank).Update(&entity.User{})
if err != nil {
return false, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -69,7 +71,8 @@ func (ur *UserRankRepo) TriggerUserRank(ctx context.Context,
}
func (ur *UserRankRepo) checkUserMinRank(ctx context.Context, session *xorm.Session, userID string, deltaRank int) (
isReachStandard bool, err error) {
isReachStandard bool, err error,
) {
bean := &entity.User{ID: userID}
_, err = session.Select("rank").Get(bean)
if err != nil {
@ -83,11 +86,13 @@ func (ur *UserRankRepo) checkUserMinRank(ctx context.Context, session *xorm.Sess
}
func (ur *UserRankRepo) checkUserTodayRank(ctx context.Context,
session *xorm.Session, userID string, activityType int) (isReachStandard bool, err error) {
session *xorm.Session, userID string, activityType int,
) (isReachStandard bool, err error) {
// exclude daily rank
exclude, err := ur.configRepo.GetArrayString("daily_rank_limit.exclude")
exclude, _ := ur.configRepo.GetArrayString("daily_rank_limit.exclude")
for _, item := range exclude {
excludeActivityType, err := ur.configRepo.GetInt(item)
var excludeActivityType int
excludeActivityType, err = ur.configRepo.GetInt(item)
if err != nil {
return false, err
}
@ -123,14 +128,15 @@ func (ur *UserRankRepo) checkUserTodayRank(ctx context.Context,
return true, nil
}
func (ur *UserRankRepo) UserRankPage(ctx context.Context, userId string, page, pageSize int) (
rankPage []*entity.Activity, total int64, err error) {
func (ur *UserRankRepo) UserRankPage(ctx context.Context, userID string, page, pageSize int) (
rankPage []*entity.Activity, total int64, err error,
) {
rankPage = make([]*entity.Activity, 0)
session := ur.data.DB.Where(builder.Eq{"has_rank": 1}.And(builder.Eq{"cancelled": 0}))
session.Desc("created_at")
cond := &entity.Activity{UserID: userId}
cond := &entity.Activity{UserID: userID}
total, err = pager.Help(page, pageSize, &rankPage, cond, session)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()

View File

@ -86,7 +86,8 @@ func (ar *reportRepo) GetByID(ctx context.Context, id string) (report entity.Rep
func (ar *reportRepo) UpdateByID(
ctx context.Context,
id string,
handleData entity.Report) (err error) {
handleData entity.Report,
) (err error) {
_, err = ar.data.DB.ID(id).Update(&handleData)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()

View File

@ -81,7 +81,8 @@ func (rr *revisionRepo) UpdateObjectRevisionId(ctx context.Context, revision *en
// GetRevision get revision one
func (rr *revisionRepo) GetRevision(ctx context.Context, id string) (
revision *entity.Revision, exist bool, err error) {
revision *entity.Revision, exist bool, err error,
) {
revision = &entity.Revision{}
exist, err = rr.data.DB.ID(id).Get(revision)
if err != nil {
@ -92,7 +93,8 @@ func (rr *revisionRepo) GetRevision(ctx context.Context, id string) (
// GetLastRevisionByObjectID get object's last revision by object TagID
func (rr *revisionRepo) GetLastRevisionByObjectID(ctx context.Context, objectID string) (
revision *entity.Revision, exist bool, err error) {
revision *entity.Revision, exist bool, err error,
) {
revision = &entity.Revision{}
exist, err = rr.data.DB.Where("object_id = ?", objectID).OrderBy("create_time DESC").Get(revision)
if err != nil {

View File

@ -21,7 +21,7 @@ import (
)
var (
q_fields = []string{
qFields = []string{
"`question`.`id`",
"`question`.`id` as `question_id`",
"`title`",
@ -34,7 +34,7 @@ var (
"`question`.`status` as `status`",
"`post_update_time`",
}
a_fields = []string{
aFields = []string{
"`answer`.`id` as `id`",
"`question_id`",
"`question`.`title` as `title`",
@ -70,8 +70,8 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID,
var (
b *builder.Builder
ub *builder.Builder
qfs = q_fields
afs = a_fields
qfs = qFields
afs = aFields
argsQ = []interface{}{}
argsA = []interface{}{}
)
@ -141,11 +141,11 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID,
b = b.Union("all", ub)
querySql, _, err := builder.MySQL().Select("*").From(b, "t").OrderBy(sr.parseOrder(ctx, order)).Limit(size, page-1).ToSQL()
querySQL, _, err := builder.MySQL().Select("*").From(b, "t").OrderBy(sr.parseOrder(ctx, order)).Limit(size, page-1).ToSQL()
if err != nil {
return
}
countSql, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
countSQL, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
if err != nil {
return
}
@ -153,11 +153,11 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID,
queryArgs := []interface{}{}
countArgs := []interface{}{}
queryArgs = append(queryArgs, querySql)
queryArgs = append(queryArgs, querySQL)
queryArgs = append(queryArgs, argsQ...)
queryArgs = append(queryArgs, argsA...)
countArgs = append(countArgs, countSql)
countArgs = append(countArgs, countSQL)
countArgs = append(countArgs, argsQ...)
countArgs = append(countArgs, argsA...)
@ -182,7 +182,7 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagID,
// SearchQuestions search question data
func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limitNoAccepted bool, answers, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
var (
qfs = q_fields
qfs = qFields
args = []interface{}{}
)
if order == "relevance" {
@ -223,18 +223,18 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limit
queryArgs := []interface{}{}
countArgs := []interface{}{}
querySql, _, err := b.OrderBy(sr.parseOrder(ctx, order)).Limit(size, page-1).ToSQL()
querySQL, _, err := b.OrderBy(sr.parseOrder(ctx, order)).Limit(size, page-1).ToSQL()
if err != nil {
return
}
countSql, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
countSQL, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
if err != nil {
return
}
queryArgs = append(queryArgs, querySql)
queryArgs = append(queryArgs, querySQL)
queryArgs = append(queryArgs, args...)
countArgs = append(countArgs, countSql)
countArgs = append(countArgs, countSQL)
countArgs = append(countArgs, args...)
res, err := sr.data.DB.Query(queryArgs...)
@ -250,10 +250,6 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limit
if len(tr) != 0 {
total = converter.StringToInt64(string(tr[0]["total"]))
}
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return
}
resp, err = sr.parseResult(ctx, res)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
@ -264,7 +260,7 @@ func (sr *searchRepo) SearchQuestions(ctx context.Context, words []string, limit
// SearchAnswers search answer data
func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, limitAccepted bool, questionID string, page, size int, order string) (resp []schema.SearchResp, total int64, err error) {
var (
afs = a_fields
afs = aFields
args = []interface{}{}
)
if order == "relevance" {
@ -289,8 +285,8 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, limitAc
}
if limitAccepted {
b.Where(builder.Eq{"adopted": schema.Answer_Adopted_Enable})
args = append(args, schema.Answer_Adopted_Enable)
b.Where(builder.Eq{"adopted": schema.AnswerAdoptedEnable})
args = append(args, schema.AnswerAdoptedEnable)
}
if questionID != "" {
@ -301,18 +297,18 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, limitAc
queryArgs := []interface{}{}
countArgs := []interface{}{}
querySql, _, err := b.OrderBy(sr.parseOrder(ctx, order)).Limit(size, page-1).ToSQL()
querySQL, _, err := b.OrderBy(sr.parseOrder(ctx, order)).Limit(size, page-1).ToSQL()
if err != nil {
return
}
countSql, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
countSQL, _, err := builder.MySQL().Select("count(*) total").From(b, "c").ToSQL()
if err != nil {
return
}
queryArgs = append(queryArgs, querySql)
queryArgs = append(queryArgs, querySQL)
queryArgs = append(queryArgs, args...)
countArgs = append(countArgs, countSql)
countArgs = append(countArgs, countSQL)
countArgs = append(countArgs, args...)
res, err := sr.data.DB.Query(queryArgs...)
@ -326,10 +322,6 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, limitAc
}
total = converter.StringToInt64(string(tr[0]["total"]))
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return
}
resp, err = sr.parseResult(ctx, res)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
@ -438,7 +430,7 @@ func (sr *searchRepo) userBasicInfoFormat(ctx context.Context, dbinfo *entity.Us
Avatar: dbinfo.Avatar,
Website: dbinfo.Website,
Location: dbinfo.Location,
IpInfo: dbinfo.IPInfo,
IPInfo: dbinfo.IPInfo,
}
}
@ -451,24 +443,24 @@ func cutOutParsedText(parsedText string) string {
return parsedText
}
func addRelevanceField(search_fields, words, fields []string) (res []string, args []interface{}) {
var relevanceRes = []string{}
func addRelevanceField(searchFields, words, fields []string) (res []string, args []interface{}) {
relevanceRes := []string{}
args = []interface{}{}
for _, search_field := range search_fields {
for _, searchField := range searchFields {
var (
relevance = "(LENGTH(" + search_field + ") - LENGTH(%s))"
replacement = "REPLACE(%s, ?, '')"
replace_field = search_field
replaced string
argsField = []interface{}{}
relevance = "(LENGTH(" + searchField + ") - LENGTH(%s))"
replacement = "REPLACE(%s, ?, '')"
replaceField = searchField
replaced string
argsField = []interface{}{}
)
res = fields
for i, word := range words {
if i == 0 {
argsField = append(argsField, word)
replaced = fmt.Sprintf(replacement, replace_field)
replaced = fmt.Sprintf(replacement, replaceField)
} else {
argsField = append(argsField, word)
replaced = fmt.Sprintf(replacement, replaced)

View File

@ -27,7 +27,7 @@ func (sr *siteInfoRepo) SaveByType(ctx context.Context, siteType string, data *e
old = &entity.SiteInfo{}
exist bool
)
exist, err = sr.data.DB.Where(builder.Eq{"type": siteType}).Get(old)
exist, _ = sr.data.DB.Where(builder.Eq{"type": siteType}).Get(old)
if exist {
_, err = sr.data.DB.ID(old.ID).Update(data)
if err != nil {

View File

@ -32,8 +32,8 @@ func (tr *tagListRepo) AddTagRelList(ctx context.Context, tagList []*entity.TagR
}
// RemoveTagRelListByObjectID delete tag list
func (tr *tagListRepo) RemoveTagRelListByObjectID(ctx context.Context, objectId string) (err error) {
_, err = tr.data.DB.Where("object_id = ?", objectId).Update(&entity.TagRel{Status: entity.TagRelStatusDeleted})
func (tr *tagListRepo) RemoveTagRelListByObjectID(ctx context.Context, objectID string) (err error) {
_, err = tr.data.DB.Where("object_id = ?", objectID).Update(&entity.TagRel{Status: entity.TagRelStatusDeleted})
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
@ -50,10 +50,11 @@ func (tr *tagListRepo) RemoveTagRelListByIDs(ctx context.Context, ids []int64) (
}
// GetObjectTagRelWithoutStatus get object tag relation no matter status
func (tr *tagListRepo) GetObjectTagRelWithoutStatus(ctx context.Context, objectId, tagID string) (
tagRel *entity.TagRel, exist bool, err error) {
func (tr *tagListRepo) GetObjectTagRelWithoutStatus(ctx context.Context, objectID, tagID string) (
tagRel *entity.TagRel, exist bool, err error,
) {
tagRel = &entity.TagRel{}
session := tr.data.DB.Where("object_id = ?", objectId).And("tag_id = ?", tagID)
session := tr.data.DB.Where("object_id = ?", objectID).And("tag_id = ?", tagID)
exist, err = session.Get(tagRel)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
@ -71,9 +72,9 @@ func (tr *tagListRepo) EnableTagRelByIDs(ctx context.Context, ids []int64) (err
}
// GetObjectTagRelList get object tag relation list all
func (tr *tagListRepo) GetObjectTagRelList(ctx context.Context, objectId string) (tagListList []*entity.TagRel, err error) {
func (tr *tagListRepo) GetObjectTagRelList(ctx context.Context, objectID string) (tagListList []*entity.TagRel, err error) {
tagListList = make([]*entity.TagRel, 0)
session := tr.data.DB.Where("object_id = ?", objectId)
session := tr.data.DB.Where("object_id = ?", objectID)
session.Where("status = ?", entity.TagRelStatusAvailable)
err = session.Find(&tagListList)
if err != nil {

View File

@ -34,7 +34,8 @@ func NewTagRepo(
// AddTagList add tag
func (tr *tagRepo) AddTagList(ctx context.Context, tagList []*entity.Tag) (err error) {
for _, item := range tagList {
ID, err := tr.uniqueIDRepo.GenUniqueID(ctx, item.TableName())
var ID int64
ID, err = tr.uniqueIDRepo.GenUniqueID(ctx, item.TableName())
if err != nil {
return err
}
@ -128,7 +129,8 @@ func (tr *tagRepo) UpdateTagQuestionCount(ctx context.Context, tagID string, que
// UpdateTagSynonym update synonym tag
func (tr *tagRepo) UpdateTagSynonym(ctx context.Context, tagSlugNameList []string, mainTagID int64,
mainTagSlugName string) (err error) {
mainTagSlugName string,
) (err error) {
bean := &entity.Tag{MainTagID: mainTagID, MainTagSlugName: mainTagSlugName}
session := tr.data.DB.In("slug_name", tagSlugNameList).MustCols("main_tag_id", "main_tag_slug_name")
_, err = session.Update(bean)
@ -140,7 +142,8 @@ func (tr *tagRepo) UpdateTagSynonym(ctx context.Context, tagSlugNameList []strin
// GetTagByID get tag one
func (tr *tagRepo) GetTagByID(ctx context.Context, tagID string) (
tag *entity.Tag, exist bool, err error) {
tag *entity.Tag, exist bool, err error,
) {
tag = &entity.Tag{}
session := tr.data.DB.Where(builder.Eq{"id": tagID})
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
@ -164,7 +167,8 @@ func (tr *tagRepo) GetTagList(ctx context.Context, tag *entity.Tag) (tagList []*
// GetTagPage get tag page
func (tr *tagRepo) GetTagPage(ctx context.Context, page, pageSize int, tag *entity.Tag, queryCond string) (
tagList []*entity.Tag, total int64, err error) {
tagList []*entity.Tag, total int64, err error,
) {
tagList = make([]*entity.Tag, 0)
session := tr.data.DB.NewSession()

View File

@ -33,7 +33,8 @@ func NewUserBackyardRepo(data *data.Data) user_backyard.UserBackyardRepo {
// UpdateUserStatus update user status
func (ur *userBackyardRepo) UpdateUserStatus(ctx context.Context, userID string, userStatus, mailStatus int,
email string) (err error) {
email string,
) (err error) {
cond := &entity.User{Status: userStatus, MailStatus: mailStatus, EMail: email}
switch userStatus {
case entity.UserStatusSuspended:
@ -75,11 +76,12 @@ func (ur *userBackyardRepo) GetUserInfo(ctx context.Context, userID string) (use
func (ur *userBackyardRepo) GetUserPage(ctx context.Context, page, pageSize int, user *entity.User, query string) (users []*entity.User, total int64, err error) {
users = make([]*entity.User, 0)
session := ur.data.DB.NewSession()
if user.Status == entity.UserStatusDeleted {
switch user.Status {
case entity.UserStatusDeleted:
session.Desc("deleted_at")
} else if user.Status == entity.UserStatusSuspended {
case entity.UserStatusSuspended:
session.Desc("suspended_at")
} else {
default:
session.Desc("created_at")
}

View File

@ -9,44 +9,44 @@ type RemoveAnswerReq struct {
}
const (
Answer_Adopted_Failed = 1
Answer_Adopted_Enable = 2
AnswerAdoptedFailed = 1
AnswerAdoptedEnable = 2
)
type AnswerAddReq struct {
QuestionId string `json:"question_id" ` // question_id
QuestionID string `json:"question_id" ` // question_id
Content string `json:"content" ` // content
Html string `json:"html" ` // html
HTML string `json:"html" ` // html
UserID string `json:"-" ` // user_id
}
type AnswerUpdateReq struct {
ID string `json:"id"` // id
QuestionId string `json:"question_id" ` // question_id
QuestionID string `json:"question_id" ` // question_id
UserID string `json:"-" ` // user_id
Title string `json:"title" ` // title
Content string `json:"content"` // content
Html string `json:"html" ` // html
EditSummary string `validate:"omitempty" json:"edit_summary"` //edit_summary
HTML string `json:"html" ` // html
EditSummary string `validate:"omitempty" json:"edit_summary"` // edit_summary
}
type AnswerList struct {
QuestionId string `json:"question_id" form:"question_id"` // question_id
QuestionID string `json:"question_id" form:"question_id"` // question_id
Order string `json:"order" form:"order"` // 1 Default 2 time
Page int `json:"page" form:"page"` //Query number of pages
PageSize int `json:"page_size" form:"page_size"` //Search page size
Page int `json:"page" form:"page"` // Query number of pages
PageSize int `json:"page_size" form:"page_size"` // Search page size
LoginUserID string `json:"-" `
}
type AnswerInfo struct {
ID string `json:"id" xorm:"id"` // id
QuestionId string `json:"question_id" xorm:"question_id"` // question_id
QuestionID string `json:"question_id" xorm:"question_id"` // question_id
Content string `json:"content" xorm:"content"` // content
Html string `json:"html" xorm:"html"` // html
HTML string `json:"html" xorm:"html"` // html
CreateTime int64 `json:"create_time" xorm:"created"` // create_time
UpdateTime int64 `json:"update_time" xorm:"updated"` // update_time
Adopted int `json:"adopted"` // 1 Failed 2 Adopted
UserId string `json:"-" `
UserID string `json:"-" `
UserInfo *UserBasicInfo `json:"user_info,omitempty"`
UpdateUserInfo *UserBasicInfo `json:"update_user_info,omitempty"`
Collected bool `json:"collected"`
@ -60,12 +60,12 @@ type AnswerInfo struct {
type AdminAnswerInfo struct {
ID string `json:"id"`
QuestionId string `json:"question_id"`
QuestionID string `json:"question_id"`
Description string `json:"description"`
CreateTime int64 `json:"create_time"`
UpdateTime int64 `json:"update_time"`
Adopted int `json:"adopted"`
UserId string `json:"-" `
UserID string `json:"-" `
UserInfo *UserBasicInfo `json:"user_info"`
VoteCount int `json:"vote_count"`
QuestionInfo struct {

View File

@ -3,8 +3,8 @@ package schema
import "time"
const (
CG_DEFAULT = 1
CG_DIY = 2
CGDefault = 1
CGDIY = 2
)
// CollectionSwitchReq switch collection request

View File

@ -2,7 +2,7 @@ package schema
const (
ForbiddenReasonTypeInactive = "inactive"
ForbiddenReasonTypeUrlExpired = "url_expired"
ForbiddenReasonTypeURLExpired = "url_expired"
ForbiddenReasonTypeUserSuspended = "suspended"
)

View File

@ -5,12 +5,11 @@ type RemoveQuestionReq struct {
// question id
ID string `validate:"required" comment:"question id" json:"id"`
UserID string `json:"-" ` // user_id
}
type CloseQuestionReq struct {
ID string `validate:"required" comment:"question id" json:"id"`
UserId string `json:"-" ` // user_id
UserID string `json:"-" ` // user_id
CloseType int `json:"close_type" ` // close_type
CloseMsg string `json:"close_msg" ` // close_type
}
@ -26,7 +25,7 @@ type QuestionAdd struct {
// content
Content string `validate:"required,gte=6,lte=65535" json:"content"`
// html
Html string `validate:"required,gte=6,lte=65535" json:"html"`
HTML string `validate:"required,gte=6,lte=65535" json:"html"`
// tags
Tags []*TagItem `validate:"required,dive" json:"tags"`
// user id
@ -41,7 +40,7 @@ type QuestionUpdate struct {
// content
Content string `validate:"required,gte=6,lte=65535" json:"content"`
// html
Html string `validate:"required,gte=6,lte=65535" json:"html"`
HTML string `validate:"required,gte=6,lte=65535" json:"html"`
// tags
Tags []*TagItem `validate:"required,dive" json:"tags"`
// edit summary
@ -65,7 +64,7 @@ type QuestionInfo struct {
ID string `json:"id" `
Title string `json:"title" xorm:"title"` // title
Content string `json:"content" xorm:"content"` // content
Html string `json:"html" xorm:"html"` // html
HTML string `json:"html" xorm:"html"` // html
Tags []*TagResp `json:"tags" ` // tags
ViewCount int `json:"view_count" xorm:"view_count"` // view_count
UniqueViewCount int `json:"unique_view_count" xorm:"unique_view_count"` // unique_view_count
@ -73,15 +72,15 @@ type QuestionInfo struct {
AnswerCount int `json:"answer_count" xorm:"answer_count"` // answer count
CollectionCount int `json:"collection_count" xorm:"collection_count"` // collection count
FollowCount int `json:"follow_count" xorm:"follow_count"` // follow count
AcceptedAnswerId string `json:"accepted_answer_id" ` // accepted_answer_id
LastAnswerId string `json:"last_answer_id" ` // last_answer_id
AcceptedAnswerID string `json:"accepted_answer_id" ` // accepted_answer_id
LastAnswerID string `json:"last_answer_id" ` // last_answer_id
CreateTime int64 `json:"create_time" ` // create_time
UpdateTime int64 `json:"-"` // update_time
PostUpdateTime int64 `json:"update_time"`
QuestionUpdateTime int64 `json:"edit_time"`
Status int `json:"status"`
Operation *Operation `json:"operation,omitempty"`
UserId string `json:"-" `
UserID string `json:"-" `
UserInfo *UserBasicInfo `json:"user_info"`
UpdateUserInfo *UserBasicInfo `json:"update_user_info,omitempty"`
LastAnsweredUserInfo *UserBasicInfo `json:"last_answered_user_info,omitempty"`
@ -108,10 +107,10 @@ type AdminQuestionInfo struct {
}
type Operation struct {
Operation_Type string `json:"operation_type"`
Operation_Description string `json:"operation_description"`
Operation_Msg string `json:"operation_msg"`
Operation_Time int64 `json:"operation_time"`
OperationType string `json:"operation_type"`
OperationDescription string `json:"operation_description"`
OperationMsg string `json:"operation_msg"`
OperationTime int64 `json:"operation_time"`
}
type GetCloseTypeResp struct {
@ -151,26 +150,26 @@ type UserQuestionInfo struct {
AnswerCount int `json:"answer_count"`
CollectionCount int `json:"collection_count"`
CreateTime int `json:"create_time"`
AcceptedAnswerId string `json:"accepted_answer_id"`
AcceptedAnswerID string `json:"accepted_answer_id"`
Status string `json:"status"`
}
type QuestionSearch struct {
Page int `json:"page" form:"page"` //Query number of pages
PageSize int `json:"page_size" form:"page_size"` //Search page size
Order string `json:"order" form:"order"` //Search order by
//Tags []string `json:"tags" form:"tags"` //Search tag
Page int `json:"page" form:"page"` // Query number of pages
PageSize int `json:"page_size" form:"page_size"` // Search page size
Order string `json:"order" form:"order"` // Search order by
// Tags []string `json:"tags" form:"tags"` // Search tag
Tag string `json:"tag" form:"tag"` //Search tag
TagIDs []string `json:"-" form:"-"` //Search tag
UserName string `json:"username" form:"username"` //Search username
TagIDs []string `json:"-" form:"-"` // Search tag
UserName string `json:"username" form:"username"` // Search username
UserID string `json:"-" form:"-"`
}
type CmsQuestionSearch struct {
Page int `json:"page" form:"page"` //Query number of pages
PageSize int `json:"page_size" form:"page_size"` //Search page size
Page int `json:"page" form:"page"` // Query number of pages
PageSize int `json:"page_size" form:"page_size"` // Search page size
Status int `json:"-" form:"-"`
StatusStr string `json:"status" form:"status"` //Status 1 Available 2 closed 10 UserDeleted
StatusStr string `json:"status" form:"status"` // Status 1 Available 2 closed 10 UserDeleted
Query string `validate:"omitempty,gt=0,lte=100" json:"query" form:"query" ` //Query string
}

View File

@ -107,7 +107,7 @@ func (tr *GetTagPageResp) GetExcerpt() {
}
type TagChange struct {
ObjectId string `json:"object_id"` // object_id
ObjectID string `json:"object_id"` // object_id
Tags []*TagItem `json:"tags"` // tags name
// user id
UserID string `json:"-"`

View File

@ -56,7 +56,7 @@ type GetUserResp struct {
// bio markdown
Bio string `json:"bio"`
// bio html
BioHtml string `json:"bio_html"`
BioHTML string `json:"bio_html"`
// website
Website string `json:"website"`
// location
@ -157,7 +157,7 @@ type GetOtherUserInfoByUsernameResp struct {
// bio markdown
Bio string `json:"bio"`
// bio html
BioHtml string `json:"bio_html"`
BioHTML string `json:"bio_html"`
// website
Website string `json:"website"`
// location
@ -192,20 +192,19 @@ func (r *GetOtherUserInfoByUsernameResp) GetFromUserEntity(userInfo *entity.User
r.StatusMsg = statusMsgShow
}
}
}
const (
Mail_State_Pass = 1
Mail_State_Verifi = 2
MailStatePass = 1
MailStateVerifi = 2
Notice_Status_On = 1
Notice_Status_Off = 2
NoticeStatusOn = 1
NoticeStatusOff = 2
//ActionRecord ReportType
ActionRecord_Type_Login = "login"
ActionRecord_Type_Email = "e_mail"
ActionRecord_Type_Find_Pass = "find_pass"
// ActionRecord ReportType
ActionRecordTypeLogin = "login"
ActionRecordTypeEmail = "e_mail"
ActionRecordTypeFindPass = "find_pass"
)
var UserStatusShow = map[int]string{
@ -213,6 +212,7 @@ var UserStatusShow = map[int]string{
9: "forbidden",
10: "deleted",
}
var UserStatusShowMsg = map[int]string{
1: "",
9: "<strong>This user was suspended forever.</strong> This user doesnt meet a community guideline.",
@ -253,7 +253,7 @@ func (u *UserRegisterReq) Check() (errField *validator.ErrorField, err error) {
// UserModifyPassWordRequest
type UserModifyPassWordRequest struct {
UserId string `json:"-" ` // user_id
UserID string `json:"-" ` // user_id
OldPass string `json:"old_pass" ` // old password
Pass string `json:"pass" ` // password
}
@ -280,13 +280,13 @@ type UpdateInfoRequest struct {
// bio
Bio string `validate:"omitempty,gt=0,lte=4096" json:"bio"`
// bio
BioHtml string `validate:"omitempty,gt=0,lte=4096" json:"bio_html"`
BioHTML string `validate:"omitempty,gt=0,lte=4096" json:"bio_html"`
// website
Website string `validate:"omitempty,gt=0,lte=500" json:"website"`
// location
Location string `validate:"omitempty,gt=0,lte=100" json:"location"`
// user id
UserId string `json:"-" `
UserID string `json:"-" `
}
type AvatarInfo struct {
@ -335,7 +335,7 @@ func (u *UserRePassWordRequest) Check() (errField *validator.ErrorField, err err
}
type UserNoticeSetRequest struct {
UserId string `json:"-" ` // user_id
UserID string `json:"-" ` // user_id
NoticeSwitch bool `json:"notice_switch" `
}
@ -346,7 +346,7 @@ type UserNoticeSetResp struct {
type ActionRecordReq struct {
// action
Action string `validate:"required,oneof=login e_mail find_pass" form:"action"`
Ip string `json:"-"`
IP string `json:"-"`
}
type ActionRecordResp struct {
@ -363,7 +363,7 @@ type UserBasicInfo struct {
Avatar string `json:"avatar" ` // avatar
Website string `json:"website" ` // website
Location string `json:"location" ` // location
IpInfo string `json:"ip_info"` // ip info
IPInfo string `json:"ip_info"` // ip info
Status string `json:"status"` // status
}

View File

@ -36,7 +36,7 @@ func NewCaptchaService(captchaRepo CaptchaRepo) *CaptchaService {
// ActionRecord action record
func (cs *CaptchaService) ActionRecord(ctx context.Context, req *schema.ActionRecordReq) (resp *schema.ActionRecordResp, err error) {
resp = &schema.ActionRecordResp{}
num, err := cs.captchaRepo.GetActionType(ctx, req.Ip, req.Action)
num, err := cs.captchaRepo.GetActionType(ctx, req.IP, req.Action)
if err != nil {
num = 0
}
@ -51,7 +51,8 @@ func (cs *CaptchaService) ActionRecord(ctx context.Context, req *schema.ActionRe
// ActionRecordVerifyCaptcha
// Verify that you need to enter a CAPTCHA, and that the CAPTCHA is correct
func (cs *CaptchaService) ActionRecordVerifyCaptcha(
ctx context.Context, actionType string, ip string, id string, VerifyValue string) bool {
ctx context.Context, actionType string, ip string, id string, VerifyValue string,
) bool {
num, cahceErr := cs.captchaRepo.GetActionType(ctx, ip, actionType)
if cahceErr != nil {
return true

View File

@ -14,9 +14,9 @@ type AnswerRepo interface {
GetAnswer(ctx context.Context, id string) (answer *entity.Answer, exist bool, err error)
GetAnswerList(ctx context.Context, answer *entity.Answer) (answerList []*entity.Answer, err error)
GetAnswerPage(ctx context.Context, page, pageSize int, answer *entity.Answer) (answerList []*entity.Answer, total int64, err error)
UpdateAdopted(ctx context.Context, id string, questionId string) error
UpdateAdopted(ctx context.Context, id string, questionID string) error
GetByID(ctx context.Context, id string) (*entity.Answer, bool, error)
GetByUserIdQuestionId(ctx context.Context, userId string, questionId string) (*entity.Answer, bool, error)
GetByUserIDQuestionID(ctx context.Context, userID string, questionID string) (*entity.Answer, bool, error)
SearchList(ctx context.Context, search *entity.AnswerSearch) ([]*entity.Answer, int64, error)
CmsSearchList(ctx context.Context, search *entity.CmsAnswerSearch) ([]*entity.Answer, int64, error)
UpdateAnswerStatus(ctx context.Context, answer *entity.Answer) (err error)
@ -33,8 +33,8 @@ func NewAnswerCommon(answerRepo AnswerRepo) *AnswerCommon {
}
}
func (as *AnswerCommon) SearchAnswered(ctx context.Context, userId, questionId string) (bool, error) {
_, has, err := as.answerRepo.GetByUserIdQuestionId(ctx, userId, questionId)
func (as *AnswerCommon) SearchAnswered(ctx context.Context, userID, questionID string) (bool, error) {
_, has, err := as.answerRepo.GetByUserIDQuestionID(ctx, userID, questionID)
if err != nil {
return has, err
}
@ -59,26 +59,26 @@ func (as *AnswerCommon) Search(ctx context.Context, search *entity.AnswerSearch)
func (as *AnswerCommon) ShowFormat(ctx context.Context, data *entity.Answer) *schema.AnswerInfo {
info := schema.AnswerInfo{}
info.ID = data.ID
info.QuestionId = data.QuestionID
info.QuestionID = data.QuestionID
info.Content = data.OriginalText
info.Html = data.ParsedText
info.HTML = data.ParsedText
info.Adopted = data.Adopted
info.VoteCount = data.VoteCount
info.CreateTime = data.CreatedAt.Unix()
info.UpdateTime = data.UpdatedAt.Unix()
info.UserId = data.UserID
info.UserID = data.UserID
return &info
}
func (as *AnswerCommon) AdminShowFormat(ctx context.Context, data *entity.Answer) *schema.AdminAnswerInfo {
info := schema.AdminAnswerInfo{}
info.ID = data.ID
info.QuestionId = data.QuestionID
info.QuestionID = data.QuestionID
info.Description = data.ParsedText
info.Adopted = data.Adopted
info.VoteCount = data.VoteCount
info.CreateTime = data.CreatedAt.Unix()
info.UpdateTime = data.UpdatedAt.Unix()
info.UserId = data.UserID
info.UserID = data.UserID
return &info
}

View File

@ -74,7 +74,7 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, id string) (err error
return nil
}
//user add question count
// user add question count
err = as.questionCommon.UpdateAnswerCount(ctx, answerInfo.QuestionID, -1)
if err != nil {
log.Error("IncreaseAnswerCount error", err.Error())
@ -97,7 +97,7 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, id string) (err error
}
func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) (string, error) {
questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionId)
questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID)
if err != nil {
return "", err
}
@ -108,24 +108,24 @@ func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) (
insertData := new(entity.Answer)
insertData.UserID = req.UserID
insertData.OriginalText = req.Content
insertData.ParsedText = req.Html
insertData.Adopted = schema.Answer_Adopted_Failed
insertData.QuestionID = req.QuestionId
insertData.ParsedText = req.HTML
insertData.Adopted = schema.AnswerAdoptedFailed
insertData.QuestionID = req.QuestionID
insertData.RevisionID = "0"
insertData.Status = entity.AnswerStatusAvailable
insertData.UpdatedAt = now
if err := as.answerRepo.AddAnswer(ctx, insertData); err != nil {
if err = as.answerRepo.AddAnswer(ctx, insertData); err != nil {
return "", err
}
err = as.questionCommon.UpdateAnswerCount(ctx, req.QuestionId, 1)
err = as.questionCommon.UpdateAnswerCount(ctx, req.QuestionID, 1)
if err != nil {
log.Error("IncreaseAnswerCount error", err.Error())
}
err = as.questionCommon.UpdateLastAnswer(ctx, req.QuestionId, insertData.ID)
err = as.questionCommon.UpdateLastAnswer(ctx, req.QuestionID, insertData.ID)
if err != nil {
log.Error("UpdateLastAnswer error", err.Error())
}
err = as.questionCommon.UpdataPostTime(ctx, req.QuestionId)
err = as.questionCommon.UpdataPostTime(ctx, req.QuestionID)
if err != nil {
return insertData.ID, err
}
@ -140,8 +140,8 @@ func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) (
ObjectID: insertData.ID,
Title: "",
}
InfoJson, _ := json.Marshal(insertData)
revisionDTO.Content = string(InfoJson)
infoJSON, _ := json.Marshal(insertData)
revisionDTO.Content = string(infoJSON)
err = as.revisionService.AddRevision(ctx, revisionDTO, true)
if err != nil {
return insertData.ID, err
@ -151,7 +151,7 @@ func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) (
}
func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq) (string, error) {
questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionId)
questionInfo, exist, err := as.questionRepo.GetQuestion(ctx, req.QuestionID)
if err != nil {
return "", err
}
@ -161,15 +161,15 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
now := time.Now()
insertData := new(entity.Answer)
insertData.ID = req.ID
insertData.QuestionID = req.QuestionId
insertData.QuestionID = req.QuestionID
insertData.UserID = req.UserID
insertData.OriginalText = req.Content
insertData.ParsedText = req.Html
insertData.ParsedText = req.HTML
insertData.UpdatedAt = now
if err := as.answerRepo.UpdateAnswer(ctx, insertData, []string{"original_text", "parsed_text", "update_time"}); err != nil {
if err = as.answerRepo.UpdateAnswer(ctx, insertData, []string{"original_text", "parsed_text", "update_time"}); err != nil {
return "", err
}
err = as.questionCommon.UpdataPostTime(ctx, req.QuestionId)
err = as.questionCommon.UpdataPostTime(ctx, req.QuestionID)
if err != nil {
return insertData.ID, err
}
@ -179,8 +179,8 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
Title: "",
Log: req.EditSummary,
}
InfoJson, _ := json.Marshal(insertData)
revisionDTO.Content = string(InfoJson)
infoJSON, _ := json.Marshal(insertData)
revisionDTO.Content = string(infoJSON)
err = as.revisionService.AddRevision(ctx, revisionDTO, true)
if err != nil {
return insertData.ID, err
@ -228,7 +228,7 @@ func (as *AnswerService) UpdateAdopted(ctx context.Context, req *schema.AnswerAd
var oldAnswerInfo *entity.Answer
if len(questionInfo.AcceptedAnswerID) > 0 && questionInfo.AcceptedAnswerID != "0" {
oldAnswerInfo, exist, err = as.answerRepo.GetByID(ctx, questionInfo.AcceptedAnswerID)
oldAnswerInfo, _, err = as.answerRepo.GetByID(ctx, questionInfo.AcceptedAnswerID)
if err != nil {
return err
}
@ -249,8 +249,8 @@ func (as *AnswerService) UpdateAdopted(ctx context.Context, req *schema.AnswerAd
}
func (as *AnswerService) updateAnswerRank(ctx context.Context, userID string,
questionInfo *entity.Question, newAnswerInfo *entity.Answer, oldAnswerInfo *entity.Answer) {
questionInfo *entity.Question, newAnswerInfo *entity.Answer, oldAnswerInfo *entity.Answer,
) {
// if this question is already been answered, should cancel old answer rank
if oldAnswerInfo != nil {
err := as.answerActivityService.CancelAcceptAnswer(
@ -266,21 +266,20 @@ func (as *AnswerService) updateAnswerRank(ctx context.Context, userID string,
log.Error(err)
}
}
}
func (as *AnswerService) Get(ctx context.Context, answerID, loginUserId string) (*schema.AnswerInfo, *schema.QuestionInfo, bool, error) {
func (as *AnswerService) Get(ctx context.Context, answerID, loginUserID string) (*schema.AnswerInfo, *schema.QuestionInfo, bool, error) {
answerInfo, has, err := as.answerRepo.GetByID(ctx, answerID)
if err != nil {
return nil, nil, has, err
}
info := as.ShowFormat(ctx, answerInfo)
//todo questionFunc
questionInfo, err := as.questionCommon.Info(ctx, answerInfo.QuestionID, loginUserId)
// todo questionFunc
questionInfo, err := as.questionCommon.Info(ctx, answerInfo.QuestionID, loginUserID)
if err != nil {
return nil, nil, has, err
}
//todo UserFunc
// todo UserFunc
userinfo, has, err := as.userCommon.GetUserBasicInfoByID(ctx, answerInfo.UserID)
if err != nil {
return nil, nil, has, err
@ -290,13 +289,13 @@ func (as *AnswerService) Get(ctx context.Context, answerID, loginUserId string)
info.UpdateUserInfo = userinfo
}
if loginUserId == "" {
if loginUserID == "" {
return info, questionInfo, has, nil
}
info.VoteStatus = as.voteRepo.GetVoteStatus(ctx, answerID, loginUserId)
info.VoteStatus = as.voteRepo.GetVoteStatus(ctx, answerID, loginUserID)
CollectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, loginUserId, []string{answerInfo.ID})
CollectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, loginUserID, []string{answerInfo.ID})
if err != nil {
log.Error("CollectionFunc.SearchObjectCollected error", err)
}
@ -348,7 +347,7 @@ func (as *AnswerService) AdminSetAnswerStatus(ctx context.Context, answerID stri
func (as *AnswerService) SearchList(ctx context.Context, search *schema.AnswerList) ([]*schema.AnswerInfo, int64, error) {
list := make([]*schema.AnswerInfo, 0)
dbSearch := entity.AnswerSearch{}
dbSearch.QuestionID = search.QuestionId
dbSearch.QuestionID = search.QuestionID
dbSearch.Page = search.Page
dbSearch.PageSize = search.PageSize
dbSearch.Order = search.Order
@ -363,7 +362,7 @@ func (as *AnswerService) SearchList(ctx context.Context, search *schema.AnswerLi
return AnswerList, count, nil
}
func (as *AnswerService) SearchFormatInfo(ctx context.Context, dblist []*entity.Answer, loginUserId string) ([]*schema.AnswerInfo, error) {
func (as *AnswerService) SearchFormatInfo(ctx context.Context, dblist []*entity.Answer, loginUserID string) ([]*schema.AnswerInfo, error) {
list := make([]*schema.AnswerInfo, 0)
objectIds := make([]string, 0)
userIds := make([]string, 0)
@ -372,9 +371,9 @@ func (as *AnswerService) SearchFormatInfo(ctx context.Context, dblist []*entity.
list = append(list, item)
objectIds = append(objectIds, dbitem.ID)
userIds = append(userIds, dbitem.UserID)
if loginUserId != "" {
//item.VoteStatus = as.activityFunc.GetVoteStatus(ctx, item.TagID, loginUserId)
item.VoteStatus = as.voteRepo.GetVoteStatus(ctx, item.ID, loginUserId)
if loginUserID != "" {
// item.VoteStatus = as.activityFunc.GetVoteStatus(ctx, item.TagID, loginUserId)
item.VoteStatus = as.voteRepo.GetVoteStatus(ctx, item.ID, loginUserID)
}
}
userInfoMap, err := as.userCommon.BatchUserBasicInfoByID(ctx, userIds)
@ -382,18 +381,18 @@ func (as *AnswerService) SearchFormatInfo(ctx context.Context, dblist []*entity.
return list, err
}
for _, item := range list {
_, ok := userInfoMap[item.UserId]
_, ok := userInfoMap[item.UserID]
if ok {
item.UserInfo = userInfoMap[item.UserId]
item.UpdateUserInfo = userInfoMap[item.UserId]
item.UserInfo = userInfoMap[item.UserID]
item.UpdateUserInfo = userInfoMap[item.UserID]
}
}
if loginUserId == "" {
if loginUserID == "" {
return list, nil
}
CollectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, loginUserId, objectIds)
CollectedMap, err := as.collectionCommon.SearchObjectCollected(ctx, loginUserID, objectIds)
if err != nil {
log.Error("CollectionFunc.SearchObjectCollected error", err)
}
@ -406,7 +405,7 @@ func (as *AnswerService) SearchFormatInfo(ctx context.Context, dblist []*entity.
}
for _, item := range list {
item.MemberActions = permission.GetAnswerPermission(loginUserId, item.UserId)
item.MemberActions = permission.GetAnswerPermission(loginUserID, item.UserID)
}
return list, nil

View File

@ -17,7 +17,7 @@ type CollectionGroupRepo interface {
UpdateCollectionGroup(ctx context.Context, collectionGroup *entity.CollectionGroup, cols []string) (err error)
GetCollectionGroup(ctx context.Context, id string) (collectionGroup *entity.CollectionGroup, exist bool, err error)
GetCollectionGroupPage(ctx context.Context, page, pageSize int, collectionGroup *entity.CollectionGroup) (collectionGroupList []*entity.CollectionGroup, total int64, err error)
GetDefaultID(ctx context.Context, userId string) (collectionGroup *entity.CollectionGroup, has bool, err error)
GetDefaultID(ctx context.Context, userID string) (collectionGroup *entity.CollectionGroup, has bool, err error)
}
// CollectionGroupService user service

View File

@ -23,7 +23,6 @@ func NewCollectionService(
collectionRepo collectioncommon.CollectionRepo,
collectionGroupRepo CollectionGroupRepo,
questionCommon *questioncommon.QuestionCommon,
) *CollectionService {
return &CollectionService{
collectionRepo: collectionRepo,
@ -31,6 +30,7 @@ func NewCollectionService(
questionCommon: questionCommon,
}
}
func (cs *CollectionService) CollectionSwitch(ctx context.Context, dto *schema.CollectionSwitchDTO) (resp *schema.CollectionSwitchResp, err error) {
resp = &schema.CollectionSwitchResp{}
dbData, has, err := cs.collectionRepo.GetOneByObjectIDAndUser(ctx, dto.UserID, dto.ObjectID)
@ -46,7 +46,8 @@ func (cs *CollectionService) CollectionSwitch(ctx context.Context, dto *schema.C
if err != nil {
log.Error("UpdateCollectionCount", err.Error())
}
count, err := cs.objectCollectionCount(ctx, dto.ObjectID)
var count int64
count, err = cs.objectCollectionCount(ctx, dto.ObjectID)
if err != nil {
return resp, err
}
@ -56,12 +57,17 @@ func (cs *CollectionService) CollectionSwitch(ctx context.Context, dto *schema.C
}
if dto.GroupID == "" || dto.GroupID == "0" {
defaultGroup, has, err := cs.collectionGroupRepo.GetDefaultID(ctx, dto.UserID)
var (
defaultGroup *entity.CollectionGroup
has bool
)
defaultGroup, has, err = cs.collectionGroupRepo.GetDefaultID(ctx, dto.UserID)
if err != nil {
return nil, err
}
if !has {
dbdefaultGroup, err := cs.collectionGroupRepo.AddCollectionDefaultGroup(ctx, dto.UserID)
var dbdefaultGroup *entity.CollectionGroup
dbdefaultGroup, err = cs.collectionGroupRepo.AddCollectionDefaultGroup(ctx, dto.UserID)
if err != nil {
return nil, err
}
@ -93,8 +99,8 @@ func (cs *CollectionService) CollectionSwitch(ctx context.Context, dto *schema.C
return
}
func (cs *CollectionService) objectCollectionCount(ctx context.Context, objectId string) (int64, error) {
count, err := cs.collectionRepo.CountByObjectID(ctx, objectId)
func (cs *CollectionService) objectCollectionCount(ctx context.Context, objectID string) (int64, error) {
count, err := cs.collectionRepo.CountByObjectID(ctx, objectID)
return count, err
}
@ -108,12 +114,16 @@ func (cs *CollectionService) add(ctx context.Context, collection *entity.Collect
}
if collection.UserCollectionGroupID == "" || collection.UserCollectionGroupID == "0" {
defaultGroup, has, err := cs.collectionGroupRepo.GetDefaultID(ctx, collection.UserID)
var (
defaultGroup *entity.CollectionGroup
has bool
)
defaultGroup, has, err = cs.collectionGroupRepo.GetDefaultID(ctx, collection.UserID)
if err != nil {
return err
}
if !has {
defaultGroup, err := cs.collectionGroupRepo.AddCollectionDefaultGroup(ctx, collection.UserID)
defaultGroup, err = cs.collectionGroupRepo.AddCollectionDefaultGroup(ctx, collection.UserID)
if err != nil {
return err
}

View File

@ -31,9 +31,9 @@ type QuestionRepo interface {
SearchList(ctx context.Context, search *schema.QuestionSearch) ([]*entity.QuestionTag, int64, error)
UpdateQuestionStatus(ctx context.Context, question *entity.Question) (err error)
SearchByTitleLike(ctx context.Context, title string) (questionList []*entity.Question, err error)
UpdatePvCount(ctx context.Context, questionId string) (err error)
UpdateAnswerCount(ctx context.Context, questionId string, num int) (err error)
UpdateCollectionCount(ctx context.Context, questionId string, num int) (err error)
UpdatePvCount(ctx context.Context, questionID string) (err error)
UpdateAnswerCount(ctx context.Context, questionID string, num int) (err error)
UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error)
UpdateAccepted(ctx context.Context, question *entity.Question) (err error)
UpdateLastAnswer(ctx context.Context, question *entity.Question) (err error)
FindByID(ctx context.Context, id []string) (questionList []*entity.Question, err error)
@ -64,7 +64,6 @@ func NewQuestionCommon(questionRepo QuestionRepo,
answerCommon *answercommon.AnswerCommon,
metaService *meta.MetaService,
configRepo config.ConfigRepo,
) *QuestionCommon {
return &QuestionCommon{
questionRepo: questionRepo,
@ -80,42 +79,44 @@ func NewQuestionCommon(questionRepo QuestionRepo,
}
}
func (qs *QuestionCommon) UpdataPv(ctx context.Context, questionId string) error {
return qs.questionRepo.UpdatePvCount(ctx, questionId)
}
func (qs *QuestionCommon) UpdateAnswerCount(ctx context.Context, questionId string, num int) error {
return qs.questionRepo.UpdateAnswerCount(ctx, questionId, num)
}
func (qs *QuestionCommon) UpdateCollectionCount(ctx context.Context, questionId string, num int) error {
return qs.questionRepo.UpdateCollectionCount(ctx, questionId, num)
func (qs *QuestionCommon) UpdataPv(ctx context.Context, questionID string) error {
return qs.questionRepo.UpdatePvCount(ctx, questionID)
}
func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionId, AnswerId string) error {
func (qs *QuestionCommon) UpdateAnswerCount(ctx context.Context, questionID string, num int) error {
return qs.questionRepo.UpdateAnswerCount(ctx, questionID, num)
}
func (qs *QuestionCommon) UpdateCollectionCount(ctx context.Context, questionID string, num int) error {
return qs.questionRepo.UpdateCollectionCount(ctx, questionID, num)
}
func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionID, AnswerID string) error {
question := &entity.Question{}
question.ID = questionId
question.AcceptedAnswerID = AnswerId
question.ID = questionID
question.AcceptedAnswerID = AnswerID
return qs.questionRepo.UpdateAccepted(ctx, question)
}
func (qs *QuestionCommon) UpdateLastAnswer(ctx context.Context, questionId, AnswerId string) error {
func (qs *QuestionCommon) UpdateLastAnswer(ctx context.Context, questionID, AnswerID string) error {
question := &entity.Question{}
question.ID = questionId
question.LastAnswerID = AnswerId
question.ID = questionID
question.LastAnswerID = AnswerID
return qs.questionRepo.UpdateLastAnswer(ctx, question)
}
func (qs *QuestionCommon) UpdataPostTime(ctx context.Context, questionId string) error {
func (qs *QuestionCommon) UpdataPostTime(ctx context.Context, questionID string) error {
questioninfo := &entity.Question{}
now := time.Now()
questioninfo.ID = questionId
questioninfo.ID = questionID
questioninfo.PostUpdateTime = now
return qs.questionRepo.UpdateQuestion(ctx, questioninfo, []string{"post_update_time"})
}
func (qs *QuestionCommon) FindInfoByID(ctx context.Context, questionIds []string, loginUserID string) (map[string]*schema.QuestionInfo, error) {
func (qs *QuestionCommon) FindInfoByID(ctx context.Context, questionIDs []string, loginUserID string) (map[string]*schema.QuestionInfo, error) {
list := make(map[string]*schema.QuestionInfo)
listAddTag := make([]*entity.QuestionTag, 0)
questionList, err := qs.questionRepo.FindByID(ctx, questionIds)
questionList, err := qs.questionRepo.FindByID(ctx, questionIDs)
if err != nil {
return list, err
}
@ -134,8 +135,8 @@ func (qs *QuestionCommon) FindInfoByID(ctx context.Context, questionIds []string
return list, nil
}
func (qs *QuestionCommon) Info(ctx context.Context, questionId string, loginUserID string) (showinfo *schema.QuestionInfo, err error) {
dbinfo, has, err := qs.questionRepo.GetQuestion(ctx, questionId)
func (qs *QuestionCommon) Info(ctx context.Context, questionID string, loginUserID string) (showinfo *schema.QuestionInfo, err error) {
dbinfo, has, err := qs.questionRepo.GetQuestion(ctx, questionID)
if err != nil {
return showinfo, err
}
@ -145,13 +146,14 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionId string, loginUser
showinfo = qs.ShowFormat(ctx, dbinfo)
if showinfo.Status == 2 {
metainfo, err := qs.metaService.GetMetaByObjectIdAndKey(ctx, dbinfo.ID, entity.QuestionCloseReasonKey)
var metainfo *entity.Meta
metainfo, err = qs.metaService.GetMetaByObjectIdAndKey(ctx, dbinfo.ID, entity.QuestionCloseReasonKey)
if err != nil {
log.Error(err)
} else {
//metainfo.Value
// metainfo.Value
closemsg := &schema.CloseQuestionMeta{}
err := json.Unmarshal([]byte(metainfo.Value), closemsg)
err = json.Unmarshal([]byte(metainfo.Value), closemsg)
if err != nil {
log.Error("json.Unmarshal CloseQuestionMeta error", err.Error())
} else {
@ -161,10 +163,10 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionId string, loginUser
log.Error("json.Unmarshal QuestionCloseJson error", err.Error())
} else {
operation := &schema.Operation{}
operation.Operation_Type = closeinfo.Name
operation.Operation_Description = closeinfo.Description
operation.Operation_Msg = closemsg.CloseMsg
operation.Operation_Time = metainfo.CreatedAt.Unix()
operation.OperationType = closeinfo.Name
operation.OperationDescription = closeinfo.Description
operation.OperationMsg = closemsg.CloseMsg
operation.OperationTime = metainfo.CreatedAt.Unix()
showinfo.Operation = operation
}
@ -173,7 +175,7 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionId string, loginUser
}
}
tagmap, err := qs.tagCommon.GetObjectTag(ctx, questionId)
tagmap, err := qs.tagCommon.GetObjectTag(ctx, questionID)
if err != nil {
return showinfo, err
}
@ -193,10 +195,10 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionId string, loginUser
return showinfo, nil
}
showinfo.VoteStatus = qs.voteRepo.GetVoteStatus(ctx, questionId, loginUserID)
showinfo.VoteStatus = qs.voteRepo.GetVoteStatus(ctx, questionID, loginUserID)
// // check is followed
isFollowed, _ := qs.followCommon.IsFollowed(loginUserID, questionId)
isFollowed, _ := qs.followCommon.IsFollowed(loginUserID, questionID)
showinfo.IsFollowed = isFollowed
has, err = qs.AnswerCommon.SearchAnswered(ctx, loginUserID, dbinfo.ID)
@ -205,7 +207,7 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionId string, loginUser
}
showinfo.Answered = has
//login user Collected information
// login user Collected information
CollectedMap, err := qs.collectionCommon.SearchObjectCollected(ctx, loginUserID, []string{dbinfo.ID})
if err != nil {
@ -245,11 +247,11 @@ func (qs *QuestionCommon) ListFormat(ctx context.Context, questionList []*entity
if ok {
item.Tags = tagsMap[item.ID]
}
_, ok = userInfoMap[item.UserId]
_, ok = userInfoMap[item.UserID]
if ok {
item.UserInfo = userInfoMap[item.UserId]
item.UpdateUserInfo = userInfoMap[item.UserId]
item.LastAnsweredUserInfo = userInfoMap[item.UserId]
item.UserInfo = userInfoMap[item.UserID]
item.UpdateUserInfo = userInfoMap[item.UserID]
item.LastAnsweredUserInfo = userInfoMap[item.UserID]
}
}
@ -286,7 +288,7 @@ func (qs *QuestionCommon) RemoveQuestion(ctx context.Context, req *schema.Remove
return err
}
//user add question count
// user add question count
err = qs.userCommon.UpdateQuestionCount(ctx, questionInfo.UserID, -1)
if err != nil {
log.Error("user UpdateQuestionCount error", err.Error())
@ -332,7 +334,7 @@ func (as *QuestionCommon) RemoveAnswer(ctx context.Context, id string) (err erro
return nil
}
//user add question count
// user add question count
err = as.UpdateAnswerCount(ctx, answerinfo.QuestionID, -1)
if err != nil {
@ -356,21 +358,21 @@ func (qs *QuestionCommon) ShowFormat(ctx context.Context, data *entity.Question)
info.ID = data.ID
info.Title = data.Title
info.Content = data.OriginalText
info.Html = data.ParsedText
info.HTML = data.ParsedText
info.ViewCount = data.ViewCount
info.UniqueViewCount = data.UniqueViewCount
info.VoteCount = data.VoteCount
info.AnswerCount = data.AnswerCount
info.CollectionCount = data.CollectionCount
info.FollowCount = data.FollowCount
info.AcceptedAnswerId = data.AcceptedAnswerID
info.LastAnswerId = data.LastAnswerID
info.AcceptedAnswerID = data.AcceptedAnswerID
info.LastAnswerID = data.LastAnswerID
info.CreateTime = data.CreatedAt.Unix()
info.UpdateTime = data.UpdatedAt.Unix()
info.PostUpdateTime = data.PostUpdateTime.Unix()
info.QuestionUpdateTime = data.UpdatedAt.Unix()
info.Status = data.Status
info.UserId = data.UserID
info.UserID = data.UserID
info.Tags = make([]*schema.TagResp, 0)
return &info
}

View File

@ -89,9 +89,10 @@ func (qs *QuestionService) CloseQuestion(ctx context.Context, req *schema.CloseQ
// CloseMsgList list close question condition
func (qs *QuestionService) CloseMsgList(ctx context.Context, lang i18n.Language) (
resp []*schema.GetCloseTypeResp, err error) {
resp []*schema.GetCloseTypeResp, err error,
) {
resp = make([]*schema.GetCloseTypeResp, 0)
err = json.Unmarshal([]byte(constant.QuestionCloseJson), &resp)
err = json.Unmarshal([]byte(constant.QuestionCloseJSON), &resp)
if err != nil {
return nil, errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
}
@ -110,7 +111,7 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question
question.UserID = req.UserID
question.Title = req.Title
question.OriginalText = req.Content
question.ParsedText = req.Html
question.ParsedText = req.HTML
question.AcceptedAnswerID = "0"
question.LastAnswerID = "0"
question.PostUpdateTime = now
@ -123,7 +124,7 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question
return
}
objectTagData := schema.TagChange{}
objectTagData.ObjectId = question.ID
objectTagData.ObjectID = question.ID
objectTagData.Tags = req.Tags
objectTagData.UserID = req.UserID
err = qs.ChangeTag(ctx, &objectTagData)
@ -136,14 +137,14 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question
ObjectID: question.ID,
Title: "",
}
InfoJson, _ := json.Marshal(question)
revisionDTO.Content = string(InfoJson)
infoJSON, _ := json.Marshal(question)
revisionDTO.Content = string(infoJSON)
err = qs.revisionService.AddRevision(ctx, revisionDTO, true)
if err != nil {
return
}
//user add question count
// user add question count
err = qs.userCommon.UpdateQuestionCount(ctx, question.UserID, 1)
if err != nil {
log.Error("user IncreaseQuestionCount error", err.Error())
@ -168,7 +169,7 @@ func (qs *QuestionService) RemoveQuestion(ctx context.Context, req *schema.Remov
return err
}
//user add question count
// user add question count
err = qs.userCommon.UpdateQuestionCount(ctx, questionInfo.UserID, -1)
if err != nil {
log.Error("user IncreaseQuestionCount error", err.Error())
@ -190,7 +191,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
question.UserID = req.UserID
question.Title = req.Title
question.OriginalText = req.Content
question.ParsedText = req.Html
question.ParsedText = req.HTML
question.ID = req.ID
question.UpdatedAt = now
dbinfo, has, err := qs.questionRepo.GetQuestion(ctx, question.ID)
@ -208,7 +209,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
return
}
objectTagData := schema.TagChange{}
objectTagData.ObjectId = question.ID
objectTagData.ObjectID = question.ID
objectTagData.Tags = req.Tags
objectTagData.UserID = req.UserID
err = qs.ChangeTag(ctx, &objectTagData)
@ -222,8 +223,8 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
Title: "",
Log: req.EditSummary,
}
InfoJson, _ := json.Marshal(question)
revisionDTO.Content = string(InfoJson)
infoJSON, _ := json.Marshal(question)
revisionDTO.Content = string(infoJSON)
err = qs.revisionService.AddRevision(ctx, revisionDTO, true)
if err != nil {
return
@ -246,7 +247,7 @@ func (qs *QuestionService) GetQuestion(ctx context.Context, id, loginUserID stri
}
}
question.MemberActions = permission.GetQuestionPermission(loginUserID, question.UserId)
question.MemberActions = permission.GetQuestionPermission(loginUserID, question.UserID)
return question, nil
}
@ -300,9 +301,9 @@ func (qs *QuestionService) SearchUserAnswerList(ctx context.Context, userName, o
answersearch.PageSize = pageSize
answersearch.Page = page
if order == "newest" {
answersearch.Order = entity.Answer_Search_OrderBy_Time
answersearch.Order = entity.AnswerSearchOrderByTime
} else {
answersearch.Order = entity.Answer_Search_OrderBy_Default
answersearch.Order = entity.AnswerSearchOrderByDefault
}
questionIDs := make([]string, 0)
answerList, count, err := qs.questioncommon.AnswerCommon.Search(ctx, answersearch)
@ -319,16 +320,16 @@ func (qs *QuestionService) SearchUserAnswerList(ctx context.Context, userName, o
return userAnswerlist, count, err
}
for _, item := range answerlist {
_, ok := questionMaps[item.QuestionId]
_, ok := questionMaps[item.QuestionID]
if ok {
item.QuestionInfo = questionMaps[item.QuestionId]
item.QuestionInfo = questionMaps[item.QuestionID]
}
}
for _, item := range answerlist {
info := &schema.UserAnswerInfo{}
_ = copier.Copy(info, item)
info.AnswerID = item.ID
info.QuestionID = item.QuestionId
info.QuestionID = item.QuestionID
userAnswerlist = append(userAnswerlist, info)
}
return userAnswerlist, count, nil
@ -366,7 +367,7 @@ func (qs *QuestionService) SearchUserCollectionList(ctx context.Context, page, p
questionMaps[id].LastAnsweredUserInfo = nil
questionMaps[id].UpdateUserInfo = nil
questionMaps[id].Content = ""
questionMaps[id].Html = ""
questionMaps[id].HTML = ""
list = append(list, questionMaps[id])
}
}
@ -399,7 +400,7 @@ func (qs *QuestionService) SearchUserTopList(ctx context.Context, userName strin
answersearch := &entity.AnswerSearch{}
answersearch.UserID = userinfo.ID
answersearch.PageSize = 5
answersearch.Order = entity.Answer_Search_OrderBy_Vote
answersearch.Order = entity.AnswerSearchOrderByVote
questionIDs := make([]string, 0)
answerList, _, err := qs.questioncommon.AnswerCommon.Search(ctx, answersearch)
if err != nil {
@ -415,9 +416,9 @@ func (qs *QuestionService) SearchUserTopList(ctx context.Context, userName strin
return userQuestionlist, userAnswerlist, err
}
for _, item := range answerlist {
_, ok := questionMaps[item.QuestionId]
_, ok := questionMaps[item.QuestionID]
if ok {
item.QuestionInfo = questionMaps[item.QuestionId]
item.QuestionInfo = questionMaps[item.QuestionID]
}
}
@ -431,7 +432,7 @@ func (qs *QuestionService) SearchUserTopList(ctx context.Context, userName strin
info := &schema.UserAnswerInfo{}
_ = copier.Copy(info, item)
info.AnswerID = item.ID
info.QuestionID = item.QuestionId
info.QuestionID = item.QuestionID
userAnswerlist = append(userAnswerlist, info)
}
@ -629,13 +630,13 @@ func (qs *QuestionService) CmsSearchAnswerList(ctx context.Context, search *enti
return answerlist, count, err
}
for _, item := range answerlist {
_, ok := questionMaps[item.QuestionId]
_, ok := questionMaps[item.QuestionID]
if ok {
item.QuestionInfo.Title = questionMaps[item.QuestionId].Title
item.QuestionInfo.Title = questionMaps[item.QuestionID].Title
}
_, ok = userInfoMap[item.UserId]
_, ok = userInfoMap[item.UserID]
if ok {
item.UserInfo = userInfoMap[item.UserId]
item.UserInfo = userInfoMap[item.UserID]
}
}
return answerlist, count, nil

View File

@ -24,7 +24,8 @@ type ReportService struct {
// NewReportService new report service
func NewReportService(reportRepo report_common.ReportRepo,
objectInfoService *object_info.ObjService) *ReportService {
objectInfoService *object_info.ObjService,
) *ReportService {
return &ReportService{
reportRepo: reportRepo,
objectInfoService: objectInfoService,
@ -58,15 +59,16 @@ func (rs *ReportService) AddReport(ctx context.Context, req *schema.AddReportReq
// GetReportTypeList get report list all
func (rs *ReportService) GetReportTypeList(ctx context.Context, lang i18n.Language, req *schema.GetReportListReq) (
resp []*schema.GetReportTypeResp, err error) {
resp []*schema.GetReportTypeResp, err error,
) {
resp = make([]*schema.GetReportTypeResp, 0)
switch req.Source {
case constant.QuestionObjectType:
err = json.Unmarshal([]byte(constant.QuestionReportJson), &resp)
err = json.Unmarshal([]byte(constant.QuestionReportJSON), &resp)
case constant.AnswerObjectType:
err = json.Unmarshal([]byte(constant.AnswerReportJson), &resp)
err = json.Unmarshal([]byte(constant.AnswerReportJSON), &resp)
case constant.CommentObjectType:
err = json.Unmarshal([]byte(constant.CommentReportJson), &resp)
err = json.Unmarshal([]byte(constant.CommentReportJSON), &resp)
}
if err != nil {
err = errors.BadRequest(reason.UnknownError)

View File

@ -64,7 +64,7 @@ func (s *SiteInfoService) SaveSiteGeneral(ctx context.Context, req schema.SiteGe
siteType = "general"
content []byte
)
content, err = json.Marshal(req)
content, _ = json.Marshal(req)
data := entity.SiteInfo{
Type: siteType,
@ -107,7 +107,7 @@ func (s *SiteInfoService) SaveSiteInterface(ctx context.Context, req schema.Site
return
}
content, err = json.Marshal(req)
content, _ = json.Marshal(req)
data := entity.SiteInfo{
Type: siteType,
@ -120,7 +120,8 @@ func (s *SiteInfoService) SaveSiteInterface(ctx context.Context, req schema.Site
// GetSMTPConfig get smtp config
func (s *SiteInfoService) GetSMTPConfig(ctx context.Context) (
resp *schema.GetSMTPConfigResp, err error) {
resp *schema.GetSMTPConfigResp, err error,
) {
emailConfig, err := s.emailService.GetEmailConfig()
if err != nil {
return nil, err

View File

@ -47,7 +47,8 @@ type TagCommonService struct {
// NewTagCommonService new tag service
func NewTagCommonService(tagRepo TagRepo, tagRelRepo TagRelRepo,
revisionService *revision_common.RevisionService) *TagCommonService {
revisionService *revision_common.RevisionService,
) *TagCommonService {
return &TagCommonService{
tagRepo: tagRepo,
tagRelRepo: tagRelRepo,
@ -97,20 +98,20 @@ func (ts *TagCommonService) GetObjectTag(ctx context.Context, objectId string) (
// BatchGetObjectTag batch get object tag
func (ts *TagCommonService) BatchGetObjectTag(ctx context.Context, objectIds []string) (map[string][]*schema.TagResp, error) {
objectIdTagMap := make(map[string][]*schema.TagResp)
objectIDTagMap := make(map[string][]*schema.TagResp)
tagIDList := make([]string, 0)
tagsInfoMap := make(map[string]*entity.Tag)
tagList, err := ts.tagRelRepo.BatchGetObjectTagRelList(ctx, objectIds)
if err != nil {
return objectIdTagMap, err
return objectIDTagMap, err
}
for _, tag := range tagList {
tagIDList = append(tagIDList, tag.TagID)
}
tagsInfoList, err := ts.tagRepo.GetTagListByIDs(ctx, tagIDList)
if err != nil {
return objectIdTagMap, err
return objectIDTagMap, err
}
for _, item := range tagsInfoList {
tagsInfoMap[item.ID] = item
@ -124,10 +125,10 @@ func (ts *TagCommonService) BatchGetObjectTag(ctx context.Context, objectIds []s
DisplayName: tagInfo.DisplayName,
MainTagSlugName: tagInfo.MainTagSlugName,
}
objectIdTagMap[item.ObjectID] = append(objectIdTagMap[item.ObjectID], t)
objectIDTagMap[item.ObjectID] = append(objectIDTagMap[item.ObjectID], t)
}
}
return objectIdTagMap, nil
return objectIDTagMap, nil
}
// ObjectChangeTag change object tag list
@ -191,7 +192,7 @@ func (ts *TagCommonService) ObjectChangeTag(ctx context.Context, objectTagData *
}
}
err = ts.CreateOrUpdateTagRelList(ctx, objectTagData.ObjectId, thisObjTagIDList)
err = ts.CreateOrUpdateTagRelList(ctx, objectTagData.ObjectID, thisObjTagIDList)
if err != nil {
return err
}

View File

@ -84,7 +84,7 @@ func (us *UserCommon) UserBasicInfoFormat(ctx context.Context, userInfo *entity.
userBasicInfo.Avatar = Avatar
userBasicInfo.Website = userInfo.Website
userBasicInfo.Location = userInfo.Location
userBasicInfo.IpInfo = userInfo.IPInfo
userBasicInfo.IPInfo = userInfo.IPInfo
userBasicInfo.Status = schema.UserStatusShow[userInfo.Status]
if userBasicInfo.Status == schema.UserDeleted {
userBasicInfo.Avatar = ""

View File

@ -40,7 +40,8 @@ func NewUserService(userRepo usercommon.UserRepo,
userActivity activity.UserActiveActivityRepo,
emailService *export.EmailService,
authService *auth.AuthService,
serviceConfig *service_config.ServiceConfig) *UserService {
serviceConfig *service_config.ServiceConfig,
) *UserService {
return &UserService{
userRepo: userRepo,
userActivity: userActivity,
@ -95,7 +96,8 @@ func (us *UserService) GetUserStatus(ctx context.Context, userID, token string)
}
func (us *UserService) GetOtherUserInfoByUsername(ctx context.Context, username string) (
resp *schema.GetOtherUserInfoResp, err error) {
resp *schema.GetOtherUserInfoResp, err error,
) {
userInfo, exist, err := us.userRepo.GetByUsername(ctx, username)
if err != nil {
return nil, err
@ -166,8 +168,8 @@ func (us *UserService) RetrievePassWord(ctx context.Context, req *schema.UserRet
UserID: userInfo.ID,
}
code := uuid.NewString()
verifyEmailUrl := fmt.Sprintf("%s/users/password-reset?code=%s", us.serviceConfig.WebHost, code)
title, body, err := us.emailService.PassResetTemplate(ctx, verifyEmailUrl)
verifyEmailURL := fmt.Sprintf("%s/users/password-reset?code=%s", us.serviceConfig.WebHost, code)
title, body, err := us.emailService.PassResetTemplate(ctx, verifyEmailURL)
if err != nil {
return "", err
}
@ -180,7 +182,7 @@ func (us *UserService) UseRePassWord(ctx context.Context, req *schema.UserRePass
data := &schema.EmailCodeContent{}
err = data.FromJSONString(req.Content)
if err != nil {
return nil, errors.BadRequest(reason.EmailVerifyUrlExpired)
return nil, errors.BadRequest(reason.EmailVerifyURLExpired)
}
userInfo, exist, err := us.userRepo.GetByEmail(ctx, data.Email)
@ -204,8 +206,7 @@ func (us *UserService) UseRePassWord(ctx context.Context, req *schema.UserRePass
}
func (us *UserService) UserModifyPassWordVerification(ctx context.Context, request *schema.UserModifyPassWordRequest) (bool, error) {
userInfo, has, err := us.userRepo.GetByUserID(ctx, request.UserId)
userInfo, has, err := us.userRepo.GetByUserID(ctx, request.UserID)
if err != nil {
return false, err
}
@ -226,7 +227,7 @@ func (us *UserService) UserModifyPassWord(ctx context.Context, request *schema.U
if err != nil {
return err
}
userInfo, has, err := us.userRepo.GetByUserID(ctx, request.UserId)
userInfo, has, err := us.userRepo.GetByUserID(ctx, request.UserID)
if err != nil {
return err
}
@ -252,21 +253,21 @@ func (us *UserService) UpdateInfo(ctx context.Context, req *schema.UpdateInfoReq
if err != nil {
return err
}
if exist && userInfo.ID != req.UserId {
if exist && userInfo.ID != req.UserID {
return errors.BadRequest(reason.UsernameDuplicate)
}
}
Avatar, err := json.Marshal(req.Avatar)
avatar, err := json.Marshal(req.Avatar)
if err != nil {
err = errors.BadRequest(reason.UserSetAvatar).WithError(err).WithStack()
return err
}
userInfo := entity.User{}
userInfo.ID = req.UserId
userInfo.Avatar = string(Avatar)
userInfo.ID = req.UserID
userInfo.Avatar = string(avatar)
userInfo.DisplayName = req.DisplayName
userInfo.Bio = req.Bio
userInfo.BioHtml = req.BioHtml
userInfo.BioHTML = req.BioHTML
userInfo.Location = req.Location
userInfo.Website = req.Website
userInfo.Username = req.Username
@ -286,7 +287,8 @@ func (us *UserService) UserEmailHas(ctx context.Context, email string) (bool, er
// UserRegisterByEmail user register
func (us *UserService) UserRegisterByEmail(ctx context.Context, registerUserInfo *schema.UserRegisterReq) (
resp *schema.GetUserResp, err error) {
resp *schema.GetUserResp, err error,
) {
_, has, err := us.userRepo.GetByEmail(ctx, registerUserInfo.Email)
if err != nil {
return nil, err
@ -320,8 +322,8 @@ func (us *UserService) UserRegisterByEmail(ctx context.Context, registerUserInfo
UserID: userInfo.ID,
}
code := uuid.NewString()
verifyEmailUrl := fmt.Sprintf("%s/users/account-activation?code=%s", us.serviceConfig.WebHost, code)
title, body, err := us.emailService.RegisterTemplate(ctx, verifyEmailUrl)
verifyEmailURL := fmt.Sprintf("%s/users/account-activation?code=%s", us.serviceConfig.WebHost, code)
title, body, err := us.emailService.RegisterTemplate(ctx, verifyEmailURL)
if err != nil {
return nil, err
}
@ -363,8 +365,8 @@ func (us *UserService) UserVerifyEmailSend(ctx context.Context, userID string) e
UserID: userInfo.ID,
}
code := uuid.NewString()
verifyEmailUrl := fmt.Sprintf("%s/users/account-activation?code=%s", us.serviceConfig.WebHost, code)
title, body, err := us.emailService.RegisterTemplate(ctx, verifyEmailUrl)
verifyEmailURL := fmt.Sprintf("%s/users/account-activation?code=%s", us.serviceConfig.WebHost, code)
title, body, err := us.emailService.RegisterTemplate(ctx, verifyEmailURL)
if err != nil {
return err
}
@ -372,9 +374,10 @@ func (us *UserService) UserVerifyEmailSend(ctx context.Context, userID string) e
return nil
}
func (us *UserService) UserNoticeSet(ctx context.Context, userId string, noticeSwitch bool) (
resp *schema.UserNoticeSetResp, err error) {
userInfo, has, err := us.userRepo.GetByUserID(ctx, userId)
func (us *UserService) UserNoticeSet(ctx context.Context, userID string, noticeSwitch bool) (
resp *schema.UserNoticeSetResp, err error,
) {
userInfo, has, err := us.userRepo.GetByUserID(ctx, userID)
if err != nil {
return nil, err
}
@ -382,9 +385,9 @@ func (us *UserService) UserNoticeSet(ctx context.Context, userId string, noticeS
return nil, errors.BadRequest(reason.UserNotFound)
}
if noticeSwitch {
userInfo.NoticeStatus = schema.Notice_Status_On
userInfo.NoticeStatus = schema.NoticeStatusOn
} else {
userInfo.NoticeStatus = schema.Notice_Status_Off
userInfo.NoticeStatus = schema.NoticeStatusOff
}
err = us.userRepo.UpdateNoticeStatus(ctx, userInfo.ID, userInfo.NoticeStatus)
return &schema.UserNoticeSetResp{NoticeSwitch: noticeSwitch}, err
@ -394,7 +397,7 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri
data := &schema.EmailCodeContent{}
err = data.FromJSONString(req.Content)
if err != nil {
return nil, errors.BadRequest(reason.EmailVerifyUrlExpired)
return nil, errors.BadRequest(reason.EmailVerifyURLExpired)
}
userInfo, has, err := us.userRepo.GetByEmail(ctx, data.Email)
@ -476,17 +479,14 @@ func (us *UserService) makeUsername(ctx context.Context, displayName string) (us
// Compare whether the password is correct
func (us *UserService) verifyPassword(ctx context.Context, LoginPass, UserPass string) bool {
err := bcrypt.CompareHashAndPassword([]byte(UserPass), []byte(LoginPass))
if err != nil {
return false
}
return true
return err == nil
}
// encryptPassword
// The password does irreversible encryption.
func (us *UserService) encryptPassword(ctx context.Context, Pass string) (string, error) {
hashPwd, err := bcrypt.GenerateFromPassword([]byte(Pass), bcrypt.DefaultCost)
//This encrypted string can be saved to the database and can be used as password matching verification
// This encrypted string can be saved to the database and can be used as password matching verification
return string(hashPwd), err
}
@ -514,7 +514,7 @@ func (us *UserService) UserChangeEmailSendCode(ctx context.Context, req *schema.
}
code := uuid.NewString()
var title, body string
verifyEmailUrl := fmt.Sprintf("%s/users/confirm-new-email?code=%s", us.serviceConfig.WebHost, code)
verifyEmailURL := fmt.Sprintf("%s/users/confirm-new-email?code=%s", us.serviceConfig.WebHost, code)
if userInfo.MailStatus == entity.EmailStatusToBeVerified {
title, body, err = us.emailService.RegisterTemplate(ctx, verifyEmailUrl)
} else {
@ -523,7 +523,7 @@ func (us *UserService) UserChangeEmailSendCode(ctx context.Context, req *schema.
if err != nil {
return err
}
log.Infof("send email confirmation %s", verifyEmailUrl)
log.Infof("send email confirmation %s", verifyEmailURL)
go us.emailService.Send(context.Background(), req.Email, title, body, code, data.ToJSONString())
return nil
@ -534,7 +534,7 @@ func (us *UserService) UserChangeEmailVerify(ctx context.Context, content string
data := &schema.EmailCodeContent{}
err = data.FromJSONString(content)
if err != nil {
return errors.BadRequest(reason.EmailVerifyUrlExpired)
return errors.BadRequest(reason.EmailVerifyURLExpired)
}
_, exist, err := us.userRepo.GetByEmail(ctx, data.Email)

View File

@ -67,7 +67,7 @@ func (as *VoteService) VoteUp(ctx context.Context, dto *schema.VoteDTO) (voteRes
var objectUserID string
objectUserID, err = as.GetObjectUserId(ctx, dto.ObjectID)
objectUserID, err = as.GetObjectUserID(ctx, dto.ObjectID)
if err != nil {
return
}
@ -91,7 +91,7 @@ func (as *VoteService) VoteDown(ctx context.Context, dto *schema.VoteDTO) (voteR
var objectUserID string
objectUserID, err = as.GetObjectUserId(ctx, dto.ObjectID)
objectUserID, err = as.GetObjectUserID(ctx, dto.ObjectID)
if err != nil {
return
}
@ -109,7 +109,7 @@ func (as *VoteService) VoteDown(ctx context.Context, dto *schema.VoteDTO) (voteR
}
}
func (vs *VoteService) GetObjectUserId(ctx context.Context, objectID string) (userID string, err error) {
func (vs *VoteService) GetObjectUserID(ctx context.Context, objectID string) (userID string, err error) {
var objectKey string
objectKey, err = obj.GetObjectTypeStrByObjectID(objectID)
@ -162,7 +162,8 @@ func (vs *VoteService) ListUserVotes(ctx context.Context, req schema.GetVoteWith
)
for _, typeKey := range typeKeys {
t, err := vs.configRepo.GetConfigType(typeKey)
var t int
t, err = vs.configRepo.GetConfigType(typeKey)
if err != nil {
continue
}
@ -175,7 +176,8 @@ func (vs *VoteService) ListUserVotes(ctx context.Context, req schema.GetVoteWith
}
for _, voteInfo := range voteList {
objInfo, err := vs.objectService.GetInfo(ctx, voteInfo.ObjectID)
var objInfo *schema.SimpleObjectInfo
objInfo, err = vs.objectService.GetInfo(ctx, voteInfo.ObjectID)
if err != nil {
log.Error(err)
}

View File

@ -3,12 +3,10 @@ package checker
import "unicode"
func IsChinese(str string) bool {
var count int
for _, v := range str {
if unicode.Is(unicode.Han, v) {
count++
break
return true
}
}
return count > 0
return false
}

View File

@ -30,7 +30,7 @@ func CheckPassword(minLength, maxLength, minLevel int, pwd string) error {
// The password strength level is initialized to D.
// The regular is used to verify the password strength.
// If the matching is successful, the password strength increases by 1
var level int = levelD
level := levelD
patternList := []string{`[0-9]+`, `[a-z]+`, `[A-Z]+`, `[~!@#$%^&*?_-]+`}
for _, pattern := range patternList {
match, _ := regexp.MatchString(pattern, pwd)
@ -41,7 +41,7 @@ func CheckPassword(minLength, maxLength, minLevel int, pwd string) error {
// If the final password strength falls below the required minimum strength, return with an error
if level < minLevel {
return fmt.Errorf("The password does not satisfy the current policy requirements. ")
return fmt.Errorf("the password does not satisfy the current policy requirements")
}
return nil
}

View File

@ -15,7 +15,7 @@ type SnowFlakeID struct {
var snowFlakeIDGenerator *SnowFlakeID
func init() {
//todo
// todo
rand.Seed(time.Now().UnixNano())
node, err := snowflake.NewNode(int64(rand.Intn(1000)) + 1)
if err != nil {

View File

@ -3,5 +3,6 @@
"tabWidth": 2,
"singleQuote": true,
"jsxBracketSameLine": true,
"printWidth": 80
}
"printWidth": 80,
"endOfLine": "auto"
}

View File

@ -19,7 +19,9 @@ const Form = ({ userName, onSendReply, onCancel, mode }) => {
return (
<div className="mb-2">
<div className="fs-14 mb-2">Reply to {userName}</div>
<div className="fs-14 mb-2">
{t('reply_to')} {userName}
</div>
<div className="d-flex mb-1 align-items-start flex-column flex-md-row">
<div>
<Mentions

View File

@ -251,7 +251,7 @@
"synonyms_text": "The following tags will be remapped to",
"delete": {
"title": "Delete this tag",
"content": "<p>We do not allowed deleting tag with posts.</p><p>Please remove the python tag from the posts first.</p>",
"content": "<p>We do not allowed deleting tag with posts.</p><p>Please remove this tag from the posts first.</p>",
"content2": "Are you sure you wish to delete?",
"close": "Close"
}
@ -404,7 +404,7 @@
}
},
"footer": {
"build_on": "Build on <1> Answer </1>- the open-source software that power Q&A communities.<br />Made with love. © 2022 Answer."
"build_on": "Built on <1> Answer </1>- the open-source software that power Q&A communities<br />Made with love © 2022 Answer"
},
"upload_img": {
"name": "Change",
@ -591,6 +591,8 @@
"update": "Modified",
"edit": "edited",
"Views": "Viewed",
"Follow": "Follow",
"Following": "Following",
"answered": "answered",
"closed_in": "Closed in",
"show_exist": "Show existing question.",

View File

@ -1,45 +1,440 @@
{
"how_to_format": {
"title": "如何设定文本格式",
"description": "<ul class=\"mb-0\"><li><p class=\"mb-2\">添加链接:</p><pre class=\"mb-2\"><code>&lt;https://url.com&gt;<br/><br/>[标题](https://url.com)</code></pre></li><li><p class=\"mb-2\">段落之间使用空行分隔</p></li><li><p class=\"mb-2\"><em>_斜体_</em> 或者 **<strong>粗体</strong>**</p></li><li><p class=\"mb-2\">使用 4 个空格缩进代码</p></li><li><p class=\"mb-2\">在行首添加<code>&gt;</code>表示引用</p></li><li><p class=\"mb-2\">反引号进行转义 <code>`像 _这样_`</code></p></li><li><p class=\"mb-2\">使用<code>```</code>创建代码块</p><pre class=\"mb-0\"><code>```<br/>// 这是代码<br/>```</code></pre></li></ul>"
},
"pagination": {
"prev": "上一页",
"next": "下一页"
},
"page_title": {
"question": "问题",
"questions": "问题",
"tag": "标签",
"tags": "标签",
"tag_wiki": "标签 wiki",
"edit_tag": "编辑标签",
"ask_a_question": "提问题",
"edit_question": "编辑问题",
"edit_answer": "编辑回答",
"search": "搜索",
"posts_containing": "包含",
"settings": "设定",
"notifications": "通知",
"login": "登录",
"sign_up": "注册",
"account_recovery": "账号恢复",
"account_activation": "账号激活",
"confirm_email": "确认电子邮件",
"account_suspended": "账号已封禁",
"admin": "后台管理"
},
"notifications": {
"title": "通知",
"inbox": "收件箱",
"achievement": "成就",
"all_read": "全部标记为已读",
"show_more": "显示更多"
},
"suspended": {
"title": "账号已封禁",
"until_time": "你的账号被封禁至{{ time }}。",
"forever": "你的账号已被永久封禁。",
"end": "违反了我们的社区准则。"
},
"editor": {
"blockquote": {
"text": "引用"
},
"bold": {
"text": "粗体"
},
"chart": {
"text": "图表",
"flow_chart": "流程图",
"sequence_diagram": "时序图",
"class_diagram": "类图",
"state_diagram": "状态图",
"entity_relationship_diagram": "ER 图",
"user_defined_diagram": "User defined diagram",
"gantt_chart": "甘特图",
"pie_chart": "饼图"
},
"code": {
"text": "代码块",
"add_code": "添加代码块",
"form": {
"fields": {
"code": {
"label": "代码块",
"msg": {
"empty": "代码块不能为空"
}
},
"language": {
"label": "语言 (可选)",
"placeholder": "自动识别"
}
}
},
"btn_cancel": "取消",
"btn_confirm": "添加"
},
"formula": {
"text": "公式",
"options": {
"inline": "行内公式",
"block": "公式块"
}
},
"heading": {
"text": "标题",
"options": {
"h1": "标题 1",
"h2": "标题 2",
"h3": "标题 3",
"h4": "标题 4",
"h5": "标题 5",
"h6": "标题 6"
}
},
"help": {
"text": "帮助"
},
"hr": {
"text": "水平分割线"
},
"image": {
"text": "图片",
"add_image": "添加图片",
"tab_image": "上传图片",
"form_image": {
"fields": {
"file": {
"label": "图片文件",
"btn": "选择图片",
"msg": {
"empty": "请选择图片文件。",
"only_image": "只能上传图片文件。",
"max_size": "图片文件大小不能超过 4 MB。"
}
},
"description": {
"label": "图片描述(可选)"
}
}
},
"tab_url": "网络图片",
"form_url": {
"fields": {
"url": {
"label": "图片地址",
"msg": {
"empty": "图片地址不能为空"
}
},
"name": {
"label": "图片描述(可选)"
}
}
},
"btn_cancel": "取消",
"btn_confirm": "添加",
"uploading": "上传中..."
},
"indent": {
"text": "添加缩进"
},
"outdent": {
"text": "减少缩进"
},
"italic": {
"text": "斜体"
},
"link": {
"text": "超链接",
"add_link": "添加超链接",
"form": {
"fields": {
"url": {
"label": "链接",
"msg": {
"empty": "链接不能为空。"
}
},
"name": {
"label": "链接描述(可选)"
}
}
},
"btn_cancel": "取消",
"btn_confirm": "添加"
},
"ordered_list": {
"text": "有编号列表"
},
"unordered_list": {
"text": "无编号列表"
},
"table": {
"text": "表格",
"heading": "表头",
"cell": "单元格"
}
},
"close_modal": {
"title": "关闭原因是...",
"btn_cancel": "取消",
"btn_submit": "提交",
"remark": {
"empty": "不能为空。"
},
"msg": {
"empty": "请选择一个原因。"
}
},
"report_modal": {
"flag_title": "举报原因是...",
"close_title": "关闭原因是...",
"review_question_title": "审查问题",
"review_answer_title": "审查回答",
"review_comment_title": "审查评论",
"btn_cancel": "取消",
"btn_submit": "提交",
"remark": {
"empty": "不能为空"
},
"msg": {
"empty": "请选择一个原因。"
}
},
"tag_modal": {
"title": "创建新标签",
"form": {
"fields": {
"display_name": {
"label": "显示名称(别名)",
"msg": {
"empty": "不能为空",
"range": "不能超过 35 个字符"
}
},
"slug_name": {
"label": "URL 固定链接",
"description": "必须由 \"a-z\", \"0-9\", \"+ # - .\" 组成",
"msg": {
"empty": "不能为空",
"range": "不能超过 35 个字符",
"character": "包含非法字符"
}
},
"description": {
"label": "标签描述(可选)"
}
}
},
"btn_cancel": "取消",
"btn_submit": "提交"
},
"tag_info": {
"created_at": "创建于",
"edited_at": "编辑于",
"synonyms": {
"title": "同义词",
"text": "以下标签等同于",
"empty": "此标签目前没有同义词。",
"btn_add": "添加同义词",
"btn_edit": "编辑",
"btn_save": "保存"
},
"synonyms_text": "以下标签等同于",
"delete": {
"title": "删除标签",
"content": "<p>不允许删除有关联问题的标签。</p><p>请先从关联的问题中删除此标签的引用。</p>",
"content2": "确定要删除吗?",
"close": "关闭"
}
},
"edit_tag": {
"title": "编辑标签",
"default_reason": "编辑标签",
"form": {
"fields": {
"revision": {
"label": "编辑历史"
},
"display_name": {
"label": "名称"
},
"slug_name": {
"label": "URL 固定链接",
"info": "必须由 \"a-z\", \"0-9\", \"+ # - .\" 组成"
},
"description": {
"label": "描述"
},
"edit_summary": {
"label": "编辑概要",
"placeholder": "简单描述更改原因 (错别字、文字表达、格式等等)"
}
}
},
"btn_save_edits": "保存更改",
"btn_cancel": "取消"
},
"dates": {
"long_date": "YYYY年MM月",
"long_date_with_year": "YYYY年MM月DD日",
"long_date_with_time": "YYYY年MM月DD日 HH:mm",
"now": "刚刚",
"x_seconds_ago": "{{count}} 秒前",
"x_minutes_ago": "{{count}} 分钟前",
"x_hours_ago": "{{count}} 小时前"
},
"comment": {
"btn_add_comment": "添加评论",
"reply_to": "回复",
"btn_reply": "回复",
"btn_edit": "编辑",
"btn_delete": "删除",
"btn_flag": "举报",
"btn_save_edits": "保存",
"btn_cancel": "取消",
"show_more": "显示更多评论",
"tip_question": "使用评论提问更多信息或者提出改进意见。尽量避免使用评论功能回答问题。",
"tip_answer": "使用评论对回答者进行回复,或者通知回答者你已更新了问题的内容。如果要补充或者完善问题的内容,请在原问题中更改。"
},
"edit_answer": {
"title": "编辑回答",
"default_reason": "编辑回答",
"form": {
"fields": {
"revision": {
"label": "编辑历史"
},
"answer": {
"label": "回答内容"
},
"edit_summary": {
"label": "编辑概要",
"placeholder": "简单描述更改原因 (错别字、文字表达、格式等等)"
}
}
},
"btn_save_edits": "保存更改",
"btn_cancel": "取消"
},
"tags": {
"title": "标签",
"sort_buttons": {
"popular": "热门",
"name": "名称",
"newest": "最新"
},
"button_follow": "关注",
"button_following": "已关注",
"tag_label": "个问题",
"search_placeholder": "通过标签名过滤",
"no_description": "此标签无描述。",
"more": "更多"
},
"ask": {
"title": "提交新的问题",
"edit_title": "编辑问题",
"default_reason": "编辑问题",
"similar_questions": "相似的问题",
"form": {
"fields": {
"revision": {
"label": "编辑历史"
},
"title": {
"label": "标题",
"placeholder": "请详细描述你的问题",
"msg": {
"empty": "标题不能为空",
"range": "标题最多 150 个字符"
}
},
"body": {
"label": "内容",
"msg": {
"empty": "内容不能为空"
}
},
"tags": {
"label": "标签",
"msg": {
"empty": "必须选择一个标签"
}
},
"answer": {
"label": "回答内容",
"msg": {
"empty": "回答内容不能为空"
}
}
}
},
"btn_post_question": "提交问题",
"btn_save_edits": "保存更改",
"answer_question": "直接发表回答",
"post_question&answer": "提交问题和回答"
},
"tag_selector": {
"add_btn": "添加标签",
"create_btn": "创建新标签",
"search_tag": "搜索标签",
"hint": "选择至少一个与问题相关的标签。",
"no_result": "没有匹配的标签"
},
"header": {
"nav": {
"question": "问题",
"tag": "标签",
"user": "用户",
"profile": "个人主页",
"setting": "个人设置",
"logout": "退出登录"
"profile": "用户主页",
"setting": "账号设置",
"logout": "退出登录",
"admin": "后台管理"
},
"search": {
"placeholder": "搜索"
},
"add_question": "提问题"
}
},
"footer": {
"build_on": "Built on <1> Answer </1>- the open-source software that power Q&A communities<br />Made with love © 2022 Answer"
},
"upload_img": {
"name": "更改图片",
"loading": "加载中..."
},
"pic_auth_code": {
"btn_name": "验证",
"title": "验证码",
"placeholder": "输入上面的文字",
"placeholder": "输入图片中的文字",
"msg": {
"empty": "不能为空"
}
},
"inactive": {
"first": "你几乎已经完成!我们发送了一封激活邮件到 <strong>{{mail}}</strong>. 请按照邮件中的说明激活您的帐户。",
"first": "马上就好了!我们发送了一封激活邮件到 <bold>{{mail}}</bold>。请按照邮件中的说明激活您的帐户。",
"info": "如果没有收到,请检查您的垃圾邮件文件夹。",
"another": "我们向您发送了另一封激活电子邮件,地址为 <strong>{{mail}}</strong>. 它可能需要几分钟才能到达;请务必检查您的垃圾邮件文件夹。",
"btn_name": "重新发送激活电邮",
"another": "我们向您发送了另一封激活电子邮件,地址为 <bold>{{mail}}</bold>。它可能需要几分钟才能到达;请务必检查您的垃圾邮件文件夹。",
"btn_name": "重新发送激活",
"msg": {
"empty": "不能为空"
}
},
"login": {
"page_title": "欢迎来到 Answer",
"btn_name": "登录",
"info_sign": "没有帐户?<1>注册</1>",
"info_login": "已经有一个帐户?<1>登录</1>",
"forgot_pass": "忘记密码?",
"name": {
"label": "昵称",
"msg": {
"empty": "昵称不能为空"
"empty": "昵称不能为空",
"range": "昵称最多 30 个字符"
}
},
"email": {
@ -56,7 +451,464 @@
}
}
},
"footer": {
"build_on": "由 <1> Answer </1>构建- 为知识社区提供动力的开源软件.<br />Made with love. © 2022 Answer ."
"account_forgot": {
"page_title": "忘记密码",
"btn_name": "发送恢复邮件",
"send_success": "如无意外,你的邮箱 <strong>{{mail}}</strong> 将会收到一封重置密码的邮件,请根据指引重置你的密码。",
"email": {
"label": "邮箱",
"msg": {
"empty": "邮箱不能为空"
}
}
},
"password_reset": {
"page_title": "密码重置",
"btn_name": "重置我的密码",
"reset_success": "你已经成功更改密码,将返回登录页面",
"link_invalid": "抱歉,此密码重置链接已失效。也许是你已经重置过密码了?",
"to_login": "前往登录页面",
"password": {
"label": "密码",
"msg": {
"empty": "密码不能为空",
"length": "密码长度在8-32个字符之间",
"different": "两次输入密码不一致"
}
},
"password_confirm": {
"label": "确认新密码"
}
},
"settings": {
"page_title": "设置",
"nav": {
"profile": "我的资料",
"notification": "通知",
"account": "账号",
"interface": "界面"
},
"profile": {
"btn_name": "保存更改",
"display_name": {
"label": "昵称",
"msg": "昵称不能为空",
"msg_range": "昵称不能超过 30 个字符"
},
"username": {
"label": "用户名",
"caption": "用户之间可以通过 \"@用户名\" 进行交互。",
"msg": "用户名不能为空",
"msg_range": "用户名不能超过 30 个字符",
"character": "用户名只能由 \"a-z\", \"0-9\", \" - . _\" 组成"
},
"avatar": {
"label": "头像",
"text": "您可以上传图片作为头像,也可以 <1>重置</1> 为"
},
"bio": {
"label": "关于我 (可选)"
},
"website": {
"label": "网站 (可选)",
"placeholder": "https://example.com",
"msg": "格式不正确"
},
"location": {
"label": "位置 (可选)",
"placeholder": "城市, 国家"
}
},
"notification": {
"email": {
"label": "邮件通知",
"radio": "你的提问有新的回答,评论,和其他"
}
},
"account": {
"change_email_btn": "更改邮箱",
"change_pass_btn": "更改密码",
"change_email_info": "邮件已发送。请根据指引完成验证。",
"email": {
"label": "邮箱",
"msg": "邮箱不能为空"
},
"password_title": "密码",
"current_pass": {
"label": "当前密码",
"msg": {
"empty": "当前密码不能为空",
"length": "密码长度必须在 8 至 32 之间",
"different": "两次输入的密码不匹配"
}
},
"new_pass": {
"label": "新密码"
},
"pass_confirm": {
"label": "确认新密码"
}
},
"interface": {
"lang": {
"label": "界面语言",
"text": "设置用户界面语言,在刷新页面后生效。"
}
}
},
"toast": {
"update": "更新成功",
"update_password": "更改密码成功。",
"flag_success": "感谢您的标记,我们会尽快处理。"
},
"related_question": {
"title": "相关问题",
"btn": "我要提问",
"answers": "个回答"
},
"question_detail": {
"Asked": "提问于",
"asked": "提问于",
"update": "修改于",
"edit": "最后编辑于",
"Views": "阅读次数",
"Follow": "关注此问题",
"Following": "已关注",
"answered": "回答于",
"closed_in": "关闭于",
"show_exist": "查看相关问题。",
"answers": {
"title": "个回答",
"score": "评分",
"newest": "最新",
"btn_accept": "采纳",
"btn_accepted": "已被采纳"
},
"write_answer": {
"title": "你的回答",
"btn_name": "提交你的回答",
"confirm_title": "继续回答",
"continue": "继续",
"confirm_info": "<p>您确定要提交一个新的回答吗?</p><p>您可以直接编辑和改善您之前的回答的。</p>",
"empty": "回答内容不能为空。"
}
},
"delete": {
"title": "删除",
"question": "我们不建议<strong>删除有回答的帖子</strong>。因为这样做会使得后来的读者无法从该问题中获得帮助。</p><p>如果删除过多有回答的帖子,你的账号将会被禁止提问。你确定要删除吗?",
"answer_accepted": "<p>我们不建议<strong>删除被采纳的回答</strong>。因为这样做会使得后来的读者无法从该回答中获得帮助。</p>如果删除过多被采纳的回答,你的账号将会被禁止回答任何提问。你确定要删除吗?",
"other": "你确定要删除?",
"tip_question_deleted": "此问题已被删除",
"tip_answer_deleted": "此回答已被删除"
},
"btns": {
"confirm": "确认",
"cancel": "取消",
"save": "保存",
"delete": "删除",
"login": "登录",
"signup": "注册",
"logout": "退出登录",
"verify": "验证",
"add_question": "我要提问"
},
"search": {
"title": "搜索结果",
"keywords": "关键词",
"options": "选项",
"follow": "关注",
"following": "已关注",
"counts": "{{count}} 个结果",
"more": "更多",
"sort_btns": {
"relevance": "相关性",
"newest": "最新的",
"active": "活跃的",
"score": "评分"
},
"tips": {
"title": "高级搜索提示",
"tag": "<1>[tag]</1> 在指定标签中搜索",
"user": "<1>user:username</1> 根据作者搜索",
"answer": "<1>answers:0</1> 搜索未回答的问题",
"score": "<1>score:3</1> 评分 3 分或以上",
"question": "<1>is:question</1> 只搜索问题",
"is_answer": "<1>is:answer</1> 只搜索回答"
},
"empty": "找不到任何相关的内容。<br /> 请尝试其他关键字,或者减少查找内容的长度。"
},
"share": {
"name": "分享",
"copy": "复制链接",
"via": "分享在...",
"copied": "已复制",
"facebook": "分享到 Facebook",
"twitter": "分享到 Twitter"
},
"cannot_vote_for_self": "不能给自己投票",
"modal_confirm": {
"title": "发生错误..."
},
"account_result": {
"page_title": "欢迎来到 Answer",
"success": "你的账号已通过验证,即将返回首页。",
"link": "返回首页",
"invalid": "抱歉,此验证链接已失效。也许是你的账号已经通过验证了?",
"confirm_new_email": "你的电子邮箱已更新",
"confirm_new_email_invalid": "抱歉,此验证链接已失效。也许是你的邮箱已经成功更改了?"
},
"question": {
"following_tags": "已关注的标签",
"edit": "编辑",
"save": "保存",
"follow_tag_tip": "按照标签整理您的问题列表。",
"hot_questions": "热点问题",
"all_questions": "全部问题",
"x_questions": "{{ count }} 个问题",
"x_answers": "{{ count }} 个回答",
"questions": "个问题",
"answers": "回答",
"newest": "最新",
"active": "活跃",
"frequent": "浏览量",
"score": "评分",
"unanswered": "未回答",
"modified": "修改于",
"answered": "回答于",
"asked": "提问于",
"closed": "已关闭",
"follow_a_tag": "关注一个标签",
"more": "更多"
},
"personal": {
"overview": "概览",
"answers": "回答",
"answer": "回答",
"questions": "问题",
"question": "问题",
"bookmarks": "收藏",
"reputation": "声望",
"comments": "评论",
"votes": "得票",
"newest": "最新",
"score": "评分",
"edit_profile": "编辑我的资料",
"visited_x_days": "Visited {{ count }} days",
"viewed": "Viewed",
"joined": "加入于",
"last_login": "上次登录",
"about_me": "关于我",
"about_me_empty": "// Hello, World !",
"top_answers": "热门回答",
"top_questions": "热门问题",
"stats": "状态",
"list_empty": "没有找到相关的内容。<br />试试看其他标签?",
"accepted": "已采纳",
"answered": "回答于",
"asked": "提问于",
"upvote": "赞同",
"downvote": "反对",
"mod_short": "管理员",
"mod_long": "管理员",
"x_reputation": "声望",
"x_votes": "得票",
"x_answers": "个回答",
"x_questions": "个问题"
},
"page_404": {
"description": "页面不存在",
"back_home": "回到主页"
},
"page_50X": {
"description": "服务器遇到了一个错误,无法完成你的请求。",
"back_home": "回到主页"
},
"admin": {
"admin_header": {
"title": "后台管理"
},
"nav_menus": {
"dashboard": "后台管理",
"contents": "内容管理",
"questions": "问题",
"answers": "回答",
"users": "用户管理",
"flags": "举报管理",
"settings": "站点设置",
"general": "一般",
"interface": "界面",
"smtp": "SMTP"
},
"dashboard": {
"title": "后台管理",
"welcome": "欢迎来到 Answer 后台管理!",
"version": "版本"
},
"flags": {
"title": "举报",
"pending": "等待处理",
"completed": "已完成",
"flagged": "被举报内容",
"created": "创建于",
"action": "操作",
"review": "审查"
},
"change_modal": {
"title": "更改用户状态为...",
"btn_cancel": "取消",
"btn_submit": "提交",
"normal_name": "正常",
"normal_description": "正常状态的用户可以提问和回答。",
"suspended_name": "封禁",
"suspended_description": "被封禁的用户将无法登录。",
"deleted_name": "删除",
"deleted_description": "删除用户的个人信息,认证等等。",
"inactive_name": "不活跃",
"inactive_description": "不活跃的用户必须重新验证邮箱。",
"confirm_title": "删除此用户",
"confirm_content": "确定要删除此用户?此操作无法撤销!",
"confirm_btn": "删除",
"msg": {
"empty": "请选择一个原因"
}
},
"status_modal": {
"title": "更改 {{ type }} 状态为...",
"normal_name": "正常",
"normal_description": "所有用户都可以访问",
"closed_name": "关闭",
"closed_description": "不能回答,但仍然可以编辑、投票和评论。",
"deleted_name": "删除",
"deleted_description": "所有获得/损失的声望将会恢复。",
"btn_cancel": "取消",
"btn_submit": "提交",
"btn_next": "下一步"
},
"users": {
"title": "用户",
"name": "名称",
"email": "邮箱",
"reputation": "声望",
"created_at": "创建时间",
"delete_at": "删除时间",
"suspend_at": "封禁时间",
"status": "状态",
"action": "操作",
"change": "更改",
"all": "全部",
"inactive": "不活跃",
"suspended": "已封禁",
"deleted": "已删除",
"normal": "正常"
},
"questions": {
"page_title": "问题",
"normal": "正常",
"closed": "已关闭",
"deleted": "已删除",
"post": "标题",
"votes": "得票数",
"answers": "回答数",
"created": "创建于",
"status": "状态",
"action": "操作",
"change": "更改"
},
"answers": {
"page_title": "回答",
"normal": "正常",
"deleted": "已删除",
"post": "标题",
"votes": "得票数",
"created": "创建于",
"status": "状态",
"action": "操作",
"change": "更改"
},
"general": {
"page_title": "一般",
"name": {
"label": "站点名称",
"msg": "不能为空",
"text": "站点的名称作为站点的标题HTML 的 title 标签)。"
},
"short_description": {
"label": "简短的站点标语 (可选)",
"msg": "不能为空",
"text": "简短的标语作为网站主页的标题HTML 的 title 标签)。"
},
"description": {
"label": "网站描述 (可选)",
"msg": "不能为空",
"text": "使用一句话描述本站作为网站的描述HTML 的 meta 标签)。"
}
},
"interface": {
"page_title": "界面",
"logo": {
"label": "Logo (可选)",
"msg": "不能为空",
"text": "可以上传图片,或者<1>重置</1>为站点标题。"
},
"theme": {
"label": "主题",
"msg": "不能为空",
"text": "选择一个主题"
},
"language": {
"label": "界面语言",
"msg": "不能为空",
"text": "设置用户界面语言,在刷新页面后生效。"
}
},
"smtp": {
"page_title": "SMTP",
"from_email": {
"label": "发件人地址",
"msg": "不能为空",
"text": "用于发送邮件的地址。"
},
"from_name": {
"label": "发件人名称",
"msg": "不能为空",
"text": "发件人的名称"
},
"smtp_host": {
"label": "SMTP 主机",
"msg": "不能为空",
"text": "邮件服务器"
},
"encryption": {
"label": "加密",
"msg": "不能为空",
"text": "对于大多数服务器而言SSL 是推荐开启的。",
"ssl": "SSL",
"none": "无加密"
},
"smtp_port": {
"label": "SMTP 端口",
"msg": "SMTP 端口必须在 1 ~ 65535 之间。",
"text": "邮件服务器的端口号。"
},
"smtp_username": {
"label": "SMTP 用户名",
"msg": "不能为空"
},
"smtp_password": {
"label": "SMTP 密码",
"msg": "不能为空"
},
"test_email_recipient": {
"label": "测试邮件收件人",
"text": "提供用于接收测试邮件的邮箱地址。",
"msg": "地址无效"
},
"smtp_authentication": {
"label": "SMTP 认证",
"msg": "不能为空",
"yes": "是",
"no": "否"
}
}
}
}

View File

@ -88,7 +88,7 @@ const Index: FC<Props> = ({ data, initPage, hasAnswer }) => {
size="sm"
className="p-0 btn-no-border"
onClick={(e) => handleFollow(e)}>
{followed ? 'Following' : 'Follow'}
{t(followed ? 'Following' : 'Follow')}
</Button>
</div>
<div className="m-n1">

View File

@ -116,7 +116,7 @@ const Personal: FC = () => {
)}
</Col>
<Col xxl={3} lg={4} sm={12} className="mt-5 mt-lg-0">
<h5 className="mb-3">Stats</h5>
<h5 className="mb-3">{t('stats')}</h5>
{userInfo?.info && (
<>
<div className="text-secondary">

View File

@ -120,7 +120,7 @@ export const getUserInfo = () => {
};
export const modifyPassword = (params: Type.ModifyPasswordReq) => {
return request.post('/answer/api/v1/user/password/modify', params);
return request.put('/answer/api/v1/user/password', params);
};
export const modifyUserInfo = (params: Type.ModifyUserReq) => {