Compare commits

...

10 Commits

Author SHA1 Message Date
becomer 7d6dcd198c fix: woodpecker when 条件简化,只用 event: tag
ci/woodpecker/tag/build Pipeline was successful
2026-08-09 22:03:38 +08:00
becomer 27d83f193f fix: 智慧教育网站更新后 ParseJsUrl 无法匹配新的 chunk URL 结构
ci/woodpecker/tag/build Pipeline was successful
网站将 chunk-vendors 改为了 chunk-libs/chunk-elementUI,
且首页组件被合并到多模块组合 chunk 中。
更新正则:匹配 chunk-libs 或 chunk-elementUI 的 URL,
提取 base 路径和 hash,构造新的组合 chunk 文件 URL。
2026-08-09 21:56:58 +08:00
becomer f4c2b8de4c fix: 提交验证码识别失败 — 调用分类器时缺少 X-Api-Key 请求头
ci/woodpecker/tag/build Pipeline was successful
NormalSubmitCaptchaResolver.getResultFromItStar 调用验证码分类服务
/classifier 时没有传 X-Api-Key 请求头,而分类服务已启用 ApiKeyAuth
中间件,导致返回 401,最终报"提交验证码识别失败"。
2026-07-08 23:02:48 +08:00
becomer d454ecc7cf fix: 无历史时保底使用管理员配置的签到范围信息
ci/woodpecker/tag/build Pipeline was successful
- 有历史签到数据 → 优先使用历史中的真实地址和经纬度
- 无历史签到数据 → 保底从 signPlaceSelected 提取管理员配置的范围信息
2026-07-04 01:04:10 +08:00
becomer 7ede964c4c fix: 未签到任务表单中地址和经纬度仍错误使用管理员配置数据
ci/woodpecker/tag/build Pipeline was successful
- ParseFormJson: 完全移除 signPlaceSelected 提取(始终是管理员范围数据)
- ParseFormJson: 将 longitude/latitude/position/signAddress 提取全部包进 if hasHistory
- QueryFormByTitle: 已签到(相同 instanceWid)时将自身 rows 设为 historyRows
- 确保无历史数据的未签到任务不会错误显示管理员范围名称(如"7")
2026-07-04 00:59:33 +08:00
becomer 4b50af3ae0 fix: woodpecker 只应在推送 tag 时触发,移除 push event 2026-07-04 00:51:27 +08:00
becomer 65293c4f81 fix: 编辑表单时签到地址错误显示为管理员范围名称的问题
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/build Pipeline was successful
当任务没有历史已签到数据时,ParseFormJson 中 histRows 回退到 rows
(当前任务定义),此时 signPlaceSelected 包含的是管理员后台圈定范围的
数据(范围名称如"7"),而不是用户实际签到地址。

修复:
1. ParseFormJson: 只有有实际历史数据(historyRows 存在)时才从
   signPlaceSelected 提取地址/经纬度,否则跳过
2. QueryFormByTitle: 当前任务自身已签到时,不再将自身 rows 作为
   historyRows,让逻辑正常从历史月份查找其他已签到实例
2026-07-04 00:48:58 +08:00
becomer a41341e732 fix: 修复历史任务经纬度/地址获取到的是教师边界坐标而非用户历史提交数据的问题
ci/woodpecker/tag/build Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
- sign.go: 移除 signInstanceWid 比较限制,当已签到任务与当前任务是同一实例时,
  直接复用已有详情数据作为历史数据,确保 ParseFormJson 能从 signPlaceSelected 提取用户真实坐标
- sleepcheck.go: 移除 if !isFromSigned 守卫条件,无论当前任务是否已签到都尝试获取历史数据
2026-07-02 00:36:42 +08:00
becomer ecfa50359b fix: add X-Api-Key header for captcha OCR requests
ci/woodpecker/push/build Pipeline was canceled
ci/woodpecker/tag/build Pipeline was successful
The captcha OCR service now requires X-Api-Key authentication.
Add captcha.apiKey config option and pass it as header in all
OCR-related API calls (ocr, semiOcr, calc).
2026-07-01 20:22:03 +08:00
becomer 2879336ce4 feat: make PostgreSQL connection optional
ci/woodpecker/push/build Pipeline was successful
Remove hard requirement on PG database (likedream-pg container).
PG is now only initialized when dsn2 is configured; skip gracefully when empty.
Add nil-safety checks on GlobalGorm references in balance migration logic.
Remove dsn2 from default config.
2026-07-01 14:08:36 +08:00
10 changed files with 199 additions and 162 deletions
+1 -4
View File
@@ -1,8 +1,5 @@
when:
- event: push
branch: [main, master]
- event: tag
branch: [v*]
event: tag
clone:
git:
+6 -4
View File
@@ -20,8 +20,9 @@ key = "sk-acacac439b346036df45e90c85c177c375568ef72c469e49"
[database]
type = "mysql"
dsn = "test_likedream_go:EpXckXmxawDEQGxJ@tcp(database.out:3306)/test_likedream_go?parseTime=true&loc=Asia%2FShanghai"
dsn2 = "host=database.out user=dev password=JPmKjmpcaG3EYAJZ dbname=dev port=5432 sslmode=disable TimeZone=Asia/Shanghai"
# host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai
dsn2 = "host=pg.out user=dev password=JPmKjmpcaG3EYAJZ dbname=dev port=5432 sslmode=disable TimeZone=Asia/Shanghai"
#type = "postgres"
#dsn = "host=pg.out user=dev password=JPmKjmpcaG3EYAJZ dbname=dev port=5432 sslmode=disable TimeZone=Asia/Shanghai"
[server]
port = 8091
url = "https://devocr.likedream.xyz"
@@ -35,8 +36,9 @@ balanceMigrateUrl = "http://localhost:3200/balance-migrate/"
mode = "dev"
[captcha]
baseUrl = "http://captcha-resolver.out"
#baseUrl = "http://localhost:8890"
#baseUrl = "http://captcha-resolver.out"
baseUrl = "http://likedream-go-captcha:8890"
apiKey = "baca122..."
[redis]
url = "redis://:jhkdjhkjdhsIUTYURTU_pEGmFP@database.out:56379"
+6 -3
View File
@@ -16,13 +16,14 @@ func ApiSemiOCRVerification(bytes []byte, shape1, shape2 int64) string {
data := Bytes2Base64(bytes)
ctx := gctx.GetInitCtx()
baseUrl := g.Config().MustGetWithEnv(ctx, cst.ConfigCaptchaBaseUrl).String() + "/semiOcr"
apiKey := g.Config().MustGetWithEnv(ctx, cst.ConfigCaptchaApiKey).String()
client := httpclient.Cpdaily.Clone(ctx)
client.SetDoNotParseResponse(false)
post, err := client.R().SetBody(map[string]any{
"base64": data,
"shape1": shape1,
"shape2": shape2,
}).Post(baseUrl)
}).SetHeader("X-Api-Key", apiKey).Post(baseUrl)
utils.OkOrPanic(err, func(err error) error {
return oops.
With("SemiOCRVerification", baseUrl).
@@ -37,11 +38,12 @@ func ApiAutoOCRVerification(bytes []byte) string {
data := Bytes2Base64(bytes)
ctx := gctx.GetInitCtx()
baseUrl := g.Config().MustGetWithEnv(ctx, cst.ConfigCaptchaBaseUrl).String() + "/ocr"
apiKey := g.Config().MustGetWithEnv(ctx, cst.ConfigCaptchaApiKey).String()
client := httpclient.Cpdaily.Clone(ctx)
client.SetDoNotParseResponse(false)
post, err := client.R().SetBody(map[string]any{
"base64": data,
}).Post(baseUrl)
}).SetHeader("X-Api-Key", apiKey).Post(baseUrl)
utils.OkOrPanic(err, func(err error) error {
return oops.
With("AutoOCRVerification", baseUrl).
@@ -55,11 +57,12 @@ func ApiAutoOCRVerification(bytes []byte) string {
func ApiAutoCalcVerification(b64 string) string {
ctx := gctx.GetInitCtx()
baseUrl := g.Config().MustGetWithEnv(ctx, cst.ConfigCaptchaBaseUrl).String() + "/calc"
apiKey := g.Config().MustGetWithEnv(ctx, cst.ConfigCaptchaApiKey).String()
client := httpclient.Cpdaily.Clone(ctx)
client.SetDoNotParseResponse(false)
post, err := client.R().SetBody(map[string]any{
"base64": b64,
}).Post(baseUrl)
}).SetHeader("X-Api-Key", apiKey).Post(baseUrl)
utils.OkOrPanic(err, func(err error) error {
return oops.
With("AutoOCRVerification", baseUrl).
@@ -146,8 +146,10 @@ func (r *NormalSubmitCaptchaResolver) getResultFromItStar(rawResponse json.RawMe
utils.OkOrPanic(err)
url := r.getITStarUrl()
apiKey := g.Config().MustGetWithEnv(gctx.GetInitCtx(), cst.ConfigCaptchaApiKey).String()
resp, err := r.client.R().
SetHeader("X-Api-Key", apiKey).
SetBody(responseMap).
Post(url)
utils.OkOrPanic(err)
+55 -43
View File
@@ -226,20 +226,26 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
// 尝试从已签到的历史任务中获取历史数据用于预填充
signedMatch := findMatchTitle(signedTasks)
if signedMatch != nil && (signedMatch["signInstanceWid"] == nil || matchTask["signInstanceWid"] == nil || signedMatch["signInstanceWid"].String() != matchTask["signInstanceWid"].String()) {
histResp, histErr := c.client.R().
SetBody(map[string]*gvar.Var{
"taskName": gvar.New(signedMatch["taskName"].String()),
"signWid": signedMatch["signWid"],
"signInstanceWid": signedMatch["signInstanceWid"],
}).
WithContext(ctx).
Post(c.getReqUrl("detailSignInstance"))
if histErr == nil {
histJSON := utils.ReadJson[map[string]*gvar.Var](histResp.Body)
histDatas := histJSON["datas"].MapStrVar()
if len(histDatas) > 0 {
result["historyRows"] = gvar.New(histDatas)
if signedMatch != nil {
if matchTask != nil && signedMatch["signInstanceWid"] != nil && matchTask["signInstanceWid"] != nil &&
signedMatch["signInstanceWid"].String() == matchTask["signInstanceWid"].String() {
// 任务已签到(同一个 instanceWid),自身 rows 中的 longitude/latitude/position 就是用户自己提交的数据
result["historyRows"] = gvar.New(formDatas)
} else {
histResp, histErr := c.client.R().
SetBody(map[string]*gvar.Var{
"taskName": gvar.New(signedMatch["taskName"].String()),
"signWid": signedMatch["signWid"],
"signInstanceWid": signedMatch["signInstanceWid"],
}).
WithContext(ctx).
Post(c.getReqUrl("detailSignInstance"))
if histErr == nil {
histJSON := utils.ReadJson[map[string]*gvar.Var](histResp.Body)
histDatas := histJSON["datas"].MapStrVar()
if len(histDatas) > 0 {
result["historyRows"] = gvar.New(histDatas)
}
}
}
}
@@ -436,9 +442,11 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
// 优先从 historyRows(已签到的历史任务详情)中提取历史值,否则从 rows 中提取
histRows := rows
hasHistory := false
if hr := rawJson["historyRows"]; hr != nil {
if hrMap := hr.MapStrVar(); len(hrMap) > 0 {
histRows = hrMap
hasHistory = true
}
}
@@ -450,47 +458,51 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
histSignPhotoUrl := ""
histIsMalposition := ""
// 优先从 signPlaceSelected 提取经纬度和地址
if sps := histRows["signPlaceSelected"]; sps != nil && sps.String() != "" && sps.String() != "[]" {
placeArr := gjson.Parse(sps.String()).Array()
if len(placeArr) > 0 {
place := placeArr[0]
lng := place.Get("longitude").String()
lat := place.Get("latitude").String()
addr := place.Get("address").String()
if lng != "" && lat != "" {
histLatAndLon = lng + "," + lat
}
if addr != "" {
histAddress = addr
}
}
}
if histLatAndLon == "" {
// 优先使用历史签到数据(真实地址),无历史时保底使用管理员配置的范围信息
if hasHistory {
// 从历史签到数据中提取用户真实的地址和经纬度
if lon := histRows["longitude"]; lon != nil && lon.String() != "" {
if lat := histRows["latitude"]; lat != nil && lat.String() != "" {
histLatAndLon = lon.String() + "," + lat.String()
}
}
}
if histAddress == "" {
if pos := histRows["position"]; pos != nil && pos.String() != "" {
histAddress = pos.String()
if histAddress == "" {
if pos := histRows["position"]; pos != nil && pos.String() != "" {
histAddress = pos.String()
}
}
if histAddress == "" {
if addr := histRows["signAddress"]; addr != nil && addr.String() != "" {
histAddress = addr.String()
}
}
if photo := histRows["signPhotoUrl"]; photo != nil && photo.String() != "" {
histSignPhotoUrl = photo.String()
}
if mal := histRows["isMalposition"]; mal != nil {
if mal.Int() == 1 {
histIsMalposition = "是"
} else {
histIsMalposition = "否"
}
}
}
if photo := histRows["signPhotoUrl"]; photo != nil && photo.String() != "" {
histSignPhotoUrl = photo.String()
}
if mal := histRows["isMalposition"]; mal != nil {
if mal.Int() == 1 {
histIsMalposition = "是"
} else {
histIsMalposition = "否"
// 无历史签到数据时,保底使用管理员配置的范围信息
if histLatAndLon == "" && histAddress == "" {
if sps := rows["signPlaceSelected"]; sps != nil && sps.String() != "" && sps.String() != "[]" {
placeArr := gjson.Parse(sps.String()).Array()
if len(placeArr) > 0 {
place := placeArr[0]
lng := place.Get("longitude").String()
lat := place.Get("latitude").String()
addr := place.Get("address").String()
if lng != "" && lat != "" {
histLatAndLon = lng + "," + lat
}
if addr != "" {
histAddress = addr
}
}
}
}
+95 -90
View File
@@ -221,7 +221,6 @@ func (c *CpdailySleepCheckTask) QueryFormByTitle(ctx context.Context, titleGlob
signedTasks := datas["signedTasks"].Array()
var matchTask map[string]*gvar.Var
isFromSigned := false
matchTask = findMatchTitle(unSignedTasks)
if matchTask == nil {
@@ -229,9 +228,6 @@ func (c *CpdailySleepCheckTask) QueryFormByTitle(ctx context.Context, titleGlob
if matchTask == nil {
matchTask = findMatchTitle(signedTasks)
if matchTask != nil {
isFromSigned = true
}
if matchTask == nil {
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("没有查询到查寝任务: %s", titleGlob)), func(err error) error {
@@ -281,11 +277,15 @@ func (c *CpdailySleepCheckTask) QueryFormByTitle(ctx context.Context, titleGlob
result["taskInfo"] = gvar.New(matchTask)
result["rows"] = gvar.New(datas)
// 如果当前任务不是已签到的,尝试从已签到的历史任务中获取历史数据用于预填充
if !isFromSigned {
// 先看今天有没有已签到的同名任务
signedMatch := findMatchTitle(signedTasks)
if signedMatch != nil {
// 尝试从已签到的历史任务中获取历史数据用于预填充
// 无论当前任务是否已签到,都尝试获取历史数据
signedMatch := findMatchTitle(signedTasks)
if signedMatch != nil {
if matchTask != nil && signedMatch["signInstanceWid"] != nil && matchTask["signInstanceWid"] != nil &&
signedMatch["signInstanceWid"].String() == matchTask["signInstanceWid"].String() {
// 任务已签到(同一个 instanceWid),自身 rows 中的 longitude/latitude/position 就是用户自己提交的数据
result["historyRows"] = gvar.New(datas)
} else {
histResp, histErr := c.client.R().
SetBody(map[string]*gvar.Var{
"taskName": gvar.New(signedMatch["taskName"].String()),
@@ -302,63 +302,63 @@ func (c *CpdailySleepCheckTask) QueryFormByTitle(ctx context.Context, titleGlob
}
}
}
// 今天没有已签到的同名任务,从历史月份中只查 signedTasks
if result["historyRows"] == nil {
func() {
defer func() { recover() }()
now := time.Now().In(cst.TimeZoneShangHai)
year := strconv.Itoa(now.Year())
month := strconv.Itoa(int(now.Month()))
if len(month) == 1 {
month = "0" + month
}
resp, e := c.client.R().
SetBody(map[string]any{
"statisticYearMonth": fmt.Sprintf("%s-%s", year, month),
}).
WithContext(ctx).
Post(c.getReqUrl("getStuSignInfosByWeekMonth"))
if e != nil {
return
}
respJSON := utils.ReadJson[map[string]*gvar.Var](resp.Body)
monthDatas := respJSON["datas"].MapStrVar()
monthRows := monthDatas["rows"].Vars()
}
// 今天没有已签到的同名任务,从历史月份中只查 signedTasks
if result["historyRows"] == nil {
func() {
defer func() { recover() }()
now := time.Now().In(cst.TimeZoneShangHai)
year := strconv.Itoa(now.Year())
month := strconv.Itoa(int(now.Month()))
if len(month) == 1 {
month = "0" + month
}
resp, e := c.client.R().
SetBody(map[string]any{
"statisticYearMonth": fmt.Sprintf("%s-%s", year, month),
}).
WithContext(ctx).
Post(c.getReqUrl("getStuSignInfosByWeekMonth"))
if e != nil {
return
}
respJSON := utils.ReadJson[map[string]*gvar.Var](resp.Body)
monthDatas := respJSON["datas"].MapStrVar()
monthRows := monthDatas["rows"].Vars()
// 只从 signedTasks 中查找匹配的已签到任务
for _, row := range monthRows {
rowMap := row.MapStrVar()
signed := rowMap["signedTasks"].Vars()
for _, st := range signed {
item := st.MapStrVar()
tn, exist := item["taskName"]
if !exist || tn.String() == "" {
// 只从 signedTasks 中查找匹配的已签到任务
for _, row := range monthRows {
rowMap := row.MapStrVar()
signed := rowMap["signedTasks"].Vars()
for _, st := range signed {
item := st.MapStrVar()
tn, exist := item["taskName"]
if !exist || tn.String() == "" {
continue
}
if match.Match(tn.String(), titleGlob) {
// 找到已签到的历史任务,获取详情
dr, de := c.client.R().
SetBody(map[string]*gvar.Var{
"signInstanceWid": item["signInstanceWid"],
"signWid": item["signWid"],
"taskName": gvar.New(tn.String()),
}).
WithContext(ctx).
Post(c.getReqUrl("detailSignInstance"))
if de != nil {
continue
}
if match.Match(tn.String(), titleGlob) {
// 找到已签到的历史任务,获取详情
dr, de := c.client.R().
SetBody(map[string]*gvar.Var{
"signInstanceWid": item["signInstanceWid"],
"signWid": item["signWid"],
"taskName": gvar.New(tn.String()),
}).
WithContext(ctx).
Post(c.getReqUrl("detailSignInstance"))
if de != nil {
continue
}
dj := utils.ReadJson[map[string]*gvar.Var](dr.Body)
dd := dj["datas"].MapStrVar()
if len(dd) > 0 {
result["historyRows"] = gvar.New(dd)
return
}
dj := utils.ReadJson[map[string]*gvar.Var](dr.Body)
dd := dj["datas"].MapStrVar()
if len(dd) > 0 {
result["historyRows"] = gvar.New(dd)
return
}
}
}
}()
}
}
}()
}
return result
@@ -518,9 +518,11 @@ func (c *CpdailySleepCheckTask) ParseFormJson(ctx context.Context, rawJson map[s
// 优先从 historyRows(已签到的历史任务详情)中提取历史值,否则从 rows 中提取
histRows := rows
hasHistory := false
if hr := rawJson["historyRows"]; hr != nil {
if hrMap := hr.MapStrVar(); len(hrMap) > 0 {
histRows = hrMap
hasHistory = true
}
}
@@ -533,48 +535,51 @@ func (c *CpdailySleepCheckTask) ParseFormJson(ctx context.Context, rawJson map[s
histSignPhotoUrl := ""
histIsMalposition := ""
// 优先从 signPlaceSelected 提取经纬度和地址
if sps := histRows["signPlaceSelected"]; sps != nil && sps.String() != "" && sps.String() != "[]" {
placeArr := gjson.Parse(sps.String()).Array()
if len(placeArr) > 0 {
place := placeArr[0]
lng := place.Get("longitude").String()
lat := place.Get("latitude").String()
addr := place.Get("address").String()
if lng != "" && lat != "" {
histLatAndLon = lng + "," + lat
}
if addr != "" {
histAddress = addr
}
}
}
// 降级:直接从 longitude/latitude/position 字段取
if histLatAndLon == "" {
// 优先使用历史签到数据(真实地址),无历史时保底使用管理员配置的范围信息
if hasHistory {
// 从历史签到数据中提取用户真实的地址和经纬度
if lon := histRows["longitude"]; lon != nil && lon.String() != "" {
if lat := histRows["latitude"]; lat != nil && lat.String() != "" {
histLatAndLon = lon.String() + "," + lat.String()
}
}
}
if histAddress == "" {
if pos := histRows["position"]; pos != nil && pos.String() != "" {
histAddress = pos.String()
if histAddress == "" {
if pos := histRows["position"]; pos != nil && pos.String() != "" {
histAddress = pos.String()
}
}
if histAddress == "" {
if addr := histRows["signAddress"]; addr != nil && addr.String() != "" {
histAddress = addr.String()
}
}
if photo := histRows["signPhotoUrl"]; photo != nil && photo.String() != "" {
histSignPhotoUrl = photo.String()
}
if mal := histRows["isMalposition"]; mal != nil {
if mal.Int() == 1 {
histIsMalposition = "是"
} else {
histIsMalposition = "否"
}
}
}
if photo := histRows["signPhotoUrl"]; photo != nil && photo.String() != "" {
histSignPhotoUrl = photo.String()
}
if mal := histRows["isMalposition"]; mal != nil {
if mal.Int() == 1 {
histIsMalposition = "是"
} else {
histIsMalposition = "否"
// 无历史签到数据时,保底使用管理员配置的范围信息
if histLatAndLon == "" && histAddress == "" {
if sps := rows["signPlaceSelected"]; sps != nil && sps.String() != "" && sps.String() != "[]" {
placeArr := gjson.Parse(sps.String()).Array()
if len(placeArr) > 0 {
place := placeArr[0]
lng := place.Get("longitude").String()
lat := place.Get("latitude").String()
addr := place.Get("address").String()
if lng != "" && lat != "" {
histLatAndLon = lng + "," + lat
}
if addr != "" {
histAddress = addr
}
}
}
}
+10 -5
View File
@@ -166,13 +166,18 @@ func (c *Course) Refresh(ctx context.Context, c2 model.Course, ch model.Chapter,
}
func ParseJsUrl(str string) string {
// <script defer src="https://cdnbasic.scbdc.edu.cn/%E7%9C%81%E7%BA%A7%E8%B5%84%E6%BA%90/hd/chunk-vendors.5e79f5ce155849.js">
re := regexp.MustCompile(`https://[^"'\s]+chunk-vendors[^"'\s]+\.js`)
match := re.FindString(str)
if match == "" {
// 网站已更新,chunk-vendors 不再存在。
// 现在从 HTML 中找到任一 chunk-*.js 的 URL,提取其 base 路径和 hash,
// 然后构造包含 src_views_home_index_vue 的组合 chunk 文件 URL。
re := regexp.MustCompile(`(https://[^"'\s]+/)chunk-(?:libs|elementUI)\.([0-9a-f]+)\.js`)
match := re.FindStringSubmatch(str)
if len(match) < 3 {
return ""
}
return strings.Replace(match, "chunk-vendors", "src_views_home_index_vue", 1)
basePath := match[1]
hash := match[2]
// 用已知的组合 chunk 名称拼出 URL:该 chunk 同时包含首页和 CourseList 组件
return basePath + "src_views_home_index_vue-src_views_noPermission_index_vue-src_views_components_CourseList_vue." + hash + ".js"
}
func (c *Course) GetCourseProcees(ctx context.Context, courseId string) (finished string, total string) {
post, err := c.Client.R().SetHeader("X-Token", c.Token).SetBody(map[string]any{
+1
View File
@@ -15,6 +15,7 @@ const (
ConfigAuthorizationKey = "server.authorization"
ConfigJwtKey = "server.jwt"
ConfigCaptchaBaseUrl = "captcha.baseUrl"
ConfigCaptchaApiKey = "captcha.apiKey"
ConfigS3AccessKey = "s3.accessKey"
ConfigS3SecretKey = "s3.secretKey"
ConfigS3BaseUrl = "s3.baseUrl"
+17 -13
View File
@@ -33,18 +33,22 @@ func InitDB() {
Global = client
dbDsn2, err := g.Cfg().Get(gctx.New(), cst.ConfigDatabaseDsn2)
utils.OkOrPanic(err)
GlobalGorm, err = gorm.Open(postgres.Open(dbDsn2.String()), &gorm.Config{})
if err != nil {
logger.Logger.Fatal("连接pg数据库失败: %v", zap.Error(err))
// PG 数据库为可选配置,如果 dsn2 为空则跳过
if dbDsn2.String() != "" {
GlobalGorm, err = gorm.Open(postgres.Open(dbDsn2.String()), &gorm.Config{})
if err != nil {
logger.Logger.Warn("连接pg数据库失败, 跳过: %v", zap.Error(err))
} else {
// 可选:配置连接池
sqlDB, err := GlobalGorm.DB()
if err != nil {
logger.Logger.Warn("获取pg数据库实例失败, 跳过: %v", zap.Error(err))
} else {
// 设置连接池参数
sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量
sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量
sqlDB.SetConnMaxLifetime(0) // 设置连接可复用的最大时间(0表示永久)
}
}
}
// 可选:配置连接池
sqlDB, err := GlobalGorm.DB()
if err != nil {
logger.Logger.Fatal("获取数据库实例失败: %v", zap.Error(err))
}
// 设置连接池参数
sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量
sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量
sqlDB.SetConnMaxLifetime(0) // 设置连接可复用的最大时间(0表示永久)
}
@@ -270,6 +270,9 @@ func (s *UserInfoServiceV1) RequestBalanceMigrate(ctx context.Context, req *v1.R
}
// 查询旧系统数据库中是否存在该邮箱的用户
if db.GlobalGorm == nil {
return utils.SuccessWithMsg("如果该邮箱在旧系统中存在积分,转移链接已发送")
}
var oldUser AspNetUser
err := db.GlobalGorm.Table("AspNetUsers").Where("email = ?", oldSystemEmail).First(&oldUser).Error
if err != nil {
@@ -343,6 +346,9 @@ func (s *UserInfoServiceV1) BalanceMigrate(ctx context.Context, req *v1.BalanceM
}
// 查询旧系统用户
if db.GlobalGorm == nil {
return utils.FailParam("旧系统数据库未连接")
}
var oldUser AspNetUser
err := db.GlobalGorm.Table("AspNetUsers").Where("email = ?", oldSystemEmail).First(&oldUser).Error
if err != nil {