mirror of https://gitee.com/answerdev/answer.git
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:
commit
6e5d89d593
|
@ -1,4 +1,8 @@
|
|||
# Contributing to answer
|
||||
## Coding and documentation Style
|
||||
|
||||
To be developed.
|
||||
|
||||
## Submitting Modifications
|
||||
|
||||
To be developed.
|
||||
|
|
54
INSTALL.md
54
INSTALL.md
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
||||
[](https://github.com/answerdev/answer/blob/main/LICENSE)
|
||||
[](https://golang.org/)
|
||||
[](https://reactjs.org/)
|
||||
[](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)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[](https://github.com/answerdev/answer/blob/main/LICENSE)
|
||||
[](https://golang.org/)
|
||||
[](https://reactjs.org/)
|
||||
[](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)
|
||||
|
|
|
@ -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 [✔]")
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
|
@ -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:"
|
||||
|
|
|
@ -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"}]`
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 doesn’t 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 can’t 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 can’t 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 can’t 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 doesn’t 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 can’t 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 can’t 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 can’t 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 ""
|
||||
}
|
||||
|
|
|
@ -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}).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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("")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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("")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -3,8 +3,8 @@ package schema
|
|||
import "time"
|
||||
|
||||
const (
|
||||
CG_DEFAULT = 1
|
||||
CG_DIY = 2
|
||||
CGDefault = 1
|
||||
CGDIY = 2
|
||||
)
|
||||
|
||||
// CollectionSwitchReq switch collection request
|
||||
|
|
|
@ -2,7 +2,7 @@ package schema
|
|||
|
||||
const (
|
||||
ForbiddenReasonTypeInactive = "inactive"
|
||||
ForbiddenReasonTypeUrlExpired = "url_expired"
|
||||
ForbiddenReasonTypeURLExpired = "url_expired"
|
||||
ForbiddenReasonTypeUserSuspended = "suspended"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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:"-"`
|
||||
|
|
|
@ -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 doesn’t 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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 = ""
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"printWidth": 80
|
||||
}
|
||||
"printWidth": 80,
|
||||
"endOfLine": "auto"
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -1,45 +1,440 @@
|
|||
{
|
||||
"how_to_format": {
|
||||
"title": "如何设定文本格式",
|
||||
"description": "<ul class=\"mb-0\"><li><p class=\"mb-2\">添加链接:</p><pre class=\"mb-2\"><code><https://url.com><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>></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": "否"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in New Issue