mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-30 23:14:28 +08:00
更新配置代码
This commit is contained in:
@@ -94,15 +94,24 @@ func LoadSystemConfig(db *gorm.DB) *types.SystemConfig {
|
|||||||
logger.Error("load license config error: ", err)
|
logger.Error("load license config error: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载 GeekAPI 配置
|
// 加载验证码配置
|
||||||
var geekAPIConfig types.GeekAPIConfig
|
var captchaConfig types.CaptchaConfig
|
||||||
sysConfig.Id = 0
|
sysConfig.Id = 0
|
||||||
db.Where("name", types.ConfigKeyGeekAPI).First(&sysConfig)
|
db.Where("name", types.ConfigKeyCaptcha).First(&sysConfig)
|
||||||
err = utils.JsonDecode(sysConfig.Value, &geekAPIConfig)
|
err = utils.JsonDecode(sysConfig.Value, &captchaConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("load geek service config error: ", err)
|
logger.Error("load geek service config error: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载微信登录配置
|
||||||
|
var wxLoginConfig types.WxLoginConfig
|
||||||
|
sysConfig.Id = 0
|
||||||
|
db.Where("name", types.ConfigKeyWxLogin).First(&sysConfig)
|
||||||
|
err = utils.JsonDecode(sysConfig.Value, &wxLoginConfig)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("load wx login config error: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
// 加载短信配置
|
// 加载短信配置
|
||||||
var smsConfig types.SMSConfig
|
var smsConfig types.SMSConfig
|
||||||
sysConfig.Id = 0
|
sysConfig.Id = 0
|
||||||
@@ -146,6 +155,7 @@ func LoadSystemConfig(db *gorm.DB) *types.SystemConfig {
|
|||||||
OSS: ossConfig,
|
OSS: ossConfig,
|
||||||
SMTP: smtpConfig,
|
SMTP: smtpConfig,
|
||||||
Payment: paymentConfig,
|
Payment: paymentConfig,
|
||||||
GeekAPI: geekAPIConfig,
|
Captcha: captchaConfig,
|
||||||
|
WxLogin: wxLoginConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,8 @@ type SystemConfig struct {
|
|||||||
OSS OSSConfig
|
OSS OSSConfig
|
||||||
SMS SMSConfig
|
SMS SMSConfig
|
||||||
SMTP SmtpConfig
|
SMTP SmtpConfig
|
||||||
GeekAPI GeekAPIConfig
|
Captcha CaptchaConfig
|
||||||
|
WxLogin WxLoginConfig
|
||||||
Jimeng JimengConfig
|
Jimeng JimengConfig
|
||||||
License License
|
License License
|
||||||
}
|
}
|
||||||
@@ -121,7 +122,8 @@ const (
|
|||||||
ConfigKeyNotice = "notice"
|
ConfigKeyNotice = "notice"
|
||||||
ConfigKeyAgreement = "agreement"
|
ConfigKeyAgreement = "agreement"
|
||||||
ConfigKeyPrivacy = "privacy"
|
ConfigKeyPrivacy = "privacy"
|
||||||
ConfigKeyGeekAPI = "geekapi"
|
ConfigKeyCaptcha = "captcha"
|
||||||
|
ConfigKeyWxLogin = "wx_login"
|
||||||
ConfigKeyLicense = "license"
|
ConfigKeyLicense = "license"
|
||||||
ConfigKeySms = "sms"
|
ConfigKeySms = "sms"
|
||||||
ConfigKeySmtp = "smtp"
|
ConfigKeySmtp = "smtp"
|
||||||
|
|||||||
@@ -31,8 +31,3 @@ type WxLoginConfig struct {
|
|||||||
NotifyURL string `json:"notify_url"` // 登录成功回调 URL
|
NotifyURL string `json:"notify_url"` // 登录成功回调 URL
|
||||||
Enabled bool `json:"enabled"` // 是否启用微信登录
|
Enabled bool `json:"enabled"` // 是否启用微信登录
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeekAPIConfig struct {
|
|
||||||
Captcha CaptchaConfig
|
|
||||||
WxLogin WxLoginConfig
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package types
|
|||||||
|
|
||||||
type PaymentConfig struct {
|
type PaymentConfig struct {
|
||||||
Alipay AlipayConfig `json:"alipay"` // 支付宝支付渠道配置
|
Alipay AlipayConfig `json:"alipay"` // 支付宝支付渠道配置
|
||||||
Epay EpayConfig `json:"epay"` // GEEK 支付配置
|
Epay EpayConfig `json:"epay"` // 易支付配置
|
||||||
WxPay WxPayConfig `json:"wxpay"` // 微信支付渠道配置
|
WxPay WxPayConfig `json:"wxpay"` // 微信支付渠道配置
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,109 +8,379 @@ package admin
|
|||||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"geekai/core"
|
"geekai/core"
|
||||||
"geekai/core/middleware"
|
"geekai/core/middleware"
|
||||||
"geekai/core/types"
|
"geekai/core/types"
|
||||||
"geekai/handler"
|
"geekai/handler"
|
||||||
"geekai/service"
|
"geekai/service"
|
||||||
"geekai/store"
|
"geekai/service/oss"
|
||||||
|
"geekai/service/payment"
|
||||||
|
"geekai/service/sms"
|
||||||
"geekai/store/model"
|
"geekai/store/model"
|
||||||
"geekai/utils"
|
"geekai/utils"
|
||||||
"geekai/utils/resp"
|
"geekai/utils/resp"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/shirou/gopsutil/host"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigHandler struct {
|
type ConfigHandler struct {
|
||||||
handler.BaseHandler
|
handler.BaseHandler
|
||||||
levelDB *store.LevelDB
|
|
||||||
licenseService *service.LicenseService
|
licenseService *service.LicenseService
|
||||||
configService *service.ConfigService
|
sysConfig *types.SystemConfig
|
||||||
|
alipayService *payment.AlipayService
|
||||||
|
wxpayService *payment.WxPayService
|
||||||
|
epayService *payment.EPayService
|
||||||
|
smsAliyun *sms.AliYunSmsService
|
||||||
|
smsBao *sms.BaoSmsService
|
||||||
|
smsManager *sms.SmsManager
|
||||||
|
localOss *oss.LocalStorage
|
||||||
|
qiniuOss *oss.QiNiuOss
|
||||||
|
aliyunOss *oss.AliYunOss
|
||||||
|
minioOss *oss.MiniOss
|
||||||
|
smtpService *service.SmtpService
|
||||||
|
captchaService *service.CaptchaService
|
||||||
|
wxLoginService *service.WxLoginService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfigHandler(app *core.AppServer, db *gorm.DB, levelDB *store.LevelDB, licenseService *service.LicenseService, configService *service.ConfigService) *ConfigHandler {
|
func NewConfigHandler(
|
||||||
|
app *core.AppServer,
|
||||||
|
db *gorm.DB,
|
||||||
|
licenseService *service.LicenseService,
|
||||||
|
sysConfig *types.SystemConfig,
|
||||||
|
alipayService *payment.AlipayService,
|
||||||
|
wxpayService *payment.WxPayService,
|
||||||
|
epayService *payment.EPayService,
|
||||||
|
smsAliyun *sms.AliYunSmsService,
|
||||||
|
smsBao *sms.BaoSmsService,
|
||||||
|
smsManager *sms.SmsManager,
|
||||||
|
localOss *oss.LocalStorage,
|
||||||
|
qiniuOss *oss.QiNiuOss,
|
||||||
|
aliyunOss *oss.AliYunOss,
|
||||||
|
minioOss *oss.MiniOss,
|
||||||
|
smtpService *service.SmtpService,
|
||||||
|
captchaService *service.CaptchaService,
|
||||||
|
wxLoginService *service.WxLoginService,
|
||||||
|
) *ConfigHandler {
|
||||||
return &ConfigHandler{
|
return &ConfigHandler{
|
||||||
BaseHandler: handler.BaseHandler{App: app, DB: db},
|
BaseHandler: handler.BaseHandler{App: app, DB: db},
|
||||||
levelDB: levelDB,
|
|
||||||
licenseService: licenseService,
|
licenseService: licenseService,
|
||||||
configService: configService,
|
sysConfig: sysConfig,
|
||||||
|
alipayService: alipayService,
|
||||||
|
wxpayService: wxpayService,
|
||||||
|
epayService: epayService,
|
||||||
|
smsAliyun: smsAliyun,
|
||||||
|
smsBao: smsBao,
|
||||||
|
smsManager: smsManager,
|
||||||
|
localOss: localOss,
|
||||||
|
qiniuOss: qiniuOss,
|
||||||
|
aliyunOss: aliyunOss,
|
||||||
|
minioOss: minioOss,
|
||||||
|
smtpService: smtpService,
|
||||||
|
captchaService: captchaService,
|
||||||
|
wxLoginService: wxLoginService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterRoutes 注册路由
|
// RegisterRoutes 注册路由
|
||||||
func (h *ConfigHandler) RegisterRoutes() {
|
func (h *ConfigHandler) RegisterRoutes() {
|
||||||
group := h.App.Engine.Group("/api/admin/config/")
|
rg := h.App.Engine.Group("/api/admin/config")
|
||||||
group.GET("get", h.Get)
|
|
||||||
|
|
||||||
// 需要管理员授权的接口
|
// 需要管理员登录的接口
|
||||||
group.Use(middleware.AdminAuthMiddleware(h.App.Config.AdminSession.SecretKey, h.App.Redis))
|
rg.Use(middleware.AdminAuthMiddleware(h.App.Config.AdminSession.SecretKey, h.App.Redis))
|
||||||
{
|
{
|
||||||
group.POST("update", h.Update)
|
rg.POST("update/base", h.UpdateBase)
|
||||||
group.POST("active", h.Active)
|
rg.POST("update/notice", h.UpdateNotice)
|
||||||
group.POST("test", h.Test)
|
rg.POST("update/captcha", h.UpdateCaptcha)
|
||||||
group.GET("license", h.GetLicense)
|
rg.POST("update/wx_login", h.UpdateWxLogin)
|
||||||
|
rg.POST("update/payment", h.UpdatePayment)
|
||||||
|
rg.POST("update/sms", h.UpdateSms)
|
||||||
|
rg.POST("update/oss", h.UpdateOss)
|
||||||
|
rg.POST("update/smtp", h.UpdateStmp)
|
||||||
|
rg.GET("get", h.Get)
|
||||||
|
rg.POST("license/active", h.Active)
|
||||||
|
rg.GET("license/get", h.GetLicense)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ConfigHandler) Update(c *gin.Context) {
|
// UpdateBase 更新基础配置
|
||||||
var payload struct {
|
func (h *ConfigHandler) UpdateBase(c *gin.Context) {
|
||||||
Key string `json:"key"`
|
var data types.BaseConfig
|
||||||
Config json.RawMessage `json:"config"`
|
|
||||||
ConfigBak types.SystemConfig `json:"config_bak,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.ShouldBindJSON(&payload); err != nil {
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
logger.Errorf("Update config failed: %v", err)
|
|
||||||
resp.ERROR(c, types.InvalidArgs)
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.Key == "system" {
|
// 未授权的话不允许修改版权
|
||||||
var sys types.SystemConfig
|
license := h.licenseService.GetLicense()
|
||||||
if err := json.Unmarshal(payload.Config, &sys); err != nil {
|
if !license.IsActive && data.Copyright != h.sysConfig.Base.Copyright {
|
||||||
resp.ERROR(c, "系统配置解析失败: "+err.Error())
|
resp.ERROR(c, "未授权系统不允许修改版权信息")
|
||||||
return
|
return
|
||||||
}
|
|
||||||
if (sys.Base.Copyright != payload.ConfigBak.Base.Copyright) && !h.licenseService.GetLicense().Configs.DeCopy {
|
|
||||||
resp.ERROR(c, "您无权修改版权信息,请先联系作者获取授权")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用统一配置服务写入与广播
|
// 未授权的话不允许修改 Logo
|
||||||
if err := h.configService.Set(payload.Key, payload.Config); err != nil {
|
if !license.IsActive && data.Logo != h.sysConfig.Base.Logo {
|
||||||
|
resp.ERROR(c, "未授权系统不允许修改 Logo")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := h.Update(types.ConfigKeySystem, data)
|
||||||
|
if err != nil {
|
||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if payload.Key == "system" {
|
|
||||||
var sys types.SystemConfig
|
h.sysConfig.Base = data
|
||||||
if err := json.Unmarshal(payload.Config, &sys); err == nil {
|
|
||||||
h.App.SysConfig = &sys
|
resp.SUCCESS(c, data)
|
||||||
}
|
|
||||||
}
|
|
||||||
resp.SUCCESS(c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 获取指定的系统配置
|
// UpdateNotice 更新公告配置
|
||||||
func (h *ConfigHandler) Get(c *gin.Context) {
|
func (h *ConfigHandler) UpdateNotice(c *gin.Context) {
|
||||||
key := c.Query("key")
|
var data struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := h.Update(types.ConfigKeyNotice, data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCaptcha 更新行为验证码配置
|
||||||
|
func (h *ConfigHandler) UpdateCaptcha(c *gin.Context) {
|
||||||
|
var data types.CaptchaConfig
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := h.Update(types.ConfigKeyCaptcha, data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if data.Enabled {
|
||||||
|
h.captchaService.UpdateConfig(data)
|
||||||
|
}
|
||||||
|
h.sysConfig.Captcha = data
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePayment 更新支付配置
|
||||||
|
func (h *ConfigHandler) UpdatePayment(c *gin.Context) {
|
||||||
|
var data types.PaymentConfig
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var config model.Config
|
var config model.Config
|
||||||
res := h.DB.Where("name", key).First(&config)
|
oldData := types.PaymentConfig{}
|
||||||
if res.Error != nil {
|
err := h.DB.Where("name", types.ConfigKeyPayment).First(&config).Error
|
||||||
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
|
if err == nil {
|
||||||
resp.SUCCESS(c, map[string]interface{}{})
|
utils.JsonDecode(config.Value, &oldData)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.Update(types.ConfigKeyPayment, data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果启用状态发生改变,则需要更新支付服务配置
|
||||||
|
if data.WxPay.Enabled {
|
||||||
|
err = h.wxpayService.UpdateConfig(&data.WxPay)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if data.Epay.Enabled {
|
||||||
|
h.epayService.UpdateConfig(&data.Epay)
|
||||||
|
}
|
||||||
|
if data.Alipay.Enabled {
|
||||||
|
err = h.alipayService.UpdateConfig(&data.Alipay)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.sysConfig.Payment = data
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSms 更新短信配置
|
||||||
|
func (h *ConfigHandler) UpdateSms(c *gin.Context) {
|
||||||
|
var data types.SMSConfig
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var config model.Config
|
||||||
|
oldData := types.SMSConfig{}
|
||||||
|
err := h.DB.Where("name", types.ConfigKeySms).First(&config).Error
|
||||||
|
if err == nil {
|
||||||
|
utils.JsonDecode(config.Value, &oldData)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.Update(types.ConfigKeySms, data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新服务配置
|
||||||
|
switch data.Active {
|
||||||
|
case sms.Ali:
|
||||||
|
err = h.smsAliyun.UpdateConfig(&data.Ali)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case sms.Bao:
|
||||||
|
h.smsBao.UpdateConfig(&data.Bao)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.smsManager.SetActive(data.Active)
|
||||||
|
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOss 更新 Oss 配置
|
||||||
|
func (h *ConfigHandler) UpdateOss(c *gin.Context) {
|
||||||
|
var data types.OSSConfig
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var config model.Config
|
||||||
|
oldData := types.OSSConfig{}
|
||||||
|
err := h.DB.Where("name", types.ConfigKeyOss).First(&config).Error
|
||||||
|
if err == nil {
|
||||||
|
utils.JsonDecode(config.Value, &oldData)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.Update("oss", data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新服务配置
|
||||||
|
switch data.Active {
|
||||||
|
case oss.Local:
|
||||||
|
h.localOss.UpdateConfig(&data.Local)
|
||||||
|
case oss.QiNiu:
|
||||||
|
h.qiniuOss.UpdateConfig(&data.QiNiu)
|
||||||
|
case oss.AliYun:
|
||||||
|
err := h.aliyunOss.UpdateConfig(&data.AliYun)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case oss.Minio:
|
||||||
|
err := h.minioOss.UpdateConfig(&data.Minio)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.sysConfig.OSS = data
|
||||||
|
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateStmp 更新 Stmp 配置
|
||||||
|
func (h *ConfigHandler) UpdateStmp(c *gin.Context) {
|
||||||
|
var data types.SmtpConfig
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var config model.Config
|
||||||
|
oldData := types.SmtpConfig{}
|
||||||
|
err := h.DB.Where("name", types.ConfigKeySmtp).First(&config).Error
|
||||||
|
if err == nil {
|
||||||
|
utils.JsonDecode(config.Value, &oldData)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.Update(types.ConfigKeySmtp, data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置发生改变时更新服务配置
|
||||||
|
if !data.Equal(&oldData) {
|
||||||
|
h.smtpService.UpdateConfig(&data)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.sysConfig.SMTP = data
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWxLogin 更新微信登录配置
|
||||||
|
func (h *ConfigHandler) UpdateWxLogin(c *gin.Context) {
|
||||||
|
var data types.WxLoginConfig
|
||||||
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := h.Update(types.ConfigKeyWxLogin, data)
|
||||||
|
if err != nil {
|
||||||
|
resp.ERROR(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Enabled {
|
||||||
|
h.wxLoginService.UpdateConfig(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.sysConfig.WxLogin = data
|
||||||
|
resp.SUCCESS(c, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 更新系统配置
|
||||||
|
func (h *ConfigHandler) Update(name string, value any) error {
|
||||||
|
var config model.Config
|
||||||
|
err := h.DB.Where("name", name).First(&config).Error
|
||||||
|
if err != nil { // 不存在则创建
|
||||||
|
config.Name = name
|
||||||
|
config.Value = utils.JsonEncode(value)
|
||||||
|
return h.DB.Create(&config).Error
|
||||||
|
} else { // 存在则更新
|
||||||
|
config.Value = utils.JsonEncode(value)
|
||||||
|
return h.DB.Updates(&config).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 获取指定名称的系统配置
|
||||||
|
func (h *ConfigHandler) Get(c *gin.Context) {
|
||||||
|
name := c.Query("key")
|
||||||
|
var config model.Config
|
||||||
|
res := h.DB.Where("name", name).First(&config)
|
||||||
|
if res.Error != nil {
|
||||||
resp.ERROR(c, res.Error.Error())
|
resp.ERROR(c, res.Error.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var value map[string]interface{}
|
var value map[string]any
|
||||||
err := utils.JsonDecode(config.Value, &value)
|
err := utils.JsonDecode(config.Value, &value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
@@ -120,23 +390,6 @@ func (h *ConfigHandler) Get(c *gin.Context) {
|
|||||||
resp.SUCCESS(c, value)
|
resp.SUCCESS(c, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test 配置测试(占位)
|
|
||||||
func (h *ConfigHandler) Test(c *gin.Context) {
|
|
||||||
var data struct {
|
|
||||||
Key string `json:"key"`
|
|
||||||
}
|
|
||||||
if err := c.ShouldBindJSON(&data); err != nil {
|
|
||||||
resp.ERROR(c, types.InvalidArgs)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg, err := h.configService.Test(data.Key)
|
|
||||||
if err != nil {
|
|
||||||
resp.ERROR(c, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.SUCCESS(c, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Active 激活系统
|
// Active 激活系统
|
||||||
func (h *ConfigHandler) Active(c *gin.Context) {
|
func (h *ConfigHandler) Active(c *gin.Context) {
|
||||||
var data struct {
|
var data struct {
|
||||||
@@ -146,19 +399,21 @@ func (h *ConfigHandler) Active(c *gin.Context) {
|
|||||||
resp.ERROR(c, types.InvalidArgs)
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
info, err := host.Info()
|
|
||||||
|
err := h.licenseService.ActiveLicense(data.License)
|
||||||
|
license := h.licenseService.GetLicense()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err := h.Update(types.ConfigKeyLicense, license); err != nil {
|
||||||
err = h.licenseService.ActiveLicense(data.License, info.HostID)
|
|
||||||
if err != nil {
|
|
||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 更新系统配置
|
||||||
|
h.sysConfig.License = *license
|
||||||
|
|
||||||
resp.SUCCESS(c)
|
resp.SUCCESS(c, license.MachineId)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,3 +422,5 @@ func (h *ConfigHandler) GetLicense(c *gin.Context) {
|
|||||||
license := h.licenseService.GetLicense()
|
license := h.licenseService.GetLicense()
|
||||||
resp.SUCCESS(c, license)
|
resp.SUCCESS(c, license)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type CaptchaHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewCaptchaHandler(app *core.AppServer, s *service.CaptchaService, sysConfig *types.SystemConfig) *CaptchaHandler {
|
func NewCaptchaHandler(app *core.AppServer, s *service.CaptchaService, sysConfig *types.SystemConfig) *CaptchaHandler {
|
||||||
return &CaptchaHandler{App: app, service: s, config: sysConfig.GeekAPI.Captcha}
|
return &CaptchaHandler{App: app, service: s, config: sysConfig.Captcha}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterRoutes 注册路由
|
// RegisterRoutes 注册路由
|
||||||
|
|||||||
@@ -144,7 +144,6 @@ func main() {
|
|||||||
fx.Provide(handler.NewPowerLogHandler),
|
fx.Provide(handler.NewPowerLogHandler),
|
||||||
fx.Provide(handler.NewJimengHandler),
|
fx.Provide(handler.NewJimengHandler),
|
||||||
|
|
||||||
fx.Provide(service.NewConfigService),
|
|
||||||
fx.Provide(service.NewMigrationService),
|
fx.Provide(service.NewMigrationService),
|
||||||
fx.Invoke(func(migrationService *service.MigrationService) {
|
fx.Invoke(func(migrationService *service.MigrationService) {
|
||||||
migrationService.StartMigrate()
|
migrationService.StartMigrate()
|
||||||
@@ -221,10 +220,10 @@ func main() {
|
|||||||
fx.Provide(sms.NewBaoSmsService),
|
fx.Provide(sms.NewBaoSmsService),
|
||||||
fx.Provide(sms.NewSmsManager),
|
fx.Provide(sms.NewSmsManager),
|
||||||
fx.Provide(func(config *types.SystemConfig) *service.CaptchaService {
|
fx.Provide(func(config *types.SystemConfig) *service.CaptchaService {
|
||||||
return service.NewCaptchaService(config.GeekAPI.Captcha)
|
return service.NewCaptchaService(config.Captcha)
|
||||||
}),
|
}),
|
||||||
fx.Provide(func(config *types.SystemConfig, client *redis.Client) *service.WxLoginService {
|
fx.Provide(func(config *types.SystemConfig, client *redis.Client) *service.WxLoginService {
|
||||||
return service.NewWxLoginService(config.GeekAPI.WxLogin, client)
|
return service.NewWxLoginService(config.WxLogin, client)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// 支付服务
|
// 支付服务
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ func NewCaptchaService(captchaConfig types.CaptchaConfig) *CaptchaService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *CaptchaService) UpdateConfig(config types.CaptchaConfig) {
|
||||||
|
s.config = config
|
||||||
|
}
|
||||||
|
|
||||||
func (s *CaptchaService) Get() (interface{}, error) {
|
func (s *CaptchaService) Get() (interface{}, error) {
|
||||||
url := fmt.Sprintf("%s/api/captcha/get", types.GeekAPIURL)
|
url := fmt.Sprintf("%s/api/captcha/get", types.GeekAPIURL)
|
||||||
var res types.BizVo
|
var res types.BizVo
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
// Copyright 2023 The Geek-AI Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a Apache-2.0 license
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
// @Author yangjian102621@163.com
|
|
||||||
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"geekai/store/model"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ConfigService 统一的配置访问、缓存与通知服务
|
|
||||||
type ConfigService struct {
|
|
||||||
db *gorm.DB
|
|
||||||
rdb *redis.Client
|
|
||||||
mu sync.RWMutex
|
|
||||||
cache map[string]json.RawMessage
|
|
||||||
watchers map[string][]chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfigService(db *gorm.DB, rdb *redis.Client) *ConfigService {
|
|
||||||
s := &ConfigService{
|
|
||||||
db: db,
|
|
||||||
rdb: rdb,
|
|
||||||
cache: make(map[string]json.RawMessage),
|
|
||||||
watchers: make(map[string][]chan struct{}),
|
|
||||||
}
|
|
||||||
go s.subscribe()
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get 以原始 JSON 获取配置(带本地缓存)
|
|
||||||
func (s *ConfigService) Get(key string) (json.RawMessage, error) {
|
|
||||||
s.mu.RLock()
|
|
||||||
if v, ok := s.cache[key]; ok {
|
|
||||||
s.mu.RUnlock()
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
s.mu.RUnlock()
|
|
||||||
|
|
||||||
var cfg model.Config
|
|
||||||
if err := s.db.Where("name", key).First(&cfg).Error; err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.mu.Lock()
|
|
||||||
s.cache[key] = json.RawMessage(cfg.Value)
|
|
||||||
s.mu.Unlock()
|
|
||||||
return json.RawMessage(cfg.Value), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInto 将配置解析进传入结构体
|
|
||||||
func (s *ConfigService) GetInto(key string, dest interface{}) error {
|
|
||||||
data, err := s.Get(key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(data) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set 设置配置并写入数据库,同时触发通知
|
|
||||||
func (s *ConfigService) Set(key string, config json.RawMessage) error {
|
|
||||||
value := string(config)
|
|
||||||
cfg := model.Config{Name: key, Value: value}
|
|
||||||
if err := s.db.Where("name", key).FirstOrCreate(&cfg, model.Config{Name: key}).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if cfg.Id > 0 {
|
|
||||||
cfg.Value = value
|
|
||||||
if err := s.db.Updates(&cfg).Error; err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.mu.Lock()
|
|
||||||
s.cache[key] = json.RawMessage(value)
|
|
||||||
s.mu.Unlock()
|
|
||||||
s.notifyLocal(key)
|
|
||||||
s.publish(key)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch 返回一个通道,当指定 key 发生变化时收到事件
|
|
||||||
func (s *ConfigService) Watch(key string) <-chan struct{} {
|
|
||||||
ch := make(chan struct{}, 1)
|
|
||||||
s.mu.Lock()
|
|
||||||
s.watchers[key] = append(s.watchers[key], ch)
|
|
||||||
s.mu.Unlock()
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ConfigService) notifyLocal(key string) {
|
|
||||||
s.mu.RLock()
|
|
||||||
list := s.watchers[key]
|
|
||||||
s.mu.RUnlock()
|
|
||||||
for _, ch := range list {
|
|
||||||
select { // 非阻塞通知
|
|
||||||
case ch <- struct{}{}:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通过 Redis 发布配置变更,便于多实例同步
|
|
||||||
func (s *ConfigService) publish(key string) {
|
|
||||||
if s.rdb == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
channel := "config:changed"
|
|
||||||
if err := s.rdb.Publish(context.Background(), channel, key).Err(); err != nil {
|
|
||||||
logger.Warnf("publish config change failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ConfigService) subscribe() {
|
|
||||||
if s.rdb == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
channel := "config:changed"
|
|
||||||
sub := s.rdb.Subscribe(context.Background(), channel)
|
|
||||||
for msg := range sub.Channel() {
|
|
||||||
key := msg.Payload
|
|
||||||
logger.Infof("config changed: %s", key)
|
|
||||||
// 失效本地缓存并本地广播
|
|
||||||
s.mu.Lock()
|
|
||||||
delete(s.cache, key)
|
|
||||||
s.mu.Unlock()
|
|
||||||
s.notifyLocal(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test 预留统一测试入口,根据 key 执行连通性检查
|
|
||||||
func (s *ConfigService) Test(key string) (string, error) {
|
|
||||||
// TODO: 实现各配置类型的测试逻辑
|
|
||||||
return fmt.Sprintf("%s ok", key), nil
|
|
||||||
}
|
|
||||||
@@ -53,7 +53,7 @@ type License struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ActiveLicense 激活 License
|
// ActiveLicense 激活 License
|
||||||
func (s *LicenseService) ActiveLicense(license string, machineId string) error {
|
func (s *LicenseService) ActiveLicense(license string) error {
|
||||||
var res struct {
|
var res struct {
|
||||||
Code types.BizCode `json:"code"`
|
Code types.BizCode `json:"code"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
@@ -61,7 +61,7 @@ func (s *LicenseService) ActiveLicense(license string, machineId string) error {
|
|||||||
}
|
}
|
||||||
apiURL := fmt.Sprintf("%s/%s", types.GeekAPIURL, "api/license/active")
|
apiURL := fmt.Sprintf("%s/%s", types.GeekAPIURL, "api/license/active")
|
||||||
response, err := req.C().R().
|
response, err := req.C().R().
|
||||||
SetBody(map[string]string{"license": license, "machine_id": machineId}).
|
SetBody(map[string]string{"license": license, "machine_id": s.machineId}).
|
||||||
SetSuccessResult(&res).Post(apiURL)
|
SetSuccessResult(&res).Post(apiURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("发送激活请求失败: %v", err)
|
return fmt.Errorf("发送激活请求失败: %v", err)
|
||||||
@@ -81,7 +81,7 @@ func (s *LicenseService) ActiveLicense(license string, machineId string) error {
|
|||||||
|
|
||||||
s.license = &types.License{
|
s.license = &types.License{
|
||||||
Key: license,
|
Key: license,
|
||||||
MachineId: machineId,
|
MachineId: s.machineId,
|
||||||
Configs: res.Data.Configs,
|
Configs: res.Data.Configs,
|
||||||
ExpiredAt: res.Data.ExpiredAt,
|
ExpiredAt: res.Data.ExpiredAt,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
"github.com/qiniu/go-sdk/v7/storage"
|
"github.com/qiniu/go-sdk/v7/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type QinNiuOss struct {
|
type QiNiuOss struct {
|
||||||
config *types.QiNiuOssConfig
|
config *types.QiNiuOssConfig
|
||||||
mac *qbox.Mac
|
mac *qbox.Mac
|
||||||
putPolicy storage.PutPolicy
|
putPolicy storage.PutPolicy
|
||||||
@@ -33,8 +33,8 @@ type QinNiuOss struct {
|
|||||||
proxyURL string
|
proxyURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewQiNiuOss(sysConfig *types.SystemConfig, appConfig *types.AppConfig) *QinNiuOss {
|
func NewQiNiuOss(sysConfig *types.SystemConfig, appConfig *types.AppConfig) *QiNiuOss {
|
||||||
s := &QinNiuOss{
|
s := &QiNiuOss{
|
||||||
proxyURL: appConfig.ProxyURL,
|
proxyURL: appConfig.ProxyURL,
|
||||||
}
|
}
|
||||||
if sysConfig.OSS.Active == QiNiu {
|
if sysConfig.OSS.Active == QiNiu {
|
||||||
@@ -43,7 +43,7 @@ func NewQiNiuOss(sysConfig *types.SystemConfig, appConfig *types.AppConfig) *Qin
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QinNiuOss) UpdateConfig(config *types.QiNiuOssConfig) {
|
func (s *QiNiuOss) UpdateConfig(config *types.QiNiuOssConfig) {
|
||||||
zone, ok := storage.GetRegionByID(storage.RegionID(config.Zone))
|
zone, ok := storage.GetRegionByID(storage.RegionID(config.Zone))
|
||||||
if !ok {
|
if !ok {
|
||||||
zone = storage.ZoneHuanan
|
zone = storage.ZoneHuanan
|
||||||
@@ -61,7 +61,7 @@ func (s *QinNiuOss) UpdateConfig(config *types.QiNiuOssConfig) {
|
|||||||
s.uploader = formUploader
|
s.uploader = formUploader
|
||||||
s.bucket = storage.NewBucketManager(mac, &storeConfig)
|
s.bucket = storage.NewBucketManager(mac, &storeConfig)
|
||||||
}
|
}
|
||||||
func (s QinNiuOss) PutFile(ctx *gin.Context, name string) (File, error) {
|
func (s QiNiuOss) PutFile(ctx *gin.Context, name string) (File, error) {
|
||||||
// 解析表单
|
// 解析表单
|
||||||
file, err := ctx.FormFile(name)
|
file, err := ctx.FormFile(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -94,7 +94,7 @@ func (s QinNiuOss) PutFile(ctx *gin.Context, name string) (File, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s QinNiuOss) PutUrlFile(fileURL string, ext string, useProxy bool) (string, error) {
|
func (s QiNiuOss) PutUrlFile(fileURL string, ext string, useProxy bool) (string, error) {
|
||||||
var fileData []byte
|
var fileData []byte
|
||||||
var err error
|
var err error
|
||||||
if useProxy {
|
if useProxy {
|
||||||
@@ -123,7 +123,7 @@ func (s QinNiuOss) PutUrlFile(fileURL string, ext string, useProxy bool) (string
|
|||||||
return fmt.Sprintf("%s/%s", s.config.Domain, ret.Key), nil
|
return fmt.Sprintf("%s/%s", s.config.Domain, ret.Key), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s QinNiuOss) PutBase64(base64Img string) (string, error) {
|
func (s QiNiuOss) PutBase64(base64Img string) (string, error) {
|
||||||
imageData, err := base64.StdEncoding.DecodeString(base64Img)
|
imageData, err := base64.StdEncoding.DecodeString(base64Img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error decoding base64:%v", err)
|
return "", fmt.Errorf("error decoding base64:%v", err)
|
||||||
@@ -139,7 +139,7 @@ func (s QinNiuOss) PutBase64(base64Img string) (string, error) {
|
|||||||
return fmt.Sprintf("%s/%s", s.config.Domain, ret.Key), nil
|
return fmt.Sprintf("%s/%s", s.config.Domain, ret.Key), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s QinNiuOss) Delete(fileURL string) error {
|
func (s QiNiuOss) Delete(fileURL string) error {
|
||||||
var objectKey string
|
var objectKey string
|
||||||
if strings.HasPrefix(fileURL, "http") {
|
if strings.HasPrefix(fileURL, "http") {
|
||||||
filename := filepath.Base(fileURL)
|
filename := filepath.Base(fileURL)
|
||||||
@@ -151,4 +151,4 @@ func (s QinNiuOss) Delete(fileURL string) error {
|
|||||||
return s.bucket.Delete(s.config.Bucket, objectKey)
|
return s.bucket.Delete(s.config.Bucket, objectKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Uploader = QinNiuOss{}
|
var _ Uploader = QiNiuOss{}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ type UploaderManager struct {
|
|||||||
local *LocalStorage
|
local *LocalStorage
|
||||||
aliyun *AliYunOss
|
aliyun *AliYunOss
|
||||||
mini *MiniOss
|
mini *MiniOss
|
||||||
qiniu *QinNiuOss
|
qiniu *QiNiuOss
|
||||||
config *types.OSSConfig
|
config *types.OSSConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUploaderManager(sysConfig *types.SystemConfig, local *LocalStorage, aliyun *AliYunOss, mini *MiniOss, qiniu *QinNiuOss) (*UploaderManager, error) {
|
func NewUploaderManager(sysConfig *types.SystemConfig, local *LocalStorage, aliyun *AliYunOss, mini *MiniOss, qiniu *QiNiuOss) (*UploaderManager, error) {
|
||||||
if sysConfig.OSS.Active == "" {
|
if sysConfig.OSS.Active == "" {
|
||||||
sysConfig.OSS.Active = Local
|
sysConfig.OSS.Active = Local
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ func NewSmtpService(appConfig *types.AppConfig) *SmtpService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SmtpService) UpdateConfig(config *types.SmtpConfig) {
|
||||||
|
s.config = config
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SmtpService) SendVerifyCode(to string, code int) error {
|
func (s *SmtpService) SendVerifyCode(to string, code int) error {
|
||||||
subject := fmt.Sprintf("%s 注册验证码", s.config.AppName)
|
subject := fmt.Sprintf("%s 注册验证码", s.config.AppName)
|
||||||
body := fmt.Sprintf("【%s】:您的验证码为 %d,请不要告诉他人。如非本人操作,请忽略此邮件。", s.config.AppName, code)
|
body := fmt.Sprintf("【%s】:您的验证码为 %d,请不要告诉他人。如非本人操作,请忽略此邮件。", s.config.AppName, code)
|
||||||
|
|||||||
@@ -43,10 +43,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
httpPost('/api/admin/config/update', {
|
httpPost('/api/admin/config/update/base', { mark_map_text: agreement.value })
|
||||||
key: 'agreement',
|
|
||||||
config: { content: agreement.value, updated: true },
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success('操作成功!')
|
ElMessage.success('操作成功!')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { httpGet, httpPost } from '@/utils/http'
|
import { httpGet } from '@/utils/http'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
|
|
||||||
@@ -41,15 +41,11 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
httpPost('/api/admin/config/update', { key: 'api', config: api.value })
|
ElMessage.info('当前后端未提供 /api 配置的更新接口,已保留只读展示')
|
||||||
.then(() => ElMessage.success('保存成功'))
|
|
||||||
.catch((e) => ElMessage.error(e.message))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const test = () => {
|
const test = () => {
|
||||||
httpPost('/api/admin/config/test', { key: 'api' })
|
ElMessage.info('请在对应服务端手动测试 API 可用性')
|
||||||
.then((res) => ElMessage.success(res.message || '测试成功'))
|
|
||||||
.catch((e) => ElMessage.error(e.message || '测试失败'))
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -282,11 +282,7 @@ const rules = reactive({
|
|||||||
const save = function () {
|
const save = function () {
|
||||||
systemFormRef.value.validate((valid) => {
|
systemFormRef.value.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
httpPost('/api/admin/config/update', {
|
httpPost('/api/admin/config/update/base', system.value)
|
||||||
key: 'system',
|
|
||||||
config: system.value,
|
|
||||||
config_bak: configBak.value,
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success('操作成功!')
|
ElMessage.success('操作成功!')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,28 +21,27 @@
|
|||||||
<el-tab-pane label="短信服务" name="sms">
|
<el-tab-pane label="短信服务" name="sms">
|
||||||
<el-form :model="sms" label-width="140px">
|
<el-form :model="sms" label-width="140px">
|
||||||
<el-form-item label="服务商">
|
<el-form-item label="服务商">
|
||||||
<el-select v-model="sms.active" style="width: 200px">
|
<el-select v-model="sms.Active" style="width: 200px">
|
||||||
<el-option label="阿里云" value="Ali" />
|
<el-option label="阿里云" value="Ali" />
|
||||||
<el-option label="短信宝" value="Bao" />
|
<el-option label="短信宝" value="Bao" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<template v-if="sms.active === 'Ali'">
|
<template v-if="sms.Active === 'Ali'">
|
||||||
<el-form-item label="AccessKey"><el-input v-model="sms.ali.access_key" /></el-form-item>
|
<el-form-item label="AccessKey"><el-input v-model="sms.Ali.AccessKey" /></el-form-item>
|
||||||
<el-form-item label="AccessSecret"
|
<el-form-item label="AccessSecret"
|
||||||
><el-input v-model="sms.ali.access_secret"
|
><el-input v-model="sms.Ali.AccessSecret"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="签名"><el-input v-model="sms.ali.sign" /></el-form-item>
|
<el-form-item label="签名"><el-input v-model="sms.Ali.Sign" /></el-form-item>
|
||||||
<el-form-item label="模板ID"><el-input v-model="sms.ali.code_temp_id" /></el-form-item>
|
<el-form-item label="模板ID"><el-input v-model="sms.Ali.CodeTempId" /></el-form-item>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-form-item label="用户名"><el-input v-model="sms.bao.username" /></el-form-item>
|
<el-form-item label="用户名"><el-input v-model="sms.Bao.Username" /></el-form-item>
|
||||||
<el-form-item label="密码"
|
<el-form-item label="密码"
|
||||||
><el-input v-model="sms.bao.password" type="password"
|
><el-input v-model="sms.Bao.Password" type="password"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="域名"><el-input v-model="sms.bao.domain" /></el-form-item>
|
<el-form-item label="签名"><el-input v-model="sms.Bao.Sign" /></el-form-item>
|
||||||
<el-form-item label="签名"><el-input v-model="sms.bao.sign" /></el-form-item>
|
|
||||||
<el-form-item label="模板"
|
<el-form-item label="模板"
|
||||||
><el-input v-model="sms.bao.code_template" type="textarea" :rows="2"
|
><el-input v-model="sms.Bao.CodeTemplate" type="textarea" :rows="2"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
</template>
|
</template>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -64,9 +63,9 @@ const loading = ref(true)
|
|||||||
const active = ref('smtp')
|
const active = ref('smtp')
|
||||||
const smtp = ref({ use_tls: false, host: '', port: 25, app_name: '', from: '', password: '' })
|
const smtp = ref({ use_tls: false, host: '', port: 25, app_name: '', from: '', password: '' })
|
||||||
const sms = ref({
|
const sms = ref({
|
||||||
active: 'Ali',
|
Active: 'Ali',
|
||||||
ali: { access_key: '', access_secret: '', sign: '', code_temp_id: '' },
|
Ali: { AccessKey: '', AccessSecret: '', Sign: '', CodeTempId: '' },
|
||||||
bao: { username: '', password: '', domain: '', sign: '', code_template: '' },
|
Bao: { Username: '', Password: '', Sign: '', CodeTemplate: '' },
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -79,8 +78,8 @@ onMounted(() => {
|
|||||||
sms.value = {
|
sms.value = {
|
||||||
...sms.value,
|
...sms.value,
|
||||||
...smsData,
|
...smsData,
|
||||||
ali: { ...sms.value.ali, ...(smsData.ali || {}) },
|
Ali: { ...sms.value.Ali, ...(smsData.Ali || smsData.ali || {}) },
|
||||||
bao: { ...sms.value.bao, ...(smsData.bao || {}) },
|
Bao: { ...sms.value.Bao, ...(smsData.Bao || smsData.bao || {}) },
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
@@ -88,16 +87,19 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const save = (key) => {
|
const save = (key) => {
|
||||||
const map = { smtp, sms }
|
if (key === 'smtp') {
|
||||||
httpPost('/api/admin/config/update', { key, config: map[key].value })
|
httpPost('/api/admin/config/update/smtp', smtp.value)
|
||||||
.then(() => ElMessage.success('保存成功'))
|
.then(() => ElMessage.success('保存成功'))
|
||||||
.catch((e) => ElMessage.error(e.message))
|
.catch((e) => ElMessage.error(e.message))
|
||||||
|
} else if (key === 'sms') {
|
||||||
|
httpPost('/api/admin/config/update/sms', sms.value)
|
||||||
|
.then(() => ElMessage.success('保存成功'))
|
||||||
|
.catch((e) => ElMessage.error(e.message))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const test = (key) => {
|
const test = (key) => {
|
||||||
httpPost('/api/admin/config/test', { key })
|
ElMessage.info('请在对应服务侧进行验证')
|
||||||
.then((res) => ElMessage.success(res.message || '测试成功'))
|
|
||||||
.catch((e) => ElMessage.error(e.message || '测试失败'))
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const fetchLicense = () => {
|
const fetchLicense = () => {
|
||||||
httpGet('/api/admin/config/license')
|
httpGet('/api/admin/config/license/get')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
license.value = res.data
|
license.value = res.data
|
||||||
})
|
})
|
||||||
@@ -96,7 +96,7 @@ const active = () => {
|
|||||||
if (licenseKey.value === '') {
|
if (licenseKey.value === '') {
|
||||||
return ElMessage.error('请输入授权码')
|
return ElMessage.error('请输入授权码')
|
||||||
}
|
}
|
||||||
httpPost('/api/admin/config/active', { license: licenseKey.value })
|
httpPost('/api/admin/config/license/active', { license: licenseKey.value })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
ElMessage.success('授权成功,机器编码为:' + res.data)
|
ElMessage.success('授权成功,机器编码为:' + res.data)
|
||||||
fetchLicense()
|
fetchLicense()
|
||||||
|
|||||||
@@ -38,10 +38,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
httpPost('/api/admin/config/update', {
|
httpPost('/api/admin/config/update/notice', { content: notice.value })
|
||||||
key: 'notice',
|
|
||||||
config: { content: notice.value, updated: true },
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success('操作成功!')
|
ElMessage.success('操作成功!')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<el-tab-pane label="支付宝" name="alipay">
|
<el-tab-pane label="支付宝" name="alipay">
|
||||||
<el-form :model="alipay" label-width="140px">
|
<el-form :model="alipay" label-width="140px">
|
||||||
<el-form-item label="启用通道"><el-switch v-model="alipay.enabled" /></el-form-item>
|
<el-form-item label="启用通道"><el-switch v-model="alipay.enabled" /></el-form-item>
|
||||||
<el-form-item label="沙盒模式"><el-switch v-model="alipay.sand_box" /></el-form-item>
|
<el-form-item label="沙盒模式"><el-switch v-model="alipay.sandbox" /></el-form-item>
|
||||||
<el-form-item label="AppId"><el-input v-model="alipay.app_id" /></el-form-item>
|
<el-form-item label="AppId"><el-input v-model="alipay.app_id" /></el-form-item>
|
||||||
<el-form-item label="商户私钥"
|
<el-form-item label="商户私钥"
|
||||||
><el-input v-model="alipay.private_key" type="textarea" :rows="5"
|
><el-input v-model="alipay.private_key" type="textarea" :rows="5"
|
||||||
@@ -12,8 +12,7 @@
|
|||||||
<el-form-item label="支付宝公钥"
|
<el-form-item label="支付宝公钥"
|
||||||
><el-input v-model="alipay.alipay_public_key" type="textarea" :rows="3"
|
><el-input v-model="alipay.alipay_public_key" type="textarea" :rows="3"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="异步通知URL"><el-input v-model="alipay.notify_url" /></el-form-item>
|
<el-form-item label="回调域名"><el-input v-model="alipay.domain" /></el-form-item>
|
||||||
<el-form-item label="同步回跳URL"><el-input v-model="alipay.return_url" /></el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="save('alipay')">保存</el-button>
|
<el-button type="primary" @click="save('alipay')">保存</el-button>
|
||||||
<el-button @click="test('alipay')">测试</el-button>
|
<el-button @click="test('alipay')">测试</el-button>
|
||||||
@@ -21,7 +20,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="微信支付" name="wechat">
|
<el-tab-pane label="微信支付" name="wxpay">
|
||||||
<el-form :model="wechat" label-width="140px">
|
<el-form :model="wechat" label-width="140px">
|
||||||
<el-form-item label="启用通道"><el-switch v-model="wechat.enabled" /></el-form-item>
|
<el-form-item label="启用通道"><el-switch v-model="wechat.enabled" /></el-form-item>
|
||||||
<el-form-item label="AppId"><el-input v-model="wechat.app_id" /></el-form-item>
|
<el-form-item label="AppId"><el-input v-model="wechat.app_id" /></el-form-item>
|
||||||
@@ -31,25 +30,26 @@
|
|||||||
><el-input v-model="wechat.private_key" type="textarea" :rows="3"
|
><el-input v-model="wechat.private_key" type="textarea" :rows="3"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="APIv3 Key"><el-input v-model="wechat.api_v3_key" /></el-form-item>
|
<el-form-item label="APIv3 Key"><el-input v-model="wechat.api_v3_key" /></el-form-item>
|
||||||
<el-form-item label="异步通知URL"><el-input v-model="wechat.notify_url" /></el-form-item>
|
<el-form-item label="回调域名"><el-input v-model="wechat.domain" /></el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="save('wechat')">保存</el-button>
|
<el-button type="primary" @click="save('wxpay')">保存</el-button>
|
||||||
<el-button @click="test('wechat')">测试</el-button>
|
<el-button @click="test('wxpay')">测试</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="虎皮椒" name="hupi">
|
<el-tab-pane label="易支付" name="epay">
|
||||||
<el-form :model="hupi" label-width="140px">
|
<el-form :model="epay" label-width="140px">
|
||||||
<el-form-item label="启用通道"><el-switch v-model="hupi.enabled" /></el-form-item>
|
<el-form-item label="启用通道"><el-switch v-model="epay.enabled" /></el-form-item>
|
||||||
<el-form-item label="AppId"><el-input v-model="hupi.app_id" /></el-form-item>
|
<el-form-item label="商户ID"><el-input v-model="epay.app_id" /></el-form-item>
|
||||||
<el-form-item label="AppSecret"><el-input v-model="hupi.app_secret" /></el-form-item>
|
<el-form-item label="商户私钥"
|
||||||
<el-form-item label="网关地址"><el-input v-model="hupi.api_url" /></el-form-item>
|
><el-input v-model="epay.private_key" type="textarea" :rows="3"
|
||||||
<el-form-item label="异步通知URL"><el-input v-model="hupi.notify_url" /></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="同步回跳URL"><el-input v-model="hupi.return_url" /></el-form-item>
|
<el-form-item label="网关地址"><el-input v-model="epay.api_url" /></el-form-item>
|
||||||
|
<el-form-item label="回调域名"><el-input v-model="epay.domain" /></el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="save('hupi')">保存</el-button>
|
<el-button type="primary" @click="save('epay')">保存</el-button>
|
||||||
<el-button @click="test('hupi')">测试</el-button>
|
<el-button @click="test('epay')">测试</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
@@ -86,39 +86,47 @@ import { onMounted, ref } from 'vue'
|
|||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const active = ref('alipay')
|
const active = ref('alipay')
|
||||||
|
|
||||||
const alipay = ref({ enabled: false, sand_box: false })
|
const alipay = ref({
|
||||||
const wechat = ref({ enabled: false })
|
enabled: false,
|
||||||
const hupi = ref({ enabled: false })
|
sandbox: false,
|
||||||
const geekpay = ref({ enabled: false, methods: [] })
|
app_id: '',
|
||||||
|
private_key: '',
|
||||||
|
alipay_public_key: '',
|
||||||
|
domain: '',
|
||||||
|
})
|
||||||
|
const wechat = ref({
|
||||||
|
enabled: false,
|
||||||
|
app_id: '',
|
||||||
|
mch_id: '',
|
||||||
|
serial_no: '',
|
||||||
|
private_key: '',
|
||||||
|
api_v3_key: '',
|
||||||
|
domain: '',
|
||||||
|
})
|
||||||
|
const epay = ref({ enabled: false, app_id: '', private_key: '', api_url: '', domain: '' })
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
Promise.all([
|
httpGet('/api/admin/config/get?key=payment')
|
||||||
httpGet('/api/admin/config/get?key=alipay'),
|
.then((res) => {
|
||||||
httpGet('/api/admin/config/get?key=wechat'),
|
const data = res.data || {}
|
||||||
httpGet('/api/admin/config/get?key=hupi'),
|
alipay.value = { ...alipay.value, ...(data.alipay || {}) }
|
||||||
httpGet('/api/admin/config/get?key=geekpay'),
|
wechat.value = { ...wechat.value, ...(data.wxpay || data.wechat || {}) }
|
||||||
])
|
epay.value = { ...epay.value, ...(data.epay || {}) }
|
||||||
.then(([a, w, h, g]) => {
|
|
||||||
alipay.value = a.data || alipay.value
|
|
||||||
wechat.value = w.data || wechat.value
|
|
||||||
hupi.value = h.data || hupi.value
|
|
||||||
geekpay.value = g.data || geekpay.value
|
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => (loading.value = false))
|
.finally(() => (loading.value = false))
|
||||||
})
|
})
|
||||||
|
|
||||||
const save = (key) => {
|
const save = (key) => {
|
||||||
const map = { alipay, wechat, hupi, geekpay }
|
const payload = { alipay: alipay.value, wxpay: wechat.value, epay: epay.value }
|
||||||
httpPost('/api/admin/config/update', { key, config: map[key].value })
|
httpPost('/api/admin/config/update/payment', payload)
|
||||||
.then(() => ElMessage.success('保存成功'))
|
.then(() => ElMessage.success('保存成功'))
|
||||||
.catch((e) => ElMessage.error(e.message))
|
.catch((e) => ElMessage.error(e.message))
|
||||||
}
|
}
|
||||||
|
|
||||||
const test = (key) => {
|
const test = (key) => {
|
||||||
httpPost('/api/admin/config/test', { key })
|
// 后端未提供独立测试接口,保留占位提示
|
||||||
.then((res) => ElMessage.success(res.message || '测试成功'))
|
ElMessage.info('请在支付端自行验证配置')
|
||||||
.catch((e) => ElMessage.error(e.message || '测试失败'))
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
httpPost('/api/admin/config/update', {
|
httpPost('/api/admin/config/update/notice', { content: privacy.value })
|
||||||
key: 'privacy',
|
|
||||||
config: { content: privacy.value, updated: true },
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ElMessage.success('操作成功!')
|
ElMessage.success('操作成功!')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,46 +12,46 @@
|
|||||||
|
|
||||||
<template v-if="active === 'local'">
|
<template v-if="active === 'local'">
|
||||||
<el-form :model="local" label-width="140px">
|
<el-form :model="local" label-width="140px">
|
||||||
<el-form-item label="BasePath"><el-input v-model="local.base_path" /></el-form-item>
|
<el-form-item label="BasePath"><el-input v-model="local.BasePath" /></el-form-item>
|
||||||
<el-form-item label="BaseURL"><el-input v-model="local.base_url" /></el-form-item>
|
<el-form-item label="BaseURL"><el-input v-model="local.BaseURL" /></el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="active === 'minio'">
|
<template v-else-if="active === 'minio'">
|
||||||
<el-form :model="minio" label-width="140px">
|
<el-form :model="minio" label-width="140px">
|
||||||
<el-form-item label="Endpoint"><el-input v-model="minio.endpoint" /></el-form-item>
|
<el-form-item label="Endpoint"><el-input v-model="minio.Endpoint" /></el-form-item>
|
||||||
<el-form-item label="AccessKey"><el-input v-model="minio.access_key" /></el-form-item>
|
<el-form-item label="AccessKey"><el-input v-model="minio.AccessKey" /></el-form-item>
|
||||||
<el-form-item label="AccessSecret"
|
<el-form-item label="AccessSecret"
|
||||||
><el-input v-model="minio.access_secret"
|
><el-input v-model="minio.AccessSecret"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="Bucket"><el-input v-model="minio.bucket" /></el-form-item>
|
<el-form-item label="Bucket"><el-input v-model="minio.Bucket" /></el-form-item>
|
||||||
<el-form-item label="UseSSL"><el-switch v-model="minio.use_ssl" /></el-form-item>
|
<el-form-item label="UseSSL"><el-switch v-model="minio.UseSSL" /></el-form-item>
|
||||||
<el-form-item label="Domain"><el-input v-model="minio.domain" /></el-form-item>
|
<el-form-item label="Domain"><el-input v-model="minio.Domain" /></el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="active === 'qiniu'">
|
<template v-else-if="active === 'qiniu'">
|
||||||
<el-form :model="qiniu" label-width="140px">
|
<el-form :model="qiniu" label-width="140px">
|
||||||
<el-form-item label="Zone"><el-input v-model="qiniu.zone" /></el-form-item>
|
<el-form-item label="Zone"><el-input v-model="qiniu.Zone" /></el-form-item>
|
||||||
<el-form-item label="AccessKey"><el-input v-model="qiniu.access_key" /></el-form-item>
|
<el-form-item label="AccessKey"><el-input v-model="qiniu.AccessKey" /></el-form-item>
|
||||||
<el-form-item label="AccessSecret"
|
<el-form-item label="AccessSecret"
|
||||||
><el-input v-model="qiniu.access_secret"
|
><el-input v-model="qiniu.AccessSecret"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="Bucket"><el-input v-model="qiniu.bucket" /></el-form-item>
|
<el-form-item label="Bucket"><el-input v-model="qiniu.Bucket" /></el-form-item>
|
||||||
<el-form-item label="Domain"><el-input v-model="qiniu.domain" /></el-form-item>
|
<el-form-item label="Domain"><el-input v-model="qiniu.Domain" /></el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-form :model="aliyun" label-width="140px">
|
<el-form :model="aliyun" label-width="140px">
|
||||||
<el-form-item label="Endpoint"><el-input v-model="aliyun.endpoint" /></el-form-item>
|
<el-form-item label="Endpoint"><el-input v-model="aliyun.Endpoint" /></el-form-item>
|
||||||
<el-form-item label="AccessKey"><el-input v-model="aliyun.access_key" /></el-form-item>
|
<el-form-item label="AccessKey"><el-input v-model="aliyun.AccessKey" /></el-form-item>
|
||||||
<el-form-item label="AccessSecret"
|
<el-form-item label="AccessSecret"
|
||||||
><el-input v-model="aliyun.access_secret"
|
><el-input v-model="aliyun.AccessSecret"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="Bucket"><el-input v-model="aliyun.bucket" /></el-form-item>
|
<el-form-item label="Bucket"><el-input v-model="aliyun.Bucket" /></el-form-item>
|
||||||
<el-form-item label="SubDir"><el-input v-model="aliyun.sub_dir" /></el-form-item>
|
<el-form-item label="SubDir"><el-input v-model="aliyun.SubDir" /></el-form-item>
|
||||||
<el-form-item label="Domain"><el-input v-model="aliyun.domain" /></el-form-item>
|
<el-form-item label="Domain"><el-input v-model="aliyun.Domain" /></el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -70,58 +70,62 @@ import { onMounted, ref } from 'vue'
|
|||||||
|
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const active = ref('local')
|
const active = ref('local')
|
||||||
const local = ref({ base_path: '', base_url: '' })
|
const local = ref({ BasePath: '', BaseURL: '' })
|
||||||
const minio = ref({
|
const minio = ref({
|
||||||
endpoint: '',
|
Endpoint: '',
|
||||||
access_key: '',
|
AccessKey: '',
|
||||||
access_secret: '',
|
AccessSecret: '',
|
||||||
bucket: '',
|
Bucket: '',
|
||||||
use_ssl: false,
|
SubDir: '',
|
||||||
domain: '',
|
UseSSL: false,
|
||||||
|
Domain: '',
|
||||||
|
})
|
||||||
|
const qiniu = ref({
|
||||||
|
Zone: 'z2',
|
||||||
|
AccessKey: '',
|
||||||
|
AccessSecret: '',
|
||||||
|
Bucket: '',
|
||||||
|
SubDir: '',
|
||||||
|
Domain: '',
|
||||||
})
|
})
|
||||||
const qiniu = ref({ zone: 'z2', access_key: '', access_secret: '', bucket: '', domain: '' })
|
|
||||||
const aliyun = ref({
|
const aliyun = ref({
|
||||||
endpoint: '',
|
Endpoint: '',
|
||||||
access_key: '',
|
AccessKey: '',
|
||||||
access_secret: '',
|
AccessSecret: '',
|
||||||
bucket: '',
|
Bucket: '',
|
||||||
sub_dir: '',
|
SubDir: '',
|
||||||
domain: '',
|
Domain: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
httpGet('/api/admin/config/get?key=oss')
|
httpGet('/api/admin/config/get?key=oss')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const data = res.data || {}
|
const data = res.data || {}
|
||||||
active.value = (data.active || 'local').toLowerCase()
|
const Active = data.Active || data.active || 'local'
|
||||||
local.value = data.local || local.value
|
active.value = String(Active).toLowerCase()
|
||||||
minio.value = data.minio || minio.value
|
local.value = data.Local || data.local || local.value
|
||||||
qiniu.value = data.qiniu || qiniu.value
|
minio.value = data.Minio || data.minio || minio.value
|
||||||
aliyun.value = data.aliyun || aliyun.value
|
qiniu.value = data.QiNiu || data.qiniu || qiniu.value
|
||||||
|
aliyun.value = data.AliYun || data.aliyun || aliyun.value
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => (loading.value = false))
|
.finally(() => (loading.value = false))
|
||||||
})
|
})
|
||||||
|
|
||||||
const save = () => {
|
const save = () => {
|
||||||
httpPost('/api/admin/config/update', {
|
httpPost('/api/admin/config/update/oss', {
|
||||||
key: 'oss',
|
active: active.value,
|
||||||
config: {
|
local: local.value,
|
||||||
active: active.value,
|
minio: minio.value,
|
||||||
local: local.value,
|
qiniu: qiniu.value,
|
||||||
minio: minio.value,
|
aliyun: aliyun.value,
|
||||||
qiniu: qiniu.value,
|
|
||||||
aliyun: aliyun.value,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
.then(() => ElMessage.success('保存成功'))
|
.then(() => ElMessage.success('保存成功'))
|
||||||
.catch((e) => ElMessage.error(e.message))
|
.catch((e) => ElMessage.error(e.message))
|
||||||
}
|
}
|
||||||
|
|
||||||
const test = () => {
|
const test = () => {
|
||||||
httpPost('/api/admin/config/test', { key: 'oss' })
|
ElMessage.info('请在对象存储端验证配置')
|
||||||
.then((res) => ElMessage.success(res.message || '连接成功'))
|
|
||||||
.catch((e) => ElMessage.error(e.message || '连接失败'))
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user